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 ro...@apache.org on 2016/08/31 08:06:56 UTC

[07/10] james-project git commit: MAILBOX-270: getmetadata command, mailbox store support get annotation by depth

MAILBOX-270: getmetadata command, mailbox store support get annotation by depth


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

Branch: refs/heads/master
Commit: 5376a7e31a13abbee37df3354f49c6a72a82fb47
Parents: 7ac9840
Author: Quynh Nguyen <qn...@linagora.com>
Authored: Tue Jul 5 14:09:55 2016 +0700
Committer: Quynh Nguyen <qn...@linagora.com>
Committed: Tue Aug 30 16:27:44 2016 +0700

----------------------------------------------------------------------
 .../mail/CassandraAnnotationMapper.java         | 66 +++++++++++--
 .../inmemory/mail/InMemoryAnnotationMapper.java | 12 ++-
 .../mailbox/store/StoreMailboxManager.java      | 17 +++-
 .../mailbox/store/mail/AnnotationMapper.java    | 23 ++++-
 .../StoreMailboxManagerAnnotationTest.java      | 14 ++-
 .../store/mail/model/AnnotationMapperTest.java  | 99 ++++++++++++++++++--
 6 files changed, 198 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/5376a7e3/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapper.java
index a96ea69..7f5171e 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapper.java
@@ -21,18 +21,24 @@ package org.apache.james.mailbox.cassandra.mail;
 
 import static com.datastax.driver.core.querybuilder.QueryBuilder.delete;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.gte;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.in;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.lte;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import com.github.steveash.guavate.Guavate;
+import com.google.common.base.Ascii;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.mailbox.cassandra.CassandraId;
 import org.apache.james.mailbox.cassandra.table.CassandraAnnotationTable;
 import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.store.mail.AnnotationMapper;
 import org.apache.james.mailbox.store.transaction.NonTransactionalMapper;
 
@@ -40,10 +46,10 @@ import com.datastax.driver.core.Row;
 import com.datastax.driver.core.Session;
 import com.datastax.driver.core.querybuilder.Select;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
 
 public class CassandraAnnotationMapper extends NonTransactionalMapper implements AnnotationMapper {
 
+    public static final char MAXIMUM_ASCII_CHARACTER = 127;
     private final CassandraId mailboxId;
     private final Session session;
 
@@ -58,38 +64,78 @@ public class CassandraAnnotationMapper extends NonTransactionalMapper implements
             .collect(Collectors.toList());
     }
 
