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/04/13 09:13:05 UTC

[2/4] james-project git commit: JAMES-1714 Implement SetMailboxes: update

JAMES-1714 Implement SetMailboxes: update


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/f185db6f
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/f185db6f
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/f185db6f

Branch: refs/heads/master
Commit: f185db6f8dbed43cc8946e6d1091643f9617b5c1
Parents: 49b3180
Author: Laura Royet <lr...@linagora.com>
Authored: Thu Mar 31 14:45:10 2016 +0200
Committer: Laura Royet <lr...@linagora.com>
Committed: Tue Apr 12 14:15:27 2016 +0200

----------------------------------------------------------------------
 .../org/apache/james/jmap/MethodsModule.java    |   2 +
 .../integration/SetMailboxesMethodTest.java     | 759 ++++++++++++++++++-
 .../methods/SetMailboxesCreationProcessor.java  |  10 +-
 .../methods/SetMailboxesUpdateProcessor.java    | 183 +++++
 .../james/jmap/model/SetMailboxesRequest.java   |  36 +-
 .../james/jmap/model/SetMailboxesResponse.java  |  75 +-
 .../model/mailbox/MailboxCreateRequest.java     | 157 ++++
 .../jmap/model/mailbox/MailboxRequest.java      | 157 ----
 .../model/mailbox/MailboxUpdateRequest.java     | 145 ++++
 .../apache/james/jmap/utils/MailboxUtils.java   |   9 +
 .../SetMailboxesCreationProcessorTest.java      |   4 +-
 .../jmap/methods/SetMailboxesMethodTest.java    |   4 +-
 .../SetMailboxesUpdateProcessorTest.java        |  82 ++
 .../jmap/model/SetMailboxesRequestTest.java     |  27 +-
 .../jmap/model/SetMailboxesResponseTest.java    |  10 +-
 .../model/mailbox/MailboxCreateRequestTest.java |  80 ++
 .../jmap/model/mailbox/MailboxRequestTest.java  |  80 --
 .../model/mailbox/MailboxUpdateRequestTest.java |  60 ++
 .../james/jmap/utils/MailboxUtilsTest.java      |  39 +
 19 files changed, 1598 insertions(+), 321 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/MethodsModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/MethodsModule.java b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/MethodsModule.java
index f0af8b3..2b14c94 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/MethodsModule.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/MethodsModule.java
@@ -32,6 +32,7 @@ import org.apache.james.jmap.methods.SetMailboxesCreationProcessor;
 import org.apache.james.jmap.methods.SetMailboxesDestructionProcessor;
 import org.apache.james.jmap.methods.SetMailboxesMethod;
 import org.apache.james.jmap.methods.SetMailboxesProcessor;
+import org.apache.james.jmap.methods.SetMailboxesUpdateProcessor;
 import org.apache.james.jmap.methods.SetMessagesCreationProcessor;
 import org.apache.james.jmap.methods.SetMessagesDestructionProcessor;
 import org.apache.james.jmap.methods.SetMessagesMethod;
