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 2019/12/06 02:34:16 UTC

[james-project] 06/21: JAMES-2992 hasAttachment is a fast view property

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 5afc1619b86b4e07612c716834a4da2f91e69d7a
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Tue Dec 3 14:49:30 2019 +0700

    JAMES-2992 hasAttachment is a fast view property
---
 .../org/apache/james/jmap/draft/model/Emailer.java  |  8 +++-----
 .../draft/model/message/view/MessageFastView.java   | 21 ++++++++++++++++++---
 .../model/message/view/MessageFastViewFactory.java  |  6 +++---
 .../draft/model/message/view/MessageFullView.java   | 21 +++++++++++----------
 .../draft/model/message/view/MessageHeaderView.java | 10 ++++++++--
 .../jmap/draft/json/ParsingWritingObjects.java      |  1 +
 .../apache/james/jmap/draft/model/EmailerTest.java  |  6 +++---
 .../jmap/draft/model/SetMessagesResponseTest.java   |  2 ++
 .../message/view/MessageFastViewFactoryTest.java    |  6 ++++--
 .../message/view/MessageFullViewFactoryTest.java    |  3 +++
 .../model/message/view/MessageFullViewTest.java     | 19 +++++++++++++++----
 11 files changed, 71 insertions(+), 32 deletions(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/Emailer.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/Emailer.java
index 819831c..ffb037c 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/Emailer.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/Emailer.java
@@ -56,13 +56,11 @@ public class Emailer {
             .orElse(ImmutableList.of());
     }
 
-    public static Emailer firstFromMailboxList(MailboxList list) {
+    public static Optional<Emailer> firstFromMailboxList(MailboxList list) {
         return Optional.ofNullable(list)
-            .map(mailboxes -> mailboxes.stream()
+            .flatMap(mailboxes -> mailboxes.stream()
                 .map(Emailer::fromMailbox)
-                .findFirst()
-                .orElse(null))
-            .orElse(null);
+                .findFirst());
     }
 
     private static Emailer fromMailbox(Mailbox mailbox) {
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastView.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastView.java
index 3143ba1..5c0eaae 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastView.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastView.java
@@ -54,10 +54,12 @@ public class MessageFastView extends MessageHeaderView {
     @JsonPOJOBuilder(withPrefix = "")
     public static class Builder<S extends MessageFastView.Builder<S>> extends MessageHeaderView.Builder<S> {
         protected Optional<Preview> preview;
+        protected Optional<Boolean> hasAttachment;
 
         protected Builder() {
             super();
             this.preview = Optional.empty();
+            this.hasAttachment = Optional.empty();
         }
 
         public S preview(Preview preview) {
@@ -70,22 +72,29 @@ public class MessageFastView extends MessageHeaderView {
             return (S) this;
         }
 
+        public S hasAttachment(boolean hasAttachment) {
+            this.hasAttachment = Optional.of(hasAttachment);
+            return (S) this;
+        }
+
         public MessageFastView build() {
             checkState();
             return new MessageFastView(id, blobId, threadId, mailboxIds, Optional.ofNullable(inReplyToMessageId),
-                headers, Optional.ofNullable(from),
+                headers, from,
                 to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, size, PreviewDTO.from(preview),
-                keywords.orElse(Keywords.DEFAULT_VALUE));
+                keywords.orElse(Keywords.DEFAULT_VALUE), hasAttachment.get());
         }
 
         @Override
         public void checkState() {
             super.checkState();
             Preconditions.checkState(preview != null, "'preview' is mandatory");
+            Preconditions.checkState(hasAttachment.isPresent(), "'hasAttachment' should be present");
         }
     }
 
     private final PreviewDTO preview;
+    private final boolean hasAttachment;
 
     @VisibleForTesting
     MessageFastView(MessageId id,
@@ -103,12 +112,18 @@ public class MessageFastView extends MessageHeaderView {
                     Instant date,
                     Number size,
                     PreviewDTO preview,
-                    Keywords keywords) {
+                    Keywords keywords,
+                    boolean hasAttachment) {
         super(id, blobId, threadId, mailboxIds, inReplyToMessageId, headers, from, to, cc, bcc, replyTo, subject, date, size, keywords);
         this.preview = preview;
+        this.hasAttachment = hasAttachment;
     }
 
     public PreviewDTO getPreview() {
         return preview;
     }
+
+    public boolean isHasAttachment() {
+        return hasAttachment;
+    }
 }
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactory.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactory.java
index edc43b7..e33993b 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactory.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactory.java
@@ -42,7 +42,6 @@ import org.apache.james.mime4j.dom.Message;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
@@ -73,7 +72,7 @@ public class MessageFastViewFactory implements MessageViewFactory<MessageFastVie
             MessageResult firstMessageResult = messageResults.iterator().next();
             Preconditions.checkArgument(fastProjections.containsKey(firstMessageResult.getMessageId()),
                 "FromMessageResultAndPreview usage requires a precomputed preview");
-
+            MessageFastViewPrecomputedProperties messageProjection = fastProjections.get(firstMessageResult.getMessageId());
             List<MailboxId> mailboxIds = Helpers.getMailboxIds(messageResults);
 
             Message mimeMessage = Helpers.parse(firstMessageResult.getFullContent().getInputStream());
@@ -94,7 +93,8 @@ public class MessageFastViewFactory implements MessageViewFactory<MessageFastVie
                 .bcc(Emailer.fromAddressList(mimeMessage.getBcc()))
                 .replyTo(Emailer.fromAddressList(mimeMessage.getReplyTo()))
                 .date(Helpers.getDateFromHeaderOrInternalDateOtherwise(mimeMessage, firstMessageResult))
-                .preview(fastProjections.get(firstMessageResult.getMessageId()).getPreview())
+                .preview(messageProjection.getPreview())
+                .hasAttachment(messageProjection.hasAttachment())
                 .build();
         }
     }
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFullView.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFullView.java
index fc809c8..528eda2 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFullView.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageFullView.java
@@ -76,7 +76,8 @@ public class MessageFullView extends MessageFastView {
 
         public Builder attachments(List<Attachment> attachments) {
             this.attachments.addAll(attachments);
-            return this;
+            boolean hasAttachments = this.hasAttachment(this.attachments.build());
+            return super.hasAttachment(hasAttachments);
         }
 
         public Builder attachedMessages(Map<BlobId, SubMessage> attachedMessages) {
@@ -88,18 +89,23 @@ public class MessageFullView extends MessageFastView {
             ImmutableList<Attachment> attachments = this.attachments.build();
             ImmutableMap<BlobId, SubMessage> attachedMessages = this.attachedMessages.build();
             checkState(attachments, attachedMessages);
-            boolean hasAttachment = hasAttachment(attachments);
 
             return new MessageFullView(id, blobId, threadId, mailboxIds, Optional.ofNullable(inReplyToMessageId),
-                hasAttachment, headers, Optional.ofNullable(from),
+                hasAttachment.get(), headers, from,
                 to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, size, PreviewDTO.from(preview), textBody, htmlBody, attachments, attachedMessages,
                 keywords.orElse(Keywords.DEFAULT_VALUE));
         }
 
-        public void checkState(ImmutableList<Attachment> attachments, ImmutableMap<BlobId, SubMessage> attachedMessages) {
+        private void checkState(ImmutableList<Attachment> attachments, ImmutableMap<BlobId, SubMessage> attachedMessages) {
             super.checkState();
             Preconditions.checkState(areAttachedMessagesKeysInAttachments(attachments, attachedMessages), "'attachedMessages' keys must be in 'attachements'");
         }
+
+        private boolean hasAttachment(List<Attachment> attachments) {
+            return attachments.stream()
+                .anyMatch(attachment -> !attachment.isInlinedWithCid());
+        }
+
     }
 
     protected static boolean areAttachedMessagesKeysInAttachments(ImmutableList<Attachment> attachments, ImmutableMap<BlobId, SubMessage> attachedMessages) {
@@ -113,11 +119,6 @@ public class MessageFullView extends MessageFastView {
             .anyMatch(blobId -> blobId.equals(key));
     }
 
-    private static boolean hasAttachment(List<Attachment> attachments) {
-        return attachments.stream()
-                .anyMatch(attachment -> !attachment.isInlinedWithCid());
-    }
-
     private final boolean hasAttachment;
     private final Optional<String> textBody;
     private final Optional<String> htmlBody;
@@ -146,7 +147,7 @@ public class MessageFullView extends MessageFastView {
                     ImmutableList<Attachment> attachments,
                     ImmutableMap<BlobId, SubMessage> attachedMessages,
                     Keywords keywords) {
-        super(id, blobId, threadId, mailboxIds, inReplyToMessageId, headers, from, to, cc, bcc, replyTo, subject, date, size, preview, keywords);
+        super(id, blobId, threadId, mailboxIds, inReplyToMessageId, headers, from, to, cc, bcc, replyTo, subject, date, size, preview, keywords, hasAttachment);
         this.hasAttachment = hasAttachment;
         this.textBody = textBody;
         this.htmlBody = htmlBody;
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageHeaderView.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageHeaderView.java
index 9ad4610..c7eb122 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageHeaderView.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/message/view/MessageHeaderView.java
@@ -46,7 +46,7 @@ public class MessageHeaderView extends MessageMetadataView {
     public static class Builder<S extends MessageHeaderView.Builder<S>> extends MessageMetadataView.Builder<S> {
         protected String inReplyToMessageId;
         protected ImmutableMap<String, String> headers;
-        protected Emailer from;
+        protected Optional<Emailer> from;
         protected final ImmutableList.Builder<Emailer> to;
         protected final ImmutableList.Builder<Emailer> cc;
         protected final ImmutableList.Builder<Emailer> bcc;
@@ -56,6 +56,7 @@ public class MessageHeaderView extends MessageMetadataView {
 
         protected Builder() {
             super();
+            from = Optional.empty();
             to = ImmutableList.builder();
             cc = ImmutableList.builder();
             bcc = ImmutableList.builder();
@@ -73,6 +74,11 @@ public class MessageHeaderView extends MessageMetadataView {
         }
 
         public S from(Emailer from) {
+            this.from = Optional.of(from);
+            return (S) this;
+        }
+
+        public S from(Optional<Emailer> from) {
             this.from = from;
             return (S) this;
         }
@@ -111,7 +117,7 @@ public class MessageHeaderView extends MessageMetadataView {
             checkState();
 
             return new MessageHeaderView(id, blobId, threadId, mailboxIds, Optional.ofNullable(inReplyToMessageId),
-                headers, Optional.ofNullable(from),
+                headers, from,
                 to.build(), cc.build(), bcc.build(), replyTo.build(), subject, date, size,
                 keywords.orElse(Keywords.DEFAULT_VALUE));
         }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/json/ParsingWritingObjects.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/json/ParsingWritingObjects.java
index dab006b..d52c27a 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/json/ParsingWritingObjects.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/json/ParsingWritingObjects.java
@@ -91,6 +91,7 @@ public interface ParsingWritingObjects {
             .preview(Common.PREVIEW)
             .textBody(Common.TEXT_BODY)
             .htmlBody(Common.HTML_BODY)
+            .hasAttachment(false)
             .build();
 
     SubMessage SUB_MESSAGE = SubMessage.builder()
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/EmailerTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/EmailerTest.java
index f056d0c..94cceca 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/EmailerTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/EmailerTest.java
@@ -154,9 +154,9 @@ public class EmailerTest {
     }
 
     @Test
-    public void firstFromMailboxListShouldReturnNullWhenNullMailboxList() {
+    public void firstFromMailboxListShouldReturnEmptyWhenNullMailboxList() {
         assertThat(Emailer.firstFromMailboxList(null))
-            .isNull();
+            .isEmpty();
     }
 
     @Test
@@ -164,7 +164,7 @@ public class EmailerTest {
         assertThat(Emailer.firstFromMailboxList(new MailboxList(
                 new Mailbox("user1Inbox", "user1", "james.org"),
                 new Mailbox("user2Inbox", "user2", "james.org"))))
-            .isEqualTo(Emailer.builder()
+            .contains(Emailer.builder()
                 .name("user1Inbox")
                 .email("user1@james.org")
                 .build());
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/SetMessagesResponseTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/SetMessagesResponseTest.java
index b668490..49cc9de 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/SetMessagesResponseTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/SetMessagesResponseTest.java
@@ -71,6 +71,7 @@ public class SetMessagesResponseTest {
                 .size(123)
                 .date(currentDate)
                 .preview(PREVIEW)
+                .hasAttachment(false)
                 .build());
         ImmutableList<MessageId> updated = ImmutableList.of(TestMessageId.of(2));
         ImmutableList<MessageId> destroyed = ImmutableList.of(TestMessageId.of(3));
@@ -125,6 +126,7 @@ public class SetMessagesResponseTest {
                 .size(0)
                 .date(Instant.now())
                 .preview(PREVIEW)
+                .hasAttachment(false)
                 .build());
     }
 
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java
index 044bcaf..a254fb9 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java
@@ -149,7 +149,7 @@ class MessageFastViewFactoryTest {
     }
 
     @Test
-    void fromMessageIdsShouldReturnAMessageWithPreviewInThePreviewStore() throws Exception {
+    void fromMessageIdsShouldReturnAMessageWithComputedFastProperties() throws Exception {
         MessageFastView actual = messageFastViewFactory.fromMessageIds(ImmutableList.of(previewComputedMessage1.getMessageId()), session).get(0);
         SoftAssertions.assertSoftly(softly -> {
             softly.assertThat(actual.getId()).isEqualTo(previewComputedMessage1.getMessageId());
@@ -168,12 +168,13 @@ class MessageFastViewFactoryTest {
             softly.assertThat(actual.getSubject()).isEqualTo("Full message");
             softly.assertThat(actual.getDate()).isEqualTo("2016-06-07T14:23:37Z");
 
+            softly.assertThat(actual.isHasAttachment()).isTrue();
             softly.assertThat(actual.getPreview()).isEqualTo(PreviewDTO.of(PREVIEW_1_STRING));
         });
     }
 
     @Test
-    void fromMessageIdsShouldReturnAMessageWithPreviewComputedFromFullMessageWhenNotInThePreviewStore() throws Exception {
+    void fromMessageIdsShouldReturnAMessageWithPropertiesComputedFromFullMessageWhenNotPreComputed() throws Exception {
         MessageFastView actual = messageFastViewFactory.fromMessageIds(ImmutableList.of(missingPreviewComputedMessage1.getMessageId()), session).get(0);
         SoftAssertions.assertSoftly(softly -> {
             softly.assertThat(actual.getId()).isEqualTo(missingPreviewComputedMessage1.getMessageId());
@@ -192,6 +193,7 @@ class MessageFastViewFactoryTest {
             softly.assertThat(actual.getSubject()).isEqualTo("Full message");
             softly.assertThat(actual.getDate()).isEqualTo("2016-06-07T14:23:37Z");
 
+            softly.assertThat(actual.isHasAttachment()).isTrue();
             softly.assertThat(actual.getPreview()).isEqualTo(PreviewDTO.of(DEFAULT_PREVIEW_STRING));
         });
     }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java
index c717a41..38363c6 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java
@@ -245,6 +245,7 @@ class MessageFullViewFactoryTest {
                 .textBody(Optional.of(""))
                 .htmlBody(Optional.empty())
                 .keywords(keywords)
+                .hasAttachment(false)
                 .build();
         assertThat(testee).isEqualToComparingFieldByField(expected);
     }
@@ -296,6 +297,7 @@ class MessageFullViewFactoryTest {
             .textBody(Optional.of(""))
             .htmlBody(Optional.empty())
             .keywords(keywords)
+            .hasAttachment(false)
             .build();
 
         assertThat(testee).isEqualToComparingFieldByField(expected);
@@ -345,6 +347,7 @@ class MessageFullViewFactoryTest {
             .textBody(Optional.of(""))
             .htmlBody(Optional.empty())
             .keywords(keywords)
+            .hasAttachment(false)
             .build();
 
         assertThat(testee).isEqualToComparingFieldByField(expected);
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewTest.java
index 2cdf070..b8756f8 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewTest.java
@@ -19,6 +19,7 @@
 package org.apache.james.jmap.draft.model.message.view;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.time.Instant;
@@ -151,10 +152,19 @@ class MessageFullViewTest {
     }
 
     @Test
-    void buildShouldThrowWhenPreviewIsNull() {
-        assertThatThrownBy(() -> MessageFullView.builder().id(TestMessageId.of(1)).blobId(BlobId.of("blobId")).threadId("threadId").fluentMailboxIds().headers(ImmutableMap.of())
-            .subject("subject").size(123).date(Instant.now()).build())
-            .isInstanceOf(IllegalStateException.class);
+    void buildShouldNotThrowWhenPreviewIsNotPresent() {
+        assertThatCode(() -> MessageFullView.builder()
+                .id(TestMessageId.of(1))
+                .blobId(BlobId.of("blobId"))
+                .threadId("threadId")
+                .fluentMailboxIds()
+                    .headers(ImmutableMap.of())
+                .subject("subject")
+                .size(123)
+                .date(Instant.now())
+                .hasAttachment(false)
+                .build())
+            .doesNotThrowAnyException();
     }
 
     @Test
@@ -178,6 +188,7 @@ class MessageFullViewTest {
                 .size(123)
                 .date(currentDate)
                 .preview(PREVIEW)
+                .hasAttachment(false)
                 .build();
         assertThat(tested).isEqualToComparingFieldByField(expected);
     }


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