diff --git a/deploy.sh b/bin/deploy.sh
similarity index 100%
rename from deploy.sh
rename to bin/deploy.sh
diff --git a/bin/format.sh b/bin/format.sh
new file mode 100755
index 0000000..10b2bf0
--- /dev/null
+++ b/bin/format.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+for f in $(find ./src -name \*.java); do
+ echo Formatting $f
+ java -jar ./lib/google-java-format-1.3-all-deps.jar --replace $f
+done
+
diff --git a/sign.sh b/bin/sign.sh
similarity index 100%
rename from sign.sh
rename to bin/sign.sh
diff --git a/lib/google-java-format-1.3-all-deps.jar b/lib/google-java-format-1.3-all-deps.jar
new file mode 100644
index 0000000..859a3ca
Binary files /dev/null and b/lib/google-java-format-1.3-all-deps.jar differ
diff --git a/pom.xml b/pom.xml
index dac750d..71feca8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,8 +4,8 @@
4.0.0
net.helenus
- helenus-core
- 2.0.40-SNAPSHOT
+ helenus-net-core
+ 2.1
jar
helenus
diff --git a/src/main/java/com/datastax/driver/core/querybuilder/IsNotNullClause.java b/src/main/java/com/datastax/driver/core/querybuilder/IsNotNullClause.java
new file mode 100644
index 0000000..9ff2596
--- /dev/null
+++ b/src/main/java/com/datastax/driver/core/querybuilder/IsNotNullClause.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Helenus Authors
+ *
+ * Licensed 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 com.datastax.driver.core.querybuilder;
+
+import com.datastax.driver.core.CodecRegistry;
+import java.util.List;
+
+public class IsNotNullClause extends Clause {
+
+ final String name;
+
+ public IsNotNullClause(String name) {
+ this.name = name;
+ }
+
+ @Override
+ String name() {
+ return name;
+ }
+
+ @Override
+ Object firstValue() {
+ return null;
+ }
+
+ @Override
+ void appendTo(StringBuilder sb, List variables, CodecRegistry codecRegistry) {
+ Utils.appendName(name, sb).append(" IS NOT NULL");
+ }
+
+ @Override
+ boolean containsBindMarker() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/datastax/driver/core/schemabuilder/CreateMaterializedView.java b/src/main/java/com/datastax/driver/core/schemabuilder/CreateMaterializedView.java
new file mode 100644
index 0000000..919becc
--- /dev/null
+++ b/src/main/java/com/datastax/driver/core/schemabuilder/CreateMaterializedView.java
@@ -0,0 +1,53 @@
+package com.datastax.driver.core.schemabuilder;
+
+import com.datastax.driver.core.CodecRegistry;
+import com.datastax.driver.core.querybuilder.Select;
+
+public class CreateMaterializedView extends Create {
+
+ private String viewName;
+ private Select.Where selection;
+ private String primaryKey;
+ private String clustering;
+
+ public CreateMaterializedView(
+ String keyspaceName, String viewName, Select.Where selection, String primaryKey, String clustering) {
+ super(keyspaceName, viewName);
+ this.viewName = viewName;
+ this.selection = selection;
+ this.primaryKey = primaryKey;
+ this.clustering = clustering;
+ }
+
+ public String getQueryString(CodecRegistry codecRegistry) {
+ return buildInternal();
+ }
+
+ public String buildInternal() {
+ StringBuilder createStatement =
+ new StringBuilder(STATEMENT_START).append("CREATE MATERIALIZED VIEW");
+ if (ifNotExists) {
+ createStatement.append(" IF NOT EXISTS");
+ }
+ createStatement.append(" ");
+ if (keyspaceName.isPresent()) {
+ createStatement.append(keyspaceName.get()).append(".");
+ }
+ createStatement.append(viewName);
+ createStatement.append(" AS ");
+ createStatement.append(selection.getQueryString());
+ createStatement.setLength(createStatement.length() - 1);
+ createStatement.append(" ");
+ createStatement.append(primaryKey);
+ if (clustering != null) {
+ createStatement.append(" ").append(clustering);
+ }
+ createStatement.append(";");
+
+ return createStatement.toString();
+ }
+
+ public String toString() {
+ return buildInternal();
+ }
+}
diff --git a/src/main/java/com/datastax/driver/core/schemabuilder/DropMaterializedView.java b/src/main/java/com/datastax/driver/core/schemabuilder/DropMaterializedView.java
new file mode 100644
index 0000000..7eca05d
--- /dev/null
+++ b/src/main/java/com/datastax/driver/core/schemabuilder/DropMaterializedView.java
@@ -0,0 +1,53 @@
+package com.datastax.driver.core.schemabuilder;
+
+import com.google.common.base.Optional;
+
+public class DropMaterializedView extends Drop {
+
+ enum DroppedItem {
+ TABLE,
+ TYPE,
+ INDEX,
+ MATERIALIZED_VIEW
+ }
+
+ private Optional keyspaceName = Optional.absent();
+ private String itemName;
+ private boolean ifExists = true;
+ private final String itemType = "MATERIALIZED VIEW";
+
+ public DropMaterializedView(String keyspaceName, String viewName) {
+ this(keyspaceName, viewName, DroppedItem.MATERIALIZED_VIEW);
+ }
+
+ private DropMaterializedView(String keyspaceName, String viewName, DroppedItem itemType) {
+ super(keyspaceName, viewName, Drop.DroppedItem.TABLE);
+ validateNotEmpty(keyspaceName, "Keyspace name");
+ this.keyspaceName = Optional.fromNullable(keyspaceName);
+ this.itemName = viewName;
+ }
+
+ /**
+ * Add the 'IF EXISTS' condition to this DROP statement.
+ *
+ * @return this statement.
+ */
+ public Drop ifExists() {
+ this.ifExists = true;
+ return this;
+ }
+
+ @Override
+ public String buildInternal() {
+ StringBuilder dropStatement = new StringBuilder("DROP " + itemType + " ");
+ if (ifExists) {
+ dropStatement.append("IF EXISTS ");
+ }
+ if (keyspaceName.isPresent()) {
+ dropStatement.append(keyspaceName.get()).append(".");
+ }
+
+ dropStatement.append(itemName);
+ return dropStatement.toString();
+ }
+}
diff --git a/src/main/java/net/helenus/config/GetterMethodDetector.java b/src/main/java/net/helenus/config/GetterMethodDetector.java
index 2d1f908..60a9ec0 100644
--- a/src/main/java/net/helenus/config/GetterMethodDetector.java
+++ b/src/main/java/net/helenus/config/GetterMethodDetector.java
@@ -16,6 +16,7 @@
package net.helenus.config;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.function.Function;
import net.helenus.mapping.annotation.Transient;
@@ -33,6 +34,10 @@ public enum GetterMethodDetector implements Function {
return false;
}
+ if (Modifier.isStatic(method.getModifiers())) {
+ return false;
+ }
+
// Methods marked "Transient" are not mapped, skip them.
if (method.getDeclaredAnnotation(Transient.class) != null) {
return false;
diff --git a/src/main/java/net/helenus/core/AbstractAuditedEntityDraft.java b/src/main/java/net/helenus/core/AbstractAuditedEntityDraft.java
index 5ec76d3..a9a09e2 100644
--- a/src/main/java/net/helenus/core/AbstractAuditedEntityDraft.java
+++ b/src/main/java/net/helenus/core/AbstractAuditedEntityDraft.java
@@ -1,41 +1,38 @@
package net.helenus.core;
-import net.helenus.core.reflect.MapExportable;
-
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
-
+import net.helenus.core.reflect.MapExportable;
public abstract class AbstractAuditedEntityDraft extends AbstractEntityDraft {
- public AbstractAuditedEntityDraft(MapExportable entity) {
- super(entity);
+ public AbstractAuditedEntityDraft(MapExportable entity) {
+ super(entity);
- Date in = new Date();
- LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
- Date now = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
+ Date in = new Date();
+ LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
+ Date now = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
- String who = getCurrentAuditor();
+ String who = getCurrentAuditor();
- if (entity == null) {
- if (who != null) {
- set("createdBy", who);
- }
- set("createdAt", now);
- }
- if (who != null) {
- set("modifiedBy", who);
- }
- set("modifiedAt", now);
+ if (entity == null) {
+ if (who != null) {
+ set("createdBy", who);
+ }
+ set("createdAt", now);
}
-
- protected String getCurrentAuditor() {
- return null;
+ if (who != null) {
+ set("modifiedBy", who);
}
+ set("modifiedAt", now);
+ }
- public Date createdAt() {
- return (Date) get("createdAt", Date.class);
- }
+ protected String getCurrentAuditor() {
+ return null;
+ }
+ public Date createdAt() {
+ return (Date) get("createdAt", Date.class);
+ }
}
diff --git a/src/main/java/net/helenus/core/AbstractEntityDraft.java b/src/main/java/net/helenus/core/AbstractEntityDraft.java
index 54a3edf..fbccb3b 100644
--- a/src/main/java/net/helenus/core/AbstractEntityDraft.java
+++ b/src/main/java/net/helenus/core/AbstractEntityDraft.java
@@ -1,151 +1,159 @@
package net.helenus.core;
-import java.util.*;
-
import com.google.common.primitives.Primitives;
-
+import java.util.*;
import net.helenus.core.reflect.DefaultPrimitiveTypes;
import net.helenus.core.reflect.Drafted;
import net.helenus.core.reflect.MapExportable;
import net.helenus.mapping.MappingUtil;
-
public abstract class AbstractEntityDraft implements Drafted {
- private final Map backingMap = new HashMap();
- private final Set mutatedSet = new HashSet();
- private final MapExportable entity;
- private final Map entityMap;
+ private final Map backingMap = new HashMap();
+ private final MapExportable entity;
+ private final Map entityMap;
+ public AbstractEntityDraft(MapExportable entity) {
+ this.entity = entity;
+ this.entityMap = entity != null ? entity.toMap() : new HashMap();
+ }
- public AbstractEntityDraft(MapExportable entity) {
- this.entity = entity;
- this.entityMap = entity != null ? entity.toMap() : new HashMap();
+ public abstract Class getEntityClass();
+
+ public E build() {
+ return Helenus.map(getEntityClass(), toMap());
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T get(Getter getter, Class> returnType) {
+ return (T) get(this.methodNameFor(getter), returnType);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T get(String key, Class> returnType) {
+ T value = (T) backingMap.get(key);
+
+ if (value == null) {
+ value = (T) entityMap.get(key);
+ if (value == null) {
+
+ if (Primitives.allPrimitiveTypes().contains(returnType)) {
+
+ DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType);
+ if (type == null) {
+ throw new RuntimeException("unknown primitive type " + returnType);
+ }
+
+ return (T) type.getDefaultValue();
+ }
+ }
}
- public abstract Class getEntityClass();
+ return value;
+ }
- public E build() { return Helenus.map(getEntityClass(), toMap()); }
+ protected Object set(Getter getter, Object value) {
+ return set(this.methodNameFor(getter), value);
+ }
- protected T get(String key, Class> returnType) {
- T value = (T) entityMap.get(key);
-
- if (value == null) {
-
- if (Primitives.allPrimitiveTypes().contains(returnType)) {
-
- DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType);
- if (type == null) {
- throw new RuntimeException("unknown primitive type " + returnType);
- }
-
- return (T) type.getDefaultValue();
- }
- }
-
- return value;
+ protected Object set(String key, Object value) {
+ if (key == null || value == null) {
+ return null;
}
- protected Object set(String key, Object value) {
+ backingMap.put(key, value);
+ return value;
+ }
- if (key == null || value == null) {
- return null;
- }
+ @SuppressWarnings("unchecked")
+ protected T mutate(Getter getter, T value) {
+ return (T) mutate(this.methodNameFor(getter), value);
+ }
+ protected Object mutate(String key, Object value) {
+ Objects.requireNonNull(key);
+
+ if (value == null) {
+ return null;
+ }
+
+ if (entity != null) {
+ Map map = entity.toMap();
+
+ if (map.containsKey(key) && !value.equals(map.get(key))) {
backingMap.put(key, value);
- mutatedSet.add(key);
return value;
+ }
+
+ return map.get(key);
+ } else {
+ backingMap.put(key, value);
+
+ return null;
}
+ }
- protected Object mutate(String key, Object value) {
- Objects.requireNonNull(key);
+ private String methodNameFor(Getter getter) {
+ return MappingUtil.resolveMappingProperty(getter).getProperty().getPropertyName();
+ }
- if (value == null) {
- return null;
- }
+ public Object unset(Getter getter) {
+ return unset(methodNameFor(getter));
+ }
- if (entity != null) {
- Map map = entity.toMap();
-
- if (map.containsKey(key) && !value.equals(map.get(key))) {
- backingMap.put(key, value);
- mutatedSet.add(key);
- return value;
- }
-
- return map.get(key);
- } else {
- backingMap.put(key, value);
- mutatedSet.add(key);
-
- return null;
- }
+ public Object unset(String key) {
+ if (key != null) {
+ Object value = backingMap.get(key);
+ backingMap.put(key, null);
+ return value;
}
+ return null;
+ }
- private String methodNameFor(Getter> getter) {
- return MappingUtil.resolveMappingProperty(getter)
- .getProperty()
- .getPropertyName();
+ public boolean reset(Getter getter, T desiredValue) {
+ return this.reset(this.methodNameFor(getter), desiredValue);
+ }
+
+ public boolean reset(String key, T desiredValue) {
+ if (key != null && desiredValue != null) {
+ @SuppressWarnings("unchecked")
+ T currentValue = (T) backingMap.get(key);
+ if (currentValue == null || !currentValue.equals(desiredValue)) {
+ set(key, desiredValue);
+ return true;
+ }
}
+ return false;
+ }
- public Object unset(Getter> getter) {
- return unset(methodNameFor(getter));
+ @Override
+ public Map toMap() {
+ return toMap(entityMap);
+ }
+
+ public Map toMap(Map entityMap) {
+ Map combined;
+ if (entityMap != null && entityMap.size() > 0) {
+ combined = new HashMap(entityMap.size());
+ for (String key : entityMap.keySet()) {
+ combined.put(key, entityMap.get(key));
+ }
+ } else {
+ combined = new HashMap(backingMap.size());
}
-
- public Object unset(String key) {
- if (key != null) {
- Object value = backingMap.get(key);
- backingMap.put(key, null);
- mutatedSet.add(key);
- return value;
- }
- return null;
+ for (String key : mutated()) {
+ combined.put(key, backingMap.get(key));
}
+ return combined;
+ }
- public boolean reset(Getter> getter, T desiredValue) {
- return this.reset(methodNameFor(getter), desiredValue);
- }
-
- public boolean reset(String key, T desiredValue) {
- if (key != null && desiredValue != null) {
- @SuppressWarnings("unchecked")
- T currentValue = (T) backingMap.get(key);
- if (currentValue != null && !currentValue.equals(desiredValue)) {
- return set(key, desiredValue) != null;
- }
- }
- return false;
- }
-
- @Override
- public Map toMap() {
- return toMap(entityMap);
- }
-
- public Map toMap(MapentityMap) {
- Map combined;
- if (entityMap != null && entityMap.size() > 0) {
- combined = new HashMap(entityMap.size());
- for (String key : entityMap.keySet()) {
- combined.put(key, entityMap.get(key));
- }
- } else {
- combined = new HashMap(backingMap.size());
- }
- for (String key : mutatedSet) {
- combined.put(key, backingMap.get(key));
- }
- return combined;
- }
-
- @Override
- public Set mutated() {
- return mutatedSet;
- }
-
- @Override
- public String toString() {
- return backingMap.toString();
- }
+ @Override
+ public Set mutated() {
+ return backingMap.keySet();
+ }
+ @Override
+ public String toString() {
+ return backingMap.toString();
+ }
}
diff --git a/src/main/java/net/helenus/core/AbstractSessionOperations.java b/src/main/java/net/helenus/core/AbstractSessionOperations.java
index 920fabd..5721051 100644
--- a/src/main/java/net/helenus/core/AbstractSessionOperations.java
+++ b/src/main/java/net/helenus/core/AbstractSessionOperations.java
@@ -22,7 +22,6 @@ import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.PrintStream;
import java.util.concurrent.Executor;
-
import net.helenus.mapping.value.ColumnValuePreparer;
import net.helenus.mapping.value.ColumnValueProvider;
import net.helenus.support.HelenusException;
@@ -51,6 +50,8 @@ public abstract class AbstractSessionOperations {
public abstract ConsistencyLevel getDefaultConsistencyLevel();
+ public abstract boolean getDefaultQueryIdempotency();
+
public PreparedStatement prepare(RegularStatement statement) {
try {
log(statement, false);
@@ -122,5 +123,4 @@ public abstract class AbstractSessionOperations {
void printCql(String cql) {
getPrintStream().println(cql);
}
-
}
diff --git a/src/main/java/net/helenus/core/AbstractUnitOfWork.java b/src/main/java/net/helenus/core/AbstractUnitOfWork.java
index dfb1ff7..c621770 100644
--- a/src/main/java/net/helenus/core/AbstractUnitOfWork.java
+++ b/src/main/java/net/helenus/core/AbstractUnitOfWork.java
@@ -17,10 +17,8 @@ package net.helenus.core;
import com.diffplug.common.base.Errors;
import com.google.common.collect.TreeTraverser;
-
import java.util.*;
-
/** Encapsulates the concept of a "transaction" as a unit-of-work. */
public abstract class AbstractUnitOfWork implements UnitOfWork, AutoCloseable {
private final List> nested = new ArrayList<>();
@@ -70,22 +68,25 @@ public abstract class AbstractUnitOfWork implements UnitOfW
return null;
}
- public Map> getCache() { return cache; }
+ public Map> getCache() {
+ return cache;
+ }
private Iterator> getChildNodes() {
return nested.iterator();
}
- /**
- * Checks to see if the work performed between calling begin and now can be committed or not.
- *
- * @return a function from which to chain work that only happens when commit is successful
- * @throws E when the work overlaps with other concurrent writers.
- */
+ /**
+ * Checks to see if the work performed between calling begin and now can be committed or not.
+ *
+ * @return a function from which to chain work that only happens when commit is successful
+ * @throws E when the work overlaps with other concurrent writers.
+ */
public PostCommitFunction commit() throws E {
// All nested UnitOfWork should be committed (not aborted) before calls to commit, check.
boolean canCommit = true;
- TreeTraverser> traverser = TreeTraverser.using(node -> node::getChildNodes);
+ TreeTraverser> traverser =
+ TreeTraverser.using(node -> node::getChildNodes);
for (AbstractUnitOfWork uow : traverser.postOrderTraversal(this)) {
if (this != uow) {
canCommit &= (!uow.aborted && uow.committed);
@@ -112,7 +113,8 @@ public abstract class AbstractUnitOfWork implements UnitOfW
if (parentCache.containsKey(key)) {
// merge the sets
Set ps = parentCache.get(key);
- ps.addAll(cache.get(key)); //TODO(gburd): review this, likely not correct in all cases as-is.
+ ps.addAll(
+ cache.get(key)); //TODO(gburd): review this, likely not correct in all cases as-is.
} else {
// add the missing set
parentCache.put(key, cache.get(key));
@@ -122,9 +124,12 @@ public abstract class AbstractUnitOfWork implements UnitOfW
// Apply all post-commit functions for
if (parent == null) {
- traverser.postOrderTraversal(this).forEach(uow -> {
- uow.applyPostCommitFunctions();
- });
+ traverser
+ .postOrderTraversal(this)
+ .forEach(
+ uow -> {
+ uow.applyPostCommitFunctions();
+ });
return new PostCommitFunction(this, null);
}
}
@@ -137,11 +142,15 @@ public abstract class AbstractUnitOfWork implements UnitOfW
/* Explicitly discard the work and mark it as as such in the log. */
public void abort() {
- TreeTraverser> traverser = TreeTraverser.using(node -> node::getChildNodes);
- traverser.postOrderTraversal(this).forEach(uow -> {
- uow.committed = false;
- uow.aborted = true;
- });
+ TreeTraverser> traverser =
+ TreeTraverser.using(node -> node::getChildNodes);
+ traverser
+ .postOrderTraversal(this)
+ .forEach(
+ uow -> {
+ uow.committed = false;
+ uow.aborted = true;
+ });
// log.record(txn::abort)
// cache.invalidateSince(txn::start time)
}
@@ -165,5 +174,4 @@ public abstract class AbstractUnitOfWork implements UnitOfW
public boolean hasCommitted() {
return committed;
}
-
}
diff --git a/src/main/java/net/helenus/core/CommitThunk.java b/src/main/java/net/helenus/core/CommitThunk.java
index c200061..ff50f4a 100644
--- a/src/main/java/net/helenus/core/CommitThunk.java
+++ b/src/main/java/net/helenus/core/CommitThunk.java
@@ -1,8 +1,7 @@
package net.helenus.core;
-import java.util.function.Function;
@FunctionalInterface
public interface CommitThunk {
- void apply();
+ void apply();
}
diff --git a/src/main/java/net/helenus/core/Helenus.java b/src/main/java/net/helenus/core/Helenus.java
index 26a453b..c0d9bc6 100644
--- a/src/main/java/net/helenus/core/Helenus.java
+++ b/src/main/java/net/helenus/core/Helenus.java
@@ -140,7 +140,14 @@ public final class Helenus {
}
public static HelenusEntity entity(Class> iface) {
- return entity(iface, metadataForEntity.get(iface));
+ Metadata metadata = metadataForEntity.get(iface);
+ if (metadata == null) {
+ HelenusSession session = session();
+ if (session != null) {
+ metadata = session.getMetadata();
+ }
+ }
+ return entity(iface, metadata);
}
public static HelenusEntity entity(Class> iface, Metadata metadata) {
diff --git a/src/main/java/net/helenus/core/HelenusSession.java b/src/main/java/net/helenus/core/HelenusSession.java
index e2a2104..601a773 100644
--- a/src/main/java/net/helenus/core/HelenusSession.java
+++ b/src/main/java/net/helenus/core/HelenusSession.java
@@ -15,10 +15,21 @@
*/
package net.helenus.core;
+import static net.helenus.core.Query.eq;
+
import brave.Tracer;
-import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.datastax.driver.core.*;
+import java.io.Closeable;
+import java.io.PrintStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.Function;
import net.helenus.core.operation.*;
import net.helenus.core.reflect.Drafted;
import net.helenus.core.reflect.HelenusPropertyNode;
@@ -33,19 +44,6 @@ import net.helenus.support.Fun.Tuple6;
import net.helenus.support.HelenusException;
import net.helenus.support.HelenusMappingException;
-import java.io.Closeable;
-import java.io.PrintStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.function.Function;
-
-import static net.helenus.core.Query.eq;
-
public final class HelenusSession extends AbstractSessionOperations implements Closeable {
private final int MAX_CACHE_SIZE = 10000;
@@ -56,6 +54,7 @@ public final class HelenusSession extends AbstractSessionOperations implements C
private volatile String usingKeyspace;
private volatile boolean showCql;
private final ConsistencyLevel defaultConsistencyLevel;
+ private final boolean defaultQueryIdempotency;
private final MetricRegistry metricRegistry;
private final Tracer zipkinTracer;
private final PrintStream printStream;
@@ -68,31 +67,32 @@ public final class HelenusSession extends AbstractSessionOperations implements C
private final StatementColumnValuePreparer valuePreparer;
private final Metadata metadata;
-
HelenusSession(
- Session session,
- String usingKeyspace,
- CodecRegistry registry,
- boolean showCql,
- PrintStream printStream,
- SessionRepositoryBuilder sessionRepositoryBuilder,
- Executor executor,
- boolean dropSchemaOnClose,
- ConsistencyLevel consistencyLevel,
- Class extends UnitOfWork> unitOfWorkClass,
- MetricRegistry metricRegistry,
- Tracer tracer) {
+ Session session,
+ String usingKeyspace,
+ CodecRegistry registry,
+ boolean showCql,
+ PrintStream printStream,
+ SessionRepositoryBuilder sessionRepositoryBuilder,
+ Executor executor,
+ boolean dropSchemaOnClose,
+ ConsistencyLevel consistencyLevel,
+ boolean defaultQueryIdempotency,
+ Class extends UnitOfWork> unitOfWorkClass,
+ MetricRegistry metricRegistry,
+ Tracer tracer) {
this.session = session;
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
this.usingKeyspace =
- Objects.requireNonNull(
- usingKeyspace, "keyspace needs to be selected before creating session");
+ Objects.requireNonNull(
+ usingKeyspace, "keyspace needs to be selected before creating session");
this.showCql = showCql;
this.printStream = printStream;
this.sessionRepository = sessionRepositoryBuilder.build();
this.executor = executor;
this.dropSchemaOnClose = dropSchemaOnClose;
this.defaultConsistencyLevel = consistencyLevel;
+ this.defaultQueryIdempotency = defaultQueryIdempotency;
this.unitOfWorkClass = unitOfWorkClass;
this.metricRegistry = metricRegistry;
this.zipkinTracer = tracer;
@@ -168,46 +168,59 @@ public final class HelenusSession extends AbstractSessionOperations implements C
return metricRegistry;
}
+ @Override
public ConsistencyLevel getDefaultConsistencyLevel() {
return defaultConsistencyLevel;
}
+ @Override
+ public boolean getDefaultQueryIdempotency() {
+ return defaultQueryIdempotency;
+ }
+
public Metadata getMetadata() {
return metadata;
}
public synchronized UnitOfWork begin() {
- return begin(null);
+ return begin(null);
}
public synchronized UnitOfWork begin(UnitOfWork parent) {
try {
Class extends UnitOfWork> clazz = unitOfWorkClass;
- Constructor extends UnitOfWork> ctor = clazz.getConstructor(HelenusSession.class, UnitOfWork.class);
+ Constructor extends UnitOfWork> ctor =
+ clazz.getConstructor(HelenusSession.class, UnitOfWork.class);
UnitOfWork uow = ctor.newInstance(this, parent);
if (parent != null) {
parent.addNestedUnitOfWork(uow);
}
return uow.begin();
- }
- catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
- throw new HelenusException(String.format("Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()), e);
+ } catch (NoSuchMethodException
+ | InvocationTargetException
+ | InstantiationException
+ | IllegalAccessException e) {
+ throw new HelenusException(
+ String.format(
+ "Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()),
+ e);
}
}
public SelectOperation select(E pojo) {
- Objects.requireNonNull(pojo, "supplied object must be a dsl for a registered entity but cannot be null");
+ Objects.requireNonNull(
+ pojo, "supplied object must be a dsl for a registered entity but cannot be null");
ColumnValueProvider valueProvider = getValueProvider();
HelenusEntity entity = Helenus.resolve(pojo);
Class> entityClass = entity.getMappingInterface();
return new SelectOperation(
- this,
- entity,
- (r) -> {
- Map map = new ValueProviderMap(r, valueProvider, entity);
- return (E) Helenus.map(entityClass, map);
- });
+ this,
+ entity,
+ (r) -> {
+ Map map = new ValueProviderMap(r, valueProvider, entity);
+ return (E) Helenus.map(entityClass, map);
+ });
}
public SelectOperation select(Class entityClass) {
@@ -216,12 +229,12 @@ public final class HelenusSession extends AbstractSessionOperations implements C
HelenusEntity entity = Helenus.entity(entityClass);
return new SelectOperation(
- this,
- entity,
- (r) -> {
- Map map = new ValueProviderMap(r, valueProvider, entity);
- return (E) Helenus.map(entityClass, map);
- });
+ this,
+ entity,
+ (r) -> {
+ Map map = new ValueProviderMap(r, valueProvider, entity);
+ return (E) Helenus.map(entityClass, map);
+ });
}
public SelectOperation select() {
@@ -234,7 +247,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
}
public SelectOperation selectAll(E pojo) {
- Objects.requireNonNull(pojo, "supplied object must be a dsl for a registered entity but cannot be null");
+ Objects.requireNonNull(
+ pojo, "supplied object must be a dsl for a registered entity but cannot be null");
HelenusEntity entity = Helenus.resolve(pojo);
return new SelectOperation(this, entity);
}
@@ -406,51 +420,62 @@ public final class HelenusSession extends AbstractSessionOperations implements C
public UpdateOperation update(Drafted drafted) {
if (drafted instanceof AbstractEntityDraft == false) {
- throw new HelenusMappingException("update of draft objects that don't inherit from AbstractEntityDraft is not yet supported");
+ throw new HelenusMappingException(
+ "update of draft objects that don't inherit from AbstractEntityDraft is not yet supported");
}
- AbstractEntityDraft draft = (AbstractEntityDraft)drafted;
+ AbstractEntityDraft draft = (AbstractEntityDraft) drafted;
UpdateOperation update = new UpdateOperation(this, draft);
Map map = draft.toMap();
Set mutatedProperties = draft.mutated();
HelenusEntity entity = Helenus.entity(draft.getEntityClass());
// Add all the mutated values contained in the draft.
- entity.getOrderedProperties().forEach(property -> {
- switch (property.getColumnType()) {
- case PARTITION_KEY:
- case CLUSTERING_COLUMN:
- break;
- default:
- String propertyName = property.getPropertyName();
- if (mutatedProperties.contains(propertyName)) {
- Object value = map.get(propertyName);
- Getter getter = new Getter() {
- @Override
- public Object get() {
- throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty()));
+ entity
+ .getOrderedProperties()
+ .forEach(
+ property -> {
+ switch (property.getColumnType()) {
+ case PARTITION_KEY:
+ case CLUSTERING_COLUMN:
+ break;
+ default:
+ String propertyName = property.getPropertyName();
+ if (mutatedProperties.contains(propertyName)) {
+ Object value = map.get(propertyName);
+ Getter getter =
+ new Getter() {
+ @Override
+ public Object get() {
+ throw new DslPropertyException(
+ new HelenusPropertyNode(property, Optional.empty()));
+ }
+ };
+ update.set(getter, value);
+ }
}
- };
- update.set(getter, value);
- }
- }
- });
+ });
// Add the partition and clustering keys if they were in the draft (normally the case).
- entity.getOrderedProperties().forEach(property -> {
- switch (property.getColumnType()) {
- case PARTITION_KEY:
- case CLUSTERING_COLUMN:
- String propertyName = property.getPropertyName();
- Object value = map.get(propertyName);
- Getter getter = new Getter() {
- @Override
- public Object get() {
- throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty()));
- }
- };
- update.where(getter, eq(value));
- }
- });
+ entity
+ .getOrderedProperties()
+ .forEach(
+ property -> {
+ switch (property.getColumnType()) {
+ case PARTITION_KEY:
+ case CLUSTERING_COLUMN:
+ String propertyName = property.getPropertyName();
+ Object value = map.get(propertyName);
+ Getter getter =
+ new Getter() {
+ @Override
+ public Object get() {
+ throw new DslPropertyException(
+ new HelenusPropertyNode(property, Optional.empty()));
+ }
+ };
+ update.where(getter, eq(value));
+ }
+ });
return update;
}
@@ -473,9 +498,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
}
public InsertOperation insert(T pojo) {
- Objects.requireNonNull(pojo, "supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
+ Objects.requireNonNull(
+ pojo,
+ "supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
HelenusEntity entity = null;
- try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {}
+ try {
+ entity = Helenus.resolve(pojo);
+ } catch (HelenusMappingException e) {
+ }
if (entity != null) {
return new InsertOperation(this, entity.getMappingInterface(), true);
} else {
@@ -483,7 +513,9 @@ public final class HelenusSession extends AbstractSessionOperations implements C
}
}
- public InsertOperation insert(Drafted draft) { return insert(draft.build(), draft.mutated()); }
+ public InsertOperation insert(Drafted draft) {
+ return insert(draft.build(), draft.mutated());
+ }
private InsertOperation insert(T pojo, Set mutations) {
Objects.requireNonNull(pojo, "pojo is empty");
@@ -507,9 +539,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
}
public InsertOperation upsert(T pojo) {
- Objects.requireNonNull(pojo, "supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
+ Objects.requireNonNull(
+ pojo,
+ "supplied object must be either an instance of the entity class or a dsl for it, but cannot be null");
HelenusEntity entity = null;
- try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {}
+ try {
+ entity = Helenus.resolve(pojo);
+ } catch (HelenusMappingException e) {
+ }
if (entity != null) {
return new InsertOperation(this, entity.getMappingInterface(), false);
} else {
@@ -582,5 +619,4 @@ public final class HelenusSession extends AbstractSessionOperations implements C
break;
}
}
-
}
diff --git a/src/main/java/net/helenus/core/PostCommitFunction.java b/src/main/java/net/helenus/core/PostCommitFunction.java
index 22835c5..3ba2b8b 100644
--- a/src/main/java/net/helenus/core/PostCommitFunction.java
+++ b/src/main/java/net/helenus/core/PostCommitFunction.java
@@ -1,30 +1,29 @@
package net.helenus.core;
-
-import java.util.Objects;
import java.util.*;
+import java.util.Objects;
public class PostCommitFunction implements java.util.function.Function {
- private final UnitOfWork uow;
- private final List postCommit;
+ private final UnitOfWork uow;
+ private final List postCommit;
- PostCommitFunction(UnitOfWork uow, List postCommit) {
- this.uow = uow;
- this.postCommit = postCommit;
- }
+ PostCommitFunction(UnitOfWork uow, List postCommit) {
+ this.uow = uow;
+ this.postCommit = postCommit;
+ }
- public void andThen(CommitThunk after) {
- Objects.requireNonNull(after);
- if (postCommit == null) {
- after.apply();
- } else {
- postCommit.add(after);
- }
+ public void andThen(CommitThunk after) {
+ Objects.requireNonNull(after);
+ if (postCommit == null) {
+ after.apply();
+ } else {
+ postCommit.add(after);
}
+ }
- @Override
- public R apply(T t) {
- return null;
- }
+ @Override
+ public R apply(T t) {
+ return null;
+ }
}
diff --git a/src/main/java/net/helenus/core/SchemaUtil.java b/src/main/java/net/helenus/core/SchemaUtil.java
index e2bb681..6a228e9 100644
--- a/src/main/java/net/helenus/core/SchemaUtil.java
+++ b/src/main/java/net/helenus/core/SchemaUtil.java
@@ -17,16 +17,22 @@ package net.helenus.core;
import com.datastax.driver.core.*;
import com.datastax.driver.core.IndexMetadata;
+import com.datastax.driver.core.querybuilder.IsNotNullClause;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.core.schemabuilder.*;
import com.datastax.driver.core.schemabuilder.Create.Options;
import java.util.*;
import java.util.stream.Collectors;
+import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.mapping.*;
import net.helenus.mapping.ColumnType;
+import net.helenus.mapping.annotation.ClusteringColumn;
import net.helenus.mapping.type.OptionalColumnMetadata;
import net.helenus.support.CqlUtil;
import net.helenus.support.HelenusMappingException;
+
public final class SchemaUtil {
private SchemaUtil() {}
@@ -143,6 +149,78 @@ public final class SchemaUtil {
return SchemaBuilder.dropType(type.getTypeName()).ifExists();
}
+ public static SchemaStatement createMaterializedView(
+ String keyspace, String viewName, HelenusEntity entity) {
+ if (entity.getType() != HelenusEntityType.VIEW) {
+ throw new HelenusMappingException("expected view entity " + entity);
+ }
+
+ if (entity == null) {
+ throw new HelenusMappingException("no entity or table to select data");
+ }
+
+ List props = new ArrayList();
+ entity
+ .getOrderedProperties()
+ .stream()
+ .map(p -> new HelenusPropertyNode(p, Optional.empty()))
+ .forEach(p -> props.add(p));
+
+ Select.Selection selection = QueryBuilder.select();
+
+ for (HelenusPropertyNode prop : props) {
+ String columnName = prop.getColumnName();
+ selection = selection.column(columnName);
+ }
+ Class> iface = entity.getMappingInterface();
+ String tableName = Helenus.entity(iface.getInterfaces()[0]).getName().toCql();
+ Select.Where where = selection.from(tableName).where();
+ List p = new ArrayList(props.size());
+ List c = new ArrayList(props.size());
+ List o = new ArrayList(props.size());
+
+ for (HelenusPropertyNode prop : props) {
+ String columnName = prop.getColumnName();
+ switch (prop.getProperty().getColumnType()) {
+ case PARTITION_KEY:
+ p.add(columnName);
+ where = where.and(new IsNotNullClause(columnName));
+ break;
+
+ case CLUSTERING_COLUMN:
+ c.add(columnName);
+ where = where.and(new IsNotNullClause(columnName));
+
+ ClusteringColumn clusteringColumn = prop.getProperty().getGetterMethod().getAnnotation(ClusteringColumn.class);
+ if (clusteringColumn != null && clusteringColumn.ordering() != null) {
+ o.add(columnName + " " + clusteringColumn.ordering().cql());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ String primaryKey =
+ "PRIMARY KEY ("
+ + ((p.size() > 1) ? "(" + String.join(", ", p) + ")" : p.get(0))
+ + ((c.size() > 0)
+ ? ", " + ((c.size() > 1) ? "(" + String.join(", ", c) + ")" : c.get(0))
+ : "")
+ + ")";
+
+ String clustering = "";
+ if (o.size() > 0) {
+ clustering = "WITH CLUSTERING ORDER BY (" + String.join(", ", o) + ")";
+ }
+ return new CreateMaterializedView(keyspace, viewName, where, primaryKey, clustering);
+ }
+
+ public static SchemaStatement dropMaterializedView(
+ String keyspace, String viewName, HelenusEntity entity) {
+ return new DropMaterializedView(keyspace, viewName);
+ }
+
public static SchemaStatement createTable(HelenusEntity entity) {
if (entity.getType() != HelenusEntityType.TABLE) {
diff --git a/src/main/java/net/helenus/core/SessionInitializer.java b/src/main/java/net/helenus/core/SessionInitializer.java
index 677eb1b..f6ecfd6 100644
--- a/src/main/java/net/helenus/core/SessionInitializer.java
+++ b/src/main/java/net/helenus/core/SessionInitializer.java
@@ -25,10 +25,13 @@ import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
+import net.helenus.core.reflect.DslExportable;
import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.HelenusEntityType;
+import net.helenus.mapping.MappingUtil;
import net.helenus.mapping.value.ColumnValuePreparer;
import net.helenus.mapping.value.ColumnValueProvider;
+import net.helenus.support.Either;
import net.helenus.support.HelenusException;
import net.helenus.support.PackageUtil;
@@ -39,6 +42,7 @@ public final class SessionInitializer extends AbstractSessionOperations {
private String usingKeyspace;
private boolean showCql = false;
private ConsistencyLevel consistencyLevel;
+ private boolean idempotent = true;
private MetricRegistry metricRegistry = new MetricRegistry();
private Tracer zipkinTracer;
private PrintStream printStream = System.out;
@@ -52,7 +56,7 @@ public final class SessionInitializer extends AbstractSessionOperations {
private KeyspaceMetadata keyspaceMetadata;
- private final List initList = new ArrayList();
+ private final List>> initList = new ArrayList>>();
private AutoDdl autoDdl = AutoDdl.UPDATE;
SessionInitializer(Session session) {
@@ -125,6 +129,15 @@ public final class SessionInitializer extends AbstractSessionOperations {
return consistencyLevel;
}
+ public SessionInitializer idempotentQueryExecution(boolean idempotent) {
+ this.idempotent = idempotent;
+ return this;
+ }
+
+ public boolean getDefaultQueryIdempotency() {
+ return idempotent;
+ }
+
@Override
public PrintStream getPrintStream() {
return printStream;
@@ -171,7 +184,10 @@ public final class SessionInitializer extends AbstractSessionOperations {
PackageUtil.getClasses(packageName)
.stream()
.filter(c -> c.isInterface() && !c.isAnnotation())
- .forEach(initList::add);
+ .forEach(
+ clazz -> {
+ initList.add(Either.right(clazz));
+ });
} catch (IOException | ClassNotFoundException e) {
throw new HelenusException("fail to add package " + packageName, e);
}
@@ -183,7 +199,7 @@ public final class SessionInitializer extends AbstractSessionOperations {
int len = dsls.length;
for (int i = 0; i != len; ++i) {
Object obj = Objects.requireNonNull(dsls[i], "element " + i + " is empty");
- initList.add(obj);
+ initList.add(Either.left(obj));
}
return this;
}
@@ -241,6 +257,7 @@ public final class SessionInitializer extends AbstractSessionOperations {
executor,
autoDdl == AutoDdl.CREATE_DROP,
consistencyLevel,
+ idempotent,
unitOfWorkClass,
metricRegistry,
zipkinTracer);
@@ -250,7 +267,19 @@ public final class SessionInitializer extends AbstractSessionOperations {
Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator");
- initList.forEach(dsl -> sessionRepository.add(dsl));
+ initList.forEach(
+ (either) -> {
+ Class> iface = null;
+ if (either.isLeft()) {
+ iface = MappingUtil.getMappingInterface(either.getLeft());
+ } else {
+ iface = either.getRight();
+ }
+
+ DslExportable dsl = (DslExportable) Helenus.dsl(iface);
+ dsl.setCassandraMetadataForHelenusSesion(session.getCluster().getMetadata());
+ sessionRepository.add(dsl);
+ });
TableOperations tableOps = new TableOperations(this, dropUnusedColumns, dropUnusedIndexes);
UserTypeOperations userTypeOps = new UserTypeOperations(this, dropUnusedColumns);
@@ -258,8 +287,16 @@ public final class SessionInitializer extends AbstractSessionOperations {
switch (autoDdl) {
case CREATE_DROP:
- // Drop tables first, otherwise a `DROP TYPE ...` will fail as the type is still referenced
- // by a table.
+ // Drop view first, otherwise a `DROP TABLE ...` will fail as the type is still referenced
+ // by a view.
+ sessionRepository
+ .entities()
+ .stream()
+ .filter(e -> e.getType() == HelenusEntityType.VIEW)
+ .forEach(e -> tableOps.dropView(e));
+
+ // Drop tables second, before DROP TYPE otherwise a `DROP TYPE ...` will fail as the type is
+ // still referenced by a table.
sessionRepository
.entities()
.stream()
@@ -278,6 +315,12 @@ public final class SessionInitializer extends AbstractSessionOperations {
.filter(e -> e.getType() == HelenusEntityType.TABLE)
.forEach(e -> tableOps.createTable(e));
+ sessionRepository
+ .entities()
+ .stream()
+ .filter(e -> e.getType() == HelenusEntityType.VIEW)
+ .forEach(e -> tableOps.createView(e));
+
break;
case VALIDATE:
@@ -288,16 +331,29 @@ public final class SessionInitializer extends AbstractSessionOperations {
.stream()
.filter(e -> e.getType() == HelenusEntityType.TABLE)
.forEach(e -> tableOps.validateTable(getTableMetadata(e), e));
+
break;
case UPDATE:
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.updateUserType(getUserType(e), e));
+ sessionRepository
+ .entities()
+ .stream()
+ .filter(e -> e.getType() == HelenusEntityType.VIEW)
+ .forEach(e -> tableOps.dropView(e));
+
sessionRepository
.entities()
.stream()
.filter(e -> e.getType() == HelenusEntityType.TABLE)
.forEach(e -> tableOps.updateTable(getTableMetadata(e), e));
+
+ sessionRepository
+ .entities()
+ .stream()
+ .filter(e -> e.getType() == HelenusEntityType.VIEW)
+ .forEach(e -> tableOps.createView(e));
break;
}
diff --git a/src/main/java/net/helenus/core/TableOperations.java b/src/main/java/net/helenus/core/TableOperations.java
index f9c83d0..3c602d6 100644
--- a/src/main/java/net/helenus/core/TableOperations.java
+++ b/src/main/java/net/helenus/core/TableOperations.java
@@ -35,14 +35,11 @@ public final class TableOperations {
}
public void createTable(HelenusEntity entity) {
-
sessionOps.execute(SchemaUtil.createTable(entity), true);
-
executeBatch(SchemaUtil.createIndexes(entity));
}
public void dropTable(HelenusEntity entity) {
-
sessionOps.execute(SchemaUtil.dropTable(entity), true);
}
@@ -50,7 +47,10 @@ public final class TableOperations {
if (tmd == null) {
throw new HelenusException(
- "table not exists " + entity.getName() + "for entity " + entity.getMappingInterface());
+ "table does not exists "
+ + entity.getName()
+ + "for entity "
+ + entity.getMappingInterface());
}
List list = SchemaUtil.alterTable(tmd, entity, dropUnusedColumns);
@@ -67,7 +67,31 @@ public final class TableOperations {
}
public void updateTable(TableMetadata tmd, HelenusEntity entity) {
+ if (tmd == null) {
+ createTable(entity);
+ return;
+ }
+ executeBatch(SchemaUtil.alterTable(tmd, entity, dropUnusedColumns));
+ executeBatch(SchemaUtil.alterIndexes(tmd, entity, dropUnusedIndexes));
+ }
+
+ public void createView(HelenusEntity entity) {
+ sessionOps.execute(
+ SchemaUtil.createMaterializedView(
+ sessionOps.usingKeyspace(), entity.getName().toCql(), entity),
+ true);
+ // executeBatch(SchemaUtil.createIndexes(entity)); NOTE: Unfortunately C* 3.10 does not yet support 2i on materialized views.
+ }
+
+ public void dropView(HelenusEntity entity) {
+ sessionOps.execute(
+ SchemaUtil.dropMaterializedView(
+ sessionOps.usingKeyspace(), entity.getName().toCql(), entity),
+ true);
+ }
+
+ public void updateView(TableMetadata tmd, HelenusEntity entity) {
if (tmd == null) {
createTable(entity);
return;
diff --git a/src/main/java/net/helenus/core/UnitOfWork.java b/src/main/java/net/helenus/core/UnitOfWork.java
index 0cfa536..f27b76c 100644
--- a/src/main/java/net/helenus/core/UnitOfWork.java
+++ b/src/main/java/net/helenus/core/UnitOfWork.java
@@ -15,44 +15,42 @@
*/
package net.helenus.core;
-import net.helenus.support.Either;
import java.util.Map;
import java.util.Set;
public interface UnitOfWork extends AutoCloseable {
- /**
- * Marks the beginning of a transactional section of work. Will write a record to the shared
- * write-ahead log.
- *
- * @return the handle used to commit or abort the work.
- */
- UnitOfWork begin();
+ /**
+ * Marks the beginning of a transactional section of work. Will write a record to the shared
+ * write-ahead log.
+ *
+ * @return the handle used to commit or abort the work.
+ */
+ UnitOfWork begin();
- UnitOfWork addNestedUnitOfWork(UnitOfWork uow);
+ UnitOfWork addNestedUnitOfWork(UnitOfWork uow);
- /**
- * Checks to see if the work performed between calling begin and now can be committed or not.
- *
- * @return a function from which to chain work that only happens when commit is successful
- * @throws E when the work overlaps with other concurrent writers.
- */
- PostCommitFunction commit() throws E;
+ /**
+ * Checks to see if the work performed between calling begin and now can be committed or not.
+ *
+ * @return a function from which to chain work that only happens when commit is successful
+ * @throws E when the work overlaps with other concurrent writers.
+ */
+ PostCommitFunction commit() throws E;
- /**
- * Explicitly abort the work within this unit of work. Any nested aborted unit of work
- * will trigger the entire unit of work to commit.
- */
- void abort();
+ /**
+ * Explicitly abort the work within this unit of work. Any nested aborted unit of work will
+ * trigger the entire unit of work to commit.
+ */
+ void abort();
+ boolean hasAborted();
- boolean hasAborted();
+ boolean hasCommitted();
- boolean hasCommitted();
+ //Either> cacheLookup(String key);
+ Set cacheLookup(String key);
- //Either> cacheLookup(String key);
- Set cacheLookup(String key);
-
- Map> getCache();
+ Map> getCache();
}
diff --git a/src/main/java/net/helenus/core/UnitOfWorkImpl.java b/src/main/java/net/helenus/core/UnitOfWorkImpl.java
index b9aab3b..52cae59 100644
--- a/src/main/java/net/helenus/core/UnitOfWorkImpl.java
+++ b/src/main/java/net/helenus/core/UnitOfWorkImpl.java
@@ -19,9 +19,8 @@ import net.helenus.support.HelenusException;
class UnitOfWorkImpl extends AbstractUnitOfWork {
- @SuppressWarnings("unchecked")
- public UnitOfWorkImpl(HelenusSession session, UnitOfWork parent) {
- super(session, (AbstractUnitOfWork) parent);
- }
-
+ @SuppressWarnings("unchecked")
+ public UnitOfWorkImpl(HelenusSession session, UnitOfWork parent) {
+ super(session, (AbstractUnitOfWork) parent);
+ }
}
diff --git a/src/main/java/net/helenus/core/operation/AbstractFilterOptionalOperation.java b/src/main/java/net/helenus/core/operation/AbstractFilterOptionalOperation.java
index 8ed14af..6abfd81 100644
--- a/src/main/java/net/helenus/core/operation/AbstractFilterOptionalOperation.java
+++ b/src/main/java/net/helenus/core/operation/AbstractFilterOptionalOperation.java
@@ -19,11 +19,11 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-
import net.helenus.core.*;
import net.helenus.mapping.HelenusProperty;
-public abstract class AbstractFilterOptionalOperation>
+public abstract class AbstractFilterOptionalOperation<
+ E, O extends AbstractFilterOptionalOperation>
extends AbstractOptionalOperation {
protected Map> filters = null;
diff --git a/src/main/java/net/helenus/core/operation/AbstractFilterStreamOperation.java b/src/main/java/net/helenus/core/operation/AbstractFilterStreamOperation.java
index 755e220..b78daf1 100644
--- a/src/main/java/net/helenus/core/operation/AbstractFilterStreamOperation.java
+++ b/src/main/java/net/helenus/core/operation/AbstractFilterStreamOperation.java
@@ -19,11 +19,11 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-
import net.helenus.core.*;
import net.helenus.mapping.HelenusProperty;
-public abstract class AbstractFilterStreamOperation>
+public abstract class AbstractFilterStreamOperation<
+ E, O extends AbstractFilterStreamOperation>
extends AbstractStreamOperation {
protected Map> filters = null;
diff --git a/src/main/java/net/helenus/core/operation/AbstractOperation.java b/src/main/java/net/helenus/core/operation/AbstractOperation.java
index 46739b9..8eb7961 100644
--- a/src/main/java/net/helenus/core/operation/AbstractOperation.java
+++ b/src/main/java/net/helenus/core/operation/AbstractOperation.java
@@ -17,8 +17,6 @@ package net.helenus.core.operation;
import com.codahale.metrics.Timer;
import com.datastax.driver.core.ResultSet;
-
-import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.UnitOfWork;
@@ -40,7 +38,6 @@ public abstract class AbstractOperation>
return new PreparedOperation(prepareStatement(), this);
}
-
public E sync() {
final Timer.Context context = requestLatency.time();
try {
@@ -72,5 +69,4 @@ public abstract class AbstractOperation>
if (uow == null) return async();
return CompletableFuture.supplyAsync(() -> sync(uow));
}
-
}
diff --git a/src/main/java/net/helenus/core/operation/AbstractOptionalOperation.java b/src/main/java/net/helenus/core/operation/AbstractOptionalOperation.java
index 93ec79d..1d34223 100644
--- a/src/main/java/net/helenus/core/operation/AbstractOptionalOperation.java
+++ b/src/main/java/net/helenus/core/operation/AbstractOptionalOperation.java
@@ -21,12 +21,10 @@ import com.datastax.driver.core.ResultSet;
import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
-
import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.UnitOfWork;
@@ -114,5 +112,4 @@ public abstract class AbstractOptionalOperation>supplyAsync(() -> sync(uow));
}
-
}
diff --git a/src/main/java/net/helenus/core/operation/AbstractStatementOperation.java b/src/main/java/net/helenus/core/operation/AbstractStatementOperation.java
index 19a0682..5177724 100644
--- a/src/main/java/net/helenus/core/operation/AbstractStatementOperation.java
+++ b/src/main/java/net/helenus/core/operation/AbstractStatementOperation.java
@@ -32,7 +32,8 @@ import net.helenus.support.HelenusException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public abstract class AbstractStatementOperation> extends Operation {
+public abstract class AbstractStatementOperation>
+ extends Operation {
final Logger logger = LoggerFactory.getLogger(getClass());
@@ -44,6 +45,7 @@ public abstract class AbstractStatementOperation>
extends AbstractStatementOperation {
@@ -113,5 +104,4 @@ public abstract class AbstractStreamOperation>supplyAsync(() -> sync(uow));
}
-
}
diff --git a/src/main/java/net/helenus/core/operation/BoundOptionalOperation.java b/src/main/java/net/helenus/core/operation/BoundOptionalOperation.java
index 4230bab..c3f5332 100644
--- a/src/main/java/net/helenus/core/operation/BoundOptionalOperation.java
+++ b/src/main/java/net/helenus/core/operation/BoundOptionalOperation.java
@@ -34,7 +34,9 @@ public final class BoundOptionalOperation
}
@Override
- public Optional transform(ResultSet resultSet) { return delegate.transform(resultSet); }
+ public Optional transform(ResultSet resultSet) {
+ return delegate.transform(resultSet);
+ }
@Override
public Statement buildStatement(boolean cached) {
diff --git a/src/main/java/net/helenus/core/operation/BoundStreamOperation.java b/src/main/java/net/helenus/core/operation/BoundStreamOperation.java
index 4210b04..7a3cf2c 100644
--- a/src/main/java/net/helenus/core/operation/BoundStreamOperation.java
+++ b/src/main/java/net/helenus/core/operation/BoundStreamOperation.java
@@ -26,14 +26,17 @@ public final class BoundStreamOperation
private final BoundStatement boundStatement;
private final AbstractStreamOperation delegate;
- public BoundStreamOperation(BoundStatement boundStatement, AbstractStreamOperation operation) {
+ public BoundStreamOperation(
+ BoundStatement boundStatement, AbstractStreamOperation operation) {
super(operation.sessionOps);
this.boundStatement = boundStatement;
this.delegate = operation;
}
@Override
- public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
+ public String getStatementCacheKey() {
+ return delegate.getStatementCacheKey();
+ }
@Override
public Stream transform(ResultSet resultSet) {
@@ -41,5 +44,7 @@ public final class BoundStreamOperation
}
@Override
- public Statement buildStatement(boolean cached) { return boundStatement; }
+ public Statement buildStatement(boolean cached) {
+ return boundStatement;
+ }
}
diff --git a/src/main/java/net/helenus/core/operation/InsertOperation.java b/src/main/java/net/helenus/core/operation/InsertOperation.java
index 52ad767..3ee0c8a 100644
--- a/src/main/java/net/helenus/core/operation/InsertOperation.java
+++ b/src/main/java/net/helenus/core/operation/InsertOperation.java
@@ -19,10 +19,9 @@ import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.google.common.base.Joiner;
import java.util.*;
import java.util.function.Function;
-
-import com.google.common.base.Joiner;
import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.Getter;
import net.helenus.core.Helenus;
@@ -41,7 +40,8 @@ public final class InsertOperation extends AbstractOperation> values = new ArrayList>();
+ private final List> values =
+ new ArrayList>();
private final T pojo;
private final Class> resultType;
private boolean ifNotExists;
@@ -57,7 +57,8 @@ public final class InsertOperation extends AbstractOperation resultType, boolean ifNotExists) {
+ public InsertOperation(
+ AbstractSessionOperations sessionOperations, Class> resultType, boolean ifNotExists) {
super(sessionOperations);
this.ifNotExists = ifNotExists;
@@ -172,7 +173,7 @@ public final class InsertOperation extends AbstractOperation> converter =
- prop.getReadConverter(sessionOps.getSessionRepository());
+ prop.getReadConverter(sessionOps.getSessionRepository());
if (converter.isPresent()) {
backingMap.put(key, converter.get().apply(backingMap.get(key)));
}
@@ -232,22 +233,25 @@ public final class InsertOperation extends AbstractOperation keys = new ArrayList<>(values.size());
values.forEach(
- t -> {
- HelenusPropertyNode prop = t._1;
- switch (prop.getProperty().getColumnType()) {
- case PARTITION_KEY:
- case CLUSTERING_COLUMN:
- keys.add(prop.getColumnName() + "==" + t._2.toString());
- break;
- default:
- break;
- }
- });
+ t -> {
+ HelenusPropertyNode prop = t._1;
+ switch (prop.getProperty().getColumnType()) {
+ case PARTITION_KEY:
+ case CLUSTERING_COLUMN:
+ keys.add(prop.getColumnName() + "==" + t._2.toString());
+ break;
+ default:
+ break;
+ }
+ });
return entity.getName() + ": " + Joiner.on(",").join(keys);
}
@Override
public T sync(UnitOfWork uow) {
+ if (uow == null) {
+ return sync();
+ }
T result = super.sync(uow);
Class> iface = entity.getMappingInterface();
if (resultType == iface) {
@@ -260,5 +264,4 @@ public final class InsertOperation extends AbstractOperation {
- protected final AbstractSessionOperations sessionOps;
- protected final Meter uowCacheHits;
- protected final Meter uowCacheMiss;
- protected final Timer requestLatency;
+ protected final AbstractSessionOperations sessionOps;
+ protected final Meter uowCacheHits;
+ protected final Meter uowCacheMiss;
+ protected final Timer requestLatency;
- Operation(AbstractSessionOperations sessionOperations) {
- this.sessionOps = sessionOperations;
- MetricRegistry metrics = sessionOperations.getMetricRegistry();
- this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
- this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
- this.requestLatency = metrics.timer("net.helenus.request-latency");
+ Operation(AbstractSessionOperations sessionOperations) {
+ this.sessionOps = sessionOperations;
+ MetricRegistry metrics = sessionOperations.getMetricRegistry();
+ this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
+ this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
+ this.requestLatency = metrics.timer("net.helenus.request-latency");
+ }
+
+ public ResultSet execute(
+ AbstractSessionOperations session,
+ UnitOfWork uow,
+ TraceContext traceContext,
+ boolean showValues,
+ boolean cached) {
+
+ // Start recording in a Zipkin sub-span our execution time to perform this operation.
+ Tracer tracer = session.getZipkinTracer();
+ Span span = null;
+ if (tracer != null && traceContext != null) {
+ span = tracer.newChild(traceContext);
}
- public ResultSet execute(AbstractSessionOperations session, UnitOfWork uow, TraceContext traceContext, boolean showValues, boolean cached) {
+ try {
- // Start recording in a Zipkin sub-span our execution time to perform this operation.
- Tracer tracer = session.getZipkinTracer();
- Span span = null;
- if (tracer != null && traceContext != null) {
- span = tracer.newChild(traceContext);
- }
+ if (span != null) {
+ span.name("cassandra");
+ span.start();
+ }
- try {
+ Statement statement = options(buildStatement(cached));
+ ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
+ return futureResultSet.get();
- if (span != null) {
- span.name("cassandra");
- span.start();
- }
+ } catch (InterruptedException | ExecutionException e) {
- Statement statement = options(buildStatement(cached));
- ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
- return futureResultSet.get();
+ throw new RuntimeException(e);
- } catch (InterruptedException | ExecutionException e) {
+ } finally {
- throw new RuntimeException(e);
-
- } finally {
-
- if (span != null) {
- span.finish();
- }
-
- }
+ if (span != null) {
+ span.finish();
+ }
}
+ }
- public Statement options(Statement statement) { return statement; }
+ public Statement options(Statement statement) {
+ return statement;
+ }
- public Statement buildStatement(boolean cached) { return null; }
-
- public String getStatementCacheKey() { return null; }
+ public Statement buildStatement(boolean cached) {
+ return null;
+ }
+ public String getStatementCacheKey() {
+ return null;
+ }
}
diff --git a/src/main/java/net/helenus/core/operation/PreparedStreamOperation.java b/src/main/java/net/helenus/core/operation/PreparedStreamOperation.java
index b622874..cd0f6be 100644
--- a/src/main/java/net/helenus/core/operation/PreparedStreamOperation.java
+++ b/src/main/java/net/helenus/core/operation/PreparedStreamOperation.java
@@ -17,7 +17,6 @@ package net.helenus.core.operation;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
-import java.util.regex.Pattern;
public final class PreparedStreamOperation {
diff --git a/src/main/java/net/helenus/core/operation/SelectFirstOperation.java b/src/main/java/net/helenus/core/operation/SelectFirstOperation.java
index ff88555..d5cf01e 100644
--- a/src/main/java/net/helenus/core/operation/SelectFirstOperation.java
+++ b/src/main/java/net/helenus/core/operation/SelectFirstOperation.java
@@ -38,7 +38,9 @@ public final class SelectFirstOperation
}
@Override
- public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
+ public String getStatementCacheKey() {
+ return delegate.getStatementCacheKey();
+ }
@Override
public BuiltStatement buildStatement(boolean cached) {
diff --git a/src/main/java/net/helenus/core/operation/SelectFirstTransformingOperation.java b/src/main/java/net/helenus/core/operation/SelectFirstTransformingOperation.java
index 1d95256..8ef4f60 100644
--- a/src/main/java/net/helenus/core/operation/SelectFirstTransformingOperation.java
+++ b/src/main/java/net/helenus/core/operation/SelectFirstTransformingOperation.java
@@ -36,7 +36,9 @@ public final class SelectFirstTransformingOperation
}
@Override
- public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
+ public String getStatementCacheKey() {
+ return delegate.getStatementCacheKey();
+ }
@Override
public BuiltStatement buildStatement(boolean cached) {
diff --git a/src/main/java/net/helenus/core/operation/SelectOperation.java b/src/main/java/net/helenus/core/operation/SelectOperation.java
index 05403d1..e483659 100644
--- a/src/main/java/net/helenus/core/operation/SelectOperation.java
+++ b/src/main/java/net/helenus/core/operation/SelectOperation.java
@@ -23,13 +23,12 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.core.querybuilder.Select.Selection;
import com.datastax.driver.core.querybuilder.Select.Where;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.Iterables;
import net.helenus.core.*;
import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.mapping.HelenusEntity;
@@ -48,6 +47,7 @@ public final class SelectOperation extends AbstractFilterStreamOperation ordering = null;
protected Integer limit = null;
protected boolean allowFiltering = false;
+ protected String alternateTableName = null;
@SuppressWarnings("unchecked")
public SelectOperation(AbstractSessionOperations sessionOperations) {
@@ -129,6 +129,19 @@ public final class SelectOperation extends AbstractFilterStreamOperation SelectOperation from(Class materializedViewClass) {
+ Objects.requireNonNull(materializedViewClass);
+ HelenusEntity entity = Helenus.entity(materializedViewClass);
+ this.alternateTableName = entity.getName().toCql();
+ this.allowFiltering = true;
+ return this;
+ }
+
+ public SelectOperation from(String alternateTableName) {
+ this.alternateTableName = alternateTableName;
+ return this;
+ }
+
public SelectFirstOperation single() {
limit(1);
return new SelectFirstOperation(this);
@@ -189,7 +202,6 @@ public final class SelectOperation extends AbstractFilterStreamOperation extends AbstractFilterStreamOperation extends AbstractFilterStreamOperation extends AbstractFilterStreamOperation transform(ResultSet resultSet) {
if (rowMapper != null) {
- return StreamSupport.stream(Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED), false).map(rowMapper);
+ return StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED), false)
+ .map(rowMapper);
} else {
return (Stream)
- StreamSupport.stream(Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED),false);
+ StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED),
+ false);
}
}
diff --git a/src/main/java/net/helenus/core/operation/SelectTransformingOperation.java b/src/main/java/net/helenus/core/operation/SelectTransformingOperation.java
index 8883f7e..f93ca41 100644
--- a/src/main/java/net/helenus/core/operation/SelectTransformingOperation.java
+++ b/src/main/java/net/helenus/core/operation/SelectTransformingOperation.java
@@ -36,7 +36,9 @@ public final class SelectTransformingOperation
}
@Override
- public String getStatementCacheKey() { return delegate.getStatementCacheKey(); }
+ public String getStatementCacheKey() {
+ return delegate.getStatementCacheKey();
+ }
@Override
public BuiltStatement buildStatement(boolean cached) {
@@ -47,5 +49,4 @@ public final class SelectTransformingOperation
public Stream transform(ResultSet resultSet) {
return delegate.transform(resultSet).map(fn);
}
-
}
diff --git a/src/main/java/net/helenus/core/operation/UpdateOperation.java b/src/main/java/net/helenus/core/operation/UpdateOperation.java
index f04c90e..b918bc6 100644
--- a/src/main/java/net/helenus/core/operation/UpdateOperation.java
+++ b/src/main/java/net/helenus/core/operation/UpdateOperation.java
@@ -15,15 +15,13 @@
*/
package net.helenus.core.operation;
-import java.util.*;
-import java.util.function.Function;
-
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.querybuilder.Assignment;
import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update;
-
+import java.util.*;
+import java.util.function.Function;
import net.helenus.core.*;
import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.mapping.HelenusEntity;
@@ -43,19 +41,21 @@ public final class UpdateOperation extends AbstractFilterOperation draft) {
+ public UpdateOperation(
+ AbstractSessionOperations sessionOperations, AbstractEntityDraft draft) {
super(sessionOperations);
this.draft = draft;
this.draftMap = draft.toMap();
}
- public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
+ public UpdateOperation(
+ AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
super(sessionOperations);
this.draft = null;
this.draftMap = null;
@@ -152,7 +152,7 @@ public final class UpdateOperation extends AbstractFilterOperation list = (List)draftMap.get(key);
+ List list = (List) draftMap.get(key);
list.add(0, value);
}
@@ -194,7 +194,7 @@ public final class UpdateOperation extends AbstractFilterOperation list = (List)draftMap.get(key);
+ List list = (List) draftMap.get(key);
if (idx < 0) {
list.add(0, value);
} else if (idx > list.size()) {
@@ -222,7 +222,7 @@ public final class UpdateOperation extends AbstractFilterOperation list = (List)draftMap.get(key);
+ List list = (List) draftMap.get(key);
list.add(value);
}
@@ -579,6 +579,9 @@ public final class UpdateOperation extends AbstractFilterOperation extends AbstractFilterOperation implements InvocationHandler {
- private final HelenusEntity entity;
+ private HelenusEntity entity = null;
+ private Metadata metadata = null;
+
+ private final Class iface;
+ private final ClassLoader classLoader;
+
private final Optional parent;
private final Map map = new HashMap();
@@ -48,18 +53,46 @@ public class DslInvocationHandler implements InvocationHandler {
Optional parent,
Metadata metadata) {
- this.entity = new HelenusMappingEntity(iface, metadata);
+ this.metadata = metadata;
this.parent = parent;
+ this.iface = iface;
+ this.classLoader = classLoader;
+ }
- if (this.entity != null) {
- for (HelenusProperty prop : entity.getOrderedProperties()) {
+ public void setCassandraMetadataForHelenusSesion(Metadata metadata) {
+ if (metadata != null) {
+ this.metadata = metadata;
+ entity = init(metadata);
+ }
+ }
- map.put(prop.getGetterMethod(), prop);
+ private HelenusEntity init(Metadata metadata) {
+ HelenusEntity entity = new HelenusMappingEntity(iface, metadata);
- AbstractDataType type = prop.getDataType();
- Class> javaType = prop.getJavaType();
+ for (HelenusProperty prop : entity.getOrderedProperties()) {
- if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
+ map.put(prop.getGetterMethod(), prop);
+
+ AbstractDataType type = prop.getDataType();
+ Class> javaType = prop.getJavaType();
+
+ if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
+
+ Object childDsl =
+ Helenus.dsl(
+ javaType,
+ classLoader,
+ Optional.of(new HelenusPropertyNode(prop, parent)),
+ metadata);
+
+ udtMap.put(prop.getGetterMethod(), childDsl);
+ }
+
+ if (type instanceof DTDataType) {
+ DTDataType dataType = (DTDataType) type;
+
+ if (dataType.getDataType() instanceof TupleType
+ && !TupleValue.class.isAssignableFrom(javaType)) {
Object childDsl =
Helenus.dsl(
@@ -68,32 +101,18 @@ public class DslInvocationHandler implements InvocationHandler {
Optional.of(new HelenusPropertyNode(prop, parent)),
metadata);
- udtMap.put(prop.getGetterMethod(), childDsl);
- }
-
- if (type instanceof DTDataType) {
- DTDataType dataType = (DTDataType) type;
-
- if (dataType.getDataType() instanceof TupleType
- && !TupleValue.class.isAssignableFrom(javaType)) {
-
- Object childDsl =
- Helenus.dsl(
- javaType,
- classLoader,
- Optional.of(new HelenusPropertyNode(prop, parent)),
- metadata);
-
- tupleMap.put(prop.getGetterMethod(), childDsl);
- }
+ tupleMap.put(prop.getGetterMethod(), childDsl);
}
}
}
+
+ return entity;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ HelenusEntity entity = this.entity;
String methodName = method.getName();
if ("equals".equals(methodName) && method.getParameterCount() == 1) {
@@ -107,6 +126,15 @@ public class DslInvocationHandler implements InvocationHandler {
return false;
}
+ if (DslExportable.SET_METADATA_METHOD.equals(methodName)
+ && args.length == 1
+ && args[0] instanceof Metadata) {
+ if (metadata == null) {
+ this.setCassandraMetadataForHelenusSesion((Metadata) args[0]);
+ }
+ return null;
+ }
+
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
throw new HelenusException("invalid getter method " + method);
}
@@ -115,6 +143,14 @@ public class DslInvocationHandler implements InvocationHandler {
return hashCode();
}
+ if (DslExportable.GET_PARENT_METHOD.equals(methodName)) {
+ return parent.get();
+ }
+
+ if (entity == null) {
+ entity = init(metadata);
+ }
+
if ("toString".equals(methodName)) {
return entity.toString();
}
@@ -123,10 +159,6 @@ public class DslInvocationHandler implements InvocationHandler {
return entity;
}
- if (DslExportable.GET_PARENT_METHOD.equals(methodName)) {
- return parent.get();
- }
-
HelenusProperty prop = map.get(method);
if (prop == null) {
prop = entity.getProperty(methodName);
diff --git a/src/main/java/net/helenus/core/reflect/MapperInvocationHandler.java b/src/main/java/net/helenus/core/reflect/MapperInvocationHandler.java
index 7df8a51..4845c11 100644
--- a/src/main/java/net/helenus/core/reflect/MapperInvocationHandler.java
+++ b/src/main/java/net/helenus/core/reflect/MapperInvocationHandler.java
@@ -23,6 +23,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.Map;
+import net.helenus.core.Helenus;
import net.helenus.mapping.annotation.Transient;
import net.helenus.support.HelenusException;
@@ -91,6 +92,10 @@ public class MapperInvocationHandler implements InvocationHandler, Serializab
return iface.getSimpleName() + ": " + src.toString();
}
+ if ("dsl".equals(methodName)) {
+ return Helenus.dsl(iface);
+ }
+
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
return Collections.unmodifiableMap(src);
}
diff --git a/src/main/java/net/helenus/mapping/HelenusEntityType.java b/src/main/java/net/helenus/mapping/HelenusEntityType.java
index 1d93991..2ef8d63 100644
--- a/src/main/java/net/helenus/mapping/HelenusEntityType.java
+++ b/src/main/java/net/helenus/mapping/HelenusEntityType.java
@@ -17,6 +17,7 @@ package net.helenus.mapping;
public enum HelenusEntityType {
TABLE,
+ VIEW,
TUPLE,
UDT;
}
diff --git a/src/main/java/net/helenus/mapping/HelenusMappingEntity.java b/src/main/java/net/helenus/mapping/HelenusMappingEntity.java
index 75a967d..570d7b9 100644
--- a/src/main/java/net/helenus/mapping/HelenusMappingEntity.java
+++ b/src/main/java/net/helenus/mapping/HelenusMappingEntity.java
@@ -25,6 +25,7 @@ import net.helenus.core.Helenus;
import net.helenus.core.annotation.Cacheable;
import net.helenus.mapping.annotation.*;
import net.helenus.support.HelenusMappingException;
+import org.apache.commons.lang3.ClassUtils;
public final class HelenusMappingEntity implements HelenusEntity {
@@ -52,18 +53,33 @@ public final class HelenusMappingEntity implements HelenusEntity {
HelenusSettings settings = Helenus.settings();
- List methods = new ArrayList();
+ Map methods = new HashMap();
+ for (Method m : iface.getDeclaredMethods()) {
+ methods.put(m.getName(), m);
+ }
- methods.addAll(Arrays.asList(iface.getDeclaredMethods()));
- for (Class> c : iface.getInterfaces()) {
- methods.addAll(Arrays.asList(c.getDeclaredMethods()));
+ for (Class> c : ClassUtils.getAllInterfaces(iface)) {
+ if (c.getDeclaredAnnotation(Table.class) != null
+ || c.getDeclaredAnnotation(InheritedTable.class) != null) {
+ for (Method m : c.getDeclaredMethods()) {
+ Method o = methods.get(m.getName());
+ if (o != null) {
+ // Prefer overridden method implementation.
+ if (o.getDeclaringClass().isAssignableFrom(m.getDeclaringClass())) {
+ methods.put(m.getName(), m);
+ }
+ } else {
+ methods.put(m.getName(), m);
+ }
+ }
+ }
}
List propsLocal = new ArrayList();
ImmutableMap.Builder propsBuilder = ImmutableMap.builder();
ImmutableMap.Builder