JAMES-1692 Strong typing creationId in SetMessages requests/responses
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8174cb77 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8174cb77 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8174cb77 Branch: refs/heads/master Commit: 8174cb776ed611fc3208ae650fb604b2a5a945d0 Parents: 078ba1a Author: Fabien Vignon <[email protected]> Authored: Thu Feb 25 16:01:05 2016 +0100 Committer: Raphael Ouazana <[email protected]> Committed: Tue Mar 1 15:46:15 2016 +0100 ---------------------------------------------------------------------- .../jmap/methods/MIMEMessageConverter.java | 5 +- .../james/jmap/methods/MessageWithId.java | 9 +-- .../methods/SetMessagesCreationProcessor.java | 3 +- .../james/jmap/model/CreationMessageId.java | 59 ++++++++++++++++++++ .../james/jmap/model/SetMessagesRequest.java | 10 ++-- .../james/jmap/model/SetMessagesResponse.java | 20 +++---- .../jmap/methods/MIMEMessageConverterTest.java | 9 +-- .../SetMessagesCreationProcessorTest.java | 3 +- .../jmap/model/SetMessagesResponseTest.java | 16 +++--- 9 files changed, 99 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java index 783ced0..207a36d 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MIMEMessageConverter.java @@ -30,6 +30,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; import org.apache.james.jmap.model.CreationMessage; +import org.apache.james.jmap.model.CreationMessageId; import org.apache.james.mime4j.Charsets; import org.apache.james.mime4j.codec.DecodeMonitor; import org.apache.james.mime4j.dom.FieldParser; @@ -86,7 +87,7 @@ public class MIMEMessageConverter { return message; } - private Header buildMimeHeaders(String creationId, CreationMessage newMessage) { + private Header buildMimeHeaders(CreationMessageId creationId, CreationMessage newMessage) { Header messageHeaders = new HeaderImpl(); // add From: and Sender: headers @@ -116,7 +117,7 @@ public class MIMEMessageConverter { // add Subject: header messageHeaders.addField(Fields.subject(newMessage.getSubject())); // set creation Id as MessageId: header - messageHeaders.addField(Fields.messageId(creationId)); + messageHeaders.addField(Fields.messageId(creationId.getId())); // date(String fieldName, Date date, TimeZone zone) // note that date conversion probably lose milliseconds ! http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java index fbc7105..0e4e172 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageWithId.java @@ -20,18 +20,19 @@ package org.apache.james.jmap.methods; import org.apache.james.jmap.model.CreationMessage; +import org.apache.james.jmap.model.CreationMessageId; public class MessageWithId<T> { - private String creationId; + private CreationMessageId creationId; private T message; - public MessageWithId(String creationId, T message) { + public MessageWithId(CreationMessageId creationId, T message) { this.creationId = creationId; this.message = message; } - public String getCreationId() { + public CreationMessageId getCreationId() { return creationId; } @@ -40,7 +41,7 @@ public class MessageWithId<T> { } public static class CreationMessageEntry extends MessageWithId<CreationMessage> { - public CreationMessageEntry(String creationId, CreationMessage message) { + public CreationMessageEntry(CreationMessageId creationId, CreationMessage message) { super(creationId, message); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java index 1177e54..718734d 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesCreationProcessor.java @@ -38,6 +38,7 @@ import javax.mail.util.SharedByteArrayInputStream; import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException; import org.apache.james.jmap.model.CreationMessage; +import org.apache.james.jmap.model.CreationMessageId; import org.apache.james.jmap.model.Message; import org.apache.james.jmap.model.MessageId; import org.apache.james.jmap.model.MessageProperties; @@ -114,7 +115,7 @@ public class SetMessagesCreationProcessor<Id extends MailboxId> implements SetMe .build(); } - private Map<String, SetError> handleCreationErrors(Predicate<CreationMessage> invalidMessagesTester, + private Map<CreationMessageId, SetError> handleCreationErrors(Predicate<CreationMessage> invalidMessagesTester, SetMessagesRequest request) { return request.getCreate().entrySet().stream() .filter(e -> invalidMessagesTester.test(e.getValue())) http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java new file mode 100644 index 0000000..e23dd6a --- /dev/null +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessageId.java @@ -0,0 +1,59 @@ +/**************************************************************** + * 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.jmap.model; + +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Preconditions; + +public class CreationMessageId { + + public static CreationMessageId of(String creationMessageId) { + return new CreationMessageId(creationMessageId); + } + + private final String id; + + private CreationMessageId(String id) { + Preconditions.checkNotNull(id); + Preconditions.checkArgument(!id.isEmpty()); + this.id = id; + } + + @JsonValue + public String getId() { + return id; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CreationMessageId) { + CreationMessageId other = (CreationMessageId) obj; + return Objects.equals(this.id, other.id); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java index 8e25ac5..096e9c6 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java @@ -48,7 +48,7 @@ public class SetMessagesRequest implements JmapRequest { private String accountId; private String ifInState; - private ImmutableMap.Builder<String, CreationMessage> create; + private ImmutableMap.Builder<CreationMessageId, CreationMessage> create; private ImmutableMap.Builder<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> updatesProvider; private ImmutableList.Builder<MessageId> destroy; @@ -73,7 +73,7 @@ public class SetMessagesRequest implements JmapRequest { return this; } - public Builder create(Map<String, CreationMessage> creations) { + public Builder create(Map<CreationMessageId, CreationMessage> creations) { this.create.putAll(creations); return this; } @@ -95,11 +95,11 @@ public class SetMessagesRequest implements JmapRequest { private final Optional<String> accountId; private final Optional<String> ifInState; - private final Map<String, CreationMessage> create; + private final Map<CreationMessageId, CreationMessage> create; private final Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update; private final List<MessageId> destroy; - @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<String, CreationMessage> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) { + @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, Map<CreationMessageId, CreationMessage> create, Map<MessageId, Function<UpdateMessagePatchConverter, UpdateMessagePatch>> update, List<MessageId> destroy) { this.accountId = accountId; this.ifInState = ifInState; this.create = create; @@ -115,7 +115,7 @@ public class SetMessagesRequest implements JmapRequest { return ifInState; } - public Map<String, CreationMessage> getCreate() { + public Map<CreationMessageId, CreationMessage> getCreate() { return create; } http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java index 004b11b..a536ba4 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java @@ -53,10 +53,10 @@ public class SetMessagesResponse implements Method.Response { private String accountId; private String oldState; private String newState; - private final ImmutableMap.Builder<String, Message> created; + private final ImmutableMap.Builder<CreationMessageId, Message> created; private final ImmutableList.Builder<MessageId> updated; private final ImmutableList.Builder<MessageId> destroyed; - private final ImmutableMap.Builder<String, SetError> notCreated; + private final ImmutableMap.Builder<CreationMessageId, SetError> notCreated; private final ImmutableMap.Builder<MessageId, SetError> notUpdated; private final ImmutableMap.Builder<MessageId, SetError> notDestroyed; @@ -81,7 +81,7 @@ public class SetMessagesResponse implements Method.Response { throw new NotImplementedException(); } - public Builder created(Map<String, Message> created) { + public Builder created(Map<CreationMessageId, Message> created) { this.created.putAll(created); return this; } @@ -101,7 +101,7 @@ public class SetMessagesResponse implements Method.Response { return this; } - public Builder notCreated(Map<String, SetError> notCreated) { + public Builder notCreated(Map<CreationMessageId, SetError> notCreated) { this.notCreated.putAll(notCreated); return this; } @@ -130,15 +130,15 @@ public class SetMessagesResponse implements Method.Response { private final String accountId; private final String oldState; private final String newState; - private final Map<String, Message> created; + private final Map<CreationMessageId, Message> created; private final List<MessageId> updated; private final List<MessageId> destroyed; - private final Map<String, SetError> notCreated; + private final Map<CreationMessageId, SetError> notCreated; private final Map<MessageId, SetError> notUpdated; private final Map<MessageId, SetError> notDestroyed; - @VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, Map<String, Message> created, List<MessageId> updated, List<MessageId> destroyed, - Map<String, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) { + @VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, Map<CreationMessageId, Message> created, List<MessageId> updated, List<MessageId> destroyed, + Map<CreationMessageId, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) { this.accountId = accountId; this.oldState = oldState; this.newState = newState; @@ -166,7 +166,7 @@ public class SetMessagesResponse implements Method.Response { } @JsonSerialize - public Map<String, Message> getCreated() { + public Map<CreationMessageId, Message> getCreated() { return created; } @@ -181,7 +181,7 @@ public class SetMessagesResponse implements Method.Response { } @JsonSerialize - public Map<String, SetError> getNotCreated() { + public Map<CreationMessageId, SetError> getNotCreated() { return notCreated; } http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java index 0224f49..b238dbf 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/MIMEMessageConverterTest.java @@ -28,6 +28,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import org.apache.james.jmap.model.CreationMessage; +import org.apache.james.jmap.model.CreationMessageId; import org.apache.james.mime4j.dom.Message; import org.apache.james.mime4j.dom.address.Mailbox; import org.apache.james.mime4j.stream.Field; @@ -51,7 +52,7 @@ public class MIMEMessageConverterTest { // When Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry( - "user|mailbox|1", messageHavingInReplyTo)); + CreationMessageId.of("user|mailbox|1"), messageHavingInReplyTo)); // Then assertThat(result.getHeader().getFields("In-Reply-To")).extracting(Field::getBody) @@ -62,7 +63,7 @@ public class MIMEMessageConverterTest { public void convertToMimeShouldThrowWhenMessageIsNull() { MIMEMessageConverter sut = new MIMEMessageConverter(); - sut.convertToMime(new MessageWithId.CreationMessageEntry("any", null)); + sut.convertToMime(new MessageWithId.CreationMessageEntry(CreationMessageId.of("any"), null)); } @Test @@ -79,7 +80,7 @@ public class MIMEMessageConverterTest { // When Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry( - "user|mailbox|1", testMessage)); + CreationMessageId.of("user|mailbox|1"), testMessage)); // Then assertThat(result.getFrom()).extracting(Mailbox::getAddress).allMatch(f -> f.equals(joesEmail)); @@ -103,7 +104,7 @@ public class MIMEMessageConverterTest { // When Message result = sut.convertToMime(new MessageWithId.CreationMessageEntry( - "user|mailbox|1", testMessage)); + CreationMessageId.of("user|mailbox|1"), testMessage)); // Then assertThat(result.getDate()).isEqualToIgnoringMillis(Date.from(now)); http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java index c5c8db6..5978f0e 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMessagesCreationProcessorTest.java @@ -33,6 +33,7 @@ import java.util.function.Function; import org.apache.james.jmap.exceptions.MailboxRoleNotFoundException; import org.apache.james.jmap.model.CreationMessage; +import org.apache.james.jmap.model.CreationMessageId; import org.apache.james.jmap.model.Message; import org.apache.james.jmap.model.MessageId; import org.apache.james.jmap.model.SetMessagesRequest; @@ -164,7 +165,7 @@ public class SetMessagesCreationProcessorTest { private SetMessagesRequest buildFakeCreationRequest() { return SetMessagesRequest.builder() - .create(ImmutableMap.of("anything-really", CreationMessage.builder() + .create(ImmutableMap.of(CreationMessageId.of("anything-really"), CreationMessage.builder() .from(DraftEmailer.builder().name("alice").email("[email protected]").build()) .to(ImmutableList.of(DraftEmailer.builder().name("bob").email("[email protected]").build())) .subject("Hey! ") http://git-wip-us.apache.org/repos/asf/james-project/blob/8174cb77/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java index 373f1b3..631fa96 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java @@ -53,7 +53,7 @@ public class SetMessagesResponseTest { @Test public void builderShouldWork() { ZonedDateTime currentDate = ZonedDateTime.now(); - ImmutableMap<String, Message> created = ImmutableMap.of("user|created|1", + ImmutableMap<CreationMessageId, Message> created = ImmutableMap.of(CreationMessageId.of("user|created|1"), Message.builder() .id(MessageId.of("user|created|1")) .blobId("blobId") @@ -67,7 +67,7 @@ public class SetMessagesResponseTest { .build()); ImmutableList<MessageId> updated = ImmutableList.of(MessageId.of("user|updated|1")); ImmutableList<MessageId> destroyed = ImmutableList.of(MessageId.of("user|destroyed|1")); - ImmutableMap<String, SetError> notCreated = ImmutableMap.of("dead-beef-defec8", SetError.builder().type("created").build()); + ImmutableMap<CreationMessageId, SetError> notCreated = ImmutableMap.of(CreationMessageId.of("dead-beef-defec8"), SetError.builder().type("created").build()); ImmutableMap<MessageId, SetError> notUpdated = ImmutableMap.of(MessageId.of("user|update|2"), SetError.builder().type("updated").build()); ImmutableMap<MessageId, SetError> notDestroyed = ImmutableMap.of(MessageId.of("user|destroyed|3"), SetError.builder().type("destroyed").build()); SetMessagesResponse expected = new SetMessagesResponse(null, null, null, created, updated, destroyed, notCreated, notUpdated, notDestroyed); @@ -89,10 +89,10 @@ public class SetMessagesResponseTest { // Given SetMessagesResponse.Builder emptyBuilder = SetMessagesResponse.builder(); SetMessagesResponse testee = SetMessagesResponse.builder() - .created(buildMessage("user|inbox|1")) + .created(buildMessage(CreationMessageId.of("user|inbox|1"))) .updated(ImmutableList.of(MessageId.of("user|inbox|2"))) .destroyed(ImmutableList.of(MessageId.of("user|inbox|3"))) - .notCreated(ImmutableMap.of( "dead-beef-defec8", SetError.builder().type("type").build())) + .notCreated(ImmutableMap.of(CreationMessageId.of("dead-beef-defec8"), SetError.builder().type("type").build())) .notUpdated(ImmutableMap.of(MessageId.of("user|inbox|5"), SetError.builder().type("type").build())) .notDestroyed(ImmutableMap.of(MessageId.of("user|inbox|6"), SetError.builder().type("type").build())) .build(); @@ -103,9 +103,9 @@ public class SetMessagesResponseTest { assertThat(emptyBuilder.build()).isEqualToComparingFieldByField(testee); } - private ImmutableMap<String, Message> buildMessage(String messageId) { + private ImmutableMap<CreationMessageId, Message> buildMessage(CreationMessageId messageId) { return ImmutableMap.of(messageId, Message.builder() - .id(MessageId.of(messageId)) + .id(MessageId.of(messageId.getId())) .blobId("blobId") .threadId("threadId") .mailboxIds(ImmutableList.of()) @@ -138,10 +138,10 @@ public class SetMessagesResponseTest { @Test public void mergeIntoShouldMergeCreatedLists() { // Given - String buildersCreatedMessageId = "user|inbox|1"; + CreationMessageId buildersCreatedMessageId = CreationMessageId.of("user|inbox|1"); SetMessagesResponse.Builder nonEmptyBuilder = SetMessagesResponse.builder() .created(buildMessage(buildersCreatedMessageId)); - String createdMessageId = "user|inbox|2"; + CreationMessageId createdMessageId = CreationMessageId.of("user|inbox|2"); SetMessagesResponse testee = SetMessagesResponse.builder() .created(buildMessage(createdMessageId)) .build(); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
