Author: btellier
Date: Wed Jun 17 09:07:58 2015
New Revision: 1685960

URL: http://svn.apache.org/r1685960
Log:
MAILBOX-239 LIST related operations should be MPT compliant for the Cassandra 
mailbox

Modified:
    
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
    
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
    
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
    
james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMailboxMapperTest.java

Modified: 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java?rev=1685960&r1=1685959&r2=1685960&view=diff
==============================================================================
--- 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
 (original)
+++ 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraTableManager.java
 Wed Jun 17 09:07:58 2015
@@ -45,8 +45,7 @@ public class CassandraTableManager {
             SchemaBuilder.createTable(CassandraMailboxTable.TABLE_NAME)
                 .ifNotExists()
                 .addPartitionKey(CassandraMailboxTable.ID, timeuuid())
-                .addColumn(CassandraMailboxTable.NAMESPACE, text())
-                .addColumn(CassandraMailboxTable.USER, text())
+                .addUDTColumn(CassandraMailboxTable.MAILBOX_BASE, 
SchemaBuilder.frozen(CassandraTypesProvider.TYPE.MailboxBase.getName()))
                 .addColumn(CassandraMailboxTable.NAME, text())
                 .addColumn(CassandraMailboxTable.PATH, text())
                 .addColumn(CassandraMailboxTable.UIDVALIDITY, bigint())),
@@ -112,7 +111,14 @@ public class CassandraTableManager {
         MailboxPath(SchemaBuilder.createIndex(CassandraMailboxTable.TABLE_NAME)
             .ifNotExists()
             .onTable(CassandraMailboxTable.TABLE_NAME)
-            .andColumn(CassandraMailboxTable.PATH));
+            .andColumn(CassandraMailboxTable.PATH)),
+        AggregateNamespaceUser(
+            SchemaBuilder.createIndex(CassandraMailboxTable.MAILBOX_BASE)
+                .ifNotExists()
+                .onTable(CassandraMailboxTable.TABLE_NAME)
+                .andColumn(CassandraMailboxTable.MAILBOX_BASE)
+        ),
+        ;
         private SchemaStatement createIndexStatement;
 
         INDEX(SchemaStatement createIndexStatement) {

Modified: 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java?rev=1685960&r1=1685959&r2=1685960&view=diff
==============================================================================
--- 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
 (original)
+++ 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
 Wed Jun 17 09:07:58 2015
@@ -22,13 +22,21 @@ package org.apache.james.mailbox.cassand
 import static com.datastax.driver.core.querybuilder.QueryBuilder.*;
 import static org.apache.james.mailbox.cassandra.table.CassandraMailboxTable.*;
 
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
+import java.util.StringTokenizer;
 import java.util.UUID;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import com.datastax.driver.core.utils.UUIDs;
 import com.google.common.base.Preconditions;
 import org.apache.james.mailbox.cassandra.CassandraTypesProvider;
 import org.apache.james.mailbox.cassandra.CassandraTypesProvider.TYPE;
+import org.apache.james.mailbox.cassandra.table.CassandraMailboxTable;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxACL;
@@ -76,7 +84,12 @@ public class CassandraMailboxMapper impl
     }
 
     private SimpleMailbox<UUID> mailbox(Row row) {
-        SimpleMailbox<UUID> mailbox = new SimpleMailbox<UUID>(new 
MailboxPath(row.getString(NAMESPACE), row.getString(USER), 
row.getString(NAME)), row.getLong(UIDVALIDITY));
+        SimpleMailbox<UUID> mailbox = new SimpleMailbox<>(
+            new MailboxPath(
+                row.getUDTValue(MAILBOX_BASE).getString(MailboxBase.NAMESPACE),
+                row.getUDTValue(MAILBOX_BASE).getString(MailboxBase.USER),
+                row.getString(NAME)),
+            row.getLong(UIDVALIDITY));
         mailbox.setMailboxId(row.getUUID(ID));
         mailbox.setACL(new CassandraACLMapper(mailbox, session, 
maxRetry).getACL());
         return mailbox;
@@ -84,15 +97,25 @@ public class CassandraMailboxMapper impl
 
     @Override
     public List<Mailbox<UUID>> findMailboxWithPathLike(MailboxPath path) 
throws MailboxException {
-        final String regexWithUser = ".*" + path.getNamespace() + ".*" + 
path.getUser() + ".*" + path.getName() + ".*";
-        final String regexWithoutUser = ".*" + path.getNamespace() + 
".*null.*" + path.getName() + ".*";
-        Builder<Mailbox<UUID>> result = ImmutableList.<Mailbox<UUID>> 
builder();
-        for (Row row : session.execute(select(FIELDS).from(TABLE_NAME))) {
-            if (row.getString(PATH).matches(regexWithUser) || 
row.getString(PATH).matches(regexWithoutUser)) {
-                result.add(mailbox(row));
-            }
-        }
-        return result.build();
+        Pattern regex = 
Pattern.compile(constructEscapedRegexForMailboxNameMatching(path));
+        return getMailboxFilteredByNamespaceAndUserStream(path.getNamespace(), 
path.getUser())
+            .filter((row) -> regex.matcher(row.getString(NAME)).matches())
+            .map(this::mailbox)
+            .collect(Collectors.toList());
+    }
+
+    private String constructEscapedRegexForMailboxNameMatching(MailboxPath 
path) {
+        return Collections
+            .list(new StringTokenizer(path.getName(), WILDCARD, true))
+            .stream()
+            .map((token) -> {
+                    if (token.equals(WILDCARD)) {
+                        return ".*";
+                    } else {
+                        return Pattern.quote((String) token);
+                    }
+                }
+            ).collect(Collectors.joining());
     }
 
     @Override
@@ -110,9 +133,11 @@ public class CassandraMailboxMapper impl
             insertInto(TABLE_NAME)
                 .value(ID, mailbox.getMailboxId())
                 .value(NAME, mailbox.getName())
-                .value(NAMESPACE, mailbox.getNamespace())
                 .value(UIDVALIDITY, mailbox.getUidValidity())
-                .value(USER, mailbox.getUser())
+                .value(MAILBOX_BASE, 
typesProvider.getDefinedUserType(TYPE.MailboxBase)
+                    .newValue()
+                    .setString(MailboxBase.NAMESPACE, mailbox.getNamespace())
+                    .setString(MailboxBase.USER, mailbox.getUser()))
                 .value(PATH, path(mailbox).toString())
         );
     }
