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:42 UTC
[04/13] james-project git commit: JAMES-2110 SetMessage with update
should support keywords for flags
JAMES-2110 SetMessage with update 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/92365a2e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/92365a2e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/92365a2e
Branch: refs/heads/master
Commit: 92365a2ee4813062a37f113a308ea172bc84025e
Parents: 78a4a57
Author: quynhn <qn...@linagora.com>
Authored: Tue Aug 15 16:43:27 2017 +0700
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Thu Aug 24 15:47:27 2017 +0200
----------------------------------------------------------------------
.../methods/SetMessagesUpdateProcessor.java | 7 +
.../james/jmap/model/UpdateMessagePatch.java | 72 ++++----
.../jmap/model/UpdateMessagePatchTest.java | 184 +++++++++++++++++--
3 files changed, 206 insertions(+), 57 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/92365a2e/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
index c303359..da7dceb 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesUpdateProcessor.java
@@ -111,6 +111,13 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
}
} catch (MailboxException e) {
handleMessageUpdateException(messageId, builder, e);
+ } catch (IllegalArgumentException e) {
+ ValidationResult invalidPropertyKeywords = ValidationResult.builder()
+ .property(MessageProperties.MessageProperty.keywords.asFieldName())
+ .message(e.getMessage())
+ .build();
+
+ handleInvalidRequest(builder, messageId, ImmutableList.of(invalidPropertyKeywords));
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/92365a2e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/UpdateMessagePatch.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/UpdateMessagePatch.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/UpdateMessagePatch.java
index 32e3fe2..6a46bf8 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/UpdateMessagePatch.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/UpdateMessagePatch.java
@@ -20,9 +20,9 @@
package org.apache.james.jmap.model;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
-
import javax.mail.Flags;
import org.apache.james.jmap.methods.ValidationResult;
@@ -31,6 +31,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@@ -47,6 +48,7 @@ public class UpdateMessagePatch {
private Optional<Boolean> isFlagged = Optional.empty();
private Optional<Boolean> isUnread = Optional.empty();
private Optional<Boolean> isAnswered = Optional.empty();
+ private Optional<Map<String, Boolean>> keywords = Optional.empty();
private Set<ValidationResult> validationResult = Sets.newHashSet();
public Builder mailboxIds(List<String> mailboxIds) {
@@ -54,6 +56,11 @@ public class UpdateMessagePatch {
return this;
}
+ public Builder keywords(Map<String, Boolean> keywords) {
+ this.keywords = Optional.of(ImmutableMap.copyOf(keywords));
+ return this;
+ }
+
public Builder isFlagged(Boolean isFlagged) {
this.isFlagged = Optional.of(isFlagged);
return this;
@@ -81,28 +88,36 @@ public class UpdateMessagePatch {
.message("mailboxIds property is not supposed to be empty")
.build()));
}
- return new UpdateMessagePatch(mailboxIds, isUnread, isFlagged, isAnswered, ImmutableList.copyOf(validationResult));
+
+ Optional<Keywords> updateKeywords = Keywords.factory()
+ .throwOnImapNonExposedKeywords()
+ .fromMapOrOldKeyword(keywords, getOldKeywords());
+
+ return new UpdateMessagePatch(mailboxIds, updateKeywords, ImmutableList.copyOf(validationResult));
+ }
+
+ private Optional<OldKeyword> getOldKeywords() {
+ if (isAnswered.isPresent() || isFlagged.isPresent() || isUnread.isPresent()) {
+ Optional<Boolean> isDraft = Optional.empty();
+ return Optional.of(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft));
+ }
+ return Optional.empty();
}
+
}
private final Optional<List<String>> mailboxIds;
- private final Optional<Boolean> isUnread;
- private final Optional<Boolean> isFlagged;
- private final Optional<Boolean> isAnswered;
+ private final Optional<Keywords> keywords;
private final ImmutableList<ValidationResult> validationErrors;
@VisibleForTesting
UpdateMessagePatch(Optional<List<String>> mailboxIds,
- Optional<Boolean> isUnread,
- Optional<Boolean> isFlagged,
- Optional<Boolean> isAnswered,
+ Optional<Keywords> keywords,
ImmutableList<ValidationResult> validationResults) {
this.mailboxIds = mailboxIds;
- this.isUnread = isUnread;
- this.isFlagged = isFlagged;
- this.isAnswered = isAnswered;
+ this.keywords = keywords;
this.validationErrors = validationResults;
}
@@ -110,22 +125,12 @@ public class UpdateMessagePatch {
return mailboxIds;
}
- public Optional<Boolean> isUnread() {
- return isUnread;
- }
-
- public Optional<Boolean> isFlagged() {
- return isFlagged;
- }
-
- public Optional<Boolean> isAnswered() {
- return isAnswered;
+ public Optional<Keywords> getKeywords() {
+ return keywords;
}
public boolean isFlagsIdentity() {
- return !isAnswered.isPresent()
- && !isFlagged.isPresent()
- && !isUnread.isPresent();
+ return !keywords.isPresent();
}
public ImmutableList<ValidationResult> getValidationErrors() {
@@ -137,19 +142,12 @@ public class UpdateMessagePatch {
}
public Flags applyToState(Flags currentFlags) {
- Flags newStateFlags = new Flags();
-
- if (isFlagged().orElse(currentFlags.contains(Flags.Flag.FLAGGED))) {
- newStateFlags.add(Flags.Flag.FLAGGED);
- }
- if (isAnswered().orElse(currentFlags.contains(Flags.Flag.ANSWERED))) {
- newStateFlags.add(Flags.Flag.ANSWERED);
- }
- boolean shouldMessageBeMarkSeen = isUnread().map(b -> !b).orElse(currentFlags.contains(Flags.Flag.SEEN));
- if (shouldMessageBeMarkSeen) {
- newStateFlags.add(Flags.Flag.SEEN);
- }
- return newStateFlags;
+ return keywords.map(keyword -> {
+ if (currentFlags.contains(Flags.Flag.DRAFT) != keyword.getKeywords().contains(Keyword.DRAFT)) {
+ throw new IllegalArgumentException("Cannot add or remove draft flag");
+ }
+ return keyword.asFlagsWithRecentAndDeletedFrom(currentFlags);
+ }).orElse(new Flags());
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/92365a2e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/UpdateMessagePatchTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/UpdateMessagePatchTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/UpdateMessagePatchTest.java
index e97c49c..e227746 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/UpdateMessagePatchTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/UpdateMessagePatchTest.java
@@ -20,42 +20,52 @@
package org.apache.james.jmap.model;
import static org.assertj.core.api.Assertions.assertThat;
-
import java.util.Arrays;
import java.util.List;
-
import javax.mail.Flags;
+import org.apache.james.mailbox.FlagsBuilder;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
public class UpdateMessagePatchTest {
+ private final static String FORWARDED = "forwarded";
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
@Test
public void UnsetUpdatePatchShouldBeValid() {
UpdateMessagePatch emptyPatch = UpdateMessagePatch.builder().build();
assertThat(emptyPatch.isValid()).isTrue();
- assertThat(emptyPatch.isUnread()).isEmpty();
- assertThat(emptyPatch.isFlagged()).isEmpty();
- assertThat(emptyPatch.isAnswered()).isEmpty();
}
@Test
public void builderShouldSetUnreadFalseWhenBuiltWithIsUnreadFalse() {
UpdateMessagePatch testee = UpdateMessagePatch.builder().isUnread(false).build();
- assertThat(testee.isUnread()).isPresent();
- assertThat(testee.isUnread().get()).isFalse();
}
@Test
- public void applyStateShouldSetFlaggedOnlyWhenUnsetPatchAppliedToFlaggedState() {
- UpdateMessagePatch testee = UpdateMessagePatch.builder().build();
- Flags isFlaggedSet = new Flags(Flags.Flag.FLAGGED);
- List<Flags.Flag> updatedFlags = Arrays.asList(testee.applyToState(isFlaggedSet).getSystemFlags());
+ public void applyStateShouldSetFlaggedOnlyWhenIsFlagged() {
+ UpdateMessagePatch testee = UpdateMessagePatch.builder().isFlagged(true).build();
+ List<Flags.Flag> updatedFlags = Arrays.asList(testee.applyToState(new Flags()).getSystemFlags());
assertThat(updatedFlags).containsExactly(Flags.Flag.FLAGGED);
}
@Test
+ public void applyStateShouldRemoveFlaggedWhenEmptyIsFlaggedOnFlaggedMessage() {
+ UpdateMessagePatch testee = UpdateMessagePatch.builder().isAnswered(true).build();
+ Flags isFlagged = new Flags(Flags.Flag.FLAGGED);
+ List<Flags.Flag> updatedFlags = Arrays.asList(testee.applyToState(isFlagged).getSystemFlags());
+ assertThat(updatedFlags).doesNotContain(Flags.Flag.FLAGGED);
+ }
+
+ @Test
public void applyStateShouldReturnUnreadFlagWhenUnreadSetOnSeenMessage() {
UpdateMessagePatch testee = UpdateMessagePatch.builder().isUnread(true).build();
Flags isSeen = new Flags(Flags.Flag.SEEN);
@@ -64,14 +74,6 @@ public class UpdateMessagePatchTest {
}
@Test
- public void applyStateShouldReturnFlaggedWhenEmptyPatchOnFlaggedMessage() {
- UpdateMessagePatch testee = UpdateMessagePatch.builder().build();
- Flags isFlagged = new Flags(Flags.Flag.FLAGGED);
- List<Flags.Flag> updatedFlags = Arrays.asList(testee.applyToState(isFlagged).getSystemFlags());
- assertThat(updatedFlags).containsExactly(Flags.Flag.FLAGGED);
- }
-
- @Test
public void applyStateShouldReturnSeenWhenPatchSetsSeenOnSeenMessage() {
UpdateMessagePatch testee = UpdateMessagePatch.builder().isUnread(false).build();
Flags isSeen = new Flags(Flags.Flag.SEEN);
@@ -80,7 +82,116 @@ public class UpdateMessagePatchTest {
}
@Test
- public void isIdentityShouldReturnTrueWhenNoFlags() {
+ public void applyStateShouldReturnNewFlagsWhenKeywords() {
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Answered", true,
+ "$Flagged", true);
+
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+ Flags isSeen = new Flags(Flags.Flag.SEEN);
+ assertThat(testee.applyToState(isSeen).getSystemFlags())
+ .containsExactly(Flags.Flag.ANSWERED, Flags.Flag.FLAGGED);
+ }
+
+ @Test
+ public void applyStateShouldReturnRemoveFlagsWhenKeywords() {
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(ImmutableMap.of())
+ .build();
+ Flags isSeen = new Flags(Flags.Flag.SEEN);
+ assertThat(testee.applyToState(isSeen).getSystemFlags()).isEmpty();
+ }
+
+ @Test
+ public void applyStateShouldThrowWhenKeywordsContainDeletedFlag() {
+ expectedException.expect(IllegalArgumentException.class);
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Deleted", true);
+
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+
+ Flags currentFlags = new Flags(Flags.Flag.SEEN);
+
+ testee.applyToState(currentFlags);
+ }
+
+ @Test
+ public void applyStateShouldThrowWhenKeywordsContainRecentFlag() {
+ expectedException.expect(IllegalArgumentException.class);
+
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Recent", true);
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+
+ Flags currentFlags = new Flags(Flags.Flag.SEEN);
+
+ testee.applyToState(currentFlags);
+ }
+
+ @Test
+ public void applyStateShouldReturnFlagsWithoutUserFlagWhenKeywordsContainForwarded() {
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Answered", Keyword.FLAG_VALUE,
+ FORWARDED, Keyword.FLAG_VALUE);
+
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+ Flags isSeen = new Flags(Flags.Flag.SEEN);
+ assertThat(testee.applyToState(isSeen).getSystemFlags())
+ .doesNotContain(Flags.Flag.USER);
+ }
+
+ @Test
+ public void applyStateShouldReturnFlagsWithUserFlagStringWhenKeywordsContainForwarded() {
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Answered", Keyword.FLAG_VALUE,
+ FORWARDED, Keyword.FLAG_VALUE);
+
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+ Flags isSeen = new Flags(Flags.Flag.SEEN);
+ assertThat(testee.applyToState(isSeen).getUserFlags())
+ .containsExactly(FORWARDED);
+ }
+
+ @Test
+ public void applyStateShouldReturnFlagsWithDeletedFlagWhenKeywordsDoNotContainDeletedButOriginFlagsHaveDeleted() {
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Answered", Keyword.FLAG_VALUE);
+
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+ Flags isSeen = new Flags(Flags.Flag.DELETED);
+ assertThat(testee.applyToState(isSeen).getSystemFlags())
+ .containsOnly(Flags.Flag.DELETED, Flags.Flag.ANSWERED);
+ }
+
+ @Test
+ public void applyStateShouldReturnFlagsWithRecentFlagWhenKeywordsDoNotContainRecentButOriginFlagsHaveRecent() {
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Answered", Keyword.FLAG_VALUE);
+
+ UpdateMessagePatch testee = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+ Flags flags = FlagsBuilder.builder()
+ .add(Flags.Flag.DELETED, Flags.Flag.RECENT)
+ .build();
+ assertThat(testee.applyToState(flags).getSystemFlags())
+ .containsOnly(Flags.Flag.DELETED, Flags.Flag.RECENT, Flags.Flag.ANSWERED);
+ }
+
+ @Test
+ public void isIdentityShouldReturnTrueWhenNoFlagsAndEmptyKeywords() {
UpdateMessagePatch messagePatch = UpdateMessagePatch.builder().build();
assertThat(messagePatch.isFlagsIdentity()).isTrue();
@@ -113,4 +224,37 @@ public class UpdateMessagePatchTest {
assertThat(messagePatch.isFlagsIdentity()).isFalse();
}
+ @Test
+ public void isIdentityShouldReturnFalseWhenKeywords() {
+ ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
+ "$Answered", Keyword.FLAG_VALUE,
+ "$Flagged", Keyword.FLAG_VALUE);
+
+ UpdateMessagePatch messagePatch = UpdateMessagePatch.builder()
+ .keywords(keywords)
+ .build();
+
+ assertThat(messagePatch.isFlagsIdentity()).isFalse();
+ }
+
+ @Test
+ public void isIdentityShouldReturnFalseWhenEmptyKeywords() {
+ UpdateMessagePatch messagePatch = UpdateMessagePatch.builder()
+ .keywords(ImmutableMap.of())
+ .build();
+
+ assertThat(messagePatch.isFlagsIdentity()).isFalse();
+ }
+
+ @Test
+ public void isIdentityShouldThrowWhenBothIsFlagAndKeywords() {
+ expectedException.expect(IllegalArgumentException.class);
+
+ UpdateMessagePatch messagePatch = UpdateMessagePatch.builder()
+ .keywords(ImmutableMap.of())
+ .isAnswered(false)
+ .build();
+
+ messagePatch.isFlagsIdentity();
+ }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org