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 bt...@apache.org on 2016/09/29 10:51:53 UTC

[03/12] james-project git commit: JAMES-1781 Cassandra implementation for partial updates

JAMES-1781 Cassandra implementation for partial updates


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

Branch: refs/heads/master
Commit: 6da598471ac2f3632ae9c341b5b5a42e6fcec451
Parents: 50e3ab5
Author: Benoit Tellier <bt...@linagora.com>
Authored: Mon Jun 27 19:02:53 2016 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Sep 29 12:48:14 2016 +0200

----------------------------------------------------------------------
 .../vacation/CassandraVacationDAO.java          | 66 +++++++++++++-------
 .../vacation/CassandraVacationRepository.java   | 13 +++-
 2 files changed, 55 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/6da59847/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java
----------------------------------------------------------------------
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java
index e52139c..2ac0823 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java
@@ -27,6 +27,7 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import java.time.ZonedDateTime;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
 
 import javax.inject.Inject;
 
@@ -36,51 +37,53 @@ import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
 import org.apache.james.backends.cassandra.utils.ZonedDateTimeRepresentation;
 import org.apache.james.jmap.api.vacation.AccountId;
 import org.apache.james.jmap.api.vacation.Vacation;
+import org.apache.james.jmap.api.vacation.VacationPatch;
 import org.apache.james.jmap.cassandra.vacation.tables.CassandraVacationTable;
+import org.apache.james.util.FunctionGenerator;
+import org.apache.james.util.PatchedValue;
 
 import com.datastax.driver.core.PreparedStatement;
 import com.datastax.driver.core.Row;
 import com.datastax.driver.core.Session;
 import com.datastax.driver.core.UDTValue;
 import com.datastax.driver.core.UserType;