@@ -128,14 +153,21 @@ public class CassandraMailboxMapper impl
 
     @Override
     public boolean hasChildren(Mailbox<UUID> mailbox, char delimiter) {
-        final String regexWithUser = ".*" + mailbox.getNamespace() + ".*" + 
mailbox.getUser() + ".*" + mailbox.getName() + delimiter + ".*";
-        final String regexWithoutUser = ".*" + mailbox.getNamespace() + 
".*null.*" + mailbox.getName() + delimiter + ".*";
-        for (Row row : session.execute(select(PATH).from(TABLE_NAME))) {
-            if (row.getString(PATH).matches(regexWithUser) || 
row.getString(PATH).matches(regexWithoutUser)) {
-                return true;
-            }
-        }
-        return false;
+        final Pattern regex = Pattern.compile(Pattern.quote( mailbox.getName() 
+ String.valueOf(delimiter)) + ".*");
+        return 
getMailboxFilteredByNamespaceAndUserStream(mailbox.getNamespace(), 
mailbox.getUser())
+            .anyMatch((row) -> regex.matcher(row.getString(NAME)).matches());
+    }
+
+    private Stream<Row> getMailboxFilteredByNamespaceAndUserStream (String 
namespace, String user) {
+        return StreamSupport.stream(session.execute(
+                select(FIELDS)
+                    .from(TABLE_NAME)
+                    .where(eq(MAILBOX_BASE, 
typesProvider.getDefinedUserType(TYPE.MailboxBase)
+                        .newValue()
+                        .setString(MailboxBase.NAMESPACE, namespace)
+                        .setString(MailboxBase.USER, user))))
+                .spliterator(),
+            true);
     }
 
     @Override

Modified: 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java?rev=1685960&r1=1685959&r2=1685960&view=diff
==============================================================================
--- 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
 (original)
+++ 
james/mailbox/trunk/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxTable.java
 Wed Jun 17 09:07:58 2015
@@ -19,13 +19,18 @@
 
 package org.apache.james.mailbox.cassandra.table;
 
