Formatting

This commit is contained in:
Greg Burd 2017-10-12 16:18:17 -04:00
parent 306c9e68ef
commit 74832a32dd
56 changed files with 1133 additions and 1095 deletions

View file

@ -35,7 +35,7 @@ public enum GetterMethodDetector implements Function<Method, Boolean> {
} }
if (Modifier.isStatic(method.getModifiers())) { if (Modifier.isStatic(method.getModifiers())) {
return false; return false;
} }
// Methods marked "Transient" are not mapped, skip them. // Methods marked "Transient" are not mapped, skip them.

View file

@ -1,41 +1,38 @@
package net.helenus.core; package net.helenus.core;
import net.helenus.core.reflect.MapExportable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.Date; import java.util.Date;
import net.helenus.core.reflect.MapExportable;
public abstract class AbstractAuditedEntityDraft<E> extends AbstractEntityDraft<E> { public abstract class AbstractAuditedEntityDraft<E> extends AbstractEntityDraft<E> {
public AbstractAuditedEntityDraft(MapExportable entity) { public AbstractAuditedEntityDraft(MapExportable entity) {
super(entity); super(entity);
Date in = new Date(); Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault()); LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date now = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()); Date now = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
String who = getCurrentAuditor(); String who = getCurrentAuditor();
if (entity == null) { if (entity == null) {
if (who != null) { if (who != null) {
set("createdBy", who); set("createdBy", who);
} }
set("createdAt", now); set("createdAt", now);
}
if (who != null) {
set("modifiedBy", who);
}
set("modifiedAt", now);
} }
if (who != null) {
protected String getCurrentAuditor() { set("modifiedBy", who);
return null;
} }
set("modifiedAt", now);
}
public Date createdAt() { protected String getCurrentAuditor() {
return (Date) get("createdAt", Date.class); return null;
} }
public Date createdAt() {
return (Date) get("createdAt", Date.class);
}
} }

View file

@ -1,164 +1,159 @@
package net.helenus.core; package net.helenus.core;
import java.util.*;
import com.google.common.primitives.Primitives; import com.google.common.primitives.Primitives;
import java.util.*;
import net.helenus.core.reflect.DefaultPrimitiveTypes; import net.helenus.core.reflect.DefaultPrimitiveTypes;
import net.helenus.core.reflect.Drafted; import net.helenus.core.reflect.Drafted;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
import net.helenus.mapping.MappingUtil; import net.helenus.mapping.MappingUtil;
public abstract class AbstractEntityDraft<E> implements Drafted<E> { public abstract class AbstractEntityDraft<E> implements Drafted<E> {
private final Map<String, Object> backingMap = new HashMap<String, Object>(); private final Map<String, Object> backingMap = new HashMap<String, Object>();
private final MapExportable entity; private final MapExportable entity;
private final Map<String, Object> entityMap; private final Map<String, Object> entityMap;
public AbstractEntityDraft(MapExportable entity) {
this.entity = entity;
this.entityMap = entity != null ? entity.toMap() : new HashMap<String, Object>();
}
public AbstractEntityDraft(MapExportable entity) { public abstract Class<E> getEntityClass();
this.entity = entity;
this.entityMap = entity != null ? entity.toMap() : new HashMap<String, Object>();
}
public abstract Class<E> getEntityClass(); public E build() {
return Helenus.map(getEntityClass(), toMap());
}
public E build() { return Helenus.map(getEntityClass(), toMap()); } @SuppressWarnings("unchecked")
protected <T> T get(Getter<T> getter, Class<?> returnType) {
return (T) get(this.<T>methodNameFor(getter), returnType);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> T get(Getter<T> getter, Class<?> returnType) { protected <T> T get(String key, Class<?> returnType) {
return (T) get(this.<T>methodNameFor(getter), returnType); T value = (T) backingMap.get(key);
}
@SuppressWarnings("unchecked") if (value == null) {
protected <T> T get(String key, Class<?> returnType) { value = (T) entityMap.get(key);
T value = (T) backingMap.get(key); if (value == null) {
if (value == null) { if (Primitives.allPrimitiveTypes().contains(returnType)) {
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);
}
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType); return (T) type.getDefaultValue();
if (type == null) {
throw new RuntimeException("unknown primitive type " + returnType);
}
return (T) type.getDefaultValue();
}
}
} }
}
return value;
} }
protected <T> Object set(Getter<T> getter, Object value) { return value;
return set(this.<T>methodNameFor(getter), value); }
protected <T> Object set(Getter<T> getter, Object value) {
return set(this.<T>methodNameFor(getter), 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);
if (key == null || value == null) { return value;
return null; }
}
@SuppressWarnings("unchecked")
protected <T> T mutate(Getter<T> getter, T value) {
return (T) mutate(this.<T>methodNameFor(getter), value);
}
protected Object mutate(String key, Object value) {
Objects.requireNonNull(key);
if (value == null) {
return null;
}
if (entity != null) {
Map<String, Object> map = entity.toMap();
if (map.containsKey(key) && !value.equals(map.get(key))) {
backingMap.put(key, value); backingMap.put(key, value);
return value; return value;
}
return map.get(key);
} else {
backingMap.put(key, value);
return null;
} }
}
@SuppressWarnings("unchecked") private <T> String methodNameFor(Getter<T> getter) {
protected <T> T mutate(Getter<T> getter, T value) { return MappingUtil.resolveMappingProperty(getter).getProperty().getPropertyName();
return (T) mutate(this.<T>methodNameFor(getter), value); }
public <T> Object unset(Getter<T> getter) {
return unset(methodNameFor(getter));
}
public Object unset(String key) {
if (key != null) {
Object value = backingMap.get(key);
backingMap.put(key, null);
return value;
} }
return null;
}
protected Object mutate(String key, Object value) { public <T> boolean reset(Getter<T> getter, T desiredValue) {
Objects.requireNonNull(key); return this.<T>reset(this.<T>methodNameFor(getter), desiredValue);
}
if (value == null) { public <T> boolean reset(String key, T desiredValue) {
return null; if (key != null && desiredValue != null) {
} @SuppressWarnings("unchecked")
T currentValue = (T) backingMap.get(key);
if (entity != null) { if (currentValue == null || !currentValue.equals(desiredValue)) {
Map<String, Object> map = entity.toMap(); set(key, desiredValue);
return true;
if (map.containsKey(key) && !value.equals(map.get(key))) { }
backingMap.put(key, value);
return value;
}
return map.get(key);
} else {
backingMap.put(key, value);
return null;
}
} }
return false;
}
private <T> String methodNameFor(Getter<T> getter) { @Override
return MappingUtil.resolveMappingProperty(getter) public Map<String, Object> toMap() {
.getProperty() return toMap(entityMap);
.getPropertyName(); }
public Map<String, Object> toMap(Map<String, Object> entityMap) {
Map<String, Object> combined;
if (entityMap != null && entityMap.size() > 0) {
combined = new HashMap<String, Object>(entityMap.size());
for (String key : entityMap.keySet()) {
combined.put(key, entityMap.get(key));
}
} else {
combined = new HashMap<String, Object>(backingMap.size());
} }
for (String key : mutated()) {
public <T> Object unset(Getter<T> getter) { combined.put(key, backingMap.get(key));
return unset(methodNameFor(getter));
} }
return combined;
}
public Object unset(String key) { @Override
if (key != null) { public Set<String> mutated() {
Object value = backingMap.get(key); return backingMap.keySet();
backingMap.put(key, null); }
return value;
}
return null;
}
public <T> boolean reset(Getter<T> getter, T desiredValue) {
return this.<T>reset(this.<T>methodNameFor(getter), desiredValue);
}
public <T> 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;
}
@Override
public Map<String, Object> toMap() {
return toMap(entityMap);
}
public Map<String, Object> toMap(Map<String, Object>entityMap) {
Map<String, Object> combined;
if (entityMap != null && entityMap.size() > 0) {
combined = new HashMap<String, Object>(entityMap.size());
for (String key : entityMap.keySet()) {
combined.put(key, entityMap.get(key));
}
} else {
combined = new HashMap<String, Object>(backingMap.size());
}
for (String key : mutated()) {
combined.put(key, backingMap.get(key));
}
return combined;
}
@Override
public Set<String> mutated() {
return backingMap.keySet();
}
@Override
public String toString() {
return backingMap.toString();
}
@Override
public String toString() {
return backingMap.toString();
}
} }

View file

@ -22,7 +22,6 @@ import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import net.helenus.mapping.value.ColumnValuePreparer; import net.helenus.mapping.value.ColumnValuePreparer;
import net.helenus.mapping.value.ColumnValueProvider; import net.helenus.mapping.value.ColumnValueProvider;
import net.helenus.support.HelenusException; import net.helenus.support.HelenusException;
@ -124,5 +123,4 @@ public abstract class AbstractSessionOperations {
void printCql(String cql) { void printCql(String cql) {
getPrintStream().println(cql); getPrintStream().println(cql);
} }
} }

View file

