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 ad...@apache.org on 2017/11/28 13:50:31 UTC
[4/5] james-project git commit: JAMES-2232 Flags in JMAP should be
handled by Keywords & is attributes
JAMES-2232 Flags in JMAP should be handled by Keywords & is attributes
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/35a6e923
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/35a6e923
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/35a6e923
Branch: refs/heads/master
Commit: 35a6e92304605fb95d2a9cbec607de22cef053d3
Parents: 5f8f0d5
Author: Antoine Duprat <ad...@linagora.com>
Authored: Thu Nov 23 15:12:25 2017 +0100
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Tue Nov 28 14:49:41 2017 +0100
----------------------------------------------------------------------
.../integration/SetMessagesMethodTest.java | 357 +++++++++++++++++++
.../cucumber/SetMessagesMethodStepdefs.java | 18 +
.../test/resources/cucumber/SetMessages.feature | 11 +
.../james/jmap/methods/MessageAppender.java | 22 +-
.../methods/SetMessagesCreationProcessor.java | 21 +-
.../methods/SetMessagesUpdateProcessor.java | 36 +-
.../james/jmap/model/CreationMessage.java | 23 +-
.../org/apache/james/jmap/model/Keywords.java | 70 ++--
.../org/apache/james/jmap/model/OldKeyword.java | 46 +++
.../james/jmap/model/UpdateMessagePatch.java | 25 +-
.../james/jmap/utils/KeywordsCombiner.java | 6 +-
.../james/jmap/json/ParsingWritingObjects.java | 2 +-
.../james/jmap/model/CreationMessageTest.java | 15 +
.../apache/james/jmap/model/KeywordsTest.java | 178 +--------
.../apache/james/jmap/model/OldKeywordTest.java | 59 ++-
.../jmap/model/UpdateMessagePatchTest.java | 35 --
16 files changed, 641 insertions(+), 283 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
index 00a28d1..2470b51 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
@@ -1429,6 +1429,47 @@ public abstract class SetMessagesMethodTest {
}
@Test
+ public void setMessagesShouldMarkAsDraftWhenIsDraftPassed() {
+ String messageCreationId = "creationId1337";
+ String fromAddress = USERNAME;
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"subject\"," +
+ " \"isDraft\": true," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created." + messageCreationId + ".id");
+
+ with()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isDraft", equalTo(true));
+ }
+
+ @Test
public void setMessagesShouldRejectCreateInDraftAndOutboxForASingleMessage() {
String messageCreationId = "creationId1337";
String fromAddress = USERNAME;
@@ -4852,4 +4893,320 @@ public abstract class SetMessagesMethodTest {
.body(SECOND_ARGUMENTS + ".list", hasSize(1))
.body(SECOND_ARGUMENTS + ".list[0].keywords.$Seen", equalTo(true));
}
+
+ @Test
+ public void setMessagesShouldCreateMessageWithFlagsWhenFlagsAttributesAreGiven() {
+ String messageCreationId = "creationId1337";
+ String fromAddress = USERNAME;
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"subject\"," +
+ " \"isUnread\": true," +
+ " \"isFlagged\": true," +
+ " \"isAnswered\": true," +
+ " \"isDraft\": true," +
+ " \"isForwarded\": true," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
+
+ with()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isUnread", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isFlagged", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isAnswered", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isDraft", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isForwarded", equalTo(true));
+ }
+
+ @Test
+ public void setMessagesShouldUpdateFlagsWhenSomeAreAlreadySet() {
+ String messageCreationId = "creationId1337";
+ String fromAddress = USERNAME;
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"subject\"," +
+ " \"isDraft\": true," +
+ " \"isForwarded\": true," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created."+ messageCreationId +".id");
+
+ String updateRequestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"update\": { \"" + messageId + "\" : {" +
+ " \"isUnread\": true," +
+ " \"isFlagged\": true," +
+ " \"isAnswered\": true," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body(updateRequestBody)
+ .when()
+ .post("/jmap");
+
+ with()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isUnread", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isFlagged", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isAnswered", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isDraft", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isForwarded", equalTo(true));
+ }
+
+ @Test
+ public void setMessagesShouldRemoveFlagsWhenAskedFor() {
+ String messageCreationId = "creationId1337";
+ String fromAddress = USERNAME;
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"subject\"," +
+ " \"isUnread\": true," +
+ " \"isFlagged\": true," +
+ " \"isAnswered\": true," +
+ " \"isDraft\": true," +
+ " \"isForwarded\": true," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created." + messageCreationId + ".id");
+
+ String updateRequestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"update\": { \"" + messageId + "\" : {" +
+ " \"isUnread\": false," +
+ " \"isFlagged\": false," +
+ " \"isAnswered\": false," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body(updateRequestBody)
+ .when()
+ .post("/jmap");
+
+ with()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isUnread", equalTo(false))
+ .body(ARGUMENTS + ".list[0].isFlagged", equalTo(false))
+ .body(ARGUMENTS + ".list[0].isAnswered", equalTo(false))
+ .body(ARGUMENTS + ".list[0].isDraft", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isForwarded", equalTo(true));
+ }
+
+ @Test
+ public void setMessagesShouldReturnErrorWhenTryingToChangeDraftFlagAmongOthers() {
+ String messageCreationId = "creationId1337";
+ String fromAddress = USERNAME;
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"subject\"," +
+ " \"isUnread\": true," +
+ " \"isFlagged\": true," +
+ " \"isAnswered\": true," +
+ " \"isDraft\": true," +
+ " \"isForwarded\": true," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created." + messageCreationId + ".id");
+
+ String updateRequestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"update\": { \"" + messageId + "\" : {" +
+ " \"isUnread\": false," +
+ " \"isFlagged\": false," +
+ " \"isAnswered\": false," +
+ " \"isDraft\": false," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body(updateRequestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void setMessagesShouldNotModifyTheMessageWhenTryingToChangeDraftFlagAmongOthers() {
+ String messageCreationId = "creationId1337";
+ String fromAddress = USERNAME;
+ String requestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"create\": { \"" + messageCreationId + "\" : {" +
+ " \"from\": { \"name\": \"Me\", \"email\": \"" + fromAddress + "\"}," +
+ " \"to\": [{ \"name\": \"BOB\", \"email\": \"someone@example.com\"}]," +
+ " \"subject\": \"subject\"," +
+ " \"isUnread\": true," +
+ " \"isFlagged\": true," +
+ " \"isAnswered\": true," +
+ " \"isDraft\": true," +
+ " \"isForwarded\": true," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ String messageId = given()
+ .header("Authorization", accessToken.serialize())
+ .body(requestBody)
+ .when()
+ .post("/jmap")
+ .then()
+ .extract()
+ .body()
+ .<String>path(ARGUMENTS + ".created." + messageCreationId + ".id");
+
+ String updateRequestBody = "[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"update\": { \"" + messageId + "\" : {" +
+ " \"isUnread\": false," +
+ " \"isFlagged\": false," +
+ " \"isAnswered\": false," +
+ " \"isDraft\": false," +
+ " \"mailboxIds\": [\"" + getDraftId(accessToken) + "\"]" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]";
+
+ given()
+ .header("Authorization", accessToken.serialize())
+ .body(updateRequestBody)
+ .when()
+ .post("/jmap");
+
+ with()
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+ .post("/jmap")
+ .then()
+ .log().ifValidationFails()
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1))
+ .body(ARGUMENTS + ".list[0].isUnread", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isFlagged", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isAnswered", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isDraft", equalTo(true))
+ .body(ARGUMENTS + ".list[0].isForwarded", equalTo(true));
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
index 8cdd65a..026ac90 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/SetMessagesMethodStepdefs.java
@@ -202,6 +202,24 @@ public class SetMessagesMethodStepdefs {
userStepdefs.execWithUser(username, () -> setFlags(keywords, message));
}
+ @When("^\"([^\"]*)\" marks the message \"([^\"]*)\" as flagged$")
+ public void flag(String username, String message) throws Throwable {
+ MessageId messageId = messageIdStepdefs.getMessageId(message);
+
+ httpClient.post("[" +
+ " [" +
+ " \"setMessages\","+
+ " {" +
+ " \"update\": { \"" + messageId.serialize() + "\" : {" +
+ " \"isFlagged\": true" +
+ " }}" +
+ " }," +
+ " \"#0\"" +
+ " ]" +
+ "]");
+ mainStepdefs.awaitMethod.run();
+ }
+
@When("^\"([^\"]*)\" destroys message \"([^\"]*)\"$")
public void destroyMessage(String username, String message) throws Throwable {
MessageId messageId = messageIdStepdefs.getMessageId(message);
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
index 46ede38..f3ac1bf 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/SetMessages.feature
@@ -80,6 +80,11 @@ Feature: SetMessages method on shared folders
# Flags update
+ Scenario: A user can update the flags on a message
+ Given "alice@domain.tld" sets flags "$Flagged,$Seen" on message "mAlice"
+ When "alice@domain.tld" sets flags "$Flagged,$Forwarded" on message "mAlice"
+ Then "alice@domain.tld" should see message "mAlice" with keywords $Flagged,$Forwarded
+
Scenario: A delegated user add keywords on a delegated message when having "write" right
Given "bob@domain.tld" shares his mailbox "shared" with "alice@domain.tld" with "lrw" rights
When "alice@domain.tld" sets flags "$Flagged" on message "mBob"
@@ -117,6 +122,12 @@ Feature: SetMessages method on shared folders
Then message "mDraft" is not updated
And "bob@domain.tld" should see message "mDraft" with keywords $Draft
+ Scenario: A user can add a flag on a draft
+ Given "bob@domain.tld" has a mailbox "Drafts"
+ And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
+ When "bob@domain.tld" marks the message "mDraft" as flagged
+ Then "bob@domain.tld" should see message "mDraft" with keywords $Draft,$Flagged
+
Scenario: A user can destroy a draft
Given "bob@domain.tld" has a mailbox "Drafts"
And "bob@domain.tld" tries to create a draft message "mDraft" in mailbox "Drafts"
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageAppender.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageAppender.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageAppender.java
index 4d09810..763ba27 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageAppender.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/MessageAppender.java
@@ -23,12 +23,15 @@ import java.util.Date;
import java.util.Optional;
import javax.inject.Inject;
+import javax.mail.Flags;
import javax.mail.util.SharedByteArrayInputStream;
import org.apache.james.jmap.methods.ValueWithId.CreationMessageEntry;
import org.apache.james.jmap.model.Attachment;
+import org.apache.james.jmap.model.CreationMessage;
import org.apache.james.jmap.model.Keywords;
import org.apache.james.jmap.model.MessageFactory;
+import org.apache.james.jmap.model.OldKeyword;
import org.apache.james.mailbox.AttachmentManager;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxSession;
@@ -71,16 +74,13 @@ public class MessageAppender {
SharedByteArrayInputStream content = new SharedByteArrayInputStream(messageContent);
Date internalDate = Date.from(createdEntry.getValue().getDate().toInstant());
- Keywords keywords = createdEntry.getValue()
- .getKeywords()
- .orElse(Keywords.DEFAULT_VALUE);
boolean notRecent = false;
- ComposedMessageId message = mailbox.appendMessage(content, internalDate, session, notRecent, keywords.asFlags());
+ ComposedMessageId message = mailbox.appendMessage(content, internalDate, session, notRecent, getFlags(createdEntry.getValue()));
return MessageFactory.MetaDataWithContent.builder()
.uid(message.getUid())
- .keywords(keywords)
+ .keywords(keywordsOrDefault(createdEntry.getValue()))
.internalDate(internalDate.toInstant())
.sharedContent(content)
.size(messageContent.length)
@@ -90,6 +90,18 @@ public class MessageAppender {
.build();
}
+ private Flags getFlags(CreationMessage message) {
+ return message.getOldKeyword()
+ .map(OldKeyword::asFlags)
+ .orElseGet(() -> keywordsOrDefault(message)
+ .asFlags());
+ }
+
+ private Keywords keywordsOrDefault(CreationMessage message) {
+ return message.getKeywords()
+ .orElse(Keywords.DEFAULT_VALUE);
+ }
+
public MessageFactory.MetaDataWithContent appendMessageInMailbox(CreationMessageEntry createdEntry,
MailboxId mailboxId,
MailboxSession session) throws MailboxException {
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/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 964ceeb..2f60b82 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
@@ -189,32 +189,37 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor {
private void sendMailViaOutbox(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) throws AttachmentsNotFoundException, MailboxException, MessagingException {
validateArguments(entry, session);
- assertNoDraftKeywords(entry);
+ assertNoDraftKeywords(entry.getValue());
MessageWithId created = handleOutboxMessages(entry, session);
responseBuilder.created(created.getCreationId(), created.getValue());
}
private void saveDraft(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) throws AttachmentsNotFoundException, MailboxException, MessagingException {
attachmentChecker.assertAttachmentsExist(entry, session);
- assertDraftKeywords(entry);
+ assertDraftKeywords(entry.getValue());
MessageWithId created = handleDraftMessages(entry, session);
responseBuilder.created(created.getCreationId(), created.getValue());
}
- private void assertDraftKeywords(CreationMessageEntry entry) {
- if (!isDraft(entry)) {
+ private void assertDraftKeywords(CreationMessage creationMessage) {
+ if (!isDraft(creationMessage)) {
throw new InvalidDraftKeywordsException("A draft message should be flagged as Draft");
}
}
- private void assertNoDraftKeywords(CreationMessageEntry entry) {
- if (isDraft(entry)) {
+ private void assertNoDraftKeywords(CreationMessage creationMessage) {
+ if (isDraft(creationMessage)) {
throw new InvalidDraftKeywordsException("A draft message can not be created out of draft mailbox");
}
}
- private Boolean isDraft(CreationMessageEntry entry) {
- return entry.getValue()
+ private Boolean isDraft(CreationMessage creationMessage) {
+ if (creationMessage.getOldKeyword().isPresent()) {
+ return creationMessage.getOldKeyword().get()
+ .isDraft()
+ .orElse(false);
+ }
+ return creationMessage
.getKeywords()
.map(keywords -> keywords.contains(Keyword.DRAFT))
.orElse(false);
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/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 e9de2f9..f7cbe62 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
@@ -40,6 +40,7 @@ import org.apache.james.core.MailAddress;
import org.apache.james.jmap.exceptions.DraftMessageMailboxUpdateException;
import org.apache.james.jmap.exceptions.InvalidOutboxMoveException;
import org.apache.james.jmap.model.MessageProperties;
+import org.apache.james.jmap.model.OldKeyword;
import org.apache.james.jmap.model.SetError;
import org.apache.james.jmap.model.SetMessagesRequest;
import org.apache.james.jmap.model.SetMessagesResponse;
@@ -49,6 +50,7 @@ import org.apache.james.jmap.utils.SystemMailboxesProvider;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.MessageIdManager;
import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.MessageManager.FlagsUpdateMode;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.exception.MailboxNotFoundException;
import org.apache.james.mailbox.model.FetchGroupImpl;
@@ -242,10 +244,23 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
}
private List<Flags> patchFlags(List<MessageResult> messagesToBeUpdated, UpdateMessagePatch updateMessagePatch) {
+ return updateMessagePatch.getOldKeyword()
+ .map(oldKeyword -> flagsFromOldKeyword(messagesToBeUpdated, oldKeyword))
+ .orElse(flagsFromKeywords(messagesToBeUpdated, updateMessagePatch));
+ }
+
+ private List<Flags> flagsFromOldKeyword(List<MessageResult> messagesToBeUpdated, OldKeyword oldKeyword) {
return messagesToBeUpdated.stream()
- .map(MessageResult::getFlags)
- .map(updateMessagePatch::applyToState)
- .collect(Guavate.toImmutableList());
+ .map(MessageResult::getFlags)
+ .map(flags -> oldKeyword.applyToState(flags))
+ .collect(Guavate.toImmutableList());
+ }
+
+ private ImmutableList<Flags> flagsFromKeywords(List<MessageResult> messagesToBeUpdated, UpdateMessagePatch updateMessagePatch) {
+ return messagesToBeUpdated.stream()
+ .map(MessageResult::getFlags)
+ .map(updateMessagePatch::applyToState)
+ .collect(Guavate.toImmutableList());
}
private List<MailboxId> mailboxIdFor(Role role, MailboxSession session) throws MailboxException {
@@ -285,8 +300,7 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
private Stream<MailboxException> updateFlags(MessageId messageId, UpdateMessagePatch updateMessagePatch, MailboxSession mailboxSession, MessageResult messageResult) {
try {
if (!updateMessagePatch.isFlagsIdentity()) {
- Flags newState = updateMessagePatch.applyToState(messageResult.getFlags());
- messageIdManager.setFlags(newState, MessageManager.FlagsUpdateMode.REPLACE, messageId, ImmutableList.of(messageResult.getMailboxId()), mailboxSession);
+ messageIdManager.setFlags(newState(messageResult, updateMessagePatch), FlagsUpdateMode.REPLACE, messageId, ImmutableList.of(messageResult.getMailboxId()), mailboxSession);
}
return Stream.of();
} catch (MailboxException e) {
@@ -294,6 +308,18 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor {
}
}
+ private Flags newState(MessageResult messageResult, UpdateMessagePatch updateMessagePatch) {
+ return updateMessagePatch.getOldKeyword()
+ .map(oldKeyword -> firstFlagsFromOldKeyword(ImmutableList.of(messageResult), oldKeyword))
+ .orElse(updateMessagePatch.applyToState(messageResult.getFlags()));
+ }
+
+ private Flags firstFlagsFromOldKeyword(List<MessageResult> messagesToBeUpdated, OldKeyword oldKeyword) {
+ return flagsFromOldKeyword(messagesToBeUpdated, oldKeyword).stream()
+ .findFirst()
+ .orElse(null);
+ }
+
private void setInMailboxes(MessageId messageId, UpdateMessagePatch updateMessagePatch, Stream<Flags> originalFlags, MailboxSession mailboxSession) throws MailboxException {
Optional<List<String>> serializedMailboxIds = updateMessagePatch.getMailboxIds();
if (serializedMailboxIds.isPresent()) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/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 097d172..1fca744 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
@@ -218,17 +218,22 @@ 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();
}
+ Optional<Keywords> maybeKeywords = creationKeywords();
+ Optional<OldKeyword> oldKeywords = getOldKeywords();
+ Preconditions.checkArgument(!(maybeKeywords.isPresent() && oldKeywords.isPresent()), "Does not support keyword and is* at the same time");
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);
+ attachments, attachedMessages, maybeKeywords, oldKeywords);
+ }
+
+ private Optional<Keywords> creationKeywords() {
+ return keywords.map(map -> Keywords.factory()
+ .throwOnImapNonExposedKeywords()
+ .fromMap(map));
}
private Optional<OldKeyword> getOldKeywords() {
@@ -254,11 +259,12 @@ public class CreationMessage {
private final ImmutableList<Attachment> attachments;
private final ImmutableMap<BlobId, SubMessage> attachedMessages;
private final Optional<Keywords> keywords;
+ private final Optional<OldKeyword> oldKeyword;
@VisibleForTesting
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, Optional<Keywords> keywords) {
+ ImmutableMap<BlobId, SubMessage> attachedMessages, Optional<Keywords> keywords, Optional<OldKeyword> oldKeyword) {
this.mailboxIds = mailboxIds;
this.inReplyToMessageId = inReplyToMessageId;
this.headers = headers;
@@ -274,6 +280,7 @@ public class CreationMessage {
this.attachments = attachments;
this.attachedMessages = attachedMessages;
this.keywords = keywords;
+ this.oldKeyword = oldKeyword;
}
public ImmutableList<String> getMailboxIds() {
@@ -340,6 +347,10 @@ public class CreationMessage {
return keywords;
}
+ public Optional<OldKeyword> getOldKeyword() {
+ return oldKeyword;
+ }
+
public List<ValidationResult> validate() {
ImmutableList.Builder<ValidationResult> errors = ImmutableList.builder();
assertValidFromProvided(errors);
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
index 286468f..5df79fa 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
@@ -43,7 +43,7 @@ import com.google.common.collect.ImmutableSet;
public class Keywords {
- public static final Keywords DEFAULT_VALUE = factory().fromSet(ImmutableSet.of());
+ public static final Keywords DEFAULT_VALUE = factory().fromSet(ImmutableSet.of(), Optional.empty());
private static final Logger LOGGER = LoggerFactory.getLogger(Keywords.class);
public interface KeywordsValidator {
@@ -78,24 +78,27 @@ public class Keywords {
return this;
}
- public Keywords fromSet(Set<Keyword> setKeywords) {
+ public Keywords fromSet(Set<Keyword> setKeywords, Optional<OldKeyword> oldKeyword) {
validator.orElse(keywords -> {})
.validate(setKeywords);
return new Keywords(setKeywords.stream()
- .filter(filter.orElse(keyword -> true))
- .collect(Guavate.toImmutableSet()));
+ .filter(filter.orElse(keyword -> true))
+ .collect(Guavate.toImmutableSet()),
+ oldKeyword);
}
public Keywords from(Keyword... keywords) {
return fromSet(Arrays.stream(keywords)
- .collect(Guavate.toImmutableSet()));
+ .collect(Guavate.toImmutableSet()),
+ Optional.empty());
}
public Keywords fromList(List<String> keywords) {
return fromSet(keywords.stream()
- .map(Keyword::new)
- .collect(Guavate.toImmutableSet()));
+ .map(Keyword::new)
+ .collect(Guavate.toImmutableSet()),
+ Optional.empty());
}
@VisibleForTesting
@@ -108,37 +111,17 @@ public class Keywords {
.map(Keyword::new)
.collect(Guavate.toImmutableSet());
- return fromSet(setKeywords);
- }
-
- @VisibleForTesting
- Keywords fromOldKeyword(OldKeyword oldKeyword) {
- ImmutableSet.Builder<Keyword> builder = ImmutableSet.builder();
- if (oldKeyword.isAnswered().orElse(false)) {
- builder.add(Keyword.ANSWERED);
- }
- if (oldKeyword.isDraft().orElse(false)) {
- builder.add(Keyword.DRAFT);
- }
- if (oldKeyword.isFlagged().orElse(false)) {
- builder.add(Keyword.FLAGGED);
- }
- if (oldKeyword.isUnread().isPresent() && oldKeyword.isUnread().get() == false) {
- builder.add(Keyword.SEEN);
- }
- if (oldKeyword.isForwarded().orElse(false)) {
- builder.add(Keyword.FORWARDED);
- }
- return fromSet(builder.build());
+ return fromSet(setKeywords, Optional.empty());
}
public Keywords fromFlags(Flags flags) {
return fromSet(Stream.concat(
- Stream.of(flags.getUserFlags())
- .flatMap(this::asKeyword),
- Stream.of(flags.getSystemFlags())
- .map(Keyword::fromFlag))
- .collect(Guavate.toImmutableSet()));
+ Stream.of(flags.getUserFlags())
+ .flatMap(this::asKeyword),
+ Stream.of(flags.getSystemFlags())
+ .map(Keyword::fromFlag))
+ .collect(Guavate.toImmutableSet()),
+ Optional.empty());
}
private Stream<Keyword> asKeyword(String flagName) {
@@ -149,15 +132,6 @@ public class Keywords {
return Stream.of();
}
}
-
- public Optional<Keywords> fromMapOrOldKeyword(Optional<Map<String, Boolean>> mapKeyword, Optional<OldKeyword> oldKeyword) {
- Preconditions.checkArgument(!(mapKeyword.isPresent() && oldKeyword.isPresent()), "Does not support keyword and is* at the same time");
-
- Keywords keywords = mapKeyword.map(this::fromMap)
- .orElse(oldKeyword.map(this::fromOldKeyword)
- .orElse(null));
- return Optional.ofNullable(keywords);
- }
}
public static KeywordsFactory factory() {
@@ -165,9 +139,11 @@ public class Keywords {
}
private final ImmutableSet<Keyword> keywords;
+ private final Optional<OldKeyword> oldKeyword;
- private Keywords(ImmutableSet<Keyword> keywords) {
+ private Keywords(ImmutableSet<Keyword> keywords, Optional<OldKeyword> oldKeyword) {
this.keywords = keywords;
+ this.oldKeyword = oldKeyword;
}
public Flags asFlags() {
@@ -205,20 +181,22 @@ public class Keywords {
public final boolean equals(Object other) {
if (other instanceof Keywords) {
Keywords otherKeyword = (Keywords) other;
- return Objects.equal(keywords, otherKeyword.keywords);
+ return Objects.equal(keywords, otherKeyword.keywords)
+ && Objects.equal(oldKeyword, otherKeyword.oldKeyword);
}
return false;
}
@Override
public final int hashCode() {
- return Objects.hashCode(keywords);
+ return Objects.hashCode(keywords, oldKeyword);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("keywords", keywords)
+ .add("oldKeyword", oldKeyword)
.toString();
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/OldKeyword.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/OldKeyword.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/OldKeyword.java
index 207b275..7620873 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/OldKeyword.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/OldKeyword.java
@@ -21,6 +21,8 @@ package org.apache.james.jmap.model;
import java.util.Optional;
+import javax.mail.Flags;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
@@ -70,6 +72,50 @@ public class OldKeyword {
return isForwarded;
}
+ 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);
+ }
+ if (isDraft().orElse(currentFlags.contains(Flags.Flag.DRAFT))) {
+ newStateFlags.add(Flags.Flag.DRAFT);
+ }
+ if (isForwarded().orElse(currentFlags.contains(new Flags("$Forwarded")))) {
+ newStateFlags.add(new Flags("$Forwarded"));
+ }
+ boolean shouldMessageBeMarkSeen = isUnread().map(b -> !b).orElse(currentFlags.contains(Flags.Flag.SEEN));
+ if (shouldMessageBeMarkSeen) {
+ newStateFlags.add(Flags.Flag.SEEN);
+ }
+ return newStateFlags;
+ }
+
+ public Flags asFlags() {
+ Flags newStateFlags = new Flags();
+
+ if (isFlagged().orElse(false)) {
+ newStateFlags.add(Flags.Flag.FLAGGED);
+ }
+ if (isAnswered().orElse(false)) {
+ newStateFlags.add(Flags.Flag.ANSWERED);
+ }
+ if (isDraft().orElse(false)) {
+ newStateFlags.add(Flags.Flag.DRAFT);
+ }
+ if (isForwarded().orElse(false)) {
+ newStateFlags.add(new Flags("$Forwarded"));
+ }
+ boolean shouldMessageBeMarkSeen = isUnread().map(b -> !b).orElse(false);
+ if (shouldMessageBeMarkSeen) {
+ newStateFlags.add(Flags.Flag.SEEN);
+ }
+ return newStateFlags;
+ }
+
@Override
public final boolean equals(Object other) {
if (other instanceof OldKeyword) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/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 e0b73e2..e735778 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
@@ -31,6 +31,7 @@ import org.apache.james.jmap.methods.ValidationResult;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -96,11 +97,17 @@ public class UpdateMessagePatch {
.build()));
}
- Optional<Keywords> updateKeywords = Keywords.factory()
- .throwOnImapNonExposedKeywords()
- .fromMapOrOldKeyword(keywords, getOldKeywords());
+ Optional<Keywords> mayBeKeywords = creationKeywords();
+ Optional<OldKeyword> oldKeywords = getOldKeywords();
+ Preconditions.checkArgument(!(mayBeKeywords.isPresent() && oldKeywords.isPresent()), "Does not support keyword and is* at the same time");
- return new UpdateMessagePatch(mailboxIds, updateKeywords, ImmutableList.copyOf(validationResult));
+ return new UpdateMessagePatch(mailboxIds, mayBeKeywords, oldKeywords, ImmutableList.copyOf(validationResult));
+ }
+
+ private Optional<Keywords> creationKeywords() {
+ return keywords.map(map -> Keywords.factory()
+ .throwOnImapNonExposedKeywords()
+ .fromMap(map));
}
private Optional<OldKeyword> getOldKeywords() {
@@ -115,16 +122,18 @@ public class UpdateMessagePatch {
private final Optional<List<String>> mailboxIds;
private final Optional<Keywords> keywords;
-
+ private final Optional<OldKeyword> oldKeywords;
private final ImmutableList<ValidationResult> validationErrors;
@VisibleForTesting
UpdateMessagePatch(Optional<List<String>> mailboxIds,
Optional<Keywords> keywords,
+ Optional<OldKeyword> oldKeywords,
ImmutableList<ValidationResult> validationResults) {
this.mailboxIds = mailboxIds;
this.keywords = keywords;
+ this.oldKeywords = oldKeywords;
this.validationErrors = validationResults;
}
@@ -136,8 +145,12 @@ public class UpdateMessagePatch {
return keywords;
}
+ public Optional<OldKeyword> getOldKeyword() {
+ return oldKeywords;
+ }
+
public boolean isFlagsIdentity() {
- return !keywords.isPresent();
+ return !oldKeywords.isPresent() && !keywords.isPresent();
}
public ImmutableList<ValidationResult> getValidationErrors() {
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/KeywordsCombiner.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/KeywordsCombiner.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/KeywordsCombiner.java
index 258f5df..2dba575 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/KeywordsCombiner.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/KeywordsCombiner.java
@@ -20,6 +20,7 @@
package org.apache.james.jmap.utils;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.function.BinaryOperator;
@@ -45,8 +46,9 @@ public class KeywordsCombiner implements BinaryOperator<Keywords> {
public Keywords apply(Keywords keywords, Keywords keywords2) {
return keywordsFactory
.fromSet(Sets.union(
- union(keywords.getKeywords(), keywords2.getKeywords(), KEYWORD_NOT_TO_UNION),
- intersect(keywords.getKeywords(), keywords2.getKeywords(), KEYWORD_TO_INTERSECT)));
+ union(keywords.getKeywords(), keywords2.getKeywords(), KEYWORD_NOT_TO_UNION),
+ intersect(keywords.getKeywords(), keywords2.getKeywords(), KEYWORD_TO_INTERSECT)),
+ Optional.empty());
}
public Set<Keyword> union(Set<Keyword> set1, Set<Keyword> set2, List<Keyword> exceptKeywords) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
index b81731a..427a6d9 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/json/ParsingWritingObjects.java
@@ -77,7 +77,7 @@ public interface ParsingWritingObjects {
.threadId(Common.THREAD_ID)
.mailboxIds(Common.MAILBOX_IDS)
.inReplyToMessageId(Common.IN_REPLY_TO_MESSAGE_ID)
- .keywords(Keywords.factory().fromSet(Common.KEYWORDS))
+ .keywords(Keywords.factory().fromSet(Common.KEYWORDS, Optional.empty()))
.headers(Common.HEADERS)
.from(Common.FROM)
.to(Common.TO)
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
index e7762aa..d31e0a1 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/CreationMessageTest.java
@@ -20,6 +20,9 @@
package org.apache.james.jmap.model;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.Optional;
import org.apache.james.jmap.methods.ValidationResult;
import org.apache.james.jmap.model.CreationMessage.DraftEmailer;
@@ -42,6 +45,18 @@ public class CreationMessageTest {
}
@Test
+ public void buildShouldThrowWhenBothMapAndOldKeyword() {
+ assertThatThrownBy(() -> CreationMessage.builder()
+ .mailboxIds(ImmutableList.of("ba9-0f-dead-beef"))
+ .headers(ImmutableMap.of())
+ .keywords(ImmutableMap.of("$Draft", true))
+ .isAnswered(Optional.of(true))
+ .build())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Does not support keyword and is* at the same time");
+ }
+
+ @Test
public void validateShouldReturnErrorWhenFromIsMissing() {
testedBuilder = testedBuilder
.subject("anything");
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
index 5fa1d56..4c3ca03 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
@@ -77,172 +77,16 @@ public class KeywordsTest {
@Test
public void fromSetShouldReturnKeywordsFromSetOfKeywords() throws Exception {
Keywords keywords = Keywords.factory()
- .fromSet(ImmutableSet.of(Keyword.ANSWERED));
+ .fromSet(ImmutableSet.of(Keyword.ANSWERED), Optional.empty());
assertThat(keywords.getKeywords())
.containsOnly(Keyword.ANSWERED);
}
@Test
- public void fromOldKeywordsShouldReturnKeywordsFromIsAnswered() throws Exception {
- Optional<Boolean> isAnswered = Optional.of(true);
- Optional<Boolean> isUnread = Optional.empty();
- Optional<Boolean> isFlagged = Optional.empty();
- Optional<Boolean> isDraft = Optional.empty();
- Optional<Boolean> isForwarded = Optional.empty();
- Keywords keywords = Keywords.factory()
- .fromOldKeyword(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded));
-
- assertThat(keywords.getKeywords())
- .containsOnly(Keyword.ANSWERED);
- }
-
- @Test
- public void fromOldKeywordsShouldReturnKeywordsFromIsForwarded() throws Exception {
- Optional<Boolean> isAnswered = Optional.empty();
- Optional<Boolean> isUnread = Optional.empty();
- Optional<Boolean> isFlagged = Optional.empty();
- Optional<Boolean> isDraft = Optional.empty();
- Optional<Boolean> isForwarded = Optional.of(true);
- Keywords keywords = Keywords.factory()
- .fromOldKeyword(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded));
-
- assertThat(keywords.getKeywords())
- .containsOnly(Keyword.FORWARDED);
- }
-
- @Test
- public void fromOldKeywordsShouldReturnKeywordsFromIsDraft() throws Exception {
- Optional<Boolean> isAnswered = Optional.empty();
- Optional<Boolean> isUnread = Optional.empty();
- Optional<Boolean> isFlagged = Optional.empty();
- Optional<Boolean> isDraft = Optional.of(true);
- Optional<Boolean> isForwarded = Optional.empty();
- Keywords keywords = Keywords.factory()
- .fromOldKeyword(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded));
-
- assertThat(keywords.getKeywords())
- .containsOnly(Keyword.DRAFT);
- }
-
- @Test
- public void fromOldKeywordsShouldReturnKeywordsFromIsFlagged() throws Exception {
- Optional<Boolean> isAnswered = Optional.empty();
- Optional<Boolean> isUnread = Optional.empty();
- Optional<Boolean> isFlagged = Optional.of(true);
- Optional<Boolean> isDraft = Optional.empty();
- Optional<Boolean> isForwarded = Optional.empty();
- Keywords keywords = Keywords.factory()
- .fromOldKeyword(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded));
-
- assertThat(keywords.getKeywords())
- .containsOnly(Keyword.FLAGGED);
- }
-
- @Test
- public void fromOldKeywordsShouldReturnKeywordsFromIsUnread() throws Exception {
- Optional<Boolean> isAnswered = Optional.empty();
- Optional<Boolean> isUnread = Optional.of(false);
- Optional<Boolean> isFlagged = Optional.empty();
- Optional<Boolean> isDraft = Optional.empty();
- Optional<Boolean> isForwarded = Optional.empty();
- Keywords keywords = Keywords.factory()
- .fromOldKeyword(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded));
-
- assertThat(keywords.getKeywords())
- .containsOnly(Keyword.SEEN);
- }
-
- @Test
- public void fromOldKeywordsShouldReturnKeywordsFromIsFlag() throws Exception {
- Optional<Boolean> isAnswered = Optional.of(true);
- Optional<Boolean> isUnread = Optional.of(true);
- Optional<Boolean> isFlagged = Optional.of(true);
- Optional<Boolean> isDraft = Optional.of(true);
- Optional<Boolean> isForwarded = Optional.empty();
- Keywords keywords = Keywords.factory()
- .fromOldKeyword(new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded));
-
- assertThat(keywords.getKeywords())
- .containsOnly(Keyword.ANSWERED, Keyword.DRAFT, Keyword.FLAGGED);
- }
-
- @Test
- public void fromMapOrOldKeywordShouldReturnEmptyWhenBothAreEmpty() throws Exception {
- assertThat(Keywords.factory()
- .fromMapOrOldKeyword(Optional.empty(), Optional.empty()))
- .isEmpty();
- }
-
- @Test
- public void fromMapOrOldKeywordShouldReturnKeywordsWhenMap() throws Exception {
- assertThat(Keywords.factory()
- .fromMapOrOldKeyword(Optional.of(ImmutableMap.of()), Optional.empty()))
- .isPresent();
- }
-
- @Test
- public void fromMapOrOldKeywordShouldReturnKeywordsWhenOldKeyword() throws Exception {
- Optional<Boolean> isAnswered = Optional.of(true);
- Optional<Boolean> isUnread = Optional.of(true);
- Optional<Boolean> isFlagged = Optional.of(true);
- Optional<Boolean> isDraft = Optional.of(true);
- Optional<Boolean> isForwarded = Optional.of(true);
-
- OldKeyword oldKeyword = new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded);
-
- assertThat(Keywords.factory()
- .fromMapOrOldKeyword(Optional.empty(), Optional.of(oldKeyword)))
- .isPresent();
- }
-
- @Test
- public void fromMapOrOldKeywordShouldThrownWhenBothMapAndOldKeyword() throws Exception {
- expectedException.expect(IllegalArgumentException.class);
- Optional<Boolean> isAnswered = Optional.of(true);
- Optional<Boolean> isUnread = Optional.of(true);
- Optional<Boolean> isFlagged = Optional.of(true);
- Optional<Boolean> isDraft = Optional.of(true);
- Optional<Boolean> isForwarded = Optional.of(true);
-
- OldKeyword oldKeyword = new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded);
-
- Keywords.factory()
- .fromMapOrOldKeyword(Optional.of(ImmutableMap.of()), Optional.of(oldKeyword));
- }
-
- @Test
- public void fromMapOrOldKeywordShouldReturnKeywordsFromMap() throws Exception {
- ImmutableMap<String, Boolean> mapKeywords = ImmutableMap.of(ANY_KEYWORD, Keyword.FLAG_VALUE);
-
- assertThat(Keywords.factory()
- .fromMapOrOldKeyword(Optional.of(mapKeywords), Optional.empty())
- .get()
- .getKeywords())
- .containsOnly(new Keyword(ANY_KEYWORD));
- }
-
- @Test
- public void fromMapOrOldKeywordShouldReturnKeywordsFromOldKeyword() throws Exception {
- Optional<Boolean> isAnswered = Optional.of(true);
- Optional<Boolean> isUnread = Optional.of(true);
- Optional<Boolean> isFlagged = Optional.of(true);
- Optional<Boolean> isDraft = Optional.of(true);
- Optional<Boolean> isForwarded = Optional.of(true);
-
- OldKeyword oldKeyword = new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded);
-
- Keywords keywords = Keywords.factory()
- .fromMapOrOldKeyword(Optional.empty(), Optional.of(oldKeyword))
- .get();
- assertThat(keywords.getKeywords())
- .containsOnly(Keyword.ANSWERED, Keyword.DRAFT, Keyword.FLAGGED, Keyword.FORWARDED);
- }
-
- @Test
public void asFlagsShouldBuildFlagsFromKeywords() throws Exception {
assertThat(Keywords.factory()
- .fromSet(ImmutableSet.of(Keyword.ANSWERED))
+ .fromSet(ImmutableSet.of(Keyword.ANSWERED), Optional.empty())
.asFlags())
.isEqualTo(new Flags(Flags.Flag.ANSWERED));
}
@@ -258,7 +102,7 @@ public class KeywordsTest {
.build();
assertThat(Keywords.factory()
- .fromSet(ImmutableSet.of(Keyword.ANSWERED))
+ .fromSet(ImmutableSet.of(Keyword.ANSWERED), Optional.empty())
.asFlagsWithRecentAndDeletedFrom(originFlags))
.isEqualTo(expectedFlags);
}
@@ -274,7 +118,7 @@ public class KeywordsTest {
.build();
assertThat(Keywords.factory()
- .fromSet(ImmutableSet.of(Keyword.ANSWERED))
+ .fromSet(ImmutableSet.of(Keyword.ANSWERED), Optional.empty())
.asFlagsWithRecentAndDeletedFrom(originFlags))
.isEqualTo(expectedFlags);
}
@@ -282,7 +126,7 @@ public class KeywordsTest {
@Test
public void asMapShouldReturnEmptyWhenEmptyMapOfStringAndBoolean() throws Exception {
assertThat(Keywords.factory()
- .fromSet(ImmutableSet.of())
+ .fromSet(ImmutableSet.of(), Optional.empty())
.asMap())
.isEmpty();;
}
@@ -291,7 +135,7 @@ public class KeywordsTest {
public void asMapShouldReturnMapOfStringAndBoolean() throws Exception {
Map<String, Boolean> expectedMap = ImmutableMap.of("$Answered", Keyword.FLAG_VALUE);
assertThat(Keywords.factory()
- .fromSet(ImmutableSet.of(Keyword.ANSWERED))
+ .fromSet(ImmutableSet.of(Keyword.ANSWERED), Optional.empty())
.asMap())
.isEqualTo(expectedMap);
}
@@ -302,14 +146,14 @@ public class KeywordsTest {
Keywords.factory()
.throwOnImapNonExposedKeywords()
- .fromSet(ImmutableSet.of(Keyword.DRAFT, Keyword.DELETED));
+ .fromSet(ImmutableSet.of(Keyword.DRAFT, Keyword.DELETED), Optional.empty());
}
@Test
public void throwWhenUnsupportedKeywordShouldNotThrowWhenHaveDraft() throws Exception {
Keywords keywords = Keywords.factory()
.throwOnImapNonExposedKeywords()
- .fromSet(ImmutableSet.of(Keyword.ANSWERED, Keyword.DRAFT));
+ .fromSet(ImmutableSet.of(Keyword.ANSWERED, Keyword.DRAFT), Optional.empty());
assertThat(keywords.getKeywords())
.containsOnly(Keyword.ANSWERED, Keyword.DRAFT);
@@ -319,7 +163,7 @@ public class KeywordsTest {
public void filterUnsupportedShouldFilter() throws Exception {
Keywords keywords = Keywords.factory()
.filterImapNonExposedKeywords()
- .fromSet(ImmutableSet.of(Keyword.ANSWERED, Keyword.DELETED, Keyword.RECENT, Keyword.DRAFT));
+ .fromSet(ImmutableSet.of(Keyword.ANSWERED, Keyword.DELETED, Keyword.RECENT, Keyword.DRAFT), Optional.empty());
assertThat(keywords.getKeywords())
.containsOnly(Keyword.ANSWERED, Keyword.DRAFT);
@@ -328,7 +172,7 @@ public class KeywordsTest {
@Test
public void containsShouldReturnTrueWhenKeywordsContainKeyword() {
Keywords keywords = Keywords.factory()
- .fromSet(ImmutableSet.of(Keyword.SEEN));
+ .fromSet(ImmutableSet.of(Keyword.SEEN), Optional.empty());
assertThat(keywords.contains(Keyword.SEEN)).isTrue();
}
@@ -336,7 +180,7 @@ public class KeywordsTest {
@Test
public void containsShouldReturnFalseWhenKeywordsDoNotContainKeyword() {
Keywords keywords = Keywords.factory()
- .fromSet(ImmutableSet.of());
+ .fromSet(ImmutableSet.of(), Optional.empty());
assertThat(keywords.contains(Keyword.SEEN)).isFalse();
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/OldKeywordTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/OldKeywordTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/OldKeywordTest.java
index 024271a..46db6b8 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/OldKeywordTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/OldKeywordTest.java
@@ -7,7 +7,7 @@
* "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 *
+ * 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 *
@@ -19,13 +19,68 @@
package org.apache.james.jmap.model;
-import nl.jqno.equalsverifier.EqualsVerifier;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Optional;
+
+import javax.mail.Flags;
+import javax.mail.Flags.Flag;
+
import org.junit.Test;
+import nl.jqno.equalsverifier.EqualsVerifier;
+
public class OldKeywordTest {
@Test
public void shouldRespectBeanContract() {
EqualsVerifier.forClass(OldKeyword.class).verify();
}
+ @Test
+ public void applyStateShouldSetFlaggedOnlyWhenIsFlagged() {
+ Optional<Boolean> isUnread = Optional.empty();
+ Optional<Boolean> isFlagged = Optional.of(true);
+ Optional<Boolean> isAnswered = Optional.empty();
+ Optional<Boolean> isDraft = Optional.empty();
+ Optional<Boolean> isForwarded = Optional.empty();
+ OldKeyword testee = new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded);
+
+ assertThat(testee.applyToState(new Flags())).isEqualTo(new Flags(Flag.FLAGGED));
+ }
+
+ @Test
+ public void applyStateShouldRemoveFlaggedWhenEmptyIsFlaggedOnFlaggedMessage() {
+ Optional<Boolean> isUnread = Optional.empty();
+ Optional<Boolean> isFlagged = Optional.of(false);
+ Optional<Boolean> isAnswered = Optional.empty();
+ Optional<Boolean> isDraft = Optional.empty();
+ Optional<Boolean> isForwarded = Optional.empty();
+ OldKeyword testee = new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded);
+
+ assertThat(testee.applyToState(new Flags(Flag.FLAGGED))).isEqualTo(new Flags());
+ }
+
+ @Test
+ public void applyStateShouldReturnUnreadFlagWhenUnreadSetOnSeenMessage() {
+ Optional<Boolean> isUnread = Optional.of(true);
+ Optional<Boolean> isFlagged = Optional.empty();
+ Optional<Boolean> isAnswered = Optional.empty();
+ Optional<Boolean> isDraft = Optional.empty();
+ Optional<Boolean> isForwarded = Optional.empty();
+ OldKeyword testee = new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded);
+
+ assertThat(testee.applyToState(new Flags(Flag.SEEN))).isEqualTo(new Flags());
+ }
+
+ @Test
+ public void applyStateShouldReturnSeenWhenPatchSetsSeenOnSeenMessage() {
+ Optional<Boolean> isUnread = Optional.of(false);
+ Optional<Boolean> isFlagged = Optional.empty();
+ Optional<Boolean> isAnswered = Optional.empty();
+ Optional<Boolean> isDraft = Optional.empty();
+ Optional<Boolean> isForwarded = Optional.empty();
+ OldKeyword testee = new OldKeyword(isUnread, isFlagged, isAnswered, isDraft, isForwarded);
+
+ assertThat(testee.applyToState(new Flags(Flag.SEEN))).isEqualTo(new Flags(Flag.SEEN));
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/35a6e923/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 c556ce6..5b8c4a1 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
@@ -21,9 +21,6 @@ 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;
@@ -50,38 +47,6 @@ public class UpdateMessagePatchTest {
}
@Test
- 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);
- List<Flags.Flag> updatedFlags = Arrays.asList(testee.applyToState(isSeen).getSystemFlags());
- assertThat(updatedFlags).doesNotContain(Flags.Flag.SEEN);
- }
-
- @Test
- public void applyStateShouldReturnSeenWhenPatchSetsSeenOnSeenMessage() {
- UpdateMessagePatch testee = UpdateMessagePatch.builder().isUnread(false).build();
- Flags isSeen = new Flags(Flags.Flag.SEEN);
- List<Flags.Flag> updatedFlags = Arrays.asList(testee.applyToState(isSeen).getSystemFlags());
- assertThat(updatedFlags).containsExactly(Flags.Flag.SEEN);
- }
-
- @Test
public void applyStateShouldReturnNewFlagsWhenKeywords() {
ImmutableMap<String, Boolean> keywords = ImmutableMap.of(
"$Answered", true,
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org