+
 public interface CassandraMailboxTable {
     String TABLE_NAME = "mailbox";
     String ID = "id";
-    String USER = "user";
     String PATH = "path";
-    String NAMESPACE = "namespace";
+    String MAILBOX_BASE = "mailboxbase";
     String UIDVALIDITY = "uidvalidity";
     String NAME = "name";
-    String[] FIELDS = { ID, USER, NAMESPACE, UIDVALIDITY, NAME, PATH };
+    String[] FIELDS = { ID, MAILBOX_BASE, UIDVALIDITY, NAME, PATH };
+
+    interface MailboxBase {
+        String USER = "user";
+        String NAMESPACE = "namespace";
+    }
 }

Modified: 
james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMailboxMapperTest.java
URL: 
http://svn.apache.org/viewvc/james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMailboxMapperTest.java?rev=1685960&r1=1685959&r2=1685960&view=diff
==============================================================================
--- 
james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMailboxMapperTest.java
 (original)
+++ 
james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/mail/model/AbstractMailboxMapperTest.java
 Wed Jun 17 09:07:58 2015
@@ -26,7 +26,6 @@ import org.apache.james.mailbox.store.ma
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.List;
@@ -172,14 +171,12 @@ public abstract class AbstractMailboxMap
         assertThat(mailboxMapper.hasChildren(esnDevGroupInboxMailbox, 
DELIMITER)).isTrue();
     }
 
-    @Ignore("See MAILBOX-11 and JWC-125")
     @Test
     public void hasChildrenShouldNotBeAcrossUsersAndNamespace() throws 
MailboxException {
         saveAll();
         assertThat(mailboxMapper.hasChildren(bobInboxMailbox, '.')).isFalse();
     }
 
-    @Ignore("See MAILBOX-11 and JWC-125")
     @Test
     public void findMailboxWithPathLikeShouldBeLimitedToUserAndNamespace() 
throws MailboxException {
         saveAll();
@@ -209,10 +206,6 @@ public abstract class AbstractMailboxMap
         mailboxMapper.findMailboxByPath(esnDevGroupJamesPath);
     }
 
-    // findMailboxWithPathLike does not behave as intended in Cassandra 
Mailbox implementation
-    // It matches .*namespace.*:.*user.*:.*name%.* instead of 
namespace:user:name.*
-    // For instance see this method in use line 436 of StoreMailboxManager
-    @Ignore
     @Test
     public void findMailboxWithPathLikeWithChildRegexShouldRetrieveChildren() 
throws MailboxException {
         saveAll();
@@ -220,8 +213,6 @@ public abstract class AbstractMailboxMap
         
assertThat(mailboxMapper.findMailboxWithPathLike(regexPath)).containsOnly(benwaWorkMailbox,
 benwaWorkTodoMailbox, benwaWorkDoneMailbox);
     }
 
-    // Same thing
-    @Ignore
     @Test
     public void 
findMailboxWithPathLikeWithNullUserWithChildRegexShouldRetrieveChildren() 
throws MailboxException {
         saveAll();
@@ -229,8 +220,6 @@ public abstract class AbstractMailboxMap
         
assertThat(mailboxMapper.findMailboxWithPathLike(regexPath)).contains(obmTeamGroupInboxMailbox,
 obmTeamGroupOPushMailbox, obmTeamGroupRoundCubeMailbox);
     }
 
-    // Same thing
-    @Ignore
     @Test
     public void 
findMailboxWithPathLikeWithRegexShouldRetrieveCorrespondingMailbox() throws 
MailboxException {
         saveAll();
@@ -238,8 +227,6 @@ public abstract class AbstractMailboxMap
         
assertThat(mailboxMapper.findMailboxWithPathLike(regexPath)).containsOnly(benwaInboxMailbox);
     }
 
-    // Same thing
-    @Ignore
     @Test
     public void 
findMailboxWithPathLikeWithNullUserWithRegexShouldRetrieveCorrespondingMailbox()
 throws MailboxException {
         saveAll();
@@ -247,7 +234,6 @@ public abstract class AbstractMailboxMap
         
assertThat(mailboxMapper.findMailboxWithPathLike(regexPath)).contains(esnDevGroupInboxMailbox);
     }
 
-    @Ignore("Mailbox name is not escaped")
     @Test
     public void findMailboxWithPathLikeShouldEscapeMailboxName() throws 
MailboxException {
         saveAll();



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to