@ -17,10 +17,8 @@ package net.helenus.core;
import com.diffplug.common.base.Errors; import com.diffplug.common.base.Errors;
import com.google.common.collect.TreeTraverser; import com.google.common.collect.TreeTraverser;
import java.util.*; import java.util.*;
/** Encapsulates the concept of a "transaction" as a unit-of-work. */ /** Encapsulates the concept of a "transaction" as a unit-of-work. */
public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork, AutoCloseable { public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfWork, AutoCloseable {
private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>(); private final List<AbstractUnitOfWork<E>> nested = new ArrayList<>();
@ -70,22 +68,25 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
return null; return null;
} }
public Map<String, Set<Object>> getCache() { return cache; } public Map<String, Set<Object>> getCache() {
return cache;
}
private Iterator<AbstractUnitOfWork<E>> getChildNodes() { private Iterator<AbstractUnitOfWork<E>> getChildNodes() {
return nested.iterator(); return nested.iterator();
} }
/** /**
* Checks to see if the work performed between calling begin and now can be committed or not. * 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 * @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. * @throws E when the work overlaps with other concurrent writers.
*/ */
public PostCommitFunction<Void, Void> commit() throws E { public PostCommitFunction<Void, Void> commit() throws E {
// All nested UnitOfWork should be committed (not aborted) before calls to commit, check. // All nested UnitOfWork should be committed (not aborted) before calls to commit, check.
boolean canCommit = true; boolean canCommit = true;
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes); TreeTraverser<AbstractUnitOfWork<E>> traverser =
TreeTraverser.using(node -> node::getChildNodes);
for (AbstractUnitOfWork<E> uow : traverser.postOrderTraversal(this)) { for (AbstractUnitOfWork<E> uow : traverser.postOrderTraversal(this)) {
if (this != uow) { if (this != uow) {
canCommit &= (!uow.aborted && uow.committed); canCommit &= (!uow.aborted && uow.committed);
@ -112,7 +113,8 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
if (parentCache.containsKey(key)) { if (parentCache.containsKey(key)) {
// merge the sets // merge the sets
Set<Object> ps = parentCache.get(key); Set<Object> 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 { } else {
// add the missing set // add the missing set
parentCache.put(key, cache.get(key)); parentCache.put(key, cache.get(key));
@ -122,9 +124,12 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
// Apply all post-commit functions for // Apply all post-commit functions for
if (parent == null) { if (parent == null) {
traverser.postOrderTraversal(this).forEach(uow -> { traverser
uow.applyPostCommitFunctions(); .postOrderTraversal(this)
}); .forEach(
uow -> {
uow.applyPostCommitFunctions();
});
return new PostCommitFunction(this, null); return new PostCommitFunction(this, null);
} }
} }
@ -137,11 +142,15 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
/* Explicitly discard the work and mark it as as such in the log. */ /* Explicitly discard the work and mark it as as such in the log. */
public void abort() { public void abort() {
TreeTraverser<AbstractUnitOfWork<E>> traverser = TreeTraverser.using(node -> node::getChildNodes); TreeTraverser<AbstractUnitOfWork<E>> traverser =
traverser.postOrderTraversal(this).forEach(uow -> { TreeTraverser.using(node -> node::getChildNodes);
uow.committed = false; traverser
uow.aborted = true; .postOrderTraversal(this)
}); .forEach(
uow -> {
uow.committed = false;
uow.aborted = true;
});
// log.record(txn::abort) // log.record(txn::abort)
// cache.invalidateSince(txn::start time) // cache.invalidateSince(txn::start time)
} }
@ -165,5 +174,4 @@ public abstract class AbstractUnitOfWork<E extends Exception> implements UnitOfW
public boolean hasCommitted() { public boolean hasCommitted() {
return committed; return committed;
} }
} }

View file

@ -1,8 +1,7 @@
package net.helenus.core; package net.helenus.core;
import java.util.function.Function;
@FunctionalInterface @FunctionalInterface
public interface CommitThunk { public interface CommitThunk {
void apply(); void apply();
} }

View file

@ -142,10 +142,10 @@ public final class Helenus {
public static HelenusEntity entity(Class<?> iface) { public static HelenusEntity entity(Class<?> iface) {
Metadata metadata = metadataForEntity.get(iface); Metadata metadata = metadataForEntity.get(iface);
if (metadata == null) { if (metadata == null) {
HelenusSession session = session(); HelenusSession session = session();
if (session != null) { if (session != null) {
metadata = session.getMetadata(); metadata = session.getMetadata();
} }
} }
return entity(iface, metadata); return entity(iface, metadata);
} }

View file

@ -15,10 +15,21 @@
*/ */
package net.helenus.core; package net.helenus.core;
import static net.helenus.core.Query.eq;
import brave.Tracer; import brave.Tracer;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
import com.datastax.driver.core.*; 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.operation.*;
import net.helenus.core.reflect.Drafted; import net.helenus.core.reflect.Drafted;
import net.helenus.core.reflect.HelenusPropertyNode; 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.HelenusException;
import net.helenus.support.HelenusMappingException; 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 { public final class HelenusSession extends AbstractSessionOperations implements Closeable {
private final int MAX_CACHE_SIZE = 10000; private final int MAX_CACHE_SIZE = 10000;
@ -69,26 +67,25 @@ public final class HelenusSession extends AbstractSessionOperations implements C
private final StatementColumnValuePreparer valuePreparer; private final StatementColumnValuePreparer valuePreparer;
private final Metadata metadata; private final Metadata metadata;
HelenusSession( HelenusSession(
Session session, Session session,
String usingKeyspace, String usingKeyspace,
CodecRegistry registry, CodecRegistry registry,
boolean showCql, boolean showCql,
PrintStream printStream, PrintStream printStream,
SessionRepositoryBuilder sessionRepositoryBuilder, SessionRepositoryBuilder sessionRepositoryBuilder,
Executor executor, Executor executor,
boolean dropSchemaOnClose, boolean dropSchemaOnClose,
ConsistencyLevel consistencyLevel, ConsistencyLevel consistencyLevel,
boolean defaultQueryIdempotency, boolean defaultQueryIdempotency,
Class<? extends UnitOfWork> unitOfWorkClass, Class<? extends UnitOfWork> unitOfWorkClass,
MetricRegistry metricRegistry, MetricRegistry metricRegistry,
Tracer tracer) { Tracer tracer) {
this.session = session; this.session = session;
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry; this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
this.usingKeyspace = this.usingKeyspace =
Objects.requireNonNull( Objects.requireNonNull(
usingKeyspace, "keyspace needs to be selected before creating session"); usingKeyspace, "keyspace needs to be selected before creating session");
this.showCql = showCql; this.showCql = showCql;
this.printStream = printStream; this.printStream = printStream;
this.sessionRepository = sessionRepositoryBuilder.build(); this.sessionRepository = sessionRepositoryBuilder.build();
@ -177,42 +174,53 @@ public final class HelenusSession extends AbstractSessionOperations implements C
} }
@Override @Override
public boolean getDefaultQueryIdempotency() { return defaultQueryIdempotency; } public boolean getDefaultQueryIdempotency() {
return defaultQueryIdempotency;
}
public Metadata getMetadata() { return metadata; } public Metadata getMetadata() {
return metadata;
}
public synchronized <T extends UnitOfWork> T begin() { public synchronized <T extends UnitOfWork> T begin() {
return begin(null); return begin(null);
} }
public synchronized <T extends UnitOfWork> T begin(T parent) { public synchronized <T extends UnitOfWork> T begin(T parent) {
try { try {
Class<? extends UnitOfWork> clazz = unitOfWorkClass; 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); UnitOfWork uow = ctor.newInstance(this, parent);
if (parent != null) { if (parent != null) {
parent.addNestedUnitOfWork(uow); parent.addNestedUnitOfWork(uow);
} }
return (T) uow.begin(); return (T) uow.begin();
} } catch (NoSuchMethodException
catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { | InvocationTargetException
throw new HelenusException(String.format("Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()), e); | InstantiationException
| IllegalAccessException e) {
throw new HelenusException(
String.format(
"Unable to instantiate {} as a UnitOfWork.", unitOfWorkClass.getSimpleName()),
e);
} }
} }
public <E> SelectOperation<E> select(E pojo) { public <E> SelectOperation<E> 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(); ColumnValueProvider valueProvider = getValueProvider();
HelenusEntity entity = Helenus.resolve(pojo); HelenusEntity entity = Helenus.resolve(pojo);
Class<?> entityClass = entity.getMappingInterface(); Class<?> entityClass = entity.getMappingInterface();
return new SelectOperation<E>( return new SelectOperation<E>(
this, this,
entity, entity,
(r) -> { (r) -> {
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity); Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
return (E) Helenus.map(entityClass, map); return (E) Helenus.map(entityClass, map);
}); });
} }
public <E> SelectOperation<E> select(Class<E> entityClass) { public <E> SelectOperation<E> select(Class<E> entityClass) {
@ -221,12 +229,12 @@ public final class HelenusSession extends AbstractSessionOperations implements C
HelenusEntity entity = Helenus.entity(entityClass); HelenusEntity entity = Helenus.entity(entityClass);
return new SelectOperation<E>( return new SelectOperation<E>(
this, this,
entity, entity,
(r) -> { (r) -> {
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity); Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
return (E) Helenus.map(entityClass, map); return (E) Helenus.map(entityClass, map);
}); });
} }
public SelectOperation<Fun.ArrayTuple> select() { public SelectOperation<Fun.ArrayTuple> select() {
@ -239,7 +247,8 @@ public final class HelenusSession extends AbstractSessionOperations implements C
} }
public <E> SelectOperation<Row> selectAll(E pojo) { public <E> SelectOperation<Row> 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); HelenusEntity entity = Helenus.resolve(pojo);
return new SelectOperation<Row>(this, entity); return new SelectOperation<Row>(this, entity);
} }
@ -411,51 +420,62 @@ public final class HelenusSession extends AbstractSessionOperations implements C
public <E> UpdateOperation<E> update(Drafted<E> drafted) { public <E> UpdateOperation<E> update(Drafted<E> drafted) {
if (drafted instanceof AbstractEntityDraft == false) { 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<E> draft = (AbstractEntityDraft<E>)drafted; AbstractEntityDraft<E> draft = (AbstractEntityDraft<E>) drafted;
UpdateOperation update = new UpdateOperation<E>(this, draft); UpdateOperation update = new UpdateOperation<E>(this, draft);
Map<String, Object> map = draft.toMap(); Map<String, Object> map = draft.toMap();
Set<String> mutatedProperties = draft.mutated(); Set<String> mutatedProperties = draft.mutated();
HelenusEntity entity = Helenus.entity(draft.getEntityClass()); HelenusEntity entity = Helenus.entity(draft.getEntityClass());
// Add all the mutated values contained in the draft. // Add all the mutated values contained in the draft.
entity.getOrderedProperties().forEach(property -> { entity
switch (property.getColumnType()) { .getOrderedProperties()
case PARTITION_KEY: .forEach(
case CLUSTERING_COLUMN: property -> {
break; switch (property.getColumnType()) {
default: case PARTITION_KEY:
String propertyName = property.getPropertyName(); case CLUSTERING_COLUMN:
if (mutatedProperties.contains(propertyName)) { break;
Object value = map.get(propertyName); default:
Getter<Object> getter = new Getter<Object>() { String propertyName = property.getPropertyName();
@Override if (mutatedProperties.contains(propertyName)) {
public Object get() { Object value = map.get(propertyName);
throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty())); Getter<Object> getter =
new Getter<Object>() {
@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). // Add the partition and clustering keys if they were in the draft (normally the case).
entity.getOrderedProperties().forEach(property -> { entity
switch (property.getColumnType()) { .getOrderedProperties()
case PARTITION_KEY: .forEach(
case CLUSTERING_COLUMN: property -> {
String propertyName = property.getPropertyName(); switch (property.getColumnType()) {
Object value = map.get(propertyName); case PARTITION_KEY:
Getter<Object> getter = new Getter<Object>() { case CLUSTERING_COLUMN:
@Override String propertyName = property.getPropertyName();
public Object get() { Object value = map.get(propertyName);
throw new DslPropertyException(new HelenusPropertyNode(property, Optional.empty())); Getter<Object> getter =
} new Getter<Object>() {
}; @Override
update.where(getter, eq(value)); public Object get() {
} throw new DslPropertyException(
}); new HelenusPropertyNode(property, Optional.empty()));
}
};
update.where(getter, eq(value));
}
});
return update; return update;
} }
@ -478,9 +498,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
} }
public <T> InsertOperation<T> insert(T pojo) { public <T> InsertOperation<T> 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; HelenusEntity entity = null;
try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {} try {
entity = Helenus.resolve(pojo);
} catch (HelenusMappingException e) {
}
if (entity != null) { if (entity != null) {
return new InsertOperation<T>(this, entity.getMappingInterface(), true); return new InsertOperation<T>(this, entity.getMappingInterface(), true);
} else { } else {
@ -488,7 +513,9 @@ public final class HelenusSession extends AbstractSessionOperations implements C
} }
} }
public <T> InsertOperation<T> insert(Drafted draft) { return insert(draft.build(), draft.mutated()); } public <T> InsertOperation<T> insert(Drafted draft) {
return insert(draft.build(), draft.mutated());
}
private <T> InsertOperation<T> insert(T pojo, Set<String> mutations) { private <T> InsertOperation<T> insert(T pojo, Set<String> mutations) {
Objects.requireNonNull(pojo, "pojo is empty"); Objects.requireNonNull(pojo, "pojo is empty");
@ -512,9 +539,14 @@ public final class HelenusSession extends AbstractSessionOperations implements C
} }
public <T> InsertOperation<T> upsert(T pojo) { public <T> InsertOperation<T> 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; HelenusEntity entity = null;
try { entity = Helenus.resolve(pojo); } catch (HelenusMappingException e) {} try {
entity = Helenus.resolve(pojo);
} catch (HelenusMappingException e) {
}
if (entity != null) { if (entity != null) {
return new InsertOperation<T>(this, entity.getMappingInterface(), false); return new InsertOperation<T>(this, entity.getMappingInterface(), false);
} else { } else {
@ -587,5 +619,4 @@ public final class HelenusSession extends AbstractSessionOperations implements C
break; break;
} }
} }
} }

View file

@ -1,30 +1,29 @@
package net.helenus.core; package net.helenus.core;
import java.util.Objects;
import java.util.*; import java.util.*;
import java.util.Objects;
public class PostCommitFunction<T, R> implements java.util.function.Function<T, R> { public class PostCommitFunction<T, R> implements java.util.function.Function<T, R> {
private final UnitOfWork uow; private final UnitOfWork uow;
private final List<CommitThunk> postCommit; private final List<CommitThunk> postCommit;
PostCommitFunction(UnitOfWork uow, List<CommitThunk> postCommit) { PostCommitFunction(UnitOfWork uow, List<CommitThunk> postCommit) {
this.uow = uow; this.uow = uow;
this.postCommit = postCommit; this.postCommit = postCommit;
} }
public void andThen(CommitThunk after) { public void andThen(CommitThunk after) {
Objects.requireNonNull(after); Objects.requireNonNull(after);
if (postCommit == null) { if (postCommit == null) {
after.apply(); after.apply();
} else { } else {
postCommit.add(after); postCommit.add(after);
}
} }
}
@Override @Override
public R apply(T t) { public R apply(T t) {
return null; return null;
} }
} }

View file

@ -25,7 +25,6 @@ import java.util.*;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.function.Consumer; import java.util.function.Consumer;
import net.helenus.core.reflect.DslExportable; import net.helenus.core.reflect.DslExportable;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.HelenusEntityType; import net.helenus.mapping.HelenusEntityType;
@ -131,12 +130,12 @@ public final class SessionInitializer extends AbstractSessionOperations {
} }
public SessionInitializer idempotentQueryExecution(boolean idempotent) { public SessionInitializer idempotentQueryExecution(boolean idempotent) {
this.idempotent = idempotent; this.idempotent = idempotent;
return this; return this;
} }
public boolean getDefaultQueryIdempotency() { public boolean getDefaultQueryIdempotency() {
return idempotent; return idempotent;
} }
@Override @Override
@ -185,9 +184,10 @@ public final class SessionInitializer extends AbstractSessionOperations {
PackageUtil.getClasses(packageName) PackageUtil.getClasses(packageName)
.stream() .stream()
.filter(c -> c.isInterface() && !c.isAnnotation()) .filter(c -> c.isInterface() && !c.isAnnotation())
.forEach(clazz -> { .forEach(
initList.add(Either.right(clazz)); clazz -> {
}); initList.add(Either.right(clazz));
});
} catch (IOException | ClassNotFoundException e) { } catch (IOException | ClassNotFoundException e) {
throw new HelenusException("fail to add package " + packageName, e); throw new HelenusException("fail to add package " + packageName, e);
} }
@ -267,18 +267,19 @@ public final class SessionInitializer extends AbstractSessionOperations {
Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator"); Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator");
initList.forEach((either) -> { initList.forEach(
Class<?> iface = null; (either) -> {
if (either.isLeft()) { Class<?> iface = null;
if (either.isLeft()) {
iface = MappingUtil.getMappingInterface(either.getLeft()); iface = MappingUtil.getMappingInterface(either.getLeft());
} else { } else {
iface = either.getRight(); iface = either.getRight();
} }
DslExportable dsl = (DslExportable) Helenus.dsl(iface); DslExportable dsl = (DslExportable) Helenus.dsl(iface);
dsl.setMetadata(session.getCluster().getMetadata()); dsl.setMetadata(session.getCluster().getMetadata());
sessionRepository.add(dsl); sessionRepository.add(dsl);
}); });
TableOperations tableOps = new TableOperations(this, dropUnusedColumns, dropUnusedIndexes); TableOperations tableOps = new TableOperations(this, dropUnusedColumns, dropUnusedIndexes);
UserTypeOperations userTypeOps = new UserTypeOperations(this, dropUnusedColumns); UserTypeOperations userTypeOps = new UserTypeOperations(this, dropUnusedColumns);

View file

@ -15,44 +15,42 @@
*/ */
package net.helenus.core; package net.helenus.core;
import net.helenus.support.Either;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
public interface UnitOfWork<E extends Exception> extends AutoCloseable { public interface UnitOfWork<E extends Exception> extends AutoCloseable {
/** /**
* Marks the beginning of a transactional section of work. Will write a record to the shared * Marks the beginning of a transactional section of work. Will write a record to the shared
* write-ahead log. * write-ahead log.
* *
* @return the handle used to commit or abort the work. * @return the handle used to commit or abort the work.
*/ */
UnitOfWork begin(); 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. * 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 * @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. * @throws E when the work overlaps with other concurrent writers.
*/ */
PostCommitFunction<Void, Void> commit() throws E; PostCommitFunction<Void, Void> commit() throws E;
/** /**
* Explicitly abort the work within this unit of work. Any nested aborted unit of work * Explicitly abort the work within this unit of work. Any nested aborted unit of work will
* will trigger the entire unit of work to commit. * trigger the entire unit of work to commit.
*/ */
void abort(); void abort();
boolean hasAborted();
boolean hasAborted(); boolean hasCommitted();
boolean hasCommitted(); //Either<Object, Set<Object>> cacheLookup(String key);
Set<Object> cacheLookup(String key);
//Either<Object, Set<Object>> cacheLookup(String key); Map<String, Set<Object>> getCache();
Set<Object> cacheLookup(String key);
Map<String, Set<Object>> getCache();
} }

View file

@ -19,9 +19,8 @@ import net.helenus.support.HelenusException;
class UnitOfWorkImpl extends AbstractUnitOfWork<HelenusException> { class UnitOfWorkImpl extends AbstractUnitOfWork<HelenusException> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public UnitOfWorkImpl(HelenusSession session, UnitOfWork parent) { public UnitOfWorkImpl(HelenusSession session, UnitOfWork parent) {
super(session, (AbstractUnitOfWork<HelenusException>) parent); super(session, (AbstractUnitOfWork<HelenusException>) parent);
} }
} }

View file

@ -4,11 +4,7 @@ import net.helenus.mapping.HelenusProperty;
public class EntityIdentifyingFacet extends Facet { public class EntityIdentifyingFacet extends Facet {
public EntityIdentifyingFacet(HelenusProperty prop) { public EntityIdentifyingFacet(HelenusProperty prop) {}
} public EntityIdentifyingFacet(HelenusProperty[]... props) {}
public EntityIdentifyingFacet(HelenusProperty[]... props) {
}
} }

View file

@ -1,7 +1,6 @@
package net.helenus.core.cache; package net.helenus.core.cache;
public class Facet { public class Facet {}
}
/* /*
An Entity is identifiable via one or more Facets An Entity is identifiable via one or more Facets

View file

@ -19,11 +19,11 @@ import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.helenus.core.*; import net.helenus.core.*;
import net.helenus.mapping.HelenusProperty; import net.helenus.mapping.HelenusProperty;
public abstract class AbstractFilterOptionalOperation<E, O extends AbstractFilterOptionalOperation<E, O>> public abstract class AbstractFilterOptionalOperation<
E, O extends AbstractFilterOptionalOperation<E, O>>
extends AbstractOptionalOperation<E, O> { extends AbstractOptionalOperation<E, O> {
protected Map<HelenusProperty, Filter<?>> filters = null; protected Map<HelenusProperty, Filter<?>> filters = null;

View file

@ -19,11 +19,11 @@ import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.helenus.core.*; import net.helenus.core.*;
import net.helenus.mapping.HelenusProperty; import net.helenus.mapping.HelenusProperty;
public abstract class AbstractFilterStreamOperation<E, O extends AbstractFilterStreamOperation<E, O>> public abstract class AbstractFilterStreamOperation<
E, O extends AbstractFilterStreamOperation<E, O>>
extends AbstractStreamOperation<E, O> { extends AbstractStreamOperation<E, O> {
protected Map<HelenusProperty, Filter<?>> filters = null; protected Map<HelenusProperty, Filter<?>> filters = null;

View file

@ -17,8 +17,6 @@ package net.helenus.core.operation;
import com.codahale.metrics.Timer; import com.codahale.metrics.Timer;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
import java.util.Objects;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import net.helenus.core.AbstractSessionOperations; import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.UnitOfWork; import net.helenus.core.UnitOfWork;
@ -40,7 +38,6 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
return new PreparedOperation<E>(prepareStatement(), this); return new PreparedOperation<E>(prepareStatement(), this);
} }
public E sync() { public E sync() {
final Timer.Context context = requestLatency.time(); final Timer.Context context = requestLatency.time();
try { try {
@ -72,5 +69,4 @@ public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
if (uow == null) return async(); if (uow == null) return async();
return CompletableFuture.<E>supplyAsync(() -> sync(uow)); return CompletableFuture.<E>supplyAsync(() -> sync(uow));
} }
} }

View file

@ -32,7 +32,8 @@ import net.helenus.support.HelenusException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>> extends Operation<E> { public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>>
extends Operation<E> {
final Logger logger = LoggerFactory.getLogger(getClass()); final Logger logger = LoggerFactory.getLogger(getClass());
@ -55,7 +56,6 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
this.idempotent = sessionOperations.getDefaultQueryIdempotency(); this.idempotent = sessionOperations.getDefaultQueryIdempotency();
} }
public O ignoreCache(boolean enabled) { public O ignoreCache(boolean enabled) {
enableCache = enabled; enableCache = enabled;
return (O) this; return (O) this;
@ -93,8 +93,8 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
} }
public O isIdempotent(boolean idempotent) { public O isIdempotent(boolean idempotent) {
this.idempotent = idempotent; this.idempotent = idempotent;
return (O) this; return (O) this;
} }
public O downgradingConsistencyRetryPolicy() { public O downgradingConsistencyRetryPolicy() {
@ -232,7 +232,7 @@ public abstract class AbstractStatementOperation<E, O extends AbstractStatementO
} }
if (idempotent) { if (idempotent) {
statement.setIdempotent(true); statement.setIdempotent(true);
} }
return statement; return statement;

View file

@ -21,20 +21,11 @@ import com.datastax.driver.core.ResultSet;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import net.helenus.core.AbstractSessionOperations; import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.Helenus;
import net.helenus.core.UnitOfWork; import net.helenus.core.UnitOfWork;
import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.value.ColumnValueProvider;
import net.helenus.mapping.value.ValueProviderMap;
public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperation<E, O>> public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperation<E, O>>
extends AbstractStatementOperation<E, O> { extends AbstractStatementOperation<E, O> {
@ -113,5 +104,4 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
if (uow == null) return async(); if (uow == null) return async();
return CompletableFuture.<Stream<E>>supplyAsync(() -> sync(uow)); return CompletableFuture.<Stream<E>>supplyAsync(() -> sync(uow));
} }
} }

View file

@ -34,7 +34,9 @@ public final class BoundOptionalOperation<E>
} }
@Override @Override
public Optional<E> transform(ResultSet resultSet) { return delegate.transform(resultSet); } public Optional<E> transform(ResultSet resultSet) {
return delegate.transform(resultSet);
}
@Override @Override
public Statement buildStatement(boolean cached) { public Statement buildStatement(boolean cached) {

View file

@ -26,14 +26,17 @@ public final class BoundStreamOperation<E>
private final BoundStatement boundStatement; private final BoundStatement boundStatement;
private final AbstractStreamOperation<E, ?> delegate; private final AbstractStreamOperation<E, ?> delegate;
public BoundStreamOperation(BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) { public BoundStreamOperation(
BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) {
super(operation.sessionOps); super(operation.sessionOps);
this.boundStatement = boundStatement; this.boundStatement = boundStatement;
this.delegate = operation; this.delegate = operation;
} }
@Override @Override
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); } public String getStatementCacheKey() {
return delegate.getStatementCacheKey();
}
@Override @Override
public Stream<E> transform(ResultSet resultSet) { public Stream<E> transform(ResultSet resultSet) {
@ -41,5 +44,7 @@ public final class BoundStreamOperation<E>
} }
@Override @Override
public Statement buildStatement(boolean cached) { return boundStatement; } public Statement buildStatement(boolean cached) {
return boundStatement;
}
} }

View file

@ -19,10 +19,9 @@ import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.datastax.driver.core.querybuilder.Insert; import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.google.common.base.Joiner;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import com.google.common.base.Joiner;
import net.helenus.core.AbstractSessionOperations; import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.Getter; import net.helenus.core.Getter;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
@ -41,7 +40,8 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
private HelenusEntity entity; private HelenusEntity entity;
private final List<Fun.Tuple2<HelenusPropertyNode, Object>> values = new ArrayList<Fun.Tuple2<HelenusPropertyNode, Object>>(); private final List<Fun.Tuple2<HelenusPropertyNode, Object>> values =
new ArrayList<Fun.Tuple2<HelenusPropertyNode, Object>>();
private final T pojo; private final T pojo;
private final Class<?> resultType; private final Class<?> resultType;
private boolean ifNotExists; private boolean ifNotExists;
@ -57,7 +57,8 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
this.resultType = ResultSet.class; this.resultType = ResultSet.class;
} }
public InsertOperation(AbstractSessionOperations sessionOperations, Class<?> resultType, boolean ifNotExists) { public InsertOperation(
AbstractSessionOperations sessionOperations, Class<?> resultType, boolean ifNotExists) {
super(sessionOperations); super(sessionOperations);
this.ifNotExists = ifNotExists; this.ifNotExists = ifNotExists;
@ -172,7 +173,7 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
// Some values man need to be converted (e.g. from String to Enum). This is done // Some values man need to be converted (e.g. from String to Enum). This is done
// within the BeanColumnValueProvider below. // within the BeanColumnValueProvider below.
Optional<Function<Object, Object>> converter = Optional<Function<Object, Object>> converter =
prop.getReadConverter(sessionOps.getSessionRepository()); prop.getReadConverter(sessionOps.getSessionRepository());
if (converter.isPresent()) { if (converter.isPresent()) {
backingMap.put(key, converter.get().apply(backingMap.get(key))); backingMap.put(key, converter.get().apply(backingMap.get(key)));
} }
@ -232,23 +233,25 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
public String getStatementCacheKey() { public String getStatementCacheKey() {
List<String> keys = new ArrayList<>(values.size()); List<String> keys = new ArrayList<>(values.size());
values.forEach( values.forEach(
t -> { t -> {
HelenusPropertyNode prop = t._1; HelenusPropertyNode prop = t._1;
switch (prop.getProperty().getColumnType()) { switch (prop.getProperty().getColumnType()) {
case PARTITION_KEY: case PARTITION_KEY:
case CLUSTERING_COLUMN: case CLUSTERING_COLUMN:
keys.add(prop.getColumnName() + "==" + t._2.toString()); keys.add(prop.getColumnName() + "==" + t._2.toString());
break; break;
default: default:
break; break;
} }
}); });
return entity.getName() + ": " + Joiner.on(",").join(keys); return entity.getName() + ": " + Joiner.on(",").join(keys);
} }
@Override @Override
public T sync(UnitOfWork uow) { public T sync(UnitOfWork uow) {
if (uow == null) { return sync(); } if (uow == null) {
return sync();
}
T result = super.sync(uow); T result = super.sync(uow);
Class<?> iface = entity.getMappingInterface(); Class<?> iface = entity.getMappingInterface();
if (resultType == iface) { if (resultType == iface) {
@ -261,5 +264,4 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
} }
return result; return result;
} }
} }

View file

@ -1,74 +1,81 @@
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.Set; import brave.Span;
import java.util.concurrent.ExecutionException; import brave.Tracer;
import brave.propagation.TraceContext;
import com.codahale.metrics.Meter; import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer; import com.codahale.metrics.Timer;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture; import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Statement; import com.datastax.driver.core.Statement;
import java.util.Set;
import brave.Span; import java.util.concurrent.ExecutionException;
import brave.Tracer;
import brave.propagation.TraceContext;
import net.helenus.core.AbstractSessionOperations; import net.helenus.core.AbstractSessionOperations;
import net.helenus.core.UnitOfWork; import net.helenus.core.UnitOfWork;
import net.helenus.core.cache.EntityIdentifyingFacet; import net.helenus.core.cache.EntityIdentifyingFacet;
public abstract class Operation<E> { public abstract class Operation<E> {
protected final AbstractSessionOperations sessionOps; protected final AbstractSessionOperations sessionOps;
protected final Meter uowCacheHits; protected final Meter uowCacheHits;
protected final Meter uowCacheMiss; protected final Meter uowCacheMiss;
protected final Timer requestLatency; protected final Timer requestLatency;
Operation(AbstractSessionOperations sessionOperations) { Operation(AbstractSessionOperations sessionOperations) {
this.sessionOps = sessionOperations; this.sessionOps = sessionOperations;
MetricRegistry metrics = sessionOperations.getMetricRegistry(); MetricRegistry metrics = sessionOperations.getMetricRegistry();
this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits"); this.uowCacheHits = metrics.meter("net.helenus.UOW-cache-hits");
this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss"); this.uowCacheMiss = metrics.meter("net.helenus.UOW-cache-miss");
this.requestLatency = metrics.timer("net.helenus.request-latency"); 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. if (span != null) {
Tracer tracer = session.getZipkinTracer(); span.name("cassandra");
Span span = null; span.start();
if (tracer != null && traceContext != null) { }
span = tracer.newChild(traceContext);
}
try { Statement statement = options(buildStatement(cached));
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
return futureResultSet.get();
if (span != null) { } catch (InterruptedException | ExecutionException e) {
span.name("cassandra");
span.start();
}
Statement statement = options(buildStatement(cached)); throw new RuntimeException(e);
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
return futureResultSet.get();
} catch (InterruptedException | ExecutionException e) { } finally {
throw new RuntimeException(e); if (span != null) {
span.finish();
} finally { }
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 Statement buildStatement(boolean cached) {
return null;
public Set<EntityIdentifyingFacet> getIdentifyingFacets() { return null; } }
public Set<EntityIdentifyingFacet> getIdentifyingFacets() {
return null;
}
} }

View file

@ -17,7 +17,6 @@ package net.helenus.core.operation;
import com.datastax.driver.core.BoundStatement; import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.PreparedStatement;
import java.util.regex.Pattern;
public final class PreparedStreamOperation<E> { public final class PreparedStreamOperation<E> {

View file

@ -38,7 +38,9 @@ public final class SelectFirstOperation<E>
} }
@Override @Override
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); } public String getStatementCacheKey() {
return delegate.getStatementCacheKey();
}
@Override @Override
public BuiltStatement buildStatement(boolean cached) { public BuiltStatement buildStatement(boolean cached) {

View file

@ -36,7 +36,9 @@ public final class SelectFirstTransformingOperation<R, E>
} }
@Override @Override
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); } public String getStatementCacheKey() {
return delegate.getStatementCacheKey();
}
@Override @Override
public BuiltStatement buildStatement(boolean cached) { public BuiltStatement buildStatement(boolean cached) {

View file

@ -22,15 +22,12 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select; import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.core.querybuilder.Select.Selection; import com.datastax.driver.core.querybuilder.Select.Selection;
import com.datastax.driver.core.querybuilder.Select.Where; import com.datastax.driver.core.querybuilder.Select.Where;
import com.google.common.collect.Iterables;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; 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.*;
import net.helenus.core.cache.Facet;
import net.helenus.core.cache.EntityIdentifyingFacet; import net.helenus.core.cache.EntityIdentifyingFacet;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
@ -56,7 +53,7 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
super(sessionOperations); super(sessionOperations);
this.rowMapper = this.rowMapper =
new Function<Row, E>() { new Function<Row, E>() {
@Override @Override
public E apply(Row source) { public E apply(Row source) {
@ -188,20 +185,25 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
final Set<EntityIdentifyingFacet> facets = new HashSet<>(filters.size()); final Set<EntityIdentifyingFacet> facets = new HashSet<>(filters.size());
// Check to see if this select statement has enough information to build one or // Check to see if this select statement has enough information to build one or
// more identifying facets. // more identifying facets.
entity.getIdentityFacets().forEach((facetName, facet) -> { entity
EntityIdentifyingFacet boundFacet = null; .getIdentityFacets()
if (!facet.isFullyBound()) { .forEach(
boundFacet = new EntityIdentifyingFacet(facet); (facetName, facet) -> {
for (HelenusProperty prop : facet.getUnboundEntityProperties()) { EntityIdentifyingFacet boundFacet = null;
Filter filter = filters.get(facet.getProperty()); if (!facet.isFullyBound()) {
if (filter == null) { break; } boundFacet = new EntityIdentifyingFacet(facet);
boundFacet.setValueForProperty(prop, filter.toString()); for (HelenusProperty prop : facet.getUnboundEntityProperties()) {
} Filter filter = filters.get(facet.getProperty());
} if (filter == null) {
if (boundFacet != null && boundFacet.isFullyBound()) { break;
facets.add(boundFacet); }
} boundFacet.setValueForProperty(prop, filter.toString());
}); }
}
if (boundFacet != null && boundFacet.isFullyBound()) {
facets.add(boundFacet);
}
});
return facets; return facets;
} }
@ -223,14 +225,14 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
entity = prop.getEntity(); entity = prop.getEntity();
} else if (entity != prop.getEntity()) { } else if (entity != prop.getEntity()) {
throw new HelenusMappingException( throw new HelenusMappingException(
"you can select columns only from a single entity " "you can select columns only from a single entity "
+ entity.getMappingInterface() + entity.getMappingInterface()
+ " or " + " or "
+ prop.getEntity().getMappingInterface()); + prop.getEntity().getMappingInterface());
} }
if (cached) { if (cached) {
switch(prop.getProperty().getColumnType()) { switch (prop.getProperty().getColumnType()) {
case PARTITION_KEY: case PARTITION_KEY:
case CLUSTERING_COLUMN: case CLUSTERING_COLUMN:
break; break;
@ -288,10 +290,14 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
@Override @Override
public Stream<E> transform(ResultSet resultSet) { public Stream<E> transform(ResultSet resultSet) {
if (rowMapper != null) { 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 { } else {
return (Stream<E>) return (Stream<E>)
StreamSupport.stream(Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED),false); StreamSupport.stream(
Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED),
false);
} }
} }

View file

@ -36,7 +36,9 @@ public final class SelectTransformingOperation<R, E>
} }
@Override @Override
public String getStatementCacheKey() { return delegate.getStatementCacheKey(); } public String getStatementCacheKey() {
return delegate.getStatementCacheKey();
}
@Override @Override
public BuiltStatement buildStatement(boolean cached) { public BuiltStatement buildStatement(boolean cached) {
@ -47,5 +49,4 @@ public final class SelectTransformingOperation<R, E>
public Stream<R> transform(ResultSet resultSet) { public Stream<R> transform(ResultSet resultSet) {
return delegate.transform(resultSet).map(fn); return delegate.transform(resultSet).map(fn);
} }
} }

View file

@ -15,15 +15,13 @@
*/ */
package net.helenus.core.operation; package net.helenus.core.operation;
import java.util.*;
import java.util.function.Function;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.querybuilder.Assignment; import com.datastax.driver.core.querybuilder.Assignment;
import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update; import com.datastax.driver.core.querybuilder.Update;
import java.util.*;
import java.util.function.Function;
import net.helenus.core.*; import net.helenus.core.*;
import net.helenus.core.reflect.HelenusPropertyNode; import net.helenus.core.reflect.HelenusPropertyNode;
import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntity;
@ -43,19 +41,21 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
private int[] ttl; private int[] ttl;
private long[] timestamp; private long[] timestamp;
public UpdateOperation(AbstractSessionOperations sessionOperations){ public UpdateOperation(AbstractSessionOperations sessionOperations) {
super(sessionOperations); super(sessionOperations);
this.draft = null; this.draft = null;
this.draftMap = null; this.draftMap = null;
} }
public UpdateOperation(AbstractSessionOperations sessionOperations, AbstractEntityDraft<E> draft) { public UpdateOperation(
AbstractSessionOperations sessionOperations, AbstractEntityDraft<E> draft) {
super(sessionOperations); super(sessionOperations);
this.draft = draft; this.draft = draft;
this.draftMap = draft.toMap(); this.draftMap = draft.toMap();
} }
public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) { public UpdateOperation(
AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
super(sessionOperations); super(sessionOperations);
this.draft = null; this.draft = null;
this.draftMap = null; this.draftMap = null;
@ -152,7 +152,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
if (draft != null) { if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>)draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.add(0, value); list.add(0, value);
} }
@ -194,7 +194,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
if (draft != null) { if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>)draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
if (idx < 0) { if (idx < 0) {
list.add(0, value); list.add(0, value);
} else if (idx > list.size()) { } else if (idx > list.size()) {
@ -222,7 +222,7 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
if (draft != null) { if (draft != null) {
String key = p.getProperty().getPropertyName(); String key = p.getProperty().getPropertyName();
List<V> list = (List<V>)draftMap.get(key); List<V> list = (List<V>) draftMap.get(key);
list.add(value); list.add(value);
} }
@ -579,7 +579,9 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
@Override @Override
public E sync(UnitOfWork uow) { public E sync(UnitOfWork uow) {
if (uow == null) { return sync(); } if (uow == null) {
return sync();
}
E result = super.sync(uow); E result = super.sync(uow);
if (draft != null) { if (draft != null) {
String key = getStatementCacheKey(); String key = getStatementCacheKey();
@ -591,5 +593,4 @@ public final class UpdateOperation<E> extends AbstractFilterOperation<E, UpdateO
} }
return result; return result;
} }
} }

View file

@ -1,6 +1,5 @@
package net.helenus.core.reflect; package net.helenus.core.reflect;
import net.helenus.mapping.HelenusEntity;
import java.util.Set; import java.util.Set;

View file

@ -67,46 +67,46 @@ public class DslInvocationHandler<E> implements InvocationHandler {
} }
private HelenusEntity init(Metadata metadata) { private HelenusEntity init(Metadata metadata) {
HelenusEntity entity = new HelenusMappingEntity(iface, metadata); HelenusEntity entity = new HelenusMappingEntity(iface, metadata);
for (HelenusProperty prop : entity.getOrderedProperties()) { for (HelenusProperty prop : entity.getOrderedProperties()) {
map.put(prop.getGetterMethod(), prop); map.put(prop.getGetterMethod(), prop);
AbstractDataType type = prop.getDataType(); AbstractDataType type = prop.getDataType();
Class<?> javaType = prop.getJavaType(); Class<?> javaType = prop.getJavaType();
if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) { if (type instanceof UDTDataType && !UDTValue.class.isAssignableFrom(javaType)) {
Object childDsl = Object childDsl =
Helenus.dsl( Helenus.dsl(
javaType, javaType,
classLoader, classLoader,
Optional.of(new HelenusPropertyNode(prop, parent)), Optional.of(new HelenusPropertyNode(prop, parent)),
metadata); metadata);
udtMap.put(prop.getGetterMethod(), childDsl); 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);
}
}
} }
return entity; 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);
}
}
}
return entity;
} }
@Override @Override
@ -127,10 +127,10 @@ public class DslInvocationHandler<E> implements InvocationHandler {
} }
if (DslExportable.SET_METADATA_METHOD.equals(methodName) if (DslExportable.SET_METADATA_METHOD.equals(methodName)
&& args.length == 1 && args.length == 1
&& args[0] instanceof Metadata) { && args[0] instanceof Metadata) {
if (metadata == null) { if (metadata == null) {
this.setMetadata((Metadata) args[0]); this.setMetadata((Metadata) args[0]);
} }
return null; return null;
} }

