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 rc...@apache.org on 2019/11/25 02:19:38 UTC

[james-project] 10/10: JAMES-2988 Deduce read levels from MessageProperties

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

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

commit 31fe9b08e2ec0c447149667ccdac2d442cd2c0cb
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 21 15:35:59 2019 +0700

    JAMES-2988 Deduce read levels from MessageProperties
---
 .../jmap/draft/methods/GetMessagesMethod.java      |   1 +
 .../james/jmap/draft/model/MessageProperties.java  | 109 +++++++++++++++------
 .../jmap/draft/model/MessagePropertiesTest.java    |  96 ++++++++++++++++++
 3 files changed, 174 insertions(+), 32 deletions(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
index faae6f4..1b414a0 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
@@ -130,6 +130,7 @@ public class GetMessagesMethod implements Method {
         getMessagesRequest.getAccountId().ifPresent((input) -> notImplemented("accountId"));
 
         try {
+            MessageProperties.ReadLevel readLevel = getMessagesRequest.getProperties().computeReadLevel();
             return GetMessagesResponse.builder()
                 .messages(
                     messageIdManager.getMessages(getMessagesRequest.getIds(), FetchGroupImpl.FULL_CONTENT, mailboxSession)
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java
index 2bebd95..13d8f9c 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java
@@ -71,6 +71,28 @@ public class MessageProperties {
                 .ensureHeadersMessageProperty();
     }
 
+    public ReadLevel computeReadLevel() {
+        Stream<ReadLevel> readLevels = Stream.concat(this.buildOutputMessageProperties()
+                .stream()
+                .map(MessageProperty::getReadLevel),
+            headerPropertiesReadLevel());
+
+        // If `null`, all properties will be fetched (JMAP Draft)
+        // This defer from RFC-8621 behavior (not implemented here)
+        // If omitted, this defaults to: [ "partId", "blobId", "size", "name", "type", "charset", "disposition", "cid",
+        // "language", "location" ]
+        return readLevels.reduce(ReadLevel::combine)
+            .orElse(ReadLevel.Full);
+
+    }
+
+    private Stream<ReadLevel> headerPropertiesReadLevel() {
+        return headersProperties.map(collection ->
+            collection.stream()
+                .map(any -> ReadLevel.Header))
+            .orElse(Stream.of());
+    }
+
     private ImmutableSet<MessageProperty> buildOutputMessageProperties() {
         return this.messageProperties.orElseGet(MessageProperty::allOutputProperties);
     }
@@ -112,57 +134,62 @@ public class MessageProperties {
         return this;
     }
 
-
     private enum PropertyType {
         INPUTONLY,
         INPUTOUTPUT
     }
 
     public enum MessageProperty implements Property {
-        id("id"),
-        blobId("blobId"),
-        threadId("threadId"),
-        mailboxIds("mailboxIds"),
-        inReplyToMessageId("inReplyToMessageId"),
-        isUnread("isUnread"),
-        isFlagged("isFlagged"),
-        isAnswered("isAnswered"),
-        isDraft("isDraft"),
-        isForwarded("isForwarded"),
-        hasAttachment("hasAttachment"),
-        headers("headers"),
-        from("from"),
-        to("to"),
-        cc("cc"),
-        bcc("bcc"),
-        replyTo("replyTo"),
-        subject("subject"),
-        date("date"),
-        size("size"),
-        preview("preview"),
-        textBody("textBody"),
-        htmlBody("htmlBody"),
-        attachments("attachments"),
-        attachedMessages("attachedMessages"),
-        keywords("keywords"),
-        body("body", PropertyType.INPUTONLY);
+        id("id", ReadLevel.Metadata),
+        blobId("blobId", ReadLevel.Metadata),
+        threadId("threadId", ReadLevel.Metadata),
+        mailboxIds("mailboxIds", ReadLevel.Metadata),
+        inReplyToMessageId("inReplyToMessageId", ReadLevel.Header),
+        isUnread("isUnread", ReadLevel.Metadata),
+        isFlagged("isFlagged", ReadLevel.Metadata),
+        isAnswered("isAnswered", ReadLevel.Metadata),
+        isDraft("isDraft", ReadLevel.Metadata),
+        isForwarded("isForwarded", ReadLevel.Metadata),
+        hasAttachment("hasAttachment", ReadLevel.Full),
+        headers("headers", ReadLevel.Header),
+        from("from", ReadLevel.Header),
+        to("to", ReadLevel.Header),
+        cc("cc", ReadLevel.Header),
+        bcc("bcc", ReadLevel.Header),
+        replyTo("replyTo", ReadLevel.Header),
+        subject("subject", ReadLevel.Header),
+        date("date", ReadLevel.Header),
+        size("size", ReadLevel.Metadata),
+        preview("preview", ReadLevel.Full),
+        textBody("textBody", ReadLevel.Full),
+        htmlBody("htmlBody", ReadLevel.Full),
+        attachments("attachments", ReadLevel.Full),
+        attachedMessages("attachedMessages", ReadLevel.Full),
+        keywords("keywords", ReadLevel.Metadata),
+        body("body", PropertyType.INPUTONLY, ReadLevel.Full);
     
         private final String property;
         private final PropertyType type;
+        private final ReadLevel readLevel;
 
-        MessageProperty(String property) {
-            this(property, PropertyType.INPUTOUTPUT);
+        MessageProperty(String property, ReadLevel readLevel) {
+            this(property, PropertyType.INPUTOUTPUT, readLevel);
         }
 
-        MessageProperty(String property, PropertyType type) {
+        MessageProperty(String property, PropertyType type, ReadLevel readLevel) {
             this.property = property;
             this.type = type;
+            this.readLevel = readLevel;
         }
     
         @Override
         public String asFieldName() {
             return property;
         }
+
+        public ReadLevel getReadLevel() {
+            return readLevel;
+        }
     
         public static Stream<MessageProperty> find(String property) {
             Preconditions.checkNotNull(property);
@@ -184,7 +211,25 @@ public class MessageProperties {
             }
         }
     }
-    
+
+    public enum ReadLevel {
+        Metadata(0),
+        Header(1),
+        Full(2);
+
+        static ReadLevel combine(ReadLevel readLevel1, ReadLevel readLevel2) {
+            if (readLevel1.priority > readLevel2.priority) {
+                return readLevel1;
+            }
+            return readLevel2;
+        }
+
+        private final int priority;
+
+        ReadLevel(int priority) {
+            this.priority = priority;
+        }
+    }
 
     public static class HeaderProperty implements Property {
     
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
index 78bb1e7..82738b7 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
@@ -25,6 +25,7 @@ import java.util.Optional;
 
 import org.apache.james.jmap.draft.model.MessageProperties.HeaderProperty;
 import org.apache.james.jmap.draft.model.MessageProperties.MessageProperty;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableSet;
@@ -87,4 +88,99 @@ class MessagePropertiesTest {
             value -> assertThat(value).contains(HeaderProperty.fromFieldName("x-spam-score"))
         );
     }
+
+    @Test
+    void computeReadLevelShouldReturnHeaderWhenOnlyHeaderProperties() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("headers.X-Spam-Score"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Header);
+    }
+
+    @Test
+    void computeReadLevelShouldReturnMetadataWhenOnlyKeywordProperty() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("keywords"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Metadata);
+    }
+
+    @Test
+    void computeReadLevelShouldReturnFullWhenHtmlBodyProperty() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("htmlBody"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Full);
+    }
+
+    @Test
+    void computeReadLevelShouldCombineReadLevels() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("headers.X-Spam-Score", "keywords"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Header);
+    }
+
+    @Nested
+    class ReadLevelTest {
+        @Test
+        void combineShouldReturnMetadataWhenOnlyMetadata() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                    MessageProperties.ReadLevel.Metadata,
+                    MessageProperties.ReadLevel.Metadata))
+                .isEqualTo(MessageProperties.ReadLevel.Metadata);
+        }
+
+        @Test
+        void combineShouldReturnHeaderWhenOnlyHeader() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                    MessageProperties.ReadLevel.Header,
+                    MessageProperties.ReadLevel.Header))
+                .isEqualTo(MessageProperties.ReadLevel.Header);
+        }
+
+        @Test
+        void combineShouldReturnFullWhenOnlyFull() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                    MessageProperties.ReadLevel.Full,
+                    MessageProperties.ReadLevel.Full))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+
+        @Test
+        void combineShouldReturnHeaderWhenHeaderAndMetadata() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Metadata,
+                MessageProperties.ReadLevel.Header))
+                .isEqualTo(MessageProperties.ReadLevel.Header);
+        }
+
+        @Test
+        void combineShouldReturnFullWhenFullAndMetadata() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Metadata,
+                MessageProperties.ReadLevel.Full))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+
+        @Test
+        void combineShouldReturnFullWhenFullAndHeader() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Header,
+                MessageProperties.ReadLevel.Full))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+
+        @Test
+        void combineShouldCommute() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Full,
+                MessageProperties.ReadLevel.Header))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+    }
 }


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