@@ -72,6 +73,7 @@ public class MethodsModule<Id extends MailboxId> extends AbstractModule {
         Multibinder<SetMailboxesProcessor<Id>> setMailboxesProcessor =
             Multibinder.newSetBinder(binder(), guiceGenericType.newGenericType(SetMailboxesProcessor.class));
         setMailboxesProcessor.addBinding().to(guiceGenericType.newGenericType(SetMailboxesCreationProcessor.class));
+        setMailboxesProcessor.addBinding().to(guiceGenericType.newGenericType(SetMailboxesUpdateProcessor.class));
         setMailboxesProcessor.addBinding().to(guiceGenericType.newGenericType(SetMailboxesDestructionProcessor.class));
 
         Multibinder<SetMessagesProcessor<Id>> setMessagesProcessors =

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMailboxesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMailboxesMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMailboxesMethodTest.java
index 830777e..07718f8 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMailboxesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMailboxesMethodTest.java
@@ -24,6 +24,7 @@ import static com.jayway.restassured.RestAssured.with;
 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.containsString;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasEntry;
@@ -32,6 +33,7 @@ import static org.hamcrest.Matchers.hasKey;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.isEmptyOrNullString;
 import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.nullValue;
 import static org.hamcrest.collection.IsMapWithSize.aMapWithSize;
 
 import org.apache.james.GuiceJamesServer;
@@ -85,7 +87,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldErrorNotSupportedWhenRoleGiven() throws Exception {
+    public void setMailboxesShouldErrorNotSupportedWhenRoleGiven() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -115,7 +117,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldErrorNotSupportedWhenSortOrderGiven() throws Exception {
+    public void setMailboxesShouldErrorNotSupportedWhenSortOrderGiven() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -145,7 +147,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnCreatedMailbox() throws Exception {
+    public void setMailboxesShouldReturnCreatedMailbox() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -174,7 +176,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldCreateMailbox() throws Exception {
+    public void setMailboxesShouldCreateMailbox() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -212,7 +214,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnCreatedMailboxWhenChildOfInboxMailbox() throws Exception {
+    public void setMailboxesShouldReturnCreatedMailboxWhenChildOfInboxMailbox() {
         String inboxId =
             with()
                 .accept(ContentType.JSON)
@@ -258,7 +260,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldCreateMailboxWhenChildOfInboxMailbox() throws Exception {
+    public void setMailboxesShouldCreateMailboxWhenChildOfInboxMailbox() {
         String inboxId =
             with()
                 .accept(ContentType.JSON)
@@ -310,7 +312,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnNotCreatedWhenInvalidParentId() throws Exception {
+    public void setMailboxesShouldReturnNotCreatedWhenInvalidParentId() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -343,7 +345,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnCreatedMailboxWhenCreatingParentThenChildMailboxes() throws Exception {
+    public void setMailboxesShouldReturnCreatedMailboxWhenCreatingParentThenChildMailboxes() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -382,7 +384,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnCreatedMailboxWhenCreatingChildThenParentMailboxes() throws Exception {
+    public void setMailboxesShouldReturnCreatedMailboxWhenCreatingChildThenParentMailboxes() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -421,7 +423,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnNotCreatedWhenMailboxAlreadyExists() throws Exception {
+    public void setMailboxesShouldReturnNotCreatedWhenMailboxAlreadyExists() {
         jmapServer.serverProbe().createMailbox("#private", username, "myBox");
         String requestBody =
             "[" +
@@ -454,7 +456,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnNotCreatedWhenCycleDetected() throws Exception {
+    public void setMailboxesShouldReturnNotCreatedWhenCycleDetected() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -496,7 +498,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnNotCreatedWhenMailboxNameContainsPathDelimiter() throws Exception {
+    public void setMailboxesShouldReturnNotCreatedWhenMailboxNameContainsPathDelimiter() {
         String requestBody =
                 "[" +
                     "  [ \"setMailboxes\"," +
@@ -519,16 +521,16 @@ public abstract class SetMailboxesMethodTest {
             .when()
                 .post("/jmap")
             .then()
-            .statusCode(200)
-            .body(NAME, equalTo("mailboxesSet"))
-            .body(ARGUMENTS + ".notCreated", aMapWithSize(1))
-            .body(ARGUMENTS + ".notCreated", hasEntry(equalTo("create-id01"), Matchers.allOf(
-                        hasEntry(equalTo("type"), equalTo("invalidArguments")),
-                        hasEntry(equalTo("description"), equalTo("The mailbox 'A.B.C.D' contains an illegal character: '.'")))
-                    ));
+                .statusCode(200)
+                .body(NAME, equalTo("mailboxesSet"))
+                .body(ARGUMENTS + ".notCreated", aMapWithSize(1))
+                .body(ARGUMENTS + ".notCreated", hasEntry(equalTo("create-id01"), Matchers.allOf(
+                            hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                            hasEntry(equalTo("description"), equalTo("The mailbox 'A.B.C.D' contains an illegal character: '.'")))
+                        ));
     }
 
-    public void setMailboxesShouldReturnDestroyedMailbox() throws Exception {
+    public void setMailboxesShouldReturnDestroyedMailbox() {
         jmapServer.serverProbe().createMailbox("#private", username, "myBox");
         Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
         String mailboxId = mailbox.getMailboxId().serialize();
@@ -550,14 +552,13 @@ public abstract class SetMailboxesMethodTest {
         .when()
             .post("/jmap")
         .then()
-            .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("mailboxesSet"))
             .body(ARGUMENTS + ".destroyed", contains(mailboxId));
     }
 
     @Test
-    public void setMailboxesShouldDestroyMailbox() throws Exception {
+    public void setMailboxesShouldDestroyMailbox() {
         jmapServer.serverProbe().createMailbox("#private", username, "myBox");
         Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
         String requestBody =
@@ -588,14 +589,13 @@ public abstract class SetMailboxesMethodTest {
         .when()
             .post("/jmap")
         .then()
-            .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("mailboxes"))
-            .body(ARGUMENTS + ".list", hasSize(1)); // Inbox
+            .body(ARGUMENTS + ".list", hasSize(1));
     }
 
     @Test
-    public void setMailboxesShouldReturnNotDestroyedWhenMailboxDoesntExist() throws Exception {
+    public void setMailboxesShouldReturnNotDestroyedWhenMailboxDoesntExist() {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -614,7 +614,6 @@ public abstract class SetMailboxesMethodTest {
         .when()
             .post("/jmap")
         .then()
-            .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("mailboxesSet"))
             .body(ARGUMENTS + ".notDestroyed", aMapWithSize(1))
@@ -624,7 +623,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnNotDestroyedWhenMailboxHasChild() throws Exception {
+    public void setMailboxesShouldReturnNotDestroyedWhenMailboxHasChild() {
         jmapServer.serverProbe().createMailbox("#private", username, "myBox");
         jmapServer.serverProbe().createMailbox("#private", username, "myBox.child");
         Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
@@ -647,7 +646,6 @@ public abstract class SetMailboxesMethodTest {
         .when()
             .post("/jmap")
         .then()
-            .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("mailboxesSet"))
             .body(ARGUMENTS + ".notDestroyed", aMapWithSize(1))
@@ -657,7 +655,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnNotDestroyedWhenSystemMailbox() throws Exception {
+    public void setMailboxesShouldReturnNotDestroyedWhenSystemMailbox() {
         Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "inbox");
         String mailboxId = mailbox.getMailboxId().serialize();
         String requestBody =
@@ -678,7 +676,6 @@ public abstract class SetMailboxesMethodTest {
         .when()
             .post("/jmap")
         .then()
-            .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("mailboxesSet"))
             .body(ARGUMENTS + ".notDestroyed", aMapWithSize(1))
@@ -688,7 +685,7 @@ public abstract class SetMailboxesMethodTest {
     }
 
     @Test
-    public void setMailboxesShouldReturnDestroyedWhenParentThenChildMailboxes() throws Exception {
+    public void setMailboxesShouldReturnDestroyedWhenParentThenChildMailboxes() {
         jmapServer.serverProbe().createMailbox("#private", username, "parent");
         Mailbox<?> parentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "parent");
         String parentMailboxId = parentMailbox.getMailboxId().serialize();
@@ -713,14 +710,13 @@ public abstract class SetMailboxesMethodTest {
         .when()
             .post("/jmap")
         .then()
-            .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("mailboxesSet"))
             .body(ARGUMENTS + ".destroyed", containsInAnyOrder(parentMailboxId, childMailboxId));
     }
 
     @Test
-    public void setMailboxesShouldReturnDestroyedWhenChildThenParentMailboxes() throws Exception {
+    public void setMailboxesShouldReturnDestroyedWhenChildThenParentMailboxes() {
         jmapServer.serverProbe().createMailbox("#private", username, "parent");
         Mailbox<?> parentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "parent");
         String parentMailboxId = parentMailbox.getMailboxId().serialize();
@@ -745,9 +741,704 @@ public abstract class SetMailboxesMethodTest {
         .when()
             .post("/jmap")
         .then()
-            .log().ifValidationFails()
             .statusCode(200)
             .body(NAME, equalTo("mailboxesSet"))
             .body(ARGUMENTS + ".destroyed", containsInAnyOrder(parentMailboxId, childMailboxId));
     }
+
+    @Test
+    public void setMailboxesShouldReturnNotUpdatedWhenUnknownMailbox() {
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"unknown-update-id01\" : {" +
+                    "          \"name\" : \"yolo\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".notUpdated", hasEntry(equalTo("unknown-update-id01"), Matchers.allOf(
+                    hasEntry(equalTo("type"), equalTo("notFound")),
+                    hasEntry(equalTo("description"), containsString("unknown-update-id01")))));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnUpdatedMailboxIdWhenNoUpdateAskedOnExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".updated", contains(mailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnUpdatedWhenNameUpdateAskedOnExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"myRenamedBox\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".updated", contains(mailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldUpdateMailboxNameWhenNameUpdateAskedOnExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"myRenamedBox\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        with()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(ARGUMENTS + ".list[0].name", equalTo("myRenamedBox"));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnMailboxIdWhenMovingToAnotherParentMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myChosenParentBox");
+        Mailbox<?> chosenMailboxParent = jmapServer.serverProbe().getMailbox("#private", username, "myChosenParentBox");
+        String chosenMailboxParentId = chosenMailboxParent.getMailboxId().serialize();
+        
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : \"" + chosenMailboxParentId + "\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".updated", contains(mailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldUpdateMailboxParentIdWhenMovingToAnotherParentMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myPreviousParentBox.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        
+        jmapServer.serverProbe().createMailbox("#private", username, "myNewParentBox");
+        Mailbox<?> newParentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "myNewParentBox");
+        String newParentMailboxId = newParentMailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : \"" + newParentMailboxId + "\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        with()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(ARGUMENTS + ".list[0].parentId", equalTo(newParentMailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnMailboxIdWhenParentIdUpdateAskedOnExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myPreviousParentBox.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        
+        jmapServer.serverProbe().createMailbox("#private", username, "myNewParentBox");
+        Mailbox<?> newParentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "myNewParentBox");
+        String newParentMailboxId = newParentMailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : \"" + newParentMailboxId + "\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".updated", contains(mailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldUpdateMailboxParentIdWhenParentIdUpdateAskedOnExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myPreviousParentBox.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        
+        jmapServer.serverProbe().createMailbox("#private", username, "myNewParentBox");
+        Mailbox<?> newParentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "myNewParentBox");
+        String newParentMailboxId = newParentMailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : \"" + newParentMailboxId + "\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        with()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(ARGUMENTS + ".list[0].parentId", equalTo(newParentMailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnMailboxIdWhenParentIdUpdateAskedAsOrphanForExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myPreviousParentBox.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : null" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".updated", contains(mailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldUpdateParentIdWhenAskedAsOrphanForExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myPreviousParentBox.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : null" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        with()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(ARGUMENTS + ".list[0].parentId", nullValue());
+    }
+
+    @Test
+    public void setMailboxesShouldReturnMailboxIdWhenNameAndParentIdUpdateForExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myPreviousParentBox.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myNewParentBox");
+        Mailbox<?> newParentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "myNewParentBox");
+        String newParentMailboxId = newParentMailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"myRenamedBox\", " +
+                    "          \"parentId\" : \"" + newParentMailboxId + "\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".updated", contains(mailboxId));
+    }
+
+    @Test
+    public void setMailboxesShoulUpdateMailboxIAndParentIddWhenBothUpdatedForExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myPreviousParentBox.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myPreviousParentBox.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myNewParentBox");
+        Mailbox<?> newParentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "myNewParentBox");
+        String newParentMailboxId = newParentMailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"myRenamedBox\", " +
+                    "          \"parentId\" : \"" + newParentMailboxId + "\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        with()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(ARGUMENTS + ".list[0].parentId",equalTo(newParentMailboxId))
+            .body(ARGUMENTS + ".list[0].name",equalTo("myRenamedBox"));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotUpdatedWhenNameContainsPathDelimiter() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"my.Box\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".notUpdated", hasEntry(equalTo(mailboxId), Matchers.allOf(
+                    hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                    hasEntry(equalTo("description"), equalTo("The mailbox 'my.Box' contains an illegal character: '.'"))))); 
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotUpdatedWhenNewParentDoesntExist() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : \"badParent\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".notUpdated", hasEntry(equalTo(mailboxId), Matchers.allOf(
+                    hasEntry(equalTo("type"), equalTo("notFound")),
+                    hasEntry(equalTo("description"), containsString("badParent")))));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotUpdatedWhenUpdatingParentIdOfAParentMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "root");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "root.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "root.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        jmapServer.serverProbe().createMailbox("#private", username, "root.myBox.child");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "myNewParentBox");
+        Mailbox<?> newParentMailbox = jmapServer.serverProbe().getMailbox("#private", username, "myNewParentBox");
+        String newParentMailboxId = newParentMailbox.getMailboxId().serialize();
+
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"parentId\" : \"" + newParentMailboxId + "\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".notUpdated", hasEntry(equalTo(mailboxId), Matchers.allOf(
+                    hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                    hasEntry(equalTo("description"), equalTo("Cannot update a parent mailbox."))))); 
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotUpdatedWhenRenamingAMailboxToAnAlreadyExistingMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        jmapServer.serverProbe().createMailbox("#private", username, "mySecondBox");
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"mySecondBox\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".notUpdated", hasEntry(equalTo(mailboxId), Matchers.allOf(
+                    hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                    hasEntry(equalTo("description"), equalTo("Cannot rename a mailbox to an already existing mailbox."))))); 
+    }
+
+    @Test
+    public void setMailboxesShouldReturnUpdatedWhenRenamingAChildMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "root");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "root.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "root.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"mySecondBox\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxesSet"))
+            .body(ARGUMENTS + ".updated", contains(mailboxId));
+    }
+
+    @Test
+    public void setMailboxesShouldUpdateMailboxNameWhenRenamingAChildMailbox() {
+        jmapServer.serverProbe().createMailbox("#private", username, "root");
+
+        jmapServer.serverProbe().createMailbox("#private", username, "root.myBox");
+        Mailbox<?> mailbox = jmapServer.serverProbe().getMailbox("#private", username, "root.myBox");
+        String mailboxId = mailbox.getMailboxId().serialize();
+
+        String requestBody =
+                "[" +
+                    "  [ \"setMailboxes\"," +
+                    "    {" +
+                    "      \"update\": {" +
+                    "        \"" + mailboxId + "\" : {" +
+                    "          \"name\" : \"mySecondBox\"" +
+                    "        }" +
+                    "      }" +
+                    "    }," +
+                    "    \"#0\"" +
+                    "  ]" +
+                    "]";
+
+        with()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\"]}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(1))
+            .body(ARGUMENTS + ".list[0].name", equalTo("mySecondBox"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessor.java
index fe6696b..6ca69f5 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessor.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessor.java
@@ -32,7 +32,7 @@ import org.apache.james.jmap.model.SetError;
 import org.apache.james.jmap.model.SetMailboxesRequest;
 import org.apache.james.jmap.model.SetMailboxesResponse;
 import org.apache.james.jmap.model.mailbox.Mailbox;
-import org.apache.james.jmap.model.mailbox.MailboxRequest;
+import org.apache.james.jmap.model.mailbox.MailboxCreateRequest;
 import org.apache.james.jmap.utils.SortingHierarchicalCollections;
 import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
 import org.apache.james.jmap.utils.MailboxUtils;
@@ -53,7 +53,7 @@ public class SetMailboxesCreationProcessor<Id extends MailboxId> implements SetM
     private static final Logger LOGGER = LoggerFactory.getLogger(SetMailboxesCreationProcessor.class);
 
     private final MailboxManager mailboxManager;
-    private final SortingHierarchicalCollections<Map.Entry<MailboxCreationId, MailboxRequest>, String> sortingHierarchicalCollections;
+    private final SortingHierarchicalCollections<Map.Entry<MailboxCreationId, MailboxCreateRequest>, String> sortingHierarchicalCollections;
     private final MailboxUtils<Id> mailboxUtils;
 
     @Inject
@@ -90,7 +90,7 @@ public class SetMailboxesCreationProcessor<Id extends MailboxId> implements SetM
                         .build()));
     }
 
