Skip to content

Commit

Permalink
MAILBOX-307 Dealing with CassandraACLMapper is the job of CassandraMa…
Browse files Browse the repository at this point in the history
…ilboxMapper, not of its DAO
  • Loading branch information
chibenwa authored and mbaechler committed Sep 29, 2017
1 parent edf8a9a commit ee68d17
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 37 deletions.
Expand Up @@ -34,22 +34,18 @@


import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;


import javax.inject.Inject; import javax.inject.Inject;


import org.apache.james.backends.cassandra.init.CassandraConfiguration;
import org.apache.james.backends.cassandra.init.CassandraTypesProvider; import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor; import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
import org.apache.james.backends.cassandra.utils.CassandraUtils; import org.apache.james.backends.cassandra.utils.CassandraUtils;
import org.apache.james.mailbox.cassandra.ids.CassandraId; import org.apache.james.mailbox.cassandra.ids.CassandraId;
import org.apache.james.mailbox.cassandra.mail.utils.MailboxBaseTupleUtil; import org.apache.james.mailbox.cassandra.mail.utils.MailboxBaseTupleUtil;
import org.apache.james.mailbox.cassandra.table.CassandraMailboxTable; import org.apache.james.mailbox.cassandra.table.CassandraMailboxTable;
import org.apache.james.mailbox.model.MailboxACL;
import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.mail.model.Mailbox; import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox; import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
import org.apache.james.util.CompletableFutureUtil;
import org.apache.james.util.FluentFutureStream; import org.apache.james.util.FluentFutureStream;