-    public List<MailboxAnnotation> getAnnotationsByKeys(Set<String> keys) {
+    public List<MailboxAnnotation> getAnnotationsByKeys(Set<MailboxAnnotationKey> keys) {
         return CassandraUtils.convertToStream(session.execute(getStoredAnnotationsQueryForKeys(keys)))
             .map(this::toAnnotation)
             .collect(Collectors.toList());
     }
 
-    public void deleteAnnotation(String key) {
+    public List<MailboxAnnotation> getAnnotationsByKeysWithOneDepth(Set<MailboxAnnotationKey> keys) {
+        return keys.stream()
+            .flatMap(this::getAnnotationsByKeyWithOneDepth)
+            .collect(Guavate.toImmutableList());
+    }
+
+    public List<MailboxAnnotation> getAnnotationsByKeysWithAllDepth(Set<MailboxAnnotationKey> keys) {
+        return keys.stream()
+            .flatMap(this::getAnnotationsByKeyWithAllDepth)
+            .collect(Guavate.toImmutableList());
+    }
+
+    public void deleteAnnotation(MailboxAnnotationKey key) {
         session.execute(delete().from(CassandraAnnotationTable.TABLE_NAME)
             .where(eq(CassandraAnnotationTable.MAILBOX_ID, mailboxId.asUuid()))
-            .and(eq(CassandraAnnotationTable.KEY, key)));
+            .and(eq(CassandraAnnotationTable.KEY, key.getKey())));
     }
 
     public void insertAnnotation(MailboxAnnotation mailboxAnnotation) {
         Preconditions.checkArgument(!mailboxAnnotation.isNil());
         session.execute(insertInto(CassandraAnnotationTable.TABLE_NAME)
             .value(CassandraAnnotationTable.MAILBOX_ID, mailboxId.asUuid())
-            .value(CassandraAnnotationTable.KEY, mailboxAnnotation.getKey())
+            .value(CassandraAnnotationTable.KEY, mailboxAnnotation.getKey().getKey())
             .value(CassandraAnnotationTable.VALUE, mailboxAnnotation.getValue().get()));
     }
 
     private MailboxAnnotation toAnnotation(Row row) {
-        return MailboxAnnotation.newInstance(row.getString(CassandraAnnotationTable.KEY), row.getString(CassandraAnnotationTable.VALUE));
+        return MailboxAnnotation.newInstance(new MailboxAnnotationKey(row.getString(CassandraAnnotationTable.KEY)),
+            row.getString(CassandraAnnotationTable.VALUE));
     }
 
     private Select.Where getStoredAnnotationsQuery() {
         return select(CassandraAnnotationTable.SELECT_FIELDS)
-                .from(CassandraAnnotationTable.TABLE_NAME)
-                .where(eq(CassandraAnnotationTable.MAILBOX_ID, mailboxId.asUuid()));
+            .from(CassandraAnnotationTable.TABLE_NAME)
+            .where(eq(CassandraAnnotationTable.MAILBOX_ID, mailboxId.asUuid()));
+    }
+
+    private Select.Where getStoredAnnotationsQueryForKeys(Set<MailboxAnnotationKey> keys) {
+        return getStoredAnnotationsQuery().and(in(CassandraAnnotationTable.KEY, keys.stream()
+            .map(MailboxAnnotationKey::asString)
+            .collect(Guavate.toImmutableList())));
+    }
+
+    private Select.Where getStoredAnnotationsQueryLikeKey(String key) {
+        return getStoredAnnotationsQuery()
+            .and(gte(CassandraAnnotationTable.KEY, key))
+            .and(lte(CassandraAnnotationTable.KEY, buildNextKey(key)));
+    }
+    
+    private String buildNextKey(String key) {
+        return key + MailboxAnnotationKey.SLASH_CHARACTER + MAXIMUM_ASCII_CHARACTER;
+    }
+
+    private Stream<MailboxAnnotation> getAnnotationsByKeyWithAllDepth(MailboxAnnotationKey key) {
+        return CassandraUtils.convertToStream(session.execute(getStoredAnnotationsQueryLikeKey(key.getKey())))
+            .map(this::toAnnotation);
+    }
+
+    private Stream<MailboxAnnotation> getAnnotationsByKeyWithOneDepth(MailboxAnnotationKey key) {
+        return CassandraUtils.convertToStream(session.execute(getStoredAnnotationsQueryLikeKey(key.getKey())))
+            .map(this::toAnnotation)
+            .filter(annotation -> isChild(key, annotation));
     }
 
-    private Select.Where getStoredAnnotationsQueryForKeys(Set<String> keys) {
-        return getStoredAnnotationsQuery().and(in(CassandraAnnotationTable.KEY, Lists.newArrayList(keys)));
+    private boolean isChild(MailboxAnnotationKey key, MailboxAnnotation annotation) {
+        return annotation.getKey().countSlash() <= key.countSlash();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/5376a7e3/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
index cc9bcf6..c951e07 100644
--- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
+++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryAnnotationMapper.java
@@ -26,9 +26,11 @@ import java.util.Set;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.store.mail.AnnotationMapper;
 
 import com.google.common.base.Function;
@@ -41,7 +43,7 @@ import com.google.common.collect.Table;
 
 public class InMemoryAnnotationMapper implements AnnotationMapper {
     private final InMemoryId mailboxId;
-    private final Table<InMemoryId, String, String> mailboxesAnnotations;
+    private final Table<InMemoryId, MailboxAnnotationKey, String> mailboxesAnnotations;
     private final ReadWriteLock lock = new ReentrantReadWriteLock();
 
     public InMemoryAnnotationMapper(InMemoryId mailboxId) {
@@ -59,11 +61,11 @@ public class InMemoryAnnotationMapper implements AnnotationMapper {
         return transaction.run();
     }
 
-    private Iterable<MailboxAnnotation> retrieveAllAnnotations(InMemoryId maiboxId) {
+    private Iterable<MailboxAnnotation> retrieveAllAnnotations(InMemoryId mailboxId) {
         lock.readLock().lock();
         try {
             return Iterables.transform(
-                mailboxesAnnotations.row(maiboxId).entrySet(), 
+                mailboxesAnnotations.row(maiboxId).entrySet(),
                 new Function<Map.Entry<String, String>, MailboxAnnotation>() {
                     @Override
                     public MailboxAnnotation apply(Entry<String, String> input) {
@@ -81,7 +83,7 @@ public class InMemoryAnnotationMapper implements AnnotationMapper {
     }
 
     @Override
-    public List<MailboxAnnotation> getAnnotationsByKeys(final Set<String> keys) {
+    public List<MailboxAnnotation> getAnnotationsByKeys(final Set<MailboxAnnotationKey> keys) {
         return ImmutableList.copyOf(
             Iterables.filter(retrieveAllAnnotations(mailboxId),
                 new Predicate<MailboxAnnotation>() {
@@ -150,7 +152,7 @@ public class InMemoryAnnotationMapper implements AnnotationMapper {
     }
 
     @Override
-    public void deleteAnnotation(String key) {
+    public void deleteAnnotation(MailboxAnnotationKey key) {
         lock.writeLock().lock();
         try {
             mailboxesAnnotations.remove(mailboxId, key);

http://git-wip-us.apache.org/repos/asf/james-project/blob/5376a7e3/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
index e3ae3c1..e974e18 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
@@ -49,6 +49,7 @@ import org.apache.james.mailbox.exception.MailboxExistsException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxMetaData;
@@ -733,7 +734,7 @@ public class StoreMailboxManager implements MailboxManager {
     }
 
     @Override
-    public List<MailboxAnnotation> getAnnotationsByKeys(MailboxPath mailboxPath, MailboxSession session, Set<String> keys) 
+    public List<MailboxAnnotation> getAnnotationsByKeys(MailboxPath mailboxPath, MailboxSession session, Set<MailboxAnnotationKey> keys)
             throws MailboxException {
         AnnotationMapper annotationMapper = getAnnotationMapper(mailboxPath, session);
         return annotationMapper.getAnnotationsByKeys(keys);
@@ -756,4 +757,18 @@ public class StoreMailboxManager implements MailboxManager {
     public boolean hasCapability(MailboxCapabilities capability) {
         return getSupportedMailboxCapabilities().contains(capability);
     }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeysWithOneDepth(MailboxPath mailboxPath, MailboxSession session,
+            Set<MailboxAnnotationKey> keys) throws MailboxException {
+        AnnotationMapper annotationMapper = getAnnotationMapper(mailboxPath, session);
+        return annotationMapper.getAnnotationsByKeysWithOneDepth(keys);
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeysWithAllDepth(MailboxPath mailboxPath, MailboxSession session,
+            Set<MailboxAnnotationKey> keys) throws MailboxException {
+        AnnotationMapper annotationMapper = getAnnotationMapper(mailboxPath, session);
+        return annotationMapper.getAnnotationsByKeysWithAllDepth(keys);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/5376a7e3/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AnnotationMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AnnotationMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AnnotationMapper.java
index d2b6e4d..468a708 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AnnotationMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AnnotationMapper.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.store.transaction.Mapper;
 
 public interface AnnotationMapper extends Mapper {
@@ -42,14 +43,32 @@ public interface AnnotationMapper extends Mapper {
      * @param keys the set of the key should be filtered
      * @return List<MailboxAnnotation>
      */
-    List<MailboxAnnotation> getAnnotationsByKeys(Set<String> keys);
+    List<MailboxAnnotation> getAnnotationsByKeys(Set<MailboxAnnotationKey> keys);
+
+    /**
+     * Search all the <code>MailboxAnnotation</code> by the set of annotation's keys as well as its children entries 
+     * The result is not ordered and should not contain duplicate by key
+     * 
+     * @param keys the set of the key should be filtered
+     * @return List<MailboxAnnotation>
+     */
+    List<MailboxAnnotation> getAnnotationsByKeysWithOneDepth(Set<MailboxAnnotationKey> keys);
+
+    /**
+     * Search all the <code>MailboxAnnotation</code> by the set of annotation's keys and entries below the keys 
+     * The result is not ordered and should not contain duplicate by key
+     * 
+     * @param keys the set of the key should be filtered
+     * @return List<MailboxAnnotation>
+     */
+    List<MailboxAnnotation> getAnnotationsByKeysWithAllDepth(Set<MailboxAnnotationKey> keys);
 
     /**
      * Delete the annotation by its key.
      * 
      * @param key the key of annotation should be deleted
      */
-    void deleteAnnotation(String key);
+    void deleteAnnotation(MailboxAnnotationKey key);
 
     /**
      * - Insert new annotation if it does not exist on store

http://git-wip-us.apache.org/repos/asf/james-project/blob/5376a7e3/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerAnnotationTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerAnnotationTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerAnnotationTest.java
index f662dea..6b3007f 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerAnnotationTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerAnnotationTest.java
@@ -37,6 +37,7 @@ import org.apache.james.mailbox.acl.MailboxACLResolver;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxAnnotation;
 import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.store.mail.AnnotationMapper;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
@@ -52,12 +53,15 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
 public class StoreMailboxManagerAnnotationTest {
-    private static final MailboxAnnotation PRIVATE_ANNOTATION = MailboxAnnotation.newInstance("/private/comment", "My private comment");
-    private static final MailboxAnnotation SHARED_ANNOTATION =  MailboxAnnotation.newInstance("/shared/comment", "My shared comment");
-    private static final Set<String> KEYS = ImmutableSet.of("/private/comment");
+    private static final MailboxAnnotationKey PRIVATE_KEY = new MailboxAnnotationKey("/private/comment");
+    private static final MailboxAnnotationKey SHARED_KEY = new MailboxAnnotationKey("/shared/comment");
+
+    private static final MailboxAnnotation PRIVATE_ANNOTATION = MailboxAnnotation.newInstance(PRIVATE_KEY, "My private comment");
+    private static final MailboxAnnotation SHARED_ANNOTATION =  MailboxAnnotation.newInstance(SHARED_KEY, "My shared comment");
+    private static final Set<MailboxAnnotationKey> KEYS = ImmutableSet.of(PRIVATE_KEY);
 
     private static final List<MailboxAnnotation> ANNOTATIONS = ImmutableList.of(PRIVATE_ANNOTATION, SHARED_ANNOTATION);
-    private static final List<MailboxAnnotation> ANNOTATIONS_WITH_NIL_ENTRY = ImmutableList.of(PRIVATE_ANNOTATION, MailboxAnnotation.nil("/shared/comment"));
+    private static final List<MailboxAnnotation> ANNOTATIONS_WITH_NIL_ENTRY = ImmutableList.of(PRIVATE_ANNOTATION, MailboxAnnotation.nil(SHARED_KEY));
 
     @Mock private MailboxSessionMapperFactory mailboxSessionMapperFactory;
     @Mock private Authenticator authenticator;
@@ -106,7 +110,7 @@ public class StoreMailboxManagerAnnotationTest {
         storeMailboxManager.updateAnnotations(mailboxPath, session, ANNOTATIONS_WITH_NIL_ENTRY);
 
         verify(annotationMapper, times(1)).insertAnnotation(eq(PRIVATE_ANNOTATION));
-        verify(annotationMapper, times(1)).deleteAnnotation(eq("/shared/comment"));
+        verify(annotationMapper, times(1)).deleteAnnotation(eq(SHARED_KEY));
     }
 
     @Test(expected = MailboxException.class)

http://git-wip-us.apache.org/repos/asf/james-project/blob/5376a7e3/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AnnotationMapperTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AnnotationMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AnnotationMapperTest.java
index 196f8df..56a3ee3 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AnnotationMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AnnotationMapperTest.java
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.store.mail.AnnotationMapper;
 import org.junit.After;
 import org.junit.Rule;
@@ -38,12 +39,19 @@ import com.google.common.collect.Lists;
 
 @Contract(MapperProvider.class)
 public class AnnotationMapperTest<T extends MapperProvider> {
-    private static final MailboxAnnotation PRIVATE_ANNOTATION = MailboxAnnotation.newInstance("/private/comment", "My private comment");
-    private static final MailboxAnnotation PRIVATE_USER_ANNOTATION = MailboxAnnotation.newInstance("/private/comment/user", "My private comment");
-    private static final MailboxAnnotation PRIVATE_ANNOTATION_UPDATE = MailboxAnnotation.newInstance("/private/comment", "My updated private comment");
-    private static final MailboxAnnotation SHARED_ANNOTATION =  MailboxAnnotation.newInstance("/shared/comment", "My shared comment");
+    private static final MailboxAnnotationKey PRIVATE_USER_KEY = new MailboxAnnotationKey("/private/commentuser");
+    private static final MailboxAnnotationKey PRIVATE_KEY = new MailboxAnnotationKey("/private/comment");
+    private static final MailboxAnnotationKey PRIVATE_CHILD_KEY = new MailboxAnnotationKey("/private/comment/user");
+    private static final MailboxAnnotationKey PRIVATE_GRANDCHILD_KEY = new MailboxAnnotationKey("/private/comment/user/name");
+    private static final MailboxAnnotationKey SHARED_KEY = new MailboxAnnotationKey("/shared/comment");
 
-    private static final List<MailboxAnnotation> PRIVATE_AND_SHARED_ANNOTATIONS = Lists.newArrayList(PRIVATE_ANNOTATION, SHARED_ANNOTATION);
+    private static final MailboxAnnotation PRIVATE_USER_ANNOTATION = MailboxAnnotation.newInstance(PRIVATE_USER_KEY, "My private comment");
+    private static final MailboxAnnotation PRIVATE_ANNOTATION = MailboxAnnotation.newInstance(PRIVATE_KEY, "My private comment");
+    private static final MailboxAnnotation PRIVATE_CHILD_ANNOTATION = MailboxAnnotation.newInstance(PRIVATE_CHILD_KEY, "My private comment");
+    private static final MailboxAnnotation PRIVATE_ANNOTATION_UPDATE = MailboxAnnotation.newInstance(PRIVATE_KEY, "My updated private comment");
+    private static final MailboxAnnotation SHARED_ANNOTATION =  MailboxAnnotation.newInstance(SHARED_KEY, "My shared comment");
+
+    private static final MailboxAnnotation PRIVATE_GRANDCHILD_ANNOTATION = MailboxAnnotation.newInstance(PRIVATE_GRANDCHILD_KEY, "My private comment");
 
 
     private IProducer<T> producer;
@@ -66,7 +74,7 @@ public class AnnotationMapperTest<T extends MapperProvider> {
     @ContractTest
     public void insertAnnotationShouldThrowExceptionWithNilData() {
         expected.expect(IllegalArgumentException.class);
-        annotationMapper.insertAnnotation(MailboxAnnotation.nil("/private/comment"));
+        annotationMapper.insertAnnotation(MailboxAnnotation.nil(PRIVATE_KEY));
     }
 
     @ContractTest
@@ -87,7 +95,7 @@ public class AnnotationMapperTest<T extends MapperProvider> {
     @ContractTest
     public void deleteAnnotationShouldDeleteStoredAnnotation() throws MailboxException {
         annotationMapper.insertAnnotation(PRIVATE_ANNOTATION);
-        annotationMapper.deleteAnnotation("/private/comment");
+        annotationMapper.deleteAnnotation(PRIVATE_KEY);
 
         assertThat(annotationMapper.getAllAnnotations()).isEmpty();
     }
@@ -102,16 +110,87 @@ public class AnnotationMapperTest<T extends MapperProvider> {
         annotationMapper.insertAnnotation(PRIVATE_ANNOTATION);
         annotationMapper.insertAnnotation(SHARED_ANNOTATION);
 
-        assertThat(annotationMapper.getAllAnnotations()).containsExactlyElementsOf(PRIVATE_AND_SHARED_ANNOTATIONS);
+        assertThat(annotationMapper.getAllAnnotations()).contains(PRIVATE_ANNOTATION, SHARED_ANNOTATION);
     }
 
     @ContractTest
     public void getAnnotationsByKeysShouldReturnStoredAnnotationWithFilter() throws MailboxException {
         annotationMapper.insertAnnotation(PRIVATE_ANNOTATION);
-        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_CHILD_ANNOTATION);
 
-        assertThat(annotationMapper.getAnnotationsByKeys(ImmutableSet.of("/private/comment")))
+        assertThat(annotationMapper.getAnnotationsByKeys(ImmutableSet.of(PRIVATE_KEY)))
             .containsOnly(PRIVATE_ANNOTATION);
     }
 
+    @ContractTest
+    public void getAnnotationsByKeysWithOneDepthShouldReturnThatEntryAndItsChildren() throws MailboxException {
+        annotationMapper.insertAnnotation(PRIVATE_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_CHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_GRANDCHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(SHARED_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+
+        assertThat(annotationMapper.getAnnotationsByKeysWithOneDepth(ImmutableSet.of(PRIVATE_KEY)))
+            .contains(PRIVATE_ANNOTATION, PRIVATE_CHILD_ANNOTATION);
+    }
+
+    @ContractTest
+    public void getAnnotationsByKeysWithAllDepthShouldReturnThatEntryAndAllBelowEntries() throws MailboxException {
+        annotationMapper.insertAnnotation(PRIVATE_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_CHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_GRANDCHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(SHARED_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+
+        assertThat(annotationMapper.getAnnotationsByKeysWithAllDepth(ImmutableSet.of(PRIVATE_KEY)))
+            .contains(PRIVATE_ANNOTATION, PRIVATE_CHILD_ANNOTATION, PRIVATE_GRANDCHILD_ANNOTATION);
+    }
+
+    @ContractTest
+    public void getAnnotationsByKeysWithOneDepthShouldReturnTheChildrenEntriesEvenItDoesNotExist() throws Exception {
+        annotationMapper.insertAnnotation(PRIVATE_CHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_GRANDCHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(SHARED_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+
+        assertThat(annotationMapper.getAnnotationsByKeysWithOneDepth(ImmutableSet.of(PRIVATE_KEY)))
+            .contains(PRIVATE_CHILD_ANNOTATION);
+    }
+
+    @ContractTest
+    public void getAnnotationsByKeysWithAllDepthShouldReturnTheChildrenEntriesEvenItDoesNotExist() throws Exception {
+        annotationMapper.insertAnnotation(PRIVATE_CHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_GRANDCHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(SHARED_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+
+        assertThat(annotationMapper.getAnnotationsByKeysWithAllDepth(ImmutableSet.of(PRIVATE_KEY)))
+            .contains(PRIVATE_CHILD_ANNOTATION, PRIVATE_GRANDCHILD_ANNOTATION);
+    }
+
+    @ContractTest
+    public void getAnnotationsByKeysWithOneDepthShouldReturnEmptyWithEmptyInputKeys() throws Exception {
+        annotationMapper.insertAnnotation(PRIVATE_CHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_GRANDCHILD_ANNOTATION);
+        annotationMapper.insertAnnotation(SHARED_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+
+        assertThat(annotationMapper.getAnnotationsByKeysWithOneDepth(ImmutableSet.<MailboxAnnotationKey>of())).isEmpty();
+    }
+
+    @ContractTest
+    public void getAnnotationsByKeysWithOneDepthShouldReturnEmptyIfDoNotFind() throws Exception {
+        annotationMapper.insertAnnotation(SHARED_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+
+        assertThat(annotationMapper.getAnnotationsByKeysWithOneDepth(ImmutableSet.of(PRIVATE_KEY))).isEmpty();
+    }
+
+    @ContractTest
+    public void getAnnotationsByKeysWithAllDepthShouldReturnEmptyIfDoNotFind() throws Exception {
+        annotationMapper.insertAnnotation(SHARED_ANNOTATION);
+        annotationMapper.insertAnnotation(PRIVATE_USER_ANNOTATION);
+
+        assertThat(annotationMapper.getAnnotationsByKeysWithAllDepth(ImmutableSet.of(PRIVATE_KEY))).isEmpty();
+    }
 }


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