MAILBOX-359 Added Scala Event Serialization
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/39bc507a Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/39bc507a Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/39bc507a Branch: refs/heads/master Commit: 39bc507acae024f4686a78c750f09a494cde1282 Parents: 0f9024f Author: tran tien duc <[email protected]> Authored: Fri Dec 14 17:49:09 2018 +0700 Committer: Benoit Tellier <[email protected]> Committed: Wed Dec 19 18:05:57 2018 +0700 ---------------------------------------------------------------------- .../org/apache/james/mailbox/FlagsBuilder.java | 5 + .../apache/james/mailbox/MailboxListener.java | 26 +- .../james/mailbox/MailboxListenerTest.java | 5 + .../james/event/json/EventSerializer.scala | 73 +- .../apache/james/event/json/MetaDataDTO.scala | 90 ++ .../event/json/AddedSerializationTest.java | 1465 ++++++++++++++++++ ...MailboxACLUpdatedEventSerializationTest.java | 3 +- .../json/MailboxAddedSerializationTest.java | 3 +- .../json/MailboxDeletionSerializationTest.java | 3 +- .../json/MailboxRenamedSerializationTest.java | 3 +- ...QuotaUsageUpdatedEventSerializationTest.java | 3 +- 11 files changed, 1663 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java ---------------------------------------------------------------------- diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java b/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java index 7a791ec..f36189b 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/FlagsBuilder.java @@ -61,6 +61,11 @@ public class FlagsBuilder { return this; } + public FlagsBuilder merge(FlagsBuilder flagsBuilder) { + internalFlags.add(flagsBuilder.internalFlags); + return this; + } + public Flags build() { return new Flags(internalFlags); } http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxListener.java ---------------------------------------------------------------------- diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxListener.java b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxListener.java index b3d4785..2b7fdb9 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxListener.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxListener.java @@ -24,7 +24,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.SortedMap; import org.apache.james.core.User; import org.apache.james.core.quota.QuotaCount; @@ -429,7 +428,7 @@ public interface MailboxListener { class Added extends MetaDataHoldingEvent { private final Map<MessageUid, MessageMetaData> added; - public Added(MailboxSession.SessionId sessionId, User user, MailboxPath path, MailboxId mailboxId, SortedMap<MessageUid, MessageMetaData> uids) { + public Added(MailboxSession.SessionId sessionId, User user, MailboxPath path, MailboxId mailboxId, Map<MessageUid, MessageMetaData> uids) { super(sessionId, user, path, mailboxId); this.added = ImmutableMap.copyOf(uids); } @@ -447,6 +446,29 @@ public interface MailboxListener { public Collection<MessageUid> getUids() { return added.keySet(); } + + public Map<MessageUid, MessageMetaData> getAdded() { + return added; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof Added) { + Added that = (Added) o; + + return Objects.equals(this.sessionId, that.sessionId) + && Objects.equals(this.user, that.user) + && Objects.equals(this.path, that.path) + && Objects.equals(this.mailboxId, that.mailboxId) + && Objects.equals(this.added, that.added); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(sessionId, user, path, mailboxId, added); + } } } http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxListenerTest.java ---------------------------------------------------------------------- diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxListenerTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxListenerTest.java index ac9c364..a276c3f 100644 --- a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxListenerTest.java +++ b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxListenerTest.java @@ -43,4 +43,9 @@ class MailboxListenerTest { void mailboxACLUpdatedShouldMatchBeanContract() { EqualsVerifier.forClass(MailboxListener.MailboxACLUpdated.class).verify(); } + + @Test + void addedShouldMatchBeanContract() { + EqualsVerifier.forClass(MailboxListener.Added.class).verify(); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala ---------------------------------------------------------------------- diff --git a/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala b/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala index 5a14668..549e105 100644 --- a/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala +++ b/mailbox/event/json/src/main/scala/org/apache/james/event/json/EventSerializer.scala @@ -22,15 +22,21 @@ package org.apache.james.event.json import java.time.Instant import java.util.Optional +import javax.mail.{Flags => JavaMailFlags} import julienrf.json.derived import org.apache.james.core.quota.{QuotaCount, QuotaSize, QuotaValue} import org.apache.james.core.{Domain, User} import org.apache.james.event.json.DTOs.{ACLDiff, MailboxPath, Quota} -import org.apache.james.mailbox.MailboxListener.{MailboxACLUpdated => JavaMailboxACLUpdated, MailboxAdded => JavaMailboxAdded, MailboxDeletion => JavaMailboxDeletion, MailboxRenamed => JavaMailboxRenamed, QuotaUsageUpdatedEvent => JavaQuotaUsageUpdatedEvent} +import org.apache.james.event.json.MetaDataDTO.Flags +import org.apache.james.mailbox.MailboxListener.{Added => JavaAdded, MailboxACLUpdated => JavaMailboxACLUpdated, + MailboxAdded => JavaMailboxAdded, MailboxDeletion => JavaMailboxDeletion, MailboxRenamed => JavaMailboxRenamed, + QuotaUsageUpdatedEvent => JavaQuotaUsageUpdatedEvent} import org.apache.james.mailbox.MailboxSession.SessionId -import org.apache.james.mailbox.model.{MailboxId, QuotaRoot, MailboxACL => JavaMailboxACL, Quota => JavaQuota} -import org.apache.james.mailbox.{Event => JavaEvent} -import play.api.libs.json.{JsError, JsNull, JsNumber, JsObject, JsResult, JsString, JsSuccess, Json, OFormat, Reads, Writes} +import org.apache.james.mailbox.model.{MailboxId, MessageId, QuotaRoot, MailboxACL => JavaMailboxACL, Quota => JavaQuota} +import org.apache.james.mailbox.{MessageUid, Event => JavaEvent} +import play.api.libs.json.{JsArray, JsError, JsNull, JsNumber, JsObject, JsResult, JsString, JsSuccess, Json, OFormat, Reads, Writes} + +import scala.collection.JavaConverters._ private sealed trait Event { def toJava: JavaEvent @@ -60,6 +66,16 @@ private object DTO { sizeQuota: Quota[QuotaSize], time: Instant) extends Event { override def toJava: JavaEvent = new JavaQuotaUsageUpdatedEvent(user, quotaRoot, countQuota.toJava, sizeQuota.toJava, time) } + + case class Added(sessionId: SessionId, user: User, path: MailboxPath, mailboxId: MailboxId, + added: Map[MessageUid, MetaDataDTO.MessageMetaData]) extends Event { + override def toJava: JavaEvent = new JavaAdded( + sessionId, + user, + path.toJava, + mailboxId, + added.map(entry => entry._1 -> entry._2.toJava).asJava) + } } private object ScalaConverter { @@ -85,6 +101,7 @@ private object ScalaConverter { totalDeletedSize = event.getTotalDeletedSize, mailboxId = event.getMailboxId) + private def toScala(event: JavaMailboxRenamed): DTO.MailboxRenamed = DTO.MailboxRenamed( sessionId = event.getSessionId, user = event.getUser, @@ -99,17 +116,26 @@ private object ScalaConverter { sizeQuota = Quota.toScala(event.getSizeQuota), time = event.getInstant) + private def toScala(event: JavaAdded): DTO.Added = DTO.Added( + sessionId = event.getSessionId, + user = event.getUser, + path = MailboxPath.fromJava(event.getMailboxPath), + mailboxId = event.getMailboxId, + added = event.getAdded.asScala.map(entry => entry._1 -> MetaDataDTO.MessageMetaData.fromJava(entry._2)).toMap + ) + def toScala(javaEvent: JavaEvent): Event = javaEvent match { case e: JavaMailboxACLUpdated => toScala(e) case e: JavaMailboxAdded => toScala(e) case e: JavaMailboxDeletion => toScala(e) case e: JavaMailboxRenamed => toScala(e) case e: JavaQuotaUsageUpdatedEvent => toScala(e) - case _ => throw new RuntimeException("no Scala convertion known") + case e: JavaAdded => toScala(e) + case _ => throw new RuntimeException("no Scala conversion known") } } -private class JsonSerialize(mailboxIdFactory: MailboxId.Factory) { +private class JsonSerialize(mailboxIdFactory: MailboxId.Factory, messageIdFactory: MessageId.Factory) { implicit val userWriters: Writes[User] = (user: User) => JsString(user.asString) implicit val quotaRootWrites: Writes[QuotaRoot] = quotaRoot => JsString(quotaRoot.getValue) implicit val quotaValueWrites: Writes[QuotaValue[_]] = value => if (value.isUnlimited) JsNull else JsNumber(value.asLong()) @@ -122,6 +148,10 @@ private class JsonSerialize(mailboxIdFactory: MailboxId.Factory) { implicit val aclEntryKeyWrites: Writes[JavaMailboxACL.EntryKey] = value => JsString(value.serialize()) implicit val aclRightsWrites: Writes[JavaMailboxACL.Rfc4314Rights] = value => JsString(value.serialize()) implicit val aclDiffWrites: Writes[ACLDiff] = Json.writes[ACLDiff] + implicit val messageIdWrites: Writes[MessageId] = value => JsString(value.serialize()) + implicit val messageUidWrites: Writes[MessageUid] = value => JsNumber(value.asLong()) + implicit val flagsWrites: Writes[JavaMailFlags] = value => JsArray(Flags.fromJavaFlags(value).map(flag => JsString(flag))) + implicit val messageMetaDataWrites: Writes[MetaDataDTO.MessageMetaData] = Json.writes[MetaDataDTO.MessageMetaData] implicit val aclEntryKeyReads: Reads[JavaMailboxACL.EntryKey] = { case JsString(keyAsString) => JsSuccess(JavaMailboxACL.EntryKey.deserialize(keyAsString)) @@ -161,6 +191,18 @@ private class JsonSerialize(mailboxIdFactory: MailboxId.Factory) { case JsString(userAsString) => JsSuccess(User.fromUsername(userAsString)) case _ => JsError() } + implicit val messageIdReads: Reads[MessageId] = { + case JsString(value) => JsSuccess(messageIdFactory.fromString(value)) + case _ => JsError() + } + implicit val messageUidReads: Reads[MessageUid] = { + case JsNumber(value) => JsSuccess(MessageUid.of(value.toLong)) + case _ => JsError() + } + implicit val flagsReads: Reads[JavaMailFlags] = { + case JsArray(seqOfJsValues) => JsSuccess(Flags.toJavaFlags(seqOfJsValues.toArray.map(jsValue => jsValue.toString()))) + case _ => JsError() + } implicit def scopeMapReads[V](implicit vr: Reads[V]): Reads[Map[JavaQuota.Scope, V]] = Reads.mapReads[JavaQuota.Scope, V] { str => @@ -172,6 +214,7 @@ private class JsonSerialize(mailboxIdFactory: MailboxId.Factory) { JsObject(m.map { case (k, v) => (k.toString, vr.writes(v)) }.toSeq) } + implicit def scopeMapReadsACL[V](implicit vr: Reads[V]): Reads[Map[JavaMailboxACL.EntryKey, V]] = Reads.mapReads[JavaMailboxACL.EntryKey, V] { str => Json.fromJson[JavaMailboxACL.EntryKey](JsString(str)) @@ -182,10 +225,21 @@ private class JsonSerialize(mailboxIdFactory: MailboxId.Factory) { JsObject(m.map { case (k, v) => (k.toString, vr.writes(v)) }.toSeq) } + implicit def scopeMessageUidMapReads[V](implicit vr: Reads[V]): Reads[Map[MessageUid, V]] = + Reads.mapReads[MessageUid, V] { str => + JsSuccess(MessageUid.of(str.toLong)) + } + + implicit def scopeMessageUidMapWrite[V](implicit vr: Writes[V]): Writes[Map[MessageUid, V]] = + (m: Map[MessageUid, V]) => { + JsObject(m.map { case (k, v) => (String.valueOf(k.asLong()), vr.writes(v)) }.toSeq) + } + implicit val aclDiffReads: Reads[ACLDiff] = Json.reads[ACLDiff] implicit val mailboxPathReads: Reads[MailboxPath] = Json.reads[MailboxPath] implicit val quotaCReads: Reads[Quota[QuotaCount]] = Json.reads[Quota[QuotaCount]] implicit val quotaSReads: Reads[Quota[QuotaSize]] = Json.reads[Quota[QuotaSize]] + implicit val messageMetaDataReads: Reads[MetaDataDTO.MessageMetaData] = Json.reads[MetaDataDTO.MessageMetaData] implicit val eventOFormat: OFormat[Event] = derived.oformat() @@ -194,12 +248,13 @@ private class JsonSerialize(mailboxIdFactory: MailboxId.Factory) { def fromJson(json: String): JsResult[Event] = Json.fromJson[Event](Json.parse(json)) } -class EventSerializer(mailboxIdFactory: MailboxId.Factory) { - def toJson(event: JavaEvent): String = new JsonSerialize(mailboxIdFactory).toJson(ScalaConverter.toScala(event)) +class EventSerializer(mailboxIdFactory: MailboxId.Factory, messageIdFactory: MessageId.Factory) { + def toJson(event: JavaEvent): String = new JsonSerialize(mailboxIdFactory, messageIdFactory).toJson(ScalaConverter.toScala(event)) def fromJson(json: String): JsResult[JavaEvent] = { - new JsonSerialize(mailboxIdFactory) + new JsonSerialize(mailboxIdFactory, messageIdFactory) .fromJson(json) .map(event => event.toJava) } } + http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/event/json/src/main/scala/org/apache/james/event/json/MetaDataDTO.scala ---------------------------------------------------------------------- diff --git a/mailbox/event/json/src/main/scala/org/apache/james/event/json/MetaDataDTO.scala b/mailbox/event/json/src/main/scala/org/apache/james/event/json/MetaDataDTO.scala new file mode 100644 index 0000000..ee314f0 --- /dev/null +++ b/mailbox/event/json/src/main/scala/org/apache/james/event/json/MetaDataDTO.scala @@ -0,0 +1,90 @@ +/** ************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + * ***************************************************************/ + +package org.apache.james.event.json + +import java.time.Instant +import java.util.Date + +import javax.mail.{Flags => JavaMailFlags} +import org.apache.james.mailbox.model.{MessageId, MessageMetaData => JavaMessageMetaData} +import org.apache.james.mailbox.{FlagsBuilder, MessageUid} + +object MetaDataDTO { + + object MessageMetaData { + def fromJava(javaMessageMetaData: JavaMessageMetaData): MessageMetaData = MetaDataDTO.MessageMetaData( + javaMessageMetaData.getUid, + javaMessageMetaData.getModSeq, + javaMessageMetaData.getFlags, + javaMessageMetaData.getSize, + javaMessageMetaData.getInternalDate.toInstant, + javaMessageMetaData.getMessageId) + } + + object Flags { + val ANSWERED = "\\Answered" + val DELETED = "\\Deleted" + val DRAFT = "\\Draft" + val FLAGGED = "\\Flagged" + val RECENT = "\\Recent" + val SEEN = "\\Seen" + val ALL_SYSTEM_FLAGS = List(ANSWERED, DELETED, DRAFT, FLAGGED, RECENT, SEEN) + + def toJavaFlags(serializedFlags: Array[String]): JavaMailFlags = { + serializedFlags + .map(toFlagBuilder) + .reduceOption(_ merge _) + .getOrElse(new FlagsBuilder()) + .build() + } + + def toFlagBuilder(flag: String): FlagsBuilder = ALL_SYSTEM_FLAGS.contains(flag) match { + case true => new FlagsBuilder().add(stringToSystemFlag(flag)) + case false => new FlagsBuilder().add(flag) + } + + def fromJavaFlags(flags: JavaMailFlags): Array[String] = { + flags.getUserFlags ++ flags.getSystemFlags.map(flag => systemFlagToString(flag)) + } + + private def stringToSystemFlag(serializedFlag: String): JavaMailFlags.Flag = serializedFlag match { + case ANSWERED => JavaMailFlags.Flag.ANSWERED + case DELETED => JavaMailFlags.Flag.DELETED + case DRAFT => JavaMailFlags.Flag.DRAFT + case FLAGGED => JavaMailFlags.Flag.FLAGGED + case RECENT => JavaMailFlags.Flag.RECENT + case SEEN => JavaMailFlags.Flag.SEEN + case _ => throw new IllegalArgumentException(serializedFlag + " is not a system flag") + } + + private def systemFlagToString(flag: JavaMailFlags.Flag): String = flag match { + case JavaMailFlags.Flag.ANSWERED => ANSWERED + case JavaMailFlags.Flag.DELETED => DELETED + case JavaMailFlags.Flag.DRAFT => DRAFT + case JavaMailFlags.Flag.FLAGGED => FLAGGED + case JavaMailFlags.Flag.RECENT => RECENT + case JavaMailFlags.Flag.SEEN => SEEN + } + } + + case class MessageMetaData(uid: MessageUid, modSeq: Long, flags: JavaMailFlags, size: Long, internalDate: Instant, messageId: MessageId) { + def toJava: JavaMessageMetaData = new JavaMessageMetaData(uid, modSeq, flags, size, Date.from(internalDate), messageId) + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/event/json/src/test/java/org/apache/james/event/json/AddedSerializationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/AddedSerializationTest.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/AddedSerializationTest.java new file mode 100644 index 0000000..3ddc475 --- /dev/null +++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/AddedSerializationTest.java @@ -0,0 +1,1465 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.event.json; + +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; +import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; +import static org.apache.james.mailbox.model.MailboxConstants.USER_NAMESPACE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.time.Instant; +import java.util.Date; +import java.util.Map; +import java.util.NoSuchElementException; + +import javax.mail.Flags; + +import org.apache.james.core.User; +import org.apache.james.mailbox.FlagsBuilder; +import org.apache.james.mailbox.MailboxListener; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.MessageUid; +import org.apache.james.mailbox.model.MailboxConstants; +import org.apache.james.mailbox.model.MailboxId; +import org.apache.james.mailbox.model.MailboxPath; +import org.apache.james.mailbox.model.MessageMetaData; +import org.apache.james.mailbox.model.TestId; +import org.apache.james.mailbox.model.TestMessageId; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableMap; + +class AddedSerializationTest { + + private static final User USER = User.fromUsername("user"); + private static final MailboxSession.SessionId SESSION_ID = MailboxSession.SessionId.of(42); + private static final MailboxId MAILBOX_ID = TestId.of(18); + private static final String MAILBOX_NAME = "mailboxName"; + private static final MailboxPath MAILBOX_PATH = new MailboxPath(MailboxConstants.USER_NAMESPACE, "user", MAILBOX_NAME); + private static final MessageUid MESSAGE_UID = MessageUid.of(123456); + private static final Instant INSTANT = Instant.parse("2018-12-14T09:41:51.541Z"); + private static final TestMessageId MESSAGE_ID = TestMessageId.of(42); + private static final int MOD_SEQ = 35; + private static final int SIZE = 45; + private static final Flags FLAGS = FlagsBuilder.builder() + .add(Flags.Flag.ANSWERED, Flags.Flag.DRAFT) + .add("User Custom Flag") + .build(); + private static final Map<MessageUid, MessageMetaData> ADDED = ImmutableMap.of( + MESSAGE_UID, new MessageMetaData(MESSAGE_UID, MOD_SEQ, FLAGS, SIZE, Date.from(INSTANT), MESSAGE_ID)); + + private static final MailboxListener.Added DEFAULT_ADDED_EVENT = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, ADDED); + private static final String DEFAULT_ADDED_EVENT_JSON = + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}"; + + private static final EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory()); + + @Test + void addedShouldBeWellSerialized() { + assertThatJson(EVENT_SERIALIZER.toJson(DEFAULT_ADDED_EVENT)) + .isEqualTo(DEFAULT_ADDED_EVENT_JSON); + } + + @Test + void addedShouldBeWellDeSerialized() { + assertThat(EVENT_SERIALIZER.fromJson(DEFAULT_ADDED_EVENT_JSON).get()) + .isEqualTo(DEFAULT_ADDED_EVENT); + } + + @Nested + class WithEmptyAddedMap { + + private final MailboxListener.Added emptyAddedEvent = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, ImmutableMap.of()); + private final String emptyAddedEventJson = + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {}," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}"; + + @Test + void addedShouldBeWellSerializedWhenMapKeyIsEmpty() { + assertThatJson(EVENT_SERIALIZER.toJson(emptyAddedEvent)) + .isEqualTo(emptyAddedEventJson); + } + + @Test + void addedShouldBeWellDeSerializedWhenMapKeyIsEmpty() { + assertThat(EVENT_SERIALIZER.fromJson(emptyAddedEventJson).get()) + .isEqualTo(emptyAddedEvent); + } + } + + @Nested + class WithFlags { + + @Nested + class WithEmptyFlags { + private final Flags emptyFlags = new FlagsBuilder().build(); + private final MailboxListener.Added emptyFlagsAddedEvent = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, + ImmutableMap.of( + MESSAGE_UID, + new MessageMetaData(MESSAGE_UID, MOD_SEQ, emptyFlags, SIZE, Date.from(INSTANT), MESSAGE_ID))); + + private final String emptyFlagsAddedEventJson = + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": []," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}"; + + @Test + void addedShouldBeWellSerializedWhenEmptyFlags() { + assertThatJson(EVENT_SERIALIZER.toJson(emptyFlagsAddedEvent)) + .isEqualTo(emptyFlagsAddedEventJson); + } + + @Test + void addedShouldBeWellDeSerializedWhenEmptyFlags() { + assertThat(EVENT_SERIALIZER.fromJson(emptyFlagsAddedEventJson).get()) + .isEqualTo(emptyFlagsAddedEvent); + } + } + + @Nested + class WithOnlyUserFlags { + private final Flags onlyUserFlags = new FlagsBuilder() + .add("Custom 1", "Custom 2", "") + .build(); + private final MailboxListener.Added onlyUserFlagsAddedEvent = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, + ImmutableMap.of( + MESSAGE_UID, + new MessageMetaData(MESSAGE_UID, MOD_SEQ, onlyUserFlags, SIZE, Date.from(INSTANT), MESSAGE_ID))); + + private final String userOnlyFlagsAddedEventJson = + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"Custom 1\", \"Custom 2\", \"\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}"; + + @Test + void addedShouldBeWellSerializedWhenOnlyUserFlags() { + assertThatJson(EVENT_SERIALIZER.toJson(onlyUserFlagsAddedEvent)) + .when(IGNORING_ARRAY_ORDER) + .isEqualTo(userOnlyFlagsAddedEventJson); + } + + @Test + void addedShouldBeWellDeSerializedWhenOnlyUserFlags() { + assertThat(EVENT_SERIALIZER.fromJson(userOnlyFlagsAddedEventJson).get()) + .isEqualTo(onlyUserFlagsAddedEvent); + } + } + + @Nested + class WithOnlySystemFlags { + private final Flags onlySystemFlags = new FlagsBuilder() + .add(Flags.Flag.SEEN, Flags.Flag.ANSWERED, Flags.Flag.DELETED) + .build(); + private final MailboxListener.Added onlySystemFlagsAddedEvent = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, + ImmutableMap.of( + MESSAGE_UID, + new MessageMetaData(MESSAGE_UID, MOD_SEQ, onlySystemFlags, SIZE, Date.from(INSTANT), MESSAGE_ID))); + + private final String systemOnlyFlagsAddedEventJson = + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"\\\\Seen\", \"\\\\Answered\", \"\\\\Deleted\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}"; + + @Test + void addedShouldBeWellSerializedWhenOnlySystemFlags() { + assertThatJson(EVENT_SERIALIZER.toJson(onlySystemFlagsAddedEvent)) + .when(IGNORING_ARRAY_ORDER) + .isEqualTo(systemOnlyFlagsAddedEventJson); + } + + @Test + void addedShouldBeWellDeSerializedWhenOnlySystemFlags() { + assertThat(EVENT_SERIALIZER.fromJson(systemOnlyFlagsAddedEventJson).get()) + .isEqualTo(onlySystemFlagsAddedEvent); + } + } + + @Nested + class WithFlagCaseSensitive { + + private static final String CASE_SENSITIVE_SYSTEM_FLAGS_EVENT_JSON = + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\answereD\", \"\\\\dRaFt\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}"; + + @Test + void addedShouldCareAboutSystemFlagsCaseSensitive() { + MailboxListener.Added deSerializedEvent = (MailboxListener.Added) EVENT_SERIALIZER + .fromJson(CASE_SENSITIVE_SYSTEM_FLAGS_EVENT_JSON) + .get(); + + assertThat(deSerializedEvent.getMetaData(MESSAGE_UID).getFlags().getSystemFlags()) + .isEmpty(); + } + } + } + + @Nested + class WithInternalDate { + + @Test + void addedShouldDeserializeWhenInternalDateIsInGoodISOFormat() { + Map<MessageUid, MessageMetaData> added = ImmutableMap.of( + MESSAGE_UID, new MessageMetaData(MESSAGE_UID, MOD_SEQ, FLAGS, SIZE, Date.from(Instant.parse("2018-12-14T09:41:51Z")), MESSAGE_ID)); + MailboxListener.Added eventRoundToMillis = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, added); + + assertThat(EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51+00:00\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isEqualTo(eventRoundToMillis); + } + + @Test + void addedShouldDeserializeWhenInternalDateIsMissingMilliSeconds() { + Map<MessageUid, MessageMetaData> added = ImmutableMap.of( + MESSAGE_UID, new MessageMetaData(MESSAGE_UID, MOD_SEQ, FLAGS, SIZE, Date.from(Instant.parse("2018-12-14T09:41:51Z")), MESSAGE_ID)); + MailboxListener.Added eventRoundToMillis = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, added); + + assertThat(EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isEqualTo(eventRoundToMillis); + } + + @Test + void addedShouldDeserializeWhenInternalDateIsMissingSeconds() { + Map<MessageUid, MessageMetaData> added = ImmutableMap.of( + MESSAGE_UID, new MessageMetaData(MESSAGE_UID, MOD_SEQ, FLAGS, SIZE, Date.from(Instant.parse("2018-12-14T09:41:00Z")), MESSAGE_ID)); + MailboxListener.Added eventRoundToMinute = new MailboxListener.Added(SESSION_ID, USER, MAILBOX_PATH, MAILBOX_ID, added); + + assertThat(EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isEqualTo(eventRoundToMinute); + } + } + @Nested + class NullOrEmptyNameSpaceInMailboxPath { + + @Test + void addedShouldBeWellDeSerializedWhenNullNameSpace() { + assertThat(EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isEqualTo(DEFAULT_ADDED_EVENT); + } + + @Test + void addedShouldBeWellDeSerializedWhenEmptyNameSpace() { + assertThat(EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isEqualTo(DEFAULT_ADDED_EVENT); + } + } + + @Nested + class NullUserInMailboxPath { + private final String nullUser = null; + private final MailboxListener.Added eventWithNullUserInPath = new MailboxListener.Added( + SESSION_ID, + USER, + new MailboxPath(USER_NAMESPACE, nullUser, MAILBOX_NAME), + MAILBOX_ID, + ADDED); + + private static final String EVENT_JSON_WITH_NULL_USER_IN_PATH = + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}"; + + @Test + void addedShouldBeWellSerialized() { + assertThatJson(EVENT_SERIALIZER.toJson(eventWithNullUserInPath)) + .isEqualTo(EVENT_JSON_WITH_NULL_USER_IN_PATH); + } + + @Test + void addedShouldBeWellDeSerialized() { + assertThat(EVENT_SERIALIZER.fromJson(EVENT_JSON_WITH_NULL_USER_IN_PATH).get()) + .isEqualTo(eventWithNullUserInPath); + } + } + + @Nested + class DeserializationErrors { + + @Nested + class DeserializationErrorOnSessionId { + @Test + void addedShouldThrowWhenMissingSessionId() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenNullSessionId() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": null," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenStringSessionId() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": \"42\"," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnUser { + @Test + void addedShouldThrowWhenMissingUser() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenUserIsNotAString() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": 596" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenUserIsNotWellFormatted() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user@user@anotherUser\"" + + " }" + + "}").get()) + .isInstanceOf(IllegalArgumentException.class); + } + } + + @Nested + class DeserializationErrorOnMailboxId { + @Test + void addedShouldThrowWhenMissingMailboxId() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenNullMailboxId() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": null," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenMailboxIdIsANumber() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": 18," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnMailboxPath { + + @Nested + class DeserializationErrorOnNameSpace { + @Test + void addedShouldThrowWhenNameSpaceIsNotAString() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": 48246," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnUser { + @Test + void addedShouldThrowWhenUserIsNotAString() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": 265412.64," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnMailboxName { + + @Test + void addedShouldThrowWhenNullMailboxName() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": null" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenMailboxNameIdIsANumber() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": 11861" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + } + + @Nested + class DeserializationErrorOnAddedMap { + @Test + void addedShouldThrowWhenMapKeyIsNull() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": null," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Nested + class DeserializationErrorOnMessageUid { + + @Test + void addedShouldThrowWhenMessageUidIsAString() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": null" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": \"123456\"," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenMessageUidIsNull() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": null" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": null," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnModSeq { + + @Test + void addedShouldThrowWhenModSeqIsAString() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": \"35\"," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenModSeqIsNull() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": null" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": null," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + + @Nested + class DeserializationErrorOnSize { + + @Test + void addedShouldThrowWhenSizeIsAString() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": \"45\", " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenSizeIsNull() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": null, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnMessageId { + + @Test + void addedShouldThrowWhenMessageIdIsANumber() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": 42" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenMessageIdIsNull() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541Z\"," + + " \"messageId\": null" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnInternalDate { + @Test + void addedShouldThrowWhenInternalDateIsNotInISOFormatBecauseOfMissingTWord() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14 12:52:36+07:00\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenInternalDateContainsOnlyDate() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenInternalDateIsMissingHourPart() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14TZ\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenInternalDateIsMissingTimeZone() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14T09:41:51.541\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenInternalDateIsMissingHours() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"2018-12-14Z\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenInternalDateIsEmpty() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": \"\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenInternalDateIsNull() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"User Custom Flag\", \"\\\\Answered\", \"\\\\Draft\"]," + + " \"size\": 45, " + + " \"internalDate\": null," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + + @Nested + class DeserializationErrorOnFlags { + + @Test + void addedShouldThrowWhenFlagsIsNull() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": null," + + " \"size\": 45, " + + " \"internalDate\": \"\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenFlagsContainsNullElements() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"flag 1\", null, \"flags 2\", null]," + + " \"size\": 45, " + + " \"internalDate\": \"\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void addedShouldThrowWhenFlagsContainsNumberElements() { + assertThatThrownBy(() -> EVENT_SERIALIZER.fromJson( + "{" + + " \"Added\": {" + + " \"path\": {" + + " \"namespace\": \"#private\"," + + " \"user\": \"user\"," + + " \"name\": \"mailboxName\"" + + " }," + + " \"mailboxId\": \"18\"," + + " \"added\": {" + + " \"123456\": {" + + " \"uid\": 123456," + + " \"modSeq\": 35," + + " \"flags\": [\"flag 1\", 1254, \"flags 2\", 125.36]," + + " \"size\": 45, " + + " \"internalDate\": \"\"," + + " \"messageId\": \"42\"" + + " }" + + " }," + + " \"sessionId\": 42," + + " \"user\": \"user\"" + + " }" + + "}").get()) + .isInstanceOf(NoSuchElementException.class); + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxACLUpdatedEventSerializationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxACLUpdatedEventSerializationTest.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxACLUpdatedEventSerializationTest.java index ceed360..14d3bf1 100644 --- a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxACLUpdatedEventSerializationTest.java +++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxACLUpdatedEventSerializationTest.java @@ -34,6 +34,7 @@ import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxConstants; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.TestId; +import org.apache.james.mailbox.model.TestMessageId; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -44,7 +45,7 @@ class MailboxACLUpdatedEventSerializationTest { private static final User USER = User.fromUsername("user"); private static final MailboxACL.EntryKey ENTRY_KEY = org.apache.james.mailbox.model.MailboxACL.EntryKey.createGroupEntryKey("any", false); private static final MailboxACL.Rfc4314Rights RIGHTS = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Administer, MailboxACL.Right.Read); - private static final EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory()); + private static final EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory()); private static final MailboxACL MAILBOX_ACL = new MailboxACL( new MailboxACL.Entry(ENTRY_KEY, RIGHTS), new MailboxACL.Entry(MailboxACL.EntryKey.createUserEntryKey("alice", true), http://git-wip-us.apache.org/repos/asf/james-project/blob/39bc507a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxAddedSerializationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxAddedSerializationTest.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxAddedSerializationTest.java index 0c7b3ea..339e4d6 100644 --- a/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxAddedSerializationTest.java +++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/MailboxAddedSerializationTest.java @@ -31,6 +31,7 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.model.MailboxConstants; import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.TestId; +import org.apache.james.mailbox.model.TestMessageId; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -38,7 +39,7 @@ class MailboxAddedSerializationTest { private static final User USER = User.fromUsername("user"); - private static final EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory()); + private static final EventSerializer EVENT_SERIALIZER = new EventSerializer(new TestId.Factory(), new TestMessageId.Factory()); private static final MailboxListener.MailboxAdded EVENT_1 = new MailboxListener.MailboxAdded( MailboxSession.SessionId.of(42), --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