import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.PreparedStatement;
Expand All @@ -68,10 +64,9 @@ public class CassandraMailboxDAO {
private final PreparedStatement deleteStatement; private final PreparedStatement deleteStatement;
private final PreparedStatement insertStatement; private final PreparedStatement insertStatement;
private final PreparedStatement updateStatement; private final PreparedStatement updateStatement;
private CassandraACLMapper cassandraACLMapper;


@Inject @Inject
public CassandraMailboxDAO(Session session, CassandraTypesProvider typesProvider, CassandraUtils cassandraUtils, CassandraConfiguration cassandraConfiguration) { public CassandraMailboxDAO(Session session, CassandraTypesProvider typesProvider, CassandraUtils cassandraUtils) {
this.executor = new CassandraAsyncExecutor(session); this.executor = new CassandraAsyncExecutor(session);
this.mailboxBaseTupleUtil = new MailboxBaseTupleUtil(typesProvider); this.mailboxBaseTupleUtil = new MailboxBaseTupleUtil(typesProvider);
this.insertStatement = prepareInsert(session); this.insertStatement = prepareInsert(session);
Expand All @@ -80,12 +75,11 @@ public CassandraMailboxDAO(Session session, CassandraTypesProvider typesProvider
this.listStatement = prepareList(session); this.listStatement = prepareList(session);
this.readStatement = prepareRead(session); this.readStatement = prepareRead(session);
this.cassandraUtils = cassandraUtils; this.cassandraUtils = cassandraUtils;
this.cassandraACLMapper = new CassandraACLMapper(session, cassandraConfiguration);
} }


@VisibleForTesting @VisibleForTesting
public CassandraMailboxDAO(Session session, CassandraTypesProvider typesProvider) { public CassandraMailboxDAO(Session session, CassandraTypesProvider typesProvider) {
this(session, typesProvider, CassandraUtils.WITH_DEFAULT_CONFIGURATION, CassandraConfiguration.DEFAULT_CONFIGURATION); this(session, typesProvider, CassandraUtils.WITH_DEFAULT_CONFIGURATION);
} }


private PreparedStatement prepareInsert(Session session) { private PreparedStatement prepareInsert(Session session) {
Expand Down Expand Up @@ -140,29 +134,17 @@ public CompletableFuture<Void> delete(CassandraId mailboxId) {
} }


public CompletableFuture<Optional<SimpleMailbox>> retrieveMailbox(CassandraId mailboxId) { public CompletableFuture<Optional<SimpleMailbox>> retrieveMailbox(CassandraId mailboxId) {
CompletableFuture<MailboxACL> aclCompletableFuture = cassandraACLMapper.getACL(mailboxId); return executor.executeSingleRow(readStatement.bind()

CompletableFuture<Optional<SimpleMailbox>> simpleMailboxFuture = executor.executeSingleRow(readStatement.bind()
.setUUID(ID, mailboxId.asUuid())) .setUUID(ID, mailboxId.asUuid()))
.thenApply(rowOptional -> rowOptional.map(this::mailboxFromRow)) .thenApply(rowOptional -> rowOptional.map(this::mailboxFromRow))
.thenApply(mailbox -> addMailboxId(mailboxId, mailbox)); .thenApply(mailbox -> addMailboxId(mailboxId, mailbox));

return CompletableFutureUtil.combine(
aclCompletableFuture,
simpleMailboxFuture,
this::addAcl);
} }


private Optional<SimpleMailbox> addMailboxId(CassandraId cassandraId, Optional<SimpleMailbox> mailboxOptional) { private Optional<SimpleMailbox> addMailboxId(CassandraId cassandraId, Optional<SimpleMailbox> mailboxOptional) {
mailboxOptional.ifPresent(mailbox -> mailbox.setMailboxId(cassandraId)); mailboxOptional.ifPresent(mailbox -> mailbox.setMailboxId(cassandraId));
return mailboxOptional; return mailboxOptional;
} }


private Optional<SimpleMailbox> addAcl(MailboxACL acl, Optional<SimpleMailbox> mailboxOptional) {
mailboxOptional.ifPresent(mailbox -> mailbox.setACL(acl));
return mailboxOptional;
}

private SimpleMailbox mailboxFromRow(Row row) { private SimpleMailbox mailboxFromRow(Row row) {
return new SimpleMailbox( return new SimpleMailbox(
new MailboxPath( new MailboxPath(
Expand All @@ -172,12 +154,10 @@ private SimpleMailbox mailboxFromRow(Row row) {
row.getLong(UIDVALIDITY)); row.getLong(UIDVALIDITY));
} }


public CompletableFuture<Stream<SimpleMailbox>> retrieveAllMailboxes() { public FluentFutureStream<SimpleMailbox> retrieveAllMailboxes() {
return FluentFutureStream.of(executor.execute(listStatement.bind()) return FluentFutureStream.of(executor.execute(listStatement.bind())
.thenApply(cassandraUtils::convertToStream)) .thenApply(cassandraUtils::convertToStream))
.map(this::toMailboxWithId) .map(this::toMailboxWithId);
.thenComposeOnAll(this::toMailboxWithAclFuture)
.completableFuture();
} }


private SimpleMailbox toMailboxWithId(Row row) { private SimpleMailbox toMailboxWithId(Row row) {
Expand All @@ -186,13 +166,4 @@ private SimpleMailbox toMailboxWithId(Row row) {
return mailbox; return mailbox;
} }


private CompletableFuture<SimpleMailbox> toMailboxWithAclFuture(SimpleMailbox mailbox) {
CassandraId cassandraId = (CassandraId) mailbox.getMailboxId();
return cassandraACLMapper.getACL(cassandraId)
.thenApply(acl -> {
mailbox.setACL(acl);
return mailbox;
});
}

} }
Expand Up @@ -107,11 +107,27 @@ public Mailbox findMailboxByPath(MailboxPath path) throws MailboxException {
@Override @Override
public Mailbox findMailboxById(MailboxId id) throws MailboxException { public Mailbox findMailboxById(MailboxId id) throws MailboxException {
CassandraId mailboxId = (CassandraId) id; CassandraId mailboxId = (CassandraId) id;
return mailboxDAO.retrieveMailbox(mailboxId) return retrieveMailbox(mailboxId)
.join() .join()
.orElseThrow(() -> new MailboxNotFoundException(id.serialize())); .orElseThrow(() -> new MailboxNotFoundException(id.serialize()));
} }


private CompletableFuture<Optional<SimpleMailbox>> retrieveMailbox(CassandraId mailboxId) {
CompletableFuture<MailboxACL> aclCompletableFuture = cassandraACLMapper.getACL(mailboxId);

CompletableFuture<Optional<SimpleMailbox>> simpleMailboxFuture = mailboxDAO.retrieveMailbox(mailboxId);

return CompletableFutureUtil.combine(
aclCompletableFuture,
simpleMailboxFuture,
this::addAcl);
}

private Optional<SimpleMailbox> addAcl(MailboxACL acl, Optional<SimpleMailbox> mailboxOptional) {
mailboxOptional.ifPresent(mailbox -> mailbox.setACL(acl));
return mailboxOptional;
}

@Override @Override
public List<Mailbox> findMailboxWithPathLike(MailboxPath path) throws MailboxException { public List<Mailbox> findMailboxWithPathLike(MailboxPath path) throws MailboxException {
Pattern regex = Pattern.compile(constructEscapedRegexForMailboxNameMatching(path)); Pattern regex = Pattern.compile(constructEscapedRegexForMailboxNameMatching(path));
Expand All @@ -124,7 +140,7 @@ public List<Mailbox> findMailboxWithPathLike(MailboxPath path) throws MailboxExc
} }


private CompletableFuture<Optional<SimpleMailbox>> retrieveMailbox(CassandraMailboxPathDAO.CassandraIdAndPath idAndPath) { private CompletableFuture<Optional<SimpleMailbox>> retrieveMailbox(CassandraMailboxPathDAO.CassandraIdAndPath idAndPath) {
return mailboxDAO.retrieveMailbox(idAndPath.getCassandraId()) return retrieveMailbox(idAndPath.getCassandraId())
.thenApply(optional -> OptionalUtils.ifEmpty(optional, .thenApply(optional -> OptionalUtils.ifEmpty(optional,
() -> LOGGER.warn("Could not retrieve mailbox {} with path {} in mailbox table.", idAndPath.getCassandraId(), idAndPath.getMailboxPath()))); () -> LOGGER.warn("Could not retrieve mailbox {} with path {} in mailbox table.", idAndPath.getCassandraId(), idAndPath.getMailboxPath())));
} }
Expand All @@ -150,7 +166,7 @@ public MailboxId save(Mailbox mailbox) throws MailboxException {
private CompletableFuture<Boolean> trySave(SimpleMailbox cassandraMailbox, CassandraId cassandraId) { private CompletableFuture<Boolean> trySave(SimpleMailbox cassandraMailbox, CassandraId cassandraId) {
return mailboxPathDAO.save(cassandraMailbox.generateAssociatedPath(), cassandraId) return mailboxPathDAO.save(cassandraMailbox.generateAssociatedPath(), cassandraId)
.thenCompose(CompletableFutureUtil.composeIfTrue( .thenCompose(CompletableFutureUtil.composeIfTrue(
() -> mailboxDAO.retrieveMailbox(cassandraId) () -> retrieveMailbox(cassandraId)
.thenCompose(optional -> CompletableFuture .thenCompose(optional -> CompletableFuture
.allOf(optional .allOf(optional
.map(storedMailbox -> mailboxPathDAO.delete(storedMailbox.generateAssociatedPath())) .map(storedMailbox -> mailboxPathDAO.delete(storedMailbox.generateAssociatedPath()))
Expand Down Expand Up @@ -189,6 +205,7 @@ public boolean hasChildren(Mailbox mailbox, char delimiter) {
@Override @Override
public List<Mailbox> list() throws MailboxException { public List<Mailbox> list() throws MailboxException {
return mailboxDAO.retrieveAllMailboxes() return mailboxDAO.retrieveAllMailboxes()
.thenComposeOnAll(this::toMailboxWithAclFuture)
.join() .join()
.collect(Guavate.toImmutableList()); .collect(Guavate.toImmutableList());
} }
Expand Down Expand Up @@ -231,4 +248,13 @@ private String tokenToPatternPart(Object token) {
} }
} }


private CompletableFuture<SimpleMailbox> toMailboxWithAclFuture(SimpleMailbox mailbox) {
CassandraId cassandraId = (CassandraId) mailbox.getMailboxId();
return cassandraACLMapper.getACL(cassandraId)
.thenApply(acl -> {
mailbox.setACL(acl);
return mailbox;
});
}

} }

0 comments on commit ee68d17

Please sign in to comment.