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/04 16:28:08 UTC

[1/4] james-project git commit: JAMES-1712 Introduce MailboxUtils in order to share common MailboxManager usage

Repository: james-project
Updated Branches:
  refs/heads/master f9f6e8499 -> 68ab61763


JAMES-1712 Introduce MailboxUtils in order to share common MailboxManager usage


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

Branch: refs/heads/master
Commit: 166ee8f36d9f1e9aaec1a6a570e23163ec0dbfa3
Parents: 64ff43e
Author: Antoine Duprat <an...@gmail.com>
Authored: Thu Mar 31 11:22:08 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Mon Apr 4 16:27:11 2016 +0200

----------------------------------------------------------------------
 mailbox/api/pom.xml                             |  16 ++
 mailbox/memory/pom.xml                          |  16 ++
 server/pom.xml                                  |  13 ++
 server/protocols/jmap/pom.xml                   |  12 ++
 .../james/jmap/methods/GetMailboxesMethod.java  |  49 +-----
 .../apache/james/jmap/utils/MailboxUtils.java   | 119 ++++++++++++++
 .../jmap/methods/GetMailboxesMethodTest.java    |   7 +-
 .../james/jmap/utils/MailboxUtilsTest.java      | 164 +++++++++++++++++++
 8 files changed, 350 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/mailbox/api/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/api/pom.xml b/mailbox/api/pom.xml
index 964bf82..c8a2d9e 100644
--- a/mailbox/api/pom.xml
+++ b/mailbox/api/pom.xml
@@ -76,4 +76,20 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 </project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/mailbox/memory/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/memory/pom.xml b/mailbox/memory/pom.xml
index 4a9ad04..a08a5d1 100644
--- a/mailbox/memory/pom.xml
+++ b/mailbox/memory/pom.xml
@@ -81,4 +81,20 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 </project>

http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 5a4e8e6..4b4863f 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -604,6 +604,13 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.james</groupId>
+                <artifactId>apache-james-mailbox-memory</artifactId>
+                <version>${mailbox.version}</version>
+                <type>test-jar</type>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.james</groupId>
                 <artifactId>apache-james-mailbox-cassandra</artifactId>
                 <version>${mailbox.version}</version>
             </dependency>
