You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2017/08/25 08:32:43 UTC

[05/13] james-project git commit: JAMES-2110 SetMessage with creation should support keywords for flags

JAMES-2110 SetMessage with creation should support keywords for flags


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/78a4a57d
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/78a4a57d
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/78a4a57d

Branch: refs/heads/master
Commit: 78a4a57de45038e63011e867e9a46419540cb4e5
Parents: c1387ef
Author: quynhn <qn...@linagora.com>
Authored: Tue Aug 15 16:42:17 2017 +0700
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Thu Aug 24 15:47:27 2017 +0200

----------------------------------------------------------------------
 .../methods/SetMessagesCreationProcessor.java   | 30 +++-----
 .../james/jmap/model/CreationMessage.java       | 73 ++++++++++----------
 .../SetMessagesCreationProcessorTest.java       | 57 ++++++++++++++-
 3 files changed, 101 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/78a4a57d/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 34bd029..bb9f189 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
@@ -20,14 +20,12 @@
 package org.apache.james.jmap.methods;
 
 import static org.apache.james.jmap.methods.Method.JMAP_PREFIX;
-
 import java.io.IOException;
 import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
-
 import javax.inject.Inject;
 import javax.mail.Flags;
 import javax.mail.MessagingException;
@@ -40,6 +38,7 @@ import org.apache.james.jmap.model.Attachment;
 import org.apache.james.jmap.model.BlobId;
 import org.apache.james.jmap.model.CreationMessage;
 import org.apache.james.jmap.model.CreationMessageId;
+import org.apache.james.jmap.model.Keywords;
 import org.apache.james.jmap.model.Message;
 import org.apache.james.jmap.model.MessageFactory;
 import org.apache.james.jmap.model.MessageFactory.MetaDataWithContent;
@@ -70,6 +69,7 @@ import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.metrics.api.TimeMetric;
 import org.apache.james.util.OptionalConverter;
 import org.apache.mailet.Mail;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -82,6 +82,7 @@ import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
 
+
 public class SetMessagesCreationProcessor implements SetMessagesProcessor {
 
     private static final Logger LOG = LoggerFactory.getLogger(SetMailboxesCreationProcessor.class);
@@ -290,16 +291,20 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
         byte[] messageContent = mimeMessageConverter.convert(createdEntry, messageAttachments);
         SharedByteArrayInputStream content = new SharedByteArrayInputStream(messageContent);
         Date internalDate = Date.from(createdEntry.getValue().getDate().toInstant());
-        Flags flags = getMessageFlags(createdEntry.getValue());
+
+        Flags flags = createdEntry.getValue()
+            .getKeywords()
+            .map(Keywords::asFlags)
+            .orElse(new Flags());
 
         ComposedMessageId message = outbox.appendMessage(content, internalDate, session, flags.contains(Flags.Flag.RECENT), flags);
 
         return MetaDataWithContent.builder()
                 .uid(message.getUid())
                 .flags(flags)
-                .size(messageContent.length)
                 .internalDate(internalDate.toInstant())
                 .sharedContent(content)
+                .size(messageContent.length)
                 .attachments(messageAttachments)
                 .mailboxId(outbox.getId())
                 .messageId(message.getMessageId())
@@ -332,23 +337,6 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
         }
     }
 