View file

@ -23,7 +23,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.mapping.annotation.Transient; import net.helenus.mapping.annotation.Transient;
import net.helenus.support.HelenusException; import net.helenus.support.HelenusException;
@ -94,7 +93,7 @@ public class MapperInvocationHandler<E> implements InvocationHandler, Serializab
} }
if ("dsl".equals(methodName)) { if ("dsl".equals(methodName)) {
return Helenus.dsl(iface); return Helenus.dsl(iface);
} }
if (MapExportable.TO_MAP_METHOD.equals(methodName)) { if (MapExportable.TO_MAP_METHOD.equals(methodName)) {

View file

@ -15,10 +15,9 @@
*/ */
package net.helenus.mapping; package net.helenus.mapping;
import net.helenus.core.cache.EntityIdentifyingFacet;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import net.helenus.core.cache.EntityIdentifyingFacet;
public interface HelenusEntity { public interface HelenusEntity {
@ -35,5 +34,4 @@ public interface HelenusEntity {
HelenusProperty getProperty(String name); HelenusProperty getProperty(String name);
Map<String, EntityIdentifyingFacet> getIdentityFacets(); Map<String, EntityIdentifyingFacet> getIdentityFacets();
} }

View file

@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import net.helenus.config.HelenusSettings; import net.helenus.config.HelenusSettings;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.annotation.Cacheable; import net.helenus.core.annotation.Cacheable;
@ -60,21 +59,22 @@ public final class HelenusMappingEntity implements HelenusEntity {
Map<String, Method> methods = new HashMap<String, Method>(); Map<String, Method> methods = new HashMap<String, Method>();
for (Method m : iface.getDeclaredMethods()) { for (Method m : iface.getDeclaredMethods()) {
methods.put(m.getName(), m); methods.put(m.getName(), m);
} }
for (Class<?> c : ClassUtils.getAllInterfaces(iface)) { for (Class<?> c : ClassUtils.getAllInterfaces(iface)) {
if (c.getDeclaredAnnotation(Table.class) != null || c.getDeclaredAnnotation(InheritedTable.class) != null) { if (c.getDeclaredAnnotation(Table.class) != null
|| c.getDeclaredAnnotation(InheritedTable.class) != null) {
for (Method m : c.getDeclaredMethods()) { for (Method m : c.getDeclaredMethods()) {
Method o = methods.get(m.getName()); Method o = methods.get(m.getName());
if (o != null) { if (o != null) {
// Prefer overridden method implementation. // Prefer overridden method implementation.
if (o.getDeclaringClass().isAssignableFrom(m.getDeclaringClass())) { if (o.getDeclaringClass().isAssignableFrom(m.getDeclaringClass())) {
methods.put(m.getName(), m); methods.put(m.getName(), m);
}
} else {
methods.put(m.getName(), m);
} }
} else {
methods.put(m.getName(), m);
}
} }
} }
} }
@ -110,27 +110,34 @@ public final class HelenusMappingEntity implements HelenusEntity {
cacheable = (null != iface.getDeclaredAnnotation(Cacheable.class)); cacheable = (null != iface.getDeclaredAnnotation(Cacheable.class));
ImmutableMap.Builder<String, EntityIdentifyingFacet> allFacetsBuilder = ImmutableMap.builder(); ImmutableMap.Builder<String, EntityIdentifyingFacet> allFacetsBuilder = ImmutableMap.builder();
ImmutableMap.Builder<String, EntityIdentifyingFacet> ancillaryFacetsBuilder = ImmutableMap.builder(); ImmutableMap.Builder<String, EntityIdentifyingFacet> ancillaryFacetsBuilder =
ImmutableMap.builder();
EntityIdentifyingFacet primaryFacet = null; EntityIdentifyingFacet primaryFacet = null;
List<HelenusProperty> primaryProperties = new ArrayList<HelenusProperty>(4); List<HelenusProperty> primaryProperties = new ArrayList<HelenusProperty>(4);
for (HelenusProperty prop : propsLocal) { for (HelenusProperty prop : propsLocal) {
switch(prop.getColumnType()) { switch (prop.getColumnType()) {
case PARTITION_KEY: case PARTITION_KEY:
case CLUSTERING_COLUMN: case CLUSTERING_COLUMN:
primaryProperties.add(prop); primaryProperties.add(prop);
break; break;
default: default:
if (primaryProperties != null) { if (primaryProperties != null) {
primaryFacet = new EntityIdentifyingFacet(keyspace, table, schemaVersion, primaryProperties.toArray(new HelenusProperty[props.size()])); primaryFacet =
allFacetsBuilder.put("*", primaryFacet); new EntityIdentifyingFacet(
primaryProperties = null; keyspace,
} table,
Optional<IdentityName> optionalIndexName = prop.getIndexName(); schemaVersion,
if (optionalIndexName.isPresent()) { primaryProperties.toArray(new HelenusProperty[props.size()]));
EntityIdentifyingFacet facet = new EntityIdentifyingFacet(keyspace, table, schemaVersion, prop); allFacetsBuilder.put("*", primaryFacet);
ancillaryFacetsBuilder.put(prop.getPropertyName(), facet); primaryProperties = null;
} }
} Optional<IdentityName> optionalIndexName = prop.getIndexName();
if (optionalIndexName.isPresent()) {
EntityIdentifyingFacet facet =
new EntityIdentifyingFacet(keyspace, table, schemaVersion, prop);
ancillaryFacetsBuilder.put(prop.getPropertyName(), facet);
}
}
} }
this.primaryIdentityFacet = primaryFacet; this.primaryIdentityFacet = primaryFacet;
this.ancillaryIdentityFacets = ancillaryFacetsBuilder.build(); this.ancillaryIdentityFacets = ancillaryFacetsBuilder.build();

View file

@ -2,6 +2,7 @@ package net.helenus.mapping.javatype;
public abstract class AbstractCollectionJavaType extends AbstractJavaType { public abstract class AbstractCollectionJavaType extends AbstractJavaType {
public static boolean isCollectionType() { return true; } public static boolean isCollectionType() {
return true;
}
} }

View file

@ -33,7 +33,9 @@ import net.helenus.support.HelenusMappingException;
public abstract class AbstractJavaType { public abstract class AbstractJavaType {
public static boolean isCollectionType() { return false; } public static boolean isCollectionType() {
return false;
}
public abstract Class<?> getJavaClass(); public abstract Class<?> getJavaClass();

View file

@ -18,7 +18,6 @@ package net.helenus.mapping.javatype;
import com.datastax.driver.core.*; import com.datastax.driver.core.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.AbstractCollection;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;

View file

@ -4,10 +4,11 @@ import net.helenus.mapping.ColumnType;
public abstract class AbstractCollectionDataType extends AbstractDataType { public abstract class AbstractCollectionDataType extends AbstractDataType {
public AbstractCollectionDataType(ColumnType columnType) { public AbstractCollectionDataType(ColumnType columnType) {
super(columnType); super(columnType);
} }
public boolean isCollectionType() { return true; }
public boolean isCollectionType() {
return true;
}
} }

View file

@ -55,6 +55,7 @@ public abstract class AbstractDataType {
"wrong column type " + columnType + " for UserDefinedType in columnName " + columnName); "wrong column type " + columnType + " for UserDefinedType in columnName " + columnName);
} }
public boolean isCollectionType() { return false; } public boolean isCollectionType() {
return false;
}
} }

View file

@ -18,8 +18,6 @@ package net.helenus.mapping.type;
import com.datastax.driver.core.DataType; import com.datastax.driver.core.DataType;
import com.datastax.driver.core.UserType; import com.datastax.driver.core.UserType;
import com.datastax.driver.core.schemabuilder.*; import com.datastax.driver.core.schemabuilder.*;
import java.util.AbstractCollection;
import java.util.List; import java.util.List;
import net.helenus.mapping.ColumnType; import net.helenus.mapping.ColumnType;
import net.helenus.mapping.IdentityName; import net.helenus.mapping.IdentityName;

View file

@ -33,7 +33,7 @@ public enum BeanColumnValueProvider implements ColumnValueProvider {
try { try {
value = getter.invoke(bean, new Object[] {}); value = getter.invoke(bean, new Object[] {});
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
if (e.getCause() != null ) { if (e.getCause() != null) {
throw new HelenusException("getter threw an exception", e.getCause()); throw new HelenusException("getter threw an exception", e.getCause());
} }
} catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) {

View file

@ -67,11 +67,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full object // read full object
Customer actual = session.<Customer>select(customer) Customer actual =
.where(customer::id, eq(id)) session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
.single()
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(aliases, actual.aliases()); Assert.assertEquals(aliases, actual.aliases());
Assert.assertNull(actual.names()); Assert.assertNull(actual.names());
@ -90,11 +87,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync(); session.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync();
actual = session.<Customer>select(customer) actual =
.where(customer::id, eq(id)) session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
.single()
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(expected, actual.aliases()); Assert.assertEquals(expected, actual.aliases());
@ -170,11 +164,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full object // read full object
Customer actual = session.<Customer>select(customer) Customer actual =
.where(customer::id, eq(id)) session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
.single()
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(names, actual.names()); Assert.assertEquals(names, actual.names());
@ -200,11 +191,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
session.update().set(customer::names, expected).where(customer::id, eq(id)).sync(); session.update().set(customer::names, expected).where(customer::id, eq(id)).sync();
actual = session.<Customer>select(customer) actual =
.where(customer::id, eq(id)) session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
.single()
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(expected, actual.names()); Assert.assertEquals(expected, actual.names());
@ -306,10 +294,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
// read full object // read full object
Customer actual = session.<Customer>select(customer) Customer actual =
.where(customer::id, eq(id)).single() session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(props, actual.properties()); Assert.assertEquals(props, actual.properties());
@ -343,11 +329,8 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest {
session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync(); session.update().set(customer::properties, expected).where(customer::id, eq(id)).sync();
actual = session.<Customer>select(customer) actual =
.where(customer::id, eq(id)) session.<Customer>select(customer).where(customer::id, eq(id)).single().sync().orElse(null);
.single()
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
Assert.assertEquals(expected, actual.properties()); Assert.assertEquals(expected, actual.properties());

View file

@ -18,76 +18,73 @@ package net.helenus.test.integration.core.draft;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import static net.helenus.core.Query.eq;
public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest { public class EntityDraftBuilderTest extends AbstractEmbeddedCassandraTest {
static Supply supply;
static HelenusSession session;
static Supply supply; @BeforeClass
static HelenusSession session; public static void beforeTest() {
session = Helenus.init(getSession()).showCql().add(Supply.class).autoCreateDrop().get();
supply = session.dsl(Supply.class);
}
@Test
public void testFoo() throws Exception {
Supply.Draft draft = null;
@BeforeClass draft =
public static void beforeTest() { Supply.draft("APAC")
session = Helenus.init(getSession()) .code("WIDGET-002")
.showCql() .description("Our second Widget!")
.add(Supply.class) .demand(
.autoCreateDrop() new HashMap<String, Long>() {
.get(); {
supply = session.dsl(Supply.class);
}
@Test
public void testFoo() throws Exception {
Supply.Draft draft = null;
draft = Supply.draft("APAC")
.code("WIDGET-002")
.description("Our second Widget!")
.demand(new HashMap<String, Long>() {{
put("APAC", 100L); put("APAC", 100L);
put("EMEA", 10000L); put("EMEA", 10000L);
put("NORAM", 2000000L); put("NORAM", 2000000L);
}}) }
.shipments(new HashSet<String>() {{ })
.shipments(
new HashSet<String>() {
{
add("HMS Puddle in transit to APAC, 100 units."); add("HMS Puddle in transit to APAC, 100 units.");
add("Frigate Jimmy in transit to EMEA, 10000 units."); add("Frigate Jimmy in transit to EMEA, 10000 units.");
}}) }
.suppliers(new ArrayList<String>() {{ })
.suppliers(
new ArrayList<String>() {
{
add("Puddle, Inc."); add("Puddle, Inc.");
add("Jimmy Town, LTD."); add("Jimmy Town, LTD.");
}}); }
});
Supply s1 = session.<Supply>insert(draft) Supply s1 = session.<Supply>insert(draft).sync();
.sync();
// List // List
Supply s2 = session.<Supply>update(s1.update()) Supply s2 =
.prepend(supply::suppliers, "Pignose Supply, LLC.") session
.sync(); .<Supply>update(s1.update())
Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC."); .prepend(supply::suppliers, "Pignose Supply, LLC.")
.sync();
Assert.assertEquals(s2.suppliers().get(0), "Pignose Supply, LLC.");
// Set // Set
String shipment = "Pignose, on the way! (1M units)"; String shipment = "Pignose, on the way! (1M units)";
Supply s3 = session.<Supply>update(s2.update()) Supply s3 = session.<Supply>update(s2.update()).add(supply::shipments, shipment).sync();
.add(supply::shipments, shipment) Assert.assertTrue(s3.shipments().contains(shipment));
.sync();
Assert.assertTrue(s3.shipments().contains(shipment));
// Map // Map
Supply s4 = session.<Supply>update(s3.update()) Supply s4 = session.<Supply>update(s3.update()).put(supply::demand, "NORAM", 10L).sync();
.put(supply::demand, "NORAM", 10L) Assert.assertEquals((long) s4.demand().get("NORAM"), 10L);
.sync(); }
Assert.assertEquals((long)s4.demand().get("NORAM"), 10L);
}
} }

View file

@ -1,78 +1,93 @@
package net.helenus.test.integration.core.draft; package net.helenus.test.integration.core.draft;
import java.util.UUID; import java.util.UUID;
import net.helenus.core.AbstractAuditedEntityDraft; import net.helenus.core.AbstractAuditedEntityDraft;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.*;
@Table @Table
public interface Inventory { public interface Inventory {
static Inventory inventory = Helenus.dsl(Inventory.class); static Inventory inventory = Helenus.dsl(Inventory.class);
@PartitionKey UUID id(); @PartitionKey
@Column("emea") @Types.Counter long EMEA(); UUID id();
@Column("noram") @Types.Counter long NORAM();
@Column("apac") @Types.Counter long APAC();
@Transient static Draft draft(UUID id) { return new Draft(id); } @Column("emea")
@Types.Counter
long EMEA();
@Transient default Draft update() { return new Draft(this); } @Column("noram")
@Types.Counter
long NORAM();
@Column("apac")
@Types.Counter
long APAC();
class Draft extends AbstractAuditedEntityDraft<Inventory> { @Transient
static Draft draft(UUID id) {
return new Draft(id);
}
// Entity/Draft pattern-enabling methods: @Transient
Draft(UUID id) { default Draft update() {
super(null); return new Draft(this);
}
// Primary Key: class Draft extends AbstractAuditedEntityDraft<Inventory> {
set(inventory::id, id);
}
Draft(Inventory inventory) { // Entity/Draft pattern-enabling methods:
super((MapExportable) inventory); Draft(UUID id) {
} super(null);
public Class<Inventory> getEntityClass() { return Inventory.class; }
protected String getCurrentAuditor() { return "unknown"; }
// Immutable properties:
public UUID id() {
return this.<UUID>get(inventory::id, UUID.class);
}
public long EMEA() {
return this.<Long>get(inventory::EMEA, long.class);
}
public Draft EMEA(long count) {
mutate(inventory::EMEA, count);
return this;
}
public long APAC() {
return this.<Long>get(inventory::APAC, long.class);
}
public Draft APAC(long count) {
mutate(inventory::APAC, count);
return this;
}
public long NORAM() {
return this.<Long>get(inventory::NORAM, long.class);
}
public Draft NORAM(long count) {
mutate(inventory::NORAM, count);
return this;
}
// Primary Key:
set(inventory::id, id);
} }
Draft(Inventory inventory) {
super((MapExportable) inventory);
}
public Class<Inventory> getEntityClass() {
return Inventory.class;
}
protected String getCurrentAuditor() {
return "unknown";
}
// Immutable properties:
public UUID id() {
return this.<UUID>get(inventory::id, UUID.class);
}
public long EMEA() {
return this.<Long>get(inventory::EMEA, long.class);
}
public Draft EMEA(long count) {
mutate(inventory::EMEA, count);
return this;
}
public long APAC() {
return this.<Long>get(inventory::APAC, long.class);
}
public Draft APAC(long count) {
mutate(inventory::APAC, count);
return this;
}
public long NORAM() {
return this.<Long>get(inventory::NORAM, long.class);
}
public Draft NORAM(long count) {
mutate(inventory::NORAM, count);
return this;
}
}
} }

View file

@ -1,129 +1,145 @@
package net.helenus.test.integration.core.draft; package net.helenus.test.integration.core.draft;
import java.lang.reflect.Proxy; import com.datastax.driver.core.utils.UUIDs;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import com.datastax.driver.core.utils.UUIDs;
import net.helenus.core.AbstractEntityDraft; import net.helenus.core.AbstractEntityDraft;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.reflect.MapExportable; import net.helenus.core.reflect.MapExportable;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.*;
@Table @Table
public interface Supply { public interface Supply {
static Supply supply = Helenus.dsl(Supply.class); static Supply supply = Helenus.dsl(Supply.class);
@PartitionKey UUID id(); @PartitionKey
@ClusteringColumn(ordinal=0) default String region() { return "NORAM"; } UUID id();
@Index(caseSensitive = false) String code(); @ClusteringColumn(ordinal = 0)
@Index String description(); // @IndexText == lucene index default String region() {
@Index Map<String, Long> demand(); return "NORAM";
@Index List<String> suppliers(); }
@Index Set<String> shipments();
@Transient static Draft draft(String region) { return new Draft(region); } @Index(caseSensitive = false)
String code();
@Transient default Draft update() { return new Draft(this); } @Index
String description(); // @IndexText == lucene index
@Index
Map<String, Long> demand();
class Draft extends AbstractEntityDraft<Supply> { @Index
List<String> suppliers();
// Entity/Draft pattern-enabling methods: @Index
Draft(String region) { Set<String> shipments();
super(null);
// Primary Key: @Transient
set(supply::id, UUIDs.timeBased()); static Draft draft(String region) {
set(supply::region, region); return new Draft(region);
} }
Draft(Supply supply) { @Transient
super((MapExportable) supply); default Draft update() {
} return new Draft(this);
}
public Class<Supply> getEntityClass() { return Supply.class; } class Draft extends AbstractEntityDraft<Supply> {
// Immutable properties: // Entity/Draft pattern-enabling methods:
public UUID id() { Draft(String region) {
return this.<UUID>get(supply::id, UUID.class); super(null);
}
public String region() {
return this.<String>get(supply::region, String.class);
}
// Mutable properties:
public String code() {
return this.<String>get(supply::code, String.class);
}
public Draft code(String code) {
mutate(supply::code, code);
return this;
}
public Draft setCode(String code) {
return code(code);
}
public String description() {
return this.<String>get(supply::description, String.class);
}
public Draft description(String description) {
mutate(supply::description, description);
return this;
}
public Draft setDescription(String description) {
return description(description);
}
public Map<String, Long> demand() {
return this.<Map<String, Long>>get(supply::demand, Map.class);
}
public Draft demand(Map<String, Long> demand) {
mutate(supply::demand, demand);
return this;
}
public Draft setDemand(Map<String, Long> demand) {
return demand(demand);
}
public List<String> suppliers() {
return this.<List<String>>get(supply::suppliers, List.class);
}
public Draft suppliers(List<String> suppliers) {
mutate(supply::suppliers, suppliers);
return this;
}
public Draft setSuppliers(List<String> suppliers) {
return suppliers(suppliers);
}
public Set<String> shipments() {
return this.<Set<String>>get(supply::shipments, Set.class);
}
public Draft shipments(Set<String> shipments) {
mutate(supply::shipments, shipments);
return this;
}
public Draft setshipments(Set<String> shipments) {
return shipments(shipments);
}
// Primary Key:
set(supply::id, UUIDs.timeBased());
set(supply::region, region);
} }
Draft(Supply supply) {
super((MapExportable) supply);
}
public Class<Supply> getEntityClass() {
return Supply.class;
}
// Immutable properties:
public UUID id() {
return this.<UUID>get(supply::id, UUID.class);
}
public String region() {
return this.<String>get(supply::region, String.class);
}
// Mutable properties:
public String code() {
return this.<String>get(supply::code, String.class);
}
public Draft code(String code) {
mutate(supply::code, code);
return this;
}
public Draft setCode(String code) {
return code(code);
}
public String description() {
return this.<String>get(supply::description, String.class);
}
public Draft description(String description) {
mutate(supply::description, description);
return this;
}
public Draft setDescription(String description) {
return description(description);
}
public Map<String, Long> demand() {
return this.<Map<String, Long>>get(supply::demand, Map.class);
}
public Draft demand(Map<String, Long> demand) {
mutate(supply::demand, demand);
return this;
}
public Draft setDemand(Map<String, Long> demand) {
return demand(demand);
}
public List<String> suppliers() {
return this.<List<String>>get(supply::suppliers, List.class);
}
public Draft suppliers(List<String> suppliers) {
mutate(supply::suppliers, suppliers);
return this;
}
public Draft setSuppliers(List<String> suppliers) {
return suppliers(suppliers);
}
public Set<String> shipments() {
return this.<Set<String>>get(supply::shipments, Set.class);
}
public Draft shipments(Set<String> shipments) {
mutate(supply::shipments, shipments);
return this;
}
public Draft setshipments(Set<String> shipments) {
return shipments(shipments);
}
}
} }

View file

@ -65,7 +65,8 @@ public class HierarchyTest extends AbstractEmbeddedCassandraTest {
.value(cat::nickname, "garfield") .value(cat::nickname, "garfield")
.value(cat::eatable, false) .value(cat::eatable, false)
.sync(); .sync();
Optional<Cat> animal = session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync(); Optional<Cat> animal =
session.select(Cat.class).where(cat::nickname, eq("garfield")).single().sync();
Assert.assertTrue(animal.isPresent()); Assert.assertTrue(animal.isPresent());
Cat cat = animal.get(); Cat cat = animal.get();

View file

@ -20,6 +20,7 @@ import net.helenus.mapping.annotation.InheritedTable;
@InheritedTable @InheritedTable
public interface Mammal extends Animal { public interface Mammal extends Animal {
default boolean warmBlodded() { return true; } default boolean warmBlodded() {
return true;
}
} }

View file

@ -18,21 +18,17 @@ package net.helenus.test.integration.core.simple;
import static net.helenus.core.Query.eq; import static net.helenus.core.Query.eq;
import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSet;
import java.util.*;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.Operator; import net.helenus.core.Operator;
import net.helenus.core.operation.UpdateOperation; import net.helenus.core.operation.UpdateOperation;
import net.helenus.core.reflect.Drafted;
import net.helenus.mapping.HelenusEntity;
import net.helenus.support.Fun; import net.helenus.support.Fun;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest; import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.util.*;
public class SimpleUserTest extends AbstractEmbeddedCassandraTest { public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
static User user; static User user;
@ -102,11 +98,7 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
// select as object // select as object
actual = session.<User>select(user) actual = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
.where(user::id, eq(100L))
.single()
.sync()
.orElse(null);
assertUsers(newUser, actual); assertUsers(newUser, actual);
// select by columns // select by columns
@ -192,11 +184,7 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
Assert.assertEquals("_albert", name); Assert.assertEquals("_albert", name);
User u2 = session.<User>select(user) User u2 = session.<User>select(user).where(user::id, eq(100L)).single().sync().orElse(null);
.where(user::id, eq(100L))
.single()
.sync()
.orElse(null);
Assert.assertEquals(Long.valueOf(100L), u2.id()); Assert.assertEquals(Long.valueOf(100L), u2.id());
Assert.assertEquals("albert", u2.name()); Assert.assertEquals("albert", u2.name());
@ -204,31 +192,27 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
// //
User greg = User greg =
session session
.<User>insert(user) .<User>insert(user)
.value(user::name, "greg") .value(user::name, "greg")
.value(user::age, 44) .value(user::age, 44)
.value(user::type, UserType.USER) .value(user::type, UserType.USER)
.value(user::id, 1234L) .value(user::id, 1234L)
.sync(); .sync();
Optional<User> maybeGreg = Optional<User> maybeGreg =
session session.<User>select(user).where(user::id, eq(1234L)).single().sync();
.<User>select(user)
.where(user::id, eq(1234L))
.single()
.sync();
// INSERT // INSERT
session session
.update() .update()
.set(user::name, null) .set(user::name, null)
.set(user::age, null) .set(user::age, null)
.set(user::type, null) .set(user::type, null)
.where(user::id, eq(100L)) .where(user::id, eq(100L))
.zipkinContext(null) .zipkinContext(null)
.sync(); .sync();
Fun.Tuple3<String, Integer, UserType> tuple = Fun.Tuple3<String, Integer, UserType> tuple =
session session
@ -252,21 +236,16 @@ public class SimpleUserTest extends AbstractEmbeddedCassandraTest {
public void testZipkin() throws Exception { public void testZipkin() throws Exception {
session session
.update() .update()
.set(user::name, null) .set(user::name, null)
.set(user::age, null) .set(user::age, null)
.set(user::type, null) .set(user::type, null)
.where(user::id, eq(100L)) .where(user::id, eq(100L))
.zipkinContext(null) .zipkinContext(null)
.sync(); .sync();
UpdateOperation<ResultSet> update = session.update(); UpdateOperation<ResultSet> update = session.update();
update update.set(user::name, null).zipkinContext(null).sync();
.set(user::name, null)
.zipkinContext(null)
.sync();
} }
private void assertUsers(User expected, User actual) { private void assertUsers(User expected, User actual) {

View file

@ -42,11 +42,8 @@ public class TupleMapTest extends TupleCollectionTest {
// read full object // read full object
Book actual = session.<Book>select(book) Book actual =
.where(book::id, Query.eq(id)) session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
.single()
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
assertEqualMaps(writers, actual.writers()); assertEqualMaps(writers, actual.writers());
Assert.assertNull(actual.reviewers()); Assert.assertNull(actual.reviewers());
@ -77,11 +74,7 @@ public class TupleMapTest extends TupleCollectionTest {
session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync(); session.update().set(book::writers, expected).where(book::id, Query.eq(id)).sync();
actual = session.<Book>select(book) actual = session.<Book>select(book).where(book::id, Query.eq(id)).single().sync().orElse(null);
.where(book::id, Query.eq(id))
.single()
.sync()
.orElse(null);
Assert.assertEquals(id, actual.id()); Assert.assertEquals(id, actual.id());
assertEqualMaps(expected, actual.writers()); assertEqualMaps(expected, actual.writers());
@ -96,7 +89,8 @@ public class TupleMapTest extends TupleCollectionTest {
expected.put(third, unk); expected.put(third, unk);
session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync(); session.update().put(book::writers, third, unk).where(book::id, Query.eq(id)).sync();
actualMap = session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1; actualMap =
session.select(book::writers).where(book::id, Query.eq(id)).sync().findFirst().get()._1;
assertEqualMaps(expected, actualMap); assertEqualMaps(expected, actualMap);
// putAll operation // putAll operation

View file

@ -15,6 +15,9 @@
*/ */
package net.helenus.test.integration.core.unitofwork; package net.helenus.test.integration.core.unitofwork;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
import net.helenus.core.UnitOfWork; import net.helenus.core.UnitOfWork;
@ -23,102 +26,125 @@ import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AndThenOrderTest extends AbstractEmbeddedCassandraTest { public class AndThenOrderTest extends AbstractEmbeddedCassandraTest {
static HelenusSession session; static HelenusSession session;
@BeforeClass @BeforeClass
public static void beforeTest() { public static void beforeTest() {
session = Helenus.init(getSession()) session = Helenus.init(getSession()).showCql().autoCreateDrop().get();
.showCql() }
.autoCreateDrop()
.get();
}
@Test @Test
public void testAndThenOrdering() throws Exception { public void testAndThenOrdering() throws Exception {
List<String> q = new ArrayList<String>(5); List<String> q = new ArrayList<String>(5);
UnitOfWork uow1, uow2, uow3, uow4, uow5; UnitOfWork uow1, uow2, uow3, uow4, uow5;
uow5 = session.begin(); uow5 = session.begin();
uow3 = session.begin(uow5); uow3 = session.begin(uow5);
uow1 = session.begin(uow3); uow1 = session.begin(uow3);
uow1.commit().andThen(() -> { q.add("1"); }); uow1.commit()
uow2 = session.begin(uow3); .andThen(
uow2.commit().andThen(() -> { q.add("2"); }); () -> {
uow3.commit().andThen(() -> { q.add("3"); }); q.add("1");
uow4 = session.begin(uow5); });
uow4.commit().andThen(() -> { q.add("4"); }); uow2 = session.begin(uow3);
uow5.commit().andThen(() -> { q.add("5"); }); uow2.commit()
.andThen(
() -> {
q.add("2");
});
uow3.commit()
.andThen(
() -> {
q.add("3");
});
uow4 = session.begin(uow5);
uow4.commit()
.andThen(
() -> {
q.add("4");
});
uow5.commit()
.andThen(
() -> {
q.add("5");
});
System.out.println(q); System.out.println(q);
Assert.assertTrue(Arrays.equals(q.toArray(new String[5]), new String[] {"1", "2", "3", "4", "5"})); Assert.assertTrue(
Arrays.equals(q.toArray(new String[5]), new String[] {"1", "2", "3", "4", "5"}));
}
} @Test
public void testExceptionWithinAndThen() throws Exception {
List<String> q = new ArrayList<String>(5);
UnitOfWork uow1, uow2, uow3, uow4, uow5;
@Test uow5 = session.begin();
public void testExceptionWithinAndThen() throws Exception { uow4 = session.begin(uow5);
List<String> q = new ArrayList<String>(5); try {
UnitOfWork uow1, uow2, uow3, uow4, uow5; uow3 = session.begin(uow4);
uow1 = session.begin(uow3);
uow5 = session.begin(); uow1.commit()
uow4 = session.begin(uow5); .andThen(
try { () -> {
uow3 = session.begin(uow4);
uow1 = session.begin(uow3);
uow1.commit().andThen(() -> {
q.add("1"); q.add("1");
}); });
uow2 = session.begin(uow3); uow2 = session.begin(uow3);
uow2.commit().andThen(() -> { uow2.commit()
.andThen(
() -> {
q.add("2"); q.add("2");
}); });
uow3.commit().andThen(() -> { uow3.commit()
.andThen(
() -> {
q.add("3"); q.add("3");
}); });
uow4.commit().andThen(() -> { uow4.commit()
.andThen(
() -> {
q.add("4"); q.add("4");
});
throw new Exception();
} catch (Exception e) {
uow4.abort();
}
uow5.commit()
.andThen(
() -> {
q.add("5");
}); });
throw new Exception();
} catch(Exception e) {
uow4.abort();
}
uow5.commit().andThen(() -> { q.add("5"); });
System.out.println(q); System.out.println(q);
Assert.assertTrue(q.isEmpty() == true); Assert.assertTrue(q.isEmpty() == true);
}
@Test
public void testClosableWillAbortWhenNotCommitted() throws Exception {
UnitOfWork unitOfWork;
try (UnitOfWork uow = session.begin()) {
unitOfWork = uow;
Assert.assertFalse(uow.hasAborted());
} }
Assert.assertTrue(unitOfWork.hasAborted());
}
@Test @Test
public void testClosableWillAbortWhenNotCommitted() throws Exception { public void testClosable() throws Exception {
UnitOfWork unitOfWork; UnitOfWork unitOfWork;
try(UnitOfWork uow = session.begin()) { try (UnitOfWork uow = session.begin()) {
unitOfWork = uow; unitOfWork = uow;
Assert.assertFalse(uow.hasAborted()); Assert.assertFalse(uow.hasAborted());
} uow.commit()
Assert.assertTrue(unitOfWork.hasAborted()); .andThen(
() -> {
}
@Test
public void testClosable() throws Exception {
UnitOfWork unitOfWork;
try(UnitOfWork uow = session.begin()) {
unitOfWork = uow;
Assert.assertFalse(uow.hasAborted());
uow.commit().andThen(() -> {
Assert.assertFalse(uow.hasAborted()); Assert.assertFalse(uow.hasAborted());
Assert.assertTrue(uow.hasCommitted()); Assert.assertTrue(uow.hasCommitted());
}); });
}
Assert.assertFalse(unitOfWork.hasAborted());
Assert.assertTrue(unitOfWork.hasCommitted());
} }
Assert.assertFalse(unitOfWork.hasAborted());
Assert.assertTrue(unitOfWork.hasCommitted());
}
} }

View file

@ -15,16 +15,13 @@
*/ */
package net.helenus.test.integration.core.unitofwork; package net.helenus.test.integration.core.unitofwork;
import net.helenus.mapping.annotation.*;
import com.datastax.driver.core.DataType.Name; import com.datastax.driver.core.DataType.Name;
import java.util.Set; import java.util.Set;
import net.helenus.mapping.annotation.*;
@UDT @UDT
public interface Directory extends FilesystemNode { public interface Directory extends FilesystemNode {
@Types.Set(Name.TIMEUUID) @Types.Set(Name.TIMEUUID)
Set<FilesystemNode> inodes(); Set<FilesystemNode> inodes();
} }

View file

@ -17,11 +17,9 @@ package net.helenus.test.integration.core.unitofwork;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.*;
@UDT @UDT
public interface File extends FilesystemNode { public interface File extends FilesystemNode {
@Column @Column
byte[] data(); byte[] data();
} }

View file

@ -20,6 +20,5 @@ import net.helenus.mapping.annotation.UDT;
@UDT @UDT
public interface FileAttributes { public interface FileAttributes {
String owner(); String owner();
} }

View file

@ -15,20 +15,18 @@
*/ */
package net.helenus.test.integration.core.unitofwork; package net.helenus.test.integration.core.unitofwork;
import net.helenus.mapping.annotation.*;
import java.util.UUID; import java.util.UUID;
import net.helenus.mapping.annotation.*;
@Table("fs") @Table("fs")
public interface FilesystemNode { public interface FilesystemNode {
@PartitionKey @PartitionKey
UUID inode(); UUID inode();
@ClusteringColumn @ClusteringColumn
String name(); String name();
@Column
FileAttributes attr();
@Column
FileAttributes attr();
} }

View file

@ -15,7 +15,10 @@
*/ */
package net.helenus.test.integration.core.unitofwork; package net.helenus.test.integration.core.unitofwork;
import static net.helenus.core.Query.eq;
import com.datastax.driver.core.utils.UUIDs; import com.datastax.driver.core.utils.UUIDs;
import java.util.UUID;
import net.bytebuddy.utility.RandomString; import net.bytebuddy.utility.RandomString;
import net.helenus.core.Helenus; import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession; import net.helenus.core.HelenusSession;
@ -29,167 +32,161 @@ import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.util.UUID;
import static net.helenus.core.Query.eq;
@Table @Table
@Cacheable @Cacheable
interface Widget { interface Widget {
@PartitionKey @PartitionKey
UUID id(); UUID id();
@Column
String name();
}
@Column
String name();
}
public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest { public class UnitOfWorkTest extends AbstractEmbeddedCassandraTest {
static Widget widget; static Widget widget;
static HelenusSession session; static HelenusSession session;
@BeforeClass
public static void beforeTest() {
session = Helenus.init(getSession()).showCql().add(Widget.class).autoCreateDrop().get();
widget = session.dsl(Widget.class);
}
@BeforeClass @Test
public static void beforeTest() { public void testSelectAfterSelect() throws Exception {
session = Helenus.init(getSession()) Widget w1, w2;
.showCql() UUID key = UUIDs.timeBased();
.add(Widget.class)
.autoCreateDrop()
.get();
widget = session.dsl(Widget.class);
}
@Test // This should inserted Widget, but not cache it.
public void testSelectAfterSelect() throws Exception { session
Widget w1, w2; .<Widget>insert(widget)
UUID key = UUIDs.timeBased(); .value(widget::id, key)
.value(widget::name, RandomString.make(20))
.sync();
// This should inserted Widget, but not cache it. try (UnitOfWork uow = session.begin()) {
session.<Widget>insert(widget)
.value(widget::id, key)
.value(widget::name, RandomString.make(20))
.sync();
try (UnitOfWork uow = session.begin()) { // This should read from the database and return a Widget.
w1 =
session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
// This should read from the database and return a Widget. // This should read from the cache and get the same instance of a Widget.
w1 = session.<Widget>select(widget) w2 =
.where(widget::id, eq(key)) session.<Widget>select(widget).where(widget::id, eq(key)).single().sync(uow).orElse(null);
.single()
.sync(uow)
.orElse(null);
// This should read from the cache and get the same instance of a Widget.
w2 = session.<Widget>select(widget)
.where(widget::id, eq(key))
.single()
.sync(uow)
.orElse(null);
uow.commit()
.andThen(() -> {
Assert.assertEquals(w1, w2);
});
}
}
@Test
public void testSelectAfterNestedSelect() throws Exception {
Widget w1, w2, w3, w4;
UUID key1 = UUIDs.timeBased();
UUID key2 = UUIDs.timeBased();
// This should inserted Widget, and not cache it in uow1.
try (UnitOfWork uow1 = session.begin()) {
w1 = session.<Widget>insert(widget)
.value(widget::id, key1)
.value(widget::name, RandomString.make(20))
.sync(uow1);
try (UnitOfWork uow2 = session.begin(uow1)) {
// This should read from uow1's cache and return the same Widget.
w2 = session.<Widget>select(widget)
.where(widget::id, eq(key1))
.single()
.sync(uow2)
.orElse(null);
uow.commit()
.andThen(
() -> {
Assert.assertEquals(w1, w2); Assert.assertEquals(w1, w2);
});
w3 = session.<Widget>insert(widget)
.value(widget::id, key2)
.value(widget::name, RandomString.make(20))
.sync(uow2);
uow2.commit()
.andThen(() -> {
Assert.assertEquals(w1, w2);
});
}
// This should read from the cache and get the same instance of a Widget.
w4 = session.<Widget>select(widget)
.where(widget::id, eq(key2))
.single()
.sync(uow1)
.orElse(null);
uow1.commit()
.andThen(() -> {
Assert.assertEquals(w3, w4);
});
}
} }
/* }
@Test
public void testSelectAfterInsertProperlyCachesEntity() throws Exception {
Widget w1, w2, w3, w4;
UUID key = UUIDs.timeBased();
try (UnitOfWork uow = session.begin()) { @Test
public void testSelectAfterNestedSelect() throws Exception {
Widget w1, w2, w3, w4;
UUID key1 = UUIDs.timeBased();
UUID key2 = UUIDs.timeBased();
// This should cache the inserted Widget. // This should inserted Widget, and not cache it in uow1.
w1 = session.<Widget>insert(widget) try (UnitOfWork uow1 = session.begin()) {
.value(widget::id, key) w1 =
.value(widget::name, RandomString.make(20)) session
.sync(uow); .<Widget>insert(widget)
.value(widget::id, key1)
.value(widget::name, RandomString.make(20))
.sync(uow1);
// This should read from the cache and get the same instance of a Widget. try (UnitOfWork uow2 = session.begin(uow1)) {
w2 = session.<Widget>select(widget)
.where(widget::id, eq(key))
.single()
.sync(uow)
.orElse(null);
uow.commit() // This should read from uow1's cache and return the same Widget.
.andThen(() -> { w2 =
Assert.assertEquals(w1, w2); session
}); .<Widget>select(widget)
} .where(widget::id, eq(key1))
// This should read the widget from the session cache and maintain object identity.
w3 = session.<Widget>select(widget)
.where(widget::id, eq(key))
.single() .single()
.sync() .sync(uow2)
.orElse(null); .orElse(null);
Assert.assertEquals(w1, w3); Assert.assertEquals(w1, w2);
// This should read the widget from the database, no object identity but values should match. w3 =
w4 = session.<Widget>select(widget) session
.where(widget::id, eq(key)) .<Widget>insert(widget)
.ignoreCache() .value(widget::id, key2)
.single() .value(widget::name, RandomString.make(20))
.sync() .sync(uow2);
.orElse(null);
Assert.assertNotEquals(w1, w4); uow2.commit()
Assert.assertTrue(w1.equals(w4)); .andThen(
() -> {
Assert.assertEquals(w1, w2);
});
}
// This should read from the cache and get the same instance of a Widget.
w4 =
session
.<Widget>select(widget)
.where(widget::id, eq(key2))
.single()
.sync(uow1)
.orElse(null);
uow1.commit()
.andThen(
() -> {
Assert.assertEquals(w3, w4);
});
} }
*/ }
/*
@Test
public void testSelectAfterInsertProperlyCachesEntity() throws Exception {
Widget w1, w2, w3, w4;
UUID key = UUIDs.timeBased();
try (UnitOfWork uow = session.begin()) {
// This should cache the inserted Widget.
w1 = session.<Widget>insert(widget)
.value(widget::id, key)
.value(widget::name, RandomString.make(20))
.sync(uow);
// This should read from the cache and get the same instance of a Widget.
w2 = session.<Widget>select(widget)
.where(widget::id, eq(key))
.single()
.sync(uow)
.orElse(null);
uow.commit()
.andThen(() -> {
Assert.assertEquals(w1, w2);
});
}
// This should read the widget from the session cache and maintain object identity.
w3 = session.<Widget>select(widget)
.where(widget::id, eq(key))
.single()
.sync()
.orElse(null);
Assert.assertEquals(w1, w3);
// This should read the widget from the database, no object identity but values should match.
w4 = session.<Widget>select(widget)
.where(widget::id, eq(key))
.ignoreCache()
.single()
.sync()
.orElse(null);
Assert.assertNotEquals(w1, w4);
Assert.assertTrue(w1.equals(w4));
}
*/
} }

View file

@ -19,7 +19,6 @@ import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.helenus.core.reflect.Drafted; import net.helenus.core.reflect.Drafted;
import net.helenus.mapping.HelenusEntity;
import net.helenus.mapping.annotation.*; import net.helenus.mapping.annotation.*;
@Table @Table