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 2016/02/08 15:01:10 UTC
[3/3] james-project git commit: JAMES-1675 Implement SetMessages:
destroy
JAMES-1675 Implement SetMessages: destroy
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/6665a49e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/6665a49e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/6665a49e
Branch: refs/heads/master
Commit: 6665a49e61bb241839da39738d6b798bdd8a572c
Parents: 7fca1ee
Author: Antoine Duprat <an...@gmail.com>
Authored: Wed Jan 20 16:53:16 2016 +0100
Committer: Antoine Duprat <an...@gmail.com>
Committed: Mon Feb 8 15:00:00 2016 +0100
----------------------------------------------------------------------
.../org/apache/james/jmap/MethodsModule.java | 2 +
.../protocols/jmap-integration-testing/pom.xml | 6 +
.../jmap/methods/SetMessagesMethodTest.java | 287 +++++++++++++++++++
.../CassandraSetMessagesMethodTest.java | 35 +++
.../exceptions/MessageNotFoundException.java | 23 ++
.../james/jmap/methods/SetMessagesMethod.java | 145 ++++++++++
.../org/apache/james/jmap/model/MessageId.java | 3 +-
.../org/apache/james/jmap/model/SetError.java | 80 ++++++
.../james/jmap/model/SetMessagesRequest.java | 126 ++++++++
.../james/jmap/model/SetMessagesResponse.java | 188 ++++++++++++
.../apache/james/jmap/model/SetErrorTest.java | 59 ++++
.../jmap/model/SetMessagesRequestTest.java | 96 +++++++
.../jmap/model/SetMessagesResponseTest.java | 86 ++++++
13 files changed, 1135 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
----------------------------------------------------------------------
diff --git a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
index c36619d..71e2dcd 100644
--- a/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
+++ b/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/MethodsModule.java
@@ -28,6 +28,7 @@ import org.apache.james.jmap.methods.JmapRequestParserImpl;
import org.apache.james.jmap.methods.JmapResponseWriter;
import org.apache.james.jmap.methods.JmapResponseWriterImpl;
import org.apache.james.jmap.methods.Method;
+import org.apache.james.jmap.methods.SetMessagesMethod;
import org.apache.james.mailbox.cassandra.CassandraId;
import com.google.inject.AbstractModule;
@@ -50,6 +51,7 @@ public class MethodsModule extends AbstractModule {
methods.addBinding().to(new TypeLiteral<GetMailboxesMethod<CassandraId>>(){});
methods.addBinding().to(new TypeLiteral<GetMessageListMethod<CassandraId>>(){});
methods.addBinding().to(new TypeLiteral<GetMessagesMethod<CassandraId>>(){});
+ methods.addBinding().to(new TypeLiteral<SetMessagesMethod<CassandraId>>(){});
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap-integration-testing/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/pom.xml b/server/protocols/jmap-integration-testing/pom.xml
index 655c7e9..b3ada4c 100644
--- a/server/protocols/jmap-integration-testing/pom.xml
+++ b/server/protocols/jmap-integration-testing/pom.xml
@@ -201,6 +201,12 @@
<version>${cassandra-unit.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>java-hamcrest</artifactId>
+ <version>2.0.0.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
new file mode 100644
index 0000000..bbe2e57
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/SetMessagesMethodTest.java
@@ -0,0 +1,287 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.methods;
+
+import static com.jayway.restassured.RestAssured.given;
+import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
+import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.collection.IsMapWithSize.aMapWithSize;
+import static org.hamcrest.collection.IsMapWithSize.anEmptyMap;
+
+import java.io.ByteArrayInputStream;
+import java.util.Date;
+
+import javax.mail.Flags;
+
+import org.apache.james.backends.cassandra.EmbeddedCassandra;
+import org.apache.james.jmap.JmapAuthentication;
+import org.apache.james.jmap.JmapServer;
+import org.apache.james.jmap.api.access.AccessToken;
+import org.apache.james.mailbox.elasticsearch.EmbeddedElasticSearch;
+import org.apache.james.mailbox.model.MailboxConstants;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TemporaryFolder;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableMap;
+import com.jayway.restassured.RestAssured;
+import com.jayway.restassured.http.ContentType;
+
+public abstract class SetMessagesMethodTest {
+
+ private static final String NAME = "[0][0]";
+ private static final String ARGUMENTS = "[0][1]";
+
+ private TemporaryFolder temporaryFolder = new TemporaryFolder();
+ private EmbeddedElasticSearch embeddedElasticSearch = new EmbeddedElasticSearch(temporaryFolder);
+ private EmbeddedCassandra cassandra = EmbeddedCassandra.createStartServer();
+ private JmapServer jmapServer = jmapServer(temporaryFolder, embeddedElasticSearch, cassandra);
+
+ protected abstract JmapServer jmapServer(TemporaryFolder temporaryFolder, EmbeddedElasticSearch embeddedElasticSearch, EmbeddedCassandra cassandra);
+
+ @Rule
+ public RuleChain chain = RuleChain
+ .outerRule(temporaryFolder)
+ .around(embeddedElasticSearch)
+ .around(jmapServer);
+
+ private AccessToken accessToken;
+ private String username;
+
+ @Before
+ public void setup() throws Exception {
+ RestAssured.port = jmapServer.getPort();
+ RestAssured.config = newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8));
+
+ String domain = "domain.tld";
+ username = "username@" + domain;
+ String password = "password";
+ jmapServer.serverProbe().addDomain(domain);
+ jmapServer.serverProbe().addUser(username, password);
+ jmapServer.serverProbe().createMailbox("#private", "username", "inbox");
+ accessToken = JmapAuthentication.authenticateJamesUser(username, password);
+ }
+
+ @Test
+ public void setMessagesShouldReturnErrorNotSupportedWhenRequestContainsNonNullAccountId() throws Exception {
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"accountId\": \"1\"}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("error"))
+ .body(ARGUMENTS + ".type", equalTo("Not yet implemented"));
+ }
+
+ @Test
+ public void setMessagesShouldReturnErrorNotSupportedWhenRequestContainsNonNullIfInState() throws Exception {
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"ifInState\": \"1\"}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("error"))
+ .body(ARGUMENTS + ".type", equalTo("Not yet implemented"));
+ }
+
+ @Test
+ public void setMessagesShouldReturnNotDestroyedWhenUnknownMailbox() throws Exception {
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"destroy\": [\"" + username + "|unknown|1\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".destroyed", empty())
+ .body(ARGUMENTS + ".notDestroyed", hasEntry(username + "|unknown|1",
+ ImmutableMap.of("type", "anErrorOccurred",
+ "description", "An error occurred while deleting message " + username + "|unknown|1")));
+ }
+
+ @Test
+ public void setMessagesShouldReturnNotDestroyedWhenNoMatchingMessage() throws Exception {
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"destroy\": [\"" + username + "|mailbox|12345\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".destroyed", empty())
+ .body(ARGUMENTS + ".notDestroyed", hasEntry(username + "|mailbox|12345",
+ ImmutableMap.of("type", "notFound",
+ "description", "The message " + username + "|mailbox|12345 can't be found")));
+ }
+
+ @Test
+ public void setMessagesShouldReturnDestroyedWhenMatchingMessage() throws Exception {
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ embeddedElasticSearch.awaitForElasticSearch();
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"destroy\": [\"" + username + "|mailbox|1\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".notDestroyed", anEmptyMap())
+ .body(ARGUMENTS + ".destroyed", hasSize(1))
+ .body(ARGUMENTS + ".destroyed", contains(username + "|mailbox|1"));
+ }
+
+ @Test
+ public void setMessagesShouldDeleteMessageWhenMatchingMessage() throws Exception {
+ // Given
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ embeddedElasticSearch.awaitForElasticSearch();
+
+ // When
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"destroy\": [\"" + username + "|mailbox|1\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200);
+
+ // Then
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + username + "|mailbox|1\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", empty());
+ }
+
+ @Test
+ public void setMessagesShouldReturnDestroyedNotDestroyWhenMixed() throws Exception {
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test2\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test3\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ embeddedElasticSearch.awaitForElasticSearch();
+
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"destroy\": [\"" + username + "|mailbox|1\", \"" + username + "|mailbox|4\", \"" + username + "|mailbox|3\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messagesSet"))
+ .body(ARGUMENTS + ".destroyed", hasSize(2))
+ .body(ARGUMENTS + ".notDestroyed", aMapWithSize(1))
+ .body(ARGUMENTS + ".destroyed", contains(username + "|mailbox|1", username + "|mailbox|3"))
+ .body(ARGUMENTS + ".notDestroyed", hasEntry(username + "|mailbox|4",
+ ImmutableMap.of("type", "notFound",
+ "description", "The message " + username + "|mailbox|4 can't be found")));
+ }
+
+ @Test
+ public void setMessagesShouldDeleteMatchingMessagesWhenMixed() throws Exception {
+ // Given
+ jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "mailbox");
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test2\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+
+ jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "mailbox"),
+ new ByteArrayInputStream("Subject: test3\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
+ embeddedElasticSearch.awaitForElasticSearch();
+
+ // When
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"setMessages\", {\"destroy\": [\"" + username + "|mailbox|1\", \"" + username + "|mailbox|4\", \"" + username + "|mailbox|3\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200);
+
+ // Then
+ given()
+ .accept(ContentType.JSON)
+ .contentType(ContentType.JSON)
+ .header("Authorization", accessToken.serialize())
+ .body("[[\"getMessages\", {\"ids\": [\"" + username + "|mailbox|1\", \"" + username + "|mailbox|2\", \"" + username + "|mailbox|3\"]}, \"#0\"]]")
+ .when()
+ .post("/jmap")
+ .then()
+ .statusCode(200)
+ .body(NAME, equalTo("messages"))
+ .body(ARGUMENTS + ".list", hasSize(1));
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/cassandra/CassandraSetMessagesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/cassandra/CassandraSetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/cassandra/CassandraSetMessagesMethodTest.java
new file mode 100644
index 0000000..6d48f4b
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/src/test/java/org/apache/james/jmap/methods/cassandra/CassandraSetMessagesMethodTest.java
@@ -0,0 +1,35 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.methods.cassandra;
+
+import org.apache.james.backends.cassandra.EmbeddedCassandra;
+import org.apache.james.jmap.JmapServer;
+import org.apache.james.jmap.cassandra.CassandraJmapServer;
+import org.apache.james.jmap.methods.SetMessagesMethodTest;
+import org.apache.james.mailbox.elasticsearch.EmbeddedElasticSearch;
+import org.junit.rules.TemporaryFolder;
+
+public class CassandraSetMessagesMethodTest extends SetMessagesMethodTest {
+
+ @Override
+ protected JmapServer jmapServer(TemporaryFolder temporaryFolder, EmbeddedElasticSearch embeddedElasticSearch, EmbeddedCassandra cassandra) {
+ return new CassandraJmapServer(CassandraJmapServer.defaultOverrideModule(temporaryFolder, embeddedElasticSearch, cassandra));
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MessageNotFoundException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MessageNotFoundException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MessageNotFoundException.java
new file mode 100644
index 0000000..6b09819
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MessageNotFoundException.java
@@ -0,0 +1,23 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.exceptions;
+
+public class MessageNotFoundException extends Exception {
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
new file mode 100644
index 0000000..ebdaf77
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMessagesMethod.java
@@ -0,0 +1,145 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.methods;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.exceptions.MessageNotFoundException;
+import org.apache.james.jmap.model.ClientId;
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.model.SetError;
+import org.apache.james.jmap.model.SetMessagesRequest;
+import org.apache.james.jmap.model.SetMessagesResponse;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+public class SetMessagesMethod<Id extends MailboxId> implements Method {
+
+ private static final int LIMIT_BY_ONE = 1;
+ private static final Logger LOGGER = LoggerFactory.getLogger(SetMessagesMethod.class);
+ private static final Method.Request.Name METHOD_NAME = Method.Request.name("setMessages");
+ private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("messagesSet");
+
+ private final MailboxMapperFactory<Id> mailboxMapperFactory;
+ private final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
+
+ @Inject
+ @VisibleForTesting SetMessagesMethod(MailboxMapperFactory<Id> mailboxMapperFactory, MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory) {
+ this.mailboxMapperFactory = mailboxMapperFactory;
+ this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
+ }
+
+ @Override
+ public Method.Request.Name requestHandled() {
+ return METHOD_NAME;
+ }
+
+ @Override
+ public Class<? extends JmapRequest> requestType() {
+ return SetMessagesRequest.class;
+ }
+
+ public Stream<JmapResponse> process(JmapRequest request, ClientId clientId, MailboxSession mailboxSession) {
+ Preconditions.checkArgument(request instanceof SetMessagesRequest);
+ try {
+ return Stream.of(
+ JmapResponse.builder().clientId(clientId)
+ .response(setMessagesResponse((SetMessagesRequest) request, mailboxSession))
+ .responseName(RESPONSE_NAME)
+ .build());
+ } catch (MailboxException e) {
+ return Stream.of(
+ JmapResponse.builder().clientId(clientId)
+ .error()
+ .responseName(RESPONSE_NAME)
+ .build());
+ }
+ }
+
+ private SetMessagesResponse setMessagesResponse(SetMessagesRequest request, MailboxSession mailboxSession) throws MailboxException {
+ SetMessagesResponse.Builder responseBuilder = SetMessagesResponse.builder();
+ processDestroy(request.getDestroy(), mailboxSession, responseBuilder);
+ return responseBuilder.build();
+ }
+
+ private void processDestroy(List<MessageId> messageIds, MailboxSession mailboxSession, SetMessagesResponse.Builder responseBuilder) throws MailboxException {
+ MessageMapper<Id> messageMapper = mailboxSessionMapperFactory.createMessageMapper(mailboxSession);
+ Consumer<? super MessageId> delete = delete(messageMapper, mailboxSession, responseBuilder);
+
+ messageIds.stream()
+ .forEach(delete);
+ }
+
+ private Consumer<? super MessageId> delete(MessageMapper<Id> messageMapper, MailboxSession mailboxSession, SetMessagesResponse.Builder responseBuilder) {
+ return (messageId) -> {
+ try {
+ Mailbox<Id> mailbox = mailboxMapperFactory
+ .getMailboxMapper(mailboxSession)
+ .findMailboxByPath(messageId.getMailboxPath(mailboxSession));
+
+ MailboxMessage<Id> mailboxMessage = getMailboxMessage(messageMapper, messageId, mailbox);
+
+ messageMapper.delete(mailbox, mailboxMessage);
+ responseBuilder.destroyed(messageId);
+ } catch (MessageNotFoundException e) {
+ responseBuilder.notDestroyed(messageId,
+ SetError.builder()
+ .type("notFound")
+ .description("The message " + messageId.serialize() + " can't be found")
+ .build());
+ } catch (MailboxException e) {
+ LOGGER.error("An error occurred when deleting a message", e);
+ responseBuilder.notDestroyed(messageId,
+ SetError.builder()
+ .type("anErrorOccurred")
+ .description("An error occurred while deleting message " + messageId.serialize())
+ .build());
+ }
+ };
+ }
+
+ private MailboxMessage<Id> getMailboxMessage(MessageMapper<Id> messageMapper, MessageId messageId, Mailbox<Id> mailbox)
+ throws MailboxException, MessageNotFoundException {
+
+ Iterator<MailboxMessage<Id>> mailboxMessage = messageMapper.findInMailbox(mailbox, MessageRange.one(messageId.getUid()), FetchType.Metadata, LIMIT_BY_ONE);
+ if (!mailboxMessage.hasNext()) {
+ throw new MessageNotFoundException();
+ }
+ return mailboxMessage.next();
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageId.java
index 6597111..b4b08c5 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageId.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/MessageId.java
@@ -22,6 +22,7 @@ import java.util.Objects;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.MailboxSession.User;
+import org.apache.james.mailbox.model.MailboxConstants;
import org.apache.james.mailbox.model.MailboxPath;
import org.javatuples.Triplet;
@@ -67,7 +68,7 @@ public class MessageId {
}
public MailboxPath getMailboxPath(MailboxSession mailboxSession) {
- return new MailboxPath("", username, mailboxPath);
+ return new MailboxPath(MailboxConstants.USER_NAMESPACE, username, mailboxPath);
}
@JsonValue
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
new file mode 100644
index 0000000..da94af5
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
@@ -0,0 +1,80 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.model;
+
+import java.util.Optional;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+@JsonDeserialize(builder = SetError.Builder.class)
+public class SetError {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @JsonPOJOBuilder(withPrefix = "")
+ public static class Builder {
+
+ private String type;
+ private String description;
+
+ private Builder() {
+ }
+
+ public Builder type(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public Builder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public SetError build() {
+ Preconditions.checkState(!Strings.isNullOrEmpty(type), "'type' is mandatory");
+ return new SetError(type, Optional.ofNullable(description));
+ }
+ }
+
+ private final String type;
+ private final Optional<String> description;
+
+ @VisibleForTesting SetError(String type, Optional<String> description) {
+ this.type = type;
+ this.description = description;
+ }
+
+ @JsonSerialize
+ public String getType() {
+ return type;
+ }
+
+ @JsonSerialize
+ public Optional<String> getDescription() {
+ return description;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
new file mode 100644
index 0000000..9d6d158
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesRequest.java
@@ -0,0 +1,126 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.model;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.jmap.methods.JmapRequest;
+
+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;
+
+@JsonDeserialize(builder = SetMessagesRequest.Builder.class)
+public class SetMessagesRequest implements JmapRequest {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @JsonPOJOBuilder(withPrefix = "")
+ public static class Builder {
+
+ private String accountId;
+ private String ifInState;
+ private ImmutableList.Builder<Message> create;
+ private ImmutableList.Builder<Message> update;
+ private ImmutableList.Builder<MessageId> destroy;
+
+ private Builder() {
+ create = ImmutableList.builder();
+ update = ImmutableList.builder();
+ destroy = ImmutableList.builder();
+ }
+
+ public Builder accountId(String accountId) {
+ if (accountId != null) {
+ throw new NotImplementedException();
+ }
+ return this;
+ }
+
+ public Builder ifInState(String ifInState) {
+ if (ifInState != null) {
+ throw new NotImplementedException();
+ }
+ return this;
+ }
+
+ public Builder create(List<Message> create) {
+ if (create != null && !create.isEmpty()) {
+ throw new NotImplementedException();
+ }
+ return this;
+ }
+
+ public Builder update(List<Message> update) {
+ if (update != null && !update.isEmpty()) {
+ throw new NotImplementedException();
+ }
+ return this;
+ }
+
+ public Builder destroy(List<MessageId> destroy) {
+ this.destroy.addAll(destroy);
+ return this;
+ }
+
+ public SetMessagesRequest build() {
+ return new SetMessagesRequest(Optional.ofNullable(accountId), Optional.ofNullable(ifInState), create.build(), update.build(), destroy.build());
+ }
+ }
+
+ private final Optional<String> accountId;
+ private final Optional<String> ifInState;
+ private final List<Message> create;
+ private final List<Message> update;
+ private final List<MessageId> destroy;
+
+ @VisibleForTesting SetMessagesRequest(Optional<String> accountId, Optional<String> ifInState, List<Message> create, List<Message> update, List<MessageId> destroy) {
+ this.accountId = accountId;
+ this.ifInState = ifInState;
+ this.create = create;
+ this.update = update;
+ this.destroy = destroy;
+ }
+
+ public Optional<String> getAccountId() {
+ return accountId;
+ }
+
+ public Optional<String> getIfInState() {
+ return ifInState;
+ }
+
+ public List<Message> getCreate() {
+ return create;
+ }
+
+ public List<Message> getUpdate() {
+ return update;
+ }
+
+ public List<MessageId> getDestroy() {
+ return destroy;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
new file mode 100644
index 0000000..67bdd46
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMessagesResponse.java
@@ -0,0 +1,188 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+package org.apache.james.jmap.model;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.jmap.methods.Method;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@JsonDeserialize(builder = SetMessagesResponse.Builder.class)
+public class SetMessagesResponse implements Method.Response {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @JsonPOJOBuilder(withPrefix = "")
+ public static class Builder {
+
+ private String accountId;
+ private String oldState;
+ private String newState;
+ private ImmutableList.Builder<Message> created;
+ private ImmutableList.Builder<MessageId> updated;
+ private ImmutableList.Builder<MessageId> destroyed;
+ private ImmutableMap.Builder<MessageId, SetError> notCreated;
+ private ImmutableMap.Builder<MessageId, SetError> notUpdated;
+ private ImmutableMap.Builder<MessageId, SetError> notDestroyed;
+
+ private Builder() {
+ created = ImmutableList.builder();
+ updated = ImmutableList.builder();
+ destroyed = ImmutableList.builder();
+ notCreated = ImmutableMap.builder();
+ notUpdated = ImmutableMap.builder();
+ notDestroyed = ImmutableMap.builder();
+ }
+
+ public Builder accountId(String accountId) {
+ throw new NotImplementedException();
+ }
+
+ public Builder oldState(String oldState) {
+ throw new NotImplementedException();
+ }
+
+ public Builder newState(String newState) {
+ throw new NotImplementedException();
+ }
+
+ public Builder created(List<Message> created) {
+ this.created.addAll(created);
+ return this;
+ }
+
+ public Builder updated(List<MessageId> updated) {
+ this.updated.addAll(updated);
+ return this;
+ }
+
+ public Builder destroyed(MessageId destroyed) {
+ this.destroyed.add(destroyed);
+ return this;
+ }
+
+ public Builder destroyed(List<MessageId> destroyed) {
+ this.destroyed.addAll(destroyed);
+ return this;
+ }
+
+ public Builder notCreated(Map<MessageId, SetError> notCreated) {
+ this.notCreated.putAll(notCreated);
+ return this;
+ }
+
+ public Builder notUpdated(Map<MessageId, SetError> notUpdated) {
+ this.notUpdated.putAll(notUpdated);
+ return this;
+ }
+
+ public Builder notDestroyed(MessageId messageId, SetError notDestroyed) {
+ this.notDestroyed.put(messageId, notDestroyed);
+ return this;
+ }
+
+ public Builder notDestroyed(Map<MessageId, SetError> notDestroyed) {
+ this.notDestroyed.putAll(notDestroyed);
+ return this;
+ }
+
+ public SetMessagesResponse build() {
+ return new SetMessagesResponse(accountId, oldState, newState,
+ created.build(), updated.build(), destroyed.build(), notCreated.build(), notUpdated.build(), notDestroyed.build());
+ }
+ }
+
+ private final String accountId;
+ private final String oldState;
+ private final String newState;
+ private final List<Message> created;
+ private final List<MessageId> updated;
+ private final List<MessageId> destroyed;
+ private final Map<MessageId, SetError> notCreated;
+ private final Map<MessageId, SetError> notUpdated;
+ private final Map<MessageId, SetError> notDestroyed;
+
+ @VisibleForTesting SetMessagesResponse(String accountId, String oldState, String newState, List<Message> created, List<MessageId> updated, List<MessageId> destroyed,
+ Map<MessageId, SetError> notCreated, Map<MessageId, SetError> notUpdated, Map<MessageId, SetError> notDestroyed) {
+ this.accountId = accountId;
+ this.oldState = oldState;
+ this.newState = newState;
+ this.created = created;
+ this.updated = updated;
+ this.destroyed = destroyed;
+ this.notCreated = notCreated;
+ this.notUpdated = notUpdated;
+ this.notDestroyed = notDestroyed;
+ }
+
+ @JsonSerialize
+ public String getAccountId() {
+ return accountId;
+ }
+
+ @JsonSerialize
+ public String getOldState() {
+ return oldState;
+ }
+
+ @JsonSerialize
+ public String getNewState() {
+ return newState;
+ }
+
+ @JsonSerialize
+ public List<Message> getCreated() {
+ return created;
+ }
+
+ @JsonSerialize
+ public List<MessageId> getUpdated() {
+ return updated;
+ }
+
+ @JsonSerialize
+ public List<MessageId> getDestroyed() {
+ return destroyed;
+ }
+
+ @JsonSerialize
+ public Map<MessageId, SetError> getNotCreated() {
+ return notCreated;
+ }
+
+ @JsonSerialize
+ public Map<MessageId, SetError> getNotUpdated() {
+ return notUpdated;
+ }
+
+ @JsonSerialize
+ public Map<MessageId, SetError> getNotDestroyed() {
+ return notDestroyed;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetErrorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetErrorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetErrorTest.java
new file mode 100644
index 0000000..1d5ace1
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetErrorTest.java
@@ -0,0 +1,59 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+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.junit.Test;
+
+public class SetErrorTest {
+
+ @Test
+ public void buildShouldThrowWhenTypeIsNotGiven() {
+ assertThatThrownBy(() -> SetError.builder().build())
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ public void buildShouldWorkWhenAllMandatoryFieldsAreGiven() {
+ SetError expected = new SetError("type", Optional.empty());
+
+ SetError setError = SetError.builder()
+ .type("type")
+ .build();
+
+ assertThat(setError).isEqualToComparingFieldByField(expected);
+ }
+
+ @Test
+ public void buildShouldWorkWhenAllFieldsAreGiven() {
+ SetError expected = new SetError("type", Optional.of("description"));
+
+ SetError setError = SetError.builder()
+ .type("type")
+ .description("description")
+ .build();
+
+ assertThat(setError).isEqualToComparingFieldByField(expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java
new file mode 100644
index 0000000..b600172
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesRequestTest.java
@@ -0,0 +1,96 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class SetMessagesRequestTest {
+
+ @Test
+ public void builderShouldThrowWhenAccountIdIsNotNull() {
+ assertThatThrownBy(() -> SetMessagesRequest.builder().accountId(""))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void builderShouldThrowWhenIfInStateIsNotNull() {
+ assertThatThrownBy(() -> SetMessagesRequest.builder().ifInState(""))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void builderShouldThrowWhenCreateIsNotEmpty() {
+ assertThatThrownBy(() -> SetMessagesRequest.builder().create(ImmutableList.of(Message.builder()
+ .id(MessageId.of("user|create|1"))
+ .blobId("blobId")
+ .threadId("threadId")
+ .mailboxIds(ImmutableList.of("mailboxId"))
+ .headers(ImmutableMap.of("key", "value"))
+ .subject("subject")
+ .size(123)
+ .date(ZonedDateTime.now())
+ .preview("preview")
+ .build())))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void builderShouldThrowWhenUpdateIsNotEmpty() {
+ assertThatThrownBy(() -> SetMessagesRequest.builder().update(ImmutableList.of(Message.builder()
+ .id(MessageId.of("user|create|1"))
+ .blobId("blobId")
+ .threadId("threadId")
+ .mailboxIds(ImmutableList.of("mailboxId"))
+ .headers(ImmutableMap.of("key", "value"))
+ .subject("subject")
+ .size(123)
+ .date(ZonedDateTime.now())
+ .preview("preview")
+ .build())))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void builderShouldWork() {
+ ImmutableList<MessageId> destroy = ImmutableList.of(MessageId.of("user|destroy|1"));
+
+ SetMessagesRequest expected = new SetMessagesRequest(Optional.empty(), Optional.empty(), ImmutableList.of(), ImmutableList.of(), destroy);
+
+ SetMessagesRequest setMessagesRequest = SetMessagesRequest.builder()
+ .accountId(null)
+ .ifInState(null)
+ .create(ImmutableList.of())
+ .update(ImmutableList.of())
+ .destroy(destroy)
+ .build();
+
+ assertThat(setMessagesRequest).isEqualToComparingFieldByField(expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/6665a49e/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java
new file mode 100644
index 0000000..23743f3
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/SetMessagesResponseTest.java
@@ -0,0 +1,86 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "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 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.time.ZonedDateTime;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class SetMessagesResponseTest {
+
+ @Test
+ public void builderShouldThrowWhenAccountIdIsGiven() {
+ assertThatThrownBy(() -> SetMessagesResponse.builder().accountId(""))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void builderShouldThrowWhenOldStateGiven() {
+ assertThatThrownBy(() -> SetMessagesResponse.builder().oldState(""))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void builderShouldThrowWhenNewStateIsGiven() {
+ assertThatThrownBy(() -> SetMessagesResponse.builder().newState(""))
+ .isInstanceOf(NotImplementedException.class);
+ }
+
+ @Test
+ public void builderShouldWork() {
+ ZonedDateTime currentDate = ZonedDateTime.now();
+ ImmutableList<Message> created = ImmutableList.of(
+ Message.builder()
+ .id(MessageId.of("user|created|1"))
+ .blobId("blobId")
+ .threadId("threadId")
+ .mailboxIds(ImmutableList.of("mailboxId"))
+ .headers(ImmutableMap.of("key", "value"))
+ .subject("subject")
+ .size(123)
+ .date(currentDate)
+ .preview("preview")
+ .build());
+ ImmutableList<MessageId> updated = ImmutableList.of(MessageId.of("user|updated|1"));
+ ImmutableList<MessageId> destroyed = ImmutableList.of(MessageId.of("user|destroyed|1"));
+ ImmutableMap<MessageId, SetError> notCreated = ImmutableMap.of(MessageId.of("user|created|2"), SetError.builder().type("created").build());
+ ImmutableMap<MessageId, SetError> notUpdated = ImmutableMap.of(MessageId.of("user|update|2"), SetError.builder().type("updated").build());
+ ImmutableMap<MessageId, SetError> notDestroyed = ImmutableMap.of(MessageId.of("user|destroyed|3"), SetError.builder().type("destroyed").build());
+ SetMessagesResponse expected = new SetMessagesResponse(null, null, null, created, updated, destroyed, notCreated, notUpdated, notDestroyed);
+
+ SetMessagesResponse setMessagesResponse = SetMessagesResponse.builder()
+ .created(created)
+ .updated(updated)
+ .destroyed(destroyed)
+ .notCreated(notCreated)
+ .notUpdated(notUpdated)
+ .notDestroyed(notDestroyed)
+ .build();
+
+ assertThat(setMessagesResponse).isEqualToComparingFieldByField(expected);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org