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 <[email protected]> Authored: Thu Mar 31 14:45:10 2016 +0200 Committer: Laura Royet <[email protected]> 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: [email protected] For additional commands, e-mail: [email protected]