-    private void createMailbox(MailboxCreationId mailboxCreationId, MailboxRequest mailboxRequest, MailboxSession mailboxSession,
+    private void createMailbox(MailboxCreationId mailboxCreationId, MailboxCreateRequest mailboxRequest, MailboxSession mailboxSession,
             Map<MailboxCreationId, String> creationIdsToCreatedMailboxId, SetMailboxesResponse.Builder builder) {
         try {
             ensureValidMailboxName(mailboxRequest, mailboxSession);
@@ -127,7 +127,7 @@ public class SetMailboxesCreationProcessor<Id extends MailboxId> implements SetM
         }
     }
 
-    private void ensureValidMailboxName(MailboxRequest mailboxRequest, MailboxSession mailboxSession) {
+    private void ensureValidMailboxName(MailboxCreateRequest mailboxRequest, MailboxSession mailboxSession) {
         String name = mailboxRequest.getName();
         char pathDelimiter = mailboxSession.getPathDelimiter();
         if (name.contains(String.valueOf(pathDelimiter))) {
@@ -135,7 +135,7 @@ public class SetMailboxesCreationProcessor<Id extends MailboxId> implements SetM
         }
     }
 
-    private MailboxPath getMailboxPath(MailboxRequest mailboxRequest, Map<MailboxCreationId, String> creationIdsToCreatedMailboxId, MailboxSession mailboxSession) throws MailboxException {
+    private MailboxPath getMailboxPath(MailboxCreateRequest mailboxRequest, Map<MailboxCreationId, String> creationIdsToCreatedMailboxId, MailboxSession mailboxSession) throws MailboxException {
         if (mailboxRequest.getParentId().isPresent()) {
             String parentId = mailboxRequest.getParentId().get();
             String parentName = mailboxUtils.getMailboxNameFromId(parentId, mailboxSession)

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesUpdateProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesUpdateProcessor.java
new file mode 100644
index 0000000..bf4d4ac
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesUpdateProcessor.java
@@ -0,0 +1,183 @@
+/****************************************************************
+ * 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.Optional;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.exceptions.MailboxHasChildException;
+import org.apache.james.jmap.exceptions.MailboxNameException;
+import org.apache.james.jmap.exceptions.MailboxParentNotFoundException;
+import org.apache.james.jmap.model.SetError;
+import org.apache.james.jmap.model.SetMailboxesRequest;
+import org.apache.james.jmap.model.SetMailboxesResponse;
+import org.apache.james.jmap.model.SetMailboxesResponse.Builder;
+import org.apache.james.jmap.model.mailbox.Mailbox;
+import org.apache.james.jmap.model.mailbox.MailboxUpdateRequest;
+import org.apache.james.jmap.utils.MailboxUtils;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.exception.MailboxExistsException;
+import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+public class SetMailboxesUpdateProcessor<Id extends MailboxId> implements SetMailboxesProcessor<Id> {
+
+    private final MailboxUtils<Id> mailboxUtils;
+    private final MailboxManager mailboxManager;
+
+    @Inject
+    @VisibleForTesting
+    SetMailboxesUpdateProcessor(MailboxUtils<Id> mailboxUtils, MailboxManager mailboxManager) {
+        this.mailboxUtils = mailboxUtils;
+        this.mailboxManager = mailboxManager;
+    }
+
+    @Override
+    public SetMailboxesResponse process(SetMailboxesRequest request, MailboxSession mailboxSession) {
+        SetMailboxesResponse.Builder responseBuilder = SetMailboxesResponse.builder();
+        request.getUpdate()
+            .entrySet()
+            .stream()
+            .forEach(update -> handleUpdate(update.getKey(), update.getValue(), responseBuilder, mailboxSession));
+        return responseBuilder.build();
+    }
+
+    private void handleUpdate(String mailboxId, MailboxUpdateRequest updateRequest, Builder responseBuilder, MailboxSession mailboxSession) {
+        try {
+            validateMailboxName(updateRequest, mailboxSession);
+            Mailbox mailbox = getMailbox(mailboxId, mailboxSession);
+            validateParent(mailbox, updateRequest, mailboxSession);
+
+            updateMailbox(mailbox, updateRequest, mailboxSession);
+            responseBuilder.updated(mailboxId);
+        } catch (MailboxNameException e) {
+            notUpdated(mailboxId, "invalidArguments", 
+                    e.getMessage(), responseBuilder);
+        } catch (MailboxNotFoundException e) {
+            notUpdated(mailboxId, "notFound", 
+                    String.format("The mailbox '%s' was not found", mailboxId), responseBuilder);
+        } catch (MailboxParentNotFoundException e) {
+            notUpdated(mailboxId, "notFound", 
+                    String.format("The parent mailbox '%s' was not found.", e.getParentId()), responseBuilder);
+        } catch (MailboxHasChildException e) {
+            notUpdated(mailboxId, "invalidArguments", 
+                    "Cannot update a parent mailbox.", responseBuilder);
+        } catch (MailboxExistsException e) {
+            notUpdated(mailboxId, "invalidArguments", 
+                    "Cannot rename a mailbox to an already existing mailbox.", responseBuilder);
+        } catch (MailboxException e) {
+            notUpdated(mailboxId, "anErrorOccurred", 
+                    "An error occurred when updating the mailbox", responseBuilder);
+        }
+    }
+
+    private Builder notUpdated(String mailboxId, String type, String message, Builder responseBuilder) {
+        return responseBuilder.notUpdated(mailboxId, SetError.builder()
+                .type(type)
+                .description(message)
+                .build());
+    }
+
+    private Mailbox getMailbox(String mailboxId, MailboxSession mailboxSession) throws MailboxNotFoundException {
+        return mailboxUtils.mailboxFromMailboxId(mailboxId, mailboxSession)
+                .orElseThrow(() -> new MailboxNotFoundException(mailboxId));
+    }
+
+    private void validateMailboxName(MailboxUpdateRequest updateRequest, MailboxSession mailboxSession) throws MailboxNameException {
+        char pathDelimiter = mailboxSession.getPathDelimiter();
+        if (updateRequest.getName()
+                .filter(name -> name.contains(String.valueOf(pathDelimiter)))
+                .isPresent()) {
+            throw new MailboxNameException(String.format("The mailbox '%s' contains an illegal character: '%c'", updateRequest.getName().get(), pathDelimiter));
+        }
+    }
+
+    private void validateParent(Mailbox mailbox, MailboxUpdateRequest updateRequest, MailboxSession mailboxSession) throws MailboxException, MailboxHasChildException {
+
+        if (isParentIdInRequest(updateRequest)) {
+            String newParentId = updateRequest.getParentId().get();
+            mailboxUtils.mailboxPathFromMailboxId(newParentId, mailboxSession)
+                    .orElseThrow(() -> new MailboxParentNotFoundException(newParentId));
+            if (mustChangeParent(mailbox.getParentId(), newParentId) && mailboxUtils.hasChildren(mailbox.getId(), mailboxSession)) {
+                throw new MailboxHasChildException();
+            }
+        }
+    }
+
+    private boolean isParentIdInRequest(MailboxUpdateRequest updateRequest) {
+        return updateRequest.getParentId() != null
+                && updateRequest.getParentId().isPresent();
+    }
+
+    private boolean mustChangeParent(Optional<String> currentParentId, String newParentId) {
+        return currentParentId
+                .map(x -> ! x.equals(newParentId))
+                .orElse(true);
+    }
+
+    private void updateMailbox(Mailbox mailbox, MailboxUpdateRequest updateRequest, MailboxSession mailboxSession) throws MailboxException {
+        MailboxPath originMailboxPath = mailboxUtils.getMailboxPath(mailbox, mailboxSession);
+        MailboxPath destinationMailboxPath = computeNewMailboxPath(mailbox, originMailboxPath, updateRequest, mailboxSession);
+        if (!originMailboxPath.equals(destinationMailboxPath)) {
+            mailboxManager.renameMailbox(originMailboxPath, destinationMailboxPath, mailboxSession);
+        }
+    }
+
+    private MailboxPath computeNewMailboxPath(Mailbox mailbox, MailboxPath originMailboxPath, MailboxUpdateRequest updateRequest, MailboxSession mailboxSession) {
+        Optional<String> parentId = updateRequest.getParentId();
+        if (parentId == null) {
+            return new MailboxPath(mailboxSession.getPersonalSpace(), 
+                    mailboxSession.getUser().getUserName(), 
+                    updateRequest.getName().orElse(mailbox.getName()));
+        }
+
+        MailboxPath modifiedMailboxPath = updateRequest.getName()
+                .map(newName -> computeMailboxPathWithNewName(originMailboxPath, newName))
+                .orElse(originMailboxPath);
+        return parentId
+                .map(parentMailboxId -> computeMailboxPathWithNewParentId(modifiedMailboxPath, parentMailboxId, mailboxSession))
+                .orElse(modifiedMailboxPath);
+    }
+
+    private MailboxPath computeMailboxPathWithNewName(MailboxPath originMailboxPath, String newName) {
+        return new MailboxPath(originMailboxPath, newName);
+    }
+
+    private MailboxPath computeMailboxPathWithNewParentId(MailboxPath originMailboxPath, String parentMailboxId, MailboxSession mailboxSession) {
+        Optional<MailboxPath> newParentMailboxPath = mailboxUtils.mailboxPathFromMailboxId(parentMailboxId, mailboxSession);
+        String lastName = getCurrentMailboxName(originMailboxPath, mailboxSession);
+        return new MailboxPath(originMailboxPath, newParentMailboxPath.get().getName() + mailboxSession.getPathDelimiter() + lastName);
+    }
+
+    private String getCurrentMailboxName(MailboxPath originMailboxPath, MailboxSession mailboxSession) {
+        return Iterables.getLast(
+                Splitter.on(mailboxSession.getPathDelimiter())
+                    .splitToList(originMailboxPath.getName()));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesRequest.java
index 96b77f5..a89031e 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesRequest.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesRequest.java
@@ -24,8 +24,8 @@ import java.util.Map;
 
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.james.jmap.methods.JmapRequest;
-import org.apache.james.jmap.model.mailbox.Mailbox;
-import org.apache.james.jmap.model.mailbox.MailboxRequest;
+import org.apache.james.jmap.model.mailbox.MailboxCreateRequest;
+import org.apache.james.jmap.model.mailbox.MailboxUpdateRequest;
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
@@ -43,20 +43,22 @@ public class SetMailboxesRequest implements JmapRequest {
     @JsonPOJOBuilder(withPrefix = "")
     public static class Builder {
 
-        private final ImmutableMap.Builder<MailboxCreationId, MailboxRequest> create;
+        private final ImmutableMap.Builder<MailboxCreationId, MailboxCreateRequest> create;
+        private final ImmutableMap.Builder<String, MailboxUpdateRequest> update;
         private final ImmutableList.Builder<String> destroy;
 
         private Builder() {
             create = ImmutableMap.builder();
+            update = ImmutableMap.builder();
             destroy = ImmutableList.builder();
         }
 
-        public Builder create(Map<MailboxCreationId, MailboxRequest> requests) {
+        public Builder create(Map<MailboxCreationId, MailboxCreateRequest> requests) {
             create.putAll(requests);
             return this;
         }
 
-        public Builder create(MailboxCreationId creationId, MailboxRequest mailbox) {
+        public Builder create(MailboxCreationId creationId, MailboxCreateRequest mailbox) {
             create.put(creationId, mailbox);
             return this;
         }
@@ -69,8 +71,14 @@ public class SetMailboxesRequest implements JmapRequest {
             throw new NotImplementedException();
         }
         
-        public Builder update(Map<String, Mailbox> updates) {
-            throw new NotImplementedException();
+        public Builder update(String mailboxId, MailboxUpdateRequest mailboxUpdateRequest) {
+            update.put(mailboxId, mailboxUpdateRequest);
+            return this;
+        }
+        
+        public Builder update(Map<String, MailboxUpdateRequest> updates) {
+            update.putAll(updates);
+            return this;
         }
         
         public Builder destroy(List<String> deletions) {
@@ -79,23 +87,29 @@ public class SetMailboxesRequest implements JmapRequest {
         }
 
         public SetMailboxesRequest build() {
-            return new SetMailboxesRequest(create.build(), destroy.build());
+            return new SetMailboxesRequest(create.build(), update.build(), destroy.build());
         }
     }
 
-    private final ImmutableMap<MailboxCreationId, MailboxRequest> create;
+    private final ImmutableMap<MailboxCreationId, MailboxCreateRequest> create;
+    private final ImmutableMap<String, MailboxUpdateRequest> update;
     private final ImmutableList<String> destroy;
 
     @VisibleForTesting
-    SetMailboxesRequest(ImmutableMap<MailboxCreationId, MailboxRequest> create, ImmutableList<String> destroy) {
+    SetMailboxesRequest(ImmutableMap<MailboxCreationId, MailboxCreateRequest> create, ImmutableMap<String,MailboxUpdateRequest> update, ImmutableList<String> destroy) {
         this.create = create;
+        this.update = update;
         this.destroy = destroy;
     }
 
-    public ImmutableMap<MailboxCreationId, MailboxRequest> getCreate() {
+    public ImmutableMap<MailboxCreationId, MailboxCreateRequest> getCreate() {
         return create;
     }
 
+    public ImmutableMap<String, MailboxUpdateRequest> getUpdate() {
+        return update;
+    }
+
     public ImmutableList<String> getDestroy() {
         return destroy;
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesResponse.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesResponse.java
index 6de0f77..321aba9 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesResponse.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetMailboxesResponse.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.jmap.model;
 
+import java.util.List;
 import java.util.Map;
 
 import org.apache.james.jmap.methods.Method;
@@ -37,14 +38,18 @@ public class SetMailboxesResponse implements Method.Response {
     public static class Builder {
 
         private final ImmutableMap.Builder<MailboxCreationId, Mailbox> created;
-        private final ImmutableMap.Builder<MailboxCreationId, SetError> notCreated;
+        private final ImmutableList.Builder<String> updated;
         private final ImmutableList.Builder<String> destroyed;
+        private final ImmutableMap.Builder<MailboxCreationId, SetError> notCreated;
+        private final ImmutableMap.Builder<String, SetError> notUpdated;
         private final ImmutableMap.Builder<String, SetError> notDestroyed;
 
         private Builder() {
             created = ImmutableMap.builder();
-            notCreated = ImmutableMap.builder();
+            updated = ImmutableList.builder();
             destroyed = ImmutableList.builder();
+            notCreated = ImmutableMap.builder();
+            notUpdated = ImmutableMap.builder();
             notDestroyed = ImmutableMap.builder();
         }
 
@@ -58,6 +63,26 @@ public class SetMailboxesResponse implements Method.Response {
             return this;
         }
 
+        public Builder updated(String mailboxId) {
+            updated.add(mailboxId);
+            return this;
+        }
+        
+        public Builder updated(List<String> mailboxIds) {
+            updated.addAll(mailboxIds);
+            return this;
+        }
+        
+        public Builder destroyed(String mailboxId) {
+            destroyed.add(mailboxId);
+            return this;
+        }
+        
+        public Builder destroyed(ImmutableList<String> destroyed) {
+            this.destroyed.addAll(destroyed);
+            return this;
+        }
+        
         public Builder notCreated(Map<MailboxCreationId, SetError> notCreated) {
             this.notCreated.putAll(notCreated);
             return this;
@@ -67,14 +92,14 @@ public class SetMailboxesResponse implements Method.Response {
             this.notCreated.put(mailboxCreationId, setError);
             return this;
         }
-
-        public Builder destroyed(String mailboxId) {
-            destroyed.add(mailboxId);
+        
+        public Builder notUpdated(String mailboxId, SetError setError) {
+            notUpdated.put(mailboxId, setError);
             return this;
         }
-
-        public Builder destroyed(ImmutableList<String> destroyed) {
-            this.destroyed.addAll(destroyed);
+        
+        public Builder notUpdated(Map<String, SetError> notUpdated) {
+            this.notUpdated.putAll(notUpdated);
             return this;
         }
 
@@ -89,19 +114,25 @@ public class SetMailboxesResponse implements Method.Response {
         }
 
         public SetMailboxesResponse build() {
-            return new SetMailboxesResponse(created.build(), notCreated.build(), destroyed.build(), notDestroyed.build());
+            return new SetMailboxesResponse(created.build(), updated.build(), destroyed.build(), notCreated.build(), notUpdated.build(), notDestroyed.build());
         }
     }
 
     private final ImmutableMap<MailboxCreationId, Mailbox> created;
-    private final ImmutableMap<MailboxCreationId, SetError> notCreated;
+    private final ImmutableList<String> updated;
     private final ImmutableList<String> destroyed;
+    private final ImmutableMap<MailboxCreationId, SetError> notCreated;
+    private final ImmutableMap<String, SetError> notUpdated;
     private final ImmutableMap<String, SetError> notDestroyed;
 
-    @VisibleForTesting SetMailboxesResponse(ImmutableMap<MailboxCreationId, Mailbox> created, ImmutableMap<MailboxCreationId, SetError> notCreated, ImmutableList<String> destroyed, ImmutableMap<String, SetError> notDestroyed) {
+    @VisibleForTesting
+    SetMailboxesResponse(ImmutableMap<MailboxCreationId, Mailbox> created, ImmutableList<String> updated, ImmutableList<String> destroyed,
+            ImmutableMap<MailboxCreationId, SetError> notCreated, ImmutableMap<String, SetError> notUpdated, ImmutableMap<String, SetError> notDestroyed) {
         this.created = created;
-        this.notCreated = notCreated;
+        this.updated = updated;
         this.destroyed = destroyed;
+        this.notCreated = notCreated;
+        this.notUpdated = notUpdated;
         this.notDestroyed = notDestroyed;
     }
 
@@ -109,14 +140,22 @@ public class SetMailboxesResponse implements Method.Response {
         return created;
     }
 
-    public Map<MailboxCreationId, SetError> getNotCreated() {
-        return notCreated;
+    public ImmutableList<String> getUpdated() {
+        return updated;
     }
 
     public ImmutableList<String> getDestroyed() {
         return destroyed;
     }
+    
+    public Map<MailboxCreationId, SetError> getNotCreated() {
+        return notCreated;
+    }
 
+    public ImmutableMap<String, SetError> getNotUpdated() {
+        return notUpdated;
+    }
+    
     public ImmutableMap<String, SetError> getNotDestroyed() {
         return notDestroyed;
     }
@@ -124,8 +163,10 @@ public class SetMailboxesResponse implements Method.Response {
     public SetMailboxesResponse.Builder mergeInto(SetMailboxesResponse.Builder responseBuilder) {
         return responseBuilder
             .created(getCreated())
-            .notCreated(getNotCreated())
+            .updated(getUpdated())
             .destroyed(getDestroyed())
+            .notCreated(getNotCreated())
+            .notUpdated(getNotUpdated())
             .notDestroyed(getNotDestroyed());
     }
 
@@ -139,8 +180,10 @@ public class SetMailboxesResponse implements Method.Response {
         if (obj instanceof SetMailboxesResponse) {
             SetMailboxesResponse other = (SetMailboxesResponse) obj;
             return Objects.equal(this.created, other.created)
-                && Objects.equal(this.notCreated, other.notCreated)
+                && Objects.equal(this.updated, other.updated)
                 && Objects.equal(this.destroyed, other.destroyed)
+                && Objects.equal(this.notCreated, other.notCreated)
+                && Objects.equal(this.notUpdated, other.notUpdated)
                 && Objects.equal(this.notDestroyed, other.notDestroyed);
         }
         return false;

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxCreateRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxCreateRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxCreateRequest.java
new file mode 100644
index 0000000..cd1c89f
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxCreateRequest.java
@@ -0,0 +1,157 @@
+/****************************************************************
+O * 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.mailbox;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import org.apache.commons.lang.NotImplementedException;
+
+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.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+@JsonDeserialize(builder = MailboxCreateRequest.Builder.class)
+public class MailboxCreateRequest {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    @JsonPOJOBuilder(withPrefix = "")
+    public static class Builder {
+
+        private Optional<String> id;
+        private String name;
+        private Optional<String> parentId;
+        private Optional<Role> role;
+        private Optional<SortOrder> sortOrder;
+
+        private Builder() {
+            id = Optional.empty();
+            role = Optional.empty();
+            sortOrder = Optional.empty();
+            parentId = Optional.empty();
+        }
+
+        public Builder id(String id) {
+            Preconditions.checkNotNull(id);
+            this.id = Optional.of(id);
+            return this;
+        }
+
+        public Builder name(String name) {
+            Preconditions.checkNotNull(name);
+            this.name = name;
+            return this;
+        }
+
+        public Builder parentId(String parentId) {
+            Preconditions.checkNotNull(parentId);
+            this.parentId = Optional.of(parentId);
+            return this;
+        }
+
+        public Builder role(Role role) {
+            Preconditions.checkNotNull(role);
+            throw new NotImplementedException();
+        }
+
+        public Builder sortOrder(SortOrder sortOrder) {
+            Preconditions.checkNotNull(sortOrder);
+            throw new NotImplementedException();
+        }
+
+
+        public MailboxCreateRequest build() {
+            Preconditions.checkState(!Strings.isNullOrEmpty(name), "'name' is mandatory");
+            return new MailboxCreateRequest(id, name, parentId, role, sortOrder);
+        }
+    }
+
+    private final Optional<String> id;
+    private final String name;
+    private final Optional<String> parentId;
+    private final Optional<Role> role;
+    private final Optional<SortOrder> sortOrder;
+
+    @VisibleForTesting
+    MailboxCreateRequest(Optional<String> id, String name, Optional<String> parentId, Optional<Role> role, Optional<SortOrder> sortOrder) {
+
+        this.id = id;
+        this.name = name;
+        this.parentId = parentId;
+        this.role = role;
+        this.sortOrder = sortOrder;
+    }
+
+    public Optional<String> getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Optional<String> getParentId() {
+        return parentId;
+    }
+
+    public Optional<Role> getRole() {
+        return role;
+    }
+
+    public Optional<SortOrder> getSortOrder() {
+        return sortOrder;
+    }
+
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (obj instanceof MailboxCreateRequest) {
+            MailboxCreateRequest other = (MailboxCreateRequest) obj;
+            return Objects.equals(this.id, other.id)
+                && Objects.equals(this.name, other.name)
+                && Objects.equals(this.parentId, other.parentId)
+                && Objects.equals(this.role, other.role)
+                && Objects.equals(this.sortOrder, other.sortOrder);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(id, name, parentId, role, sortOrder);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("id", id)
+                .add("name", name)
+                .add("parentId", parentId)
+                .add("role", role)
+                .add("sortOrder", sortOrder)
+                .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxRequest.java
deleted file mode 100644
index bb8cff3..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxRequest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/****************************************************************
-O * 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.mailbox;
-
-import java.util.Objects;
-import java.util.Optional;
-
-import org.apache.commons.lang.NotImplementedException;
-
-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.MoreObjects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-
-@JsonDeserialize(builder = MailboxRequest.Builder.class)
-public class MailboxRequest {
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    @JsonPOJOBuilder(withPrefix = "")
-    public static class Builder {
-
-        private Optional<String> id;
-        private String name;
-        private Optional<String> parentId;
-        private Optional<Role> role;
-        private Optional<SortOrder> sortOrder;
-
-        private Builder() {
-            id = Optional.empty();
-            role = Optional.empty();
-            sortOrder = Optional.empty();
-            parentId = Optional.empty();
-        }
-
-        public Builder id(String id) {
-            Preconditions.checkNotNull(id);
-            this.id = Optional.of(id);
-            return this;
-        }
-
-        public Builder name(String name) {
-            Preconditions.checkNotNull(name);
-            this.name = name;
-            return this;
-        }
-
-        public Builder parentId(String parentId) {
-            Preconditions.checkNotNull(parentId);
-            this.parentId = Optional.of(parentId);
-            return this;
-        }
-
-        public Builder role(Role role) {
-            Preconditions.checkNotNull(role);
-            throw new NotImplementedException();
-        }
-
-        public Builder sortOrder(SortOrder sortOrder) {
-            Preconditions.checkNotNull(sortOrder);
-            throw new NotImplementedException();
-        }
-
-
-        public MailboxRequest build() {
-            Preconditions.checkState(!Strings.isNullOrEmpty(name), "'name' is mandatory");
-            return new MailboxRequest(id, name, parentId, role, sortOrder);
-        }
-    }
-
-    private final Optional<String> id;
-    private final String name;
-    private final Optional<String> parentId;
-    private final Optional<Role> role;
-    private final Optional<SortOrder> sortOrder;
-
-    @VisibleForTesting
-    MailboxRequest(Optional<String> id, String name, Optional<String> parentId, Optional<Role> role, Optional<SortOrder> sortOrder) {
-
-        this.id = id;
-        this.name = name;
-        this.parentId = parentId;
-        this.role = role;
-        this.sortOrder = sortOrder;
-    }
-
-    public Optional<String> getId() {
-        return id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public Optional<String> getParentId() {
-        return parentId;
-    }
-
-    public Optional<Role> getRole() {
-        return role;
-    }
-
-    public Optional<SortOrder> getSortOrder() {
-        return sortOrder;
-    }
-
-
-    @Override
-    public final boolean equals(Object obj) {
-        if (obj instanceof MailboxRequest) {
-            MailboxRequest other = (MailboxRequest) obj;
-            return Objects.equals(this.id, other.id)
-                && Objects.equals(this.name, other.name)
-                && Objects.equals(this.parentId, other.parentId)
-                && Objects.equals(this.role, other.role)
-                && Objects.equals(this.sortOrder, other.sortOrder);
-        }
-        return false;
-    }
-
-    @Override
-    public final int hashCode() {
-        return Objects.hash(id, name, parentId, role, sortOrder);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .add("id", id)
-                .add("name", name)
-                .add("parentId", parentId)
-                .add("role", role)
-                .add("sortOrder", sortOrder)
-                .toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f185db6f/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxUpdateRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxUpdateRequest.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxUpdateRequest.java
new file mode 100644
index 0000000..ebffb49
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/MailboxUpdateRequest.java
@@ -0,0 +1,145 @@
+/****************************************************************
+O * 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.mailbox;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.mailbox.exception.MailboxException;
+
+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.MoreObjects;
+import com.google.common.base.Preconditions;
+
+@JsonDeserialize(builder = MailboxUpdateRequest.Builder.class)
+public class MailboxUpdateRequest {
+
+    public static Builder builder() throws MailboxException {
+        return new Builder();
+    }
+
+    @JsonPOJOBuilder(withPrefix = "")
+    public static class Builder {
+
+        private Optional<String> name;
+        private Optional<String> parentId;
+        private Optional<Role> role;
+        private Optional<SortOrder> sortOrder;
+
+        private Builder() {
+            name = Optional.empty();
+            role = Optional.empty();
+            sortOrder = Optional.empty();
+            parentId = Optional.empty();
+        }
+
+        public Builder name(String name) throws MailboxException {
+            Preconditions.checkNotNull(name);
+            Preconditions.checkArgument(!name.isEmpty());
+            this.name = Optional.of(name);
+            return this;
+        }
+
+        public Builder parentId(String parentId) {
+            if (parentId == null) {
+                this.parentId = null;
+            } else {
+                this.parentId = Optional.of(parentId);
+            }
+            return this;
+        }
+
+        public Builder role(Role role) {
+            Preconditions.checkNotNull(role);
+            throw new NotImplementedException();
+        }
+
+        public Builder sortOrder(SortOrder sortOrder) {
+            Preconditions.checkNotNull(sortOrder);
+            throw new NotImplementedException();
+        }
+
+
+        public MailboxUpdateRequest build() {
+            return new MailboxUpdateRequest(name, parentId, role, sortOrder);
+        }
+    }
+
+    private final Optional<String> name;
+    private final Optional<String> parentId;
+    private final Optional<Role> role;
+    private final Optional<SortOrder> sortOrder;
+
+    @VisibleForTesting
+    MailboxUpdateRequest(Optional<String> name, Optional<String> parentId, Optional<Role> role, Optional<SortOrder> sortOrder) {
+
+        this.name = name;
+        this.parentId = parentId;
+        this.role = role;
+        this.sortOrder = sortOrder;
+    }
+
+    public Optional<String> getName() {
+        return name;
+    }
+
+    public Optional<String> getParentId() {
+        return parentId;
+    }
+
+    public Optional<Role> getRole() {
+        return role;
+    }
+
+    public Optional<SortOrder> getSortOrder() {
+        return sortOrder;
+    }
+
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (obj instanceof MailboxUpdateRequest) {
+            MailboxUpdateRequest other = (MailboxUpdateRequest) obj;
+            return Objects.equals(this.name, other.name)
+                && Objects.equals(this.parentId, other.parentId)
+                && Objects.equals(this.role, other.role)
+                && Objects.equals(this.sortOrder, other.sortOrder);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(name, parentId, role, sortOrder);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("name", name)
+                .add("parentId", parentId)
+                .add("role", role)
+                .add("sortOrder", sortOrder)
+                .toString();
+    }
+}


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