-    private Flags getMessageFlags(CreationMessage message) {
-        Flags result = new Flags();
-        if (!message.isIsUnread()) {
-            result.add(Flags.Flag.SEEN);
-        }
-        if (message.isIsFlagged()) {
-            result.add(Flags.Flag.FLAGGED);
-        }
-        if (message.isIsAnswered() || message.getInReplyToMessageId().isPresent()) {
-            result.add(Flags.Flag.ANSWERED);
-        }
-        if (message.isIsDraft()) {
-            result.add(Flags.Flag.DRAFT);
-        }
-        return result;
-    }
-
     private MessageWithId sendMessage(CreationMessageId creationId, MetaDataWithContent message, MailboxSession session) throws MailboxException, MessagingException {
         Message jmapMessage = messageFactory.fromMetaDataWithContent(message);
         sendMessage(message, jmapMessage, session);

http://git-wip-us.apache.org/repos/asf/james-project/blob/78a4a57d/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
index 791b383..f67185d 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/CreationMessage.java
@@ -27,7 +27,6 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-
 import javax.mail.internet.AddressException;
 import javax.mail.internet.InternetAddress;
 
@@ -59,10 +58,10 @@ public class CreationMessage {
     public static class Builder {
         private ImmutableList<String> mailboxIds;
         private String inReplyToMessageId;
-        private boolean isUnread;
-        private boolean isFlagged;
-        private boolean isAnswered;
-        private boolean isDraft;
+        private Optional<Boolean> isUnread = Optional.empty();
+        private Optional<Boolean> isFlagged = Optional.empty();
+        private Optional<Boolean> isAnswered = Optional.empty();
+        private Optional<Boolean> isDraft = Optional.empty();
         private final ImmutableMap.Builder<String, String> headers;
         private Optional<DraftEmailer> from = Optional.empty();
         private final ImmutableList.Builder<DraftEmailer> to;
@@ -75,6 +74,7 @@ public class CreationMessage {
         private String htmlBody;
         private final ImmutableList.Builder<Attachment> attachments;
         private final ImmutableMap.Builder<BlobId, SubMessage> attachedMessages;
+        private Optional<Map<String, Boolean>> keywords = Optional.empty();
 
         private Builder() {
             to = ImmutableList.builder();
@@ -101,22 +101,22 @@ public class CreationMessage {
             return this;
         }
 
-        public Builder isUnread(boolean isUnread) {
+        public Builder isUnread(Optional<Boolean> isUnread) {
             this.isUnread = isUnread;
             return this;
         }
 
-        public Builder isFlagged(boolean isFlagged) {
+        public Builder isFlagged(Optional<Boolean> isFlagged) {
             this.isFlagged = isFlagged;
             return this;
         }
 
-        public Builder isAnswered(boolean isAnswered) {
+        public Builder isAnswered(Optional<Boolean> isAnswered) {
             this.isAnswered = isAnswered;
             return this;
         }
 
-        public Builder isDraft(boolean isDraft) {
+        public Builder isDraft(Optional<Boolean> isDraft) {
             this.isDraft = isDraft;
             return this;
         }
@@ -186,6 +186,11 @@ public class CreationMessage {
             return this;
         }
 
+        public Builder keywords(Map<String, Boolean> keywords) {
+            this.keywords = Optional.of(ImmutableMap.copyOf(keywords));
+            return this;
+        }
+
         private static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<BlobId, SubMessage> attachedMessages) {
             return attachedMessages.isEmpty() || attachedMessages.keySet().stream()
                     .anyMatch(inAttachments(attachments));
@@ -206,21 +211,29 @@ public class CreationMessage {
             ImmutableMap<BlobId, SubMessage> attachedMessages = this.attachedMessages.build();
             Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachments'");
 
+            Optional<Keywords> creationKeywords = Keywords.factory()
+                .throwOnImapNonExposedKeywords()
+                .fromMapOrOldKeyword(keywords, getOldKeywords());
+
             if (date == null) {
                 date = ZonedDateTime.now();
             }
 
-            return new CreationMessage(mailboxIds, Optional.ofNullable(inReplyToMessageId), isUnread, isFlagged, isAnswered, isDraft, headers.build(), from,
-                    to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, Optional.ofNullable(textBody), Optional.ofNullable(htmlBody), attachments, attachedMessages);
+            return new CreationMessage(mailboxIds, Optional.ofNullable(inReplyToMessageId), headers.build(), from,
+                    to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, Optional.ofNullable(textBody), Optional.ofNullable(htmlBody),
+                    attachments, attachedMessages, creationKeywords);
+        }
+
+        private Optional<OldKeyword> getOldKeywords() {
+            if (isAnswered.isPresent() || isFlagged.isPresent() || isUnread.isPresent() || isDraft.isPresent()) {
+                return Optional.of(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft));
+            }
+            return Optional.empty();
         }
     }
 
     private final ImmutableList<String> mailboxIds;
     private final Optional<String> inReplyToMessageId;
-    private final boolean isUnread;
-    private final boolean isFlagged;
-    private final boolean isAnswered;
-    private final boolean isDraft;
     private final ImmutableMap<String, String> headers;
     private final Optional<DraftEmailer> from;
     private final ImmutableList<DraftEmailer> to;
@@ -233,17 +246,14 @@ public class CreationMessage {
     private final Optional<String> htmlBody;
     private final ImmutableList<Attachment> attachments;
     private final ImmutableMap<BlobId, SubMessage> attachedMessages;
+    private final Optional<Keywords> keywords;
 
     @VisibleForTesting
-    CreationMessage(ImmutableList<String> mailboxIds, Optional<String> inReplyToMessageId, boolean isUnread, boolean isFlagged, boolean isAnswered, boolean isDraft, ImmutableMap<String, String> headers, Optional<DraftEmailer> from,
+    CreationMessage(ImmutableList<String> mailboxIds, Optional<String> inReplyToMessageId, ImmutableMap<String, String> headers, Optional<DraftEmailer> from,
                     ImmutableList<DraftEmailer> to, ImmutableList<DraftEmailer> cc, ImmutableList<DraftEmailer> bcc, ImmutableList<DraftEmailer> replyTo, String subject, ZonedDateTime date, Optional<String> textBody, Optional<String> htmlBody, ImmutableList<Attachment> attachments,
-                    ImmutableMap<BlobId, SubMessage> attachedMessages) {
+                    ImmutableMap<BlobId, SubMessage> attachedMessages, Optional<Keywords> keywords) {
         this.mailboxIds = mailboxIds;
         this.inReplyToMessageId = inReplyToMessageId;
-        this.isUnread = isUnread;
-        this.isFlagged = isFlagged;
-        this.isAnswered = isAnswered;
-        this.isDraft = isDraft;
         this.headers = headers;
         this.from = from;
         this.to = to;
@@ -256,6 +266,7 @@ public class CreationMessage {
         this.htmlBody = htmlBody;
         this.attachments = attachments;
         this.attachedMessages = attachedMessages;
+        this.keywords = keywords;
     }
 
     public ImmutableList<String> getMailboxIds() {
@@ -266,22 +277,6 @@ public class CreationMessage {
         return inReplyToMessageId;
     }
 
-    public boolean isIsUnread() {
-        return isUnread;
-    }
-
-    public boolean isIsFlagged() {
-        return isFlagged;
-    }
-
-    public boolean isIsAnswered() {
-        return isAnswered;
-    }
-
-    public boolean isIsDraft() {
-        return isDraft;
-    }
-
     public ImmutableMap<String, String> getHeaders() {
         return headers;
     }
@@ -334,6 +329,10 @@ public class CreationMessage {
         return validate().isEmpty();
     }
 
+    public Optional<Keywords> getKeywords() {
+        return keywords;
+    }
+
     public List<ValidationResult> validate() {
         ImmutableList.Builder<ValidationResult> errors = ImmutableList.builder();
         assertValidFromProvided(errors);

http://git-wip-us.apache.org/repos/asf/james-project/blob/78a4a57d/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 cc10186..c2c36e6 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
@@ -42,6 +42,7 @@ import org.apache.james.jmap.model.BlobId;
 import org.apache.james.jmap.model.CreationMessage;
 import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
 import org.apache.james.jmap.model.CreationMessageId;
+import org.apache.james.jmap.model.Keyword;
 import org.apache.james.jmap.model.MessageFactory;
 import org.apache.james.jmap.model.MessagePreviewGenerator;
 import org.apache.james.jmap.model.MessageProperties.MessageProperty;
@@ -72,9 +73,12 @@ import org.apache.james.util.mime.MessageContentExtractor;
 import org.apache.mailet.Mail;
 import org.junit.Before;
 import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 public class SetMessagesCreationProcessorTest {
@@ -115,7 +119,8 @@ public class SetMessagesCreationProcessorTest {
     private Optional<MessageManager> optionalOutbox;
     private Optional<MessageManager> optionalDrafts;
 
-
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
     @Before
     public void setUp() throws MailboxException {
         HtmlTextExtractor htmlTextExtractor = mock(HtmlTextExtractor.class);
@@ -157,6 +162,56 @@ public class SetMessagesCreationProcessorTest {
     }
 
     @Test
+    public void processShouldThrowWhenBothIsFlagAndKeywords() {
+        expectedException.expect(IllegalArgumentException.class);
+        SetMessagesRequest createMessageWithError = SetMessagesRequest.builder()
+            .create(
+                creationMessageId,
+                creationMessageBuilder
+                    .mailboxId(OUTBOX_ID.serialize())
+                    .isAnswered(Optional.of(true))
+                    .keywords(ImmutableMap.of("$Answered", true))
+                    .build())
+            .build();
+
+        sut.process(createMessageWithError, session);
+    }
+
+    @Test
+    public void processShouldCreateWhenKeywords() {
+        SetMessagesRequest createMessageWithKeywords = SetMessagesRequest.builder()
+            .create(
+                creationMessageId,
+                creationMessageBuilder
+                    .mailboxId(OUTBOX_ID.serialize())
+                    .keywords(ImmutableMap.of("$Answered", true))
+                    .build())
+            .build();
+
+        SetMessagesResponse result = sut.process(createMessageWithKeywords, session);
+
+        assertThat(result.getCreated()).isNotEmpty();
+        assertThat(result.getNotCreated()).isEmpty();
+    }
+
+    @Test
+    public void processShouldCreateWhenIsFlag() {
+        SetMessagesRequest createMessageWithKeywords = SetMessagesRequest.builder()
+            .create(
+                creationMessageId,
+                creationMessageBuilder
+                    .mailboxId(OUTBOX_ID.serialize())
+                    .isAnswered(Optional.of(true))
+                    .build())
+            .build();
+
+        SetMessagesResponse result = sut.process(createMessageWithKeywords, session);
+
+        assertThat(result.getCreated()).isNotEmpty();
+        assertThat(result.getNotCreated()).isEmpty();
+    }
+
+    @Test
     public void processShouldReturnNonEmptyCreatedWhenRequestHasNonEmptyCreate() throws MailboxException {
         // Given
         sut = new SetMessagesCreationProcessor(mimeMessageConverter, mockedMailSpool, mockedMailFactory, messageFactory, fakeSystemMailboxesProvider, mockedAttachmentManager, new NoopMetricFactory());


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org