+import com.datastax.driver.core.querybuilder.Insert;
+import com.google.common.collect.ImmutableList;
 
 public class CassandraVacationDAO {
 
     private final CassandraAsyncExecutor cassandraAsyncExecutor;
-    private final PreparedStatement insertStatement;
     private final PreparedStatement readStatement;
     private final UserType zonedDateTimeUserType;
+    private final FunctionGenerator<VacationPatch, Insert> insertGeneratorPipeline;
 
     @Inject
     public CassandraVacationDAO(Session session, CassandraTypesProvider cassandraTypesProvider) {
         this.zonedDateTimeUserType = cassandraTypesProvider.getDefinedUserType(CassandraZonedDateTimeModule.ZONED_DATE_TIME);
         this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
 
-        this.insertStatement = session.prepare(insertInto(CassandraVacationTable.TABLE_NAME)
-            .value(CassandraVacationTable.ACCOUNT_ID, bindMarker(CassandraVacationTable.ACCOUNT_ID))
-            .value(CassandraVacationTable.IS_ENABLED, bindMarker(CassandraVacationTable.IS_ENABLED))
-            .value(CassandraVacationTable.FROM_DATE, bindMarker(CassandraVacationTable.FROM_DATE))
-            .value(CassandraVacationTable.TO_DATE, bindMarker(CassandraVacationTable.TO_DATE))
-            .value(CassandraVacationTable.TEXT, bindMarker(CassandraVacationTable.TEXT))
-            .value(CassandraVacationTable.SUBJECT, bindMarker(CassandraVacationTable.SUBJECT))
-            .value(CassandraVacationTable.HTML, bindMarker(CassandraVacationTable.HTML)));
-
         this.readStatement = session.prepare(select()
             .from(CassandraVacationTable.TABLE_NAME)
             .where(eq(CassandraVacationTable.ACCOUNT_ID,
                 bindMarker(CassandraVacationTable.ACCOUNT_ID))));
+
+        insertGeneratorPipeline = ImmutableList.<FunctionGenerator<VacationPatch, Insert>>of(
+            patch -> applyPatchForField(CassandraVacationTable.SUBJECT, patch.getSubject()),
+            patch -> applyPatchForField(CassandraVacationTable.HTML, patch.getHtmlBody()),
+            patch -> applyPatchForField(CassandraVacationTable.TEXT, patch.getTextBody()),
+            patch -> applyPatchForField(CassandraVacationTable.IS_ENABLED, patch.getIsEnabled()),
+            patch -> applyPatchForFieldZonedDateTime(CassandraVacationTable.FROM_DATE, patch.getFromDate()),
+            patch -> applyPatchForFieldZonedDateTime(CassandraVacationTable.TO_DATE, patch.getToDate()))
+            .stream()
+            .reduce(FunctionGenerator::composeGeneratedFunctions)
+            .get();
     }
 
-    public CompletableFuture<Void> modifyVacation(AccountId accountId, Vacation vacation) {
+    public CompletableFuture<Void> modifyVacation(AccountId accountId, VacationPatch vacationPatch) {
         return cassandraAsyncExecutor.executeVoid(
-            insertStatement.bind()
-                .setString(CassandraVacationTable.ACCOUNT_ID, accountId.getIdentifier())
-                .setBool(CassandraVacationTable.IS_ENABLED, vacation.isEnabled())
-                .setUDTValue(CassandraVacationTable.FROM_DATE, convertToUDTValue(vacation.getFromDate()))
-                .setUDTValue(CassandraVacationTable.TO_DATE, convertToUDTValue(vacation.getToDate()))
-                .setString(CassandraVacationTable.TEXT, vacation.getTextBody().orElse(null))
-                .setString(CassandraVacationTable.SUBJECT, vacation.getSubject().orElse(null))
-                .setString(CassandraVacationTable.HTML, vacation.getHtmlBody().orElse(null)));
+            createSpecificUpdate(vacationPatch,
+                insertInto(CassandraVacationTable.TABLE_NAME)
+                    .value(CassandraVacationTable.ACCOUNT_ID, accountId.getIdentifier())));
     }
 
     public CompletableFuture<Optional<Vacation>> retrieveVacation(AccountId accountId) {
@@ -104,11 +107,30 @@ public class CassandraVacationDAO {
                 .getZonedDateTime());
     }
 
-    private UDTValue convertToUDTValue(Optional<ZonedDateTime> zonedDateTimeOptional) {
+    private Insert createSpecificUpdate(VacationPatch vacationPatch, Insert baseInsert) {
+        return insertGeneratorPipeline
+            .apply(vacationPatch)
+            .apply(baseInsert);
+    }
+
+    public <T> Function<Insert, Insert> applyPatchForField(String field, PatchedValue<T> patchedValue) {
+        return patchedValue.mapNotKeptToOptional(optionalValue -> applyPatchForField(field, optionalValue))
+            .orElse(Function.identity());
+    }
+
+    public Function<Insert, Insert> applyPatchForFieldZonedDateTime(String field, PatchedValue<ZonedDateTime> patchedValue) {
+        return patchedValue.mapNotKeptToOptional(optionalValue -> applyPatchForField(field, convertToUDTOptional(optionalValue)))
+            .orElse(Function.identity());
+    }
+
+    private <T> Function<Insert, Insert> applyPatchForField(String field, Optional<T> value) {
+        return insert -> insert.value(field, value.orElse(null));
+    }
+
+    private Optional<UDTValue> convertToUDTOptional(Optional<ZonedDateTime> zonedDateTimeOptional) {
         return zonedDateTimeOptional.map(ZonedDateTimeRepresentation::fromZonedDateTime)
             .map(representation -> zonedDateTimeUserType.newValue()
                 .setDate(CassandraZonedDateTimeModule.DATE, representation.getDate())
-                .setString(CassandraZonedDateTimeModule.TIME_ZONE, representation.getSerializedZoneId()))
-            .orElse(null);
+                .setString(CassandraZonedDateTimeModule.TIME_ZONE, representation.getSerializedZoneId()));
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/6da59847/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java
index 60958d4..51574f5 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java
@@ -26,6 +26,9 @@ import javax.inject.Inject;
 import org.apache.james.jmap.api.vacation.AccountId;
 import org.apache.james.jmap.api.vacation.Vacation;
 import org.apache.james.jmap.api.vacation.VacationRepository;
+import org.apache.james.jmap.api.vacation.VacationPatch;
+
+import com.google.common.base.Preconditions;
 
 public class CassandraVacationRepository implements VacationRepository {
 
@@ -37,8 +40,14 @@ public class CassandraVacationRepository implements VacationRepository {
     }
 
     @Override
-    public CompletableFuture<Void> modifyVacation(AccountId accountId, Vacation vacation) {
-        return cassandraVacationDAO.modifyVacation(accountId, vacation);
+    public CompletableFuture<Void> modifyVacation(AccountId accountId, VacationPatch vacationPatch) {
+        Preconditions.checkNotNull(accountId);
+        Preconditions.checkNotNull(vacationPatch);
+        if (vacationPatch.isIdentity()) {
+            return CompletableFuture.completedFuture(null);
+        } else {
+            return cassandraVacationDAO.modifyVacation(accountId, vacationPatch);
+        }
     }
 
     @Override


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