@@ -625,6 +632,12 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.james</groupId>
+                <artifactId>apache-james-mailbox-api</artifactId>
+                <version>${mailbox.version}</version>
+                <type>test-jar</type>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.james</groupId>
                 <artifactId>apache-james-mailbox-elasticsearch</artifactId>
                 <version>${mailbox.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/server/protocols/jmap/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml
index 296d752..e088819 100644
--- a/server/protocols/jmap/pom.xml
+++ b/server/protocols/jmap/pom.xml
@@ -158,11 +158,23 @@
                 </dependency>
                 <dependency>
                     <groupId>org.apache.james</groupId>
+                    <artifactId>apache-james-mailbox-api</artifactId>
+                    <scope>test</scope>
+                    <type>test-jar</type>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
                     <artifactId>apache-james-mailbox-memory</artifactId>
                     <scope>test</scope>
                 </dependency>
                 <dependency>
                     <groupId>org.apache.james</groupId>
+                    <artifactId>apache-james-mailbox-memory</artifactId>
+                    <scope>test</scope>
+                    <type>test-jar</type>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
                     <artifactId>apache-james-mailbox-store</artifactId>
                 </dependency>
                 <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java
index 53a22e2..d5f63b6 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/GetMailboxesMethod.java
@@ -32,20 +32,13 @@ import org.apache.james.jmap.model.GetMailboxesRequest;
 import org.apache.james.jmap.model.GetMailboxesResponse;
 import org.apache.james.jmap.model.MailboxProperty;
 import org.apache.james.jmap.model.mailbox.Mailbox;
-import org.apache.james.jmap.model.mailbox.Role;
-import org.apache.james.jmap.model.mailbox.SortOrder;
+import org.apache.james.jmap.utils.MailboxUtils;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.MessageManager;
-import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxMetaData;
-import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MailboxQuery;
-import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
 import org.apache.james.mailbox.store.mail.model.MailboxId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
@@ -56,18 +49,16 @@ import com.google.common.collect.Sets;
 
 public class GetMailboxesMethod<Id extends MailboxId> implements Method {
 
-    private static final boolean DONT_RESET_RECENT = false;
-    private static final Logger LOGGER = LoggerFactory.getLogger(GetMailboxesMethod.class);
     private static final Method.Request.Name METHOD_NAME = Method.Request.name("getMailboxes");
     private static final Method.Response.Name RESPONSE_NAME = Method.Response.name("mailboxes");
 
     private final MailboxManager mailboxManager; 
-    private final MailboxMapperFactory<Id> mailboxMapperFactory;
+    private final MailboxUtils<Id> mailboxUtils;
 
     @Inject
-    @VisibleForTesting public GetMailboxesMethod(MailboxManager mailboxManager, MailboxMapperFactory<Id> mailboxMapperFactory) {
+    @VisibleForTesting public GetMailboxesMethod(MailboxManager mailboxManager, MailboxUtils<Id> mailboxUtils) {
         this.mailboxManager = mailboxManager;
-        this.mailboxMapperFactory = mailboxMapperFactory;
+        this.mailboxUtils = mailboxUtils;
     }
 
     @Override
@@ -101,7 +92,7 @@ public class GetMailboxesMethod<Id extends MailboxId> implements Method {
             retrieveUserMailboxes(mailboxSession)
                 .stream()
                 .map(MailboxMetaData::getPath)
-                .map(mailboxPath -> mailboxFromMailboxPath(mailboxPath, mailboxSession))
+                .map(mailboxPath -> mailboxUtils.mailboxFromMailboxPath(mailboxPath, mailboxSession))
                 .filter(Optional::isPresent)
                 .map(Optional::get)
                 .filter(filterMailboxesById(mailboxesRequest.getIds()))
@@ -123,34 +114,4 @@ public class GetMailboxesMethod<Id extends MailboxId> implements Method {
                 session);
     }
 
-    private Optional<Mailbox> mailboxFromMailboxPath(MailboxPath mailboxPath, MailboxSession mailboxSession) {
-        try {
-            Optional<Role> role = Role.from(mailboxPath.getName());
-            MessageManager.MetaData mailboxMetaData = getMailboxMetaData(mailboxPath, mailboxSession);
-            return Optional.ofNullable(Mailbox.builder()
-                    .id(getMailboxId(mailboxPath, mailboxSession))
-                    .name(mailboxPath.getName())
-                    .role(role)
-                    .unreadMessages(mailboxMetaData.getUnseenCount())
-                    .totalMessages(mailboxMetaData.getMessageCount())
-                    .sortOrder(SortOrder.getSortOrder(role))
-                    .build());
-        } catch (MailboxException e) {
-            LOGGER.warn("Cannot find mailbox for :" + mailboxPath.getName(), e);
-            return Optional.empty();
-        }
-    }
-
-    private String getMailboxId(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException {
-        return mailboxMapperFactory.getMailboxMapper(mailboxSession)
-                .findMailboxByPath(mailboxPath)
-                .getMailboxId()
-                .serialize();
-    }
-
-    private MessageManager.MetaData getMailboxMetaData(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException {
-        return mailboxManager.getMailbox(mailboxPath, mailboxSession)
-                .getMetaData(DONT_RESET_RECENT, mailboxSession, FetchGroup.UNSEEN_COUNT);
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxUtils.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxUtils.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxUtils.java
new file mode 100644
index 0000000..b8128e3
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxUtils.java
@@ -0,0 +1,119 @@
+/****************************************************************
+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.utils;
+
+import java.util.List;
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.model.mailbox.Mailbox;
+import org.apache.james.jmap.model.mailbox.Role;
+import org.apache.james.jmap.model.mailbox.SortOrder;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
+
+public class MailboxUtils<Id extends MailboxId> {
+
+    private static final boolean DONT_RESET_RECENT = false;
+    private static final Logger LOGGER = LoggerFactory.getLogger(MailboxUtils.class);
+
+    private final MailboxManager mailboxManager;
+    private final MailboxMapperFactory<Id> mailboxMapperFactory;
+
+    @Inject
+    @VisibleForTesting
+    public MailboxUtils(MailboxManager mailboxManager, MailboxMapperFactory<Id> mailboxMapperFactory) {
+        this.mailboxManager = mailboxManager;
+        this.mailboxMapperFactory = mailboxMapperFactory;
+    }
+
+    public Optional<Mailbox> mailboxFromMailboxPath(MailboxPath mailboxPath, MailboxSession mailboxSession) {
+        try {
+            Optional<Role> role = Role.from(mailboxPath.getName());
+            MessageManager.MetaData mailboxMetaData = getMailboxMetaData(mailboxPath, mailboxSession);
+            String mailboxId = getMailboxId(mailboxPath, mailboxSession);
+            return Optional.ofNullable(Mailbox.builder()
+                    .id(mailboxId)
+                    .name(getName(mailboxPath, mailboxSession))
+                    .parentId(getParentIdFromMailboxPath(mailboxPath, mailboxSession))
+                    .role(role)
+                    .unreadMessages(mailboxMetaData.getUnseenCount())
+                    .totalMessages(mailboxMetaData.getMessageCount())
+                    .sortOrder(SortOrder.getSortOrder(role))
+                    .build());
+        } catch (MailboxException e) {
+            LOGGER.warn("Cannot find mailbox for :" + mailboxPath.getName(), e);
+            return Optional.empty();
+        }
+    }
+
+    private String getMailboxId(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException {
+        return mailboxMapperFactory.getMailboxMapper(mailboxSession)
+                .findMailboxByPath(mailboxPath)
+                .getMailboxId()
+                .serialize();
+    }
+
+    private MessageManager.MetaData getMailboxMetaData(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException {
+        return mailboxManager.getMailbox(mailboxPath, mailboxSession)
+                .getMetaData(DONT_RESET_RECENT, mailboxSession, MessageManager.MetaData.FetchGroup.UNSEEN_COUNT);
+    }
+
+    @VisibleForTesting String getName(MailboxPath mailboxPath, MailboxSession mailboxSession) {
+        String name = mailboxPath.getName();
+        if (name.contains(String.valueOf(mailboxSession.getPathDelimiter()))) {
+            List<String> levels = Splitter.on(mailboxSession.getPathDelimiter()).splitToList(name);
+            return levels.get(levels.size() - 1);
+        }
+        return name;
+    }
+
+    public Optional<String> getMailboxNameFromId(String mailboxId, MailboxSession mailboxSession) throws MailboxException {
+        return getMailboxFromId(mailboxId, mailboxSession)
+                .map(org.apache.james.mailbox.store.mail.model.Mailbox::getName);
+    }
+
+    private Optional<org.apache.james.mailbox.store.mail.model.Mailbox<Id>> getMailboxFromId(String mailboxId, MailboxSession mailboxSession) throws MailboxException {
+        return mailboxMapperFactory.getMailboxMapper(mailboxSession)
+                .list().stream()
+                .filter(mailbox -> mailbox.getMailboxId().serialize().equals(mailboxId))
+                .findFirst();
+    }
+
+    @VisibleForTesting String getParentIdFromMailboxPath(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException {
+        List<MailboxPath> levels = mailboxPath.getHierarchyLevels(mailboxSession.getPathDelimiter());
+        if (levels.size() <= 1) {
+            return null;
+        }
+        MailboxPath parent = levels.get(levels.size() - 2);
+        return getMailboxId(parent, mailboxSession);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java
index 08f8ef3..fbbcaf1 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/GetMailboxesMethodTest.java
@@ -37,6 +37,7 @@ import org.apache.james.jmap.model.GetMailboxesResponse;
 import org.apache.james.jmap.model.mailbox.Mailbox;
 import org.apache.james.jmap.model.mailbox.Role;
 import org.apache.james.jmap.model.mailbox.SortOrder;
+import org.apache.james.jmap.utils.MailboxUtils;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
@@ -69,6 +70,7 @@ public class GetMailboxesMethodTest {
     private GetMailboxesMethod<InMemoryId> getMailboxesMethod;
     private ClientId clientId;
     private InMemoryMailboxSessionMapperFactory mailboxMapperFactory;
+    private MailboxUtils<InMemoryId> mailboxUtils;
 
     @Before
     public void setup() throws Exception {
@@ -78,8 +80,9 @@ public class GetMailboxesMethodTest {
         GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver();
         mailboxManager = new StoreMailboxManager<>(mailboxMapperFactory, new MockAuthenticator(), aclResolver, groupMembershipResolver);
         mailboxManager.init();
+        mailboxUtils = new MailboxUtils<>(mailboxManager, mailboxMapperFactory);
 
-        getMailboxesMethod = new GetMailboxesMethod<>(mailboxManager, mailboxMapperFactory);
+        getMailboxesMethod = new GetMailboxesMethod<>(mailboxManager, mailboxUtils);
     }
 
     @Test
@@ -107,7 +110,7 @@ public class GetMailboxesMethodTest {
             .thenReturn(ImmutableList.of(new MailboxPath("namespace", "user", "name")));
         when(mockedMailboxManager.getMailbox(any(), any()))
             .thenThrow(new MailboxException());
-        GetMailboxesMethod<InMemoryId> testee = new GetMailboxesMethod<>(mockedMailboxManager, mailboxMapperFactory);
+        GetMailboxesMethod<InMemoryId> testee = new GetMailboxesMethod<>(mockedMailboxManager, mailboxUtils);
         
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();

http://git-wip-us.apache.org/repos/asf/james-project/blob/166ee8f3/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxUtilsTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxUtilsTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxUtilsTest.java
new file mode 100644
index 0000000..f6a4a89
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxUtilsTest.java
@@ -0,0 +1,164 @@
+/****************************************************************
+ * 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.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Optional;
+
+import org.apache.james.jmap.model.mailbox.Mailbox;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxSessionMapperFactory;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MailboxUtilsTest {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MailboxUtilsTest.class);
+
+    private MailboxManager mailboxManager;
+    private MailboxMapperFactory<InMemoryId> mailboxMapperFactory;
+    private MailboxSession mailboxSession;
+    private MailboxUtils<InMemoryId> sut;
+
+    @Before
+    public void setup() throws Exception {
+        InMemoryIntegrationResources inMemoryIntegrationResources = new InMemoryIntegrationResources();
+        mailboxManager = inMemoryIntegrationResources.createMailboxManager(inMemoryIntegrationResources.createGroupMembershipResolver());
+        mailboxMapperFactory = new InMemoryMailboxSessionMapperFactory();
+        mailboxSession = mailboxManager.login("user@domain.org", "pass", LOGGER);
+        sut = new MailboxUtils<>(mailboxManager, mailboxMapperFactory);
+    }
+
+    @Test
+    public void mailboxFromMailboxPathShouldReturnNotEmptyWhenMailboxExists() throws Exception {
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", "mailbox");
+        mailboxManager.createMailbox(mailboxPath, mailboxSession);
+
+        Optional<Mailbox> optionalMailbox = sut.mailboxFromMailboxPath(mailboxPath, mailboxSession);
+        assertThat(optionalMailbox).isPresent();
+        Mailbox mailbox = optionalMailbox.get();
+        assertThat(mailbox.getId()).isNotEmpty();
+    }
+
+    @Test
+    public void mailboxFromMailboxPathShouldReturnEmptyWhenMailboxDoesntExist() throws Exception {
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", "mailbox");
+
+        Optional<Mailbox> optionalMailbox = sut.mailboxFromMailboxPath(mailboxPath, mailboxSession);
+        assertThat(optionalMailbox).isEmpty();
+    }
+
+    @Test
+    public void getNameShouldReturnMailboxNameWhenRootMailbox() throws Exception {
+        String expected = "mailbox";
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", expected);
+
+        String name = sut.getName(mailboxPath, mailboxSession);
+        assertThat(name).isEqualTo(expected);
+    }
+
+    @Test
+    public void getNameShouldReturnMailboxNameWhenChildMailbox() throws Exception {
+        String expected = "mailbox";
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", "inbox." + expected);
+
+        String name = sut.getName(mailboxPath, mailboxSession);
+        assertThat(name).isEqualTo(expected);
+    }
+
+    @Test
+    public void getNameShouldReturnMailboxNameWhenChildOfChildMailbox() throws Exception {
+        String expected = "mailbox";
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", "inbox.children." + expected);
+
+        String name = sut.getName(mailboxPath, mailboxSession);
+        assertThat(name).isEqualTo(expected);
+    }
+
+    @Test
+    public void getMailboxNameFromIdShouldReturnNotEmptyWhenMailboxExists() throws Exception {
+        String expected = "mailbox";
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", expected);
+        mailboxManager.createMailbox(mailboxPath, mailboxSession);
+        InMemoryId mailboxId = mailboxMapperFactory.getMailboxMapper(mailboxSession)
+            .findMailboxByPath(mailboxPath)
+            .getMailboxId();
+
+        Optional<String> optionalName = sut.getMailboxNameFromId(mailboxId.serialize(), mailboxSession);
+        assertThat(optionalName).isPresent();
+        String name = optionalName.get();
+        assertThat(name).isEqualTo(expected);
+    }
+
+    @Test
+    public void getMailboxNameFromIdShouldReturnEmptyWhenMailboxDoesntExist() throws Exception {
+        Optional<String> optionalName = sut.getMailboxNameFromId("unknown", mailboxSession);
+        assertThat(optionalName).isEmpty();
+    }
+
+    @Test
+    public void getParentIdFromMailboxPathShouldReturNullWhenRootMailbox() throws Exception {
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", "mailbox");
+        mailboxManager.createMailbox(mailboxPath, mailboxSession);
+
+        String id = sut.getParentIdFromMailboxPath(mailboxPath, mailboxSession);
+        assertThat(id).isNull();
+    }
+
+    @Test
+    public void getParentIdFromMailboxPathShouldReturnParentIdWhenChildMailbox() throws Exception {
+        MailboxPath parentMailboxPath = new MailboxPath("#private", "user", "inbox");
+        mailboxManager.createMailbox(parentMailboxPath, mailboxSession);
+        InMemoryId parentId = mailboxMapperFactory.getMailboxMapper(mailboxSession)
+                .findMailboxByPath(parentMailboxPath)
+                .getMailboxId();
+
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", "inbox.mailbox");
+        mailboxManager.createMailbox(mailboxPath, mailboxSession);
+
+        String id = sut.getParentIdFromMailboxPath(mailboxPath, mailboxSession);
+        assertThat(id).isEqualTo(parentId.serialize());
+    }
+
+    @Test
+    public void getParentIdFromMailboxPathShouldReturnParentIdWhenChildOfChildMailbox() throws Exception {
+        MailboxPath mailboxPath = new MailboxPath("#private", "user", "inbox.children.mailbox");
+        mailboxManager.createMailbox(new MailboxPath("#private", "user", "inbox"), mailboxSession);
+
+        MailboxPath parentMailboxPath = new MailboxPath("#private", "user", "inbox.children");
+        mailboxManager.createMailbox(parentMailboxPath, mailboxSession);
+        InMemoryId parentId = mailboxMapperFactory.getMailboxMapper(mailboxSession)
+                .findMailboxByPath(parentMailboxPath)
+                .getMailboxId();
+
+        mailboxManager.createMailbox(mailboxPath, mailboxSession);
+
+        String id = sut.getParentIdFromMailboxPath(mailboxPath, mailboxSession);
+        assertThat(id).isEqualTo(parentId.serialize());
+    }
+}


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


[4/4] james-project git commit: JAMES-1712 Implement SetMailboxes: create

Posted by ad...@apache.org.
JAMES-1712 Implement SetMailboxes: create


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

Branch: refs/heads/master
Commit: 68ab61763d954d8b0d38015649c1fa63d8b0082d
Parents: 166ee8f
Author: Antoine Duprat <an...@gmail.com>
Authored: Thu Mar 31 11:22:28 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Mon Apr 4 16:27:12 2016 +0200

----------------------------------------------------------------------
 .../integration/SetMailboxesMethodTest.java     | 428 ++++++++++++++++++-
 .../jmap/exceptions/MailboxNameException.java   |  27 ++
 .../MailboxParentNotFoundException.java         |  34 ++
 .../methods/SetMailboxesCreationProcessor.java  | 124 +++++-
 .../james/jmap/methods/SetMailboxesMethod.java  |   2 +-
 .../jmap/methods/SetMailboxesProcessor.java     |   3 +-
 .../org/apache/james/jmap/model/SetError.java   |  17 +
 .../james/jmap/model/SetMailboxesResponse.java  |  25 +-
 .../jmap/utils/CollectionHierarchySorter.java   |  64 ---
 .../utils/SortingHierarchicalCollections.java   |  64 +++
 .../SetMailboxesCreationProcessorTest.java      |  71 +++
 .../jmap/methods/SetMailboxesMethodTest.java    |   2 +-
 .../utils/CollectionHierarchySorterTest.java    | 140 ------
 .../SortingHierarchicalCollectionsTest.java     | 140 ++++++
 14 files changed, 924 insertions(+), 217 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/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 162bb6e..176ec06 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
@@ -20,14 +20,22 @@
 package org.apache.james.jmap.methods.integration;
 
 import static com.jayway.restassured.RestAssured.given;
+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.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasItems;
 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.collection.IsMapWithSize.aMapWithSize;
 
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.jmap.JmapAuthentication;
 import org.apache.james.jmap.api.access.AccessToken;
+import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -56,6 +64,7 @@ public abstract class SetMailboxesMethodTest {
         jmapServer.start();
         RestAssured.port = jmapServer.getJmapPort();
         RestAssured.config = newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8));
+        RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
 
         username = "username@" + USERS_DOMAIN;
         String password = "password";
@@ -71,9 +80,69 @@ public abstract class SetMailboxesMethodTest {
     public void teardown() {
         jmapServer.stop();
     }
-    
+
     @Test
-    public void setMailboxesShouldCreateMailbox() throws Exception {
+    public void setMailboxesShouldErrorNotSupportedWhenRoleGiven() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"foo\"," +
+                "          \"role\" : \"Inbox\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#0\"" +
+                "  ]" +
+                "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("error"))
+            .body(ARGUMENTS + ".type", equalTo("Not yet implemented"));
+    }
+
+    @Test
+    public void setMailboxesShouldErrorNotSupportedWhenSortOrderGiven() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"foo\"," +
+                "          \"sortOrder\" : 11" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#0\"" +
+                "  ]" +
+                "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("error"))
+            .body(ARGUMENTS + ".type", equalTo("Not yet implemented"));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnCreatedMailbox() throws Exception {
         String requestBody =
             "[" +
                 "  [ \"setMailboxes\"," +
@@ -100,4 +169,359 @@ public abstract class SetMailboxesMethodTest {
             .body(NAME, equalTo("mailboxesSet"))
             .body(ARGUMENTS + ".created", hasKey("create-id01"));
     }
+
+    @Test
+    public void setMailboxesShouldCreateMailbox() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"foo\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#0\"" +
+                "  ]" +
+                "]";
+
+        with()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+            .then()
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(2))
+            .body(ARGUMENTS + ".list.name", hasItems("foo"));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnCreatedMailboxWhenChildOfInboxMailbox() throws Exception {
+        String inboxId =
+            with()
+                .accept(ContentType.JSON)
+                .contentType(ContentType.JSON)
+                .header("Authorization", this.accessToken.serialize())
+                .body("[[\"getMailboxes\", {}, \"#0\"]]")
+            .when()
+                .post("/jmap")
+            .then()
+                .extract()
+                .jsonPath()
+                .getString(ARGUMENTS + ".list[0].id");
+
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"foo\"," +
+                "          \"parentId\" : \"" + inboxId + "\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#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 + ".created", aMapWithSize(1))
+            .body(ARGUMENTS + ".created", hasEntry(equalTo("create-id01"), Matchers.allOf(
+                    hasEntry(equalTo("parentId"), equalTo(inboxId)),
+                    hasEntry(equalTo("name"), equalTo("foo")))));
+    }
+
+    @Test
+    public void setMailboxesShouldCreateMailboxWhenChildOfInboxMailbox() throws Exception {
+        String inboxId =
+            with()
+                .accept(ContentType.JSON)
+                .contentType(ContentType.JSON)
+                .header("Authorization", this.accessToken.serialize())
+                .body("[[\"getMailboxes\", {}, \"#0\"]]")
+            .when()
+                .post("/jmap")
+            .then()
+                .extract()
+                .jsonPath()
+                .getString(ARGUMENTS + ".list[0].id");
+
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"foo\"," +
+                "          \"parentId\" : \"" + inboxId + "\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#0\"" +
+                "  ]" +
+                "]";
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body(requestBody)
+        .when()
+            .post("/jmap");
+
+        given()
+            .accept(ContentType.JSON)
+            .contentType(ContentType.JSON)
+            .header("Authorization", this.accessToken.serialize())
+            .body("[[\"getMailboxes\", {}, \"#0\"]]")
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("mailboxes"))
+            .body(ARGUMENTS + ".list", hasSize(2))
+            .body(ARGUMENTS + ".list.name", hasItems("foo"));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotCreatedWhenInvalidParentId() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"foo\"," +
+                "          \"parentId\" : \"123\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#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 + ".notCreated", aMapWithSize(1))
+            .body(ARGUMENTS + ".notCreated", hasEntry(equalTo("create-id01"), Matchers.allOf(
+                    hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                    hasEntry(equalTo("description"), equalTo("The parent mailbox '123' was not found.")))));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnCreatedMailboxWhenCreatingParentThenChildMailboxes() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id00\" : {" +
+                "          \"name\" : \"parent\"" +
+                "        }," +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"child\"," +
+                "          \"parentId\" : \"create-id00\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#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 + ".created", aMapWithSize(2))
+            .body(ARGUMENTS + ".created", hasEntry(equalTo("create-id00"), Matchers.allOf(
+                    hasEntry(equalTo("parentId"), isEmptyOrNullString()),
+                    hasEntry(equalTo("name"), equalTo("parent")))))
+            .body(ARGUMENTS + ".created", hasEntry(equalTo("create-id01"), Matchers.allOf(
+                    hasEntry(equalTo("parentId"), not(isEmptyOrNullString())),
+                    hasEntry(equalTo("name"), equalTo("child")))));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnCreatedMailboxWhenCreatingChildThenParentMailboxes() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"child\"," +
+                "          \"parentId\" : \"create-id00\"" +
+                "        }," +
+                "        \"create-id00\" : {" +
+                "          \"name\" : \"parent\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#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 + ".created", aMapWithSize(2))
+            .body(ARGUMENTS + ".created", hasEntry(equalTo("create-id00"), Matchers.allOf(
+                    hasEntry(equalTo("parentId"), isEmptyOrNullString()),
+                    hasEntry(equalTo("name"), equalTo("parent")))))
+            .body(ARGUMENTS + ".created", hasEntry(equalTo("create-id01"), Matchers.allOf(
+                    hasEntry(equalTo("parentId"), not(isEmptyOrNullString())),
+                    hasEntry(equalTo("name"), equalTo("child")))));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotCreatedWhenMailboxAlreadyExists() throws Exception {
+        jmapServer.serverProbe().createMailbox("#private", username, "myBox");
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"myBox\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#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 + ".notCreated", aMapWithSize(1))
+            .body(ARGUMENTS + ".notCreated", hasEntry(equalTo("create-id01"), Matchers.allOf(
+                    hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                    hasEntry(equalTo("description"), equalTo("The mailbox 'create-id01' already exists.")))));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotCreatedWhenCycleDetected() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"A\"," +
+                "          \"parentId\" : \"create-id02\"" +
+                "        }," +
+                "        \"create-id02\" : {" +
+                "          \"name\" : \"B\"," +
+                "          \"parentId\" : \"create-id01\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#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 + ".notCreated", aMapWithSize(2))
+            .body(ARGUMENTS + ".notCreated", Matchers.allOf(
+                    hasEntry(equalTo("create-id01"), Matchers.allOf(
+                        hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                        hasEntry(equalTo("description"), equalTo("The created mailboxes introduce a cycle.")))),
+                    hasEntry(equalTo("create-id02"), Matchers.allOf(
+                            hasEntry(equalTo("type"), equalTo("invalidArguments")),
+                            hasEntry(equalTo("description"), equalTo("The created mailboxes introduce a cycle."))))
+                    ));
+    }
+
+    @Test
+    public void setMailboxesShouldReturnNotCreatedWhenMailboxNameContainsPathDelimiter() throws Exception {
+        String requestBody =
+            "[" +
+                "  [ \"setMailboxes\"," +
+                "    {" +
+                "      \"create\": {" +
+                "        \"create-id01\" : {" +
+                "          \"name\" : \"A.B.C.D\"" +
+                "        }" +
+                "      }" +
+                "    }," +
+                "    \"#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 + ".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: '.'")))
+                    ));
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxNameException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxNameException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxNameException.java
new file mode 100644
index 0000000..1828eee
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxNameException.java
@@ -0,0 +1,27 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.exceptions;
+
+public class MailboxNameException extends RuntimeException {
+
+    public MailboxNameException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxParentNotFoundException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxParentNotFoundException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxParentNotFoundException.java
new file mode 100644
index 0000000..aadf5eb
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxParentNotFoundException.java
@@ -0,0 +1,34 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.exceptions;
+
+public class MailboxParentNotFoundException extends RuntimeException {
+
+    private final String parentId;
+
+    public MailboxParentNotFoundException(String parentId) {
+        super(String.format("The parent mailbox '%s' was not found.", parentId));
+        this.parentId = parentId;
+    }
+
+    public String getParentId() {
+        return parentId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/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 73426f5..205528f 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
@@ -19,20 +19,134 @@
 
 package org.apache.james.jmap.methods;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.exceptions.MailboxNameException;
+import org.apache.james.jmap.exceptions.MailboxParentNotFoundException;
+import org.apache.james.jmap.model.MailboxCreationId;
+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.utils.SortingHierarchicalCollections;
+import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
+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.model.MailboxPath;
 import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.annotations.VisibleForTesting;
 
 public class SetMailboxesCreationProcessor<Id extends MailboxId> implements SetMailboxesProcessor<Id> {
 
-    public SetMailboxesResponse process(SetMailboxesRequest request) {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SetMailboxesCreationProcessor.class);
+
+    private final MailboxManager mailboxManager;
+    private final SortingHierarchicalCollections<Map.Entry<MailboxCreationId, MailboxRequest>, String> sortingHierarchicalCollections;
+    private final MailboxUtils<Id> mailboxUtils;
+
+    @Inject
+    @VisibleForTesting
+    SetMailboxesCreationProcessor(MailboxManager mailboxManager, MailboxUtils<Id> mailboxUtils) {
+        this.mailboxManager = mailboxManager;
+        this.sortingHierarchicalCollections =
+            new SortingHierarchicalCollections<>(
+                x -> x.getKey().getCreationId(),
+                x -> x.getValue().getParentId());
+        this.mailboxUtils = mailboxUtils;
+    }
+
+    public SetMailboxesResponse process(SetMailboxesRequest request, MailboxSession mailboxSession) {
         SetMailboxesResponse.Builder builder = SetMailboxesResponse.builder();
-        request.getCreate().entrySet().stream()
-            .forEach(entry -> builder.creation(
-                entry.getKey(),
-                Mailbox.builder().name(entry.getValue().getName()).id("serverId").build()));
+        try {
+            Map<MailboxCreationId, String> creationIdsToCreatedMailboxId = new HashMap<>();
+            sortingHierarchicalCollections.sortFromRootToLeaf(request.getCreate().entrySet())
+                .forEach(entry -> 
+                    createMailbox(entry.getKey(), entry.getValue(), mailboxSession, creationIdsToCreatedMailboxId, builder));
+        } catch (CycleDetectedException e) {
+            markRequestsAsNotCreatedDueToCycle(request, builder);
+        }
         return builder.build();
     }
 
+    private void markRequestsAsNotCreatedDueToCycle(SetMailboxesRequest request, SetMailboxesResponse.Builder builder) {
+        request.getCreate().entrySet()
+            .forEach(entry ->
+                builder.notCreated(entry.getKey(),
+                        SetError.builder()
+                        .type("invalidArguments")
+                        .description("The created mailboxes introduce a cycle.")
+                        .build()));
+    }
+
+    private void createMailbox(MailboxCreationId mailboxCreationId, MailboxRequest mailboxRequest, MailboxSession mailboxSession,
+            Map<MailboxCreationId, String> creationIdsToCreatedMailboxId, SetMailboxesResponse.Builder builder) {
+        try {
+            ensureValidMailboxName(mailboxRequest, mailboxSession);
+            MailboxPath mailboxPath = getMailboxPath(mailboxRequest, creationIdsToCreatedMailboxId, mailboxSession);
+            mailboxManager.createMailbox(mailboxPath, mailboxSession);
+            Optional<Mailbox> mailbox = mailboxUtils.mailboxFromMailboxPath(mailboxPath, mailboxSession);
+            if (mailbox.isPresent()) {
+                builder.creation(mailboxCreationId, mailbox.get());
+                creationIdsToCreatedMailboxId.put(mailboxCreationId, mailbox.get().getId());
+            } else {
+                builder.notCreated(mailboxCreationId, SetError.builder()
+                        .type("anErrorOccurred")
+                        .description("An error occurred when creating the mailbox")
+                        .build());
+            }
+        } catch (MailboxNameException | MailboxParentNotFoundException e) {
+            builder.notCreated(mailboxCreationId, SetError.builder()
+                    .type("invalidArguments")
+                    .description(e.getMessage())
+                    .build());
+        } catch (MailboxExistsException e) {
+            String message = String.format("The mailbox '%s' already exists.", mailboxCreationId.getCreationId());
+            builder.notCreated(mailboxCreationId, SetError.builder()
+                    .type("invalidArguments")
+                    .description(message)
+                    .build());
+        } catch (MailboxException e) {
+            String message = String.format("An error occurred when creating the mailbox '%s'", mailboxCreationId.getCreationId());
+            LOGGER.error(message, e);
+            builder.notCreated(mailboxCreationId, SetError.builder()
+                    .type("anErrorOccurred")
+                    .description(message)
+                    .build());
+        }
+    }
+
+    private void ensureValidMailboxName(MailboxRequest mailboxRequest, MailboxSession mailboxSession) {
+        String name = mailboxRequest.getName();
+        char pathDelimiter = mailboxSession.getPathDelimiter();
+        if (name.contains(String.valueOf(pathDelimiter))) {
+            throw new MailboxNameException(String.format("The mailbox '%s' contains an illegal character: '%c'", name, pathDelimiter));
+        }
+    }
+
+    private MailboxPath getMailboxPath(MailboxRequest mailboxRequest, Map<MailboxCreationId, String> creationIdsToCreatedMailboxId, MailboxSession mailboxSession) throws MailboxException {
+        if (mailboxRequest.getParentId().isPresent()) {
+            String parentId = mailboxRequest.getParentId().get();
+            String parentName = mailboxUtils.getMailboxNameFromId(parentId, mailboxSession)
+                    .orElseGet(Throwing.supplier(() ->
+                        mailboxUtils.getMailboxNameFromId(creationIdsToCreatedMailboxId.get(MailboxCreationId.of(parentId)), mailboxSession)
+                            .orElseThrow(() -> new MailboxParentNotFoundException(parentId))
+                    ));
+
+            return new MailboxPath(mailboxSession.getPersonalSpace(), mailboxSession.getUser().getUserName(), 
+                    parentName + mailboxSession.getPathDelimiter() + mailboxRequest.getName());
+        }
+        return new MailboxPath(mailboxSession.getPersonalSpace(), mailboxSession.getUser().getUserName(), mailboxRequest.getName());
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesMethod.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesMethod.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesMethod.java
index 70b6e90..51ae92f 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesMethod.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesMethod.java
@@ -63,7 +63,7 @@ public class SetMailboxesMethod<Id extends MailboxId> implements Method {
         Preconditions.checkArgument(request instanceof SetMailboxesRequest);
         SetMailboxesRequest setMailboxesRequest = (SetMailboxesRequest) request;
         return processors.stream()
-            .map(processor -> processor.process(setMailboxesRequest))
+            .map(processor -> processor.process(setMailboxesRequest, mailboxSession))
             .map(response -> toJmapResponse(clientId, response));
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesProcessor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesProcessor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesProcessor.java
index c9b7ef7..80f960e 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesProcessor.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/methods/SetMailboxesProcessor.java
@@ -21,10 +21,11 @@ package org.apache.james.jmap.methods;
 
 import org.apache.james.jmap.model.SetMailboxesRequest;
 import org.apache.james.jmap.model.SetMailboxesResponse;
+import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.store.mail.model.MailboxId;
 
 public interface SetMailboxesProcessor<Id extends MailboxId> {
 
-    SetMailboxesResponse process(SetMailboxesRequest request);
+    SetMailboxesResponse process(SetMailboxesRequest request, MailboxSession mailboxSession);
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
index aa520b3..75aacd2 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/SetError.java
@@ -28,6 +28,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
@@ -99,4 +100,20 @@ public class SetError {
     public Optional<ImmutableSet<MessageProperty>> getProperties() {
         return properties;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof SetError) {
+            SetError other = (SetError) obj;
+            return Objects.equal(this.type, other.type)
+                && Objects.equal(this.description, other.description)
+                && Objects.equal(this.properties, other.properties);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(type, description, properties);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/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 4322328..2d38706 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,8 @@
  ****************************************************************/
 package org.apache.james.jmap.model;
 
+import java.util.Map;
+
 import org.apache.james.jmap.methods.Method;
 import org.apache.james.jmap.model.mailbox.Mailbox;
 
@@ -31,10 +33,12 @@ public class SetMailboxesResponse implements Method.Response {
 
     public static class Builder {
 
-        private ImmutableMap.Builder<MailboxCreationId, Mailbox> created;
+        private final ImmutableMap.Builder<MailboxCreationId, Mailbox> created;
+        private final ImmutableMap.Builder<MailboxCreationId, SetError> notCreated;
 
         private Builder() {
             created = ImmutableMap.builder();
+            notCreated = ImmutableMap.builder();
         }
 
         public Builder creation(MailboxCreationId creationId, Mailbox mailbox) {
@@ -42,20 +46,35 @@ public class SetMailboxesResponse implements Method.Response {
             return this;
         }
 
+        public Builder notCreated(Map<MailboxCreationId, SetError> notCreated) {
+            this.notCreated.putAll(notCreated);
+            return this;
+        }
+
+        public Builder notCreated(MailboxCreationId mailboxCreationId, SetError setError) {
+            this.notCreated.put(mailboxCreationId, setError);
+            return this;
+        }
+
         public SetMailboxesResponse build() {
-            return new SetMailboxesResponse(created.build());
+            return new SetMailboxesResponse(created.build(), notCreated.build());
         }
 
     }
 
     private final ImmutableMap<MailboxCreationId, Mailbox> created;
+    private final ImmutableMap<MailboxCreationId, SetError> notCreated;
 
-    private SetMailboxesResponse(ImmutableMap<MailboxCreationId, Mailbox> created) {
+    private SetMailboxesResponse(ImmutableMap<MailboxCreationId, Mailbox> created, ImmutableMap<MailboxCreationId, SetError> notCreated) {
         this.created = created;
+        this.notCreated = notCreated;
     }
 
     public ImmutableMap<MailboxCreationId, Mailbox> getCreated() {
         return created;
     }
 
+    public Map<MailboxCreationId, SetError> getNotCreated() {
+        return notCreated;
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java
deleted file mode 100644
index 66fbf50..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************
- * 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.utils;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
-
-import com.google.common.collect.Lists;
-
-public class CollectionHierarchySorter<T, Id> {
-
-    private final Function<T, Id> index;
-    private final Function<T, Optional<Id>> parentId;
-
-    public CollectionHierarchySorter(Function<T, Id> index,
-                                  Function<T, Optional<Id>> parentId) {
-        this.index = index;
-        this.parentId = parentId;
-    }
-
-    public List<T> sortFromRootToLeaf(Collection<T> elements) throws CycleDetectedException {
-
-        Map<Id, T> mapOfElementsById = indexElementsById(elements);
-
-        DependencyGraph<T> graph = new DependencyGraph<>(m ->
-                parentId.apply(m).map(mapOfElementsById::get));
-
-        elements.stream().forEach(graph::registerItem);
-
-        return graph.getBuildChain().collect(Collectors.toList());
-    }
-
-    private Map<Id, T> indexElementsById(Collection<T> elements) {
-        return elements.stream()
-                .collect(Collectors.toMap(index, Function.identity()));
-    }
-
-    public List<T> sortFromLeafToRoot(Collection<T> elements) throws CycleDetectedException {
-        return Lists.reverse(sortFromRootToLeaf(elements));
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortingHierarchicalCollections.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortingHierarchicalCollections.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortingHierarchicalCollections.java
new file mode 100644
index 0000000..bbf0d2e
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/SortingHierarchicalCollections.java
@@ -0,0 +1,64 @@
+/****************************************************************
+ * 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.utils;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
+
+import com.google.common.collect.Lists;
+
+public class SortingHierarchicalCollections<T, Id> {
+
+    private final Function<T, Id> index;
+    private final Function<T, Optional<Id>> parentId;
+
+    public SortingHierarchicalCollections(Function<T, Id> index,
+                                  Function<T, Optional<Id>> parentId) {
+        this.index = index;
+        this.parentId = parentId;
+    }
+
+    public List<T> sortFromRootToLeaf(Collection<T> elements) throws CycleDetectedException {
+
+        Map<Id, T> mapOfElementsById = indexElementsById(elements);
+
+        DependencyGraph<T> graph = new DependencyGraph<>(m ->
+                parentId.apply(m).map(mapOfElementsById::get));
+
+        elements.stream().forEach(graph::registerItem);
+
+        return graph.getBuildChain().collect(Collectors.toList());
+    }
+
+    private Map<Id, T> indexElementsById(Collection<T> elements) {
+        return elements.stream()
+                .collect(Collectors.toMap(index, Function.identity()));
+    }
+
+    public List<T> sortFromLeafToRoot(Collection<T> elements) throws CycleDetectedException {
+        return Lists.reverse(sortFromRootToLeaf(elements));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessorTest.java
new file mode 100644
index 0000000..fe10145
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesCreationProcessorTest.java
@@ -0,0 +1,71 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.methods;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.james.jmap.model.MailboxCreationId;
+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.MailboxRequest;
+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.store.TestId;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SetMailboxesCreationProcessorTest {
+
+    private MailboxUtils<TestId> mailboxUtils;
+    private SetMailboxesCreationProcessor<TestId> sut;
+
+    @Before
+    @SuppressWarnings("unchecked")
+    public void setup() {
+        mailboxUtils = mock(MailboxUtils.class);
+        sut = new SetMailboxesCreationProcessor<>(mock(MailboxManager.class), mailboxUtils);
+    }
+
+    @Test
+    public void processShouldReturnNotCreatedWhenMailboxExceptionOccured() throws Exception {
+        String parentId = "parentId";
+        MailboxCreationId mailboxCreationId = MailboxCreationId.of("1");
+        SetMailboxesRequest request = SetMailboxesRequest.builder()
+                .create(mailboxCreationId, MailboxRequest.builder().name("name").parentId(parentId).build())
+                .build();
+
+        MailboxSession mailboxSession = mock(MailboxSession.class);
+        when(mailboxUtils.getMailboxNameFromId(parentId, mailboxSession))
+            .thenThrow(new MailboxException());
+
+        SetMailboxesResponse setMailboxesResponse = sut.process(request, mailboxSession);
+        assertThat(setMailboxesResponse.getCreated()).isEmpty();
+        assertThat(setMailboxesResponse.getNotCreated()).containsEntry(mailboxCreationId, 
+                SetError.builder()
+                    .type("anErrorOccurred")
+                    .description("An error occurred when creating the mailbox '1'")
+                    .build());
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesMethodTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesMethodTest.java
index af0d4a3..0019460 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesMethodTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/methods/SetMailboxesMethodTest.java
@@ -103,7 +103,7 @@ public class SetMailboxesMethodTest {
         MailboxSession session = mock(MailboxSession.class);
         @SuppressWarnings("unchecked")
         SetMailboxesProcessor<TestId> creatorProcessor = mock(SetMailboxesProcessor.class);
-        when(creatorProcessor.process(creationRequest)).thenReturn(creationResponse);
+        when(creatorProcessor.process(creationRequest, session)).thenReturn(creationResponse);
 
         Stream<JmapResponse> actual =
             new SetMailboxesMethod<>(ImmutableSet.of(creatorProcessor))

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java
deleted file mode 100644
index 1870f9e..0000000
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************
- * 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.utils;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.james.jmap.model.mailbox.Mailbox;
-import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class CollectionHierarchySorterTest {
-
-    private CollectionHierarchySorter<Mailbox, String> sut;
-
-    @Before
-    public void setup() {
-        sut = new CollectionHierarchySorter<>(Mailbox::getId, Mailbox::getParentId);
-    }
-
-    @Test
-    public void sortFromRootToLeafShouldReturnOrderedMailbox() {
-        // Given
-        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
-        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
-        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
-        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
-
-        // When
-        List<Mailbox> result = sut.sortFromRootToLeaf(input);
-
-        // Then
-        assertThat(result).extracting(Mailbox::getName).endsWith("C", "D", "E").startsWith("INBOX");
-    }
-
-    @Test
-    public void sortFromRootToLeafEmptyMailboxShouldReturnEmpty() {
-        ImmutableList<Mailbox> input = ImmutableList.of();
-        List<Mailbox> result = sut.sortFromRootToLeaf(input);
-        assertThat(result).isEmpty();
-    }
-
-    @Test
-    public void sortFromRootToLeafOrphanMailboxesShouldReturnInput() {
-        Mailbox a = Mailbox.builder().name("A").id("A").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").build();
-
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
-        List<String> result = sut.sortFromRootToLeaf(input).stream()
-                .map(Mailbox::getName)
-                .collect(Collectors.toList());
-
-        assertThat(result).containsExactly("A", "B", "C");
-    }
-
-    @Test(expected=CycleDetectedException.class)
-    public void sortFromRootToLeafWithLoopShouldThrow() {
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
-
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
-
-        sut.sortFromRootToLeaf(input);
-    }
-
-    @Test
-    public void sortFromLeafToRootShouldReturnOrderedMailbox() {
-        //Given
-        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
-        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
-        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
-
-        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
-
-        //When
-        List<Mailbox> result = sut.sortFromLeafToRoot(input);
-
-        assertThat(result).extracting(Mailbox::getName).endsWith("INBOX").startsWith("E");
-    }
-
-    @Test
-    public void sortFromLeafToRootEmptyMailboxShouldReturnEmpty() {
-        ImmutableList<Mailbox> input = ImmutableList.of();
-        List<Mailbox> result = sut.sortFromLeafToRoot(input);
-        assertThat(result).isEmpty();
-    }
-
-    @Test
-    public void sortFromLeafToRootOrphanMailboxesShouldReturnInput() {
-        Mailbox a = Mailbox.builder().name("A").id("A").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").build();
-
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
-        List<String> result = sut.sortFromLeafToRoot(input).stream()
-                .map(Mailbox::getName)
-                .collect(Collectors.toList());
-
-        assertThat(result).containsExactly("C", "B", "A");
-    }
-
-    @Test(expected=CycleDetectedException.class)
-    public void sortFromLeafToRootWithLoopShouldThrow() {
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
-
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
-
-        sut.sortFromLeafToRoot(input);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/68ab6176/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortingHierarchicalCollectionsTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortingHierarchicalCollectionsTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortingHierarchicalCollectionsTest.java
new file mode 100644
index 0000000..1437f88
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/SortingHierarchicalCollectionsTest.java
@@ -0,0 +1,140 @@
+/****************************************************************
+ * 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.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.james.jmap.model.mailbox.Mailbox;
+import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class SortingHierarchicalCollectionsTest {
+
+    private SortingHierarchicalCollections<Mailbox, String> sut;
+
+    @Before
+    public void setup() {
+        sut = new SortingHierarchicalCollections<>(Mailbox::getId, Mailbox::getParentId);
+    }
+
+    @Test
+    public void sortFromRootToLeafShouldReturnOrderedMailbox() {
+        // Given
+        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
+        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
+        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
+        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
+
+        // When
+        List<Mailbox> result = sut.sortFromRootToLeaf(input);
+
+        // Then
+        assertThat(result).extracting(Mailbox::getName).endsWith("C", "D", "E").startsWith("INBOX");
+    }
+
+    @Test
+    public void sortFromRootToLeafEmptyMailboxShouldReturnEmpty() {
+        ImmutableList<Mailbox> input = ImmutableList.of();
+        List<Mailbox> result = sut.sortFromRootToLeaf(input);
+        assertThat(result).isEmpty();
+    }
+
+    @Test
+    public void sortFromRootToLeafOrphanMailboxesShouldReturnInput() {
+        Mailbox a = Mailbox.builder().name("A").id("A").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
+        List<String> result = sut.sortFromRootToLeaf(input).stream()
+                .map(Mailbox::getName)
+                .collect(Collectors.toList());
+
+        assertThat(result).containsExactly("A", "B", "C");
+    }
+
+    @Test(expected=CycleDetectedException.class)
+    public void sortFromRootToLeafWithLoopShouldThrow() {
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
+
+        sut.sortFromRootToLeaf(input);
+    }
+
+    @Test
+    public void sortFromLeafToRootShouldReturnOrderedMailbox() {
+        //Given
+        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
+        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
+        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
+
+        //When
+        List<Mailbox> result = sut.sortFromLeafToRoot(input);
+
+        assertThat(result).extracting(Mailbox::getName).endsWith("INBOX").startsWith("E");
+    }
+
+    @Test
+    public void sortFromLeafToRootEmptyMailboxShouldReturnEmpty() {
+        ImmutableList<Mailbox> input = ImmutableList.of();
+        List<Mailbox> result = sut.sortFromLeafToRoot(input);
+        assertThat(result).isEmpty();
+    }
+
+    @Test
+    public void sortFromLeafToRootOrphanMailboxesShouldReturnInput() {
+        Mailbox a = Mailbox.builder().name("A").id("A").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
+        List<String> result = sut.sortFromLeafToRoot(input).stream()
+                .map(Mailbox::getName)
+                .collect(Collectors.toList());
+
+        assertThat(result).containsExactly("C", "B", "A");
+    }
+
+    @Test(expected=CycleDetectedException.class)
+    public void sortFromLeafToRootWithLoopShouldThrow() {
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
+
+        sut.sortFromLeafToRoot(input);
+    }
+}
\ No newline at end of file


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


[3/4] james-project git commit: JAMES-1712 Give MailboxHierarchySorter functions for index & parentId

Posted by ad...@apache.org.
JAMES-1712 Give MailboxHierarchySorter functions for index & parentId


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

Branch: refs/heads/master
Commit: beaecf70b7094c62f9d54c24b1c80d37699c0b76
Parents: f9f6e84
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Mar 29 15:31:33 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Mon Apr 4 16:27:11 2016 +0200

----------------------------------------------------------------------
 .../jmap/utils/CollectionHierarchySorter.java   |  64 +++++++++
 .../jmap/utils/MailboxHierarchySorter.java      |  54 -------
 .../utils/CollectionHierarchySorterTest.java    | 140 +++++++++++++++++++
 .../jmap/utils/MailboxHierarchySorterTest.java  | 139 ------------------
 4 files changed, 204 insertions(+), 193 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/beaecf70/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java
new file mode 100644
index 0000000..66fbf50
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/CollectionHierarchySorter.java
@@ -0,0 +1,64 @@
+/****************************************************************
+ * 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.utils;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
+
+import com.google.common.collect.Lists;
+
+public class CollectionHierarchySorter<T, Id> {
+
+    private final Function<T, Id> index;
+    private final Function<T, Optional<Id>> parentId;
+
+    public CollectionHierarchySorter(Function<T, Id> index,
+                                  Function<T, Optional<Id>> parentId) {
+        this.index = index;
+        this.parentId = parentId;
+    }
+
+    public List<T> sortFromRootToLeaf(Collection<T> elements) throws CycleDetectedException {
+
+        Map<Id, T> mapOfElementsById = indexElementsById(elements);
+
+        DependencyGraph<T> graph = new DependencyGraph<>(m ->
+                parentId.apply(m).map(mapOfElementsById::get));
+
+        elements.stream().forEach(graph::registerItem);
+
+        return graph.getBuildChain().collect(Collectors.toList());
+    }
+
+    private Map<Id, T> indexElementsById(Collection<T> elements) {
+        return elements.stream()
+                .collect(Collectors.toMap(index, Function.identity()));
+    }
+
+    public List<T> sortFromLeafToRoot(Collection<T> elements) throws CycleDetectedException {
+        return Lists.reverse(sortFromRootToLeaf(elements));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/beaecf70/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxHierarchySorter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxHierarchySorter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxHierarchySorter.java
deleted file mode 100644
index ea12215..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/MailboxHierarchySorter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************
- * 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.utils;
-
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import org.apache.james.jmap.model.mailbox.Mailbox;
-import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
-
-import com.google.common.collect.Lists;
-
-public class MailboxHierarchySorter {
-
-    public List<Mailbox> sortFromRootToLeaf(List<Mailbox> mailboxes) throws CycleDetectedException {
-
-        Map<String, Mailbox> mapOfMailboxesById = indexMailboxesById(mailboxes);
-
-        DependencyGraph<Mailbox> graph = new DependencyGraph<>(m ->
-                m.getParentId().map(mapOfMailboxesById::get));
-
-        mailboxes.stream().forEach(graph::registerItem);
-
-        return graph.getBuildChain().collect(Collectors.toList());
-    }
-
-    private Map<String, Mailbox> indexMailboxesById(List<Mailbox> mailboxes) {
-        return mailboxes.stream()
-                .collect(Collectors.toMap(Mailbox::getId, Function.identity()));
-    }
-
-    public List<Mailbox> sortFromLeafToRoot(List<Mailbox> mailboxes) throws CycleDetectedException {
-        return Lists.reverse(sortFromRootToLeaf(mailboxes));
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/beaecf70/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java
new file mode 100644
index 0000000..1870f9e
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/CollectionHierarchySorterTest.java
@@ -0,0 +1,140 @@
+/****************************************************************
+ * 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.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.james.jmap.model.mailbox.Mailbox;
+import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class CollectionHierarchySorterTest {
+
+    private CollectionHierarchySorter<Mailbox, String> sut;
+
+    @Before
+    public void setup() {
+        sut = new CollectionHierarchySorter<>(Mailbox::getId, Mailbox::getParentId);
+    }
+
+    @Test
+    public void sortFromRootToLeafShouldReturnOrderedMailbox() {
+        // Given
+        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
+        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
+        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
+        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
+
+        // When
+        List<Mailbox> result = sut.sortFromRootToLeaf(input);
+
+        // Then
+        assertThat(result).extracting(Mailbox::getName).endsWith("C", "D", "E").startsWith("INBOX");
+    }
+
+    @Test
+    public void sortFromRootToLeafEmptyMailboxShouldReturnEmpty() {
+        ImmutableList<Mailbox> input = ImmutableList.of();
+        List<Mailbox> result = sut.sortFromRootToLeaf(input);
+        assertThat(result).isEmpty();
+    }
+
+    @Test
+    public void sortFromRootToLeafOrphanMailboxesShouldReturnInput() {
+        Mailbox a = Mailbox.builder().name("A").id("A").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
+        List<String> result = sut.sortFromRootToLeaf(input).stream()
+                .map(Mailbox::getName)
+                .collect(Collectors.toList());
+
+        assertThat(result).containsExactly("A", "B", "C");
+    }
+
+    @Test(expected=CycleDetectedException.class)
+    public void sortFromRootToLeafWithLoopShouldThrow() {
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
+
+        sut.sortFromRootToLeaf(input);
+    }
+
+    @Test
+    public void sortFromLeafToRootShouldReturnOrderedMailbox() {
+        //Given
+        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
+        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
+        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
+
+        //When
+        List<Mailbox> result = sut.sortFromLeafToRoot(input);
+
+        assertThat(result).extracting(Mailbox::getName).endsWith("INBOX").startsWith("E");
+    }
+
+    @Test
+    public void sortFromLeafToRootEmptyMailboxShouldReturnEmpty() {
+        ImmutableList<Mailbox> input = ImmutableList.of();
+        List<Mailbox> result = sut.sortFromLeafToRoot(input);
+        assertThat(result).isEmpty();
+    }
+
+    @Test
+    public void sortFromLeafToRootOrphanMailboxesShouldReturnInput() {
+        Mailbox a = Mailbox.builder().name("A").id("A").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").build();
+        Mailbox c = Mailbox.builder().name("C").id("C").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
+        List<String> result = sut.sortFromLeafToRoot(input).stream()
+                .map(Mailbox::getName)
+                .collect(Collectors.toList());
+
+        assertThat(result).containsExactly("C", "B", "A");
+    }
+
+    @Test(expected=CycleDetectedException.class)
+    public void sortFromLeafToRootWithLoopShouldThrow() {
+        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
+        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
+
+        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
+
+        sut.sortFromLeafToRoot(input);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/beaecf70/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxHierarchySorterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxHierarchySorterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxHierarchySorterTest.java
deleted file mode 100644
index 32f4829..0000000
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/MailboxHierarchySorterTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/****************************************************************
- * 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.utils;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.james.jmap.model.mailbox.Mailbox;
-import org.apache.james.jmap.utils.DependencyGraph.CycleDetectedException;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class MailboxHierarchySorterTest {
-
-    @Test
-    public void sortFromRootToLeafShouldReturnOrderedMailbox() {
-        // Given
-        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
-        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
-        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
-        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
-
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        // When
-        List<Mailbox> result = sut.sortFromRootToLeaf(input);
-
-        // Then
-        assertThat(result).extracting(Mailbox::getName).endsWith("C", "D", "E").startsWith("INBOX");
-    }
-
-    @Test
-    public void sortFromRootToLeafEmptyMailboxShouldReturnEmpty() {
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        ImmutableList<Mailbox> input = ImmutableList.of();
-        List<Mailbox> result = sut.sortFromRootToLeaf(input);
-        assertThat(result).isEmpty();
-    }
-
-    @Test
-    public void sortFromRootToLeafOrphanMailboxesShouldReturnInput() {
-        Mailbox a = Mailbox.builder().name("A").id("A").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").build();
-
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
-        List<String> result = sut.sortFromRootToLeaf(input).stream()
-                .map(Mailbox::getName)
-                .collect(Collectors.toList());
-
-        assertThat(result).containsExactly("A", "B", "C");
-    }
-
-    @Test(expected=CycleDetectedException.class)
-    public void sortFromRootToLeafWithLoopShouldThrow() {
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
-
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
-
-        sut.sortFromRootToLeaf(input);
-    }
-
-    @Test
-    public void sortFromLeafToRootShouldReturnOrderedMailbox() {
-        //Given
-        Mailbox inbox = Mailbox.builder().name("INBOX").id("INBOX").build();
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("INBOX").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("INBOX").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").parentId("B").build();
-        Mailbox d = Mailbox.builder().name("D").id("D").parentId("A").build();
-        Mailbox e = Mailbox.builder().name("E").id("E").parentId("C").build();
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        ImmutableList<Mailbox> input = ImmutableList.of(b, c, d, a, inbox, e);
-
-        //When
-        List<Mailbox> result = sut.sortFromLeafToRoot(input);
-
-        assertThat(result).extracting(Mailbox::getName).endsWith("INBOX").startsWith("E");
-    }
-
-    @Test
-    public void sortFromLeafToRootEmptyMailboxShouldReturnEmpty() {
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        ImmutableList<Mailbox> input = ImmutableList.of();
-        List<Mailbox> result = sut.sortFromLeafToRoot(input);
-        assertThat(result).isEmpty();
-    }
-
-    @Test
-    public void sortFromLeafToRootOrphanMailboxesShouldReturnInput() {
-        Mailbox a = Mailbox.builder().name("A").id("A").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").build();
-        Mailbox c = Mailbox.builder().name("C").id("C").build();
-
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b, c);
-        List<String> result = sut.sortFromLeafToRoot(input).stream()
-                .map(Mailbox::getName)
-                .collect(Collectors.toList());
-
-        assertThat(result).containsExactly("C", "B", "A");
-    }
-
-    @Test(expected=CycleDetectedException.class)
-    public void sortFromLeafToRootWithLoopShouldThrow() {
-        Mailbox a = Mailbox.builder().name("A").id("A").parentId("B").build();
-        Mailbox b = Mailbox.builder().name("B").id("B").parentId("A").build();
-
-        MailboxHierarchySorter sut = new MailboxHierarchySorter();
-        ImmutableList<Mailbox> input = ImmutableList.of(a, b);
-
-        sut.sortFromLeafToRoot(input);
-    }
-}
\ No newline at end of file


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


[2/4] james-project git commit: JAMES-1712 Mailbox parentId is empty be default

Posted by ad...@apache.org.
JAMES-1712 Mailbox parentId is empty be default


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

Branch: refs/heads/master
Commit: 64ff43e6a86bab3e057511274898e93e02ed3c09
Parents: beaecf7
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Mar 29 15:34:05 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Mon Apr 4 16:27:11 2016 +0200

----------------------------------------------------------------------
 .../org/apache/james/jmap/model/mailbox/Mailbox.java    |  7 ++++---
 .../apache/james/jmap/model/mailbox/MailboxTest.java    | 12 ++++++++++--
 2 files changed, 14 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/64ff43e6/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Mailbox.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Mailbox.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Mailbox.java
index a0b5d70..6c3330d 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Mailbox.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/mailbox/Mailbox.java
@@ -44,7 +44,7 @@ public class Mailbox {
 
         private String id;
         private String name;
-        private String parentId;
+        private Optional<String> parentId;
         private Optional<Role> role;
         private SortOrder sortOrder;
         private boolean mustBeOnlyMailbox;
@@ -60,6 +60,7 @@ public class Mailbox {
         private long unreadThreads;
 
         private Builder() {
+            parentId = Optional.empty();
         }
 
         public Builder id(String id) {
@@ -75,7 +76,7 @@ public class Mailbox {
         }
 
         public Builder parentId(String parentId) {
-            this.parentId = parentId;
+            this.parentId = Optional.ofNullable(parentId);
             return this;
         }
 
@@ -148,7 +149,7 @@ public class Mailbox {
             Preconditions.checkState(!Strings.isNullOrEmpty(name), "'name' is mandatory");
             Preconditions.checkState(!Strings.isNullOrEmpty(id), "'id' is mandatory");
 
-            return new Mailbox(id, name, Optional.ofNullable(parentId), role, sortOrder, mustBeOnlyMailbox, mayReadItems, mayAddItems, mayRemoveItems, mayCreateChild, mayRename, mayDelete,
+            return new Mailbox(id, name, parentId, role, sortOrder, mustBeOnlyMailbox, mayReadItems, mayAddItems, mayRemoveItems, mayCreateChild, mayRename, mayDelete,
                     totalMessages, unreadMessages, totalThreads, unreadThreads);
         }
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/64ff43e6/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/MailboxTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/MailboxTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/MailboxTest.java
index 6510ba4..760d890 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/MailboxTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/mailbox/MailboxTest.java
@@ -23,8 +23,6 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import java.util.Optional;
 
-import org.apache.james.jmap.model.mailbox.Mailbox;
-import org.apache.james.jmap.model.mailbox.Role;
 import org.junit.Test;
 
 public class MailboxTest {
@@ -94,4 +92,14 @@ public class MailboxTest {
 
         assertThat(mailbox).isEqualToComparingFieldByField(expectedMailbox);
     }
+
+    @Test
+    public void parentIdDefaultValueIsEmpty() {
+        Mailbox mailbox = Mailbox.builder()
+            .id("id")
+            .name("name")
+            .build();
+
+        assertThat(mailbox.getParentId()).isEmpty();
+    }
 }


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