formatting
This commit is contained in:
parent
602e3521b4
commit
6ad99fc459
245 changed files with 11567 additions and 11917 deletions
|
@ -5,18 +5,19 @@ import java.util.List;
|
||||||
|
|
||||||
public class DefaultMetadata extends Metadata {
|
public class DefaultMetadata extends Metadata {
|
||||||
|
|
||||||
public DefaultMetadata() { super(null); }
|
public DefaultMetadata() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
private DefaultMetadata(Cluster.Manager cluster) {
|
private DefaultMetadata(Cluster.Manager cluster) {
|
||||||
super(cluster);
|
super(cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TupleType newTupleType(DataType... types) {
|
public TupleType newTupleType(DataType... types) {
|
||||||
return newTupleType(Arrays.asList(types));
|
return newTupleType(Arrays.asList(types));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TupleType newTupleType(List<DataType> types) {
|
|
||||||
return new TupleType(types, ProtocolVersion.NEWEST_SUPPORTED, CodecRegistry.DEFAULT_INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public TupleType newTupleType(List<DataType> types) {
|
||||||
|
return new TupleType(types, ProtocolVersion.NEWEST_SUPPORTED, CodecRegistry.DEFAULT_INSTANCE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,132 +1,157 @@
|
||||||
package com.datastax.driver.core.schemabuilder;
|
package com.datastax.driver.core.schemabuilder;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
import static com.datastax.driver.core.schemabuilder.SchemaStatement.STATEMENT_START;
|
import static com.datastax.driver.core.schemabuilder.SchemaStatement.STATEMENT_START;
|
||||||
import static com.datastax.driver.core.schemabuilder.SchemaStatement.validateNotEmpty;
|
import static com.datastax.driver.core.schemabuilder.SchemaStatement.validateNotEmpty;
|
||||||
import static com.datastax.driver.core.schemabuilder.SchemaStatement.validateNotKeyWord;
|
import static com.datastax.driver.core.schemabuilder.SchemaStatement.validateNotKeyWord;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
public class CreateCustomIndex extends CreateIndex {
|
public class CreateCustomIndex extends CreateIndex {
|
||||||
|
|
||||||
private String indexName;
|
private String indexName;
|
||||||
private boolean ifNotExists = false;
|
private boolean ifNotExists = false;
|
||||||
private Optional<String> keyspaceName = Optional.absent();
|
private Optional<String> keyspaceName = Optional.absent();
|
||||||
private String tableName;
|
private String tableName;
|
||||||
private String columnName;
|
private String columnName;
|
||||||
private boolean keys;
|
private boolean keys;
|
||||||
|
|
||||||
CreateCustomIndex(String indexName) {
|
CreateCustomIndex(String indexName) {
|
||||||
super(indexName);
|
super(indexName);
|
||||||
validateNotEmpty(indexName, "Index name");
|
validateNotEmpty(indexName, "Index name");
|
||||||
validateNotKeyWord(indexName, String.format("The index name '%s' is not allowed because it is a reserved keyword", indexName));
|
validateNotKeyWord(
|
||||||
this.indexName = indexName;
|
indexName,
|
||||||
|
String.format(
|
||||||
|
"The index name '%s' is not allowed because it is a reserved keyword", indexName));
|
||||||
|
this.indexName = indexName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the 'IF NOT EXISTS' condition to this CREATE INDEX statement.
|
||||||
|
*
|
||||||
|
* @return this CREATE INDEX statement.
|
||||||
|
*/
|
||||||
|
public CreateIndex ifNotExists() {
|
||||||
|
this.ifNotExists = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the keyspace and table to create the index on.
|
||||||
|
*
|
||||||
|
* @param keyspaceName the keyspace name.
|
||||||
|
* @param tableName the table name.
|
||||||
|
* @return a {@link CreateIndex.CreateIndexOn} that will allow the specification of the column.
|
||||||
|
*/
|
||||||
|
public CreateIndex.CreateIndexOn onTable(String keyspaceName, String tableName) {
|
||||||
|
validateNotEmpty(keyspaceName, "Keyspace name");
|
||||||
|
validateNotEmpty(tableName, "Table name");
|
||||||
|
validateNotKeyWord(
|
||||||
|
keyspaceName,
|
||||||
|
String.format(
|
||||||
|
"The keyspace name '%s' is not allowed because it is a reserved keyword",
|
||||||
|
keyspaceName));
|
||||||
|
validateNotKeyWord(
|
||||||
|
tableName,
|
||||||
|
String.format(
|
||||||
|
"The table name '%s' is not allowed because it is a reserved keyword", tableName));
|
||||||
|
this.keyspaceName = Optional.fromNullable(keyspaceName);
|
||||||
|
this.tableName = tableName;
|
||||||
|
return new CreateCustomIndex.CreateIndexOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the table to create the index on.
|
||||||
|
*
|
||||||
|
* @param tableName the table name.
|
||||||
|
* @return a {@link CreateIndex.CreateIndexOn} that will allow the specification of the column.
|
||||||
|
*/
|
||||||
|
public CreateIndex.CreateIndexOn onTable(String tableName) {
|
||||||
|
validateNotEmpty(tableName, "Table name");
|
||||||
|
validateNotKeyWord(
|
||||||
|
tableName,
|
||||||
|
String.format(
|
||||||
|
"The table name '%s' is not allowed because it is a reserved keyword", tableName));
|
||||||
|
this.tableName = tableName;
|
||||||
|
return new CreateCustomIndex.CreateIndexOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateIndexOn extends CreateIndex.CreateIndexOn {
|
||||||
|
/**
|
||||||
|
* Specify the column to create the index on.
|
||||||
|
*
|
||||||
|
* @param columnName the column name.
|
||||||
|
* @return the final CREATE INDEX statement.
|
||||||
|
*/
|
||||||
|
public SchemaStatement andColumn(String columnName) {
|
||||||
|
validateNotEmpty(columnName, "Column name");
|
||||||
|
validateNotKeyWord(
|
||||||
|
columnName,
|
||||||
|
String.format(
|
||||||
|
"The column name '%s' is not allowed because it is a reserved keyword", columnName));
|
||||||
|
CreateCustomIndex.this.columnName = columnName;
|
||||||
|
return SchemaStatement.fromQueryString(buildInternal());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the 'IF NOT EXISTS' condition to this CREATE INDEX statement.
|
* Create an index on the keys of the given map column.
|
||||||
*
|
*
|
||||||
* @return this CREATE INDEX statement.
|
* @param columnName the column name.
|
||||||
|
* @return the final CREATE INDEX statement.
|
||||||
*/
|
*/
|
||||||
public CreateIndex ifNotExists() {
|
public SchemaStatement andKeysOfColumn(String columnName) {
|
||||||
this.ifNotExists = true;
|
validateNotEmpty(columnName, "Column name");
|
||||||
return this;
|
validateNotKeyWord(
|
||||||
|
columnName,
|
||||||
|
String.format(
|
||||||
|
"The column name '%s' is not allowed because it is a reserved keyword", columnName));
|
||||||
|
CreateCustomIndex.this.columnName = columnName;
|
||||||
|
CreateCustomIndex.this.keys = true;
|
||||||
|
return SchemaStatement.fromQueryString(buildInternal());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getCustomClassName() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String getOptions() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String buildInternal() {
|
||||||
|
StringBuilder createStatement =
|
||||||
|
new StringBuilder(STATEMENT_START).append("CREATE CUSTOM INDEX ");
|
||||||
|
|
||||||
|
if (ifNotExists) {
|
||||||
|
createStatement.append("IF NOT EXISTS ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
createStatement.append(indexName).append(" ON ");
|
||||||
* Specify the keyspace and table to create the index on.
|
|
||||||
*
|
if (keyspaceName.isPresent()) {
|
||||||
* @param keyspaceName the keyspace name.
|
createStatement.append(keyspaceName.get()).append(".");
|
||||||
* @param tableName the table name.
|
}
|
||||||
* @return a {@link CreateIndex.CreateIndexOn} that will allow the specification of the column.
|
createStatement.append(tableName);
|
||||||
*/
|
|
||||||
public CreateIndex.CreateIndexOn onTable(String keyspaceName, String tableName) {
|
createStatement.append("(");
|
||||||
validateNotEmpty(keyspaceName, "Keyspace name");
|
if (keys) {
|
||||||
validateNotEmpty(tableName, "Table name");
|
createStatement.append("KEYS(");
|
||||||
validateNotKeyWord(keyspaceName, String.format("The keyspace name '%s' is not allowed because it is a reserved keyword", keyspaceName));
|
|
||||||
validateNotKeyWord(tableName, String.format("The table name '%s' is not allowed because it is a reserved keyword", tableName));
|
|
||||||
this.keyspaceName = Optional.fromNullable(keyspaceName);
|
|
||||||
this.tableName = tableName;
|
|
||||||
return new CreateCustomIndex.CreateIndexOn();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
createStatement.append(columnName);
|
||||||
* Specify the table to create the index on.
|
|
||||||
*
|
if (keys) {
|
||||||
* @param tableName the table name.
|
createStatement.append(")");
|
||||||
* @return a {@link CreateIndex.CreateIndexOn} that will allow the specification of the column.
|
|
||||||
*/
|
|
||||||
public CreateIndex.CreateIndexOn onTable(String tableName) {
|
|
||||||
validateNotEmpty(tableName, "Table name");
|
|
||||||
validateNotKeyWord(tableName, String.format("The table name '%s' is not allowed because it is a reserved keyword", tableName));
|
|
||||||
this.tableName = tableName;
|
|
||||||
return new CreateCustomIndex.CreateIndexOn();
|
|
||||||
}
|
}
|
||||||
|
createStatement.append(")");
|
||||||
|
|
||||||
public class CreateIndexOn extends CreateIndex.CreateIndexOn {
|
createStatement.append(" USING '");
|
||||||
/**
|
createStatement.append(getCustomClassName());
|
||||||
* Specify the column to create the index on.
|
createStatement.append("' WITH OPTIONS = {");
|
||||||
*
|
createStatement.append(getOptions());
|
||||||
* @param columnName the column name.
|
createStatement.append(" }");
|
||||||
* @return the final CREATE INDEX statement.
|
|
||||||
*/
|
|
||||||
public SchemaStatement andColumn(String columnName) {
|
|
||||||
validateNotEmpty(columnName, "Column name");
|
|
||||||
validateNotKeyWord(columnName, String.format("The column name '%s' is not allowed because it is a reserved keyword", columnName));
|
|
||||||
CreateCustomIndex.this.columnName = columnName;
|
|
||||||
return SchemaStatement.fromQueryString(buildInternal());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return createStatement.toString();
|
||||||
* Create an index on the keys of the given map column.
|
}
|
||||||
*
|
|
||||||
* @param columnName the column name.
|
|
||||||
* @return the final CREATE INDEX statement.
|
|
||||||
*/
|
|
||||||
public SchemaStatement andKeysOfColumn(String columnName) {
|
|
||||||
validateNotEmpty(columnName, "Column name");
|
|
||||||
validateNotKeyWord(columnName, String.format("The column name '%s' is not allowed because it is a reserved keyword", columnName));
|
|
||||||
CreateCustomIndex.this.columnName = columnName;
|
|
||||||
CreateCustomIndex.this.keys = true;
|
|
||||||
return SchemaStatement.fromQueryString(buildInternal());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String getCustomClassName() { return ""; }
|
|
||||||
String getOptions() { return ""; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String buildInternal() {
|
|
||||||
StringBuilder createStatement = new StringBuilder(STATEMENT_START).append("CREATE CUSTOM INDEX ");
|
|
||||||
|
|
||||||
if (ifNotExists) {
|
|
||||||
createStatement.append("IF NOT EXISTS ");
|
|
||||||
}
|
|
||||||
|
|
||||||
createStatement.append(indexName).append(" ON ");
|
|
||||||
|
|
||||||
if (keyspaceName.isPresent()) {
|
|
||||||
createStatement.append(keyspaceName.get()).append(".");
|
|
||||||
}
|
|
||||||
createStatement.append(tableName);
|
|
||||||
|
|
||||||
createStatement.append("(");
|
|
||||||
if (keys) {
|
|
||||||
createStatement.append("KEYS(");
|
|
||||||
}
|
|
||||||
|
|
||||||
createStatement.append(columnName);
|
|
||||||
|
|
||||||
if (keys) {
|
|
||||||
createStatement.append(")");
|
|
||||||
}
|
|
||||||
createStatement.append(")");
|
|
||||||
|
|
||||||
createStatement.append(" USING '");
|
|
||||||
createStatement.append(getCustomClassName());
|
|
||||||
createStatement.append("' WITH OPTIONS = {");
|
|
||||||
createStatement.append(getOptions());
|
|
||||||
createStatement.append(" }");
|
|
||||||
|
|
||||||
return createStatement.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,17 @@ package com.datastax.driver.core.schemabuilder;
|
||||||
|
|
||||||
public class CreateSasiIndex extends CreateCustomIndex {
|
public class CreateSasiIndex extends CreateCustomIndex {
|
||||||
|
|
||||||
public CreateSasiIndex(String indexName) {
|
public CreateSasiIndex(String indexName) {
|
||||||
super(indexName);
|
super(indexName);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getCustomClassName() {
|
String getCustomClassName() {
|
||||||
return "org.apache.cassandra.index.sasi.SASIIndex";
|
return "org.apache.cassandra.index.sasi.SASIIndex";
|
||||||
}
|
}
|
||||||
|
|
||||||
String getOptions() {
|
String getOptions() {
|
||||||
return "'analyzer_class': "
|
return "'analyzer_class': "
|
||||||
+ "'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer', "
|
+ "'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer', "
|
||||||
+ "'case_sensitive': 'false'";
|
+ "'case_sensitive': 'false'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,24 +17,22 @@ package com.datastax.driver.core.schemabuilder;
|
||||||
|
|
||||||
import com.datastax.driver.core.CodecRegistry;
|
import com.datastax.driver.core.CodecRegistry;
|
||||||
|
|
||||||
/**
|
/** A built CREATE TABLE statement. */
|
||||||
* A built CREATE TABLE statement.
|
|
||||||
*/
|
|
||||||
public class CreateTable extends Create {
|
public class CreateTable extends Create {
|
||||||
|
|
||||||
public CreateTable(String keyspaceName, String tableName) {
|
public CreateTable(String keyspaceName, String tableName) {
|
||||||
super(keyspaceName, tableName);
|
super(keyspaceName, tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreateTable(String tableName) {
|
public CreateTable(String tableName) {
|
||||||
super(tableName);
|
super(tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getQueryString(CodecRegistry codecRegistry) {
|
public String getQueryString(CodecRegistry codecRegistry) {
|
||||||
return buildInternal();
|
return buildInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return buildInternal();
|
return buildInternal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package net.helenus.config;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import net.helenus.core.DslInstantiator;
|
import net.helenus.core.DslInstantiator;
|
||||||
import net.helenus.core.MapperInstantiator;
|
import net.helenus.core.MapperInstantiator;
|
||||||
import net.helenus.core.reflect.ReflectionDslInstantiator;
|
import net.helenus.core.reflect.ReflectionDslInstantiator;
|
||||||
|
@ -26,24 +25,23 @@ import net.helenus.mapping.convert.CamelCaseToUnderscoreConverter;
|
||||||
|
|
||||||
public class DefaultHelenusSettings implements HelenusSettings {
|
public class DefaultHelenusSettings implements HelenusSettings {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Function<String, String> getPropertyToColumnConverter() {
|
public Function<String, String> getPropertyToColumnConverter() {
|
||||||
return CamelCaseToUnderscoreConverter.INSTANCE;
|
return CamelCaseToUnderscoreConverter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Function<Method, Boolean> getGetterMethodDetector() {
|
public Function<Method, Boolean> getGetterMethodDetector() {
|
||||||
return GetterMethodDetector.INSTANCE;
|
return GetterMethodDetector.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DslInstantiator getDslInstantiator() {
|
public DslInstantiator getDslInstantiator() {
|
||||||
return ReflectionDslInstantiator.INSTANCE;
|
return ReflectionDslInstantiator.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public MapperInstantiator getMapperInstantiator() {
|
|
||||||
return ReflectionMapperInstantiator.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapperInstantiator getMapperInstantiator() {
|
||||||
|
return ReflectionMapperInstantiator.INSTANCE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,33 +15,29 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.config;
|
package net.helenus.config;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.Transient;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import net.helenus.mapping.annotation.Transient;
|
||||||
|
|
||||||
public enum GetterMethodDetector implements Function<Method, Boolean> {
|
public enum GetterMethodDetector implements Function<Method, Boolean> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
public Boolean apply(Method method) {
|
||||||
|
|
||||||
@Override
|
if (method == null) {
|
||||||
public Boolean apply(Method method) {
|
throw new IllegalArgumentException("empty parameter");
|
||||||
|
}
|
||||||
|
|
||||||
if (method == null) {
|
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
|
||||||
throw new IllegalArgumentException("empty parameter");
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
|
// Methods marked "Transient" are not mapped, skip them.
|
||||||
return false;
|
if (method.getDeclaredAnnotation(Transient.class) != null) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
// Methods marked "Transient" are not mapped, skip them.
|
|
||||||
if (method.getDeclaredAnnotation(Transient.class) != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,16 @@ package net.helenus.config;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import net.helenus.core.DslInstantiator;
|
import net.helenus.core.DslInstantiator;
|
||||||
import net.helenus.core.MapperInstantiator;
|
import net.helenus.core.MapperInstantiator;
|
||||||
|
|
||||||
public interface HelenusSettings {
|
public interface HelenusSettings {
|
||||||
|
|
||||||
Function<String, String> getPropertyToColumnConverter();
|
Function<String, String> getPropertyToColumnConverter();
|
||||||
|
|
||||||
Function<Method, Boolean> getGetterMethodDetector();
|
Function<Method, Boolean> getGetterMethodDetector();
|
||||||
|
|
||||||
DslInstantiator getDslInstantiator();
|
DslInstantiator getDslInstantiator();
|
||||||
|
|
||||||
MapperInstantiator getMapperInstantiator();
|
|
||||||
|
|
||||||
|
MapperInstantiator getMapperInstantiator();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,118 +15,113 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import brave.Tracer;
|
import brave.Tracer;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.datastax.driver.core.schemabuilder.SchemaStatement;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.*;
|
import com.datastax.driver.core.*;
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
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.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;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.xml.validation.Schema;
|
|
||||||
|
|
||||||
public abstract class AbstractSessionOperations {
|
public abstract class AbstractSessionOperations {
|
||||||
|
|
||||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
abstract public Session currentSession();
|
public abstract Session currentSession();
|
||||||
|
|
||||||
abstract public String usingKeyspace();
|
public abstract String usingKeyspace();
|
||||||
|
|
||||||
abstract public boolean isShowCql();
|
public abstract boolean isShowCql();
|
||||||
|
|
||||||
abstract public PrintStream getPrintStream();
|
public abstract PrintStream getPrintStream();
|
||||||
|
|
||||||
abstract public Executor getExecutor();
|
public abstract Executor getExecutor();
|
||||||
|
|
||||||
abstract public SessionRepository getSessionRepository();
|
public abstract SessionRepository getSessionRepository();
|
||||||
|
|
||||||
abstract public ColumnValueProvider getValueProvider();
|
public abstract ColumnValueProvider getValueProvider();
|
||||||
|
|
||||||
abstract public ColumnValuePreparer getValuePreparer();
|
public abstract ColumnValuePreparer getValuePreparer();
|
||||||
|
|
||||||
abstract public ConsistencyLevel getDefaultConsistencyLevel();
|
public abstract ConsistencyLevel getDefaultConsistencyLevel();
|
||||||
|
|
||||||
|
public PreparedStatement prepare(RegularStatement statement) {
|
||||||
|
try {
|
||||||
|
log(statement, false);
|
||||||
|
return currentSession().prepare(statement);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw translateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PreparedStatement prepare(RegularStatement statement) {
|
public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement) {
|
||||||
try {
|
try {
|
||||||
log(statement, false);
|
log(statement, false);
|
||||||
return currentSession().prepare(statement);
|
return currentSession().prepareAsync(statement);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw translateException(e);
|
throw translateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<PreparedStatement> prepareAsync(RegularStatement statement) {
|
public ResultSet execute(Statement statement, boolean showValues) {
|
||||||
try {
|
return executeAsync(statement, showValues).getUninterruptibly();
|
||||||
log(statement, false);
|
}
|
||||||
return currentSession().prepareAsync(statement);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
throw translateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResultSet execute(Statement statement, boolean showValues) {
|
public ResultSetFuture executeAsync(Statement statement, boolean showValues) {
|
||||||
return executeAsync(statement, showValues).getUninterruptibly();
|
try {
|
||||||
}
|
log(statement, showValues);
|
||||||
|
return currentSession().executeAsync(statement);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw translateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ResultSetFuture executeAsync(Statement statement, boolean showValues) {
|
void log(Statement statement, boolean showValues) {
|
||||||
try {
|
if (logger.isInfoEnabled()) {
|
||||||
log(statement, showValues);
|
logger.info("Execute statement " + statement);
|
||||||
return currentSession().executeAsync(statement);
|
}
|
||||||
} catch (RuntimeException e) {
|
if (isShowCql()) {
|
||||||
throw translateException(e);
|
if (statement instanceof BuiltStatement) {
|
||||||
}
|
BuiltStatement builtStatement = (BuiltStatement) statement;
|
||||||
}
|
if (showValues) {
|
||||||
|
RegularStatement regularStatement = builtStatement.setForceNoValues(true);
|
||||||
|
printCql(regularStatement.getQueryString());
|
||||||
|
} else {
|
||||||
|
printCql(builtStatement.getQueryString());
|
||||||
|
}
|
||||||
|
} else if (statement instanceof RegularStatement) {
|
||||||
|
RegularStatement regularStatement = (RegularStatement) statement;
|
||||||
|
printCql(regularStatement.getQueryString());
|
||||||
|
} else {
|
||||||
|
printCql(statement.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void log(Statement statement, boolean showValues) {
|
public Tracer getZipkinTracer() {
|
||||||
if (logger.isInfoEnabled()) {
|
return null;
|
||||||
logger.info("Execute statement " + statement);
|
}
|
||||||
}
|
|
||||||
if (isShowCql()) {
|
|
||||||
if (statement instanceof BuiltStatement) {
|
|
||||||
BuiltStatement builtStatement = (BuiltStatement) statement;
|
|
||||||
if (showValues) {
|
|
||||||
RegularStatement regularStatement = builtStatement.setForceNoValues(true);
|
|
||||||
printCql(regularStatement.getQueryString());
|
|
||||||
} else {
|
|
||||||
printCql(builtStatement.getQueryString());
|
|
||||||
}
|
|
||||||
} else if (statement instanceof RegularStatement) {
|
|
||||||
RegularStatement regularStatement = (RegularStatement) statement;
|
|
||||||
printCql(regularStatement.getQueryString());
|
|
||||||
} else {
|
|
||||||
printCql(statement.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tracer getZipkinTracer() { return null; }
|
public MetricRegistry getMetricRegistry() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public MetricRegistry getMetricRegistry() { return null; }
|
public void cache(String key, Object value) {}
|
||||||
|
|
||||||
public void cache(String key, Object value) {
|
RuntimeException translateException(RuntimeException e) {
|
||||||
}
|
if (e instanceof HelenusException) {
|
||||||
|
return e;
|
||||||
RuntimeException translateException(RuntimeException e) {
|
}
|
||||||
if (e instanceof HelenusException) {
|
throw new HelenusException(e);
|
||||||
return e;
|
}
|
||||||
}
|
|
||||||
throw new HelenusException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printCql(String cql) {
|
|
||||||
getPrintStream().println(cql);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void printCql(String cql) {
|
||||||
|
getPrintStream().println(cql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,8 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
public enum AutoDdl {
|
public enum AutoDdl {
|
||||||
VALIDATE, UPDATE, CREATE, CREATE_DROP;
|
VALIDATE,
|
||||||
|
UPDATE,
|
||||||
|
CREATE,
|
||||||
|
CREATE_DROP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,9 @@ package net.helenus.core;
|
||||||
|
|
||||||
public class ConflictingUnitOfWorkException extends Exception {
|
public class ConflictingUnitOfWorkException extends Exception {
|
||||||
|
|
||||||
final UnitOfWork uow;
|
final UnitOfWork uow;
|
||||||
|
|
||||||
ConflictingUnitOfWorkException(UnitOfWork uow) {
|
|
||||||
this.uow = uow;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ConflictingUnitOfWorkException(UnitOfWork uow) {
|
||||||
|
this.uow = uow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.Metadata;
|
import com.datastax.driver.core.Metadata;
|
||||||
|
import java.util.Optional;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
|
|
||||||
public interface DslInstantiator {
|
public interface DslInstantiator {
|
||||||
|
|
||||||
<E> E instantiate(Class<E> iface, ClassLoader classLoader, Optional<HelenusPropertyNode> parent, Metadata metadata);
|
<E> E instantiate(
|
||||||
|
Class<E> iface,
|
||||||
|
ClassLoader classLoader,
|
||||||
|
Optional<HelenusPropertyNode> parent,
|
||||||
|
Metadata metadata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,99 +15,97 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.querybuilder.Clause;
|
import com.datastax.driver.core.querybuilder.Clause;
|
||||||
|
import java.util.Objects;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.MappingUtil;
|
import net.helenus.mapping.MappingUtil;
|
||||||
import net.helenus.mapping.value.ColumnValuePreparer;
|
import net.helenus.mapping.value.ColumnValuePreparer;
|
||||||
|
|
||||||
public final class Filter<V> {
|
public final class Filter<V> {
|
||||||
|
|
||||||
private final HelenusPropertyNode node;
|
private final HelenusPropertyNode node;
|
||||||
private final Postulate<V> postulate;
|
private final Postulate<V> postulate;
|
||||||
|
|
||||||
private Filter(HelenusPropertyNode node, Postulate<V> postulate) {
|
private Filter(HelenusPropertyNode node, Postulate<V> postulate) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.postulate = postulate;
|
this.postulate = postulate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusPropertyNode getNode() {
|
public HelenusPropertyNode getNode() {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Clause getClause(ColumnValuePreparer valuePreparer) {
|
public Clause getClause(ColumnValuePreparer valuePreparer) {
|
||||||
return postulate.getClause(node, valuePreparer);
|
return postulate.getClause(node, valuePreparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> equal(Getter<V> getter, V val) {
|
public static <V> Filter<V> equal(Getter<V> getter, V val) {
|
||||||
return create(getter, Operator.EQ, val);
|
return create(getter, Operator.EQ, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> in(Getter<V> getter, V... vals) {
|
public static <V> Filter<V> in(Getter<V> getter, V... vals) {
|
||||||
Objects.requireNonNull(getter, "empty getter");
|
Objects.requireNonNull(getter, "empty getter");
|
||||||
Objects.requireNonNull(vals, "empty values");
|
Objects.requireNonNull(vals, "empty values");
|
||||||
|
|
||||||
if (vals.length == 0) {
|
if (vals.length == 0) {
|
||||||
throw new IllegalArgumentException("values array is empty");
|
throw new IllegalArgumentException("values array is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i != vals.length; ++i) {
|
for (int i = 0; i != vals.length; ++i) {
|
||||||
Objects.requireNonNull(vals[i], "value[" + i + "] is empty");
|
Objects.requireNonNull(vals[i], "value[" + i + "] is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
|
||||||
Postulate<V> postulate = Postulate.of(Operator.IN, vals);
|
Postulate<V> postulate = Postulate.of(Operator.IN, vals);
|
||||||
|
|
||||||
return new Filter<V>(node, postulate);
|
return new Filter<V>(node, postulate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> greaterThan(Getter<V> getter, V val) {
|
public static <V> Filter<V> greaterThan(Getter<V> getter, V val) {
|
||||||
return create(getter, Operator.GT, val);
|
return create(getter, Operator.GT, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> lessThan(Getter<V> getter, V val) {
|
public static <V> Filter<V> lessThan(Getter<V> getter, V val) {
|
||||||
return create(getter, Operator.LT, val);
|
return create(getter, Operator.LT, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> greaterThanOrEqual(Getter<V> getter, V val) {
|
public static <V> Filter<V> greaterThanOrEqual(Getter<V> getter, V val) {
|
||||||
return create(getter, Operator.GTE, val);
|
return create(getter, Operator.GTE, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> lessThanOrEqual(Getter<V> getter, V val) {
|
public static <V> Filter<V> lessThanOrEqual(Getter<V> getter, V val) {
|
||||||
return create(getter, Operator.LTE, val);
|
return create(getter, Operator.LTE, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> create(Getter<V> getter, Postulate<V> postulate) {
|
public static <V> Filter<V> create(Getter<V> getter, Postulate<V> postulate) {
|
||||||
Objects.requireNonNull(getter, "empty getter");
|
Objects.requireNonNull(getter, "empty getter");
|
||||||
Objects.requireNonNull(postulate, "empty operator");
|
Objects.requireNonNull(postulate, "empty operator");
|
||||||
|
|
||||||
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
|
||||||
return new Filter<V>(node, postulate);
|
return new Filter<V>(node, postulate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Filter<V> create(Getter<V> getter, Operator op, V val) {
|
public static <V> Filter<V> create(Getter<V> getter, Operator op, V val) {
|
||||||
Objects.requireNonNull(getter, "empty getter");
|
Objects.requireNonNull(getter, "empty getter");
|
||||||
Objects.requireNonNull(op, "empty op");
|
Objects.requireNonNull(op, "empty op");
|
||||||
Objects.requireNonNull(val, "empty value");
|
Objects.requireNonNull(val, "empty value");
|
||||||
|
|
||||||
if (op == Operator.IN) {
|
if (op == Operator.IN) {
|
||||||
throw new IllegalArgumentException("invalid usage of the 'in' operator, use Filter.in() static method");
|
throw new IllegalArgumentException(
|
||||||
}
|
"invalid usage of the 'in' operator, use Filter.in() static method");
|
||||||
|
}
|
||||||
|
|
||||||
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
|
||||||
Postulate<V> postulate = Postulate.of(op, val);
|
Postulate<V> postulate = Postulate.of(op, val);
|
||||||
|
|
||||||
return new Filter<V>(node, postulate);
|
return new Filter<V>(node, postulate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return node.getColumnName() + postulate.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return node.getColumnName() + postulate.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,5 @@ package net.helenus.core;
|
||||||
|
|
||||||
public interface Getter<V> {
|
public interface Getter<V> {
|
||||||
|
|
||||||
V get();
|
V get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.Cluster;
|
import com.datastax.driver.core.Cluster;
|
||||||
import com.datastax.driver.core.Metadata;
|
import com.datastax.driver.core.Metadata;
|
||||||
import com.datastax.driver.core.Session;
|
import com.datastax.driver.core.Session;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import net.helenus.config.DefaultHelenusSettings;
|
import net.helenus.config.DefaultHelenusSettings;
|
||||||
import net.helenus.config.HelenusSettings;
|
import net.helenus.config.HelenusSettings;
|
||||||
import net.helenus.core.reflect.DslExportable;
|
import net.helenus.core.reflect.DslExportable;
|
||||||
|
@ -32,156 +30,157 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class Helenus {
|
public final class Helenus {
|
||||||
|
|
||||||
private static volatile HelenusSettings settings = new DefaultHelenusSettings();
|
private static volatile HelenusSettings settings = new DefaultHelenusSettings();
|
||||||
private static final ConcurrentMap<Class<?>, Object> dslCache = new ConcurrentHashMap<Class<?>, Object>();
|
private static final ConcurrentMap<Class<?>, Object> dslCache =
|
||||||
private static final ConcurrentMap<Class<?>, Metadata> metadataForEntity = new ConcurrentHashMap<Class<?>, Metadata>();
|
new ConcurrentHashMap<Class<?>, Object>();
|
||||||
private static final Set<HelenusSession> sessions = new HashSet<HelenusSession>();
|
private static final ConcurrentMap<Class<?>, Metadata> metadataForEntity =
|
||||||
private static volatile HelenusSession singleton;
|
new ConcurrentHashMap<Class<?>, Metadata>();
|
||||||
|
private static final Set<HelenusSession> sessions = new HashSet<HelenusSession>();
|
||||||
|
private static volatile HelenusSession singleton;
|
||||||
|
|
||||||
|
private Helenus() {}
|
||||||
|
|
||||||
private Helenus() {
|
protected static void setSession(HelenusSession session) {
|
||||||
}
|
sessions.add(session);
|
||||||
|
singleton = session;
|
||||||
|
}
|
||||||
|
|
||||||
protected static void setSession(HelenusSession session) {
|
public static HelenusSession session() {
|
||||||
sessions.add(session);
|
return singleton;
|
||||||
singleton = session;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static HelenusSession session() {
|
public static void shutdown() {
|
||||||
return singleton;
|
sessions.forEach(
|
||||||
}
|
(session) -> {
|
||||||
|
session.close();
|
||||||
public static void shutdown() {
|
sessions.remove(session);
|
||||||
sessions.forEach((session) -> {
|
|
||||||
session.close();
|
|
||||||
sessions.remove(session);
|
|
||||||
});
|
});
|
||||||
dslCache.clear();
|
dslCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HelenusSettings settings() {
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HelenusSettings settings(HelenusSettings overrideSettings) {
|
||||||
|
HelenusSettings old = settings;
|
||||||
|
settings = overrideSettings;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SessionInitializer connect(Cluster cluster) {
|
||||||
|
Session session = cluster.connect();
|
||||||
|
return new SessionInitializer(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SessionInitializer connect(Cluster cluster, String keyspace) {
|
||||||
|
Session session = cluster.connect(keyspace);
|
||||||
|
return new SessionInitializer(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SessionInitializer init(Session session) {
|
||||||
|
|
||||||
|
if (session == null) {
|
||||||
|
throw new IllegalArgumentException("empty session");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HelenusSettings settings() {
|
return new SessionInitializer(session);
|
||||||
return settings;
|
}
|
||||||
|
|
||||||
|
public static void clearDslCache() {
|
||||||
|
dslCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> E dsl(Class<E> iface) {
|
||||||
|
return dsl(iface, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> E dsl(Class<E> iface, Metadata metadata) {
|
||||||
|
return dsl(iface, iface.getClassLoader(), Optional.empty(), metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> E dsl(Class<E> iface, ClassLoader classLoader, Metadata metadata) {
|
||||||
|
return dsl(iface, classLoader, Optional.empty(), metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> E dsl(
|
||||||
|
Class<E> iface,
|
||||||
|
ClassLoader classLoader,
|
||||||
|
Optional<HelenusPropertyNode> parent,
|
||||||
|
Metadata metadata) {
|
||||||
|
|
||||||
|
Object instance = null;
|
||||||
|
|
||||||
|
if (!parent.isPresent()) {
|
||||||
|
instance = dslCache.get(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HelenusSettings settings(HelenusSettings overrideSettings) {
|
if (instance == null) {
|
||||||
HelenusSettings old = settings;
|
|
||||||
settings = overrideSettings;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SessionInitializer connect(Cluster cluster) {
|
instance = settings.getDslInstantiator().instantiate(iface, classLoader, parent, metadata);
|
||||||
Session session = cluster.connect();
|
|
||||||
return new SessionInitializer(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SessionInitializer connect(Cluster cluster, String keyspace) {
|
if (!parent.isPresent()) {
|
||||||
Session session = cluster.connect(keyspace);
|
|
||||||
return new SessionInitializer(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SessionInitializer init(Session session) {
|
Object c = dslCache.putIfAbsent(iface, instance);
|
||||||
|
if (c != null) {
|
||||||
if (session == null) {
|
instance = c;
|
||||||
throw new IllegalArgumentException("empty session");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new SessionInitializer(session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearDslCache() {
|
return (E) instance;
|
||||||
dslCache.clear();
|
}
|
||||||
|
|
||||||
|
public static <E> E map(Class<E> iface, Map<String, Object> src) {
|
||||||
|
return map(iface, src, iface.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> E map(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) {
|
||||||
|
return settings.getMapperInstantiator().instantiate(iface, src, classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HelenusEntity entity(Class<?> iface) {
|
||||||
|
return entity(iface, metadataForEntity.get(iface));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HelenusEntity entity(Class<?> iface, Metadata metadata) {
|
||||||
|
|
||||||
|
Object dsl = dsl(iface, metadata);
|
||||||
|
|
||||||
|
DslExportable e = (DslExportable) dsl;
|
||||||
|
|
||||||
|
return e.getHelenusMappingEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HelenusEntity resolve(Object ifaceOrDsl) {
|
||||||
|
return resolve(ifaceOrDsl, metadataForEntity.get(ifaceOrDsl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HelenusEntity resolve(Object ifaceOrDsl, Metadata metadata) {
|
||||||
|
|
||||||
|
if (ifaceOrDsl == null) {
|
||||||
|
throw new HelenusMappingException("ifaceOrDsl is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E> E dsl(Class<E> iface) {
|
if (ifaceOrDsl instanceof DslExportable) {
|
||||||
return dsl(iface, null);
|
|
||||||
|
DslExportable e = (DslExportable) ifaceOrDsl;
|
||||||
|
|
||||||
|
return e.getHelenusMappingEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E> E dsl(Class<E> iface, Metadata metadata) {
|
if (ifaceOrDsl instanceof Class) {
|
||||||
return dsl(iface, iface.getClassLoader(), Optional.empty(), metadata);
|
|
||||||
|
Class<?> iface = (Class<?>) ifaceOrDsl;
|
||||||
|
|
||||||
|
if (!iface.isInterface()) {
|
||||||
|
throw new HelenusMappingException("class is not an interface " + iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
metadataForEntity.putIfAbsent(iface, metadata);
|
||||||
|
return entity(iface, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E> E dsl(Class<E> iface, ClassLoader classLoader, Metadata metadata) {
|
throw new HelenusMappingException("unknown dsl object or mapping interface " + ifaceOrDsl);
|
||||||
return dsl(iface, classLoader, Optional.empty(), metadata);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static <E> E dsl(Class<E> iface, ClassLoader classLoader, Optional<HelenusPropertyNode> parent,
|
|
||||||
Metadata metadata) {
|
|
||||||
|
|
||||||
Object instance = null;
|
|
||||||
|
|
||||||
if (!parent.isPresent()) {
|
|
||||||
instance = dslCache.get(iface);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instance == null) {
|
|
||||||
|
|
||||||
instance = settings.getDslInstantiator().instantiate(iface, classLoader, parent, metadata);
|
|
||||||
|
|
||||||
if (!parent.isPresent()) {
|
|
||||||
|
|
||||||
Object c = dslCache.putIfAbsent(iface, instance);
|
|
||||||
if (c != null) {
|
|
||||||
instance = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (E) instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <E> E map(Class<E> iface, Map<String, Object> src) {
|
|
||||||
return map(iface, src, iface.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <E> E map(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) {
|
|
||||||
return settings.getMapperInstantiator().instantiate(iface, src, classLoader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HelenusEntity entity(Class<?> iface) {
|
|
||||||
return entity(iface, metadataForEntity.get(iface));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HelenusEntity entity(Class<?> iface, Metadata metadata) {
|
|
||||||
|
|
||||||
Object dsl = dsl(iface, metadata);
|
|
||||||
|
|
||||||
DslExportable e = (DslExportable) dsl;
|
|
||||||
|
|
||||||
return e.getHelenusMappingEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HelenusEntity resolve(Object ifaceOrDsl) {
|
|
||||||
return resolve(ifaceOrDsl, metadataForEntity.get(ifaceOrDsl));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HelenusEntity resolve(Object ifaceOrDsl, Metadata metadata) {
|
|
||||||
|
|
||||||
if (ifaceOrDsl == null) {
|
|
||||||
throw new HelenusMappingException("ifaceOrDsl is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifaceOrDsl instanceof DslExportable) {
|
|
||||||
|
|
||||||
DslExportable e = (DslExportable) ifaceOrDsl;
|
|
||||||
|
|
||||||
return e.getHelenusMappingEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifaceOrDsl instanceof Class) {
|
|
||||||
|
|
||||||
Class<?> iface = (Class<?>) ifaceOrDsl;
|
|
||||||
|
|
||||||
if (!iface.isInterface()) {
|
|
||||||
throw new HelenusMappingException("class is not an interface " + iface);
|
|
||||||
}
|
|
||||||
|
|
||||||
metadataForEntity.putIfAbsent(iface, metadata);
|
|
||||||
return entity(iface, metadata);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HelenusMappingException("unknown dsl object or mapping interface " + ifaceOrDsl);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
|
import brave.Tracer;
|
||||||
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
import com.datastax.driver.core.*;
|
||||||
|
import com.diffplug.common.base.Errors;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -23,14 +29,6 @@ import java.util.Set;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import brave.Tracer;
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
|
||||||
import com.datastax.driver.core.*;
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.diffplug.common.base.Errors;
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -44,397 +42,462 @@ import net.helenus.support.Fun.Tuple6;
|
||||||
|
|
||||||
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;
|
||||||
private final int MAX_CACHE_EXPIRE_SECONDS = 600;
|
private final int MAX_CACHE_EXPIRE_SECONDS = 600;
|
||||||
|
|
||||||
private final Session session;
|
private final Session session;
|
||||||
private final CodecRegistry registry;
|
private final CodecRegistry registry;
|
||||||
private volatile String usingKeyspace;
|
private volatile String usingKeyspace;
|
||||||
private volatile boolean showCql;
|
private volatile boolean showCql;
|
||||||
private final ConsistencyLevel defaultConsistencyLevel;
|
private final ConsistencyLevel defaultConsistencyLevel;
|
||||||
private final MetricRegistry metricRegistry;
|
private final MetricRegistry metricRegistry;
|
||||||
private final Tracer zipkinTracer;
|
private final Tracer zipkinTracer;
|
||||||
private final PrintStream printStream;
|
private final PrintStream printStream;
|
||||||
private final SessionRepository sessionRepository;
|
private final SessionRepository sessionRepository;
|
||||||
private final Executor executor;
|
private final Executor executor;
|
||||||
private final boolean dropSchemaOnClose;
|
private final boolean dropSchemaOnClose;
|
||||||
|
|
||||||
private final RowColumnValueProvider valueProvider;
|
private final RowColumnValueProvider valueProvider;
|
||||||
private final StatementColumnValuePreparer valuePreparer;
|
private final StatementColumnValuePreparer valuePreparer;
|
||||||
private final Metadata metadata;
|
private final Metadata metadata;
|
||||||
private final Cache<String, Object> sessionCache;
|
private final Cache<String, Object> sessionCache;
|
||||||
private UnitOfWork currentUnitOfWork;
|
private UnitOfWork currentUnitOfWork;
|
||||||
|
|
||||||
HelenusSession(Session session, String usingKeyspace, CodecRegistry registry, boolean showCql,
|
HelenusSession(
|
||||||
PrintStream printStream, SessionRepositoryBuilder sessionRepositoryBuilder, Executor executor,
|
Session session,
|
||||||
boolean dropSchemaOnClose, ConsistencyLevel consistencyLevel, MetricRegistry metricRegistry,
|
String usingKeyspace,
|
||||||
Tracer tracer) {
|
CodecRegistry registry,
|
||||||
this.session = session;
|
boolean showCql,
|
||||||
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
|
PrintStream printStream,
|
||||||
this.usingKeyspace = Objects.requireNonNull(usingKeyspace,
|
SessionRepositoryBuilder sessionRepositoryBuilder,
|
||||||
"keyspace needs to be selected before creating session");
|
Executor executor,
|
||||||
this.showCql = showCql;
|
boolean dropSchemaOnClose,
|
||||||
this.printStream = printStream;
|
ConsistencyLevel consistencyLevel,
|
||||||
this.sessionRepository = sessionRepositoryBuilder.build();
|
MetricRegistry metricRegistry,
|
||||||
this.executor = executor;
|
Tracer tracer) {
|
||||||
this.dropSchemaOnClose = dropSchemaOnClose;
|
this.session = session;
|
||||||
this.defaultConsistencyLevel = consistencyLevel;
|
this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry;
|
||||||
this.metricRegistry = metricRegistry;
|
this.usingKeyspace =
|
||||||
this.zipkinTracer = tracer;
|
Objects.requireNonNull(
|
||||||
|
usingKeyspace, "keyspace needs to be selected before creating session");
|
||||||
|
this.showCql = showCql;
|
||||||
|
this.printStream = printStream;
|
||||||
|
this.sessionRepository = sessionRepositoryBuilder.build();
|
||||||
|
this.executor = executor;
|
||||||
|
this.dropSchemaOnClose = dropSchemaOnClose;
|
||||||
|
this.defaultConsistencyLevel = consistencyLevel;
|
||||||
|
this.metricRegistry = metricRegistry;
|
||||||
|
this.zipkinTracer = tracer;
|
||||||
|
|
||||||
this.valueProvider = new RowColumnValueProvider(this.sessionRepository);
|
this.valueProvider = new RowColumnValueProvider(this.sessionRepository);
|
||||||
this.valuePreparer = new StatementColumnValuePreparer(this.sessionRepository);
|
this.valuePreparer = new StatementColumnValuePreparer(this.sessionRepository);
|
||||||
this.metadata = session.getCluster().getMetadata();
|
this.metadata = session.getCluster().getMetadata();
|
||||||
this.sessionCache = CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE)
|
this.sessionCache =
|
||||||
.expireAfterAccess(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS).recordStats().build();
|
CacheBuilder.newBuilder()
|
||||||
this.currentUnitOfWork = null;
|
.maximumSize(MAX_CACHE_SIZE)
|
||||||
}
|
.expireAfterAccess(MAX_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS)
|
||||||
|
.recordStats()
|
||||||
|
.build();
|
||||||
|
this.currentUnitOfWork = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Session currentSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Session currentSession() {
|
public String usingKeyspace() {
|
||||||
return session;
|
return usingKeyspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public HelenusSession useKeyspace(String keyspace) {
|
||||||
public String usingKeyspace() {
|
session.execute(SchemaUtil.use(keyspace, false));
|
||||||
return usingKeyspace;
|
this.usingKeyspace = keyspace;
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public HelenusSession useKeyspace(String keyspace) {
|
@Override
|
||||||
session.execute(SchemaUtil.use(keyspace, false));
|
public boolean isShowCql() {
|
||||||
this.usingKeyspace = keyspace;
|
return showCql;
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isShowCql() {
|
public PrintStream getPrintStream() {
|
||||||
return showCql;
|
return printStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public HelenusSession showCql() {
|
||||||
public PrintStream getPrintStream() {
|
this.showCql = true;
|
||||||
return printStream;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusSession showCql() {
|
public HelenusSession showCql(boolean showCql) {
|
||||||
this.showCql = true;
|
this.showCql = showCql;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusSession showCql(boolean showCql) {
|
@Override
|
||||||
this.showCql = showCql;
|
public Executor getExecutor() {
|
||||||
return this;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Executor getExecutor() {
|
public SessionRepository getSessionRepository() {
|
||||||
return executor;
|
return sessionRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionRepository getSessionRepository() {
|
public ColumnValueProvider getValueProvider() {
|
||||||
return sessionRepository;
|
return valueProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ColumnValueProvider getValueProvider() {
|
public ColumnValuePreparer getValuePreparer() {
|
||||||
return valueProvider;
|
return valuePreparer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ColumnValuePreparer getValuePreparer() {
|
public Tracer getZipkinTracer() {
|
||||||
return valuePreparer;
|
return zipkinTracer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Tracer getZipkinTracer() { return zipkinTracer; }
|
public MetricRegistry getMetricRegistry() {
|
||||||
|
return metricRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public ConsistencyLevel getDefaultConsistencyLevel() {
|
||||||
public MetricRegistry getMetricRegistry() { return metricRegistry; }
|
return defaultConsistencyLevel;
|
||||||
|
}
|
||||||
|
|
||||||
public ConsistencyLevel getDefaultConsistencyLevel() {
|
public Metadata getMetadata() {
|
||||||
return defaultConsistencyLevel;
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized UnitOfWork begin() {
|
||||||
|
if (currentUnitOfWork == null) {
|
||||||
|
currentUnitOfWork = new UnitOfWork(this);
|
||||||
|
return currentUnitOfWork;
|
||||||
|
} else {
|
||||||
|
return currentUnitOfWork.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Function<Void, Void> commit() throws ConflictingUnitOfWorkException {
|
||||||
|
Function<Void, Void> f = Function.<Void>identity();
|
||||||
|
if (currentUnitOfWork != null) {
|
||||||
|
f = Errors.rethrow().<Function<Void, Void>>wrap(currentUnitOfWork::commit).get();
|
||||||
|
currentUnitOfWork = null;
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void abort() {
|
||||||
|
if (currentUnitOfWork != null) {
|
||||||
|
currentUnitOfWork.abort();
|
||||||
|
currentUnitOfWork = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cache(String key, Object value) {
|
||||||
|
sessionCache.put(key, value); // ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> SelectOperation<E> select(Class<E> entityClass) {
|
||||||
|
|
||||||
|
Objects.requireNonNull(entityClass, "entityClass is empty");
|
||||||
|
ColumnValueProvider valueProvider = getValueProvider();
|
||||||
|
HelenusEntity entity = Helenus.entity(entityClass);
|
||||||
|
|
||||||
|
return new SelectOperation<E>(
|
||||||
|
this,
|
||||||
|
entity,
|
||||||
|
(r) -> {
|
||||||
|
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
|
||||||
|
return (E) Helenus.map(entityClass, map);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectOperation<Fun.ArrayTuple> select() {
|
||||||
|
return new SelectOperation<Fun.ArrayTuple>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectOperation<Row> selectAll(Class<?> entityClass) {
|
||||||
|
Objects.requireNonNull(entityClass, "entityClass is empty");
|
||||||
|
return new SelectOperation<Row>(this, Helenus.entity(entityClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> SelectOperation<E> selectAll(Class<E> entityClass, Function<Row, E> rowMapper) {
|
||||||
|
Objects.requireNonNull(entityClass, "entityClass is empty");
|
||||||
|
Objects.requireNonNull(rowMapper, "rowMapper is empty");
|
||||||
|
return new SelectOperation<E>(this, Helenus.entity(entityClass), rowMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V1> SelectOperation<Fun.Tuple1<V1>> select(Getter<V1> getter1) {
|
||||||
|
Objects.requireNonNull(getter1, "field 1 is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
||||||
|
return new SelectOperation<Tuple1<V1>>(
|
||||||
|
this, new Mappers.Mapper1<V1>(getValueProvider(), p1), p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V1, V2> SelectOperation<Tuple2<V1, V2>> select(Getter<V1> getter1, Getter<V2> getter2) {
|
||||||
|
Objects.requireNonNull(getter1, "field 1 is empty");
|
||||||
|
Objects.requireNonNull(getter2, "field 2 is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
||||||
|
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
||||||
|
return new SelectOperation<Fun.Tuple2<V1, V2>>(
|
||||||
|
this, new Mappers.Mapper2<V1, V2>(getValueProvider(), p1, p2), p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V1, V2, V3> SelectOperation<Fun.Tuple3<V1, V2, V3>> select(
|
||||||
|
Getter<V1> getter1, Getter<V2> getter2, Getter<V3> getter3) {
|
||||||
|
Objects.requireNonNull(getter1, "field 1 is empty");
|
||||||
|
Objects.requireNonNull(getter2, "field 2 is empty");
|
||||||
|
Objects.requireNonNull(getter3, "field 3 is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
||||||
|
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
||||||
|
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
||||||
|
return new SelectOperation<Fun.Tuple3<V1, V2, V3>>(
|
||||||
|
this, new Mappers.Mapper3<V1, V2, V3>(getValueProvider(), p1, p2, p3), p1, p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V1, V2, V3, V4> SelectOperation<Fun.Tuple4<V1, V2, V3, V4>> select(
|
||||||
|
Getter<V1> getter1, Getter<V2> getter2, Getter<V3> getter3, Getter<V4> getter4) {
|
||||||
|
Objects.requireNonNull(getter1, "field 1 is empty");
|
||||||
|
Objects.requireNonNull(getter2, "field 2 is empty");
|
||||||
|
Objects.requireNonNull(getter3, "field 3 is empty");
|
||||||
|
Objects.requireNonNull(getter4, "field 4 is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
||||||
|
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
||||||
|
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
||||||
|
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
||||||
|
return new SelectOperation<Fun.Tuple4<V1, V2, V3, V4>>(
|
||||||
|
this,
|
||||||
|
new Mappers.Mapper4<V1, V2, V3, V4>(getValueProvider(), p1, p2, p3, p4),
|
||||||
|
p1,
|
||||||
|
p2,
|
||||||
|
p3,
|
||||||
|
p4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V1, V2, V3, V4, V5> SelectOperation<Fun.Tuple5<V1, V2, V3, V4, V5>> select(
|
||||||
|
Getter<V1> getter1,
|
||||||
|
Getter<V2> getter2,
|
||||||
|
Getter<V3> getter3,
|
||||||
|
Getter<V4> getter4,
|
||||||
|
Getter<V5> getter5) {
|
||||||
|
Objects.requireNonNull(getter1, "field 1 is empty");
|
||||||
|
Objects.requireNonNull(getter2, "field 2 is empty");
|
||||||
|
Objects.requireNonNull(getter3, "field 3 is empty");
|
||||||
|
Objects.requireNonNull(getter4, "field 4 is empty");
|
||||||
|
Objects.requireNonNull(getter5, "field 5 is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
||||||
|
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
||||||
|
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
||||||
|
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
||||||
|
HelenusPropertyNode p5 = MappingUtil.resolveMappingProperty(getter5);
|
||||||
|
return new SelectOperation<Fun.Tuple5<V1, V2, V3, V4, V5>>(
|
||||||
|
this,
|
||||||
|
new Mappers.Mapper5<V1, V2, V3, V4, V5>(getValueProvider(), p1, p2, p3, p4, p5),
|
||||||
|
p1,
|
||||||
|
p2,
|
||||||
|
p3,
|
||||||
|
p4,
|
||||||
|
p5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V1, V2, V3, V4, V5, V6> SelectOperation<Fun.Tuple6<V1, V2, V3, V4, V5, V6>> select(
|
||||||
|
Getter<V1> getter1,
|
||||||
|
Getter<V2> getter2,
|
||||||
|
Getter<V3> getter3,
|
||||||
|
Getter<V4> getter4,
|
||||||
|
Getter<V5> getter5,
|
||||||
|
Getter<V6> getter6) {
|
||||||
|
Objects.requireNonNull(getter1, "field 1 is empty");
|
||||||
|
Objects.requireNonNull(getter2, "field 2 is empty");
|
||||||
|
Objects.requireNonNull(getter3, "field 3 is empty");
|
||||||
|
Objects.requireNonNull(getter4, "field 4 is empty");
|
||||||
|
Objects.requireNonNull(getter5, "field 5 is empty");
|
||||||
|
Objects.requireNonNull(getter6, "field 6 is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
||||||
|
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
||||||
|
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
||||||
|
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
||||||
|
HelenusPropertyNode p5 = MappingUtil.resolveMappingProperty(getter5);
|
||||||
|
HelenusPropertyNode p6 = MappingUtil.resolveMappingProperty(getter6);
|
||||||
|
return new SelectOperation<Tuple6<V1, V2, V3, V4, V5, V6>>(
|
||||||
|
this,
|
||||||
|
new Mappers.Mapper6<V1, V2, V3, V4, V5, V6>(getValueProvider(), p1, p2, p3, p4, p5, p6),
|
||||||
|
p1,
|
||||||
|
p2,
|
||||||
|
p3,
|
||||||
|
p4,
|
||||||
|
p5,
|
||||||
|
p6);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V1, V2, V3, V4, V5, V6, V7>
|
||||||
|
SelectOperation<Fun.Tuple7<V1, V2, V3, V4, V5, V6, V7>> select(
|
||||||
|
Getter<V1> getter1,
|
||||||
|
Getter<V2> getter2,
|
||||||
|
Getter<V3> getter3,
|
||||||
|
Getter<V4> getter4,
|
||||||
|
Getter<V5> getter5,
|
||||||
|
Getter<V6> getter6,
|
||||||
|
Getter<V7> getter7) {
|
||||||
|
Objects.requireNonNull(getter1, "field 1 is empty");
|
||||||
|
Objects.requireNonNull(getter2, "field 2 is empty");
|
||||||
|
Objects.requireNonNull(getter3, "field 3 is empty");
|
||||||
|
Objects.requireNonNull(getter4, "field 4 is empty");
|
||||||
|
Objects.requireNonNull(getter5, "field 5 is empty");
|
||||||
|
Objects.requireNonNull(getter6, "field 6 is empty");
|
||||||
|
Objects.requireNonNull(getter7, "field 7 is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
||||||
|
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
||||||
|
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
||||||
|
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
||||||
|
HelenusPropertyNode p5 = MappingUtil.resolveMappingProperty(getter5);
|
||||||
|
HelenusPropertyNode p6 = MappingUtil.resolveMappingProperty(getter6);
|
||||||
|
HelenusPropertyNode p7 = MappingUtil.resolveMappingProperty(getter7);
|
||||||
|
return new SelectOperation<Fun.Tuple7<V1, V2, V3, V4, V5, V6, V7>>(
|
||||||
|
this,
|
||||||
|
new Mappers.Mapper7<V1, V2, V3, V4, V5, V6, V7>(
|
||||||
|
getValueProvider(), p1, p2, p3, p4, p5, p6, p7),
|
||||||
|
p1,
|
||||||
|
p2,
|
||||||
|
p3,
|
||||||
|
p4,
|
||||||
|
p5,
|
||||||
|
p6,
|
||||||
|
p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CountOperation count() {
|
||||||
|
return new CountOperation(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CountOperation count(Object dsl) {
|
||||||
|
Objects.requireNonNull(dsl, "dsl is empty");
|
||||||
|
return new CountOperation(this, Helenus.resolve(dsl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V> UpdateOperation update() {
|
||||||
|
return new UpdateOperation(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V> UpdateOperation update(Getter<V> getter, V v) {
|
||||||
|
Objects.requireNonNull(getter, "field is empty");
|
||||||
|
Objects.requireNonNull(v, "value is empty");
|
||||||
|
|
||||||
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
|
||||||
|
return new UpdateOperation(this, p, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> insert() {
|
||||||
|
return new InsertOperation<T>(this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> insert(Object pojo) {
|
||||||
|
return this.<T>insert(pojo, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> insert(Drafted draft) {
|
||||||
|
return this.<T>insert(draft.build(), draft.mutated());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> insert(Object pojo, Set<String> mutations) {
|
||||||
|
Objects.requireNonNull(pojo, "pojo is empty");
|
||||||
|
|
||||||
|
Class<?> iface = MappingUtil.getMappingInterface(pojo);
|
||||||
|
HelenusEntity entity = Helenus.entity(iface);
|
||||||
|
|
||||||
|
return new InsertOperation<T>(this, entity, pojo, mutations, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> upsert() {
|
||||||
|
return new InsertOperation<T>(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> upsert(Drafted draft) {
|
||||||
|
return this.<T>upsert(draft.build(), draft.mutated());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> upsert(Object pojo) {
|
||||||
|
return this.<T>upsert(pojo, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> InsertOperation<T> upsert(Object pojo, Set<String> mutations) {
|
||||||
|
Objects.requireNonNull(pojo, "pojo is empty");
|
||||||
|
|
||||||
|
Class<?> iface = MappingUtil.getMappingInterface(pojo);
|
||||||
|
HelenusEntity entity = Helenus.entity(iface);
|
||||||
|
|
||||||
|
return new InsertOperation<T>(this, entity, pojo, mutations, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeleteOperation delete() {
|
||||||
|
return new DeleteOperation(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeleteOperation delete(Object dsl) {
|
||||||
|
Objects.requireNonNull(dsl, "dsl is empty");
|
||||||
|
return new DeleteOperation(this, Helenus.resolve(dsl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> E dsl(Class<E> iface) {
|
||||||
|
return Helenus.dsl(iface, getMetadata());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
if (session.isClosed()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Metadata getMetadata() { return metadata; }
|
if (dropSchemaOnClose) {
|
||||||
|
dropSchema();
|
||||||
public synchronized UnitOfWork begin() {
|
|
||||||
if (currentUnitOfWork == null) {
|
|
||||||
currentUnitOfWork = new UnitOfWork(this);
|
|
||||||
return currentUnitOfWork;
|
|
||||||
} else {
|
|
||||||
return currentUnitOfWork.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Function<Void, Void> commit() throws ConflictingUnitOfWorkException {
|
|
||||||
Function<Void, Void> f = Function.<Void>identity();
|
|
||||||
if (currentUnitOfWork != null) {
|
|
||||||
f = Errors.rethrow().<Function<Void, Void>>wrap(currentUnitOfWork::commit).get();
|
|
||||||
currentUnitOfWork = null;
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void abort() {
|
|
||||||
if (currentUnitOfWork != null) {
|
|
||||||
currentUnitOfWork.abort();
|
|
||||||
currentUnitOfWork = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cache(String key, Object value) {
|
|
||||||
sessionCache.put(key, value); // ttl
|
|
||||||
}
|
|
||||||
|
|
||||||
public <E> SelectOperation<E> select(Class<E> entityClass) {
|
|
||||||
|
|
||||||
Objects.requireNonNull(entityClass, "entityClass is empty");
|
|
||||||
ColumnValueProvider valueProvider = getValueProvider();
|
|
||||||
HelenusEntity entity = Helenus.entity(entityClass);
|
|
||||||
|
|
||||||
return new SelectOperation<E>(this, entity, (r) -> {
|
|
||||||
|
|
||||||
Map<String, Object> map = new ValueProviderMap(r, valueProvider, entity);
|
|
||||||
return (E) Helenus.map(entityClass, map);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation<Fun.ArrayTuple> select() {
|
|
||||||
return new SelectOperation<Fun.ArrayTuple>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation<Row> selectAll(Class<?> entityClass) {
|
|
||||||
Objects.requireNonNull(entityClass, "entityClass is empty");
|
|
||||||
return new SelectOperation<Row>(this, Helenus.entity(entityClass));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <E> SelectOperation<E> selectAll(Class<E> entityClass, Function<Row, E> rowMapper) {
|
|
||||||
Objects.requireNonNull(entityClass, "entityClass is empty");
|
|
||||||
Objects.requireNonNull(rowMapper, "rowMapper is empty");
|
|
||||||
return new SelectOperation<E>(this, Helenus.entity(entityClass), rowMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V1> SelectOperation<Fun.Tuple1<V1>> select(Getter<V1> getter1) {
|
|
||||||
Objects.requireNonNull(getter1, "field 1 is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
|
||||||
return new SelectOperation<Tuple1<V1>>(this, new Mappers.Mapper1<V1>(getValueProvider(), p1), p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V1, V2> SelectOperation<Tuple2<V1, V2>> select(Getter<V1> getter1, Getter<V2> getter2) {
|
|
||||||
Objects.requireNonNull(getter1, "field 1 is empty");
|
|
||||||
Objects.requireNonNull(getter2, "field 2 is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
|
||||||
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
|
||||||
return new SelectOperation<Fun.Tuple2<V1, V2>>(this, new Mappers.Mapper2<V1, V2>(getValueProvider(), p1, p2),
|
|
||||||
p1, p2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V1, V2, V3> SelectOperation<Fun.Tuple3<V1, V2, V3>> select(Getter<V1> getter1, Getter<V2> getter2,
|
|
||||||
Getter<V3> getter3) {
|
|
||||||
Objects.requireNonNull(getter1, "field 1 is empty");
|
|
||||||
Objects.requireNonNull(getter2, "field 2 is empty");
|
|
||||||
Objects.requireNonNull(getter3, "field 3 is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
|
||||||
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
|
||||||
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
|
||||||
return new SelectOperation<Fun.Tuple3<V1, V2, V3>>(this,
|
|
||||||
new Mappers.Mapper3<V1, V2, V3>(getValueProvider(), p1, p2, p3), p1, p2, p3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V1, V2, V3, V4> SelectOperation<Fun.Tuple4<V1, V2, V3, V4>> select(Getter<V1> getter1, Getter<V2> getter2,
|
|
||||||
Getter<V3> getter3, Getter<V4> getter4) {
|
|
||||||
Objects.requireNonNull(getter1, "field 1 is empty");
|
|
||||||
Objects.requireNonNull(getter2, "field 2 is empty");
|
|
||||||
Objects.requireNonNull(getter3, "field 3 is empty");
|
|
||||||
Objects.requireNonNull(getter4, "field 4 is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
|
||||||
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
|
||||||
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
|
||||||
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
|
||||||
return new SelectOperation<Fun.Tuple4<V1, V2, V3, V4>>(this,
|
|
||||||
new Mappers.Mapper4<V1, V2, V3, V4>(getValueProvider(), p1, p2, p3, p4), p1, p2, p3, p4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V1, V2, V3, V4, V5> SelectOperation<Fun.Tuple5<V1, V2, V3, V4, V5>> select(Getter<V1> getter1,
|
|
||||||
Getter<V2> getter2, Getter<V3> getter3, Getter<V4> getter4, Getter<V5> getter5) {
|
|
||||||
Objects.requireNonNull(getter1, "field 1 is empty");
|
|
||||||
Objects.requireNonNull(getter2, "field 2 is empty");
|
|
||||||
Objects.requireNonNull(getter3, "field 3 is empty");
|
|
||||||
Objects.requireNonNull(getter4, "field 4 is empty");
|
|
||||||
Objects.requireNonNull(getter5, "field 5 is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
|
||||||
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
|
||||||
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
|
||||||
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
|
||||||
HelenusPropertyNode p5 = MappingUtil.resolveMappingProperty(getter5);
|
|
||||||
return new SelectOperation<Fun.Tuple5<V1, V2, V3, V4, V5>>(this,
|
|
||||||
new Mappers.Mapper5<V1, V2, V3, V4, V5>(getValueProvider(), p1, p2, p3, p4, p5), p1, p2, p3, p4, p5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V1, V2, V3, V4, V5, V6> SelectOperation<Fun.Tuple6<V1, V2, V3, V4, V5, V6>> select(Getter<V1> getter1,
|
|
||||||
Getter<V2> getter2, Getter<V3> getter3, Getter<V4> getter4, Getter<V5> getter5, Getter<V6> getter6) {
|
|
||||||
Objects.requireNonNull(getter1, "field 1 is empty");
|
|
||||||
Objects.requireNonNull(getter2, "field 2 is empty");
|
|
||||||
Objects.requireNonNull(getter3, "field 3 is empty");
|
|
||||||
Objects.requireNonNull(getter4, "field 4 is empty");
|
|
||||||
Objects.requireNonNull(getter5, "field 5 is empty");
|
|
||||||
Objects.requireNonNull(getter6, "field 6 is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
|
||||||
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
|
||||||
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
|
||||||
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
|
||||||
HelenusPropertyNode p5 = MappingUtil.resolveMappingProperty(getter5);
|
|
||||||
HelenusPropertyNode p6 = MappingUtil.resolveMappingProperty(getter6);
|
|
||||||
return new SelectOperation<Tuple6<V1, V2, V3, V4, V5, V6>>(this,
|
|
||||||
new Mappers.Mapper6<V1, V2, V3, V4, V5, V6>(getValueProvider(), p1, p2, p3, p4, p5, p6), p1, p2, p3, p4,
|
|
||||||
p5, p6);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V1, V2, V3, V4, V5, V6, V7> SelectOperation<Fun.Tuple7<V1, V2, V3, V4, V5, V6, V7>> select(
|
|
||||||
Getter<V1> getter1, Getter<V2> getter2, Getter<V3> getter3, Getter<V4> getter4, Getter<V5> getter5,
|
|
||||||
Getter<V6> getter6, Getter<V7> getter7) {
|
|
||||||
Objects.requireNonNull(getter1, "field 1 is empty");
|
|
||||||
Objects.requireNonNull(getter2, "field 2 is empty");
|
|
||||||
Objects.requireNonNull(getter3, "field 3 is empty");
|
|
||||||
Objects.requireNonNull(getter4, "field 4 is empty");
|
|
||||||
Objects.requireNonNull(getter5, "field 5 is empty");
|
|
||||||
Objects.requireNonNull(getter6, "field 6 is empty");
|
|
||||||
Objects.requireNonNull(getter7, "field 7 is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p1 = MappingUtil.resolveMappingProperty(getter1);
|
|
||||||
HelenusPropertyNode p2 = MappingUtil.resolveMappingProperty(getter2);
|
|
||||||
HelenusPropertyNode p3 = MappingUtil.resolveMappingProperty(getter3);
|
|
||||||
HelenusPropertyNode p4 = MappingUtil.resolveMappingProperty(getter4);
|
|
||||||
HelenusPropertyNode p5 = MappingUtil.resolveMappingProperty(getter5);
|
|
||||||
HelenusPropertyNode p6 = MappingUtil.resolveMappingProperty(getter6);
|
|
||||||
HelenusPropertyNode p7 = MappingUtil.resolveMappingProperty(getter7);
|
|
||||||
return new SelectOperation<Fun.Tuple7<V1, V2, V3, V4, V5, V6, V7>>(this,
|
|
||||||
new Mappers.Mapper7<V1, V2, V3, V4, V5, V6, V7>(getValueProvider(), p1, p2, p3, p4, p5, p6, p7), p1, p2,
|
|
||||||
p3, p4, p5, p6, p7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CountOperation count() {
|
|
||||||
return new CountOperation(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CountOperation count(Object dsl) {
|
|
||||||
Objects.requireNonNull(dsl, "dsl is empty");
|
|
||||||
return new CountOperation(this, Helenus.resolve(dsl));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation update() {
|
|
||||||
return new UpdateOperation(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation update(Getter<V> getter, V v) {
|
|
||||||
Objects.requireNonNull(getter, "field is empty");
|
|
||||||
Objects.requireNonNull(v, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
|
||||||
|
|
||||||
return new UpdateOperation(this, p, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> insert() { return new InsertOperation<T>(this, true); }
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> insert(Object pojo) { return this.<T>insert(pojo, null); }
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> insert(Drafted draft) { return this.<T>insert(draft.build(), draft.mutated()); }
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> insert(Object pojo, Set<String> mutations) {
|
|
||||||
Objects.requireNonNull(pojo, "pojo is empty");
|
|
||||||
|
|
||||||
Class<?> iface = MappingUtil.getMappingInterface(pojo);
|
|
||||||
HelenusEntity entity = Helenus.entity(iface);
|
|
||||||
|
|
||||||
return new InsertOperation<T>(this, entity, pojo, mutations, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> upsert() {
|
|
||||||
return new InsertOperation<T>(this, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> upsert(Drafted draft) { return this.<T>upsert(draft.build(), draft.mutated()); }
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> upsert(Object pojo) { return this.<T>upsert(pojo, null); }
|
|
||||||
|
|
||||||
public <T> InsertOperation<T> upsert(Object pojo, Set<String> mutations) {
|
|
||||||
Objects.requireNonNull(pojo, "pojo is empty");
|
|
||||||
|
|
||||||
Class<?> iface = MappingUtil.getMappingInterface(pojo);
|
|
||||||
HelenusEntity entity = Helenus.entity(iface);
|
|
||||||
|
|
||||||
return new InsertOperation<T>(this, entity, pojo, mutations, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeleteOperation delete() {
|
|
||||||
return new DeleteOperation(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeleteOperation delete(Object dsl) {
|
|
||||||
Objects.requireNonNull(dsl, "dsl is empty");
|
|
||||||
return new DeleteOperation(this, Helenus.resolve(dsl));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Session getSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <E> E dsl(Class<E> iface) {
|
|
||||||
return Helenus.dsl(iface, getMetadata());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
if (session.isClosed()) {
|
public CloseFuture closeAsync() {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dropSchemaOnClose) {
|
if (!session.isClosed() && dropSchemaOnClose) {
|
||||||
dropSchema();
|
dropSchema();
|
||||||
}
|
}
|
||||||
|
|
||||||
session.close();
|
return session.closeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CloseFuture closeAsync() {
|
private void dropSchema() {
|
||||||
|
|
||||||
if (!session.isClosed() && dropSchemaOnClose) {
|
sessionRepository.entities().forEach(e -> dropEntity(e));
|
||||||
dropSchema();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return session.closeAsync();
|
private void dropEntity(HelenusEntity entity) {
|
||||||
}
|
|
||||||
|
|
||||||
private void dropSchema() {
|
switch (entity.getType()) {
|
||||||
|
case TABLE:
|
||||||
sessionRepository.entities().forEach(e -> dropEntity(e));
|
execute(SchemaUtil.dropTable(entity), true);
|
||||||
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
private void dropEntity(HelenusEntity entity) {
|
|
||||||
|
|
||||||
switch (entity.getType()) {
|
|
||||||
|
|
||||||
case TABLE :
|
|
||||||
execute(SchemaUtil.dropTable(entity), true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UDT :
|
|
||||||
execute(SchemaUtil.dropUserType(entity), true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
case UDT:
|
||||||
|
execute(SchemaUtil.dropUserType(entity), true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,36 +16,32 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
|
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public enum HelenusValidator implements PropertyValueValidator {
|
public enum HelenusValidator implements PropertyValueValidator {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
public void validate(HelenusProperty prop, Object value) {
|
||||||
|
|
||||||
public void validate(HelenusProperty prop, Object value) {
|
for (ConstraintValidator<? extends Annotation, ?> validator : prop.getValidators()) {
|
||||||
|
|
||||||
for (ConstraintValidator<? extends Annotation, ?> validator : prop.getValidators()) {
|
ConstraintValidator typeless = (ConstraintValidator) validator;
|
||||||
|
|
||||||
ConstraintValidator typeless = (ConstraintValidator) validator;
|
boolean valid = false;
|
||||||
|
|
||||||
boolean valid = false;
|
try {
|
||||||
|
valid = typeless.isValid(value, null);
|
||||||
try {
|
} catch (ClassCastException e) {
|
||||||
valid = typeless.isValid(value, null);
|
throw new HelenusMappingException(
|
||||||
} catch (ClassCastException e) {
|
"validator was used for wrong type '" + value + "' in " + prop, e);
|
||||||
throw new HelenusMappingException("validator was used for wrong type '" + value + "' in " + prop, e);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
throw new HelenusException("wrong value '" + value + "' for " + prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
throw new HelenusException("wrong value '" + value + "' for " + prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,5 @@ import java.util.Map;
|
||||||
|
|
||||||
public interface MapperInstantiator {
|
public interface MapperInstantiator {
|
||||||
|
|
||||||
<E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader);
|
<E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.Row;
|
import com.datastax.driver.core.Row;
|
||||||
|
import java.util.function.Function;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.mapping.value.ColumnValueProvider;
|
import net.helenus.mapping.value.ColumnValueProvider;
|
||||||
|
@ -26,162 +24,203 @@ import net.helenus.support.Fun;
|
||||||
|
|
||||||
public final class Mappers {
|
public final class Mappers {
|
||||||
|
|
||||||
private Mappers() {
|
private Mappers() {}
|
||||||
}
|
|
||||||
|
|
||||||
public final static class Mapper1<A> implements Function<Row, Fun.Tuple1<A>> {
|
public static final class Mapper1<A> implements Function<Row, Fun.Tuple1<A>> {
|
||||||
|
|
||||||
private final ColumnValueProvider provider;
|
private final ColumnValueProvider provider;
|
||||||
private final HelenusProperty p1;
|
private final HelenusProperty p1;
|
||||||
|
|
||||||
public Mapper1(ColumnValueProvider provider, HelenusPropertyNode p1) {
|
public Mapper1(ColumnValueProvider provider, HelenusPropertyNode p1) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.p1 = p1.getProperty();
|
this.p1 = p1.getProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Fun.Tuple1<A> apply(Row row) {
|
public Fun.Tuple1<A> apply(Row row) {
|
||||||
return new Fun.Tuple1<A>(provider.getColumnValue(row, 0, p1));
|
return new Fun.Tuple1<A>(provider.getColumnValue(row, 0, p1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static class Mapper2<A, B> implements Function<Row, Fun.Tuple2<A, B>> {
|
public static final class Mapper2<A, B> implements Function<Row, Fun.Tuple2<A, B>> {
|
||||||
|
|
||||||
private final ColumnValueProvider provider;
|
private final ColumnValueProvider provider;
|
||||||
private final HelenusProperty p1;
|
private final HelenusProperty p1;
|
||||||
private final HelenusProperty p2;
|
private final HelenusProperty p2;
|
||||||
|
|
||||||
public Mapper2(ColumnValueProvider provider, HelenusPropertyNode p1, HelenusPropertyNode p2) {
|
public Mapper2(ColumnValueProvider provider, HelenusPropertyNode p1, HelenusPropertyNode p2) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.p1 = p1.getProperty();
|
this.p1 = p1.getProperty();
|
||||||
this.p2 = p2.getProperty();
|
this.p2 = p2.getProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Fun.Tuple2<A, B> apply(Row row) {
|
public Fun.Tuple2<A, B> apply(Row row) {
|
||||||
return new Fun.Tuple2<A, B>(provider.getColumnValue(row, 0, p1), provider.getColumnValue(row, 1, p2));
|
return new Fun.Tuple2<A, B>(
|
||||||
}
|
provider.getColumnValue(row, 0, p1), provider.getColumnValue(row, 1, p2));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final static class Mapper3<A, B, C> implements Function<Row, Fun.Tuple3<A, B, C>> {
|
public static final class Mapper3<A, B, C> implements Function<Row, Fun.Tuple3<A, B, C>> {
|
||||||
|
|
||||||
private final ColumnValueProvider provider;
|
private final ColumnValueProvider provider;
|
||||||
private final HelenusProperty p1;
|
private final HelenusProperty p1;
|
||||||
private final HelenusProperty p2;
|
private final HelenusProperty p2;
|
||||||
private final HelenusProperty p3;
|
private final HelenusProperty p3;
|
||||||
|
|
||||||
public Mapper3(ColumnValueProvider provider, HelenusPropertyNode p1, HelenusPropertyNode p2,
|
public Mapper3(
|
||||||
HelenusPropertyNode p3) {
|
ColumnValueProvider provider,
|
||||||
this.provider = provider;
|
HelenusPropertyNode p1,
|
||||||
this.p1 = p1.getProperty();
|
HelenusPropertyNode p2,
|
||||||
this.p2 = p2.getProperty();
|
HelenusPropertyNode p3) {
|
||||||
this.p3 = p3.getProperty();
|
this.provider = provider;
|
||||||
}
|
this.p1 = p1.getProperty();
|
||||||
|
this.p2 = p2.getProperty();
|
||||||
|
this.p3 = p3.getProperty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Fun.Tuple3<A, B, C> apply(Row row) {
|
public Fun.Tuple3<A, B, C> apply(Row row) {
|
||||||
return new Fun.Tuple3<A, B, C>(provider.getColumnValue(row, 0, p1), provider.getColumnValue(row, 1, p2),
|
return new Fun.Tuple3<A, B, C>(
|
||||||
provider.getColumnValue(row, 2, p3));
|
provider.getColumnValue(row, 0, p1),
|
||||||
}
|
provider.getColumnValue(row, 1, p2),
|
||||||
}
|
provider.getColumnValue(row, 2, p3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final static class Mapper4<A, B, C, D> implements Function<Row, Fun.Tuple4<A, B, C, D>> {
|
public static final class Mapper4<A, B, C, D> implements Function<Row, Fun.Tuple4<A, B, C, D>> {
|
||||||
|
|
||||||
private final ColumnValueProvider provider;
|
private final ColumnValueProvider provider;
|
||||||
private final HelenusProperty p1;
|
private final HelenusProperty p1;
|
||||||
private final HelenusProperty p2;
|
private final HelenusProperty p2;
|
||||||
private final HelenusProperty p3;
|
private final HelenusProperty p3;
|
||||||
private final HelenusProperty p4;
|
private final HelenusProperty p4;
|
||||||
|
|
||||||
public Mapper4(ColumnValueProvider provider, HelenusPropertyNode p1, HelenusPropertyNode p2,
|
public Mapper4(
|
||||||
HelenusPropertyNode p3, HelenusPropertyNode p4) {
|
ColumnValueProvider provider,
|
||||||
this.provider = provider;
|
HelenusPropertyNode p1,
|
||||||
this.p1 = p1.getProperty();
|
HelenusPropertyNode p2,
|
||||||
this.p2 = p2.getProperty();
|
HelenusPropertyNode p3,
|
||||||
this.p3 = p3.getProperty();
|
HelenusPropertyNode p4) {
|
||||||
this.p4 = p4.getProperty();
|
this.provider = provider;
|
||||||
}
|
this.p1 = p1.getProperty();
|
||||||
|
this.p2 = p2.getProperty();
|
||||||
|
this.p3 = p3.getProperty();
|
||||||
|
this.p4 = p4.getProperty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Fun.Tuple4<A, B, C, D> apply(Row row) {
|
public Fun.Tuple4<A, B, C, D> apply(Row row) {
|
||||||
return new Fun.Tuple4<A, B, C, D>(provider.getColumnValue(row, 0, p1), provider.getColumnValue(row, 1, p2),
|
return new Fun.Tuple4<A, B, C, D>(
|
||||||
provider.getColumnValue(row, 2, p3), provider.getColumnValue(row, 3, p4));
|
provider.getColumnValue(row, 0, p1),
|
||||||
}
|
provider.getColumnValue(row, 1, p2),
|
||||||
}
|
provider.getColumnValue(row, 2, p3),
|
||||||
|
provider.getColumnValue(row, 3, p4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final static class Mapper5<A, B, C, D, E> implements Function<Row, Fun.Tuple5<A, B, C, D, E>> {
|
public static final class Mapper5<A, B, C, D, E>
|
||||||
|
implements Function<Row, Fun.Tuple5<A, B, C, D, E>> {
|
||||||
|
|
||||||
private final ColumnValueProvider provider;
|
private final ColumnValueProvider provider;
|
||||||
private final HelenusProperty p1, p2, p3, p4, p5;
|
private final HelenusProperty p1, p2, p3, p4, p5;
|
||||||
|
|
||||||
public Mapper5(ColumnValueProvider provider, HelenusPropertyNode p1, HelenusPropertyNode p2,
|
public Mapper5(
|
||||||
HelenusPropertyNode p3, HelenusPropertyNode p4, HelenusPropertyNode p5) {
|
ColumnValueProvider provider,
|
||||||
this.provider = provider;
|
HelenusPropertyNode p1,
|
||||||
this.p1 = p1.getProperty();
|
HelenusPropertyNode p2,
|
||||||
this.p2 = p2.getProperty();
|
HelenusPropertyNode p3,
|
||||||
this.p3 = p3.getProperty();
|
HelenusPropertyNode p4,
|
||||||
this.p4 = p4.getProperty();
|
HelenusPropertyNode p5) {
|
||||||
this.p5 = p5.getProperty();
|
this.provider = provider;
|
||||||
}
|
this.p1 = p1.getProperty();
|
||||||
|
this.p2 = p2.getProperty();
|
||||||
|
this.p3 = p3.getProperty();
|
||||||
|
this.p4 = p4.getProperty();
|
||||||
|
this.p5 = p5.getProperty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Fun.Tuple5<A, B, C, D, E> apply(Row row) {
|
public Fun.Tuple5<A, B, C, D, E> apply(Row row) {
|
||||||
return new Fun.Tuple5<A, B, C, D, E>(provider.getColumnValue(row, 0, p1),
|
return new Fun.Tuple5<A, B, C, D, E>(
|
||||||
provider.getColumnValue(row, 1, p2), provider.getColumnValue(row, 2, p3),
|
provider.getColumnValue(row, 0, p1),
|
||||||
provider.getColumnValue(row, 3, p4), provider.getColumnValue(row, 4, p5));
|
provider.getColumnValue(row, 1, p2),
|
||||||
}
|
provider.getColumnValue(row, 2, p3),
|
||||||
}
|
provider.getColumnValue(row, 3, p4),
|
||||||
|
provider.getColumnValue(row, 4, p5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final static class Mapper6<A, B, C, D, E, F> implements Function<Row, Fun.Tuple6<A, B, C, D, E, F>> {
|
public static final class Mapper6<A, B, C, D, E, F>
|
||||||
|
implements Function<Row, Fun.Tuple6<A, B, C, D, E, F>> {
|
||||||
|
|
||||||
private final ColumnValueProvider provider;
|
private final ColumnValueProvider provider;
|
||||||
private final HelenusProperty p1, p2, p3, p4, p5, p6;
|
private final HelenusProperty p1, p2, p3, p4, p5, p6;
|
||||||
|
|
||||||
public Mapper6(ColumnValueProvider provider, HelenusPropertyNode p1, HelenusPropertyNode p2,
|
public Mapper6(
|
||||||
HelenusPropertyNode p3, HelenusPropertyNode p4, HelenusPropertyNode p5, HelenusPropertyNode p6) {
|
ColumnValueProvider provider,
|
||||||
this.provider = provider;
|
HelenusPropertyNode p1,
|
||||||
this.p1 = p1.getProperty();
|
HelenusPropertyNode p2,
|
||||||
this.p2 = p2.getProperty();
|
HelenusPropertyNode p3,
|
||||||
this.p3 = p3.getProperty();
|
HelenusPropertyNode p4,
|
||||||
this.p4 = p4.getProperty();
|
HelenusPropertyNode p5,
|
||||||
this.p5 = p5.getProperty();
|
HelenusPropertyNode p6) {
|
||||||
this.p6 = p6.getProperty();
|
this.provider = provider;
|
||||||
}
|
this.p1 = p1.getProperty();
|
||||||
|
this.p2 = p2.getProperty();
|
||||||
|
this.p3 = p3.getProperty();
|
||||||
|
this.p4 = p4.getProperty();
|
||||||
|
this.p5 = p5.getProperty();
|
||||||
|
this.p6 = p6.getProperty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Fun.Tuple6<A, B, C, D, E, F> apply(Row row) {
|
public Fun.Tuple6<A, B, C, D, E, F> apply(Row row) {
|
||||||
return new Fun.Tuple6<A, B, C, D, E, F>(provider.getColumnValue(row, 0, p1),
|
return new Fun.Tuple6<A, B, C, D, E, F>(
|
||||||
provider.getColumnValue(row, 1, p2), provider.getColumnValue(row, 2, p3),
|
provider.getColumnValue(row, 0, p1),
|
||||||
provider.getColumnValue(row, 3, p4), provider.getColumnValue(row, 4, p5),
|
provider.getColumnValue(row, 1, p2),
|
||||||
provider.getColumnValue(row, 5, p6));
|
provider.getColumnValue(row, 2, p3),
|
||||||
}
|
provider.getColumnValue(row, 3, p4),
|
||||||
}
|
provider.getColumnValue(row, 4, p5),
|
||||||
|
provider.getColumnValue(row, 5, p6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final static class Mapper7<A, B, C, D, E, F, G> implements Function<Row, Fun.Tuple7<A, B, C, D, E, F, G>> {
|
public static final class Mapper7<A, B, C, D, E, F, G>
|
||||||
|
implements Function<Row, Fun.Tuple7<A, B, C, D, E, F, G>> {
|
||||||
|
|
||||||
private final ColumnValueProvider provider;
|
private final ColumnValueProvider provider;
|
||||||
private final HelenusProperty p1, p2, p3, p4, p5, p6, p7;
|
private final HelenusProperty p1, p2, p3, p4, p5, p6, p7;
|
||||||
|
|
||||||
public Mapper7(ColumnValueProvider provider, HelenusPropertyNode p1, HelenusPropertyNode p2,
|
public Mapper7(
|
||||||
HelenusPropertyNode p3, HelenusPropertyNode p4, HelenusPropertyNode p5, HelenusPropertyNode p6,
|
ColumnValueProvider provider,
|
||||||
HelenusPropertyNode p7) {
|
HelenusPropertyNode p1,
|
||||||
this.provider = provider;
|
HelenusPropertyNode p2,
|
||||||
this.p1 = p1.getProperty();
|
HelenusPropertyNode p3,
|
||||||
this.p2 = p2.getProperty();
|
HelenusPropertyNode p4,
|
||||||
this.p3 = p3.getProperty();
|
HelenusPropertyNode p5,
|
||||||
this.p4 = p4.getProperty();
|
HelenusPropertyNode p6,
|
||||||
this.p5 = p5.getProperty();
|
HelenusPropertyNode p7) {
|
||||||
this.p6 = p6.getProperty();
|
this.provider = provider;
|
||||||
this.p7 = p7.getProperty();
|
this.p1 = p1.getProperty();
|
||||||
}
|
this.p2 = p2.getProperty();
|
||||||
|
this.p3 = p3.getProperty();
|
||||||
@Override
|
this.p4 = p4.getProperty();
|
||||||
public Fun.Tuple7<A, B, C, D, E, F, G> apply(Row row) {
|
this.p5 = p5.getProperty();
|
||||||
return new Fun.Tuple7<A, B, C, D, E, F, G>(provider.getColumnValue(row, 0, p1),
|
this.p6 = p6.getProperty();
|
||||||
provider.getColumnValue(row, 1, p2), provider.getColumnValue(row, 2, p3),
|
this.p7 = p7.getProperty();
|
||||||
provider.getColumnValue(row, 3, p4), provider.getColumnValue(row, 4, p5),
|
}
|
||||||
provider.getColumnValue(row, 5, p6), provider.getColumnValue(row, 6, p7));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fun.Tuple7<A, B, C, D, E, F, G> apply(Row row) {
|
||||||
|
return new Fun.Tuple7<A, B, C, D, E, F, G>(
|
||||||
|
provider.getColumnValue(row, 0, p1),
|
||||||
|
provider.getColumnValue(row, 1, p2),
|
||||||
|
provider.getColumnValue(row, 2, p3),
|
||||||
|
provider.getColumnValue(row, 3, p4),
|
||||||
|
provider.getColumnValue(row, 4, p5),
|
||||||
|
provider.getColumnValue(row, 5, p6),
|
||||||
|
provider.getColumnValue(row, 6, p7));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,39 +19,37 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public enum Operator {
|
public enum Operator {
|
||||||
|
EQ("=="),
|
||||||
|
|
||||||
EQ("=="),
|
IN("in"),
|
||||||
|
|
||||||
IN("in"),
|
GT(">"),
|
||||||
|
|
||||||
GT(">"),
|
LT("<"),
|
||||||
|
|
||||||
LT("<"),
|
GTE(">="),
|
||||||
|
|
||||||
GTE(">="),
|
LTE("<=");
|
||||||
|
|
||||||
LTE("<=");
|
private final String name;
|
||||||
|
|
||||||
private final String name;
|
private static final Map<String, Operator> indexByName = new HashMap<String, Operator>();
|
||||||
|
|
||||||
private final static Map<String, Operator> indexByName = new HashMap<String, Operator>();
|
static {
|
||||||
|
for (Operator fo : Operator.values()) {
|
||||||
|
indexByName.put(fo.getName(), fo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static {
|
private Operator(String name) {
|
||||||
for (Operator fo : Operator.values()) {
|
this.name = name;
|
||||||
indexByName.put(fo.getName(), fo);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Operator(String name) {
|
public String getName() {
|
||||||
this.name = name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Operator findByOperator(String name) {
|
|
||||||
return indexByName.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public static Operator findByOperator(String name) {
|
||||||
|
return indexByName.get(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.querybuilder.Ordering;
|
import com.datastax.driver.core.querybuilder.Ordering;
|
||||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
|
import java.util.Objects;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.ColumnType;
|
import net.helenus.mapping.ColumnType;
|
||||||
import net.helenus.mapping.MappingUtil;
|
import net.helenus.mapping.MappingUtil;
|
||||||
|
@ -13,37 +11,34 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class Ordered {
|
public final class Ordered {
|
||||||
|
|
||||||
private final Getter<?> getter;
|
private final Getter<?> getter;
|
||||||
private final OrderingDirection direction;
|
private final OrderingDirection direction;
|
||||||
|
|
||||||
public Ordered(Getter<?> getter, OrderingDirection direction) {
|
public Ordered(Getter<?> getter, OrderingDirection direction) {
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ordering getOrdering() {
|
public Ordering getOrdering() {
|
||||||
|
|
||||||
Objects.requireNonNull(getter, "property is null");
|
Objects.requireNonNull(getter, "property is null");
|
||||||
Objects.requireNonNull(direction, "direction is null");
|
Objects.requireNonNull(direction, "direction is null");
|
||||||
|
|
||||||
HelenusPropertyNode propNode = MappingUtil.resolveMappingProperty(getter);
|
HelenusPropertyNode propNode = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
|
||||||
if (propNode.getProperty().getColumnType() != ColumnType.CLUSTERING_COLUMN) {
|
if (propNode.getProperty().getColumnType() != ColumnType.CLUSTERING_COLUMN) {
|
||||||
throw new HelenusMappingException(
|
throw new HelenusMappingException(
|
||||||
"property must be a clustering column " + propNode.getProperty().getPropertyName());
|
"property must be a clustering column " + propNode.getProperty().getPropertyName());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
|
case ASC:
|
||||||
|
return QueryBuilder.asc(propNode.getColumnName());
|
||||||
|
|
||||||
case ASC :
|
case DESC:
|
||||||
return QueryBuilder.asc(propNode.getColumnName());
|
return QueryBuilder.desc(propNode.getColumnName());
|
||||||
|
}
|
||||||
case DESC :
|
|
||||||
return QueryBuilder.desc(propNode.getColumnName());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HelenusMappingException("invalid direction " + direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
throw new HelenusMappingException("invalid direction " + direction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,86 +17,80 @@ package net.helenus.core;
|
||||||
|
|
||||||
import com.datastax.driver.core.querybuilder.Clause;
|
import com.datastax.driver.core.querybuilder.Clause;
|
||||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
|
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.mapping.value.ColumnValuePreparer;
|
import net.helenus.mapping.value.ColumnValuePreparer;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class Postulate<V> {
|
public final class Postulate<V> {
|
||||||
|
|
||||||
private final Operator operator;
|
private final Operator operator;
|
||||||
private final V[] values;
|
private final V[] values;
|
||||||
|
|
||||||
protected Postulate(Operator op, V[] values) {
|
protected Postulate(Operator op, V[] values) {
|
||||||
this.operator = op;
|
this.operator = op;
|
||||||
this.values = values;
|
this.values = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Postulate<V> of(Operator op, V... values) {
|
public static <V> Postulate<V> of(Operator op, V... values) {
|
||||||
return new Postulate<V>(op, values);
|
return new Postulate<V>(op, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Clause getClause(HelenusPropertyNode node, ColumnValuePreparer valuePreparer) {
|
public Clause getClause(HelenusPropertyNode node, ColumnValuePreparer valuePreparer) {
|
||||||
|
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
|
case EQ:
|
||||||
|
return QueryBuilder.eq(
|
||||||
|
node.getColumnName(), valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
||||||
|
|
||||||
case EQ :
|
case IN:
|
||||||
return QueryBuilder.eq(node.getColumnName(),
|
Object[] preparedValues = new Object[values.length];
|
||||||
valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
for (int i = 0; i != values.length; ++i) {
|
||||||
|
preparedValues[i] = valuePreparer.prepareColumnValue(values[i], node.getProperty());
|
||||||
|
}
|
||||||
|
return QueryBuilder.in(node.getColumnName(), preparedValues);
|
||||||
|
|
||||||
case IN :
|
case LT:
|
||||||
Object[] preparedValues = new Object[values.length];
|
return QueryBuilder.lt(
|
||||||
for (int i = 0; i != values.length; ++i) {
|
node.getColumnName(), valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
||||||
preparedValues[i] = valuePreparer.prepareColumnValue(values[i], node.getProperty());
|
|
||||||
}
|
|
||||||
return QueryBuilder.in(node.getColumnName(), preparedValues);
|
|
||||||
|
|
||||||
case LT :
|
case LTE:
|
||||||
return QueryBuilder.lt(node.getColumnName(),
|
return QueryBuilder.lte(
|
||||||
valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
node.getColumnName(), valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
||||||
|
|
||||||
case LTE :
|
case GT:
|
||||||
return QueryBuilder.lte(node.getColumnName(),
|
return QueryBuilder.gt(
|
||||||
valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
node.getColumnName(), valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
||||||
|
|
||||||
case GT :
|
case GTE:
|
||||||
return QueryBuilder.gt(node.getColumnName(),
|
return QueryBuilder.gte(
|
||||||
valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
node.getColumnName(), valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
||||||
|
|
||||||
case GTE :
|
default:
|
||||||
return QueryBuilder.gte(node.getColumnName(),
|
throw new HelenusMappingException("unknown filter operation " + operator);
|
||||||
valuePreparer.prepareColumnValue(values[0], node.getProperty()));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default :
|
@Override
|
||||||
throw new HelenusMappingException("unknown filter operation " + operator);
|
public String toString() {
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (operator == Operator.IN) {
|
||||||
|
|
||||||
@Override
|
if (values == null) {
|
||||||
public String toString() {
|
return "in()";
|
||||||
|
}
|
||||||
|
|
||||||
if (operator == Operator.IN) {
|
int len = values.length;
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
if (values == null) {
|
b.append("in(");
|
||||||
return "in()";
|
for (int i = 0; i != len; i++) {
|
||||||
}
|
if (b.length() > 3) {
|
||||||
|
b.append(", ");
|
||||||
int len = values.length;
|
}
|
||||||
StringBuilder b = new StringBuilder();
|
b.append(String.valueOf(values[i]));
|
||||||
b.append("in(");
|
}
|
||||||
for (int i = 0; i != len; i++) {
|
return b.append(')').toString();
|
||||||
if (b.length() > 3) {
|
}
|
||||||
b.append(", ");
|
|
||||||
}
|
|
||||||
b.append(String.valueOf(values[i]));
|
|
||||||
}
|
|
||||||
return b.append(')').toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return operator.getName() + values[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return operator.getName() + values[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,5 @@ import net.helenus.mapping.HelenusProperty;
|
||||||
|
|
||||||
public interface PropertyValueValidator {
|
public interface PropertyValueValidator {
|
||||||
|
|
||||||
void validate(HelenusProperty prop, Object value);
|
void validate(HelenusProperty prop, Object value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,90 +15,80 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.querybuilder.BindMarker;
|
||||||
|
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import com.datastax.driver.core.querybuilder.BindMarker;
|
|
||||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
|
||||||
|
|
||||||
import net.helenus.mapping.OrderingDirection;
|
import net.helenus.mapping.OrderingDirection;
|
||||||
|
|
||||||
/**
|
/** Sugar methods for the queries */
|
||||||
* Sugar methods for the queries
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final class Query {
|
public final class Query {
|
||||||
|
|
||||||
private Query() {
|
private Query() {}
|
||||||
}
|
|
||||||
|
|
||||||
public static BindMarker marker() {
|
public static BindMarker marker() {
|
||||||
return QueryBuilder.bindMarker();
|
return QueryBuilder.bindMarker();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BindMarker marker(String name) {
|
public static BindMarker marker(String name) {
|
||||||
return QueryBuilder.bindMarker(name);
|
return QueryBuilder.bindMarker(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Ordered asc(Getter<?> getter) {
|
public static Ordered asc(Getter<?> getter) {
|
||||||
return new Ordered(getter, OrderingDirection.ASC);
|
return new Ordered(getter, OrderingDirection.ASC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Ordered desc(Getter<?> getter) {
|
public static Ordered desc(Getter<?> getter) {
|
||||||
return new Ordered(getter, OrderingDirection.DESC);
|
return new Ordered(getter, OrderingDirection.DESC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Postulate<V> eq(V val) {
|
public static <V> Postulate<V> eq(V val) {
|
||||||
return Postulate.of(Operator.EQ, val);
|
return Postulate.of(Operator.EQ, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Postulate<V> lt(V val) {
|
public static <V> Postulate<V> lt(V val) {
|
||||||
return Postulate.of(Operator.LT, val);
|
return Postulate.of(Operator.LT, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Postulate<V> lte(V val) {
|
public static <V> Postulate<V> lte(V val) {
|
||||||
return Postulate.of(Operator.LTE, val);
|
return Postulate.of(Operator.LTE, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Postulate<V> gt(V val) {
|
public static <V> Postulate<V> gt(V val) {
|
||||||
return Postulate.of(Operator.GT, val);
|
return Postulate.of(Operator.GT, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Postulate<V> gte(V val) {
|
public static <V> Postulate<V> gte(V val) {
|
||||||
return Postulate.of(Operator.GTE, val);
|
return Postulate.of(Operator.GTE, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Postulate<V> in(V[] vals) {
|
public static <V> Postulate<V> in(V[] vals) {
|
||||||
return new Postulate<V>(Operator.IN, vals);
|
return new Postulate<V>(Operator.IN, vals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <K, V> Getter<V> getIdx(Getter<List<V>> listGetter, int index) {
|
public static <K, V> Getter<V> getIdx(Getter<List<V>> listGetter, int index) {
|
||||||
Objects.requireNonNull(listGetter, "listGetter is null");
|
Objects.requireNonNull(listGetter, "listGetter is null");
|
||||||
|
|
||||||
return new Getter<V>() {
|
return new Getter<V>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V get() {
|
public V get() {
|
||||||
return listGetter.get().get(index);
|
return listGetter.get().get(index);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
};
|
public static <K, V> Getter<V> get(Getter<Map<K, V>> mapGetter, K k) {
|
||||||
}
|
Objects.requireNonNull(mapGetter, "mapGetter is null");
|
||||||
|
Objects.requireNonNull(k, "key is null");
|
||||||
|
|
||||||
public static <K, V> Getter<V> get(Getter<Map<K, V>> mapGetter, K k) {
|
return new Getter<V>() {
|
||||||
Objects.requireNonNull(mapGetter, "mapGetter is null");
|
|
||||||
Objects.requireNonNull(k, "key is null");
|
|
||||||
|
|
||||||
return new Getter<V>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V get() {
|
|
||||||
return mapGetter.get().get(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get() {
|
||||||
|
return mapGetter.get().get(k);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.*;
|
import com.datastax.driver.core.*;
|
||||||
import com.datastax.driver.core.IndexMetadata;
|
import com.datastax.driver.core.IndexMetadata;
|
||||||
import com.datastax.driver.core.schemabuilder.*;
|
import com.datastax.driver.core.schemabuilder.*;
|
||||||
import com.datastax.driver.core.schemabuilder.Create.Options;
|
import com.datastax.driver.core.schemabuilder.Create.Options;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import net.helenus.mapping.*;
|
import net.helenus.mapping.*;
|
||||||
import net.helenus.mapping.ColumnType;
|
import net.helenus.mapping.ColumnType;
|
||||||
import net.helenus.mapping.type.OptionalColumnMetadata;
|
import net.helenus.mapping.type.OptionalColumnMetadata;
|
||||||
|
@ -31,335 +29,342 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class SchemaUtil {
|
public final class SchemaUtil {
|
||||||
|
|
||||||
private SchemaUtil() {
|
private SchemaUtil() {}
|
||||||
}
|
|
||||||
|
|
||||||
public static RegularStatement use(String keyspace, boolean forceQuote) {
|
public static RegularStatement use(String keyspace, boolean forceQuote) {
|
||||||
if (forceQuote) {
|
if (forceQuote) {
|
||||||
return new SimpleStatement("USE" + CqlUtil.forceQuote(keyspace));
|
return new SimpleStatement("USE" + CqlUtil.forceQuote(keyspace));
|
||||||
} else {
|
} else {
|
||||||
return new SimpleStatement("USE " + keyspace);
|
return new SimpleStatement("USE " + keyspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchemaStatement createUserType(HelenusEntity entity) {
|
public static SchemaStatement createUserType(HelenusEntity entity) {
|
||||||
|
|
||||||
if (entity.getType() != HelenusEntityType.UDT) {
|
|
||||||
throw new HelenusMappingException("expected UDT entity " + entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateType create = SchemaBuilder.createType(entity.getName().toCql());
|
|
||||||
|
|
||||||
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
|
||||||
|
|
||||||
ColumnType columnType = prop.getColumnType();
|
|
||||||
|
|
||||||
if (columnType == ColumnType.PARTITION_KEY || columnType == ColumnType.CLUSTERING_COLUMN) {
|
|
||||||
throw new HelenusMappingException("primary key columns are not supported in UserDefinedType for "
|
|
||||||
+ prop.getPropertyName() + " in entity " + entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
prop.getDataType().addColumn(create, prop.getColumnName());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new HelenusMappingException("invalid column name '" + prop.getColumnName() + "' in entity '"
|
|
||||||
+ entity.getName().getName() + "'", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return create;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<SchemaStatement> alterUserType(UserType userType, HelenusEntity entity,
|
|
||||||
boolean dropUnusedColumns) {
|
|
||||||
|
|
||||||
if (entity.getType() != HelenusEntityType.UDT) {
|
|
||||||
throw new HelenusMappingException("expected UDT entity " + entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<SchemaStatement> result = new ArrayList<SchemaStatement>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: In future replace SchemaBuilder.alterTable by SchemaBuilder.alterType
|
|
||||||
* when it will exist
|
|
||||||
*/
|
|
||||||
|
|
||||||
Alter alter = SchemaBuilder.alterTable(entity.getName().toCql());
|
|
||||||
|
|
||||||
final Set<String> visitedColumns = dropUnusedColumns ? new HashSet<String>() : Collections.<String>emptySet();
|
|
||||||
|
|
||||||
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
|
||||||
|
|
||||||
String columnName = prop.getColumnName().getName();
|
|
||||||
|
|
||||||
if (dropUnusedColumns) {
|
|
||||||
visitedColumns.add(columnName);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnType columnType = prop.getColumnType();
|
|
||||||
|
|
||||||
if (columnType == ColumnType.PARTITION_KEY || columnType == ColumnType.CLUSTERING_COLUMN) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataType dataType = userType.getFieldType(columnName);
|
|
||||||
SchemaStatement stmt = prop.getDataType().alterColumn(alter, prop.getColumnName(),
|
|
||||||
optional(columnName, dataType));
|
|
||||||
|
|
||||||
if (stmt != null) {
|
|
||||||
result.add(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dropUnusedColumns) {
|
|
||||||
for (String field : userType.getFieldNames()) {
|
|
||||||
if (!visitedColumns.contains(field)) {
|
|
||||||
|
|
||||||
result.add(alter.dropColumn(field));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SchemaStatement dropUserType(HelenusEntity entity) {
|
|
||||||
|
|
||||||
if (entity.getType() != HelenusEntityType.UDT) {
|
|
||||||
throw new HelenusMappingException("expected UDT entity " + entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SchemaBuilder.dropType(entity.getName().toCql()).ifExists();
|
|
||||||
|
|
||||||
|
if (entity.getType() != HelenusEntityType.UDT) {
|
||||||
|
throw new HelenusMappingException("expected UDT entity " + entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchemaStatement dropUserType(UserType type) {
|
CreateType create = SchemaBuilder.createType(entity.getName().toCql());
|
||||||
|
|
||||||
return SchemaBuilder.dropType(type.getTypeName()).ifExists();
|
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
||||||
}
|
|
||||||
|
|
||||||
public static SchemaStatement createTable(HelenusEntity entity) {
|
ColumnType columnType = prop.getColumnType();
|
||||||
|
|
||||||
if (entity.getType() != HelenusEntityType.TABLE) {
|
if (columnType == ColumnType.PARTITION_KEY || columnType == ColumnType.CLUSTERING_COLUMN) {
|
||||||
throw new HelenusMappingException("expected table entity " + entity);
|
throw new HelenusMappingException(
|
||||||
}
|
"primary key columns are not supported in UserDefinedType for "
|
||||||
|
+ prop.getPropertyName()
|
||||||
|
+ " in entity "
|
||||||
|
+ entity);
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: There is a bug in the normal path of createTable where the
|
try {
|
||||||
// "cache" is set too early and never unset preventing more than
|
prop.getDataType().addColumn(create, prop.getColumnName());
|
||||||
// one column on a table.
|
} catch (IllegalArgumentException e) {
|
||||||
// SchemaBuilder.createTable(entity.getName().toCql());
|
throw new HelenusMappingException(
|
||||||
CreateTable create = new CreateTable(entity.getName().toCql());
|
"invalid column name '"
|
||||||
|
+ prop.getColumnName()
|
||||||
|
+ "' in entity '"
|
||||||
|
+ entity.getName().getName()
|
||||||
|
+ "'",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
create.ifNotExists();
|
return create;
|
||||||
|
}
|
||||||
|
|
||||||
List<HelenusProperty> clusteringColumns = new ArrayList<HelenusProperty>();
|
public static List<SchemaStatement> alterUserType(
|
||||||
|
UserType userType, HelenusEntity entity, boolean dropUnusedColumns) {
|
||||||
|
|
||||||
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
if (entity.getType() != HelenusEntityType.UDT) {
|
||||||
|
throw new HelenusMappingException("expected UDT entity " + entity);
|
||||||
|
}
|
||||||
|
|
||||||
ColumnType columnType = prop.getColumnType();
|
List<SchemaStatement> result = new ArrayList<SchemaStatement>();
|
||||||
|
|
||||||
if (columnType == ColumnType.CLUSTERING_COLUMN) {
|
/**
|
||||||
clusteringColumns.add(prop);
|
* TODO: In future replace SchemaBuilder.alterTable by SchemaBuilder.alterType when it will
|
||||||
}
|
* exist
|
||||||
|
*/
|
||||||
|
Alter alter = SchemaBuilder.alterTable(entity.getName().toCql());
|
||||||
|
|
||||||
prop.getDataType().addColumn(create, prop.getColumnName());
|
final Set<String> visitedColumns =
|
||||||
|
dropUnusedColumns ? new HashSet<String>() : Collections.<String>emptySet();
|
||||||
|
|
||||||
}
|
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
||||||
|
|
||||||
if (!clusteringColumns.isEmpty()) {
|
String columnName = prop.getColumnName().getName();
|
||||||
Options options = create.withOptions();
|
|
||||||
clusteringColumns
|
|
||||||
.forEach(p -> options.clusteringOrder(p.getColumnName().toCql(), mapDirection(p.getOrdering())));
|
|
||||||
}
|
|
||||||
|
|
||||||
return create;
|
if (dropUnusedColumns) {
|
||||||
|
visitedColumns.add(columnName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
ColumnType columnType = prop.getColumnType();
|
||||||
|
|
||||||
public static List<SchemaStatement> alterTable(TableMetadata tmd, HelenusEntity entity, boolean dropUnusedColumns) {
|
if (columnType == ColumnType.PARTITION_KEY || columnType == ColumnType.CLUSTERING_COLUMN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (entity.getType() != HelenusEntityType.TABLE) {
|
DataType dataType = userType.getFieldType(columnName);
|
||||||
throw new HelenusMappingException("expected table entity " + entity);
|
SchemaStatement stmt =
|
||||||
}
|
prop.getDataType()
|
||||||
|
.alterColumn(alter, prop.getColumnName(), optional(columnName, dataType));
|
||||||
|
|
||||||
List<SchemaStatement> result = new ArrayList<SchemaStatement>();
|
if (stmt != null) {
|
||||||
|
result.add(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Alter alter = SchemaBuilder.alterTable(entity.getName().toCql());
|
if (dropUnusedColumns) {
|
||||||
|
for (String field : userType.getFieldNames()) {
|
||||||
|
if (!visitedColumns.contains(field)) {
|
||||||
|
|
||||||
final Set<String> visitedColumns = dropUnusedColumns ? new HashSet<String>() : Collections.<String>emptySet();
|
result.add(alter.dropColumn(field));
|
||||||
|
|
||||||
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
|
||||||
|
|
||||||
String columnName = prop.getColumnName().getName();
|
|
||||||
|
|
||||||
if (dropUnusedColumns) {
|
|
||||||
visitedColumns.add(columnName);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnType columnType = prop.getColumnType();
|
|
||||||
|
|
||||||
if (columnType == ColumnType.PARTITION_KEY || columnType == ColumnType.CLUSTERING_COLUMN) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnMetadata columnMetadata = tmd.getColumn(columnName);
|
|
||||||
SchemaStatement stmt = prop.getDataType().alterColumn(alter, prop.getColumnName(),
|
|
||||||
optional(columnMetadata));
|
|
||||||
|
|
||||||
if (stmt != null) {
|
|
||||||
result.add(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dropUnusedColumns) {
|
|
||||||
for (ColumnMetadata cm : tmd.getColumns()) {
|
|
||||||
if (!visitedColumns.contains(cm.getName())) {
|
|
||||||
|
|
||||||
result.add(alter.dropColumn(cm.getName()));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SchemaStatement dropTable(HelenusEntity entity) {
|
|
||||||
|
|
||||||
if (entity.getType() != HelenusEntityType.TABLE) {
|
|
||||||
throw new HelenusMappingException("expected table entity " + entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SchemaBuilder.dropTable(entity.getName().toCql()).ifExists();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SchemaStatement createIndex(HelenusProperty prop) {
|
|
||||||
if (prop.caseSensitiveIndex()) {
|
|
||||||
return SchemaBuilder.createIndex(prop.getIndexName().get().toCql())
|
|
||||||
.ifNotExists()
|
|
||||||
.onTable(prop.getEntity().getName().toCql())
|
|
||||||
.andColumn(prop.getColumnName().toCql());
|
|
||||||
} else {
|
|
||||||
return new CreateSasiIndex(prop.getIndexName().get().toCql())
|
|
||||||
.ifNotExists()
|
|
||||||
.onTable(prop.getEntity().getName().toCql())
|
|
||||||
.andColumn(prop.getColumnName().toCql());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static List<SchemaStatement> createIndexes(HelenusEntity entity) {
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return entity.getOrderedProperties().stream().filter(p -> p.getIndexName().isPresent())
|
public static SchemaStatement dropUserType(HelenusEntity entity) {
|
||||||
.map(p -> SchemaUtil.createIndex(p)).collect(Collectors.toList());
|
|
||||||
|
|
||||||
}
|
if (entity.getType() != HelenusEntityType.UDT) {
|
||||||
|
throw new HelenusMappingException("expected UDT entity " + entity);
|
||||||
|
}
|
||||||
|
|
||||||
public static List<SchemaStatement> alterIndexes(TableMetadata tmd, HelenusEntity entity,
|
return SchemaBuilder.dropType(entity.getName().toCql()).ifExists();
|
||||||
boolean dropUnusedIndexes) {
|
}
|
||||||
|
|
||||||
List<SchemaStatement> list = new ArrayList<SchemaStatement>();
|
public static SchemaStatement dropUserType(UserType type) {
|
||||||
|
|
||||||
final Set<String> visitedColumns = dropUnusedIndexes ? new HashSet<String>() : Collections.<String>emptySet();
|
return SchemaBuilder.dropType(type.getTypeName()).ifExists();
|
||||||
|
}
|
||||||
|
|
||||||
entity.getOrderedProperties().stream().filter(p -> p.getIndexName().isPresent()).forEach(p -> {
|
public static SchemaStatement createTable(HelenusEntity entity) {
|
||||||
|
|
||||||
String columnName = p.getColumnName().getName();
|
if (entity.getType() != HelenusEntityType.TABLE) {
|
||||||
|
throw new HelenusMappingException("expected table entity " + entity);
|
||||||
|
}
|
||||||
|
|
||||||
if (dropUnusedIndexes) {
|
// NOTE: There is a bug in the normal path of createTable where the
|
||||||
visitedColumns.add(columnName);
|
// "cache" is set too early and never unset preventing more than
|
||||||
}
|
// one column on a table.
|
||||||
|
// SchemaBuilder.createTable(entity.getName().toCql());
|
||||||
|
CreateTable create = new CreateTable(entity.getName().toCql());
|
||||||
|
|
||||||
ColumnMetadata cm = tmd.getColumn(columnName);
|
create.ifNotExists();
|
||||||
|
|
||||||
if (cm != null) {
|
List<HelenusProperty> clusteringColumns = new ArrayList<HelenusProperty>();
|
||||||
IndexMetadata im = tmd.getIndex(columnName);
|
|
||||||
if (im == null) {
|
|
||||||
list.add(createIndex(p));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
list.add(createIndex(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
||||||
|
|
||||||
if (dropUnusedIndexes) {
|
ColumnType columnType = prop.getColumnType();
|
||||||
|
|
||||||
tmd.getColumns().stream().filter(c -> tmd.getIndex(c.getName()) != null && !visitedColumns.contains(c.getName()))
|
if (columnType == ColumnType.CLUSTERING_COLUMN) {
|
||||||
.forEach(c -> {
|
clusteringColumns.add(prop);
|
||||||
list.add(SchemaBuilder.dropIndex(tmd.getIndex(c.getName()).getName()).ifExists());
|
}
|
||||||
|
|
||||||
});
|
prop.getDataType().addColumn(create, prop.getColumnName());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
if (!clusteringColumns.isEmpty()) {
|
||||||
|
Options options = create.withOptions();
|
||||||
|
clusteringColumns.forEach(
|
||||||
|
p -> options.clusteringOrder(p.getColumnName().toCql(), mapDirection(p.getOrdering())));
|
||||||
|
}
|
||||||
|
|
||||||
return list;
|
return create;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public static List<SchemaStatement> alterTable(
|
||||||
|
TableMetadata tmd, HelenusEntity entity, boolean dropUnusedColumns) {
|
||||||
|
|
||||||
public static SchemaStatement dropIndex(HelenusProperty prop) {
|
if (entity.getType() != HelenusEntityType.TABLE) {
|
||||||
return SchemaBuilder.dropIndex(prop.getIndexName().get().toCql()).ifExists();
|
throw new HelenusMappingException("expected table entity " + entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SchemaBuilder.Direction mapDirection(OrderingDirection o) {
|
List<SchemaStatement> result = new ArrayList<SchemaStatement>();
|
||||||
switch (o) {
|
|
||||||
case ASC :
|
|
||||||
return SchemaBuilder.Direction.ASC;
|
|
||||||
case DESC :
|
|
||||||
return SchemaBuilder.Direction.DESC;
|
|
||||||
}
|
|
||||||
throw new HelenusMappingException("unknown ordering " + o);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void throwNoMapping(HelenusProperty prop) {
|
Alter alter = SchemaBuilder.alterTable(entity.getName().toCql());
|
||||||
|
|
||||||
throw new HelenusMappingException(
|
final Set<String> visitedColumns =
|
||||||
"only primitive types and Set,List,Map collections and UserDefinedTypes are allowed, unknown type for property '"
|
dropUnusedColumns ? new HashSet<String>() : Collections.<String>emptySet();
|
||||||
+ prop.getPropertyName() + "' type is '" + prop.getJavaType() + "' in the entity "
|
|
||||||
+ prop.getEntity());
|
|
||||||
|
|
||||||
}
|
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
||||||
|
|
||||||
private static OptionalColumnMetadata optional(final ColumnMetadata columnMetadata) {
|
String columnName = prop.getColumnName().getName();
|
||||||
if (columnMetadata != null) {
|
|
||||||
return new OptionalColumnMetadata() {
|
|
||||||
|
|
||||||
@Override
|
if (dropUnusedColumns) {
|
||||||
public String getName() {
|
visitedColumns.add(columnName);
|
||||||
return columnMetadata.getName();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
ColumnType columnType = prop.getColumnType();
|
||||||
public DataType getType() {
|
|
||||||
return columnMetadata.getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
if (columnType == ColumnType.PARTITION_KEY || columnType == ColumnType.CLUSTERING_COLUMN) {
|
||||||
}
|
continue;
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static OptionalColumnMetadata optional(final String name, final DataType dataType) {
|
ColumnMetadata columnMetadata = tmd.getColumn(columnName);
|
||||||
if (dataType != null) {
|
SchemaStatement stmt =
|
||||||
return new OptionalColumnMetadata() {
|
prop.getDataType().alterColumn(alter, prop.getColumnName(), optional(columnMetadata));
|
||||||
|
|
||||||
@Override
|
if (stmt != null) {
|
||||||
public String getName() {
|
result.add(stmt);
|
||||||
return name;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
if (dropUnusedColumns) {
|
||||||
public DataType getType() {
|
for (ColumnMetadata cm : tmd.getColumns()) {
|
||||||
return dataType;
|
if (!visitedColumns.contains(cm.getName())) {
|
||||||
}
|
|
||||||
|
|
||||||
};
|
result.add(alter.dropColumn(cm.getName()));
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchemaStatement dropTable(HelenusEntity entity) {
|
||||||
|
|
||||||
|
if (entity.getType() != HelenusEntityType.TABLE) {
|
||||||
|
throw new HelenusMappingException("expected table entity " + entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SchemaBuilder.dropTable(entity.getName().toCql()).ifExists();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchemaStatement createIndex(HelenusProperty prop) {
|
||||||
|
if (prop.caseSensitiveIndex()) {
|
||||||
|
return SchemaBuilder.createIndex(prop.getIndexName().get().toCql())
|
||||||
|
.ifNotExists()
|
||||||
|
.onTable(prop.getEntity().getName().toCql())
|
||||||
|
.andColumn(prop.getColumnName().toCql());
|
||||||
|
} else {
|
||||||
|
return new CreateSasiIndex(prop.getIndexName().get().toCql())
|
||||||
|
.ifNotExists()
|
||||||
|
.onTable(prop.getEntity().getName().toCql())
|
||||||
|
.andColumn(prop.getColumnName().toCql());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchemaStatement> createIndexes(HelenusEntity entity) {
|
||||||
|
|
||||||
|
return entity
|
||||||
|
.getOrderedProperties()
|
||||||
|
.stream()
|
||||||
|
.filter(p -> p.getIndexName().isPresent())
|
||||||
|
.map(p -> SchemaUtil.createIndex(p))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchemaStatement> alterIndexes(
|
||||||
|
TableMetadata tmd, HelenusEntity entity, boolean dropUnusedIndexes) {
|
||||||
|
|
||||||
|
List<SchemaStatement> list = new ArrayList<SchemaStatement>();
|
||||||
|
|
||||||
|
final Set<String> visitedColumns =
|
||||||
|
dropUnusedIndexes ? new HashSet<String>() : Collections.<String>emptySet();
|
||||||
|
|
||||||
|
entity
|
||||||
|
.getOrderedProperties()
|
||||||
|
.stream()
|
||||||
|
.filter(p -> p.getIndexName().isPresent())
|
||||||
|
.forEach(
|
||||||
|
p -> {
|
||||||
|
String columnName = p.getColumnName().getName();
|
||||||
|
|
||||||
|
if (dropUnusedIndexes) {
|
||||||
|
visitedColumns.add(columnName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnMetadata cm = tmd.getColumn(columnName);
|
||||||
|
|
||||||
|
if (cm != null) {
|
||||||
|
IndexMetadata im = tmd.getIndex(columnName);
|
||||||
|
if (im == null) {
|
||||||
|
list.add(createIndex(p));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.add(createIndex(p));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dropUnusedIndexes) {
|
||||||
|
|
||||||
|
tmd.getColumns()
|
||||||
|
.stream()
|
||||||
|
.filter(c -> tmd.getIndex(c.getName()) != null && !visitedColumns.contains(c.getName()))
|
||||||
|
.forEach(
|
||||||
|
c -> {
|
||||||
|
list.add(SchemaBuilder.dropIndex(tmd.getIndex(c.getName()).getName()).ifExists());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchemaStatement dropIndex(HelenusProperty prop) {
|
||||||
|
return SchemaBuilder.dropIndex(prop.getIndexName().get().toCql()).ifExists();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SchemaBuilder.Direction mapDirection(OrderingDirection o) {
|
||||||
|
switch (o) {
|
||||||
|
case ASC:
|
||||||
|
return SchemaBuilder.Direction.ASC;
|
||||||
|
case DESC:
|
||||||
|
return SchemaBuilder.Direction.DESC;
|
||||||
|
}
|
||||||
|
throw new HelenusMappingException("unknown ordering " + o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void throwNoMapping(HelenusProperty prop) {
|
||||||
|
|
||||||
|
throw new HelenusMappingException(
|
||||||
|
"only primitive types and Set,List,Map collections and UserDefinedTypes are allowed, unknown type for property '"
|
||||||
|
+ prop.getPropertyName()
|
||||||
|
+ "' type is '"
|
||||||
|
+ prop.getJavaType()
|
||||||
|
+ "' in the entity "
|
||||||
|
+ prop.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OptionalColumnMetadata optional(final ColumnMetadata columnMetadata) {
|
||||||
|
if (columnMetadata != null) {
|
||||||
|
return new OptionalColumnMetadata() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return columnMetadata.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType getType() {
|
||||||
|
return columnMetadata.getType();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OptionalColumnMetadata optional(final String name, final DataType dataType) {
|
||||||
|
if (dataType != null) {
|
||||||
|
return new OptionalColumnMetadata() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType getType() {
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
|
import brave.Tracer;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.datastax.driver.core.*;
|
import com.datastax.driver.core.*;
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusEntityType;
|
import net.helenus.mapping.HelenusEntityType;
|
||||||
import net.helenus.mapping.value.ColumnValuePreparer;
|
import net.helenus.mapping.value.ColumnValuePreparer;
|
||||||
|
@ -25,335 +32,355 @@ import net.helenus.mapping.value.ColumnValueProvider;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
import net.helenus.support.PackageUtil;
|
import net.helenus.support.PackageUtil;
|
||||||
|
|
||||||
import brave.Tracer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public final class SessionInitializer extends AbstractSessionOperations {
|
public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
|
|
||||||
private final Session session;
|
private final Session session;
|
||||||
private CodecRegistry registry;
|
private CodecRegistry registry;
|
||||||
private String usingKeyspace;
|
private String usingKeyspace;
|
||||||
private boolean showCql = false;
|
private boolean showCql = false;
|
||||||
private ConsistencyLevel consistencyLevel;
|
private ConsistencyLevel consistencyLevel;
|
||||||
private MetricRegistry metricRegistry;
|
private MetricRegistry metricRegistry;
|
||||||
private Tracer zipkinTracer;
|
private Tracer zipkinTracer;
|
||||||
private PrintStream printStream = System.out;
|
private PrintStream printStream = System.out;
|
||||||
private Executor executor = MoreExecutors.directExecutor();
|
private Executor executor = MoreExecutors.directExecutor();
|
||||||
|
|
||||||
private SessionRepositoryBuilder sessionRepository;
|
private SessionRepositoryBuilder sessionRepository;
|
||||||
|
|
||||||
private boolean dropUnusedColumns = false;
|
private boolean dropUnusedColumns = false;
|
||||||
private boolean dropUnusedIndexes = false;
|
private boolean dropUnusedIndexes = false;
|
||||||
|
|
||||||
private KeyspaceMetadata keyspaceMetadata;
|
private KeyspaceMetadata keyspaceMetadata;
|
||||||
|
|
||||||
private final List<Object> initList = new ArrayList<Object>();
|
private final List<Object> initList = new ArrayList<Object>();
|
||||||
private AutoDdl autoDdl = AutoDdl.UPDATE;
|
private AutoDdl autoDdl = AutoDdl.UPDATE;
|
||||||
|
|
||||||
SessionInitializer(Session session) {
|
SessionInitializer(Session session) {
|
||||||
this.session = Objects.requireNonNull(session, "empty session");
|
this.session = Objects.requireNonNull(session, "empty session");
|
||||||
this.usingKeyspace = session.getLoggedKeyspace(); // can be null
|
this.usingKeyspace = session.getLoggedKeyspace(); // can be null
|
||||||
this.sessionRepository = new SessionRepositoryBuilder(session);
|
this.sessionRepository = new SessionRepositoryBuilder(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Session currentSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String usingKeyspace() {
|
||||||
|
return usingKeyspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Executor getExecutor() {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionRepository getSessionRepository() {
|
||||||
|
throw new HelenusException("not expected to call");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ColumnValueProvider getValueProvider() {
|
||||||
|
throw new HelenusException("not expected to call");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ColumnValuePreparer getValuePreparer() {
|
||||||
|
throw new HelenusException("not expected to call");
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer showCql() {
|
||||||
|
this.showCql = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer showCql(boolean enabled) {
|
||||||
|
this.showCql = enabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer metricRegistry(MetricRegistry metricRegistry) {
|
||||||
|
this.metricRegistry = metricRegistry;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer zipkinTracer(Tracer tracer) {
|
||||||
|
this.zipkinTracer = tracer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer consistencyLevel(ConsistencyLevel consistencyLevel) {
|
||||||
|
this.consistencyLevel = consistencyLevel;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConsistencyLevel getDefaultConsistencyLevel() {
|
||||||
|
return consistencyLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrintStream getPrintStream() {
|
||||||
|
return printStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer printTo(PrintStream out) {
|
||||||
|
this.printStream = out;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer withExecutor(Executor executor) {
|
||||||
|
Objects.requireNonNull(executor, "empty executor");
|
||||||
|
this.executor = executor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer withCachingExecutor() {
|
||||||
|
this.executor = Executors.newCachedThreadPool();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer dropUnusedColumns(boolean enabled) {
|
||||||
|
this.dropUnusedColumns = enabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer dropUnusedIndexes(boolean enabled) {
|
||||||
|
this.dropUnusedIndexes = enabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer withCodecRegistry(CodecRegistry registry) {
|
||||||
|
this.registry = registry;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShowCql() {
|
||||||
|
return showCql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer addPackage(String packageName) {
|
||||||
|
try {
|
||||||
|
PackageUtil.getClasses(packageName)
|
||||||
|
.stream()
|
||||||
|
.filter(c -> c.isInterface() && !c.isAnnotation())
|
||||||
|
.forEach(initList::add);
|
||||||
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
throw new HelenusException("fail to add package " + packageName, e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer add(Object... dsls) {
|
||||||
|
Objects.requireNonNull(dsls, "dsls is empty");
|
||||||
|
int len = dsls.length;
|
||||||
|
for (int i = 0; i != len; ++i) {
|
||||||
|
Object obj = Objects.requireNonNull(dsls[i], "element " + i + " is empty");
|
||||||
|
initList.add(obj);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer autoValidate() {
|
||||||
|
this.autoDdl = AutoDdl.VALIDATE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer autoUpdate() {
|
||||||
|
this.autoDdl = AutoDdl.UPDATE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer autoCreate() {
|
||||||
|
this.autoDdl = AutoDdl.CREATE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer autoCreateDrop() {
|
||||||
|
this.autoDdl = AutoDdl.CREATE_DROP;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer auto(AutoDdl autoDdl) {
|
||||||
|
this.autoDdl = autoDdl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer use(String keyspace) {
|
||||||
|
session.execute(SchemaUtil.use(keyspace, false));
|
||||||
|
this.usingKeyspace = keyspace;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionInitializer use(String keyspace, boolean forceQuote) {
|
||||||
|
session.execute(SchemaUtil.use(keyspace, forceQuote));
|
||||||
|
this.usingKeyspace = keyspace;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void singleton() {
|
||||||
|
|
||||||
|
Helenus.setSession(get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized HelenusSession get() {
|
||||||
|
initialize();
|
||||||
|
return new HelenusSession(
|
||||||
|
session,
|
||||||
|
usingKeyspace,
|
||||||
|
registry,
|
||||||
|
showCql,
|
||||||
|
printStream,
|
||||||
|
sessionRepository,
|
||||||
|
executor,
|
||||||
|
autoDdl == AutoDdl.CREATE_DROP,
|
||||||
|
consistencyLevel,
|
||||||
|
metricRegistry,
|
||||||
|
zipkinTracer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() {
|
||||||
|
|
||||||
|
Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator");
|
||||||
|
|
||||||
|
initList.forEach(dsl -> sessionRepository.add(dsl));
|
||||||
|
|
||||||
|
TableOperations tableOps = new TableOperations(this, dropUnusedColumns, dropUnusedIndexes);
|
||||||
|
UserTypeOperations userTypeOps = new UserTypeOperations(this, dropUnusedColumns);
|
||||||
|
|
||||||
|
switch (autoDdl) {
|
||||||
|
case CREATE_DROP:
|
||||||
|
|
||||||
|
// Drop tables first, otherwise a `DROP TYPE ...` will fail as the type is still referenced
|
||||||
|
// by a table.
|
||||||
|
sessionRepository
|
||||||
|
.entities()
|
||||||
|
.stream()
|
||||||
|
.filter(e -> e.getType() == HelenusEntityType.TABLE)
|
||||||
|
.forEach(e -> tableOps.dropTable(e));
|
||||||
|
|
||||||
|
eachUserTypeInReverseOrder(userTypeOps, e -> userTypeOps.dropUserType(e));
|
||||||
|
|
||||||
|
// FALLTHRU to CREATE case (read: the absence of a `break;` statement here is intentional!)
|
||||||
|
case CREATE:
|
||||||
|
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.createUserType(e));
|
||||||
|
|
||||||
|
sessionRepository
|
||||||
|
.entities()
|
||||||
|
.stream()
|
||||||
|
.filter(e -> e.getType() == HelenusEntityType.TABLE)
|
||||||
|
.forEach(e -> tableOps.createTable(e));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALIDATE:
|
||||||
|
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.validateUserType(getUserType(e), e));
|
||||||
|
|
||||||
|
sessionRepository
|
||||||
|
.entities()
|
||||||
|
.stream()
|
||||||
|
.filter(e -> e.getType() == HelenusEntityType.TABLE)
|
||||||
|
.forEach(e -> tableOps.validateTable(getTableMetadata(e), e));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UPDATE:
|
||||||
|
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.updateUserType(getUserType(e), e));
|
||||||
|
|
||||||
|
sessionRepository
|
||||||
|
.entities()
|
||||||
|
.stream()
|
||||||
|
.filter(e -> e.getType() == HelenusEntityType.TABLE)
|
||||||
|
.forEach(e -> tableOps.updateTable(getTableMetadata(e), e));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
KeyspaceMetadata km = getKeyspaceMetadata();
|
||||||
public Session currentSession() {
|
|
||||||
return session;
|
for (UserType userType : km.getUserTypes()) {
|
||||||
|
sessionRepository.addUserType(userType.getTypeName(), userType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void eachUserTypeInOrder(
|
||||||
|
UserTypeOperations userTypeOps, Consumer<? super HelenusEntity> action) {
|
||||||
|
|
||||||
|
Set<HelenusEntity> processedSet = new HashSet<HelenusEntity>();
|
||||||
|
Set<HelenusEntity> stack = new HashSet<HelenusEntity>();
|
||||||
|
|
||||||
|
sessionRepository
|
||||||
|
.entities()
|
||||||
|
.stream()
|
||||||
|
.filter(e -> e.getType() == HelenusEntityType.UDT)
|
||||||
|
.forEach(
|
||||||
|
e -> {
|
||||||
|
stack.clear();
|
||||||
|
eachUserTypeInRecursion(e, processedSet, stack, userTypeOps, action);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void eachUserTypeInReverseOrder(
|
||||||
|
UserTypeOperations userTypeOps, Consumer<? super HelenusEntity> action) {
|
||||||
|
ArrayDeque<HelenusEntity> deque = new ArrayDeque<>();
|
||||||
|
eachUserTypeInOrder(userTypeOps, e -> deque.addFirst(e));
|
||||||
|
deque
|
||||||
|
.stream()
|
||||||
|
.forEach(
|
||||||
|
e -> {
|
||||||
|
action.accept(e);
|
||||||
|
});
|
||||||
|
/*
|
||||||
|
Set<HelenusEntity> processedSet = new HashSet<HelenusEntity>();
|
||||||
|
Set<HelenusEntity> stack = new HashSet<HelenusEntity>();
|
||||||
|
|
||||||
|
sessionRepository.entities().stream()
|
||||||
|
.filter(e -> e.getType() == HelenusEntityType.UDT)
|
||||||
|
.collect(Collectors.toCollection(ArrayDeque::new))
|
||||||
|
.descendingIterator()
|
||||||
|
.forEachRemaining(e -> {
|
||||||
|
stack.clear();
|
||||||
|
eachUserTypeInRecursion(e, processedSet, stack, userTypeOps, action);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private void eachUserTypeInRecursion(
|
||||||
|
HelenusEntity e,
|
||||||
|
Set<HelenusEntity> processedSet,
|
||||||
|
Set<HelenusEntity> stack,
|
||||||
|
UserTypeOperations userTypeOps,
|
||||||
|
Consumer<? super HelenusEntity> action) {
|
||||||
|
|
||||||
|
stack.add(e);
|
||||||
|
|
||||||
|
Collection<HelenusEntity> createBefore = sessionRepository.getUserTypeUses(e);
|
||||||
|
|
||||||
|
for (HelenusEntity be : createBefore) {
|
||||||
|
if (!processedSet.contains(be) && !stack.contains(be)) {
|
||||||
|
eachUserTypeInRecursion(be, processedSet, stack, userTypeOps, action);
|
||||||
|
processedSet.add(be);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
if (!processedSet.contains(e)) {
|
||||||
public String usingKeyspace() {
|
action.accept(e);
|
||||||
return usingKeyspace;
|
processedSet.add(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private KeyspaceMetadata getKeyspaceMetadata() {
|
||||||
public Executor getExecutor() {
|
if (keyspaceMetadata == null) {
|
||||||
return executor;
|
keyspaceMetadata =
|
||||||
|
session.getCluster().getMetadata().getKeyspace(usingKeyspace.toLowerCase());
|
||||||
}
|
}
|
||||||
|
return keyspaceMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private TableMetadata getTableMetadata(HelenusEntity entity) {
|
||||||
public SessionRepository getSessionRepository() {
|
return getKeyspaceMetadata().getTable(entity.getName().getName());
|
||||||
throw new HelenusException("not expected to call");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private UserType getUserType(HelenusEntity entity) {
|
||||||
public ColumnValueProvider getValueProvider() {
|
return getKeyspaceMetadata().getUserType(entity.getName().getName());
|
||||||
throw new HelenusException("not expected to call");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ColumnValuePreparer getValuePreparer() {
|
|
||||||
throw new HelenusException("not expected to call");
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer showCql() {
|
|
||||||
this.showCql = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer showCql(boolean enabled) {
|
|
||||||
this.showCql = enabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer metricRegistry(MetricRegistry metricRegistry) {
|
|
||||||
this.metricRegistry = metricRegistry;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer zipkinTracer(Tracer tracer) {
|
|
||||||
this.zipkinTracer = tracer;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer consistencyLevel(ConsistencyLevel consistencyLevel) {
|
|
||||||
this.consistencyLevel = consistencyLevel;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConsistencyLevel getDefaultConsistencyLevel() {
|
|
||||||
return consistencyLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PrintStream getPrintStream() {
|
|
||||||
return printStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer printTo(PrintStream out) {
|
|
||||||
this.printStream = out;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer withExecutor(Executor executor) {
|
|
||||||
Objects.requireNonNull(executor, "empty executor");
|
|
||||||
this.executor = executor;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer withCachingExecutor() {
|
|
||||||
this.executor = Executors.newCachedThreadPool();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer dropUnusedColumns(boolean enabled) {
|
|
||||||
this.dropUnusedColumns = enabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer dropUnusedIndexes(boolean enabled) {
|
|
||||||
this.dropUnusedIndexes = enabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer withCodecRegistry(CodecRegistry registry) {
|
|
||||||
this.registry = registry;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isShowCql() {
|
|
||||||
return showCql;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer addPackage(String packageName) {
|
|
||||||
try {
|
|
||||||
PackageUtil.getClasses(packageName).stream().filter(c -> c.isInterface() && !c.isAnnotation())
|
|
||||||
.forEach(initList::add);
|
|
||||||
}
|
|
||||||
catch (IOException | ClassNotFoundException e) {
|
|
||||||
throw new HelenusException("fail to add package " + packageName, e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer add(Object... dsls) {
|
|
||||||
Objects.requireNonNull(dsls, "dsls is empty");
|
|
||||||
int len = dsls.length;
|
|
||||||
for (int i = 0; i != len; ++i) {
|
|
||||||
Object obj = Objects.requireNonNull(dsls[i], "element " + i + " is empty");
|
|
||||||
initList.add(obj);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer autoValidate() {
|
|
||||||
this.autoDdl = AutoDdl.VALIDATE;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer autoUpdate() {
|
|
||||||
this.autoDdl = AutoDdl.UPDATE;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer autoCreate() {
|
|
||||||
this.autoDdl = AutoDdl.CREATE;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer autoCreateDrop() {
|
|
||||||
this.autoDdl = AutoDdl.CREATE_DROP;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer auto(AutoDdl autoDdl) {
|
|
||||||
this.autoDdl = autoDdl;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer use(String keyspace) {
|
|
||||||
session.execute(SchemaUtil.use(keyspace, false));
|
|
||||||
this.usingKeyspace = keyspace;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionInitializer use(String keyspace, boolean forceQuote) {
|
|
||||||
session.execute(SchemaUtil.use(keyspace, forceQuote));
|
|
||||||
this.usingKeyspace = keyspace;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void singleton() {
|
|
||||||
|
|
||||||
Helenus.setSession(get());
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized HelenusSession get() {
|
|
||||||
initialize();
|
|
||||||
return new HelenusSession(session, usingKeyspace, registry, showCql, printStream, sessionRepository, executor,
|
|
||||||
autoDdl == AutoDdl.CREATE_DROP, consistencyLevel, metricRegistry, zipkinTracer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initialize() {
|
|
||||||
|
|
||||||
Objects.requireNonNull(usingKeyspace, "please define keyspace by 'use' operator");
|
|
||||||
|
|
||||||
initList.forEach(dsl -> sessionRepository.add(dsl));
|
|
||||||
|
|
||||||
TableOperations tableOps = new TableOperations(this, dropUnusedColumns, dropUnusedIndexes);
|
|
||||||
UserTypeOperations userTypeOps = new UserTypeOperations(this, dropUnusedColumns);
|
|
||||||
|
|
||||||
switch (autoDdl) {
|
|
||||||
|
|
||||||
case CREATE_DROP:
|
|
||||||
|
|
||||||
// Drop tables first, otherwise a `DROP TYPE ...` will fail as the type is still referenced
|
|
||||||
// by a table.
|
|
||||||
sessionRepository.entities().stream().filter(e -> e.getType() == HelenusEntityType.TABLE)
|
|
||||||
.forEach(e -> tableOps.dropTable(e));
|
|
||||||
|
|
||||||
eachUserTypeInReverseOrder(userTypeOps, e -> userTypeOps.dropUserType(e));
|
|
||||||
|
|
||||||
// FALLTHRU to CREATE case (read: the absence of a `break;` statement here is intentional!)
|
|
||||||
case CREATE:
|
|
||||||
|
|
||||||
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.createUserType(e));
|
|
||||||
|
|
||||||
sessionRepository.entities().stream().filter(e -> e.getType() == HelenusEntityType.TABLE)
|
|
||||||
.forEach(e -> tableOps.createTable(e));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALIDATE:
|
|
||||||
|
|
||||||
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.validateUserType(getUserType(e), e));
|
|
||||||
|
|
||||||
sessionRepository.entities().stream().filter(e -> e.getType() == HelenusEntityType.TABLE)
|
|
||||||
.forEach(e -> tableOps.validateTable(getTableMetadata(e), e));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UPDATE:
|
|
||||||
|
|
||||||
eachUserTypeInOrder(userTypeOps, e -> userTypeOps.updateUserType(getUserType(e), e));
|
|
||||||
|
|
||||||
sessionRepository.entities().stream().filter(e -> e.getType() == HelenusEntityType.TABLE)
|
|
||||||
.forEach(e -> tableOps.updateTable(getTableMetadata(e), e));
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyspaceMetadata km = getKeyspaceMetadata();
|
|
||||||
|
|
||||||
for (UserType userType : km.getUserTypes()) {
|
|
||||||
sessionRepository.addUserType(userType.getTypeName(), userType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void eachUserTypeInOrder(UserTypeOperations userTypeOps, Consumer<? super HelenusEntity> action) {
|
|
||||||
|
|
||||||
Set<HelenusEntity> processedSet = new HashSet<HelenusEntity>();
|
|
||||||
Set<HelenusEntity> stack = new HashSet<HelenusEntity>();
|
|
||||||
|
|
||||||
sessionRepository.entities().stream().filter(e -> e.getType() == HelenusEntityType.UDT).forEach(e -> {
|
|
||||||
stack.clear();
|
|
||||||
eachUserTypeInRecursion(e, processedSet, stack, userTypeOps, action);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void eachUserTypeInReverseOrder(UserTypeOperations userTypeOps, Consumer<? super HelenusEntity> action) {
|
|
||||||
ArrayDeque<HelenusEntity> deque = new ArrayDeque<>();
|
|
||||||
eachUserTypeInOrder(userTypeOps, e -> deque.addFirst(e));
|
|
||||||
deque.stream().forEach(e -> {
|
|
||||||
action.accept(e);
|
|
||||||
});
|
|
||||||
/*
|
|
||||||
Set<HelenusEntity> processedSet = new HashSet<HelenusEntity>();
|
|
||||||
Set<HelenusEntity> stack = new HashSet<HelenusEntity>();
|
|
||||||
|
|
||||||
sessionRepository.entities().stream()
|
|
||||||
.filter(e -> e.getType() == HelenusEntityType.UDT)
|
|
||||||
.collect(Collectors.toCollection(ArrayDeque::new))
|
|
||||||
.descendingIterator()
|
|
||||||
.forEachRemaining(e -> {
|
|
||||||
stack.clear();
|
|
||||||
eachUserTypeInRecursion(e, processedSet, stack, userTypeOps, action);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private void eachUserTypeInRecursion(HelenusEntity e, Set<HelenusEntity> processedSet, Set<HelenusEntity> stack,
|
|
||||||
UserTypeOperations userTypeOps, Consumer<? super HelenusEntity> action) {
|
|
||||||
|
|
||||||
stack.add(e);
|
|
||||||
|
|
||||||
Collection<HelenusEntity> createBefore = sessionRepository.getUserTypeUses(e);
|
|
||||||
|
|
||||||
for (HelenusEntity be : createBefore) {
|
|
||||||
if (!processedSet.contains(be) && !stack.contains(be)) {
|
|
||||||
eachUserTypeInRecursion(be, processedSet, stack, userTypeOps, action);
|
|
||||||
processedSet.add(be);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!processedSet.contains(e)) {
|
|
||||||
action.accept(e);
|
|
||||||
processedSet.add(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeyspaceMetadata getKeyspaceMetadata() {
|
|
||||||
if (keyspaceMetadata == null) {
|
|
||||||
keyspaceMetadata = session.getCluster().getMetadata().getKeyspace(usingKeyspace.toLowerCase());
|
|
||||||
}
|
|
||||||
return keyspaceMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TableMetadata getTableMetadata(HelenusEntity entity) {
|
|
||||||
return getKeyspaceMetadata().getTable(entity.getName().getName());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserType getUserType(HelenusEntity entity) {
|
|
||||||
return getKeyspaceMetadata().getUserType(entity.getName().getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,32 +15,30 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.UserType;
|
import com.datastax.driver.core.UserType;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import java.util.Collection;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
|
||||||
public final class SessionRepository {
|
public final class SessionRepository {
|
||||||
|
|
||||||
private final ImmutableMap<String, UserType> userTypeMap;
|
private final ImmutableMap<String, UserType> userTypeMap;
|
||||||
|
|
||||||
private final ImmutableMap<Class<?>, HelenusEntity> entityMap;
|
private final ImmutableMap<Class<?>, HelenusEntity> entityMap;
|
||||||
|
|
||||||
public SessionRepository(SessionRepositoryBuilder builder) {
|
public SessionRepository(SessionRepositoryBuilder builder) {
|
||||||
|
|
||||||
userTypeMap = ImmutableMap.<String, UserType>builder().putAll(builder.getUserTypeMap()).build();
|
userTypeMap = ImmutableMap.<String, UserType>builder().putAll(builder.getUserTypeMap()).build();
|
||||||
|
|
||||||
entityMap = ImmutableMap.<Class<?>, HelenusEntity>builder().putAll(builder.getEntityMap()).build();
|
entityMap =
|
||||||
}
|
ImmutableMap.<Class<?>, HelenusEntity>builder().putAll(builder.getEntityMap()).build();
|
||||||
|
}
|
||||||
|
|
||||||
public UserType findUserType(String name) {
|
public UserType findUserType(String name) {
|
||||||
return userTypeMap.get(name.toLowerCase());
|
return userTypeMap.get(name.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<HelenusEntity> entities() {
|
|
||||||
return entityMap.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public Collection<HelenusEntity> entities() {
|
||||||
|
return entityMap.values();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.Session;
|
import com.datastax.driver.core.Session;
|
||||||
import com.datastax.driver.core.UDTValue;
|
import com.datastax.driver.core.UDTValue;
|
||||||
import com.datastax.driver.core.UserType;
|
import com.datastax.driver.core.UserType;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusEntityType;
|
import net.helenus.mapping.HelenusEntityType;
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
|
@ -35,118 +33,112 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class SessionRepositoryBuilder {
|
public final class SessionRepositoryBuilder {
|
||||||
|
|
||||||
private static final Optional<HelenusEntityType> OPTIONAL_UDT = Optional.of(HelenusEntityType.UDT);
|
private static final Optional<HelenusEntityType> OPTIONAL_UDT =
|
||||||
|
Optional.of(HelenusEntityType.UDT);
|
||||||
|
|
||||||
private final Map<Class<?>, HelenusEntity> entityMap = new HashMap<Class<?>, HelenusEntity>();
|
private final Map<Class<?>, HelenusEntity> entityMap = new HashMap<Class<?>, HelenusEntity>();
|
||||||
|
|
||||||
private final Map<String, UserType> userTypeMap = new HashMap<String, UserType>();
|
private final Map<String, UserType> userTypeMap = new HashMap<String, UserType>();
|
||||||
|
|
||||||
private final Multimap<HelenusEntity, HelenusEntity> userTypeUsesMap = HashMultimap.create();
|
private final Multimap<HelenusEntity, HelenusEntity> userTypeUsesMap = HashMultimap.create();
|
||||||
|
|
||||||
private final Session session;
|
private final Session session;
|
||||||
|
|
||||||
|
SessionRepositoryBuilder(Session session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
SessionRepositoryBuilder(Session session) {
|
public SessionRepository build() {
|
||||||
this.session = session;
|
return new SessionRepository(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionRepository build() {
|
public Collection<HelenusEntity> getUserTypeUses(HelenusEntity udtName) {
|
||||||
return new SessionRepository(this);
|
return userTypeUsesMap.get(udtName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<HelenusEntity> getUserTypeUses(HelenusEntity udtName) {
|
public Collection<HelenusEntity> entities() {
|
||||||
return userTypeUsesMap.get(udtName);
|
return entityMap.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<HelenusEntity> entities() {
|
protected Map<Class<?>, HelenusEntity> getEntityMap() {
|
||||||
return entityMap.values();
|
return entityMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<Class<?>, HelenusEntity> getEntityMap() {
|
protected Map<String, UserType> getUserTypeMap() {
|
||||||
return entityMap;
|
return userTypeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, UserType> getUserTypeMap() {
|
public void addUserType(String name, UserType userType) {
|
||||||
return userTypeMap;
|
userTypeMap.putIfAbsent(name.toLowerCase(), userType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addUserType(String name, UserType userType) {
|
public HelenusEntity add(Object dsl) {
|
||||||
userTypeMap.putIfAbsent(name.toLowerCase(), userType);
|
return add(dsl, Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusEntity add(Object dsl) {
|
public void addEntity(HelenusEntity entity) {
|
||||||
return add(dsl, Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEntity(HelenusEntity entity) {
|
HelenusEntity concurrentEntity = entityMap.putIfAbsent(entity.getMappingInterface(), entity);
|
||||||
|
|
||||||
HelenusEntity concurrentEntity = entityMap.putIfAbsent(entity.getMappingInterface(), entity);
|
if (concurrentEntity == null) {
|
||||||
|
addUserDefinedTypes(entity.getOrderedProperties());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (concurrentEntity == null) {
|
public HelenusEntity add(Object dsl, Optional<HelenusEntityType> type) {
|
||||||
addUserDefinedTypes(entity.getOrderedProperties());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
HelenusEntity helenusEntity = Helenus.resolve(dsl, session.getCluster().getMetadata());
|
||||||
|
|
||||||
public HelenusEntity add(Object dsl, Optional<HelenusEntityType> type) {
|
Class<?> iface = helenusEntity.getMappingInterface();
|
||||||
|
|
||||||
HelenusEntity helenusEntity = Helenus.resolve(dsl, session.getCluster().getMetadata());
|
HelenusEntity entity = entityMap.get(iface);
|
||||||
|
|
||||||
Class<?> iface = helenusEntity.getMappingInterface();
|
if (entity == null) {
|
||||||
|
|
||||||
HelenusEntity entity = entityMap.get(iface);
|
entity = helenusEntity;
|
||||||
|
|
||||||
if (entity == null) {
|
if (type.isPresent() && entity.getType() != type.get()) {
|
||||||
|
throw new HelenusMappingException(
|
||||||
|
"unexpected entity type " + entity.getType() + " for " + entity);
|
||||||
|
}
|
||||||
|
|
||||||
entity = helenusEntity;
|
HelenusEntity concurrentEntity = entityMap.putIfAbsent(iface, entity);
|
||||||
|
|
||||||
if (type.isPresent() && entity.getType() != type.get()) {
|
if (concurrentEntity == null) {
|
||||||
throw new HelenusMappingException("unexpected entity type " + entity.getType() + " for " + entity);
|
addUserDefinedTypes(entity.getOrderedProperties());
|
||||||
}
|
} else {
|
||||||
|
entity = concurrentEntity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HelenusEntity concurrentEntity = entityMap.putIfAbsent(iface, entity);
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
if (concurrentEntity == null) {
|
private void addUserDefinedTypes(Collection<HelenusProperty> props) {
|
||||||
addUserDefinedTypes(entity.getOrderedProperties());
|
|
||||||
} else {
|
|
||||||
entity = concurrentEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
for (HelenusProperty prop : props) {
|
||||||
|
|
||||||
return entity;
|
AbstractDataType type = prop.getDataType();
|
||||||
}
|
|
||||||
|
|
||||||
private void addUserDefinedTypes(Collection<HelenusProperty> props) {
|
if (type instanceof DTDataType) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (HelenusProperty prop : props) {
|
if (!UDTValue.class.isAssignableFrom(prop.getJavaType())) {
|
||||||
|
|
||||||
AbstractDataType type = prop.getDataType();
|
for (Class<?> udtClass : type.getTypeArguments()) {
|
||||||
|
|
||||||
if (type instanceof DTDataType) {
|
if (UDTValue.class.isAssignableFrom(udtClass)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UDTValue.class.isAssignableFrom(prop.getJavaType())) {
|
HelenusEntity addedUserType = add(udtClass, OPTIONAL_UDT);
|
||||||
|
|
||||||
for (Class<?> udtClass : type.getTypeArguments()) {
|
|
||||||
|
|
||||||
if (UDTValue.class.isAssignableFrom(udtClass)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
HelenusEntity addedUserType = add(udtClass, OPTIONAL_UDT);
|
|
||||||
|
|
||||||
if (HelenusEntityType.UDT == prop.getEntity().getType()) {
|
|
||||||
userTypeUsesMap.put(prop.getEntity(), addedUserType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (HelenusEntityType.UDT == prop.getEntity().getType()) {
|
||||||
|
userTypeUsesMap.put(prop.getEntity(), addedUserType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,74 +15,73 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.TableMetadata;
|
import com.datastax.driver.core.TableMetadata;
|
||||||
import com.datastax.driver.core.schemabuilder.SchemaStatement;
|
import com.datastax.driver.core.schemabuilder.SchemaStatement;
|
||||||
|
import java.util.List;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
public final class TableOperations {
|
public final class TableOperations {
|
||||||
|
|
||||||
private final AbstractSessionOperations sessionOps;
|
private final AbstractSessionOperations sessionOps;
|
||||||
private final boolean dropUnusedColumns;
|
private final boolean dropUnusedColumns;
|
||||||
private final boolean dropUnusedIndexes;
|
private final boolean dropUnusedIndexes;
|
||||||
|
|
||||||
public TableOperations(AbstractSessionOperations sessionOps, boolean dropUnusedColumns, boolean dropUnusedIndexes) {
|
public TableOperations(
|
||||||
this.sessionOps = sessionOps;
|
AbstractSessionOperations sessionOps, boolean dropUnusedColumns, boolean dropUnusedIndexes) {
|
||||||
this.dropUnusedColumns = dropUnusedColumns;
|
this.sessionOps = sessionOps;
|
||||||
this.dropUnusedIndexes = dropUnusedIndexes;
|
this.dropUnusedColumns = dropUnusedColumns;
|
||||||
}
|
this.dropUnusedIndexes = dropUnusedIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
public void createTable(HelenusEntity entity) {
|
public void createTable(HelenusEntity entity) {
|
||||||
|
|
||||||
sessionOps.execute(SchemaUtil.createTable(entity), true);
|
sessionOps.execute(SchemaUtil.createTable(entity), true);
|
||||||
|
|
||||||
executeBatch(SchemaUtil.createIndexes(entity));
|
executeBatch(SchemaUtil.createIndexes(entity));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public void dropTable(HelenusEntity entity) {
|
||||||
|
|
||||||
public void dropTable(HelenusEntity entity) {
|
sessionOps.execute(SchemaUtil.dropTable(entity), true);
|
||||||
|
}
|
||||||
|
|
||||||
sessionOps.execute(SchemaUtil.dropTable(entity), true);
|
public void validateTable(TableMetadata tmd, HelenusEntity entity) {
|
||||||
|
|
||||||
|
if (tmd == null) {
|
||||||
|
throw new HelenusException(
|
||||||
|
"table not exists " + entity.getName() + "for entity " + entity.getMappingInterface());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateTable(TableMetadata tmd, HelenusEntity entity) {
|
List<SchemaStatement> list = SchemaUtil.alterTable(tmd, entity, dropUnusedColumns);
|
||||||
|
|
||||||
if (tmd == null) {
|
list.addAll(SchemaUtil.alterIndexes(tmd, entity, dropUnusedIndexes));
|
||||||
throw new HelenusException(
|
|
||||||
"table not exists " + entity.getName() + "for entity " + entity.getMappingInterface());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<SchemaStatement> list = SchemaUtil.alterTable(tmd, entity, dropUnusedColumns);
|
if (!list.isEmpty()) {
|
||||||
|
throw new HelenusException(
|
||||||
|
"schema changed for entity "
|
||||||
|
+ entity.getMappingInterface()
|
||||||
|
+ ", apply this command: "
|
||||||
|
+ list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
list.addAll(SchemaUtil.alterIndexes(tmd, entity, dropUnusedIndexes));
|
public void updateTable(TableMetadata tmd, HelenusEntity entity) {
|
||||||
|
|
||||||
if (!list.isEmpty()) {
|
if (tmd == null) {
|
||||||
throw new HelenusException(
|
createTable(entity);
|
||||||
"schema changed for entity " + entity.getMappingInterface() + ", apply this command: " + list);
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void updateTable(TableMetadata tmd, HelenusEntity entity) {
|
executeBatch(SchemaUtil.alterTable(tmd, entity, dropUnusedColumns));
|
||||||
|
executeBatch(SchemaUtil.alterIndexes(tmd, entity, dropUnusedIndexes));
|
||||||
|
}
|
||||||
|
|
||||||
if (tmd == null) {
|
private void executeBatch(List<SchemaStatement> list) {
|
||||||
createTable(entity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
executeBatch(SchemaUtil.alterTable(tmd, entity, dropUnusedColumns));
|
|
||||||
executeBatch(SchemaUtil.alterIndexes(tmd, entity, dropUnusedIndexes));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executeBatch(List<SchemaStatement> list) {
|
|
||||||
|
|
||||||
list.forEach(s -> {
|
|
||||||
sessionOps.execute(s, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
list.forEach(
|
||||||
|
s -> {
|
||||||
|
sessionOps.execute(s, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +1,59 @@
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import com.diffplug.common.base.Errors;
|
import com.diffplug.common.base.Errors;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/** Encapsulates the concept of a "transaction" as a unit-of-work. */
|
||||||
* Encapsulates the concept of a "transaction" as a unit-of-work.
|
|
||||||
*/
|
|
||||||
public class UnitOfWork {
|
public class UnitOfWork {
|
||||||
|
|
||||||
private final HelenusSession session;
|
private final HelenusSession session;
|
||||||
private ArrayList<UnitOfWork> nested;
|
private ArrayList<UnitOfWork> nested;
|
||||||
|
|
||||||
UnitOfWork(HelenusSession session) {
|
UnitOfWork(HelenusSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
// log.record(txn::start)
|
// log.record(txn::start)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the beginning of a transactional section of work. Will write a record to the shared
|
||||||
|
* write-ahead log.
|
||||||
|
*
|
||||||
|
* @return the handle used to commit or abort the work.
|
||||||
|
*/
|
||||||
|
public UnitOfWork begin() {
|
||||||
|
if (nested == null) {
|
||||||
|
nested = new ArrayList<UnitOfWork>();
|
||||||
}
|
}
|
||||||
|
UnitOfWork unitOfWork = new UnitOfWork(session);
|
||||||
|
nested.add(unitOfWork);
|
||||||
|
return unitOfWork;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the beginning of a transactional section of work. Will write a record
|
* Checks to see if the work performed between calling begin and now can be committed or not.
|
||||||
* to the shared write-ahead log.
|
*
|
||||||
*
|
* @return a function from which to chain work that only happens when commit is successful
|
||||||
* @return the handle used to commit or abort the work.
|
* @throws ConflictingUnitOfWorkException when the work overlaps with other concurrent writers.
|
||||||
*/
|
*/
|
||||||
public UnitOfWork begin() {
|
public Function<Void, Void> commit() throws ConflictingUnitOfWorkException {
|
||||||
if (nested == null) {
|
if (nested != null) {
|
||||||
nested = new ArrayList<UnitOfWork>();
|
nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit));
|
||||||
}
|
|
||||||
UnitOfWork unitOfWork = new UnitOfWork(session);
|
|
||||||
nested.add(unitOfWork);
|
|
||||||
return unitOfWork;
|
|
||||||
}
|
}
|
||||||
|
// log.record(txn::provisionalCommit)
|
||||||
|
// examine log for conflicts in read-set and write-set between begin and provisional commit
|
||||||
|
// if (conflict) { throw new ConflictingUnitOfWorkException(this) }
|
||||||
|
// else return function so as to enable commit.andThen(() -> { do something iff commit was successful; })
|
||||||
|
return Function.<Void>identity();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/** Explicitly discard the work and mark it as as such in the log. */
|
||||||
* Checks to see if the work performed between calling begin and now can be
|
public void abort() {
|
||||||
* committed or not.
|
// log.record(txn::abort)
|
||||||
*
|
// cache.invalidateSince(txn::start time)
|
||||||
* @return a function from which to chain work that only happens when commit is successful
|
}
|
||||||
* @throws ConflictingUnitOfWorkException when the work overlaps with other concurrent writers.
|
|
||||||
*/
|
|
||||||
public Function<Void, Void> commit() throws ConflictingUnitOfWorkException {
|
|
||||||
if (nested != null) {
|
|
||||||
nested.forEach((uow) -> Errors.rethrow().wrap(uow::commit));
|
|
||||||
}
|
|
||||||
// log.record(txn::provisionalCommit)
|
|
||||||
// examine log for conflicts in read-set and write-set between begin and provisional commit
|
|
||||||
// if (conflict) { throw new ConflictingUnitOfWorkException(this) }
|
|
||||||
// else return function so as to enable commit.andThen(() -> { do something iff commit was successful; })
|
|
||||||
return Function.<Void>identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Explicitly discard the work and mark it as as such in the log.
|
|
||||||
*/
|
|
||||||
public void abort() {
|
|
||||||
// log.record(txn::abort)
|
|
||||||
// cache.invalidateSince(txn::start time)
|
|
||||||
}
|
|
||||||
|
|
||||||
public String describeConflicts() {
|
|
||||||
return "it's complex...";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public String describeConflicts() {
|
||||||
|
return "it's complex...";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,69 +15,65 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core;
|
package net.helenus.core;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.UserType;
|
import com.datastax.driver.core.UserType;
|
||||||
import com.datastax.driver.core.schemabuilder.SchemaStatement;
|
import com.datastax.driver.core.schemabuilder.SchemaStatement;
|
||||||
|
import java.util.List;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
public final class UserTypeOperations {
|
public final class UserTypeOperations {
|
||||||
|
|
||||||
private final AbstractSessionOperations sessionOps;
|
private final AbstractSessionOperations sessionOps;
|
||||||
private final boolean dropUnusedColumns;
|
private final boolean dropUnusedColumns;
|
||||||
|
|
||||||
public UserTypeOperations(AbstractSessionOperations sessionOps, boolean dropUnusedColumns) {
|
public UserTypeOperations(AbstractSessionOperations sessionOps, boolean dropUnusedColumns) {
|
||||||
this.sessionOps = sessionOps;
|
this.sessionOps = sessionOps;
|
||||||
this.dropUnusedColumns = dropUnusedColumns;
|
this.dropUnusedColumns = dropUnusedColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createUserType(HelenusEntity entity) {
|
public void createUserType(HelenusEntity entity) {
|
||||||
|
|
||||||
sessionOps.execute(SchemaUtil.createUserType(entity), true);
|
sessionOps.execute(SchemaUtil.createUserType(entity), true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public void dropUserType(HelenusEntity entity) {
|
||||||
|
|
||||||
public void dropUserType(HelenusEntity entity) {
|
sessionOps.execute(SchemaUtil.dropUserType(entity), true);
|
||||||
|
}
|
||||||
|
|
||||||
sessionOps.execute(SchemaUtil.dropUserType(entity), true);
|
public void validateUserType(UserType userType, HelenusEntity entity) {
|
||||||
|
|
||||||
|
if (userType == null) {
|
||||||
|
throw new HelenusException(
|
||||||
|
"userType not exists " + entity.getName() + "for entity " + entity.getMappingInterface());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateUserType(UserType userType, HelenusEntity entity) {
|
List<SchemaStatement> list = SchemaUtil.alterUserType(userType, entity, dropUnusedColumns);
|
||||||
|
|
||||||
if (userType == null) {
|
if (!list.isEmpty()) {
|
||||||
throw new HelenusException(
|
throw new HelenusException(
|
||||||
"userType not exists " + entity.getName() + "for entity " + entity.getMappingInterface());
|
"schema changed for entity "
|
||||||
}
|
+ entity.getMappingInterface()
|
||||||
|
+ ", apply this command: "
|
||||||
|
+ list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<SchemaStatement> list = SchemaUtil.alterUserType(userType, entity, dropUnusedColumns);
|
public void updateUserType(UserType userType, HelenusEntity entity) {
|
||||||
|
|
||||||
if (!list.isEmpty()) {
|
if (userType == null) {
|
||||||
throw new HelenusException(
|
createUserType(entity);
|
||||||
"schema changed for entity " + entity.getMappingInterface() + ", apply this command: " + list);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
executeBatch(SchemaUtil.alterUserType(userType, entity, dropUnusedColumns));
|
||||||
|
}
|
||||||
|
|
||||||
public void updateUserType(UserType userType, HelenusEntity entity) {
|
private void executeBatch(List<SchemaStatement> list) {
|
||||||
|
|
||||||
if (userType == null) {
|
|
||||||
createUserType(entity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
executeBatch(SchemaUtil.alterUserType(userType, entity, dropUnusedColumns));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executeBatch(List<SchemaStatement> list) {
|
|
||||||
|
|
||||||
list.forEach(s -> {
|
|
||||||
sessionOps.execute(s, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
list.forEach(
|
||||||
|
s -> {
|
||||||
|
sessionOps.execute(s, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,4 @@ import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
public @interface Cacheable {
|
public @interface Cacheable {}
|
||||||
}
|
|
||||||
|
|
|
@ -4,14 +4,13 @@ import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import net.helenus.core.ConflictingUnitOfWorkException;
|
import net.helenus.core.ConflictingUnitOfWorkException;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface Retry {
|
public @interface Retry {
|
||||||
|
|
||||||
Class<? extends Exception>[] on() default ConflictingUnitOfWorkException.class;
|
Class<? extends Exception>[] on() default ConflictingUnitOfWorkException.class;
|
||||||
|
|
||||||
int times() default 3;
|
int times() default 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package net.helenus.core.aspect;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import net.helenus.core.annotation.Retry;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
@ -13,71 +13,69 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import net.helenus.core.annotation.Retry;
|
|
||||||
|
|
||||||
@Aspect
|
@Aspect
|
||||||
public class RetryConcurrentUnitOfWorkAspect {
|
public class RetryConcurrentUnitOfWorkAspect {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(RetryConcurrentUnitOfWorkAspect.class);
|
private static final Logger log = LoggerFactory.getLogger(RetryConcurrentUnitOfWorkAspect.class);
|
||||||
|
|
||||||
@Around("@annotation(net.helenus.core.annotations.Retry)")
|
@Around("@annotation(net.helenus.core.annotations.Retry)")
|
||||||
public Object retry(ProceedingJoinPoint pjp) throws Throwable {
|
public Object retry(ProceedingJoinPoint pjp) throws Throwable {
|
||||||
Retry retryAnnotation = getRetryAnnotation(pjp);
|
Retry retryAnnotation = getRetryAnnotation(pjp);
|
||||||
return (retryAnnotation != null) ? proceed(pjp, retryAnnotation) : proceed(pjp);
|
return (retryAnnotation != null) ? proceed(pjp, retryAnnotation) : proceed(pjp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object proceed(ProceedingJoinPoint pjp) throws Throwable {
|
private Object proceed(ProceedingJoinPoint pjp) throws Throwable {
|
||||||
return pjp.proceed();
|
return pjp.proceed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object proceed(ProceedingJoinPoint pjp, Retry retryAnnotation) throws Throwable {
|
private Object proceed(ProceedingJoinPoint pjp, Retry retryAnnotation) throws Throwable {
|
||||||
int times = retryAnnotation.times();
|
int times = retryAnnotation.times();
|
||||||
Class<? extends Throwable>[] retryOn = retryAnnotation.on();
|
Class<? extends Throwable>[] retryOn = retryAnnotation.on();
|
||||||
Assert.isTrue(times > 0, "@Retry{times} should be greater than 0!");
|
Assert.isTrue(times > 0, "@Retry{times} should be greater than 0!");
|
||||||
Assert.isTrue(retryOn.length > 0, "@Retry{on} should have at least one Throwable!");
|
Assert.isTrue(retryOn.length > 0, "@Retry{on} should have at least one Throwable!");
|
||||||
log.info("Proceed with {} retries on {}", times, Arrays.toString(retryOn));
|
log.info("Proceed with {} retries on {}", times, Arrays.toString(retryOn));
|
||||||
return tryProceeding(pjp, times, retryOn);
|
return tryProceeding(pjp, times, retryOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object tryProceeding(ProceedingJoinPoint pjp, int times, Class<? extends Throwable>[] retryOn)
|
private Object tryProceeding(
|
||||||
throws Throwable {
|
ProceedingJoinPoint pjp, int times, Class<? extends Throwable>[] retryOn) throws Throwable {
|
||||||
try {
|
try {
|
||||||
return proceed(pjp);
|
return proceed(pjp);
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
if (isRetryThrowable(throwable, retryOn) && times-- > 0) {
|
if (isRetryThrowable(throwable, retryOn) && times-- > 0) {
|
||||||
log.info("Conflict detected, {} remaining retries on {}", times, Arrays.toString(retryOn));
|
log.info("Conflict detected, {} remaining retries on {}", times, Arrays.toString(retryOn));
|
||||||
return tryProceeding(pjp, times, retryOn);
|
return tryProceeding(pjp, times, retryOn);
|
||||||
}
|
}
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRetryThrowable(Throwable throwable, Class<? extends Throwable>[] retryOn) {
|
private boolean isRetryThrowable(Throwable throwable, Class<? extends Throwable>[] retryOn) {
|
||||||
Throwable[] causes = ExceptionUtils.getThrowables(throwable);
|
Throwable[] causes = ExceptionUtils.getThrowables(throwable);
|
||||||
for (Throwable cause : causes) {
|
for (Throwable cause : causes) {
|
||||||
for (Class<? extends Throwable> retryThrowable : retryOn) {
|
for (Class<? extends Throwable> retryThrowable : retryOn) {
|
||||||
if (retryThrowable.isAssignableFrom(cause.getClass())) {
|
if (retryThrowable.isAssignableFrom(cause.getClass())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Retry getRetryAnnotation(ProceedingJoinPoint pjp) throws NoSuchMethodException {
|
private Retry getRetryAnnotation(ProceedingJoinPoint pjp) throws NoSuchMethodException {
|
||||||
MethodSignature signature = (MethodSignature) pjp.getSignature();
|
MethodSignature signature = (MethodSignature) pjp.getSignature();
|
||||||
Method method = signature.getMethod();
|
Method method = signature.getMethod();
|
||||||
Retry retryAnnotation = AnnotationUtils.findAnnotation(method, Retry.class);
|
Retry retryAnnotation = AnnotationUtils.findAnnotation(method, Retry.class);
|
||||||
|
|
||||||
if (retryAnnotation != null) {
|
if (retryAnnotation != null) {
|
||||||
return retryAnnotation;
|
return retryAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class[] argClasses = new Class[pjp.getArgs().length];
|
Class[] argClasses = new Class[pjp.getArgs().length];
|
||||||
for (int i = 0; i < pjp.getArgs().length; i++) {
|
for (int i = 0; i < pjp.getArgs().length; i++) {
|
||||||
argClasses[i] = pjp.getArgs()[i].getClass();
|
argClasses[i] = pjp.getArgs()[i].getClass();
|
||||||
}
|
}
|
||||||
method = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), argClasses);
|
method = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), argClasses);
|
||||||
return AnnotationUtils.findAnnotation(method, Retry.class);
|
return AnnotationUtils.findAnnotation(method, Retry.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,95 +17,92 @@ package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
|
|
||||||
public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperation<E, O>>
|
public abstract class AbstractFilterOperation<E, O extends AbstractFilterOperation<E, O>>
|
||||||
extends
|
extends AbstractOperation<E, O> {
|
||||||
AbstractOperation<E, O> {
|
|
||||||
|
|
||||||
protected List<Filter<?>> filters = null;
|
protected List<Filter<?>> filters = null;
|
||||||
protected List<Filter<?>> ifFilters = null;
|
protected List<Filter<?>> ifFilters = null;
|
||||||
|
|
||||||
public AbstractFilterOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractFilterOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O where(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, postulate));
|
addFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Getter<V> getter, Operator operator, V val) {
|
public <V> O where(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, operator, val));
|
addFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Filter<V> filter) {
|
public <V> O where(Filter<V> filter) {
|
||||||
|
|
||||||
addFilter(filter);
|
addFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O and(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, postulate));
|
addFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Getter<V> getter, Operator operator, V val) {
|
public <V> O and(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, operator, val));
|
addFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Filter<V> filter) {
|
public <V> O and(Filter<V> filter) {
|
||||||
|
|
||||||
addFilter(filter);
|
addFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O onlyIf(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addIfFilter(Filter.create(getter, postulate));
|
addIfFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Getter<V> getter, Operator operator, V val) {
|
public <V> O onlyIf(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addIfFilter(Filter.create(getter, operator, val));
|
addIfFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Filter<V> filter) {
|
public <V> O onlyIf(Filter<V> filter) {
|
||||||
|
|
||||||
addIfFilter(filter);
|
addIfFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFilter(Filter<?> filter) {
|
private void addFilter(Filter<?> filter) {
|
||||||
if (filters == null) {
|
if (filters == null) {
|
||||||
filters = new LinkedList<Filter<?>>();
|
filters = new LinkedList<Filter<?>>();
|
||||||
}
|
}
|
||||||
filters.add(filter);
|
filters.add(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIfFilter(Filter<?> filter) {
|
|
||||||
if (ifFilters == null) {
|
|
||||||
ifFilters = new LinkedList<Filter<?>>();
|
|
||||||
}
|
|
||||||
ifFilters.add(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void addIfFilter(Filter<?> filter) {
|
||||||
|
if (ifFilters == null) {
|
||||||
|
ifFilters = new LinkedList<Filter<?>>();
|
||||||
|
}
|
||||||
|
ifFilters.add(filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,95 +17,93 @@ package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
|
|
||||||
public abstract class AbstractFilterOptionalOperation<E, O extends AbstractFilterOptionalOperation<E, O>>
|
public abstract class AbstractFilterOptionalOperation<
|
||||||
extends
|
E, O extends AbstractFilterOptionalOperation<E, O>>
|
||||||
AbstractOptionalOperation<E, O> {
|
extends AbstractOptionalOperation<E, O> {
|
||||||
|
|
||||||
protected List<Filter<?>> filters = null;
|
protected List<Filter<?>> filters = null;
|
||||||
protected List<Filter<?>> ifFilters = null;
|
protected List<Filter<?>> ifFilters = null;
|
||||||
|
|
||||||
public AbstractFilterOptionalOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractFilterOptionalOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O where(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, postulate));
|
addFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Getter<V> getter, Operator operator, V val) {
|
public <V> O where(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, operator, val));
|
addFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Filter<V> filter) {
|
public <V> O where(Filter<V> filter) {
|
||||||
|
|
||||||
addFilter(filter);
|
addFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O and(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, postulate));
|
addFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Getter<V> getter, Operator operator, V val) {
|
public <V> O and(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, operator, val));
|
addFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Filter<V> filter) {
|
public <V> O and(Filter<V> filter) {
|
||||||
|
|
||||||
addFilter(filter);
|
addFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O onlyIf(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addIfFilter(Filter.create(getter, postulate));
|
addIfFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Getter<V> getter, Operator operator, V val) {
|
public <V> O onlyIf(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addIfFilter(Filter.create(getter, operator, val));
|
addIfFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Filter<V> filter) {
|
public <V> O onlyIf(Filter<V> filter) {
|
||||||
|
|
||||||
addIfFilter(filter);
|
addIfFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFilter(Filter<?> filter) {
|
private void addFilter(Filter<?> filter) {
|
||||||
if (filters == null) {
|
if (filters == null) {
|
||||||
filters = new LinkedList<Filter<?>>();
|
filters = new LinkedList<Filter<?>>();
|
||||||
}
|
}
|
||||||
filters.add(filter);
|
filters.add(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIfFilter(Filter<?> filter) {
|
|
||||||
if (ifFilters == null) {
|
|
||||||
ifFilters = new LinkedList<Filter<?>>();
|
|
||||||
}
|
|
||||||
ifFilters.add(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void addIfFilter(Filter<?> filter) {
|
||||||
|
if (ifFilters == null) {
|
||||||
|
ifFilters = new LinkedList<Filter<?>>();
|
||||||
|
}
|
||||||
|
ifFilters.add(filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,94 +17,93 @@ package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.helenus.core.*;
|
import net.helenus.core.*;
|
||||||
|
|
||||||
public abstract class AbstractFilterStreamOperation<E, O extends AbstractFilterStreamOperation<E, O>>
|
public abstract class AbstractFilterStreamOperation<
|
||||||
extends AbstractStreamOperation<E, O> {
|
E, O extends AbstractFilterStreamOperation<E, O>>
|
||||||
|
extends AbstractStreamOperation<E, O> {
|
||||||
|
|
||||||
protected List<Filter<?>> filters = null;
|
protected List<Filter<?>> filters = null;
|
||||||
protected List<Filter<?>> ifFilters = null;
|
protected List<Filter<?>> ifFilters = null;
|
||||||
|
|
||||||
public AbstractFilterStreamOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractFilterStreamOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O where(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, postulate));
|
addFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Getter<V> getter, Operator operator, V val) {
|
public <V> O where(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, operator, val));
|
addFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O where(Filter<V> filter) {
|
public <V> O where(Filter<V> filter) {
|
||||||
|
|
||||||
addFilter(filter);
|
addFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O and(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, postulate));
|
addFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Getter<V> getter, Operator operator, V val) {
|
public <V> O and(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addFilter(Filter.create(getter, operator, val));
|
addFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O and(Filter<V> filter) {
|
public <V> O and(Filter<V> filter) {
|
||||||
|
|
||||||
addFilter(filter);
|
addFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Getter<V> getter, Postulate<V> postulate) {
|
public <V> O onlyIf(Getter<V> getter, Postulate<V> postulate) {
|
||||||
|
|
||||||
addIfFilter(Filter.create(getter, postulate));
|
addIfFilter(Filter.create(getter, postulate));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Getter<V> getter, Operator operator, V val) {
|
public <V> O onlyIf(Getter<V> getter, Operator operator, V val) {
|
||||||
|
|
||||||
addIfFilter(Filter.create(getter, operator, val));
|
addIfFilter(Filter.create(getter, operator, val));
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> O onlyIf(Filter<V> filter) {
|
public <V> O onlyIf(Filter<V> filter) {
|
||||||
|
|
||||||
addIfFilter(filter);
|
addIfFilter(filter);
|
||||||
|
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFilter(Filter<?> filter) {
|
private void addFilter(Filter<?> filter) {
|
||||||
if (filters == null) {
|
if (filters == null) {
|
||||||
filters = new LinkedList<Filter<?>>();
|
filters = new LinkedList<Filter<?>>();
|
||||||
}
|
}
|
||||||
filters.add(filter);
|
filters.add(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIfFilter(Filter<?> filter) {
|
|
||||||
if (ifFilters == null) {
|
|
||||||
ifFilters = new LinkedList<Filter<?>>();
|
|
||||||
}
|
|
||||||
ifFilters.add(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void addIfFilter(Filter<?> filter) {
|
||||||
|
if (ifFilters == null) {
|
||||||
|
ifFilters = new LinkedList<Filter<?>>();
|
||||||
|
}
|
||||||
|
ifFilters.add(filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,40 +16,41 @@
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
||||||
|
extends AbstractStatementOperation<E, O> {
|
||||||
|
|
||||||
|
public abstract E transform(ResultSet resultSet);
|
||||||
|
|
||||||
public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>> extends AbstractStatementOperation<E, O> {
|
public boolean cacheable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract E transform(ResultSet resultSet);
|
public String getCacheKey() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
public boolean cacheable() {
|
public AbstractOperation(AbstractSessionOperations sessionOperations) {
|
||||||
return false;
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCacheKey() {
|
public PreparedOperation<E> prepare() {
|
||||||
return "";
|
return new PreparedOperation<E>(prepareStatement(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractOperation(AbstractSessionOperations sessionOperations) {
|
public E sync() {
|
||||||
super(sessionOperations);
|
ResultSet resultSet =
|
||||||
}
|
sessionOps.executeAsync(options(buildStatement()), showValues).getUninterruptibly();
|
||||||
|
E result = transform(resultSet);
|
||||||
public PreparedOperation<E> prepare() {
|
if (cacheable()) {
|
||||||
return new PreparedOperation<E>(prepareStatement(), this);
|
sessionOps.cache(getCacheKey(), result);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
public E sync() {
|
}
|
||||||
ResultSet resultSet = sessionOps.executeAsync(options(buildStatement()), showValues).getUninterruptibly();
|
|
||||||
E result = transform(resultSet);
|
|
||||||
if (cacheable()) {
|
|
||||||
sessionOps.cache(getCacheKey(), result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletableFuture<E> async() { return CompletableFuture.supplyAsync(this::sync); }
|
|
||||||
|
|
||||||
|
public CompletableFuture<E> async() {
|
||||||
|
return CompletableFuture.supplyAsync(this::sync);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,74 +23,80 @@ import com.datastax.driver.core.ResultSetFuture;
|
||||||
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.Optional;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOperation<E, O>>
|
public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOperation<E, O>>
|
||||||
extends AbstractStatementOperation<E, O> {
|
extends AbstractStatementOperation<E, O> {
|
||||||
|
|
||||||
public AbstractOptionalOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractOptionalOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Optional<E> transform(ResultSet resultSet);
|
public abstract Optional<E> transform(ResultSet resultSet);
|
||||||
|
|
||||||
public PreparedOptionalOperation<E> prepare() {
|
public PreparedOptionalOperation<E> prepare() {
|
||||||
return new PreparedOptionalOperation<E>(prepareStatement(), this);
|
return new PreparedOptionalOperation<E>(prepareStatement(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<PreparedOptionalOperation<E>> prepareAsync() {
|
public ListenableFuture<PreparedOptionalOperation<E>> prepareAsync() {
|
||||||
final O _this = (O) this;
|
final O _this = (O) this;
|
||||||
return Futures.transform(prepareStatementAsync(),
|
return Futures.transform(
|
||||||
new Function<PreparedStatement, PreparedOptionalOperation<E>>() {
|
prepareStatementAsync(),
|
||||||
@Override
|
new Function<PreparedStatement, PreparedOptionalOperation<E>>() {
|
||||||
public PreparedOptionalOperation<E> apply(PreparedStatement preparedStatement) {
|
@Override
|
||||||
return new PreparedOptionalOperation<E>(preparedStatement, _this);
|
public PreparedOptionalOperation<E> apply(PreparedStatement preparedStatement) {
|
||||||
}
|
return new PreparedOptionalOperation<E>(preparedStatement, _this);
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<E> sync() {
|
public Optional<E> sync() {
|
||||||
Tracer tracer = this.sessionOps.getZipkinTracer();
|
Tracer tracer = this.sessionOps.getZipkinTracer();
|
||||||
final Span cassandraSpan = (tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
final Span cassandraSpan =
|
||||||
if (cassandraSpan != null) {
|
(tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
||||||
cassandraSpan.name("cassandra");
|
if (cassandraSpan != null) {
|
||||||
cassandraSpan.start();
|
cassandraSpan.name("cassandra");
|
||||||
}
|
cassandraSpan.start();
|
||||||
|
}
|
||||||
|
|
||||||
ResultSet resultSet = sessionOps.executeAsync(options(buildStatement()), showValues).getUninterruptibly();
|
ResultSet resultSet =
|
||||||
Optional<E> result = transform(resultSet);
|
sessionOps.executeAsync(options(buildStatement()), showValues).getUninterruptibly();
|
||||||
|
Optional<E> result = transform(resultSet);
|
||||||
|
|
||||||
if (cassandraSpan != null) {
|
if (cassandraSpan != null) {
|
||||||
cassandraSpan.finish();
|
cassandraSpan.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<Optional<E>> async() {
|
public ListenableFuture<Optional<E>> async() {
|
||||||
final Tracer tracer = this.sessionOps.getZipkinTracer();
|
final Tracer tracer = this.sessionOps.getZipkinTracer();
|
||||||
final Span cassandraSpan = (tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
final Span cassandraSpan =
|
||||||
if (cassandraSpan != null) {
|
(tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
||||||
cassandraSpan.name("cassandra");
|
if (cassandraSpan != null) {
|
||||||
cassandraSpan.start();
|
cassandraSpan.name("cassandra");
|
||||||
}
|
cassandraSpan.start();
|
||||||
|
}
|
||||||
|
|
||||||
ResultSetFuture resultSetFuture = sessionOps.executeAsync(options(buildStatement()), showValues);
|
ResultSetFuture resultSetFuture =
|
||||||
ListenableFuture<Optional<E>> future = Futures.transform(resultSetFuture,
|
sessionOps.executeAsync(options(buildStatement()), showValues);
|
||||||
new Function<ResultSet, Optional<E>>() {
|
ListenableFuture<Optional<E>> future =
|
||||||
@Override
|
Futures.transform(
|
||||||
public Optional<E> apply(ResultSet resultSet) {
|
resultSetFuture,
|
||||||
Optional<E> result = transform(resultSet);
|
new Function<ResultSet, Optional<E>>() {
|
||||||
if (cassandraSpan != null) {
|
@Override
|
||||||
cassandraSpan.finish();
|
public Optional<E> apply(ResultSet resultSet) {
|
||||||
}
|
Optional<E> result = transform(resultSet);
|
||||||
return result;
|
if (cassandraSpan != null) {
|
||||||
}
|
cassandraSpan.finish();
|
||||||
}, sessionOps.getExecutor());
|
}
|
||||||
|
return result;
|
||||||
return future;
|
}
|
||||||
}
|
},
|
||||||
|
sessionOps.getExecutor());
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,6 @@ package net.helenus.core.operation;
|
||||||
|
|
||||||
import brave.Tracer;
|
import brave.Tracer;
|
||||||
import brave.propagation.TraceContext;
|
import brave.propagation.TraceContext;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.ConsistencyLevel;
|
import com.datastax.driver.core.ConsistencyLevel;
|
||||||
import com.datastax.driver.core.PreparedStatement;
|
import com.datastax.driver.core.PreparedStatement;
|
||||||
import com.datastax.driver.core.RegularStatement;
|
import com.datastax.driver.core.RegularStatement;
|
||||||
|
@ -30,244 +27,242 @@ import com.datastax.driver.core.policies.FallthroughRetryPolicy;
|
||||||
import com.datastax.driver.core.policies.RetryPolicy;
|
import com.datastax.driver.core.policies.RetryPolicy;
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>> {
|
public abstract class AbstractStatementOperation<E, O extends AbstractStatementOperation<E, O>> {
|
||||||
|
|
||||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
protected final AbstractSessionOperations sessionOps;
|
protected final AbstractSessionOperations sessionOps;
|
||||||
|
|
||||||
public abstract Statement buildStatement();
|
public abstract Statement buildStatement();
|
||||||
|
|
||||||
protected boolean showValues = true;
|
protected boolean showValues = true;
|
||||||
protected TraceContext traceContext;
|
protected TraceContext traceContext;
|
||||||
private ConsistencyLevel consistencyLevel;
|
private ConsistencyLevel consistencyLevel;
|
||||||
private ConsistencyLevel serialConsistencyLevel;
|
private ConsistencyLevel serialConsistencyLevel;
|
||||||
private RetryPolicy retryPolicy;
|
private RetryPolicy retryPolicy;
|
||||||
private boolean enableTracing = false;
|
private boolean enableTracing = false;
|
||||||
private long[] defaultTimestamp = null;
|
private long[] defaultTimestamp = null;
|
||||||
private int[] fetchSize = null;
|
private int[] fetchSize = null;
|
||||||
|
|
||||||
public AbstractStatementOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractStatementOperation(AbstractSessionOperations sessionOperations) {
|
||||||
this.sessionOps = sessionOperations;
|
this.sessionOps = sessionOperations;
|
||||||
this.consistencyLevel = sessionOperations.getDefaultConsistencyLevel();
|
this.consistencyLevel = sessionOperations.getDefaultConsistencyLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public O showValues(boolean enabled) {
|
public O showValues(boolean enabled) {
|
||||||
this.showValues = enabled;
|
this.showValues = enabled;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O defaultTimestamp(long timestamp) {
|
public O defaultTimestamp(long timestamp) {
|
||||||
this.defaultTimestamp = new long[1];
|
this.defaultTimestamp = new long[1];
|
||||||
this.defaultTimestamp[0] = timestamp;
|
this.defaultTimestamp[0] = timestamp;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O retryPolicy(RetryPolicy retryPolicy) {
|
public O retryPolicy(RetryPolicy retryPolicy) {
|
||||||
this.retryPolicy = retryPolicy;
|
this.retryPolicy = retryPolicy;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O defaultRetryPolicy() {
|
public O defaultRetryPolicy() {
|
||||||
this.retryPolicy = DefaultRetryPolicy.INSTANCE;
|
this.retryPolicy = DefaultRetryPolicy.INSTANCE;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O downgradingConsistencyRetryPolicy() {
|
public O downgradingConsistencyRetryPolicy() {
|
||||||
this.retryPolicy = DowngradingConsistencyRetryPolicy.INSTANCE;
|
this.retryPolicy = DowngradingConsistencyRetryPolicy.INSTANCE;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O fallthroughRetryPolicy() {
|
public O fallthroughRetryPolicy() {
|
||||||
this.retryPolicy = FallthroughRetryPolicy.INSTANCE;
|
this.retryPolicy = FallthroughRetryPolicy.INSTANCE;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O consistency(ConsistencyLevel level) {
|
public O consistency(ConsistencyLevel level) {
|
||||||
this.consistencyLevel = level;
|
this.consistencyLevel = level;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O consistencyAny() {
|
public O consistencyAny() {
|
||||||
this.consistencyLevel = ConsistencyLevel.ANY;
|
this.consistencyLevel = ConsistencyLevel.ANY;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O consistencyOne() {
|
public O consistencyOne() {
|
||||||
this.consistencyLevel = ConsistencyLevel.ONE;
|
this.consistencyLevel = ConsistencyLevel.ONE;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public O consistencyQuorum() {
|
public O consistencyQuorum() {
|
||||||
this.consistencyLevel = ConsistencyLevel.QUORUM;
|
this.consistencyLevel = ConsistencyLevel.QUORUM;
|
||||||
return (O) this;
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O consistencyAll() {
|
||||||
|
this.consistencyLevel = ConsistencyLevel.ALL;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O consistencyLocalOne() {
|
||||||
|
this.consistencyLevel = ConsistencyLevel.LOCAL_ONE;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O consistencyLocalQuorum() {
|
||||||
|
this.consistencyLevel = ConsistencyLevel.LOCAL_QUORUM;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O consistencyEachQuorum() {
|
||||||
|
this.consistencyLevel = ConsistencyLevel.EACH_QUORUM;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O serialConsistency(ConsistencyLevel level) {
|
||||||
|
this.serialConsistencyLevel = level;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O serialConsistencyAny() {
|
||||||
|
this.serialConsistencyLevel = ConsistencyLevel.ANY;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O serialConsistencyOne() {
|
||||||
|
this.serialConsistencyLevel = ConsistencyLevel.ONE;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O serialConsistencyQuorum() {
|
||||||
|
this.serialConsistencyLevel = ConsistencyLevel.QUORUM;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O serialConsistencyAll() {
|
||||||
|
this.serialConsistencyLevel = ConsistencyLevel.ALL;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O serialConsistencyLocal() {
|
||||||
|
this.serialConsistencyLevel = ConsistencyLevel.LOCAL_SERIAL;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O serialConsistencyLocalQuorum() {
|
||||||
|
this.serialConsistencyLevel = ConsistencyLevel.LOCAL_QUORUM;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O disableTracing() {
|
||||||
|
this.enableTracing = false;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O enableTracing() {
|
||||||
|
this.enableTracing = true;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O tracing(boolean enable) {
|
||||||
|
this.enableTracing = enable;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public O fetchSize(int fetchSize) {
|
||||||
|
this.fetchSize = new int[1];
|
||||||
|
this.fetchSize[0] = fetchSize;
|
||||||
|
return (O) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement options(Statement statement) {
|
||||||
|
|
||||||
|
if (defaultTimestamp != null) {
|
||||||
|
statement.setDefaultTimestamp(defaultTimestamp[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public O consistencyAll() {
|
if (consistencyLevel != null) {
|
||||||
this.consistencyLevel = ConsistencyLevel.ALL;
|
statement.setConsistencyLevel(consistencyLevel);
|
||||||
return (O) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public O consistencyLocalOne() {
|
|
||||||
this.consistencyLevel = ConsistencyLevel.LOCAL_ONE;
|
|
||||||
return (O) this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public O consistencyLocalQuorum() {
|
if (serialConsistencyLevel != null) {
|
||||||
this.consistencyLevel = ConsistencyLevel.LOCAL_QUORUM;
|
statement.setSerialConsistencyLevel(serialConsistencyLevel);
|
||||||
return (O) this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public O consistencyEachQuorum() {
|
if (retryPolicy != null) {
|
||||||
this.consistencyLevel = ConsistencyLevel.EACH_QUORUM;
|
statement.setRetryPolicy(retryPolicy);
|
||||||
return (O) this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public O serialConsistency(ConsistencyLevel level) {
|
if (enableTracing) {
|
||||||
this.serialConsistencyLevel = level;
|
statement.enableTracing();
|
||||||
return (O) this;
|
} else {
|
||||||
}
|
statement.disableTracing();
|
||||||
|
|
||||||
public O serialConsistencyAny() {
|
|
||||||
this.serialConsistencyLevel = ConsistencyLevel.ANY;
|
|
||||||
return (O) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public O serialConsistencyOne() {
|
|
||||||
this.serialConsistencyLevel = ConsistencyLevel.ONE;
|
|
||||||
return (O) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public O serialConsistencyQuorum() {
|
|
||||||
this.serialConsistencyLevel = ConsistencyLevel.QUORUM;
|
|
||||||
return (O) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public O serialConsistencyAll() {
|
|
||||||
this.serialConsistencyLevel = ConsistencyLevel.ALL;
|
|
||||||
return (O) this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public O serialConsistencyLocal() {
|
if (fetchSize != null) {
|
||||||
this.serialConsistencyLevel = ConsistencyLevel.LOCAL_SERIAL;
|
statement.setFetchSize(fetchSize[0]);
|
||||||
return (O) this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public O serialConsistencyLocalQuorum() {
|
return statement;
|
||||||
this.serialConsistencyLevel = ConsistencyLevel.LOCAL_QUORUM;
|
}
|
||||||
return (O) this;
|
|
||||||
|
public O zipkinContext(TraceContext traceContext) {
|
||||||
|
if (traceContext != null) {
|
||||||
|
Tracer tracer = this.sessionOps.getZipkinTracer();
|
||||||
|
if (tracer != null) {
|
||||||
|
this.traceContext = traceContext;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public O disableTracing() {
|
return (O) this;
|
||||||
this.enableTracing = false;
|
}
|
||||||
return (O) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public O enableTracing() {
|
public Statement statement() {
|
||||||
this.enableTracing = true;
|
return buildStatement();
|
||||||
return (O) this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public O tracing(boolean enable) {
|
public String cql() {
|
||||||
this.enableTracing = enable;
|
Statement statement = buildStatement();
|
||||||
return (O) this;
|
if (statement == null) return "";
|
||||||
}
|
if (statement instanceof BuiltStatement) {
|
||||||
|
BuiltStatement buildStatement = (BuiltStatement) statement;
|
||||||
|
return buildStatement.setForceNoValues(true).getQueryString();
|
||||||
|
} else {
|
||||||
|
return statement.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public O fetchSize(int fetchSize) {
|
public PreparedStatement prepareStatement() {
|
||||||
this.fetchSize = new int[1];
|
|
||||||
this.fetchSize[0] = fetchSize;
|
|
||||||
return (O) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Statement options(Statement statement) {
|
Statement statement = buildStatement();
|
||||||
|
|
||||||
if (defaultTimestamp != null) {
|
if (statement instanceof RegularStatement) {
|
||||||
statement.setDefaultTimestamp(defaultTimestamp[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (consistencyLevel != null) {
|
RegularStatement regularStatement = (RegularStatement) statement;
|
||||||
statement.setConsistencyLevel(consistencyLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serialConsistencyLevel != null) {
|
return sessionOps.prepare(regularStatement);
|
||||||
statement.setSerialConsistencyLevel(serialConsistencyLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retryPolicy != null) {
|
|
||||||
statement.setRetryPolicy(retryPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableTracing) {
|
|
||||||
statement.enableTracing();
|
|
||||||
} else {
|
|
||||||
statement.disableTracing();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fetchSize != null) {
|
|
||||||
statement.setFetchSize(fetchSize[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return statement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public O zipkinContext(TraceContext traceContext) {
|
|
||||||
if (traceContext != null) {
|
|
||||||
Tracer tracer = this.sessionOps.getZipkinTracer();
|
|
||||||
if (tracer != null) {
|
|
||||||
this.traceContext = traceContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (O) this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Statement statement() {
|
throw new HelenusException("only RegularStatements can be prepared");
|
||||||
return buildStatement();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public String cql() {
|
public ListenableFuture<PreparedStatement> prepareStatementAsync() {
|
||||||
Statement statement = buildStatement();
|
|
||||||
if (statement == null) return "";
|
|
||||||
if (statement instanceof BuiltStatement) {
|
|
||||||
BuiltStatement buildStatement = (BuiltStatement) statement;
|
|
||||||
return buildStatement.setForceNoValues(true).getQueryString();
|
|
||||||
} else {
|
|
||||||
return statement.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PreparedStatement prepareStatement() {
|
Statement statement = buildStatement();
|
||||||
|
|
||||||
Statement statement = buildStatement();
|
if (statement instanceof RegularStatement) {
|
||||||
|
|
||||||
if (statement instanceof RegularStatement) {
|
RegularStatement regularStatement = (RegularStatement) statement;
|
||||||
|
|
||||||
RegularStatement regularStatement = (RegularStatement) statement;
|
return sessionOps.prepareAsync(regularStatement);
|
||||||
|
}
|
||||||
return sessionOps.prepare(regularStatement);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HelenusException("only RegularStatements can be prepared");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListenableFuture<PreparedStatement> prepareStatementAsync() {
|
|
||||||
|
|
||||||
Statement statement = buildStatement();
|
|
||||||
|
|
||||||
if (statement instanceof RegularStatement) {
|
|
||||||
|
|
||||||
RegularStatement regularStatement = (RegularStatement) statement;
|
|
||||||
|
|
||||||
return sessionOps.prepareAsync(regularStatement);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HelenusException("only RegularStatements can be prepared");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
throw new HelenusException("only RegularStatements can be prepared");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import brave.Span;
|
import brave.Span;
|
||||||
import brave.Tracer;
|
import brave.Tracer;
|
||||||
import com.datastax.driver.core.PreparedStatement;
|
import com.datastax.driver.core.PreparedStatement;
|
||||||
|
@ -25,72 +23,79 @@ import com.datastax.driver.core.ResultSetFuture;
|
||||||
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.stream.Stream;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
|
|
||||||
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> {
|
||||||
|
|
||||||
public AbstractStreamOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractStreamOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Stream<E> transform(ResultSet resultSet);
|
public abstract Stream<E> transform(ResultSet resultSet);
|
||||||
|
|
||||||
public PreparedStreamOperation<E> prepare() {
|
public PreparedStreamOperation<E> prepare() {
|
||||||
return new PreparedStreamOperation<E>(prepareStatement(), this);
|
return new PreparedStreamOperation<E>(prepareStatement(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<PreparedStreamOperation<E>> prepareAsync() {
|
public ListenableFuture<PreparedStreamOperation<E>> prepareAsync() {
|
||||||
final O _this = (O) this;
|
final O _this = (O) this;
|
||||||
return Futures.transform(prepareStatementAsync(),
|
return Futures.transform(
|
||||||
new Function<PreparedStatement, PreparedStreamOperation<E>>() {
|
prepareStatementAsync(),
|
||||||
@Override
|
new Function<PreparedStatement, PreparedStreamOperation<E>>() {
|
||||||
public PreparedStreamOperation<E> apply(PreparedStatement preparedStatement) {
|
@Override
|
||||||
return new PreparedStreamOperation<E>(preparedStatement, _this);
|
public PreparedStreamOperation<E> apply(PreparedStatement preparedStatement) {
|
||||||
}
|
return new PreparedStreamOperation<E>(preparedStatement, _this);
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public Stream<E> sync() {
|
public Stream<E> sync() {
|
||||||
Tracer tracer = this.sessionOps.getZipkinTracer();
|
Tracer tracer = this.sessionOps.getZipkinTracer();
|
||||||
final Span cassandraSpan = (tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
final Span cassandraSpan =
|
||||||
if (cassandraSpan != null) {
|
(tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
||||||
cassandraSpan.name("cassandra");
|
if (cassandraSpan != null) {
|
||||||
cassandraSpan.start();
|
cassandraSpan.name("cassandra");
|
||||||
}
|
cassandraSpan.start();
|
||||||
|
}
|
||||||
|
|
||||||
ResultSet resultSet = sessionOps.executeAsync(options(buildStatement()), showValues).getUninterruptibly();
|
ResultSet resultSet =
|
||||||
Stream<E> result = transform(resultSet);
|
sessionOps.executeAsync(options(buildStatement()), showValues).getUninterruptibly();
|
||||||
|
Stream<E> result = transform(resultSet);
|
||||||
|
|
||||||
if (cassandraSpan != null) {
|
if (cassandraSpan != null) {
|
||||||
cassandraSpan.finish();
|
cassandraSpan.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<Stream<E>> async() {
|
public ListenableFuture<Stream<E>> async() {
|
||||||
Tracer tracer = this.sessionOps.getZipkinTracer();
|
Tracer tracer = this.sessionOps.getZipkinTracer();
|
||||||
final Span cassandraSpan = (tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
final Span cassandraSpan =
|
||||||
if (cassandraSpan != null) {
|
(tracer != null && traceContext != null) ? tracer.newChild(traceContext) : null;
|
||||||
cassandraSpan.name("cassandra");
|
if (cassandraSpan != null) {
|
||||||
cassandraSpan.start();
|
cassandraSpan.name("cassandra");
|
||||||
}
|
cassandraSpan.start();
|
||||||
|
}
|
||||||
ResultSetFuture resultSetFuture = sessionOps.executeAsync(options(buildStatement()), showValues);
|
|
||||||
ListenableFuture<Stream<E>> future = Futures.transform(resultSetFuture,
|
|
||||||
new Function<ResultSet, Stream<E>>() {
|
|
||||||
@Override
|
|
||||||
public Stream<E> apply(ResultSet resultSet) {
|
|
||||||
Stream<E> result = transform(resultSet);
|
|
||||||
if (cassandraSpan != null) {
|
|
||||||
cassandraSpan.finish();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}, sessionOps.getExecutor());
|
|
||||||
return future;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ResultSetFuture resultSetFuture =
|
||||||
|
sessionOps.executeAsync(options(buildStatement()), showValues);
|
||||||
|
ListenableFuture<Stream<E>> future =
|
||||||
|
Futures.transform(
|
||||||
|
resultSetFuture,
|
||||||
|
new Function<ResultSet, Stream<E>>() {
|
||||||
|
@Override
|
||||||
|
public Stream<E> apply(ResultSet resultSet) {
|
||||||
|
Stream<E> result = transform(resultSet);
|
||||||
|
if (cassandraSpan != null) {
|
||||||
|
cassandraSpan.finish();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sessionOps.getExecutor());
|
||||||
|
return future;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,23 +21,22 @@ import com.datastax.driver.core.Statement;
|
||||||
|
|
||||||
public final class BoundOperation<E> extends AbstractOperation<E, BoundOperation<E>> {
|
public final class BoundOperation<E> extends AbstractOperation<E, BoundOperation<E>> {
|
||||||
|
|
||||||
private final BoundStatement boundStatement;
|
private final BoundStatement boundStatement;
|
||||||
private final AbstractOperation<E, ?> delegate;
|
private final AbstractOperation<E, ?> delegate;
|
||||||
|
|
||||||
public BoundOperation(BoundStatement boundStatement, AbstractOperation<E, ?> operation) {
|
public BoundOperation(BoundStatement boundStatement, AbstractOperation<E, ?> operation) {
|
||||||
super(operation.sessionOps);
|
super(operation.sessionOps);
|
||||||
this.boundStatement = boundStatement;
|
this.boundStatement = boundStatement;
|
||||||
this.delegate = operation;
|
this.delegate = operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public E transform(ResultSet resultSet) {
|
public E transform(ResultSet resultSet) {
|
||||||
return delegate.transform(resultSet);
|
return delegate.transform(resultSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Statement buildStatement() {
|
|
||||||
return boundStatement;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement buildStatement() {
|
||||||
|
return boundStatement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,31 +15,31 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.BoundStatement;
|
import com.datastax.driver.core.BoundStatement;
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.Statement;
|
import com.datastax.driver.core.Statement;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public final class BoundOptionalOperation<E> extends AbstractOptionalOperation<E, BoundOptionalOperation<E>> {
|
public final class BoundOptionalOperation<E>
|
||||||
|
extends AbstractOptionalOperation<E, BoundOptionalOperation<E>> {
|
||||||
|
|
||||||
private final BoundStatement boundStatement;
|
private final BoundStatement boundStatement;
|
||||||
private final AbstractOptionalOperation<E, ?> delegate;
|
private final AbstractOptionalOperation<E, ?> delegate;
|
||||||
|
|
||||||
public BoundOptionalOperation(BoundStatement boundStatement, AbstractOptionalOperation<E, ?> operation) {
|
public BoundOptionalOperation(
|
||||||
super(operation.sessionOps);
|
BoundStatement boundStatement, AbstractOptionalOperation<E, ?> operation) {
|
||||||
this.boundStatement = boundStatement;
|
super(operation.sessionOps);
|
||||||
this.delegate = operation;
|
this.boundStatement = boundStatement;
|
||||||
}
|
this.delegate = operation;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<E> transform(ResultSet resultSet) {
|
public Optional<E> transform(ResultSet resultSet) {
|
||||||
return delegate.transform(resultSet);
|
return delegate.transform(resultSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Statement buildStatement() {
|
|
||||||
return boundStatement;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement buildStatement() {
|
||||||
|
return boundStatement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,31 +15,31 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.BoundStatement;
|
import com.datastax.driver.core.BoundStatement;
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.Statement;
|
import com.datastax.driver.core.Statement;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public final class BoundStreamOperation<E> extends AbstractStreamOperation<E, BoundStreamOperation<E>> {
|
public final class BoundStreamOperation<E>
|
||||||
|
extends AbstractStreamOperation<E, 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(
|
||||||
super(operation.sessionOps);
|
BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) {
|
||||||
this.boundStatement = boundStatement;
|
super(operation.sessionOps);
|
||||||
this.delegate = operation;
|
this.boundStatement = boundStatement;
|
||||||
}
|
this.delegate = operation;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<E> transform(ResultSet resultSet) {
|
public Stream<E> transform(ResultSet resultSet) {
|
||||||
return delegate.transform(resultSet);
|
return delegate.transform(resultSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Statement buildStatement() {
|
|
||||||
return boundStatement;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement buildStatement() {
|
||||||
|
return boundStatement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ 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.Select;
|
import com.datastax.driver.core.querybuilder.Select;
|
||||||
import com.datastax.driver.core.querybuilder.Select.Where;
|
import com.datastax.driver.core.querybuilder.Select.Where;
|
||||||
|
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.Filter;
|
import net.helenus.core.Filter;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
|
@ -29,54 +28,56 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class CountOperation extends AbstractFilterOperation<Long, CountOperation> {
|
public final class CountOperation extends AbstractFilterOperation<Long, CountOperation> {
|
||||||
|
|
||||||
private HelenusEntity entity;
|
private HelenusEntity entity;
|
||||||
|
|
||||||
public CountOperation(AbstractSessionOperations sessionOperations) {
|
public CountOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CountOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
public CountOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement() {
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty()) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
filters.forEach(f -> addPropertyNode(f.getNode()));
|
filters.forEach(f -> addPropertyNode(f.getNode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new HelenusMappingException("unknown entity");
|
throw new HelenusMappingException("unknown entity");
|
||||||
}
|
}
|
||||||
|
|
||||||
Select select = QueryBuilder.select().countAll().from(entity.getName().toCql());
|
Select select = QueryBuilder.select().countAll().from(entity.getName().toCql());
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty()) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
|
|
||||||
Where where = select.where();
|
Where where = select.where();
|
||||||
|
|
||||||
for (Filter<?> filter : filters) {
|
for (Filter<?> filter : filters) {
|
||||||
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return select;
|
return select;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long transform(ResultSet resultSet) {
|
public Long transform(ResultSet resultSet) {
|
||||||
return resultSet.one().getLong(0);
|
return resultSet.one().getLong(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPropertyNode(HelenusPropertyNode p) {
|
|
||||||
if (entity == null) {
|
|
||||||
entity = p.getEntity();
|
|
||||||
} else if (entity != p.getEntity()) {
|
|
||||||
throw new HelenusMappingException("you can count columns only in single entity "
|
|
||||||
+ entity.getMappingInterface() + " or " + p.getEntity().getMappingInterface());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void addPropertyNode(HelenusPropertyNode p) {
|
||||||
|
if (entity == null) {
|
||||||
|
entity = p.getEntity();
|
||||||
|
} else if (entity != p.getEntity()) {
|
||||||
|
throw new HelenusMappingException(
|
||||||
|
"you can count columns only in single entity "
|
||||||
|
+ entity.getMappingInterface()
|
||||||
|
+ " or "
|
||||||
|
+ p.getEntity().getMappingInterface());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import com.datastax.driver.core.querybuilder.Delete;
|
import com.datastax.driver.core.querybuilder.Delete;
|
||||||
import com.datastax.driver.core.querybuilder.Delete.Where;
|
import com.datastax.driver.core.querybuilder.Delete.Where;
|
||||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||||
|
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.Filter;
|
import net.helenus.core.Filter;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
|
@ -29,97 +28,100 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class DeleteOperation extends AbstractFilterOperation<ResultSet, DeleteOperation> {
|
public final class DeleteOperation extends AbstractFilterOperation<ResultSet, DeleteOperation> {
|
||||||
|
|
||||||
private HelenusEntity entity;
|
private HelenusEntity entity;
|
||||||
|
|
||||||
private boolean ifExists = false;
|
private boolean ifExists = false;
|
||||||
|
|
||||||
private int[] ttl;
|
private int[] ttl;
|
||||||
private long[] timestamp;
|
private long[] timestamp;
|
||||||
|
|
||||||
public DeleteOperation(AbstractSessionOperations sessionOperations) {
|
public DeleteOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
public DeleteOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement() {
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty()) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
filters.forEach(f -> addPropertyNode(f.getNode()));
|
filters.forEach(f -> addPropertyNode(f.getNode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new HelenusMappingException("unknown entity");
|
throw new HelenusMappingException("unknown entity");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty()) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
|
|
||||||
Delete delete = QueryBuilder.delete().from(entity.getName().toCql());
|
Delete delete = QueryBuilder.delete().from(entity.getName().toCql());
|
||||||
|
|
||||||
if (this.ifExists) {
|
if (this.ifExists) {
|
||||||
delete.ifExists();
|
delete.ifExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
Where where = delete.where();
|
Where where = delete.where();
|
||||||
|
|
||||||
for (Filter<?> filter : filters) {
|
for (Filter<?> filter : filters) {
|
||||||
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifFilters != null && !ifFilters.isEmpty()) {
|
if (ifFilters != null && !ifFilters.isEmpty()) {
|
||||||
|
|
||||||
for (Filter<?> filter : ifFilters) {
|
for (Filter<?> filter : ifFilters) {
|
||||||
delete.onlyIf(filter.getClause(sessionOps.getValuePreparer()));
|
delete.onlyIf(filter.getClause(sessionOps.getValuePreparer()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.ttl != null) {
|
if (this.ttl != null) {
|
||||||
delete.using(QueryBuilder.ttl(this.ttl[0]));
|
delete.using(QueryBuilder.ttl(this.ttl[0]));
|
||||||
}
|
}
|
||||||
if (this.timestamp != null) {
|
if (this.timestamp != null) {
|
||||||
delete.using(QueryBuilder.timestamp(this.timestamp[0]));
|
delete.using(QueryBuilder.timestamp(this.timestamp[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return delete;
|
return delete;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return QueryBuilder.truncate(entity.getName().toCql());
|
return QueryBuilder.truncate(entity.getName().toCql());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet transform(ResultSet resultSet) {
|
public ResultSet transform(ResultSet resultSet) {
|
||||||
return resultSet;
|
return resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteOperation ifExists() {
|
public DeleteOperation ifExists() {
|
||||||
this.ifExists = true;
|
this.ifExists = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteOperation usingTtl(int ttl) {
|
public DeleteOperation usingTtl(int ttl) {
|
||||||
this.ttl = new int[1];
|
this.ttl = new int[1];
|
||||||
this.ttl[0] = ttl;
|
this.ttl[0] = ttl;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteOperation usingTimestamp(long timestamp) {
|
public DeleteOperation usingTimestamp(long timestamp) {
|
||||||
this.timestamp = new long[1];
|
this.timestamp = new long[1];
|
||||||
this.timestamp[0] = timestamp;
|
this.timestamp[0] = timestamp;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPropertyNode(HelenusPropertyNode p) {
|
private void addPropertyNode(HelenusPropertyNode p) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
entity = p.getEntity();
|
entity = p.getEntity();
|
||||||
} else if (entity != p.getEntity()) {
|
} else if (entity != p.getEntity()) {
|
||||||
throw new HelenusMappingException("you can delete rows only in single entity "
|
throw new HelenusMappingException(
|
||||||
+ entity.getMappingInterface() + " or " + p.getEntity().getMappingInterface());
|
"you can delete rows only in single entity "
|
||||||
}
|
+ entity.getMappingInterface()
|
||||||
}
|
+ " or "
|
||||||
|
+ p.getEntity().getMappingInterface());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,13 @@ 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 java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
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;
|
||||||
import net.helenus.core.reflect.DefaultPrimitiveTypes;
|
import net.helenus.core.reflect.DefaultPrimitiveTypes;
|
||||||
import net.helenus.core.reflect.HelenusPropertyNode;
|
import net.helenus.core.reflect.HelenusPropertyNode;
|
||||||
import net.helenus.core.reflect.MapExportable;
|
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.mapping.MappingUtil;
|
import net.helenus.mapping.MappingUtil;
|
||||||
|
@ -33,178 +34,181 @@ import net.helenus.support.Fun;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public final class InsertOperation<T> extends AbstractOperation<T, InsertOperation<T>> {
|
public final class InsertOperation<T> extends AbstractOperation<T, InsertOperation<T>> {
|
||||||
|
|
||||||
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 =
|
||||||
private boolean ifNotExists;
|
new ArrayList<Fun.Tuple2<HelenusPropertyNode, Object>>();
|
||||||
private Object pojo;
|
private boolean ifNotExists;
|
||||||
|
private Object pojo;
|
||||||
|
|
||||||
private int[] ttl;
|
private int[] ttl;
|
||||||
private long[] timestamp;
|
private long[] timestamp;
|
||||||
|
|
||||||
public InsertOperation(AbstractSessionOperations sessionOperations, boolean ifNotExists) {
|
public InsertOperation(AbstractSessionOperations sessionOperations, boolean ifNotExists) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
|
||||||
this.ifNotExists = ifNotExists;
|
this.ifNotExists = ifNotExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity,
|
public InsertOperation(
|
||||||
Object pojo, Set<String> mutations, boolean ifNotExists) {
|
AbstractSessionOperations sessionOperations,
|
||||||
super(sessionOperations);
|
HelenusEntity entity,
|
||||||
|
Object pojo,
|
||||||
|
Set<String> mutations,
|
||||||
|
boolean ifNotExists) {
|
||||||
|
super(sessionOperations);
|
||||||
|
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.pojo = pojo;
|
this.pojo = pojo;
|
||||||
this.ifNotExists = ifNotExists;
|
this.ifNotExists = ifNotExists;
|
||||||
Collection<HelenusProperty> properties = entity.getOrderedProperties();
|
Collection<HelenusProperty> properties = entity.getOrderedProperties();
|
||||||
Set<String> keys = (mutations == null) ? null : mutations;
|
Set<String> keys = (mutations == null) ? null : mutations;
|
||||||
|
|
||||||
for (HelenusProperty prop : properties) {
|
for (HelenusProperty prop : properties) {
|
||||||
|
|
||||||
if (keys == null || keys.contains(prop.getPropertyName())) {
|
if (keys == null || keys.contains(prop.getPropertyName())) {
|
||||||
|
|
||||||
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
|
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop);
|
||||||
value = sessionOps.getValuePreparer().prepareColumnValue(value, prop);
|
value = sessionOps.getValuePreparer().prepareColumnValue(value, prop);
|
||||||
|
|
||||||
if (value != null) {
|
|
||||||
HelenusPropertyNode node = new HelenusPropertyNode(prop, Optional.empty());
|
|
||||||
values.add(Fun.Tuple2.of(node, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
HelenusPropertyNode node = new HelenusPropertyNode(prop, Optional.empty());
|
||||||
|
values.add(Fun.Tuple2.of(node, value));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsertOperation<T> ifNotExists() {
|
||||||
|
this.ifNotExists = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsertOperation<T> ifNotExists(boolean enable) {
|
||||||
|
this.ifNotExists = enable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V> InsertOperation<T> value(Getter<V> getter, V val) {
|
||||||
|
|
||||||
|
Objects.requireNonNull(getter, "getter is empty");
|
||||||
|
|
||||||
|
if (val != null) {
|
||||||
|
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
Object value = sessionOps.getValuePreparer().prepareColumnValue(val, node.getProperty());
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
values.add(Fun.Tuple2.of(node, value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertOperation<T> ifNotExists() {
|
return this;
|
||||||
this.ifNotExists = true;
|
}
|
||||||
return this;
|
|
||||||
|
@Override
|
||||||
|
public BuiltStatement buildStatement() {
|
||||||
|
|
||||||
|
values.forEach(t -> addPropertyNode(t._1));
|
||||||
|
|
||||||
|
if (values.isEmpty()) return null;
|
||||||
|
|
||||||
|
if (entity == null) {
|
||||||
|
throw new HelenusMappingException("unknown entity");
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertOperation<T> ifNotExists(boolean enable) {
|
Insert insert = QueryBuilder.insertInto(entity.getName().toCql());
|
||||||
this.ifNotExists = enable;
|
|
||||||
return this;
|
if (ifNotExists) {
|
||||||
|
insert.ifNotExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> InsertOperation<T> value(Getter<V> getter, V val) {
|
values.forEach(
|
||||||
|
t -> {
|
||||||
Objects.requireNonNull(getter, "getter is empty");
|
insert.value(t._1.getColumnName(), t._2);
|
||||||
|
|
||||||
if (val != null) {
|
|
||||||
HelenusPropertyNode node = MappingUtil.resolveMappingProperty(getter);
|
|
||||||
Object value = sessionOps.getValuePreparer().prepareColumnValue(val, node.getProperty());
|
|
||||||
|
|
||||||
if (value != null) {
|
|
||||||
values.add(Fun.Tuple2.of(node, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BuiltStatement buildStatement() {
|
|
||||||
|
|
||||||
values.forEach(t -> addPropertyNode(t._1));
|
|
||||||
|
|
||||||
if (values.isEmpty())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (entity == null) {
|
|
||||||
throw new HelenusMappingException("unknown entity");
|
|
||||||
}
|
|
||||||
|
|
||||||
Insert insert = QueryBuilder.insertInto(entity.getName().toCql());
|
|
||||||
|
|
||||||
if (ifNotExists) {
|
|
||||||
insert.ifNotExists();
|
|
||||||
}
|
|
||||||
|
|
||||||
values.forEach(t -> {
|
|
||||||
insert.value(t._1.getColumnName(), t._2);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.ttl != null) {
|
if (this.ttl != null) {
|
||||||
insert.using(QueryBuilder.ttl(this.ttl[0]));
|
insert.using(QueryBuilder.ttl(this.ttl[0]));
|
||||||
}
|
}
|
||||||
if (this.timestamp != null) {
|
if (this.timestamp != null) {
|
||||||
insert.using(QueryBuilder.timestamp(this.timestamp[0]));
|
insert.using(QueryBuilder.timestamp(this.timestamp[0]));
|
||||||
}
|
|
||||||
|
|
||||||
return insert;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
return insert;
|
||||||
public T transform(ResultSet resultSet) {
|
}
|
||||||
if (pojo != null && ((T) pojo).getClass().isAssignableFrom(ResultSet.class)) {
|
|
||||||
return (T) pojo;
|
|
||||||
} else {
|
|
||||||
if (values.size() > 0) {
|
|
||||||
Collection<HelenusProperty> properties = entity.getOrderedProperties();
|
|
||||||
Map<String, Object> backingMap = new HashMap<String, Object>(properties.size());
|
|
||||||
|
|
||||||
// First, add all the inserted values into our new map.
|
@Override
|
||||||
values.forEach(t -> backingMap.put(t._1.getProperty().getPropertyName(), t._2));
|
public T transform(ResultSet resultSet) {
|
||||||
|
if (pojo != null && ((T) pojo).getClass().isAssignableFrom(ResultSet.class)) {
|
||||||
|
return (T) pojo;
|
||||||
|
} else {
|
||||||
|
if (values.size() > 0) {
|
||||||
|
Collection<HelenusProperty> properties = entity.getOrderedProperties();
|
||||||
|
Map<String, Object> backingMap = new HashMap<String, Object>(properties.size());
|
||||||
|
|
||||||
// Then, fill in all the rest of the properties.
|
// First, add all the inserted values into our new map.
|
||||||
for (HelenusProperty prop : properties) {
|
values.forEach(t -> backingMap.put(t._1.getProperty().getPropertyName(), t._2));
|
||||||
String key = prop.getPropertyName();
|
|
||||||
if (backingMap.containsKey(key)) {
|
|
||||||
// Some values man need to be converted (e.g. from String to Enum). This is done
|
|
||||||
// within the BeanColumnValueProvider below.
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getReadConverter(sessionOps.getSessionRepository());
|
|
||||||
if (converter.isPresent()) {
|
|
||||||
backingMap.put(key, converter.get().apply(backingMap.get(key)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If we started this operation with an instance of this type, use values from that.
|
|
||||||
if (pojo != null) {
|
|
||||||
backingMap.put(key, BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
|
||||||
} else {
|
|
||||||
// Otherwise we'll use default values for the property type if available.
|
|
||||||
Class<?> propType = prop.getJavaType();
|
|
||||||
if (propType.isPrimitive()) {
|
|
||||||
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(propType);
|
|
||||||
if (type == null) {
|
|
||||||
throw new HelenusException("unknown primitive type " + propType);
|
|
||||||
}
|
|
||||||
backingMap.put(key, type.getDefaultValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lastly, create a new proxy object for the entity and return the new instance.
|
// Then, fill in all the rest of the properties.
|
||||||
Class<?> iface = entity.getMappingInterface();
|
for (HelenusProperty prop : properties) {
|
||||||
pojo = Helenus.map(iface, backingMap);
|
String key = prop.getPropertyName();
|
||||||
|
if (backingMap.containsKey(key)) {
|
||||||
|
// Some values man need to be converted (e.g. from String to Enum). This is done
|
||||||
|
// within the BeanColumnValueProvider below.
|
||||||
|
Optional<Function<Object, Object>> converter =
|
||||||
|
prop.getReadConverter(sessionOps.getSessionRepository());
|
||||||
|
if (converter.isPresent()) {
|
||||||
|
backingMap.put(key, converter.get().apply(backingMap.get(key)));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// If we started this operation with an instance of this type, use values from that.
|
||||||
|
if (pojo != null) {
|
||||||
|
backingMap.put(key, BeanColumnValueProvider.INSTANCE.getColumnValue(pojo, -1, prop));
|
||||||
|
} else {
|
||||||
|
// Otherwise we'll use default values for the property type if available.
|
||||||
|
Class<?> propType = prop.getJavaType();
|
||||||
|
if (propType.isPrimitive()) {
|
||||||
|
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(propType);
|
||||||
|
if (type == null) {
|
||||||
|
throw new HelenusException("unknown primitive type " + propType);
|
||||||
|
}
|
||||||
|
backingMap.put(key, type.getDefaultValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (T) pojo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InsertOperation<T> usingTtl(int ttl) {
|
// Lastly, create a new proxy object for the entity and return the new instance.
|
||||||
this.ttl = new int[1];
|
Class<?> iface = entity.getMappingInterface();
|
||||||
this.ttl[0] = ttl;
|
pojo = Helenus.map(iface, backingMap);
|
||||||
return this;
|
}
|
||||||
}
|
}
|
||||||
|
return (T) pojo;
|
||||||
|
}
|
||||||
|
|
||||||
public InsertOperation<T> usingTimestamp(long timestamp) {
|
public InsertOperation<T> usingTtl(int ttl) {
|
||||||
this.timestamp = new long[1];
|
this.ttl = new int[1];
|
||||||
this.timestamp[0] = timestamp;
|
this.ttl[0] = ttl;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPropertyNode(HelenusPropertyNode p) {
|
public InsertOperation<T> usingTimestamp(long timestamp) {
|
||||||
if (entity == null) {
|
this.timestamp = new long[1];
|
||||||
entity = p.getEntity();
|
this.timestamp[0] = timestamp;
|
||||||
} else if (entity != p.getEntity()) {
|
return this;
|
||||||
throw new HelenusMappingException("you can insert only single entity " + entity.getMappingInterface()
|
}
|
||||||
+ " or " + p.getEntity().getMappingInterface());
|
|
||||||
}
|
private void addPropertyNode(HelenusPropertyNode p) {
|
||||||
|
if (entity == null) {
|
||||||
|
entity = p.getEntity();
|
||||||
|
} else if (entity != p.getEntity()) {
|
||||||
|
throw new HelenusMappingException(
|
||||||
|
"you can insert only single entity "
|
||||||
|
+ entity.getMappingInterface()
|
||||||
|
+ " or "
|
||||||
|
+ p.getEntity().getMappingInterface());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,28 +20,27 @@ import com.datastax.driver.core.PreparedStatement;
|
||||||
|
|
||||||
public final class PreparedOperation<E> {
|
public final class PreparedOperation<E> {
|
||||||
|
|
||||||
private final PreparedStatement preparedStatement;
|
private final PreparedStatement preparedStatement;
|
||||||
private final AbstractOperation<E, ?> operation;
|
private final AbstractOperation<E, ?> operation;
|
||||||
|
|
||||||
public PreparedOperation(PreparedStatement statement, AbstractOperation<E, ?> operation) {
|
public PreparedOperation(PreparedStatement statement, AbstractOperation<E, ?> operation) {
|
||||||
this.preparedStatement = statement;
|
this.preparedStatement = statement;
|
||||||
this.operation = operation;
|
this.operation = operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreparedStatement getPreparedStatement() {
|
public PreparedStatement getPreparedStatement() {
|
||||||
return preparedStatement;
|
return preparedStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundOperation<E> bind(Object... params) {
|
public BoundOperation<E> bind(Object... params) {
|
||||||
|
|
||||||
BoundStatement boundStatement = preparedStatement.bind(params);
|
BoundStatement boundStatement = preparedStatement.bind(params);
|
||||||
|
|
||||||
return new BoundOperation<E>(boundStatement, operation);
|
return new BoundOperation<E>(boundStatement, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return preparedStatement.getQueryString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return preparedStatement.getQueryString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,28 +20,28 @@ import com.datastax.driver.core.PreparedStatement;
|
||||||
|
|
||||||
public final class PreparedOptionalOperation<E> {
|
public final class PreparedOptionalOperation<E> {
|
||||||
|
|
||||||
private final PreparedStatement preparedStatement;
|
private final PreparedStatement preparedStatement;
|
||||||
private final AbstractOptionalOperation<E, ?> operation;
|
private final AbstractOptionalOperation<E, ?> operation;
|
||||||
|
|
||||||
public PreparedOptionalOperation(PreparedStatement statement, AbstractOptionalOperation<E, ?> operation) {
|
public PreparedOptionalOperation(
|
||||||
this.preparedStatement = statement;
|
PreparedStatement statement, AbstractOptionalOperation<E, ?> operation) {
|
||||||
this.operation = operation;
|
this.preparedStatement = statement;
|
||||||
}
|
this.operation = operation;
|
||||||
|
}
|
||||||
|
|
||||||
public PreparedStatement getPreparedStatement() {
|
public PreparedStatement getPreparedStatement() {
|
||||||
return preparedStatement;
|
return preparedStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundOptionalOperation<E> bind(Object... params) {
|
public BoundOptionalOperation<E> bind(Object... params) {
|
||||||
|
|
||||||
BoundStatement boundStatement = preparedStatement.bind(params);
|
BoundStatement boundStatement = preparedStatement.bind(params);
|
||||||
|
|
||||||
return new BoundOptionalOperation<E>(boundStatement, operation);
|
return new BoundOptionalOperation<E>(boundStatement, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return preparedStatement.getQueryString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return preparedStatement.getQueryString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,28 +20,28 @@ import com.datastax.driver.core.PreparedStatement;
|
||||||
|
|
||||||
public final class PreparedStreamOperation<E> {
|
public final class PreparedStreamOperation<E> {
|
||||||
|
|
||||||
private final PreparedStatement preparedStatement;
|
private final PreparedStatement preparedStatement;
|
||||||
private final AbstractStreamOperation<E, ?> operation;
|
private final AbstractStreamOperation<E, ?> operation;
|
||||||
|
|
||||||
public PreparedStreamOperation(PreparedStatement statement, AbstractStreamOperation<E, ?> operation) {
|
public PreparedStreamOperation(
|
||||||
this.preparedStatement = statement;
|
PreparedStatement statement, AbstractStreamOperation<E, ?> operation) {
|
||||||
this.operation = operation;
|
this.preparedStatement = statement;
|
||||||
}
|
this.operation = operation;
|
||||||
|
}
|
||||||
|
|
||||||
public PreparedStatement getPreparedStatement() {
|
public PreparedStatement getPreparedStatement() {
|
||||||
return preparedStatement;
|
return preparedStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundStreamOperation<E> bind(Object... params) {
|
public BoundStreamOperation<E> bind(Object... params) {
|
||||||
|
|
||||||
BoundStatement boundStatement = preparedStatement.bind(params);
|
BoundStatement boundStatement = preparedStatement.bind(params);
|
||||||
|
|
||||||
return new BoundStreamOperation<E>(boundStatement, operation);
|
return new BoundStreamOperation<E>(boundStatement, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return preparedStatement.getQueryString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return preparedStatement.getQueryString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,36 +15,35 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
public final class SelectFirstOperation<E>
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
extends AbstractFilterOptionalOperation<E, SelectFirstOperation<E>> {
|
||||||
|
|
||||||
public final class SelectFirstOperation<E> extends AbstractFilterOptionalOperation<E, SelectFirstOperation<E>> {
|
private final SelectOperation<E> src;
|
||||||
|
|
||||||
private final SelectOperation<E> src;
|
public SelectFirstOperation(SelectOperation<E> src) {
|
||||||
|
super(src.sessionOps);
|
||||||
|
|
||||||
public SelectFirstOperation(SelectOperation<E> src) {
|
this.src = src;
|
||||||
super(src.sessionOps);
|
this.filters = src.filters;
|
||||||
|
this.ifFilters = src.ifFilters;
|
||||||
|
}
|
||||||
|
|
||||||
this.src = src;
|
public <R> SelectFirstTransformingOperation<R, E> map(Function<E, R> fn) {
|
||||||
this.filters = src.filters;
|
return new SelectFirstTransformingOperation<R, E>(src, fn);
|
||||||
this.ifFilters = src.ifFilters;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public <R> SelectFirstTransformingOperation<R, E> map(Function<E, R> fn) {
|
@Override
|
||||||
return new SelectFirstTransformingOperation<R, E>(src, fn);
|
public BuiltStatement buildStatement() {
|
||||||
}
|
return src.buildStatement();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public BuiltStatement buildStatement() {
|
|
||||||
return src.buildStatement();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<E> transform(ResultSet resultSet) {
|
|
||||||
return src.transform(resultSet).findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<E> transform(ResultSet resultSet) {
|
||||||
|
return src.transform(resultSet).findFirst();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,36 +15,33 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
|
||||||
|
|
||||||
public final class SelectFirstTransformingOperation<R, E>
|
public final class SelectFirstTransformingOperation<R, E>
|
||||||
extends
|
extends AbstractFilterOptionalOperation<R, SelectFirstTransformingOperation<R, E>> {
|
||||||
AbstractFilterOptionalOperation<R, SelectFirstTransformingOperation<R, E>> {
|
|
||||||
|
|
||||||
private final SelectOperation<E> src;
|
private final SelectOperation<E> src;
|
||||||
private final Function<E, R> fn;
|
private final Function<E, R> fn;
|
||||||
|
|
||||||
public SelectFirstTransformingOperation(SelectOperation<E> src, Function<E, R> fn) {
|
public SelectFirstTransformingOperation(SelectOperation<E> src, Function<E, R> fn) {
|
||||||
super(src.sessionOps);
|
super(src.sessionOps);
|
||||||
|
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.filters = src.filters;
|
this.filters = src.filters;
|
||||||
this.ifFilters = src.ifFilters;
|
this.ifFilters = src.ifFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement() {
|
||||||
return src.buildStatement();
|
return src.buildStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<R> transform(ResultSet resultSet) {
|
|
||||||
return src.transform(resultSet).findFirst().map(fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<R> transform(ResultSet resultSet) {
|
||||||
|
return src.transform(resultSet).findFirst().map(fn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.Row;
|
import com.datastax.driver.core.Row;
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
|
@ -28,7 +23,10 @@ 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 java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
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;
|
||||||
|
@ -41,210 +39,223 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, SelectOperation<E>> {
|
public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, SelectOperation<E>> {
|
||||||
|
|
||||||
protected Function<Row, E> rowMapper = null;
|
protected Function<Row, E> rowMapper = null;
|
||||||
protected final List<HelenusPropertyNode> props = new ArrayList<HelenusPropertyNode>();
|
protected final List<HelenusPropertyNode> props = new ArrayList<HelenusPropertyNode>();
|
||||||
|
|
||||||
protected List<Ordering> ordering = null;
|
protected List<Ordering> ordering = null;
|
||||||
protected Integer limit = null;
|
protected Integer limit = null;
|
||||||
protected boolean allowFiltering = false;
|
protected boolean allowFiltering = false;
|
||||||
|
|
||||||
public SelectOperation(AbstractSessionOperations sessionOperations) {
|
public SelectOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
|
||||||
this.rowMapper = new Function<Row, E>() {
|
this.rowMapper =
|
||||||
|
new Function<Row, E>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public E apply(Row source) {
|
public E apply(Row source) {
|
||||||
|
|
||||||
ColumnValueProvider valueProvider = sessionOps.getValueProvider();
|
ColumnValueProvider valueProvider = sessionOps.getValueProvider();
|
||||||
Object[] arr = new Object[props.size()];
|
Object[] arr = new Object[props.size()];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (HelenusPropertyNode p : props) {
|
for (HelenusPropertyNode p : props) {
|
||||||
Object value = valueProvider.getColumnValue(source, -1, p.getProperty());
|
Object value = valueProvider.getColumnValue(source, -1, p.getProperty());
|
||||||
arr[i++] = value;
|
arr[i++] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (E) Fun.ArrayTuple.of(arr);
|
return (E) Fun.ArrayTuple.of(arr);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
};
|
public SelectOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
super(sessionOperations);
|
||||||
|
|
||||||
super(sessionOperations);
|
entity
|
||||||
|
.getOrderedProperties()
|
||||||
|
.stream()
|
||||||
|
.map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
||||||
|
.forEach(p -> this.props.add(p));
|
||||||
|
}
|
||||||
|
|
||||||
entity.getOrderedProperties().stream().map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
public SelectOperation(
|
||||||
.forEach(p -> this.props.add(p));
|
AbstractSessionOperations sessionOperations,
|
||||||
|
HelenusEntity entity,
|
||||||
|
Function<Row, E> rowMapper) {
|
||||||
|
|
||||||
}
|
super(sessionOperations);
|
||||||
|
this.rowMapper = rowMapper;
|
||||||
|
|
||||||
public SelectOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity,
|
entity
|
||||||
Function<Row, E> rowMapper) {
|
.getOrderedProperties()
|
||||||
|
.stream()
|
||||||
|
.map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
||||||
|
.forEach(p -> this.props.add(p));
|
||||||
|
}
|
||||||
|
|
||||||
super(sessionOperations);
|
public SelectOperation(
|
||||||
this.rowMapper = rowMapper;
|
AbstractSessionOperations sessionOperations,
|
||||||
|
Function<Row, E> rowMapper,
|
||||||
|
HelenusPropertyNode... props) {
|
||||||
|
|
||||||
entity.getOrderedProperties().stream().map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
super(sessionOperations);
|
||||||
.forEach(p -> this.props.add(p));
|
this.rowMapper = rowMapper;
|
||||||
|
Collections.addAll(this.props, props);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public CountOperation count() {
|
||||||
|
|
||||||
public SelectOperation(AbstractSessionOperations sessionOperations, Function<Row, E> rowMapper,
|
HelenusEntity entity = null;
|
||||||
HelenusPropertyNode... props) {
|
for (HelenusPropertyNode prop : props) {
|
||||||
|
|
||||||
super(sessionOperations);
|
if (entity == null) {
|
||||||
this.rowMapper = rowMapper;
|
entity = prop.getEntity();
|
||||||
Collections.addAll(this.props, props);
|
} else if (entity != prop.getEntity()) {
|
||||||
}
|
throw new HelenusMappingException(
|
||||||
|
"you can count records only from a single entity "
|
||||||
|
+ entity.getMappingInterface()
|
||||||
|
+ " or "
|
||||||
|
+ prop.getEntity().getMappingInterface());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public CountOperation count() {
|
return new CountOperation(sessionOps, entity);
|
||||||
|
}
|
||||||
|
|
||||||
HelenusEntity entity = null;
|
public SelectFirstOperation<E> single() {
|
||||||
for (HelenusPropertyNode prop : props) {
|
limit(1);
|
||||||
|
return new SelectFirstOperation<E>(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (entity == null) {
|
public <R> SelectTransformingOperation<R, E> mapTo(Class<R> entityClass) {
|
||||||
entity = prop.getEntity();
|
|
||||||
} else if (entity != prop.getEntity()) {
|
|
||||||
throw new HelenusMappingException("you can count records only from a single entity "
|
|
||||||
+ entity.getMappingInterface() + " or " + prop.getEntity().getMappingInterface());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CountOperation(sessionOps, entity);
|
Objects.requireNonNull(entityClass, "entityClass is null");
|
||||||
}
|
|
||||||
|
|
||||||
public SelectFirstOperation<E> single() {
|
HelenusEntity entity = Helenus.entity(entityClass);
|
||||||
limit(1);
|
|
||||||
return new SelectFirstOperation<E>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <R> SelectTransformingOperation<R, E> mapTo(Class<R> entityClass) {
|
this.rowMapper = null;
|
||||||
|
|
||||||
Objects.requireNonNull(entityClass, "entityClass is null");
|
return new SelectTransformingOperation<R, E>(
|
||||||
|
this,
|
||||||
|
(r) -> {
|
||||||
|
Map<String, Object> map = new ValueProviderMap(r, sessionOps.getValueProvider(), entity);
|
||||||
|
return (R) Helenus.map(entityClass, map);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
HelenusEntity entity = Helenus.entity(entityClass);
|
public <R> SelectTransformingOperation<R, E> map(Function<E, R> fn) {
|
||||||
|
return new SelectTransformingOperation<R, E>(this, fn);
|
||||||
|
}
|
||||||
|
|
||||||
this.rowMapper = null;
|
public SelectOperation<E> column(Getter<?> getter) {
|
||||||
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
this.props.add(p);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
return new SelectTransformingOperation<R, E>(this, (r) -> {
|
public SelectOperation<E> orderBy(Getter<?> getter, OrderingDirection direction) {
|
||||||
|
getOrCreateOrdering().add(new Ordered(getter, direction).getOrdering());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, Object> map = new ValueProviderMap(r, sessionOps.getValueProvider(), entity);
|
public SelectOperation<E> orderBy(Ordered ordered) {
|
||||||
return (R) Helenus.map(entityClass, map);
|
getOrCreateOrdering().add(ordered.getOrdering());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
public SelectOperation<E> limit(Integer limit) {
|
||||||
}
|
this.limit = limit;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public <R> SelectTransformingOperation<R, E> map(Function<E, R> fn) {
|
public SelectOperation<E> allowFiltering() {
|
||||||
return new SelectTransformingOperation<R, E>(this, fn);
|
this.allowFiltering = true;
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SelectOperation<E> column(Getter<?> getter) {
|
@Override
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
public BuiltStatement buildStatement() {
|
||||||
this.props.add(p);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation<E> orderBy(Getter<?> getter, OrderingDirection direction) {
|
HelenusEntity entity = null;
|
||||||
getOrCreateOrdering().add(new Ordered(getter, direction).getOrdering());
|
Selection selection = QueryBuilder.select();
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation<E> orderBy(Ordered ordered) {
|
for (HelenusPropertyNode prop : props) {
|
||||||
getOrCreateOrdering().add(ordered.getOrdering());
|
selection = selection.column(prop.getColumnName());
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation<E> limit(Integer limit) {
|
if (prop.getProperty().caseSensitiveIndex()) {
|
||||||
this.limit = limit;
|
allowFiltering = true;
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public SelectOperation<E> allowFiltering() {
|
if (entity == null) {
|
||||||
this.allowFiltering = true;
|
entity = prop.getEntity();
|
||||||
return this;
|
} else if (entity != prop.getEntity()) {
|
||||||
}
|
throw new HelenusMappingException(
|
||||||
|
"you can select columns only from a single entity "
|
||||||
|
+ entity.getMappingInterface()
|
||||||
|
+ " or "
|
||||||
|
+ prop.getEntity().getMappingInterface());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
if (entity == null) {
|
||||||
public BuiltStatement buildStatement() {
|
throw new HelenusMappingException("no entity or table to select data");
|
||||||
|
}
|
||||||
|
|
||||||
HelenusEntity entity = null;
|
Select select = selection.from(entity.getName().toCql());
|
||||||
Selection selection = QueryBuilder.select();
|
|
||||||
|
|
||||||
for (HelenusPropertyNode prop : props) {
|
if (ordering != null && !ordering.isEmpty()) {
|
||||||
selection = selection.column(prop.getColumnName());
|
select.orderBy(ordering.toArray(new Ordering[ordering.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
if (prop.getProperty().caseSensitiveIndex()) {
|
if (limit != null) {
|
||||||
allowFiltering = true;
|
select.limit(limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity == null) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
entity = prop.getEntity();
|
|
||||||
} else if (entity != prop.getEntity()) {
|
|
||||||
throw new HelenusMappingException("you can select columns only from a single entity "
|
|
||||||
+ entity.getMappingInterface() + " or " + prop.getEntity().getMappingInterface());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity == null) {
|
Where where = select.where();
|
||||||
throw new HelenusMappingException("no entity or table to select data");
|
|
||||||
}
|
|
||||||
|
|
||||||
Select select = selection.from(entity.getName().toCql());
|
for (Filter<?> filter : filters) {
|
||||||
|
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ordering != null && !ordering.isEmpty()) {
|
if (ifFilters != null && !ifFilters.isEmpty()) {
|
||||||
select.orderBy(ordering.toArray(new Ordering[ordering.size()]));
|
logger.error(
|
||||||
}
|
"onlyIf conditions " + ifFilters + " would be ignored in the statement " + select);
|
||||||
|
}
|
||||||
|
|
||||||
if (limit != null) {
|
if (allowFiltering) {
|
||||||
select.limit(limit);
|
select.allowFiltering();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty()) {
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
Where where = select.where();
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Stream<E> transform(ResultSet resultSet) {
|
||||||
|
|
||||||
for (Filter<?> filter : filters) {
|
if (rowMapper != null) {
|
||||||
where.and(filter.getClause(sessionOps.getValuePreparer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifFilters != null && !ifFilters.isEmpty()) {
|
return StreamSupport.stream(
|
||||||
logger.error("onlyIf conditions " + ifFilters + " would be ignored in the statement " + select);
|
Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED), false)
|
||||||
}
|
.map(rowMapper);
|
||||||
|
} else {
|
||||||
|
|
||||||
if (allowFiltering) {
|
return (Stream<E>)
|
||||||
select.allowFiltering();
|
StreamSupport.stream(
|
||||||
}
|
Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED),
|
||||||
|
false);
|
||||||
return select;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Stream<E> transform(ResultSet resultSet) {
|
|
||||||
|
|
||||||
if (rowMapper != null) {
|
|
||||||
|
|
||||||
return StreamSupport
|
|
||||||
.stream(Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED), false)
|
|
||||||
.map(rowMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
|
|
||||||
return (Stream<E>) StreamSupport
|
|
||||||
.stream(Spliterators.spliteratorUnknownSize(resultSet.iterator(), Spliterator.ORDERED), false);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Ordering> getOrCreateOrdering() {
|
|
||||||
if (ordering == null) {
|
|
||||||
ordering = new ArrayList<Ordering>();
|
|
||||||
}
|
|
||||||
return ordering;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private List<Ordering> getOrCreateOrdering() {
|
||||||
|
if (ordering == null) {
|
||||||
|
ordering = new ArrayList<Ordering>();
|
||||||
|
}
|
||||||
|
return ordering;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,36 +15,33 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.operation;
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
|
||||||
import com.datastax.driver.core.querybuilder.BuiltStatement;
|
|
||||||
|
|
||||||
public final class SelectTransformingOperation<R, E>
|
public final class SelectTransformingOperation<R, E>
|
||||||
extends
|
extends AbstractFilterStreamOperation<R, SelectTransformingOperation<R, E>> {
|
||||||
AbstractFilterStreamOperation<R, SelectTransformingOperation<R, E>> {
|
|
||||||
|
|
||||||
private final SelectOperation<E> src;
|
private final SelectOperation<E> src;
|
||||||
private final Function<E, R> fn;
|
private final Function<E, R> fn;
|
||||||
|
|
||||||
public SelectTransformingOperation(SelectOperation<E> src, Function<E, R> fn) {
|
public SelectTransformingOperation(SelectOperation<E> src, Function<E, R> fn) {
|
||||||
super(src.sessionOps);
|
super(src.sessionOps);
|
||||||
|
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.filters = src.filters;
|
this.filters = src.filters;
|
||||||
this.ifFilters = src.ifFilters;
|
this.ifFilters = src.ifFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuiltStatement buildStatement() {
|
public BuiltStatement buildStatement() {
|
||||||
return src.buildStatement();
|
return src.buildStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<R> transform(ResultSet resultSet) {
|
|
||||||
return src.transform(resultSet).map(fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<R> transform(ResultSet resultSet) {
|
||||||
|
return src.transform(resultSet).map(fn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
import net.helenus.core.Filter;
|
import net.helenus.core.Filter;
|
||||||
import net.helenus.core.Getter;
|
import net.helenus.core.Getter;
|
||||||
|
@ -36,416 +34,424 @@ import net.helenus.support.Immutables;
|
||||||
|
|
||||||
public final class UpdateOperation extends AbstractFilterOperation<ResultSet, UpdateOperation> {
|
public final class UpdateOperation extends AbstractFilterOperation<ResultSet, UpdateOperation> {
|
||||||
|
|
||||||
private HelenusEntity entity = null;
|
private HelenusEntity entity = null;
|
||||||
|
|
||||||
private final List<Assignment> assignments = new ArrayList<Assignment>();
|
private final List<Assignment> assignments = new ArrayList<Assignment>();
|
||||||
|
|
||||||
private int[] ttl;
|
private int[] ttl;
|
||||||
private long[] timestamp;
|
private long[] timestamp;
|
||||||
|
|
||||||
public UpdateOperation(AbstractSessionOperations sessionOperations) {
|
public UpdateOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateOperation(AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
public UpdateOperation(
|
||||||
super(sessionOperations);
|
AbstractSessionOperations sessionOperations, HelenusPropertyNode p, Object v) {
|
||||||
|
super(sessionOperations);
|
||||||
|
|
||||||
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
|
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
|
||||||
assignments.add(QueryBuilder.set(p.getColumnName(), value));
|
assignments.add(QueryBuilder.set(p.getColumnName(), value));
|
||||||
|
|
||||||
addPropertyNode(p);
|
addPropertyNode(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> UpdateOperation set(Getter<V> getter, V v) {
|
public <V> UpdateOperation set(Getter<V> getter, V v) {
|
||||||
Objects.requireNonNull(getter, "getter is empty");
|
Objects.requireNonNull(getter, "getter is empty");
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(getter);
|
||||||
|
|
||||||
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
|
Object value = sessionOps.getValuePreparer().prepareColumnValue(v, p.getProperty());
|
||||||
assignments.add(QueryBuilder.set(p.getColumnName(), value));
|
assignments.add(QueryBuilder.set(p.getColumnName(), value));
|
||||||
|
|
||||||
addPropertyNode(p);
|
addPropertyNode(p);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* COUNTER
|
* COUNTER
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public <V> UpdateOperation increment(Getter<V> counterGetter) {
|
public <V> UpdateOperation increment(Getter<V> counterGetter) {
|
||||||
return increment(counterGetter, 1L);
|
return increment(counterGetter, 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <V> UpdateOperation increment(Getter<V> counterGetter, long delta) {
|
public <V> UpdateOperation increment(Getter<V> counterGetter, long delta) {
|
||||||
|
|
||||||
Objects.requireNonNull(counterGetter, "counterGetter is empty");
|
Objects.requireNonNull(counterGetter, "counterGetter is empty");
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
||||||
|
|
||||||
assignments.add(QueryBuilder.incr(p.getColumnName(), delta));
|
assignments.add(QueryBuilder.incr(p.getColumnName(), delta));
|
||||||
|
|
||||||
addPropertyNode(p);
|
addPropertyNode(p);
|
||||||
return this;
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public <V> UpdateOperation decrement(Getter<V> counterGetter) {
|
||||||
|
return decrement(counterGetter, 1L);
|
||||||
|
}
|
||||||
|
|
||||||
public <V> UpdateOperation decrement(Getter<V> counterGetter) {
|
public <V> UpdateOperation decrement(Getter<V> counterGetter, long delta) {
|
||||||
return decrement(counterGetter, 1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation decrement(Getter<V> counterGetter, long delta) {
|
Objects.requireNonNull(counterGetter, "counterGetter is empty");
|
||||||
|
|
||||||
Objects.requireNonNull(counterGetter, "counterGetter is empty");
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(counterGetter);
|
assignments.add(QueryBuilder.decr(p.getColumnName(), delta));
|
||||||
|
|
||||||
assignments.add(QueryBuilder.decr(p.getColumnName(), delta));
|
addPropertyNode(p);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
addPropertyNode(p);
|
/*
|
||||||
return this;
|
*
|
||||||
|
*
|
||||||
|
* LIST
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
public <V> UpdateOperation prepend(Getter<List<V>> listGetter, V value) {
|
||||||
|
|
||||||
/*
|
Objects.requireNonNull(listGetter, "listGetter is empty");
|
||||||
*
|
Objects.requireNonNull(value, "value is empty");
|
||||||
*
|
|
||||||
* LIST
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public <V> UpdateOperation prepend(Getter<List<V>> listGetter, V value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(listGetter, "listGetter is empty");
|
assignments.add(QueryBuilder.prepend(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
addPropertyNode(p);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.prepend(p.getColumnName(), valueObj));
|
public <V> UpdateOperation prependAll(Getter<List<V>> listGetter, List<V> value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(listGetter, "listGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation prependAll(Getter<List<V>> listGetter, List<V> value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
|
List valueObj = prepareListValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(listGetter, "listGetter is empty");
|
assignments.add(QueryBuilder.prependAll(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
addPropertyNode(p);
|
||||||
List valueObj = prepareListValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.prependAll(p.getColumnName(), valueObj));
|
public <V> UpdateOperation setIdx(Getter<List<V>> listGetter, int idx, V value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(listGetter, "listGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation setIdx(Getter<List<V>> listGetter, int idx, V value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(listGetter, "listGetter is empty");
|
assignments.add(QueryBuilder.setIdx(p.getColumnName(), idx, valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
addPropertyNode(p);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.setIdx(p.getColumnName(), idx, valueObj));
|
public <V> UpdateOperation append(Getter<List<V>> listGetter, V value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(listGetter, "listGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation append(Getter<List<V>> listGetter, V value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(listGetter, "listGetter is empty");
|
assignments.add(QueryBuilder.append(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
addPropertyNode(p);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.append(p.getColumnName(), valueObj));
|
public <V> UpdateOperation appendAll(Getter<List<V>> listGetter, List<V> value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(listGetter, "listGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation appendAll(Getter<List<V>> listGetter, List<V> value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
|
List valueObj = prepareListValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(listGetter, "listGetter is empty");
|
assignments.add(QueryBuilder.appendAll(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
addPropertyNode(p);
|
||||||
List valueObj = prepareListValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.appendAll(p.getColumnName(), valueObj));
|
public <V> UpdateOperation discard(Getter<List<V>> listGetter, V value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(listGetter, "listGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation discard(Getter<List<V>> listGetter, V value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
|
Object valueObj = prepareSingleListValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(listGetter, "listGetter is empty");
|
assignments.add(QueryBuilder.discard(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
addPropertyNode(p);
|
||||||
Object valueObj = prepareSingleListValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.discard(p.getColumnName(), valueObj));
|
public <V> UpdateOperation discardAll(Getter<List<V>> listGetter, List<V> value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(listGetter, "listGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation discardAll(Getter<List<V>> listGetter, List<V> value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
||||||
|
List valueObj = prepareListValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(listGetter, "listGetter is empty");
|
assignments.add(QueryBuilder.discardAll(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(listGetter);
|
addPropertyNode(p);
|
||||||
List valueObj = prepareListValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.discardAll(p.getColumnName(), valueObj));
|
private Object prepareSingleListValue(HelenusPropertyNode p, Object value) {
|
||||||
|
HelenusProperty prop = p.getProperty();
|
||||||
|
|
||||||
addPropertyNode(p);
|
Object valueObj = value;
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object prepareSingleListValue(HelenusPropertyNode p, Object value) {
|
Optional<Function<Object, Object>> converter =
|
||||||
HelenusProperty prop = p.getProperty();
|
prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
|
if (converter.isPresent()) {
|
||||||
|
List convertedList = (List) converter.get().apply(Immutables.listOf(value));
|
||||||
|
valueObj = convertedList.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
Object valueObj = value;
|
return valueObj;
|
||||||
|
}
|
||||||
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
private List prepareListValue(HelenusPropertyNode p, List value) {
|
||||||
if (converter.isPresent()) {
|
|
||||||
List convertedList = (List) converter.get().apply(Immutables.listOf(value));
|
|
||||||
valueObj = convertedList.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return valueObj;
|
HelenusProperty prop = p.getProperty();
|
||||||
}
|
|
||||||
|
|
||||||
private List prepareListValue(HelenusPropertyNode p, List value) {
|
List valueObj = value;
|
||||||
|
|
||||||
HelenusProperty prop = p.getProperty();
|
Optional<Function<Object, Object>> converter =
|
||||||
|
prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
|
if (converter.isPresent()) {
|
||||||
|
valueObj = (List) converter.get().apply(value);
|
||||||
|
}
|
||||||
|
|
||||||
List valueObj = value;
|
return valueObj;
|
||||||
|
}
|
||||||
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
/*
|
||||||
if (converter.isPresent()) {
|
*
|
||||||
valueObj = (List) converter.get().apply(value);
|
*
|
||||||
}
|
* SET
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
return valueObj;
|
public <V> UpdateOperation add(Getter<Set<V>> setGetter, V value) {
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
Objects.requireNonNull(setGetter, "setGetter is empty");
|
||||||
*
|
Objects.requireNonNull(value, "value is empty");
|
||||||
*
|
|
||||||
* SET
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public <V> UpdateOperation add(Getter<Set<V>> setGetter, V value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
|
Object valueObj = prepareSingleSetValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(setGetter, "setGetter is empty");
|
assignments.add(QueryBuilder.add(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
addPropertyNode(p);
|
||||||
Object valueObj = prepareSingleSetValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.add(p.getColumnName(), valueObj));
|
public <V> UpdateOperation addAll(Getter<Set<V>> setGetter, Set<V> value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(setGetter, "setGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation addAll(Getter<Set<V>> setGetter, Set<V> value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
|
Set valueObj = prepareSetValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(setGetter, "setGetter is empty");
|
assignments.add(QueryBuilder.addAll(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
addPropertyNode(p);
|
||||||
Set valueObj = prepareSetValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.addAll(p.getColumnName(), valueObj));
|
public <V> UpdateOperation remove(Getter<Set<V>> setGetter, V value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(setGetter, "setGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation remove(Getter<Set<V>> setGetter, V value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
|
Object valueObj = prepareSingleSetValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(setGetter, "setGetter is empty");
|
assignments.add(QueryBuilder.remove(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
addPropertyNode(p);
|
||||||
Object valueObj = prepareSingleSetValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.remove(p.getColumnName(), valueObj));
|
public <V> UpdateOperation removeAll(Getter<Set<V>> setGetter, Set<V> value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(setGetter, "setGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(value, "value is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <V> UpdateOperation removeAll(Getter<Set<V>> setGetter, Set<V> value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
||||||
|
Set valueObj = prepareSetValue(p, value);
|
||||||
|
|
||||||
Objects.requireNonNull(setGetter, "setGetter is empty");
|
assignments.add(QueryBuilder.removeAll(p.getColumnName(), valueObj));
|
||||||
Objects.requireNonNull(value, "value is empty");
|
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(setGetter);
|
addPropertyNode(p);
|
||||||
Set valueObj = prepareSetValue(p, value);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assignments.add(QueryBuilder.removeAll(p.getColumnName(), valueObj));
|
private Object prepareSingleSetValue(HelenusPropertyNode p, Object value) {
|
||||||
|
|
||||||
addPropertyNode(p);
|
HelenusProperty prop = p.getProperty();
|
||||||
return this;
|
Object valueObj = value;
|
||||||
}
|
|
||||||
|
|
||||||
private Object prepareSingleSetValue(HelenusPropertyNode p, Object value) {
|
Optional<Function<Object, Object>> converter =
|
||||||
|
prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
|
if (converter.isPresent()) {
|
||||||
|
Set convertedSet = (Set) converter.get().apply(Immutables.setOf(value));
|
||||||
|
valueObj = convertedSet.iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
HelenusProperty prop = p.getProperty();
|
return valueObj;
|
||||||
Object valueObj = value;
|
}
|
||||||
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
private Set prepareSetValue(HelenusPropertyNode p, Set value) {
|
||||||
if (converter.isPresent()) {
|
|
||||||
Set convertedSet = (Set) converter.get().apply(Immutables.setOf(value));
|
|
||||||
valueObj = convertedSet.iterator().next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return valueObj;
|
HelenusProperty prop = p.getProperty();
|
||||||
}
|
Set valueObj = value;
|
||||||
|
|
||||||
private Set prepareSetValue(HelenusPropertyNode p, Set value) {
|
Optional<Function<Object, Object>> converter =
|
||||||
|
prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
|
if (converter.isPresent()) {
|
||||||
|
valueObj = (Set) converter.get().apply(value);
|
||||||
|
}
|
||||||
|
|
||||||
HelenusProperty prop = p.getProperty();
|
return valueObj;
|
||||||
Set valueObj = value;
|
}
|
||||||
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
/*
|
||||||
if (converter.isPresent()) {
|
*
|
||||||
valueObj = (Set) converter.get().apply(value);
|
*
|
||||||
}
|
* MAP
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
return valueObj;
|
public <K, V> UpdateOperation put(Getter<Map<K, V>> mapGetter, K key, V value) {
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
Objects.requireNonNull(mapGetter, "mapGetter is empty");
|
||||||
*
|
Objects.requireNonNull(key, "key is empty");
|
||||||
*
|
|
||||||
* MAP
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public <K, V> UpdateOperation put(Getter<Map<K, V>> mapGetter, K key, V value) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
||||||
|
HelenusProperty prop = p.getProperty();
|
||||||
|
|
||||||
Objects.requireNonNull(mapGetter, "mapGetter is empty");
|
Optional<Function<Object, Object>> converter =
|
||||||
Objects.requireNonNull(key, "key is empty");
|
prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
|
if (converter.isPresent()) {
|
||||||
|
Map<Object, Object> convertedMap =
|
||||||
|
(Map<Object, Object>) converter.get().apply(Immutables.mapOf(key, value));
|
||||||
|
for (Map.Entry<Object, Object> e : convertedMap.entrySet()) {
|
||||||
|
assignments.add(QueryBuilder.put(p.getColumnName(), e.getKey(), e.getValue()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assignments.add(QueryBuilder.put(p.getColumnName(), key, value));
|
||||||
|
}
|
||||||
|
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
addPropertyNode(p);
|
||||||
HelenusProperty prop = p.getProperty();
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
public <K, V> UpdateOperation putAll(Getter<Map<K, V>> mapGetter, Map<K, V> map) {
|
||||||
if (converter.isPresent()) {
|
|
||||||
Map<Object, Object> convertedMap = (Map<Object, Object>) converter.get()
|
|
||||||
.apply(Immutables.mapOf(key, value));
|
|
||||||
for (Map.Entry<Object, Object> e : convertedMap.entrySet()) {
|
|
||||||
assignments.add(QueryBuilder.put(p.getColumnName(), e.getKey(), e.getValue()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assignments.add(QueryBuilder.put(p.getColumnName(), key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
addPropertyNode(p);
|
Objects.requireNonNull(mapGetter, "mapGetter is empty");
|
||||||
return this;
|
Objects.requireNonNull(map, "map is empty");
|
||||||
}
|
|
||||||
|
|
||||||
public <K, V> UpdateOperation putAll(Getter<Map<K, V>> mapGetter, Map<K, V> map) {
|
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
||||||
|
HelenusProperty prop = p.getProperty();
|
||||||
Objects.requireNonNull(mapGetter, "mapGetter is empty");
|
|
||||||
Objects.requireNonNull(map, "map is empty");
|
Optional<Function<Object, Object>> converter =
|
||||||
|
prop.getWriteConverter(sessionOps.getSessionRepository());
|
||||||
HelenusPropertyNode p = MappingUtil.resolveMappingProperty(mapGetter);
|
if (converter.isPresent()) {
|
||||||
HelenusProperty prop = p.getProperty();
|
Map convertedMap = (Map) converter.get().apply(map);
|
||||||
|
assignments.add(QueryBuilder.putAll(p.getColumnName(), convertedMap));
|
||||||
Optional<Function<Object, Object>> converter = prop.getWriteConverter(sessionOps.getSessionRepository());
|
} else {
|
||||||
if (converter.isPresent()) {
|
assignments.add(QueryBuilder.putAll(p.getColumnName(), map));
|
||||||
Map convertedMap = (Map) converter.get().apply(map);
|
}
|
||||||
assignments.add(QueryBuilder.putAll(p.getColumnName(), convertedMap));
|
|
||||||
} else {
|
addPropertyNode(p);
|
||||||
assignments.add(QueryBuilder.putAll(p.getColumnName(), map));
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addPropertyNode(p);
|
@Override
|
||||||
return this;
|
public BuiltStatement buildStatement() {
|
||||||
}
|
|
||||||
|
if (entity == null) {
|
||||||
@Override
|
throw new HelenusMappingException("empty update operation");
|
||||||
public BuiltStatement buildStatement() {
|
}
|
||||||
|
|
||||||
if (entity == null) {
|
Update update = QueryBuilder.update(entity.getName().toCql());
|
||||||
throw new HelenusMappingException("empty update operation");
|
|
||||||
}
|
for (Assignment assignment : assignments) {
|
||||||
|
update.with(assignment);
|
||||||
Update update = QueryBuilder.update(entity.getName().toCql());
|
}
|
||||||
|
|
||||||
for (Assignment assignment : assignments) {
|
if (filters != null && !filters.isEmpty()) {
|
||||||
update.with(assignment);
|
|
||||||
}
|
for (Filter<?> filter : filters) {
|
||||||
|
update.where(filter.getClause(sessionOps.getValuePreparer()));
|
||||||
if (filters != null && !filters.isEmpty()) {
|
}
|
||||||
|
}
|
||||||
for (Filter<?> filter : filters) {
|
|
||||||
update.where(filter.getClause(sessionOps.getValuePreparer()));
|
if (ifFilters != null && !ifFilters.isEmpty()) {
|
||||||
}
|
|
||||||
}
|
for (Filter<?> filter : ifFilters) {
|
||||||
|
update.onlyIf(filter.getClause(sessionOps.getValuePreparer()));
|
||||||
if (ifFilters != null && !ifFilters.isEmpty()) {
|
}
|
||||||
|
}
|
||||||
for (Filter<?> filter : ifFilters) {
|
|
||||||
update.onlyIf(filter.getClause(sessionOps.getValuePreparer()));
|
if (this.ttl != null) {
|
||||||
}
|
update.using(QueryBuilder.ttl(this.ttl[0]));
|
||||||
}
|
}
|
||||||
|
if (this.timestamp != null) {
|
||||||
if (this.ttl != null) {
|
update.using(QueryBuilder.timestamp(this.timestamp[0]));
|
||||||
update.using(QueryBuilder.ttl(this.ttl[0]));
|
}
|
||||||
}
|
|
||||||
if (this.timestamp != null) {
|
return update;
|
||||||
update.using(QueryBuilder.timestamp(this.timestamp[0]));
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
return update;
|
public ResultSet transform(ResultSet resultSet) {
|
||||||
}
|
return resultSet;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public ResultSet transform(ResultSet resultSet) {
|
public UpdateOperation usingTtl(int ttl) {
|
||||||
return resultSet;
|
this.ttl = new int[1];
|
||||||
}
|
this.ttl[0] = ttl;
|
||||||
|
return this;
|
||||||
public UpdateOperation usingTtl(int ttl) {
|
}
|
||||||
this.ttl = new int[1];
|
|
||||||
this.ttl[0] = ttl;
|
public UpdateOperation usingTimestamp(long timestamp) {
|
||||||
return this;
|
this.timestamp = new long[1];
|
||||||
}
|
this.timestamp[0] = timestamp;
|
||||||
|
return this;
|
||||||
public UpdateOperation usingTimestamp(long timestamp) {
|
}
|
||||||
this.timestamp = new long[1];
|
|
||||||
this.timestamp[0] = timestamp;
|
private void addPropertyNode(HelenusPropertyNode p) {
|
||||||
return this;
|
if (entity == null) {
|
||||||
}
|
entity = p.getEntity();
|
||||||
|
} else if (entity != p.getEntity()) {
|
||||||
private void addPropertyNode(HelenusPropertyNode p) {
|
throw new HelenusMappingException(
|
||||||
if (entity == null) {
|
"you can update columns only in single entity "
|
||||||
entity = p.getEntity();
|
+ entity.getMappingInterface()
|
||||||
} else if (entity != p.getEntity()) {
|
+ " or "
|
||||||
throw new HelenusMappingException("you can update columns only in single entity "
|
+ p.getEntity().getMappingInterface());
|
||||||
+ entity.getMappingInterface() + " or " + p.getEntity().getMappingInterface());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,36 +19,41 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public enum DefaultPrimitiveTypes {
|
public enum DefaultPrimitiveTypes {
|
||||||
|
BOOLEAN(boolean.class, false),
|
||||||
|
BYTE(byte.class, (byte) 0x0),
|
||||||
|
CHAR(char.class, (char) 0x0),
|
||||||
|
SHORT(short.class, (short) 0),
|
||||||
|
INT(int.class, 0),
|
||||||
|
LONG(long.class, 0L),
|
||||||
|
FLOAT(float.class, 0.0f),
|
||||||
|
DOUBLE(double.class, 0.0);
|
||||||
|
|
||||||
BOOLEAN(boolean.class, false), BYTE(byte.class, (byte) 0x0), CHAR(char.class, (char) 0x0), SHORT(short.class,
|
private final Class<?> primitiveClass;
|
||||||
(short) 0), INT(int.class, 0), LONG(long.class, 0L), FLOAT(float.class, 0.0f), DOUBLE(double.class, 0.0);
|
private final Object defaultValue;
|
||||||
|
|
||||||
private final Class<?> primitiveClass;
|
private static final Map<Class<?>, DefaultPrimitiveTypes> map =
|
||||||
private final Object defaultValue;
|
new HashMap<Class<?>, DefaultPrimitiveTypes>();
|
||||||
|
|
||||||
private final static Map<Class<?>, DefaultPrimitiveTypes> map = new HashMap<Class<?>, DefaultPrimitiveTypes>();
|
static {
|
||||||
|
for (DefaultPrimitiveTypes type : DefaultPrimitiveTypes.values()) {
|
||||||
|
map.put(type.getPrimitiveClass(), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static {
|
private DefaultPrimitiveTypes(Class<?> primitiveClass, Object defaultValue) {
|
||||||
for (DefaultPrimitiveTypes type : DefaultPrimitiveTypes.values()) {
|
this.primitiveClass = primitiveClass;
|
||||||
map.put(type.getPrimitiveClass(), type);
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private DefaultPrimitiveTypes(Class<?> primitiveClass, Object defaultValue) {
|
public static DefaultPrimitiveTypes lookup(Class<?> primitiveClass) {
|
||||||
this.primitiveClass = primitiveClass;
|
return map.get(primitiveClass);
|
||||||
this.defaultValue = defaultValue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static DefaultPrimitiveTypes lookup(Class<?> primitiveClass) {
|
public Class<?> getPrimitiveClass() {
|
||||||
return map.get(primitiveClass);
|
return primitiveClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getPrimitiveClass() {
|
|
||||||
return primitiveClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getDefaultValue() {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public Object getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@ import java.util.Set;
|
||||||
|
|
||||||
public interface Drafted<T> extends MapExportable {
|
public interface Drafted<T> extends MapExportable {
|
||||||
|
|
||||||
Set<String> mutated();
|
Set<String> mutated();
|
||||||
|
|
||||||
T build();
|
|
||||||
|
|
||||||
|
T build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,10 @@ import net.helenus.mapping.HelenusEntity;
|
||||||
|
|
||||||
public interface DslExportable {
|
public interface DslExportable {
|
||||||
|
|
||||||
public static final String GET_ENTITY_METHOD = "getHelenusMappingEntity";
|
public static final String GET_ENTITY_METHOD = "getHelenusMappingEntity";
|
||||||
public static final String GET_PARENT_METHOD = "getParentDslHelenusPropertyNode";
|
public static final String GET_PARENT_METHOD = "getParentDslHelenusPropertyNode";
|
||||||
|
|
||||||
HelenusEntity getHelenusMappingEntity();
|
HelenusEntity getHelenusMappingEntity();
|
||||||
|
|
||||||
HelenusPropertyNode getParentDslHelenusPropertyNode();
|
|
||||||
|
|
||||||
|
HelenusPropertyNode getParentDslHelenusPropertyNode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,18 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.reflect;
|
package net.helenus.core.reflect;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import com.datastax.driver.core.*;
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.datastax.driver.core.*;
|
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusMappingEntity;
|
import net.helenus.mapping.HelenusMappingEntity;
|
||||||
|
@ -39,144 +34,148 @@ import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
public class DslInvocationHandler<E> implements InvocationHandler {
|
public class DslInvocationHandler<E> implements InvocationHandler {
|
||||||
|
|
||||||
private final HelenusEntity entity;
|
private final HelenusEntity entity;
|
||||||
private final Optional<HelenusPropertyNode> parent;
|
private final Optional<HelenusPropertyNode> parent;
|
||||||
|
|
||||||
private final Map<Method, HelenusProperty> map = new HashMap<Method, HelenusProperty>();
|
private final Map<Method, HelenusProperty> map = new HashMap<Method, HelenusProperty>();
|
||||||
|
|
||||||
private final Map<Method, Object> udtMap = new HashMap<Method, Object>();
|
private final Map<Method, Object> udtMap = new HashMap<Method, Object>();
|
||||||
private final Map<Method, Object> tupleMap = new HashMap<Method, Object>();
|
private final Map<Method, Object> tupleMap = new HashMap<Method, Object>();
|
||||||
|
|
||||||
public DslInvocationHandler(Class<E> iface, ClassLoader classLoader, Optional<HelenusPropertyNode> parent, Metadata metadata) {
|
public DslInvocationHandler(
|
||||||
|
Class<E> iface,
|
||||||
|
ClassLoader classLoader,
|
||||||
|
Optional<HelenusPropertyNode> parent,
|
||||||
|
Metadata metadata) {
|
||||||
|
|
||||||
this.entity = new HelenusMappingEntity(iface, metadata);
|
this.entity = new HelenusMappingEntity(iface, metadata);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
|
||||||
if (this.entity != null) {
|
if (this.entity != null) {
|
||||||
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 = Helenus.dsl(javaType, classLoader,
|
Object childDsl =
|
||||||
Optional.of(new HelenusPropertyNode(prop, parent)), metadata);
|
Helenus.dsl(
|
||||||
|
javaType,
|
||||||
|
classLoader,
|
||||||
|
Optional.of(new HelenusPropertyNode(prop, parent)),
|
||||||
|
metadata);
|
||||||
|
|
||||||
udtMap.put(prop.getGetterMethod(), childDsl);
|
udtMap.put(prop.getGetterMethod(), childDsl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type instanceof DTDataType) {
|
if (type instanceof DTDataType) {
|
||||||
DTDataType dataType = (DTDataType) type;
|
DTDataType dataType = (DTDataType) type;
|
||||||
|
|
||||||
if (dataType.getDataType() instanceof TupleType && !TupleValue.class.isAssignableFrom(javaType)) {
|
if (dataType.getDataType() instanceof TupleType
|
||||||
|
&& !TupleValue.class.isAssignableFrom(javaType)) {
|
||||||
|
|
||||||
Object childDsl = Helenus.dsl(javaType, classLoader,
|
Object childDsl =
|
||||||
Optional.of(new HelenusPropertyNode(prop, parent)), metadata);
|
Helenus.dsl(
|
||||||
|
javaType,
|
||||||
|
classLoader,
|
||||||
|
Optional.of(new HelenusPropertyNode(prop, parent)),
|
||||||
|
metadata);
|
||||||
|
|
||||||
tupleMap.put(prop.getGetterMethod(), childDsl);
|
tupleMap.put(prop.getGetterMethod(), childDsl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
}
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
|
||||||
|
String methodName = method.getName();
|
||||||
|
|
||||||
|
if ("equals".equals(methodName) && method.getParameterCount() == 1) {
|
||||||
|
Object otherObj = args[0];
|
||||||
|
if (otherObj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Proxy.isProxyClass(otherObj.getClass())) {
|
||||||
|
return this == Proxy.getInvocationHandler(otherObj);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
|
||||||
|
throw new HelenusException("invalid getter method " + method);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("hashCode".equals(methodName)) {
|
||||||
|
return hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("toString".equals(methodName)) {
|
||||||
|
return entity.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DslExportable.GET_ENTITY_METHOD.equals(methodName)) {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DslExportable.GET_PARENT_METHOD.equals(methodName)) {
|
||||||
|
return parent.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
HelenusProperty prop = map.get(method);
|
||||||
|
if (prop == null) {
|
||||||
|
prop = entity.getProperty(methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop != null) {
|
||||||
|
|
||||||
|
AbstractDataType type = prop.getDataType();
|
||||||
|
|
||||||
|
if (type instanceof UDTDataType) {
|
||||||
|
|
||||||
|
Object childDsl = udtMap.get(method);
|
||||||
|
|
||||||
|
if (childDsl != null) {
|
||||||
|
return childDsl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type instanceof DTDataType) {
|
||||||
|
DTDataType dataType = (DTDataType) type;
|
||||||
|
DataType dt = dataType.getDataType();
|
||||||
|
|
||||||
|
switch (dt.getName()) {
|
||||||
|
case TUPLE:
|
||||||
|
Object childDsl = tupleMap.get(method);
|
||||||
|
|
||||||
|
if (childDsl != null) {
|
||||||
|
return childDsl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SET:
|
||||||
|
return new SetDsl(new HelenusPropertyNode(prop, parent));
|
||||||
|
|
||||||
|
case LIST:
|
||||||
|
return new ListDsl(new HelenusPropertyNode(prop, parent));
|
||||||
|
|
||||||
|
case MAP:
|
||||||
|
return new MapDsl(new HelenusPropertyNode(prop, parent));
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
throw new DslPropertyException(new HelenusPropertyNode(prop, parent));
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
}
|
||||||
|
|
||||||
String methodName = method.getName();
|
|
||||||
|
|
||||||
if ("equals".equals(methodName) && method.getParameterCount() == 1) {
|
|
||||||
Object otherObj = args[0];
|
|
||||||
if (otherObj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (Proxy.isProxyClass(otherObj.getClass())) {
|
|
||||||
return this == Proxy.getInvocationHandler(otherObj);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
|
|
||||||
throw new HelenusException("invalid getter method " + method);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("hashCode".equals(methodName)) {
|
|
||||||
return hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("toString".equals(methodName)) {
|
|
||||||
return entity.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DslExportable.GET_ENTITY_METHOD.equals(methodName)) {
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DslExportable.GET_PARENT_METHOD.equals(methodName)) {
|
|
||||||
return parent.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HelenusProperty prop = map.get(method);
|
|
||||||
if (prop == null) {
|
|
||||||
prop = entity.getProperty(methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prop != null) {
|
|
||||||
|
|
||||||
AbstractDataType type = prop.getDataType();
|
|
||||||
|
|
||||||
if (type instanceof UDTDataType) {
|
|
||||||
|
|
||||||
Object childDsl = udtMap.get(method);
|
|
||||||
|
|
||||||
if (childDsl != null) {
|
|
||||||
return childDsl;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type instanceof DTDataType) {
|
|
||||||
DTDataType dataType = (DTDataType) type;
|
|
||||||
DataType dt = dataType.getDataType();
|
|
||||||
|
|
||||||
switch (dt.getName()) {
|
|
||||||
|
|
||||||
case TUPLE :
|
|
||||||
|
|
||||||
Object childDsl = tupleMap.get(method);
|
|
||||||
|
|
||||||
if (childDsl != null) {
|
|
||||||
return childDsl;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SET :
|
|
||||||
return new SetDsl(new HelenusPropertyNode(prop, parent));
|
|
||||||
|
|
||||||
case LIST :
|
|
||||||
return new ListDsl(new HelenusPropertyNode(prop, parent));
|
|
||||||
|
|
||||||
case MAP :
|
|
||||||
return new MapDsl(new HelenusPropertyNode(prop, parent));
|
|
||||||
|
|
||||||
default :
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new DslPropertyException(new HelenusPropertyNode(prop, parent));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HelenusException("invalid method call " + method);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
throw new HelenusException("invalid method call " + method);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,7 @@ import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
|
|
||||||
import net.helenus.core.SessionRepository;
|
import net.helenus.core.SessionRepository;
|
||||||
import net.helenus.mapping.*;
|
import net.helenus.mapping.*;
|
||||||
import net.helenus.mapping.type.AbstractDataType;
|
import net.helenus.mapping.type.AbstractDataType;
|
||||||
|
@ -29,77 +27,79 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class HelenusNamedProperty implements HelenusProperty {
|
public final class HelenusNamedProperty implements HelenusProperty {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public HelenusNamedProperty(String name) {
|
public HelenusNamedProperty(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HelenusEntity getEntity() {
|
public HelenusEntity getEntity() {
|
||||||
throw new HelenusMappingException("will never called");
|
throw new HelenusMappingException("will never called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPropertyName() {
|
public String getPropertyName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Method getGetterMethod() {
|
public Method getGetterMethod() {
|
||||||
throw new HelenusMappingException("will never called");
|
throw new HelenusMappingException("will never called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityName getColumnName() {
|
public IdentityName getColumnName() {
|
||||||
return IdentityName.of(name, false);
|
return IdentityName.of(name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<IdentityName> getIndexName() {
|
public Optional<IdentityName> getIndexName() {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean caseSensitiveIndex() { return false; }
|
public boolean caseSensitiveIndex() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getJavaType() {
|
public Class<?> getJavaType() {
|
||||||
throw new HelenusMappingException("will never called");
|
throw new HelenusMappingException("will never called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractDataType getDataType() {
|
public AbstractDataType getDataType() {
|
||||||
throw new HelenusMappingException("will never called");
|
throw new HelenusMappingException("will never called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ColumnType getColumnType() {
|
public ColumnType getColumnType() {
|
||||||
return ColumnType.COLUMN;
|
return ColumnType.COLUMN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOrdinal() {
|
public int getOrdinal() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OrderingDirection getOrdering() {
|
public OrderingDirection getOrdering() {
|
||||||
return OrderingDirection.ASC;
|
return OrderingDirection.ASC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Function<Object, Object>> getReadConverter(SessionRepository repository) {
|
public Optional<Function<Object, Object>> getReadConverter(SessionRepository repository) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Function<Object, Object>> getWriteConverter(SessionRepository repository) {
|
public Optional<Function<Object, Object>> getWriteConverter(SessionRepository repository) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstraintValidator<? extends Annotation, ?>[] getValidators() {
|
public ConstraintValidator<? extends Annotation, ?>[] getValidators() {
|
||||||
return MappingUtil.EMPTY_VALIDATORS;
|
return MappingUtil.EMPTY_VALIDATORS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,92 +17,89 @@ package net.helenus.core.reflect;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
|
|
||||||
public final class HelenusPropertyNode implements Iterable<HelenusProperty> {
|
public final class HelenusPropertyNode implements Iterable<HelenusProperty> {
|
||||||
|
|
||||||
private final HelenusProperty prop;
|
private final HelenusProperty prop;
|
||||||
private final Optional<HelenusPropertyNode> next;
|
private final Optional<HelenusPropertyNode> next;
|
||||||
|
|
||||||
public HelenusPropertyNode(HelenusProperty prop, Optional<HelenusPropertyNode> next) {
|
public HelenusPropertyNode(HelenusProperty prop, Optional<HelenusPropertyNode> next) {
|
||||||
this.prop = prop;
|
this.prop = prop;
|
||||||
this.next = next;
|
this.next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getColumnName() {
|
public String getColumnName() {
|
||||||
if (next.isPresent()) {
|
if (next.isPresent()) {
|
||||||
|
|
||||||
List<String> columnNames = new ArrayList<String>();
|
List<String> columnNames = new ArrayList<String>();
|
||||||
for (HelenusProperty p : this) {
|
for (HelenusProperty p : this) {
|
||||||
columnNames.add(p.getColumnName().toCql(true));
|
columnNames.add(p.getColumnName().toCql(true));
|
||||||
}
|
}
|
||||||
Collections.reverse(columnNames);
|
Collections.reverse(columnNames);
|
||||||
|
|
||||||
if (prop instanceof HelenusNamedProperty) {
|
if (prop instanceof HelenusNamedProperty) {
|
||||||
int size = columnNames.size();
|
int size = columnNames.size();
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
for (int i = 0; i != size - 1; ++i) {
|
for (int i = 0; i != size - 1; ++i) {
|
||||||
if (str.length() != 0) {
|
if (str.length() != 0) {
|
||||||
str.append(".");
|
str.append(".");
|
||||||
}
|
}
|
||||||
str.append(columnNames.get(i));
|
str.append(columnNames.get(i));
|
||||||
}
|
}
|
||||||
str.append("[").append(columnNames.get(size - 1)).append("]");
|
str.append("[").append(columnNames.get(size - 1)).append("]");
|
||||||
return str.toString();
|
return str.toString();
|
||||||
} else {
|
} else {
|
||||||
return columnNames.stream().collect(Collectors.joining("."));
|
return columnNames.stream().collect(Collectors.joining("."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return prop.getColumnName().toCql();
|
return prop.getColumnName().toCql();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusEntity getEntity() {
|
public HelenusEntity getEntity() {
|
||||||
if (next.isPresent()) {
|
if (next.isPresent()) {
|
||||||
HelenusProperty last = prop;
|
HelenusProperty last = prop;
|
||||||
for (HelenusProperty p : this) {
|
for (HelenusProperty p : this) {
|
||||||
last = p;
|
last = p;
|
||||||
}
|
}
|
||||||
return last.getEntity();
|
return last.getEntity();
|
||||||
} else {
|
} else {
|
||||||
return prop.getEntity();
|
return prop.getEntity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusProperty getProperty() {
|
public HelenusProperty getProperty() {
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<HelenusPropertyNode> getNext() {
|
public Optional<HelenusPropertyNode> getNext() {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<HelenusProperty> iterator() {
|
public Iterator<HelenusProperty> iterator() {
|
||||||
return new PropertyNodeIterator(Optional.of(this));
|
return new PropertyNodeIterator(Optional.of(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PropertyNodeIterator implements Iterator<HelenusProperty> {
|
private static class PropertyNodeIterator implements Iterator<HelenusProperty> {
|
||||||
|
|
||||||
private Optional<HelenusPropertyNode> next;
|
private Optional<HelenusPropertyNode> next;
|
||||||
|
|
||||||
public PropertyNodeIterator(Optional<HelenusPropertyNode> next) {
|
public PropertyNodeIterator(Optional<HelenusPropertyNode> next) {
|
||||||
this.next = next;
|
this.next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return next.isPresent();
|
return next.isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public HelenusProperty next() {
|
|
||||||
HelenusPropertyNode node = next.get();
|
|
||||||
next = node.next;
|
|
||||||
return node.prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HelenusProperty next() {
|
||||||
|
HelenusPropertyNode node = next.get();
|
||||||
|
next = node.next;
|
||||||
|
return node.prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,165 +16,164 @@
|
||||||
package net.helenus.core.reflect;
|
package net.helenus.core.reflect;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.support.DslPropertyException;
|
import net.helenus.support.DslPropertyException;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class ListDsl<V> implements List<V> {
|
public final class ListDsl<V> implements List<V> {
|
||||||
|
|
||||||
private final HelenusPropertyNode parent;
|
private final HelenusPropertyNode parent;
|
||||||
|
|
||||||
public ListDsl(HelenusPropertyNode parent) {
|
public ListDsl(HelenusPropertyNode parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusPropertyNode getParent() {
|
public HelenusPropertyNode getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V get(int index) {
|
public V get(int index) {
|
||||||
HelenusProperty prop = new HelenusNamedProperty(Integer.toString(index));
|
HelenusProperty prop = new HelenusNamedProperty(Integer.toString(index));
|
||||||
throw new DslPropertyException(new HelenusPropertyNode(prop, Optional.of(parent)));
|
throw new DslPropertyException(new HelenusPropertyNode(prop, Optional.of(parent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<V> iterator() {
|
public Iterator<V> iterator() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] toArray() {
|
public Object[] toArray() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T[] toArray(T[] a) {
|
public <T> T[] toArray(T[] a) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(V e) {
|
public boolean add(V e) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean remove(Object o) {
|
public boolean remove(Object o) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(Collection<?> c) {
|
public boolean containsAll(Collection<?> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(Collection<? extends V> c) {
|
public boolean addAll(Collection<? extends V> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(int index, Collection<? extends V> c) {
|
public boolean addAll(int index, Collection<? extends V> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAll(Collection<?> c) {
|
public boolean removeAll(Collection<?> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean retainAll(Collection<?> c) {
|
public boolean retainAll(Collection<?> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V set(int index, V element) {
|
public V set(int index, V element) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(int index, V element) {
|
public void add(int index, V element) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V remove(int index) {
|
public V remove(int index) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int indexOf(Object o) {
|
public int indexOf(Object o) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lastIndexOf(Object o) {
|
public int lastIndexOf(Object o) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListIterator<V> listIterator() {
|
public ListIterator<V> listIterator() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListIterator<V> listIterator(int index) {
|
public ListIterator<V> listIterator(int index) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<V> subList(int fromIndex, int toIndex) {
|
public List<V> subList(int fromIndex, int toIndex) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void throwShouldNeverCall() {
|
private void throwShouldNeverCall() {
|
||||||
throw new HelenusMappingException("should be never called");
|
throw new HelenusMappingException("should be never called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ListDsl";
|
return "ListDsl";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,100 +19,98 @@ import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.helenus.mapping.HelenusProperty;
|
import net.helenus.mapping.HelenusProperty;
|
||||||
import net.helenus.support.DslPropertyException;
|
import net.helenus.support.DslPropertyException;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class MapDsl<K, V> implements Map<K, V> {
|
public final class MapDsl<K, V> implements Map<K, V> {
|
||||||
|
|
||||||
private final HelenusPropertyNode parent;
|
private final HelenusPropertyNode parent;
|
||||||
|
|
||||||
public MapDsl(HelenusPropertyNode parent) {
|
public MapDsl(HelenusPropertyNode parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusPropertyNode getParent() {
|
public HelenusPropertyNode getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V get(Object key) {
|
public V get(Object key) {
|
||||||
HelenusProperty prop = new HelenusNamedProperty(key.toString());
|
HelenusProperty prop = new HelenusNamedProperty(key.toString());
|
||||||
throw new DslPropertyException(new HelenusPropertyNode(prop, Optional.of(parent)));
|
throw new DslPropertyException(new HelenusPropertyNode(prop, Optional.of(parent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsKey(Object key) {
|
public boolean containsKey(Object key) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V put(K key, V value) {
|
public V put(K key, V value) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V remove(Object key) {
|
public V remove(Object key) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putAll(Map<? extends K, ? extends V> m) {
|
public void putAll(Map<? extends K, ? extends V> m) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<K> keySet() {
|
public Set<K> keySet() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<V> values() {
|
public Collection<V> values() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<java.util.Map.Entry<K, V>> entrySet() {
|
public Set<java.util.Map.Entry<K, V>> entrySet() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void throwShouldNeverCall() {
|
private void throwShouldNeverCall() {
|
||||||
throw new HelenusMappingException("should be never called");
|
throw new HelenusMappingException("should be never called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "MapDsl";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MapDsl";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ import java.util.Map;
|
||||||
|
|
||||||
public interface MapExportable {
|
public interface MapExportable {
|
||||||
|
|
||||||
public static final String TO_MAP_METHOD = "toMap";
|
public static final String TO_MAP_METHOD = "toMap";
|
||||||
|
|
||||||
Map<String, Object> toMap();
|
|
||||||
|
|
||||||
|
Map<String, Object> toMap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package net.helenus.core.reflect;
|
package net.helenus.core.reflect;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
@ -24,102 +23,101 @@ 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.mapping.annotation.Transient;
|
import net.helenus.mapping.annotation.Transient;
|
||||||
import net.helenus.support.HelenusException;
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
public class MapperInvocationHandler<E> implements InvocationHandler, Serializable {
|
public class MapperInvocationHandler<E> implements InvocationHandler, Serializable {
|
||||||
private static final long serialVersionUID = -7044209982830584984L;
|
private static final long serialVersionUID = -7044209982830584984L;
|
||||||
|
|
||||||
private final Map<String, Object> src;
|
private final Map<String, Object> src;
|
||||||
private final Class<E> iface;
|
private final Class<E> iface;
|
||||||
|
|
||||||
public MapperInvocationHandler(Class<E> iface, Map<String, Object> src) {
|
public MapperInvocationHandler(Class<E> iface, Map<String, Object> src) {
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.iface = iface;
|
this.iface = iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object invokeDefault(Object proxy, Method method, Object[] args) throws Throwable {
|
private Object invokeDefault(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
// NOTE: This is reflection magic to invoke (non-recursively) a default method implemented on an interface
|
// NOTE: This is reflection magic to invoke (non-recursively) a default method implemented on an interface
|
||||||
// that we've proxied (in ReflectionDslInstantiator). I found the answer in this article.
|
// that we've proxied (in ReflectionDslInstantiator). I found the answer in this article.
|
||||||
// https://zeroturnaround.com/rebellabs/recognize-and-conquer-java-proxies-default-methods-and-method-handles/
|
// https://zeroturnaround.com/rebellabs/recognize-and-conquer-java-proxies-default-methods-and-method-handles/
|
||||||
|
|
||||||
// First, we need an instance of a private inner-class found in MethodHandles.
|
// First, we need an instance of a private inner-class found in MethodHandles.
|
||||||
Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class,
|
Constructor<MethodHandles.Lookup> constructor =
|
||||||
int.class);
|
MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
|
||||||
constructor.setAccessible(true);
|
constructor.setAccessible(true);
|
||||||
|
|
||||||
// Now we need to lookup and invoke special the default method on the interface class.
|
// Now we need to lookup and invoke special the default method on the interface class.
|
||||||
final Class<?> declaringClass = method.getDeclaringClass();
|
final Class<?> declaringClass = method.getDeclaringClass();
|
||||||
Object result = constructor.newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
|
Object result =
|
||||||
.unreflectSpecial(method, declaringClass)
|
constructor
|
||||||
.bindTo(proxy)
|
.newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
|
||||||
.invokeWithArguments(args);
|
.unreflectSpecial(method, declaringClass)
|
||||||
return result;
|
.bindTo(proxy)
|
||||||
|
.invokeWithArguments(args);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
|
||||||
|
// Transient, default methods should simply be invoked as-is.
|
||||||
|
if (method.isDefault() && method.getDeclaredAnnotation(Transient.class) != null) {
|
||||||
|
return invokeDefault(proxy, method, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
String methodName = method.getName();
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
|
||||||
|
|
||||||
// Transient, default methods should simply be invoked as-is.
|
if ("equals".equals(methodName) && method.getParameterCount() == 1) {
|
||||||
if (method.isDefault() && method.getDeclaredAnnotation(Transient.class) != null) {
|
Object otherObj = args[0];
|
||||||
return invokeDefault(proxy, method, args);
|
if (otherObj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Proxy.isProxyClass(otherObj.getClass())) {
|
||||||
|
return this == Proxy.getInvocationHandler(otherObj);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
|
||||||
|
throw new HelenusException("invalid getter method " + method);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("hashCode".equals(methodName)) {
|
||||||
|
return hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("toString".equals(methodName)) {
|
||||||
|
return iface.getSimpleName() + ": " + src.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
|
||||||
|
return Collections.unmodifiableMap(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object value = src.get(methodName);
|
||||||
|
|
||||||
|
Class<?> returnType = method.getReturnType();
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
|
||||||
|
// Default implementations of non-Transient methods in entities are the default value when the
|
||||||
|
// map contains 'null'.
|
||||||
|
if (method.isDefault()) {
|
||||||
|
return invokeDefault(proxy, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if the return type of the method is a primitive Java type then we'll return the standard
|
||||||
|
// default values to avoid a NPE in user code.
|
||||||
|
if (returnType.isPrimitive()) {
|
||||||
|
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType);
|
||||||
|
if (type == null) {
|
||||||
|
throw new HelenusException("unknown primitive type " + returnType);
|
||||||
}
|
}
|
||||||
|
return type.getDefaultValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String methodName = method.getName();
|
return value;
|
||||||
|
}
|
||||||
if ("equals".equals(methodName) && method.getParameterCount() == 1) {
|
|
||||||
Object otherObj = args[0];
|
|
||||||
if (otherObj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (Proxy.isProxyClass(otherObj.getClass())) {
|
|
||||||
return this == Proxy.getInvocationHandler(otherObj);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method.getParameterCount() != 0 || method.getReturnType() == void.class) {
|
|
||||||
throw new HelenusException("invalid getter method " + method);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("hashCode".equals(methodName)) {
|
|
||||||
return hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("toString".equals(methodName)) {
|
|
||||||
return iface.getSimpleName() + ": " + src.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MapExportable.TO_MAP_METHOD.equals(methodName)) {
|
|
||||||
return Collections.unmodifiableMap(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object value = src.get(methodName);
|
|
||||||
|
|
||||||
Class<?> returnType = method.getReturnType();
|
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
|
|
||||||
// Default implementations of non-Transient methods in entities are the default value when the
|
|
||||||
// map contains 'null'.
|
|
||||||
if (method.isDefault()) {
|
|
||||||
return invokeDefault(proxy, method, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, if the return type of the method is a primitive Java type then we'll return the standard
|
|
||||||
// default values to avoid a NPE in user code.
|
|
||||||
if (returnType.isPrimitive()) {
|
|
||||||
DefaultPrimitiveTypes type = DefaultPrimitiveTypes.lookup(returnType);
|
|
||||||
if (type == null) {
|
|
||||||
throw new HelenusException("unknown primitive type " + returnType);
|
|
||||||
}
|
|
||||||
return type.getDefaultValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,22 +15,25 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.core.reflect;
|
package net.helenus.core.reflect;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.Metadata;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.datastax.driver.core.Metadata;
|
|
||||||
import net.helenus.core.DslInstantiator;
|
import net.helenus.core.DslInstantiator;
|
||||||
|
|
||||||
public enum ReflectionDslInstantiator implements DslInstantiator {
|
public enum ReflectionDslInstantiator implements DslInstantiator {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
public <E> E instantiate(
|
||||||
@SuppressWarnings("unchecked")
|
Class<E> iface,
|
||||||
public <E> E instantiate(Class<E> iface, ClassLoader classLoader, Optional<HelenusPropertyNode> parent, Metadata metadata) {
|
ClassLoader classLoader,
|
||||||
DslInvocationHandler<E> handler = new DslInvocationHandler<E>(iface, classLoader, parent, metadata);
|
Optional<HelenusPropertyNode> parent,
|
||||||
E proxy = (E) Proxy.newProxyInstance(classLoader, new Class[]{iface, DslExportable.class}, handler);
|
Metadata metadata) {
|
||||||
return proxy;
|
DslInvocationHandler<E> handler =
|
||||||
}
|
new DslInvocationHandler<E>(iface, classLoader, parent, metadata);
|
||||||
|
E proxy =
|
||||||
|
(E) Proxy.newProxyInstance(classLoader, new Class[] {iface, DslExportable.class}, handler);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,14 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class ReflectionInstantiator {
|
public final class ReflectionInstantiator {
|
||||||
|
|
||||||
private ReflectionInstantiator() {
|
private ReflectionInstantiator() {}
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T instantiateClass(Class<T> clazz) {
|
public static <T> T instantiateClass(Class<T> clazz) {
|
||||||
|
|
||||||
try {
|
|
||||||
return clazz.newInstance();
|
|
||||||
} catch (InstantiationException | IllegalAccessException e) {
|
|
||||||
throw new HelenusMappingException("invalid class " + clazz, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
return clazz.newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new HelenusMappingException("invalid class " + clazz, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,21 +17,18 @@ package net.helenus.core.reflect;
|
||||||
|
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.helenus.core.MapperInstantiator;
|
import net.helenus.core.MapperInstantiator;
|
||||||
|
|
||||||
public enum ReflectionMapperInstantiator implements MapperInstantiator {
|
public enum ReflectionMapperInstantiator implements MapperInstantiator {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
public <E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) {
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <E> E instantiate(Class<E> iface, Map<String, Object> src, ClassLoader classLoader) {
|
|
||||||
|
|
||||||
MapperInvocationHandler<E> handler = new MapperInvocationHandler<E>(iface, src);
|
|
||||||
E proxy = (E) Proxy.newProxyInstance(classLoader, new Class[]{iface, MapExportable.class}, handler);
|
|
||||||
return proxy;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
MapperInvocationHandler<E> handler = new MapperInvocationHandler<E>(iface, src);
|
||||||
|
E proxy =
|
||||||
|
(E) Proxy.newProxyInstance(classLoader, new Class[] {iface, MapExportable.class}, handler);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,104 +18,103 @@ package net.helenus.core.reflect;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class SetDsl<V> implements Set<V> {
|
public final class SetDsl<V> implements Set<V> {
|
||||||
|
|
||||||
private final HelenusPropertyNode parent;
|
private final HelenusPropertyNode parent;
|
||||||
|
|
||||||
public SetDsl(HelenusPropertyNode parent) {
|
public SetDsl(HelenusPropertyNode parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusPropertyNode getParent() {
|
public HelenusPropertyNode getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<V> iterator() {
|
public Iterator<V> iterator() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] toArray() {
|
public Object[] toArray() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T[] toArray(T[] a) {
|
public <T> T[] toArray(T[] a) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(V e) {
|
public boolean add(V e) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean remove(Object o) {
|
public boolean remove(Object o) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(Collection<?> c) {
|
public boolean containsAll(Collection<?> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(Collection<? extends V> c) {
|
public boolean addAll(Collection<? extends V> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean retainAll(Collection<?> c) {
|
public boolean retainAll(Collection<?> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAll(Collection<?> c) {
|
public boolean removeAll(Collection<?> c) {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
throwShouldNeverCall();
|
throwShouldNeverCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void throwShouldNeverCall() {
|
private void throwShouldNeverCall() {
|
||||||
throw new HelenusMappingException("should be never called");
|
throw new HelenusMappingException("should be never called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SetDsl";
|
return "SetDsl";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package net.helenus.mapping;
|
package net.helenus.mapping;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import net.helenus.mapping.annotation.ClusteringColumn;
|
import net.helenus.mapping.annotation.ClusteringColumn;
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Column;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
|
@ -25,93 +24,99 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class ColumnInformation {
|
public final class ColumnInformation {
|
||||||
|
|
||||||
private final IdentityName columnName;
|
private final IdentityName columnName;
|
||||||
private final ColumnType columnType;
|
private final ColumnType columnType;
|
||||||
private final int ordinal;
|
private final int ordinal;
|
||||||
private final OrderingDirection ordering;
|
private final OrderingDirection ordering;
|
||||||
|
|
||||||
public ColumnInformation(Method getter) {
|
public ColumnInformation(Method getter) {
|
||||||
|
|
||||||
String columnName = null;
|
String columnName = null;
|
||||||
boolean forceQuote = false;
|
boolean forceQuote = false;
|
||||||
ColumnType columnTypeLocal = ColumnType.COLUMN;
|
ColumnType columnTypeLocal = ColumnType.COLUMN;
|
||||||
int ordinalLocal = 0;
|
int ordinalLocal = 0;
|
||||||
OrderingDirection orderingLocal = OrderingDirection.ASC;
|
OrderingDirection orderingLocal = OrderingDirection.ASC;
|
||||||
|
|
||||||
PartitionKey partitionKey = getter.getDeclaredAnnotation(PartitionKey.class);
|
PartitionKey partitionKey = getter.getDeclaredAnnotation(PartitionKey.class);
|
||||||
if (partitionKey != null) {
|
if (partitionKey != null) {
|
||||||
columnName = partitionKey.value();
|
columnName = partitionKey.value();
|
||||||
forceQuote = partitionKey.forceQuote();
|
forceQuote = partitionKey.forceQuote();
|
||||||
columnTypeLocal = ColumnType.PARTITION_KEY;
|
columnTypeLocal = ColumnType.PARTITION_KEY;
|
||||||
ordinalLocal = partitionKey.ordinal();
|
ordinalLocal = partitionKey.ordinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClusteringColumn clusteringColumn = getter.getDeclaredAnnotation(ClusteringColumn.class);
|
ClusteringColumn clusteringColumn = getter.getDeclaredAnnotation(ClusteringColumn.class);
|
||||||
if (clusteringColumn != null) {
|
if (clusteringColumn != null) {
|
||||||
ensureSingleColumnType(columnTypeLocal, getter);
|
ensureSingleColumnType(columnTypeLocal, getter);
|
||||||
columnName = clusteringColumn.value();
|
columnName = clusteringColumn.value();
|
||||||
forceQuote = clusteringColumn.forceQuote();
|
forceQuote = clusteringColumn.forceQuote();
|
||||||
columnTypeLocal = ColumnType.CLUSTERING_COLUMN;
|
columnTypeLocal = ColumnType.CLUSTERING_COLUMN;
|
||||||
ordinalLocal = clusteringColumn.ordinal();
|
ordinalLocal = clusteringColumn.ordinal();
|
||||||
orderingLocal = clusteringColumn.ordering();
|
orderingLocal = clusteringColumn.ordering();
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticColumn staticColumn = getter.getDeclaredAnnotation(StaticColumn.class);
|
StaticColumn staticColumn = getter.getDeclaredAnnotation(StaticColumn.class);
|
||||||
if (staticColumn != null) {
|
if (staticColumn != null) {
|
||||||
ensureSingleColumnType(columnTypeLocal, getter);
|
ensureSingleColumnType(columnTypeLocal, getter);
|
||||||
columnName = staticColumn.value();
|
columnName = staticColumn.value();
|
||||||
forceQuote = staticColumn.forceQuote();
|
forceQuote = staticColumn.forceQuote();
|
||||||
columnTypeLocal = ColumnType.STATIC_COLUMN;
|
columnTypeLocal = ColumnType.STATIC_COLUMN;
|
||||||
ordinalLocal = staticColumn.ordinal();
|
ordinalLocal = staticColumn.ordinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
Column column = getter.getDeclaredAnnotation(Column.class);
|
Column column = getter.getDeclaredAnnotation(Column.class);
|
||||||
if (column != null) {
|
if (column != null) {
|
||||||
ensureSingleColumnType(columnTypeLocal, getter);
|
ensureSingleColumnType(columnTypeLocal, getter);
|
||||||
columnName = column.value();
|
columnName = column.value();
|
||||||
forceQuote = column.forceQuote();
|
forceQuote = column.forceQuote();
|
||||||
columnTypeLocal = ColumnType.COLUMN;
|
columnTypeLocal = ColumnType.COLUMN;
|
||||||
ordinalLocal = column.ordinal();
|
ordinalLocal = column.ordinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columnName == null || columnName.isEmpty()) {
|
if (columnName == null || columnName.isEmpty()) {
|
||||||
columnName = MappingUtil.getDefaultColumnName(getter);
|
columnName = MappingUtil.getDefaultColumnName(getter);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.columnName = new IdentityName(columnName, forceQuote);
|
this.columnName = new IdentityName(columnName, forceQuote);
|
||||||
this.columnType = columnTypeLocal;
|
this.columnType = columnTypeLocal;
|
||||||
this.ordinal = ordinalLocal;
|
this.ordinal = ordinalLocal;
|
||||||
this.ordering = orderingLocal;
|
this.ordering = orderingLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityName getColumnName() {
|
public IdentityName getColumnName() {
|
||||||
return columnName;
|
return columnName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColumnType getColumnType() {
|
public ColumnType getColumnType() {
|
||||||
return columnType;
|
return columnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOrdinal() {
|
public int getOrdinal() {
|
||||||
return ordinal;
|
return ordinal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OrderingDirection getOrdering() {
|
public OrderingDirection getOrdering() {
|
||||||
return ordering;
|
return ordering;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureSingleColumnType(ColumnType columnTypeLocal, Method getter) {
|
private void ensureSingleColumnType(ColumnType columnTypeLocal, Method getter) {
|
||||||
|
|
||||||
if (columnTypeLocal != ColumnType.COLUMN) {
|
if (columnTypeLocal != ColumnType.COLUMN) {
|
||||||
throw new HelenusMappingException("property can be annotated only by a single column type " + getter);
|
throw new HelenusMappingException(
|
||||||
}
|
"property can be annotated only by a single column type " + getter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ColumnInformation [columnName=" + columnName + ", columnType=" + columnType + ", ordinal=" + ordinal
|
|
||||||
+ ", ordering=" + ordering + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ColumnInformation [columnName="
|
||||||
|
+ columnName
|
||||||
|
+ ", columnType="
|
||||||
|
+ columnType
|
||||||
|
+ ", ordinal="
|
||||||
|
+ ordinal
|
||||||
|
+ ", ordering="
|
||||||
|
+ ordering
|
||||||
|
+ "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,8 @@
|
||||||
package net.helenus.mapping;
|
package net.helenus.mapping;
|
||||||
|
|
||||||
public enum ColumnType {
|
public enum ColumnType {
|
||||||
PARTITION_KEY, CLUSTERING_COLUMN, STATIC_COLUMN, COLUMN;
|
PARTITION_KEY,
|
||||||
|
CLUSTERING_COLUMN,
|
||||||
|
STATIC_COLUMN,
|
||||||
|
COLUMN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,15 @@ import java.util.Collection;
|
||||||
|
|
||||||
public interface HelenusEntity {
|
public interface HelenusEntity {
|
||||||
|
|
||||||
HelenusEntityType getType();
|
HelenusEntityType getType();
|
||||||
|
|
||||||
boolean isCacheable();
|
boolean isCacheable();
|
||||||
|
|
||||||
Class<?> getMappingInterface();
|
Class<?> getMappingInterface();
|
||||||
|
|
||||||
IdentityName getName();
|
IdentityName getName();
|
||||||
|
|
||||||
Collection<HelenusProperty> getOrderedProperties();
|
Collection<HelenusProperty> getOrderedProperties();
|
||||||
|
|
||||||
HelenusProperty getProperty(String name);
|
|
||||||
|
|
||||||
|
HelenusProperty getProperty(String name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,7 @@
|
||||||
package net.helenus.mapping;
|
package net.helenus.mapping;
|
||||||
|
|
||||||
public enum HelenusEntityType {
|
public enum HelenusEntityType {
|
||||||
TABLE, TUPLE, UDT;
|
TABLE,
|
||||||
|
TUPLE,
|
||||||
|
UDT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.mapping;
|
package net.helenus.mapping;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.datastax.driver.core.*;
|
import com.datastax.driver.core.*;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import java.util.*;
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
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;
|
||||||
|
@ -32,239 +28,241 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class HelenusMappingEntity implements HelenusEntity {
|
public final class HelenusMappingEntity implements HelenusEntity {
|
||||||
|
|
||||||
private final Class<?> iface;
|
private final Class<?> iface;
|
||||||
private final HelenusEntityType type;
|
private final HelenusEntityType type;
|
||||||
private final IdentityName name;
|
private final IdentityName name;
|
||||||
private final boolean cacheable;
|
private final boolean cacheable;
|
||||||
private final ImmutableMap<String, Method> methods;
|
private final ImmutableMap<String, Method> methods;
|
||||||
private final ImmutableMap<String, HelenusProperty> props;
|
private final ImmutableMap<String, HelenusProperty> props;
|
||||||
private final ImmutableList<HelenusProperty> orderedProps;
|
private final ImmutableList<HelenusProperty> orderedProps;
|
||||||
|
|
||||||
public HelenusMappingEntity(Class<?> iface, Metadata metadata) {
|
public HelenusMappingEntity(Class<?> iface, Metadata metadata) {
|
||||||
this(iface, autoDetectType(iface), metadata);
|
this(iface, autoDetectType(iface), metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelenusMappingEntity(Class<?> iface, HelenusEntityType type, Metadata metadata) {
|
public HelenusMappingEntity(Class<?> iface, HelenusEntityType type, Metadata metadata) {
|
||||||
|
|
||||||
if (iface == null || !iface.isInterface()) {
|
if (iface == null || !iface.isInterface()) {
|
||||||
throw new IllegalArgumentException("invalid parameter " + iface);
|
throw new IllegalArgumentException("invalid parameter " + iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.iface = iface;
|
this.iface = iface;
|
||||||
this.type = Objects.requireNonNull(type, "type is empty");
|
this.type = Objects.requireNonNull(type, "type is empty");
|
||||||
this.name = resolveName(iface, type);
|
this.name = resolveName(iface, type);
|
||||||
|
|
||||||
HelenusSettings settings = Helenus.settings();
|
HelenusSettings settings = Helenus.settings();
|
||||||
|
|
||||||
|
List<Method> methods = new ArrayList<Method>();
|
||||||
|
|
||||||
List<Method> methods = new ArrayList<Method>();
|
methods.addAll(Arrays.asList(iface.getDeclaredMethods()));
|
||||||
|
for (Class<?> c : iface.getInterfaces()) {
|
||||||
|
methods.addAll(Arrays.asList(c.getDeclaredMethods()));
|
||||||
|
}
|
||||||
|
|
||||||
methods.addAll(Arrays.asList(iface.getDeclaredMethods()));
|
List<HelenusProperty> propsLocal = new ArrayList<HelenusProperty>();
|
||||||
for (Class<?> c : iface.getInterfaces()) {
|
ImmutableMap.Builder<String, HelenusProperty> propsBuilder = ImmutableMap.builder();
|
||||||
methods.addAll(Arrays.asList(c.getDeclaredMethods()));
|
ImmutableMap.Builder<String, Method> methodsBuilder = ImmutableMap.builder();
|
||||||
|
|
||||||
|
for (Method method : methods) {
|
||||||
|
|
||||||
|
if (settings.getGetterMethodDetector().apply(method)) {
|
||||||
|
|
||||||
|
methodsBuilder.put(method.getName(), method);
|
||||||
|
|
||||||
|
if (metadata != null) {
|
||||||
|
HelenusProperty prop = new HelenusMappingProperty(this, method, metadata);
|
||||||
|
|
||||||
|
propsBuilder.put(prop.getPropertyName(), prop);
|
||||||
|
propsLocal.add(prop);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<HelenusProperty> propsLocal = new ArrayList<HelenusProperty>();
|
this.methods = methodsBuilder.build();
|
||||||
ImmutableMap.Builder<String, HelenusProperty> propsBuilder = ImmutableMap.builder();
|
this.props = propsBuilder.build();
|
||||||
ImmutableMap.Builder<String, Method> methodsBuilder = ImmutableMap.builder();
|
|
||||||
|
|
||||||
for (Method method : methods) {
|
Collections.sort(propsLocal, TypeAndOrdinalColumnComparator.INSTANCE);
|
||||||
|
this.orderedProps = ImmutableList.copyOf(propsLocal);
|
||||||
|
|
||||||
if (settings.getGetterMethodDetector().apply(method)) {
|
validateOrdinals();
|
||||||
|
|
||||||
methodsBuilder.put(method.getName(), method);
|
cacheable = (null != iface.getDeclaredAnnotation(Cacheable.class));
|
||||||
|
}
|
||||||
|
|
||||||
if (metadata != null) {
|
@Override
|
||||||
HelenusProperty prop = new HelenusMappingProperty(this, method, metadata);
|
public HelenusEntityType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
propsBuilder.put(prop.getPropertyName(), prop);
|
@Override
|
||||||
propsLocal.add(prop);
|
public boolean isCacheable() {
|
||||||
}
|
return cacheable;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public Class<?> getMappingInterface() {
|
||||||
|
return iface;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public Collection<HelenusProperty> getOrderedProperties() {
|
||||||
|
return orderedProps;
|
||||||
|
}
|
||||||
|
|
||||||
this.methods = methodsBuilder.build();
|
@Override
|
||||||
this.props = propsBuilder.build();
|
public HelenusProperty getProperty(String name) {
|
||||||
|
HelenusProperty property = props.get(name);
|
||||||
|
if (property == null && methods.containsKey(name)) {
|
||||||
|
property = new HelenusMappingProperty(this, methods.get(name), new DefaultMetadata());
|
||||||
|
return property; //TODO(gburd): review adding these into the props map...
|
||||||
|
}
|
||||||
|
return props.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
Collections.sort(propsLocal, TypeAndOrdinalColumnComparator.INSTANCE);
|
@Override
|
||||||
this.orderedProps = ImmutableList.copyOf(propsLocal);
|
public IdentityName getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
validateOrdinals();
|
private static IdentityName resolveName(Class<?> iface, HelenusEntityType type) {
|
||||||
|
|
||||||
cacheable = (null != iface.getDeclaredAnnotation(Cacheable.class));
|
switch (type) {
|
||||||
}
|
case TABLE:
|
||||||
|
return MappingUtil.getTableName(iface, true);
|
||||||
|
|
||||||
@Override
|
case TUPLE:
|
||||||
public HelenusEntityType getType() {
|
return IdentityName.of(MappingUtil.getDefaultEntityName(iface), false);
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
case UDT:
|
||||||
public boolean isCacheable() {
|
return MappingUtil.getUserDefinedTypeName(iface, true);
|
||||||
return cacheable;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
throw new HelenusMappingException("invalid entity type " + type + " in " + type);
|
||||||
public Class<?> getMappingInterface() {
|
}
|
||||||
return iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private static HelenusEntityType autoDetectType(Class<?> iface) {
|
||||||
public Collection<HelenusProperty> getOrderedProperties() {
|
|
||||||
return orderedProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
Objects.requireNonNull(iface, "empty iface");
|
||||||
public HelenusProperty getProperty(String name) {
|
|
||||||
HelenusProperty property = props.get(name);
|
|
||||||
if (property == null && methods.containsKey(name)) {
|
|
||||||
property = new HelenusMappingProperty(this, methods.get(name), new DefaultMetadata());
|
|
||||||
return property; //TODO(gburd): review adding these into the props map...
|
|
||||||
}
|
|
||||||
return props.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (null != iface.getDeclaredAnnotation(Table.class)) {
|
||||||
public IdentityName getName() {
|
return HelenusEntityType.TABLE;
|
||||||
return name;
|
} else if (null != iface.getDeclaredAnnotation(Tuple.class)) {
|
||||||
}
|
return HelenusEntityType.TUPLE;
|
||||||
|
} else if (null != iface.getDeclaredAnnotation(UDT.class)) {
|
||||||
|
return HelenusEntityType.UDT;
|
||||||
|
}
|
||||||
|
|
||||||
private static IdentityName resolveName(Class<?> iface, HelenusEntityType type) {
|
throw new HelenusMappingException(
|
||||||
|
"entity must be annotated by @Table or @Tuple or @UserDefinedType " + iface);
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
private void validateOrdinals() {
|
||||||
|
|
||||||
case TABLE :
|
switch (getType()) {
|
||||||
return MappingUtil.getTableName(iface, true);
|
case TABLE:
|
||||||
|
validateOrdinalsForTable();
|
||||||
|
break;
|
||||||
|
|
||||||
case TUPLE :
|
case TUPLE:
|
||||||
return IdentityName.of(MappingUtil.getDefaultEntityName(iface), false);
|
validateOrdinalsInTuple();
|
||||||
|
break;
|
||||||
|
|
||||||
case UDT :
|
default:
|
||||||
return MappingUtil.getUserDefinedTypeName(iface, true);
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new HelenusMappingException("invalid entity type " + type + " in " + type);
|
private void validateOrdinalsForTable() {
|
||||||
|
|
||||||
}
|
BitSet partitionKeys = new BitSet();
|
||||||
|
BitSet clusteringColumns = new BitSet();
|
||||||
|
|
||||||
private static HelenusEntityType autoDetectType(Class<?> iface) {
|
for (HelenusProperty prop : getOrderedProperties()) {
|
||||||
|
|
||||||
Objects.requireNonNull(iface, "empty iface");
|
ColumnType type = prop.getColumnType();
|
||||||
|
|
||||||
if (null != iface.getDeclaredAnnotation(Table.class)) {
|
int ordinal = prop.getOrdinal();
|
||||||
return HelenusEntityType.TABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (null != iface.getDeclaredAnnotation(Tuple.class)) {
|
switch (type) {
|
||||||
return HelenusEntityType.TUPLE;
|
case PARTITION_KEY:
|
||||||
}
|
if (partitionKeys.get(ordinal)) {
|
||||||
|
throw new HelenusMappingException(
|
||||||
|
"detected two or more partition key columns with the same ordinal "
|
||||||
|
+ ordinal
|
||||||
|
+ " in "
|
||||||
|
+ prop.getEntity());
|
||||||
|
}
|
||||||
|
partitionKeys.set(ordinal);
|
||||||
|
break;
|
||||||
|
|
||||||
else if (null != iface.getDeclaredAnnotation(UDT.class)) {
|
case CLUSTERING_COLUMN:
|
||||||
return HelenusEntityType.UDT;
|
if (clusteringColumns.get(ordinal)) {
|
||||||
}
|
throw new HelenusMappingException(
|
||||||
|
"detected two or clustering columns with the same ordinal "
|
||||||
|
+ ordinal
|
||||||
|
+ " in "
|
||||||
|
+ prop.getEntity());
|
||||||
|
}
|
||||||
|
clusteringColumns.set(ordinal);
|
||||||
|
break;
|
||||||
|
|
||||||
throw new HelenusMappingException("entity must be annotated by @Table or @Tuple or @UserDefinedType " + iface);
|
default:
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void validateOrdinals() {
|
private void validateOrdinalsInTuple() {
|
||||||
|
boolean[] ordinals = new boolean[props.size()];
|
||||||
|
|
||||||
switch (getType()) {
|
getOrderedProperties()
|
||||||
|
.forEach(
|
||||||
|
p -> {
|
||||||
|
int ordinal = p.getOrdinal();
|
||||||
|
|
||||||
case TABLE :
|
if (ordinal < 0 || ordinal >= ordinals.length) {
|
||||||
validateOrdinalsForTable();
|
throw new HelenusMappingException(
|
||||||
break;
|
"invalid ordinal "
|
||||||
|
+ ordinal
|
||||||
|
+ " found for property "
|
||||||
|
+ p.getPropertyName()
|
||||||
|
+ " in "
|
||||||
|
+ p.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
case TUPLE :
|
if (ordinals[ordinal]) {
|
||||||
validateOrdinalsInTuple();
|
throw new HelenusMappingException(
|
||||||
break;
|
"detected two or more properties with the same ordinal "
|
||||||
|
+ ordinal
|
||||||
|
+ " in "
|
||||||
|
+ p.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
default :
|
ordinals[ordinal] = true;
|
||||||
break;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
}
|
for (int i = 0; i != ordinals.length; ++i) {
|
||||||
|
if (!ordinals[i]) {
|
||||||
|
throw new HelenusMappingException("detected absent ordinal " + i + " in " + this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void validateOrdinalsForTable() {
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
BitSet partitionKeys = new BitSet();
|
StringBuilder str = new StringBuilder();
|
||||||
BitSet clusteringColumns = new BitSet();
|
str.append(iface.getSimpleName())
|
||||||
|
.append("(")
|
||||||
for (HelenusProperty prop : getOrderedProperties()) {
|
.append(name.getName())
|
||||||
|
.append(") ")
|
||||||
ColumnType type = prop.getColumnType();
|
.append(type.name().toLowerCase())
|
||||||
|
.append(":\n");
|
||||||
int ordinal = prop.getOrdinal();
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
|
|
||||||
case PARTITION_KEY :
|
|
||||||
if (partitionKeys.get(ordinal)) {
|
|
||||||
throw new HelenusMappingException(
|
|
||||||
"detected two or more partition key columns with the same ordinal " + ordinal + " in "
|
|
||||||
+ prop.getEntity());
|
|
||||||
}
|
|
||||||
partitionKeys.set(ordinal);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CLUSTERING_COLUMN :
|
|
||||||
if (clusteringColumns.get(ordinal)) {
|
|
||||||
throw new HelenusMappingException("detected two or clustering columns with the same ordinal "
|
|
||||||
+ ordinal + " in " + prop.getEntity());
|
|
||||||
}
|
|
||||||
clusteringColumns.set(ordinal);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default :
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateOrdinalsInTuple() {
|
|
||||||
boolean[] ordinals = new boolean[props.size()];
|
|
||||||
|
|
||||||
getOrderedProperties().forEach(p -> {
|
|
||||||
|
|
||||||
int ordinal = p.getOrdinal();
|
|
||||||
|
|
||||||
if (ordinal < 0 || ordinal >= ordinals.length) {
|
|
||||||
throw new HelenusMappingException("invalid ordinal " + ordinal + " found for property "
|
|
||||||
+ p.getPropertyName() + " in " + p.getEntity());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ordinals[ordinal]) {
|
|
||||||
throw new HelenusMappingException(
|
|
||||||
"detected two or more properties with the same ordinal " + ordinal + " in " + p.getEntity());
|
|
||||||
}
|
|
||||||
|
|
||||||
ordinals[ordinal] = true;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
for (int i = 0; i != ordinals.length; ++i) {
|
|
||||||
if (!ordinals[i]) {
|
|
||||||
throw new HelenusMappingException("detected absent ordinal " + i + " in " + this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
|
|
||||||
StringBuilder str = new StringBuilder();
|
|
||||||
str.append(iface.getSimpleName()).append("(").append(name.getName()).append(") ")
|
|
||||||
.append(type.name().toLowerCase()).append(":\n");
|
|
||||||
|
|
||||||
for (HelenusProperty prop : getOrderedProperties()) {
|
|
||||||
str.append(prop.toString());
|
|
||||||
str.append("\n");
|
|
||||||
}
|
|
||||||
return str.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (HelenusProperty prop : getOrderedProperties()) {
|
||||||
|
str.append(prop.toString());
|
||||||
|
str.append("\n");
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.mapping;
|
package net.helenus.mapping;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.Metadata;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
|
|
||||||
import com.datastax.driver.core.Metadata;
|
|
||||||
import net.helenus.core.SessionRepository;
|
import net.helenus.core.SessionRepository;
|
||||||
import net.helenus.mapping.javatype.AbstractJavaType;
|
import net.helenus.mapping.javatype.AbstractJavaType;
|
||||||
import net.helenus.mapping.javatype.MappingJavaTypes;
|
import net.helenus.mapping.javatype.MappingJavaTypes;
|
||||||
|
@ -31,176 +29,174 @@ import net.helenus.mapping.type.AbstractDataType;
|
||||||
|
|
||||||
public final class HelenusMappingProperty implements HelenusProperty {
|
public final class HelenusMappingProperty implements HelenusProperty {
|
||||||
|
|
||||||
private final HelenusEntity entity;
|
private final HelenusEntity entity;
|
||||||
private final Method getter;
|
private final Method getter;
|
||||||
|
|
||||||
private final String propertyName;
|
private final String propertyName;
|
||||||
private final Optional<IdentityName> indexName;
|
private final Optional<IdentityName> indexName;
|
||||||
private final boolean caseSensitiveIndex;
|
private final boolean caseSensitiveIndex;
|
||||||
|
|
||||||
private final ColumnInformation columnInfo;
|
private final ColumnInformation columnInfo;
|
||||||
|
|
||||||
private final Type genericJavaType;
|
private final Type genericJavaType;
|
||||||
private final Class<?> javaType;
|
private final Class<?> javaType;
|
||||||
private final AbstractJavaType abstractJavaType;
|
private final AbstractJavaType abstractJavaType;
|
||||||
private final AbstractDataType dataType;
|
private final AbstractDataType dataType;
|
||||||
|
|
||||||
private volatile Optional<Function<Object, Object>> readConverter = null;
|
private volatile Optional<Function<Object, Object>> readConverter = null;
|
||||||
private volatile Optional<Function<Object, Object>> writeConverter = null;
|
private volatile Optional<Function<Object, Object>> writeConverter = null;
|
||||||
|
|
||||||
private final ConstraintValidator<? extends Annotation, ?>[] validators;
|
private final ConstraintValidator<? extends Annotation, ?>[] validators;
|
||||||
|
|
||||||
public HelenusMappingProperty(HelenusMappingEntity entity, Method getter, Metadata metadata) {
|
public HelenusMappingProperty(HelenusMappingEntity entity, Method getter, Metadata metadata) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
|
|
||||||
this.propertyName = MappingUtil.getPropertyName(getter);
|
this.propertyName = MappingUtil.getPropertyName(getter);
|
||||||
this.indexName = MappingUtil.getIndexName(getter);
|
this.indexName = MappingUtil.getIndexName(getter);
|
||||||
this.caseSensitiveIndex = MappingUtil.caseSensitiveIndex(getter);
|
this.caseSensitiveIndex = MappingUtil.caseSensitiveIndex(getter);
|
||||||
|
|
||||||
this.columnInfo = new ColumnInformation(getter);
|
this.columnInfo = new ColumnInformation(getter);
|
||||||
|
|
||||||
this.genericJavaType = getter.getGenericReturnType();
|
this.genericJavaType = getter.getGenericReturnType();
|
||||||
this.javaType = getter.getReturnType();
|
this.javaType = getter.getReturnType();
|
||||||
this.abstractJavaType = MappingJavaTypes.resolveJavaType(this.javaType);
|
this.abstractJavaType = MappingJavaTypes.resolveJavaType(this.javaType);
|
||||||
|
|
||||||
this.dataType = abstractJavaType.resolveDataType(this.getter, this.genericJavaType,
|
this.dataType =
|
||||||
this.columnInfo.getColumnType(), metadata);
|
abstractJavaType.resolveDataType(
|
||||||
|
this.getter, this.genericJavaType, this.columnInfo.getColumnType(), metadata);
|
||||||
|
|
||||||
this.validators = MappingUtil.getValidators(getter);
|
this.validators = MappingUtil.getValidators(getter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HelenusEntity getEntity() {
|
public HelenusEntity getEntity() {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getJavaType() {
|
public Class<?> getJavaType() {
|
||||||
return (Class<?>) javaType;
|
return (Class<?>) javaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractDataType getDataType() {
|
public AbstractDataType getDataType() {
|
||||||
return dataType;
|
return dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ColumnType getColumnType() {
|
public ColumnType getColumnType() {
|
||||||
return columnInfo.getColumnType();
|
return columnInfo.getColumnType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOrdinal() {
|
public int getOrdinal() {
|
||||||
return columnInfo.getOrdinal();
|
return columnInfo.getOrdinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OrderingDirection getOrdering() {
|
public OrderingDirection getOrdering() {
|
||||||
return columnInfo.getOrdering();
|
return columnInfo.getOrdering();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityName getColumnName() {
|
public IdentityName getColumnName() {
|
||||||
return columnInfo.getColumnName();
|
return columnInfo.getColumnName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<IdentityName> getIndexName() {
|
public Optional<IdentityName> getIndexName() {
|
||||||
return indexName;
|
return indexName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean caseSensitiveIndex() {
|
public boolean caseSensitiveIndex() {
|
||||||
return caseSensitiveIndex;
|
return caseSensitiveIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPropertyName() {
|
public String getPropertyName() {
|
||||||
return propertyName;
|
return propertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Method getGetterMethod() {
|
public Method getGetterMethod() {
|
||||||
return getter;
|
return getter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Function<Object, Object>> getReadConverter(SessionRepository repository) {
|
public Optional<Function<Object, Object>> getReadConverter(SessionRepository repository) {
|
||||||
|
|
||||||
if (readConverter == null) {
|
if (readConverter == null) {
|
||||||
readConverter = abstractJavaType.resolveReadConverter(this.dataType, repository);
|
readConverter = abstractJavaType.resolveReadConverter(this.dataType, repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
return readConverter;
|
return readConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Function<Object, Object>> getWriteConverter(SessionRepository repository) {
|
public Optional<Function<Object, Object>> getWriteConverter(SessionRepository repository) {
|
||||||
|
|
||||||
if (writeConverter == null) {
|
if (writeConverter == null) {
|
||||||
writeConverter = abstractJavaType.resolveWriteConverter(this.dataType, repository);
|
writeConverter = abstractJavaType.resolveWriteConverter(this.dataType, repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
return writeConverter;
|
return writeConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstraintValidator<? extends Annotation, ?>[] getValidators() {
|
public ConstraintValidator<? extends Annotation, ?>[] getValidators() {
|
||||||
return validators;
|
return validators;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
|
|
||||||
String columnName = this.getColumnName().getName();
|
String columnName = this.getColumnName().getName();
|
||||||
str.append(" ");
|
str.append(" ");
|
||||||
str.append(this.getDataType());
|
str.append(this.getDataType());
|
||||||
str.append(" ");
|
str.append(" ");
|
||||||
str.append(this.getPropertyName());
|
str.append(this.getPropertyName());
|
||||||
str.append("(");
|
str.append("(");
|
||||||
if (!columnName.equals(this.getPropertyName())) {
|
if (!columnName.equals(this.getPropertyName())) {
|
||||||
str.append(columnName);
|
str.append(columnName);
|
||||||
}
|
}
|
||||||
str.append(") ");
|
str.append(") ");
|
||||||
|
|
||||||
ColumnType type = this.getColumnType();
|
ColumnType type = this.getColumnType();
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case PARTITION_KEY:
|
||||||
|
str.append("partition_key[");
|
||||||
|
str.append(this.getOrdinal());
|
||||||
|
str.append("] ");
|
||||||
|
break;
|
||||||
|
|
||||||
case PARTITION_KEY :
|
case CLUSTERING_COLUMN:
|
||||||
str.append("partition_key[");
|
str.append("clustering_column[");
|
||||||
str.append(this.getOrdinal());
|
str.append(this.getOrdinal());
|
||||||
str.append("] ");
|
str.append("] ");
|
||||||
break;
|
OrderingDirection od = this.getOrdering();
|
||||||
|
if (od != null) {
|
||||||
|
str.append(od.name().toLowerCase()).append(" ");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case CLUSTERING_COLUMN :
|
case STATIC_COLUMN:
|
||||||
str.append("clustering_column[");
|
str.append("static ");
|
||||||
str.append(this.getOrdinal());
|
break;
|
||||||
str.append("] ");
|
|
||||||
OrderingDirection od = this.getOrdering();
|
|
||||||
if (od != null) {
|
|
||||||
str.append(od.name().toLowerCase()).append(" ");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STATIC_COLUMN :
|
case COLUMN:
|
||||||
str.append("static ");
|
break;
|
||||||
break;
|
}
|
||||||
|
|
||||||
case COLUMN :
|
Optional<IdentityName> idx = this.getIndexName();
|
||||||
break;
|
if (idx.isPresent()) {
|
||||||
|
str.append("index(").append(idx.get().getName()).append(") ");
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<IdentityName> idx = this.getIndexName();
|
|
||||||
if (idx.isPresent()) {
|
|
||||||
str.append("index(").append(idx.get().getName()).append(") ");
|
|
||||||
}
|
|
||||||
|
|
||||||
return str.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,40 +19,37 @@ import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
|
|
||||||
import net.helenus.core.SessionRepository;
|
import net.helenus.core.SessionRepository;
|
||||||
import net.helenus.mapping.type.AbstractDataType;
|
import net.helenus.mapping.type.AbstractDataType;
|
||||||
|
|
||||||
public interface HelenusProperty {
|
public interface HelenusProperty {
|
||||||
|
|
||||||
HelenusEntity getEntity();
|
HelenusEntity getEntity();
|
||||||
|
|
||||||
String getPropertyName();
|
String getPropertyName();
|
||||||
|
|
||||||
Method getGetterMethod();
|
Method getGetterMethod();
|
||||||
|
|
||||||
IdentityName getColumnName();
|
IdentityName getColumnName();
|
||||||
|
|
||||||
Optional<IdentityName> getIndexName();
|
Optional<IdentityName> getIndexName();
|
||||||
|
|
||||||
boolean caseSensitiveIndex();
|
boolean caseSensitiveIndex();
|
||||||
|
|
||||||
Class<?> getJavaType();
|
Class<?> getJavaType();
|
||||||
|
|
||||||
AbstractDataType getDataType();
|
AbstractDataType getDataType();
|
||||||
|
|
||||||
ColumnType getColumnType();
|
ColumnType getColumnType();
|
||||||
|
|
||||||
int getOrdinal();
|
int getOrdinal();
|
||||||
|
|
||||||
OrderingDirection getOrdering();
|
OrderingDirection getOrdering();
|
||||||
|
|
||||||
Optional<Function<Object, Object>> getReadConverter(SessionRepository repository);
|
Optional<Function<Object, Object>> getReadConverter(SessionRepository repository);
|
||||||
|
|
||||||
Optional<Function<Object, Object>> getWriteConverter(SessionRepository repository);
|
Optional<Function<Object, Object>> getWriteConverter(SessionRepository repository);
|
||||||
|
|
||||||
ConstraintValidator<? extends Annotation, ?>[] getValidators();
|
|
||||||
|
|
||||||
|
ConstraintValidator<? extends Annotation, ?>[] getValidators();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,42 +19,41 @@ import net.helenus.support.CqlUtil;
|
||||||
|
|
||||||
public final class IdentityName {
|
public final class IdentityName {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private final boolean forceQuote;
|
private final boolean forceQuote;
|
||||||
|
|
||||||
public IdentityName(String name, boolean forceQuote) {
|
public IdentityName(String name, boolean forceQuote) {
|
||||||
this.name = name.toLowerCase();
|
this.name = name.toLowerCase();
|
||||||
this.forceQuote = forceQuote;
|
this.forceQuote = forceQuote;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IdentityName of(String name, boolean forceQuote) {
|
public static IdentityName of(String name, boolean forceQuote) {
|
||||||
return new IdentityName(name, forceQuote);
|
return new IdentityName(name, forceQuote);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isForceQuote() {
|
public boolean isForceQuote() {
|
||||||
return forceQuote;
|
return forceQuote;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toCql(boolean overrideForceQuote) {
|
public String toCql(boolean overrideForceQuote) {
|
||||||
if (overrideForceQuote) {
|
if (overrideForceQuote) {
|
||||||
return CqlUtil.forceQuote(name);
|
return CqlUtil.forceQuote(name);
|
||||||
} else {
|
} else {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toCql() {
|
public String toCql() {
|
||||||
return toCql(forceQuote);
|
return toCql(forceQuote);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toCql();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toCql();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,8 @@ import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import javax.validation.Constraint;
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
|
|
||||||
import net.helenus.core.Getter;
|
import net.helenus.core.Getter;
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.core.reflect.*;
|
import net.helenus.core.reflect.*;
|
||||||
|
@ -36,252 +34,232 @@ import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public final class MappingUtil {
|
public final class MappingUtil {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static final ConstraintValidator<? extends Annotation, ?>[] EMPTY_VALIDATORS = new ConstraintValidator[0];
|
public static final ConstraintValidator<? extends Annotation, ?>[] EMPTY_VALIDATORS =
|
||||||
|
new ConstraintValidator[0];
|
||||||
|
|
||||||
private MappingUtil() {
|
private MappingUtil() {}
|
||||||
}
|
|
||||||
|
|
||||||
public static ConstraintValidator<? extends Annotation, ?>[] getValidators(Method getterMethod) {
|
public static ConstraintValidator<? extends Annotation, ?>[] getValidators(Method getterMethod) {
|
||||||
|
|
||||||
List<ConstraintValidator<? extends Annotation, ?>> list = null;
|
List<ConstraintValidator<? extends Annotation, ?>> list = null;
|
||||||
|
|
||||||
for (Annotation constraintAnnotation : getterMethod.getDeclaredAnnotations()) {
|
for (Annotation constraintAnnotation : getterMethod.getDeclaredAnnotations()) {
|
||||||
|
|
||||||
list = addValidators(constraintAnnotation, list);
|
list = addValidators(constraintAnnotation, list);
|
||||||
|
|
||||||
Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
|
Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
|
||||||
|
|
||||||
for (Annotation possibleConstraint : annotationType.getDeclaredAnnotations()) {
|
for (Annotation possibleConstraint : annotationType.getDeclaredAnnotations()) {
|
||||||
|
|
||||||
list = addValidators(possibleConstraint, list);
|
list = addValidators(possibleConstraint, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
if (list == null) {
|
||||||
|
return EMPTY_VALIDATORS;
|
||||||
|
} else {
|
||||||
|
return list.toArray(EMPTY_VALIDATORS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
private static List<ConstraintValidator<? extends Annotation, ?>> addValidators(
|
||||||
|
Annotation constraintAnnotation, List<ConstraintValidator<? extends Annotation, ?>> list) {
|
||||||
|
|
||||||
if (list == null) {
|
Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
|
||||||
return EMPTY_VALIDATORS;
|
|
||||||
} else {
|
|
||||||
return list.toArray(EMPTY_VALIDATORS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<ConstraintValidator<? extends Annotation, ?>> addValidators(Annotation constraintAnnotation,
|
for (Annotation possibleConstraint : annotationType.getDeclaredAnnotations()) {
|
||||||
List<ConstraintValidator<? extends Annotation, ?>> list) {
|
|
||||||
|
|
||||||
Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
|
if (possibleConstraint instanceof Constraint) {
|
||||||
|
|
||||||
for (Annotation possibleConstraint : annotationType.getDeclaredAnnotations()) {
|
Constraint constraint = (Constraint) possibleConstraint;
|
||||||
|
|
||||||
if (possibleConstraint instanceof Constraint) {
|
for (Class<? extends ConstraintValidator<?, ?>> clazz : constraint.validatedBy()) {
|
||||||
|
|
||||||
Constraint constraint = (Constraint) possibleConstraint;
|
ConstraintValidator<? extends Annotation, ?> validator =
|
||||||
|
ReflectionInstantiator.instantiateClass(clazz);
|
||||||
|
|
||||||
for (Class<? extends ConstraintValidator<?, ?>> clazz : constraint.validatedBy()) {
|
((ConstraintValidator) validator).initialize(constraintAnnotation);
|
||||||
|
|
||||||
ConstraintValidator<? extends Annotation, ?> validator = ReflectionInstantiator
|
if (list == null) {
|
||||||
.instantiateClass(clazz);
|
list = new ArrayList<ConstraintValidator<? extends Annotation, ?>>();
|
||||||
|
}
|
||||||
|
|
||||||
((ConstraintValidator) validator).initialize(constraintAnnotation);
|
list.add(validator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (list == null) {
|
return list;
|
||||||
list = new ArrayList<ConstraintValidator<? extends Annotation, ?>>();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
list.add(validator);
|
public static Optional<IdentityName> getIndexName(Method getterMethod) {
|
||||||
|
|
||||||
}
|
String indexName = null;
|
||||||
|
boolean forceQuote = false;
|
||||||
|
|
||||||
}
|
Index index = getterMethod.getDeclaredAnnotation(Index.class);
|
||||||
|
|
||||||
}
|
if (index != null) {
|
||||||
|
indexName = index.value();
|
||||||
|
forceQuote = index.forceQuote();
|
||||||
|
|
||||||
return list;
|
if (indexName == null || indexName.isEmpty()) {
|
||||||
|
indexName = getDefaultColumnName(getterMethod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
return indexName != null
|
||||||
|
? Optional.of(new IdentityName(indexName, forceQuote))
|
||||||
|
: Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
public static Optional<IdentityName> getIndexName(Method getterMethod) {
|
public static boolean caseSensitiveIndex(Method getterMethod) {
|
||||||
|
Index index = getterMethod.getDeclaredAnnotation(Index.class);
|
||||||
|
|
||||||
String indexName = null;
|
if (index != null) {
|
||||||
boolean forceQuote = false;
|
return index.caseSensitive();
|
||||||
|
}
|
||||||
|
|
||||||
Index index = getterMethod.getDeclaredAnnotation(Index.class);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (index != null) {
|
public static String getPropertyName(Method getter) {
|
||||||
indexName = index.value();
|
return getter.getName();
|
||||||
forceQuote = index.forceQuote();
|
}
|
||||||
|
|
||||||
if (indexName == null || indexName.isEmpty()) {
|
public static String getDefaultColumnName(Method getter) {
|
||||||
indexName = getDefaultColumnName(getterMethod);
|
return Helenus.settings().getPropertyToColumnConverter().apply(getPropertyName(getter));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public static IdentityName getUserDefinedTypeName(Class<?> iface, boolean required) {
|
||||||
|
|
||||||
return indexName != null ? Optional.of(new IdentityName(indexName, forceQuote)) : Optional.empty();
|
String userTypeName = null;
|
||||||
}
|
boolean forceQuote = false;
|
||||||
|
|
||||||
public static boolean caseSensitiveIndex(Method getterMethod) {
|
UDT userDefinedType = iface.getDeclaredAnnotation(UDT.class);
|
||||||
Index index = getterMethod.getDeclaredAnnotation(Index.class);
|
|
||||||
|
|
||||||
if (index != null) {
|
if (userDefinedType != null) {
|
||||||
return index.caseSensitive();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
userTypeName = userDefinedType.value();
|
||||||
}
|
forceQuote = userDefinedType.forceQuote();
|
||||||
|
|
||||||
public static String getPropertyName(Method getter) {
|
if (userTypeName == null || userTypeName.isEmpty()) {
|
||||||
return getter.getName();
|
userTypeName = getDefaultEntityName(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDefaultColumnName(Method getter) {
|
return new IdentityName(userTypeName, forceQuote);
|
||||||
return Helenus.settings().getPropertyToColumnConverter().apply(getPropertyName(getter));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static IdentityName getUserDefinedTypeName(Class<?> iface, boolean required) {
|
if (required) {
|
||||||
|
throw new HelenusMappingException("entity must have annotation @UserDefinedType " + iface);
|
||||||
|
}
|
||||||
|
|
||||||
String userTypeName = null;
|
return null;
|
||||||
boolean forceQuote = false;
|
}
|
||||||
|
|
||||||
UDT userDefinedType = iface.getDeclaredAnnotation(UDT.class);
|
public static boolean isTuple(Class<?> iface) {
|
||||||
|
|
||||||
if (userDefinedType != null) {
|
Tuple tuple = iface.getDeclaredAnnotation(Tuple.class);
|
||||||
|
|
||||||
userTypeName = userDefinedType.value();
|
return tuple != null;
|
||||||
forceQuote = userDefinedType.forceQuote();
|
}
|
||||||
|
|
||||||
if (userTypeName == null || userTypeName.isEmpty()) {
|
public static boolean isUDT(Class<?> iface) {
|
||||||
userTypeName = getDefaultEntityName(iface);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IdentityName(userTypeName, forceQuote);
|
UDT udt = iface.getDeclaredAnnotation(UDT.class);
|
||||||
|
|
||||||
}
|
return udt != null;
|
||||||
|
}
|
||||||
|
|
||||||
if (required) {
|
public static IdentityName getTableName(Class<?> iface, boolean required) {
|
||||||
throw new HelenusMappingException("entity must have annotation @UserDefinedType " + iface);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
String tableName = null;
|
||||||
|
boolean forceQuote = false;
|
||||||
|
|
||||||
}
|
Table table = iface.getDeclaredAnnotation(Table.class);
|
||||||
|
|
||||||
public static boolean isTuple(Class<?> iface) {
|
if (table != null) {
|
||||||
|
tableName = table.value();
|
||||||
|
forceQuote = table.forceQuote();
|
||||||
|
|
||||||
Tuple tuple = iface.getDeclaredAnnotation(Tuple.class);
|
} else if (required) {
|
||||||
|
throw new HelenusMappingException("entity must have annotation @Table " + iface);
|
||||||
|
}
|
||||||
|
|
||||||
return tuple != null;
|
if (tableName == null || tableName.isEmpty()) {
|
||||||
|
tableName = getDefaultEntityName(iface);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
return new IdentityName(tableName, forceQuote);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isUDT(Class<?> iface) {
|
public static String getDefaultEntityName(Class<?> iface) {
|
||||||
|
return Helenus.settings().getPropertyToColumnConverter().apply(iface.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
UDT udt = iface.getDeclaredAnnotation(UDT.class);
|
public static Class<?> getMappingInterface(Object pojo) {
|
||||||
|
|
||||||
return udt != null;
|
Class<?> iface = null;
|
||||||
|
|
||||||
}
|
if (pojo instanceof Class) {
|
||||||
|
iface = (Class<?>) pojo;
|
||||||
|
|
||||||
public static IdentityName getTableName(Class<?> iface, boolean required) {
|
if (!iface.isInterface()) {
|
||||||
|
throw new HelenusMappingException("expected interface " + iface);
|
||||||
|
}
|
||||||
|
|
||||||
String tableName = null;
|
} else {
|
||||||
boolean forceQuote = false;
|
Class<?>[] ifaces = pojo.getClass().getInterfaces();
|
||||||
|
|
||||||
Table table = iface.getDeclaredAnnotation(Table.class);
|
int len = ifaces.length;
|
||||||
|
for (int i = 0; i != len; ++i) {
|
||||||
|
|
||||||
if (table != null) {
|
iface = ifaces[0];
|
||||||
tableName = table.value();
|
|
||||||
forceQuote = table.forceQuote();
|
|
||||||
|
|
||||||
} else if (required) {
|
if (MapExportable.class.isAssignableFrom(iface)) {
|
||||||
throw new HelenusMappingException("entity must have annotation @Table " + iface);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tableName == null || tableName.isEmpty()) {
|
if (iface.getDeclaredAnnotation(Table.class) != null
|
||||||
tableName = getDefaultEntityName(iface);
|
|| iface.getDeclaredAnnotation(UDT.class) != null
|
||||||
}
|
|| iface.getDeclaredAnnotation(Tuple.class) != null) {
|
||||||
|
|
||||||
return new IdentityName(tableName, forceQuote);
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String getDefaultEntityName(Class<?> iface) {
|
if (iface == null) {
|
||||||
return Helenus.settings().getPropertyToColumnConverter().apply(iface.getSimpleName());
|
throw new HelenusMappingException("dsl interface not found for " + pojo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class<?> getMappingInterface(Object pojo) {
|
return iface;
|
||||||
|
}
|
||||||
|
|
||||||
Class<?> iface = null;
|
public static HelenusPropertyNode resolveMappingProperty(Getter<?> getter) {
|
||||||
|
|
||||||
if (pojo instanceof Class) {
|
try {
|
||||||
iface = (Class<?>) pojo;
|
Object childDsl = getter.get();
|
||||||
|
|
||||||
if (!iface.isInterface()) {
|
if (childDsl instanceof DslExportable) {
|
||||||
throw new HelenusMappingException("expected interface " + iface);
|
DslExportable e = (DslExportable) childDsl;
|
||||||
}
|
return e.getParentDslHelenusPropertyNode();
|
||||||
|
} else if (childDsl instanceof MapDsl) {
|
||||||
|
MapDsl mapDsl = (MapDsl) childDsl;
|
||||||
|
return mapDsl.getParent();
|
||||||
|
} else if (childDsl instanceof ListDsl) {
|
||||||
|
ListDsl listDsl = (ListDsl) childDsl;
|
||||||
|
return listDsl.getParent();
|
||||||
|
} else if (childDsl instanceof SetDsl) {
|
||||||
|
SetDsl setDsl = (SetDsl) childDsl;
|
||||||
|
return setDsl.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
throw new HelenusMappingException("getter must reference to the dsl object " + getter);
|
||||||
Class<?>[] ifaces = pojo.getClass().getInterfaces();
|
|
||||||
|
|
||||||
int len = ifaces.length;
|
|
||||||
for (int i = 0; i != len; ++i) {
|
|
||||||
|
|
||||||
iface = ifaces[0];
|
|
||||||
|
|
||||||
if (MapExportable.class.isAssignableFrom(iface)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iface.getDeclaredAnnotation(Table.class) != null || iface.getDeclaredAnnotation(UDT.class) != null
|
|
||||||
|| iface.getDeclaredAnnotation(Tuple.class) != null) {
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iface == null) {
|
|
||||||
throw new HelenusMappingException("dsl interface not found for " + pojo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return iface;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HelenusPropertyNode resolveMappingProperty(Getter<?> getter) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Object childDsl = getter.get();
|
|
||||||
|
|
||||||
if (childDsl instanceof DslExportable) {
|
|
||||||
DslExportable e = (DslExportable) childDsl;
|
|
||||||
return e.getParentDslHelenusPropertyNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (childDsl instanceof MapDsl) {
|
|
||||||
MapDsl mapDsl = (MapDsl) childDsl;
|
|
||||||
return mapDsl.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (childDsl instanceof ListDsl) {
|
|
||||||
ListDsl listDsl = (ListDsl) childDsl;
|
|
||||||
return listDsl.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (childDsl instanceof SetDsl) {
|
|
||||||
SetDsl setDsl = (SetDsl) childDsl;
|
|
||||||
return setDsl.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HelenusMappingException("getter must reference to the dsl object " + getter);
|
|
||||||
|
|
||||||
} catch (DslPropertyException e) {
|
|
||||||
return e.getPropertyNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} catch (DslPropertyException e) {
|
||||||
|
return e.getPropertyNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,32 +18,28 @@ package net.helenus.mapping;
|
||||||
import net.helenus.support.HelenusMappingException;
|
import net.helenus.support.HelenusMappingException;
|
||||||
|
|
||||||
public enum OrderingDirection {
|
public enum OrderingDirection {
|
||||||
|
ASC("ASC"),
|
||||||
|
|
||||||
ASC("ASC"),
|
DESC("DESC");
|
||||||
|
|
||||||
DESC("DESC");
|
private final String cql;
|
||||||
|
|
||||||
private final String cql;
|
private OrderingDirection(String cql) {
|
||||||
|
this.cql = cql;
|
||||||
|
}
|
||||||
|
|
||||||
private OrderingDirection(String cql) {
|
public String cql() {
|
||||||
this.cql = cql;
|
return cql;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String cql() {
|
public static OrderingDirection parseString(String name) {
|
||||||
return cql;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OrderingDirection parseString(String name) {
|
if (ASC.cql.equalsIgnoreCase(name)) {
|
||||||
|
return ASC;
|
||||||
|
} else if (DESC.cql.equalsIgnoreCase(name)) {
|
||||||
|
return DESC;
|
||||||
|
}
|
||||||
|
|
||||||
if (ASC.cql.equalsIgnoreCase(name)) {
|
throw new HelenusMappingException("invalid ordering direction name " + name);
|
||||||
return ASC;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else if (DESC.cql.equalsIgnoreCase(name)) {
|
|
||||||
return DESC;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HelenusMappingException("invalid ordering direction name " + name);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,17 @@ package net.helenus.mapping;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
public enum TypeAndOrdinalColumnComparator implements Comparator<HelenusProperty> {
|
public enum TypeAndOrdinalColumnComparator implements Comparator<HelenusProperty> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
public int compare(HelenusProperty thisVal, HelenusProperty anotherVal) {
|
||||||
|
|
||||||
public int compare(HelenusProperty thisVal, HelenusProperty anotherVal) {
|
int c =
|
||||||
|
Integer.compare(thisVal.getColumnType().ordinal(), anotherVal.getColumnType().ordinal());
|
||||||
|
|
||||||
int c = Integer.compare(thisVal.getColumnType().ordinal(), anotherVal.getColumnType().ordinal());
|
if (c == 0) {
|
||||||
|
c = Integer.compare(thisVal.getOrdinal(), anotherVal.getOrdinal());
|
||||||
if (c == 0) {
|
}
|
||||||
c = Integer.compare(thisVal.getOrdinal(), anotherVal.getOrdinal());
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,93 +19,78 @@ import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import net.helenus.mapping.OrderingDirection;
|
import net.helenus.mapping.OrderingDirection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClusteringColumn is the family column in legacy Cassandra API
|
* ClusteringColumn is the family column in legacy Cassandra API
|
||||||
*
|
*
|
||||||
* The purpose of this column is have additional dimension in the table.
|
* <p>The purpose of this column is have additional dimension in the table. Both @PartitionKey
|
||||||
* Both @PartitionKey and @ClusteringColumn together are parts of the primary
|
* and @ClusteringColumn together are parts of the primary key of the table. The primary difference
|
||||||
* key of the table. The primary difference between them is that the first one
|
* between them is that the first one is using for routing purposes in order to locate a data node
|
||||||
* is using for routing purposes in order to locate a data node in the cluster,
|
* in the cluster, otherwise the second one is using inside the node to locate peace of data in
|
||||||
* otherwise the second one is using inside the node to locate peace of data in
|
|
||||||
* concrete machine.
|
* concrete machine.
|
||||||
*
|
*
|
||||||
* ClusteringColumn can be represented as a Key in SortedMap that fully stored
|
* <p>ClusteringColumn can be represented as a Key in SortedMap that fully stored in a single node.
|
||||||
* in a single node. All developers must be careful for selecting fields for
|
* All developers must be careful for selecting fields for clustering columns, because all data
|
||||||
* clustering columns, because all data inside this SortedMap must fit in to one
|
* inside this SortedMap must fit in to one node.
|
||||||
* node.
|
|
||||||
*
|
*
|
||||||
* ClusteringColumn can have more than one part and the order of parts is
|
* <p>ClusteringColumn can have more than one part and the order of parts is important. This order
|
||||||
* important. This order defines the way how Cassandra joins the parts and
|
* defines the way how Cassandra joins the parts and influence of data retrieval operations. Each
|
||||||
* influence of data retrieval operations. Each part can have ordering property
|
* part can have ordering property that defines default ascending or descending order of data. In
|
||||||
* that defines default ascending or descending order of data. In case of two
|
* case of two and more parts in select queries developer needs to have consisdent order of all
|
||||||
* and more parts in select queries developer needs to have consisdent order of
|
* parts as they defined in table.
|
||||||
* all parts as they defined in table.
|
|
||||||
*
|
|
||||||
* For example, first part is ASC ordering, second is also ASC, so Cassandra
|
|
||||||
* will sort entries like this: a-a a-b b-a b-b In this case we are able run
|
|
||||||
* queries: ORDER BY first ASC, second ASC ORDER BY first DESC, second DESC
|
|
||||||
* WHERE first=? ORDER BY second ASC WHERE first=? ORDER BY second DESC WHERE
|
|
||||||
* first=? AND second=?
|
|
||||||
*
|
|
||||||
* But, we can not run queries: ORDER BY first DESC, second ASC ORDER BY first
|
|
||||||
* ASC, second DESC WHERE second=? ORDER BY first (ASC,DESC)
|
|
||||||
*
|
*
|
||||||
|
* <p>For example, first part is ASC ordering, second is also ASC, so Cassandra will sort entries
|
||||||
|
* like this: a-a a-b b-a b-b In this case we are able run queries: ORDER BY first ASC, second ASC
|
||||||
|
* ORDER BY first DESC, second DESC WHERE first=? ORDER BY second ASC WHERE first=? ORDER BY second
|
||||||
|
* DESC WHERE first=? AND second=?
|
||||||
*
|
*
|
||||||
|
* <p>But, we can not run queries: ORDER BY first DESC, second ASC ORDER BY first ASC, second DESC
|
||||||
|
* WHERE second=? ORDER BY first (ASC,DESC)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Retention(value = RetentionPolicy.RUNTIME)
|
@Retention(value = RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface ClusteringColumn {
|
public @interface ClusteringColumn {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value is the name of the method normalized to underscore
|
* Default value is the name of the method normalized to underscore
|
||||||
*
|
*
|
||||||
* @return name of the column
|
* @return name of the column
|
||||||
*/
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
String value() default "";
|
/**
|
||||||
|
* ClusteringColumn parts must be ordered in the @Table. It is the requirement of Cassandra.
|
||||||
|
* Cassandra joins all parts to the final clustering key that is stored in column family name.
|
||||||
|
* Additionally all parts can have some ordering (ASC, DESC) that with sequence of parts
|
||||||
|
* determines key comparison function, so Cassandra storing column family names always in sorted
|
||||||
|
* order.
|
||||||
|
*
|
||||||
|
* <p>Be default ordinal has 0 value, that's because in most cases @Table have single column for
|
||||||
|
* ClusteringColumn If you have 2 and more parts of the ClusteringColumn, then you need to use
|
||||||
|
* ordinal() to define the sequence of the parts
|
||||||
|
*
|
||||||
|
* @return number that used to sort clustering columns
|
||||||
|
*/
|
||||||
|
int ordinal() default 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClusteringColumn parts must be ordered in the @Table. It is the requirement
|
* Default order of values in the ClusteringColumn This ordering is using for comparison of the
|
||||||
* of Cassandra. Cassandra joins all parts to the final clustering key that is
|
* clustering column values when Cassandra stores it in the sorted order.
|
||||||
* stored in column family name. Additionally all parts can have some ordering
|
*
|
||||||
* (ASC, DESC) that with sequence of parts determines key comparison function,
|
* <p>Default value is the ascending order
|
||||||
* so Cassandra storing column family names always in sorted order.
|
*
|
||||||
*
|
* @return ascending order or descending order of clustering column values
|
||||||
* Be default ordinal has 0 value, that's because in most cases @Table have
|
*/
|
||||||
* single column for ClusteringColumn If you have 2 and more parts of the
|
OrderingDirection ordering() default OrderingDirection.ASC;
|
||||||
* ClusteringColumn, then you need to use ordinal() to define the sequence of
|
|
||||||
* the parts
|
|
||||||
*
|
|
||||||
* @return number that used to sort clustering columns
|
|
||||||
*/
|
|
||||||
|
|
||||||
int ordinal() default 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default order of values in the ClusteringColumn This ordering is using for
|
|
||||||
* comparison of the clustering column values when Cassandra stores it in the
|
|
||||||
* sorted order.
|
|
||||||
*
|
|
||||||
* Default value is the ascending order
|
|
||||||
*
|
|
||||||
* @return ascending order or descending order of clustering column values
|
|
||||||
*/
|
|
||||||
|
|
||||||
OrderingDirection ordering() default OrderingDirection.ASC;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For reserved words in Cassandra we need quotation in CQL queries. This
|
|
||||||
* property marks that the name of the UDT type needs to be quoted.
|
|
||||||
*
|
|
||||||
* Default value is false, we are quoting only selected names.
|
|
||||||
*
|
|
||||||
* @return true if name have to be quoted
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean forceQuote() default false;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||||
|
* name of the UDT type needs to be quoted.
|
||||||
|
*
|
||||||
|
* <p>Default value is false, we are quoting only selected names.
|
||||||
|
*
|
||||||
|
* @return true if name have to be quoted
|
||||||
|
*/
|
||||||
|
boolean forceQuote() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,53 +18,45 @@ package net.helenus.mapping.annotation;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column annotation is used to define additional properties of the column in
|
* Column annotation is used to define additional properties of the column in entity mapping
|
||||||
* entity mapping interfaces: @Table, @UDT, @Tuple
|
* interfaces: @Table, @UDT, @Tuple
|
||||||
*
|
|
||||||
* Column annotation can be used to override default name of the column or to
|
|
||||||
* setup order of the columns in the mapping
|
|
||||||
*
|
|
||||||
* Usually for @Table and @UDT types it is not important to define order of the
|
|
||||||
* columns, but in @Tuple mapping it is required, because tuple itself
|
|
||||||
* represents the sequence of the types with particular order in the table's
|
|
||||||
* column
|
|
||||||
*
|
*
|
||||||
|
* <p>Column annotation can be used to override default name of the column or to setup order of the
|
||||||
|
* columns in the mapping
|
||||||
*
|
*
|
||||||
|
* <p>Usually for @Table and @UDT types it is not important to define order of the columns, but
|
||||||
|
* in @Tuple mapping it is required, because tuple itself represents the sequence of the types with
|
||||||
|
* particular order in the table's column
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface Column {
|
public @interface Column {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value is the name of the method normalized to underscore
|
* Default value is the name of the method normalized to underscore
|
||||||
*
|
*
|
||||||
* @return name of the column
|
* @return name of the column
|
||||||
*/
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
String value() default "";
|
/**
|
||||||
|
* Ordinal will be used for ascending sorting of columns
|
||||||
|
*
|
||||||
|
* <p>Default value is 0, because not all mapping entities require all fields to have unique
|
||||||
|
* ordinals, only @Tuple mapping entity requires all of them to be unique.
|
||||||
|
*
|
||||||
|
* @return number that used to sort columns, usually for @Tuple only
|
||||||
|
*/
|
||||||
|
int ordinal() default 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ordinal will be used for ascending sorting of columns
|
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||||
*
|
* name of the UDT type needs to be quoted.
|
||||||
* Default value is 0, because not all mapping entities require all fields to
|
*
|
||||||
* have unique ordinals, only @Tuple mapping entity requires all of them to be
|
* <p>Default value is false, we are quoting only selected names.
|
||||||
* unique.
|
*
|
||||||
*
|
* @return true if name have to be quoted
|
||||||
* @return number that used to sort columns, usually for @Tuple only
|
*/
|
||||||
*/
|
boolean forceQuote() default false;
|
||||||
|
|
||||||
int ordinal() default 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For reserved words in Cassandra we need quotation in CQL queries. This
|
|
||||||
* property marks that the name of the UDT type needs to be quoted.
|
|
||||||
*
|
|
||||||
* Default value is false, we are quoting only selected names.
|
|
||||||
*
|
|
||||||
* @return true if name have to be quoted
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean forceQuote() default false;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,255 +16,200 @@
|
||||||
package net.helenus.mapping.annotation;
|
package net.helenus.mapping.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import javax.validation.Constraint;
|
||||||
|
|
||||||
import net.helenus.mapping.validator.*;
|
import net.helenus.mapping.validator.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constraint annotations are using for data integrity mostly
|
* Constraint annotations are using for data integrity mostly for @java.lang.String types. The place
|
||||||
* for @java.lang.String types. The place of the annotation is the particular
|
* of the annotation is the particular method in model interface.
|
||||||
* method in model interface.
|
|
||||||
*
|
|
||||||
* All of them does not have effect on selects and data retrieval operations.
|
|
||||||
*
|
|
||||||
* Support types: - @NotNull supports any @java.lang.Object type - All
|
|
||||||
* annotations support @java.lang.String type
|
|
||||||
*
|
*
|
||||||
|
* <p>All of them does not have effect on selects and data retrieval operations.
|
||||||
*
|
*
|
||||||
|
* <p>Support types: - @NotNull supports any @java.lang.Object type - All annotations
|
||||||
|
* support @java.lang.String type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class Constraints {
|
public final class Constraints {
|
||||||
|
|
||||||
private Constraints() {
|
private Constraints() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NotNull annotation is using to check that value is not null before storing it
|
* NotNull annotation is using to check that value is not null before storing it
|
||||||
*
|
*
|
||||||
* Applicable to use in any @java.lang.Object
|
* <p>Applicable to use in any @java.lang.Object
|
||||||
*
|
*
|
||||||
* It does not check on selects and data retrieval operations
|
* <p>It does not check on selects and data retrieval operations
|
||||||
*
|
*/
|
||||||
*/
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = NotNullValidator.class)
|
||||||
|
public @interface NotNull {}
|
||||||
|
|
||||||
@Documented
|
/**
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* NotEmpty annotation is using to check that value has text before storing it
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
*
|
||||||
@Constraint(validatedBy = NotNullValidator.class)
|
* <p>Also checks for the null and it is more strict annotation then @NotNull
|
||||||
public @interface NotNull {
|
*
|
||||||
|
* <p>Can be used for @java.lang.CharSequence, @ByteBuffer and any array
|
||||||
|
*
|
||||||
|
* <p>It does not check on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = NotEmptyValidator.class)
|
||||||
|
public @interface NotEmpty {}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Email annotation is using to check that value has a valid email before storing it
|
||||||
|
*
|
||||||
|
* <p>Can be used only for @CharSequence
|
||||||
|
*
|
||||||
|
* <p>It does not check on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = EmailValidator.class)
|
||||||
|
public @interface Email {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NotEmpty annotation is using to check that value has text before storing it
|
* Number annotation is using to check that all letters in value are digits before storing it
|
||||||
*
|
*
|
||||||
* Also checks for the null and it is more strict annotation then @NotNull
|
* <p>Can be used only for @java.lang.CharSequence
|
||||||
*
|
*
|
||||||
* Can be used for @java.lang.CharSequence, @ByteBuffer and any array
|
* <p>It does not check on selects and data retrieval operations
|
||||||
*
|
*/
|
||||||
* It does not check on selects and data retrieval operations
|
@Documented
|
||||||
*
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
*/
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = NumberValidator.class)
|
||||||
|
public @interface Number {}
|
||||||
|
|
||||||
@Documented
|
/**
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* Alphabet annotation is using to check that all letters in value are in specific alphabet before
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
* storing it
|
||||||
@Constraint(validatedBy = NotEmptyValidator.class)
|
*
|
||||||
public @interface NotEmpty {
|
* <p>Can be used only for @java.lang.CharSequence
|
||||||
|
*
|
||||||
|
* <p>It does not check on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = AlphabetValidator.class)
|
||||||
|
public @interface Alphabet {
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Defines alphabet that will be used to check value
|
||||||
|
*
|
||||||
|
* @return alphabet characters in the string
|
||||||
|
*/
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Email annotation is using to check that value has a valid email before
|
* Length annotation is using to ensure that value has exact length before storing it
|
||||||
* storing it
|
*
|
||||||
*
|
* <p>Can be used for @java.lang.CharSequence, @ByteBuffer and any array
|
||||||
* Can be used only for @CharSequence
|
*
|
||||||
*
|
* <p>It does not have effect on selects and data retrieval operations
|
||||||
* It does not check on selects and data retrieval operations
|
*/
|
||||||
*
|
@Documented
|
||||||
*/
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = LengthValidator.class)
|
||||||
|
public @interface Length {
|
||||||
|
|
||||||
@Documented
|
int value();
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
}
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
@Constraint(validatedBy = EmailValidator.class)
|
|
||||||
public @interface Email {
|
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* MaxLength annotation is using to ensure that value has length less or equal to some threshold
|
||||||
|
* before storing it
|
||||||
|
*
|
||||||
|
* <p>Can be used for @java.lang.CharSequence, @ByteBuffer and byte[]
|
||||||
|
*
|
||||||
|
* <p>It does not have effect on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = MaxLengthValidator.class)
|
||||||
|
public @interface MaxLength {
|
||||||
|
|
||||||
/**
|
int value();
|
||||||
* Number annotation is using to check that all letters in value are digits
|
}
|
||||||
* before storing it
|
|
||||||
*
|
|
||||||
* Can be used only for @java.lang.CharSequence
|
|
||||||
*
|
|
||||||
* It does not check on selects and data retrieval operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
/**
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* MinLength annotation is using to ensure that value has length greater or equal to some
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
* threshold before storing it
|
||||||
@Constraint(validatedBy = NumberValidator.class)
|
*
|
||||||
public @interface Number {
|
* <p>Can be used for @java.lang.CharSequence, @ByteBuffer and byte[]
|
||||||
|
*
|
||||||
|
* <p>It does not have effect on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = MinLengthValidator.class)
|
||||||
|
public @interface MinLength {
|
||||||
|
|
||||||
}
|
int value();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alphabet annotation is using to check that all letters in value are in
|
* LowerCase annotation is using to ensure that value is in lower case before storing it
|
||||||
* specific alphabet before storing it
|
*
|
||||||
*
|
* <p>Can be used only for @java.lang.CharSequence
|
||||||
* Can be used only for @java.lang.CharSequence
|
*
|
||||||
*
|
* <p>It does not have effect on selects and data retrieval operations
|
||||||
* It does not check on selects and data retrieval operations
|
*/
|
||||||
*
|
@Documented
|
||||||
*/
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = LowerCaseValidator.class)
|
||||||
|
public @interface LowerCase {}
|
||||||
|
|
||||||
@Documented
|
/**
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* UpperCase annotation is using to ensure that value is in upper case before storing it
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
*
|
||||||
@Constraint(validatedBy = AlphabetValidator.class)
|
* <p>Can be used only for @java.lang.CharSequence
|
||||||
public @interface Alphabet {
|
*
|
||||||
|
* <p>It does not have effect on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = UpperCaseValidator.class)
|
||||||
|
public @interface UpperCase {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines alphabet that will be used to check value
|
* Pattern annotation is LowerCase annotation is using to ensure that value is upper case before
|
||||||
*
|
* storing it
|
||||||
* @return alphabet characters in the string
|
*
|
||||||
*/
|
* <p>Can be used only for @java.lang.CharSequence
|
||||||
|
*
|
||||||
|
* <p>It does not have effect on selects and data retrieval operations
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Constraint(validatedBy = PatternValidator.class)
|
||||||
|
public @interface Pattern {
|
||||||
|
|
||||||
String value();
|
/**
|
||||||
|
* User defined regex expression to check match of the value
|
||||||
}
|
*
|
||||||
|
* @return Java regex pattern
|
||||||
/**
|
*/
|
||||||
* Length annotation is using to ensure that value has exact length before
|
String value();
|
||||||
* storing it
|
|
||||||
*
|
|
||||||
* Can be used for @java.lang.CharSequence, @ByteBuffer and any array
|
|
||||||
*
|
|
||||||
* It does not have effect on selects and data retrieval operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
@Constraint(validatedBy = LengthValidator.class)
|
|
||||||
public @interface Length {
|
|
||||||
|
|
||||||
int value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MaxLength annotation is using to ensure that value has length less or equal
|
|
||||||
* to some threshold before storing it
|
|
||||||
*
|
|
||||||
* Can be used for @java.lang.CharSequence, @ByteBuffer and byte[]
|
|
||||||
*
|
|
||||||
* It does not have effect on selects and data retrieval operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
@Constraint(validatedBy = MaxLengthValidator.class)
|
|
||||||
public @interface MaxLength {
|
|
||||||
|
|
||||||
int value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MinLength annotation is using to ensure that value has length greater or
|
|
||||||
* equal to some threshold before storing it
|
|
||||||
*
|
|
||||||
* Can be used for @java.lang.CharSequence, @ByteBuffer and byte[]
|
|
||||||
*
|
|
||||||
* It does not have effect on selects and data retrieval operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
@Constraint(validatedBy = MinLengthValidator.class)
|
|
||||||
public @interface MinLength {
|
|
||||||
|
|
||||||
int value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LowerCase annotation is using to ensure that value is in lower case before
|
|
||||||
* storing it
|
|
||||||
*
|
|
||||||
* Can be used only for @java.lang.CharSequence
|
|
||||||
*
|
|
||||||
* It does not have effect on selects and data retrieval operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
@Constraint(validatedBy = LowerCaseValidator.class)
|
|
||||||
public @interface LowerCase {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UpperCase annotation is using to ensure that value is in upper case before
|
|
||||||
* storing it
|
|
||||||
*
|
|
||||||
* Can be used only for @java.lang.CharSequence
|
|
||||||
*
|
|
||||||
* It does not have effect on selects and data retrieval operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
@Constraint(validatedBy = UpperCaseValidator.class)
|
|
||||||
public @interface UpperCase {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pattern annotation is LowerCase annotation is using to ensure that value is
|
|
||||||
* upper case before storing it
|
|
||||||
*
|
|
||||||
* Can be used only for @java.lang.CharSequence
|
|
||||||
*
|
|
||||||
* It does not have effect on selects and data retrieval operations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
@Constraint(validatedBy = PatternValidator.class)
|
|
||||||
public @interface Pattern {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User defined regex expression to check match of the value
|
|
||||||
*
|
|
||||||
* @return Java regex pattern
|
|
||||||
*/
|
|
||||||
|
|
||||||
String value();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex flags composition
|
|
||||||
*
|
|
||||||
* @return Java regex flags
|
|
||||||
*/
|
|
||||||
|
|
||||||
int flags();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex flags composition
|
||||||
|
*
|
||||||
|
* @return Java regex flags
|
||||||
|
*/
|
||||||
|
int flags();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,52 +18,45 @@ package net.helenus.mapping.annotation;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Index annotation is using under the specific column or method in entity
|
* Index annotation is using under the specific column or method in entity interface with @Table
|
||||||
* interface with @Table annotation.
|
* annotation.
|
||||||
*
|
*
|
||||||
* The corresponding secondary index will be created in the underline @Table for
|
* <p>The corresponding secondary index will be created in the underline @Table for the specific
|
||||||
* the specific column.
|
* column.
|
||||||
*
|
|
||||||
* Currently Cassandra supports only single column index, so this index works
|
|
||||||
* only for single column.
|
|
||||||
*
|
|
||||||
* Make sure that you are using low cardinality columns for this index, that is
|
|
||||||
* the requirement of the Cassandra. Low cardinality fields examples: gender,
|
|
||||||
* country, age, status and etc High cardinality fields examples: id, email,
|
|
||||||
* timestamp, UUID and etc
|
|
||||||
*
|
*
|
||||||
|
* <p>Currently Cassandra supports only single column index, so this index works only for single
|
||||||
|
* column.
|
||||||
*
|
*
|
||||||
|
* <p>Make sure that you are using low cardinality columns for this index, that is the requirement
|
||||||
|
* of the Cassandra. Low cardinality fields examples: gender, country, age, status and etc High
|
||||||
|
* cardinality fields examples: id, email, timestamp, UUID and etc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface Index {
|
public @interface Index {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defined the name of the index. By default will be used the column name.
|
* Defined the name of the index. By default will be used the column name.
|
||||||
*
|
*
|
||||||
* @return name of the index
|
* @return name of the index
|
||||||
*/
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
String value() default "";
|
/**
|
||||||
|
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||||
|
* name of the UDT type needs to be quoted.
|
||||||
|
*
|
||||||
|
* <p>Default value is false, we are quoting only selected names.
|
||||||
|
*
|
||||||
|
* @return true if name have to be quoted
|
||||||
|
*/
|
||||||
|
boolean forceQuote() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For reserved words in Cassandra we need quotation in CQL queries. This
|
* Create a case-insensitive index using Cassandra 3.x+ support for SASI indexing.
|
||||||
* property marks that the name of the UDT type needs to be quoted.
|
*
|
||||||
*
|
* @return true if the index should ignore case when comparing
|
||||||
* Default value is false, we are quoting only selected names.
|
*/
|
||||||
*
|
boolean caseSensitive() default true;
|
||||||
* @return true if name have to be quoted
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean forceQuote() default false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a case-insensitive index using Cassandra 3.x+ support for SASI indexing.
|
|
||||||
*
|
|
||||||
* @return true if the index should ignore case when comparing
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean caseSensitive() default true;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,11 @@ import java.lang.annotation.*;
|
||||||
/**
|
/**
|
||||||
* Inherited Entity annotation
|
* Inherited Entity annotation
|
||||||
*
|
*
|
||||||
* Inherited Table annotation is used to indicate that the methods should also be mapped
|
* <p>Inherited Table annotation is used to indicate that the methods should also be mapped
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Inherited
|
@Inherited
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
public @interface InheritedTable {
|
public @interface InheritedTable {
|
||||||
String value() default "";
|
String value() default "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,58 +21,48 @@ import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PartitionKey annotation is using to define that particular column is the part
|
* PartitionKey annotation is using to define that particular column is the part of partition key in
|
||||||
* of partition key in the table.
|
* the table.
|
||||||
*
|
|
||||||
* Partition Key is the routing key. Cassandra is using it to find the primary
|
|
||||||
* data node in the cluster that holds data. Cassandra combines all parts of the
|
|
||||||
* partition key to byte array and then calculates hash function by using good
|
|
||||||
* distribution algorithm (by default MurMur3). After that it uses hash number
|
|
||||||
* as a token in the ring to find a virtual and then a physical data server.
|
|
||||||
*
|
|
||||||
* For @Table mapping entity it is required to have as minimum one PartitionKey
|
|
||||||
* column. For @UDT and @Tuple mapping entities @PartitionKey annotation is not
|
|
||||||
* using.
|
|
||||||
*
|
*
|
||||||
|
* <p>Partition Key is the routing key. Cassandra is using it to find the primary data node in the
|
||||||
|
* cluster that holds data. Cassandra combines all parts of the partition key to byte array and then
|
||||||
|
* calculates hash function by using good distribution algorithm (by default MurMur3). After that it
|
||||||
|
* uses hash number as a token in the ring to find a virtual and then a physical data server.
|
||||||
*
|
*
|
||||||
|
* <p>For @Table mapping entity it is required to have as minimum one PartitionKey column. For @UDT
|
||||||
|
* and @Tuple mapping entities @PartitionKey annotation is not using.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Retention(value = RetentionPolicy.RUNTIME)
|
@Retention(value = RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface PartitionKey {
|
public @interface PartitionKey {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value is the name of the method normalized to underscore
|
* Default value is the name of the method normalized to underscore
|
||||||
*
|
*
|
||||||
* @return name of the column
|
* @return name of the column
|
||||||
*/
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
String value() default "";
|
/**
|
||||||
|
* PartitionKey parts must be ordered in the @Table. It is the requirement of Cassandra. That is
|
||||||
/**
|
* how the partition key calculation works, column parts will be joined based on some order and
|
||||||
* PartitionKey parts must be ordered in the @Table. It is the requirement of
|
* final hash/token will be calculated.
|
||||||
* Cassandra. That is how the partition key calculation works, column parts will
|
*
|
||||||
* be joined based on some order and final hash/token will be calculated.
|
* <p>Be default ordinal has 0 value, that's because in most cases @Table have single column
|
||||||
*
|
* for @PartitionKey If you have 2 and more parts of the PartitionKey, then you need to use
|
||||||
* Be default ordinal has 0 value, that's because in most cases @Table have
|
* ordinal() to define the sequence of the parts
|
||||||
* single column for @PartitionKey If you have 2 and more parts of the
|
*
|
||||||
* PartitionKey, then you need to use ordinal() to define the sequence of the
|
* @return number that used to sort columns in PartitionKey
|
||||||
* parts
|
*/
|
||||||
*
|
int ordinal() default 0;
|
||||||
* @return number that used to sort columns in PartitionKey
|
|
||||||
*/
|
|
||||||
|
|
||||||
int ordinal() default 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For reserved words in Cassandra we need quotation in CQL queries. This
|
|
||||||
* property marks that the name of the UDT type needs to be quoted.
|
|
||||||
*
|
|
||||||
* Default value is false, we are quoting only selected names.
|
|
||||||
*
|
|
||||||
* @return true if name have to be quoted
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean forceQuote() default false;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||||
|
* name of the UDT type needs to be quoted.
|
||||||
|
*
|
||||||
|
* <p>Default value is false, we are quoting only selected names.
|
||||||
|
*
|
||||||
|
* @return true if name have to be quoted
|
||||||
|
*/
|
||||||
|
boolean forceQuote() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,45 +23,38 @@ import java.lang.annotation.Target;
|
||||||
/**
|
/**
|
||||||
* StaticColumn annotation is using to define a static column in Cassandra Table
|
* StaticColumn annotation is using to define a static column in Cassandra Table
|
||||||
*
|
*
|
||||||
* It does not have effect in @UDT and @Tuple types and in @Table-s that does
|
* <p>It does not have effect in @UDT and @Tuple types and in @Table-s that does not
|
||||||
* not have @ClusteringColumn-s
|
* have @ClusteringColumn-s
|
||||||
*
|
|
||||||
* In case of using @ClusteringColumn we can repeat some information that is
|
|
||||||
* unique for a row. For this purpose we can define @StaticColumn annotation,
|
|
||||||
* that will create static column in the table
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
|
* <p>In case of using @ClusteringColumn we can repeat some information that is unique for a row.
|
||||||
|
* For this purpose we can define @StaticColumn annotation, that will create static column in the
|
||||||
|
* table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Retention(value = RetentionPolicy.RUNTIME)
|
@Retention(value = RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface StaticColumn {
|
public @interface StaticColumn {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value is the name of the method normalized to underscore
|
* Default value is the name of the method normalized to underscore
|
||||||
*
|
*
|
||||||
* @return name of the column
|
* @return name of the column
|
||||||
*/
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
String value() default "";
|
/**
|
||||||
|
* Ordinal will be used for ascending sorting of static columns
|
||||||
/**
|
*
|
||||||
* Ordinal will be used for ascending sorting of static columns
|
* @return number that used to sort columns in PartitionKey
|
||||||
*
|
*/
|
||||||
* @return number that used to sort columns in PartitionKey
|
int ordinal() default 0;
|
||||||
*/
|
|
||||||
|
|
||||||
int ordinal() default 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For reserved words in Cassandra we need quotation in CQL queries. This
|
|
||||||
* property marks that the name of the UDT type needs to be quoted.
|
|
||||||
*
|
|
||||||
* Default value is false, we are quoting only selected names.
|
|
||||||
*
|
|
||||||
* @return true if name have to be quoted
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean forceQuote() default false;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||||
|
* name of the UDT type needs to be quoted.
|
||||||
|
*
|
||||||
|
* <p>Default value is false, we are quoting only selected names.
|
||||||
|
*
|
||||||
|
* @return true if name have to be quoted
|
||||||
|
*/
|
||||||
|
boolean forceQuote() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,38 +20,32 @@ import java.lang.annotation.*;
|
||||||
/**
|
/**
|
||||||
* Entity annotation
|
* Entity annotation
|
||||||
*
|
*
|
||||||
* Table annotation is used to define Table mapping to some interface
|
* <p>Table annotation is used to define Table mapping to some interface
|
||||||
*
|
|
||||||
* There are three types of Entity mapping annotations: @Table, @UDT, @Tuple
|
|
||||||
*
|
|
||||||
* For each @Table annotated interface Helenus will create/update/verify
|
|
||||||
* Cassandra Table and some indexes if needed on startup.
|
|
||||||
*
|
*
|
||||||
|
* <p>There are three types of Entity mapping annotations: @Table, @UDT, @Tuple
|
||||||
*
|
*
|
||||||
|
* <p>For each @Table annotated interface Helenus will create/update/verify Cassandra Table and some
|
||||||
|
* indexes if needed on startup.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Inherited
|
@Inherited
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
public @interface Table {
|
public @interface Table {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value is the SimpleName of the interface normalized to underscore
|
* Default value is the SimpleName of the interface normalized to underscore
|
||||||
*
|
*
|
||||||
* @return name of the UDT type
|
* @return name of the UDT type
|
||||||
*/
|
*/
|
||||||
|
String value() default "";
|
||||||
String value() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For reserved words in Cassandra we need quotation in CQL queries. This
|
|
||||||
* property marks that the name of the UDT type needs to be quoted.
|
|
||||||
*
|
|
||||||
* Default value is false, we are quoting only selected names.
|
|
||||||
*
|
|
||||||
* @return true if name have to be quoted
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean forceQuote() default false;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||||
|
* name of the UDT type needs to be quoted.
|
||||||
|
*
|
||||||
|
* <p>Default value is false, we are quoting only selected names.
|
||||||
|
*
|
||||||
|
* @return true if name have to be quoted
|
||||||
|
*/
|
||||||
|
boolean forceQuote() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,8 @@ package net.helenus.mapping.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/** Transient annotation is used to mark properties that are need not be mapped to the database. */
|
||||||
* Transient annotation is used to mark properties that are need not be mapped
|
|
||||||
* to the database.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface Transient {
|
public @interface Transient {}
|
||||||
}
|
|
||||||
|
|
|
@ -20,20 +20,15 @@ import java.lang.annotation.*;
|
||||||
/**
|
/**
|
||||||
* Entity annotation
|
* Entity annotation
|
||||||
*
|
*
|
||||||
* Tuple annotation is used to define Tuple type mapping to some interface
|
* <p>Tuple annotation is used to define Tuple type mapping to some interface
|
||||||
*
|
|
||||||
* There are three types of Entity mapping annotations: @Table, @UDT, @Tuple
|
|
||||||
*
|
|
||||||
* Tuple is fully embedded type, it is the sequence of the underline types and
|
|
||||||
* the order of the sub-types is important, therefore all @Column-s must have
|
|
||||||
* ordinal() and only @Column annotation supported for underline types
|
|
||||||
*
|
*
|
||||||
|
* <p>There are three types of Entity mapping annotations: @Table, @UDT, @Tuple
|
||||||
*
|
*
|
||||||
|
* <p>Tuple is fully embedded type, it is the sequence of the underline types and the order of the
|
||||||
|
* sub-types is important, therefore all @Column-s must have ordinal() and only @Column annotation
|
||||||
|
* supported for underline types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Inherited
|
@Inherited
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
public @interface Tuple {
|
public @interface Tuple {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,542 +15,412 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.mapping.annotation;
|
package net.helenus.mapping.annotation;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.DataType;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
import com.datastax.driver.core.DataType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types annotations are using for clarification of Cassandra data type for
|
* Types annotations are using for clarification of Cassandra data type for particular Java type.
|
||||||
* particular Java type.
|
|
||||||
*
|
*
|
||||||
* Sometimes it is possible to have for single Java type multiple Cassandra data
|
* <p>Sometimes it is possible to have for single Java type multiple Cassandra data types: - @String
|
||||||
* types: - @String can be @DataType.Name.ASCII or @DataType.Name.TEXT
|
* can be @DataType.Name.ASCII or @DataType.Name.TEXT or @DataType.Name.VARCHAR - @Long can
|
||||||
* or @DataType.Name.VARCHAR - @Long can be @DataType.Name.BIGINT
|
* be @DataType.Name.BIGINT or @DataType.Name.COUNTER
|
||||||
* or @DataType.Name.COUNTER
|
|
||||||
*
|
*
|
||||||
* All those type annotations simplify mapping between Java types and Cassandra
|
* <p>All those type annotations simplify mapping between Java types and Cassandra data types. They
|
||||||
* data types. They are not required, for each Java type there is a default
|
* are not required, for each Java type there is a default Cassandra data type in Helenus, but in
|
||||||
* Cassandra data type in Helenus, but in some cases you would like to control
|
* some cases you would like to control mapping to make sure that the right Cassandra data type is
|
||||||
* mapping to make sure that the right Cassandra data type is using.
|
* using.
|
||||||
*
|
|
||||||
* For complex types like collections, UDF and Tuple types all those annotations
|
|
||||||
* are using to clarify the sub-type(s) or class/UDF names.
|
|
||||||
*
|
|
||||||
* Has significant effect on schema operations.
|
|
||||||
*
|
*
|
||||||
|
* <p>For complex types like collections, UDF and Tuple types all those annotations are using to
|
||||||
|
* clarify the sub-type(s) or class/UDF names.
|
||||||
*
|
*
|
||||||
|
* <p>Has significant effect on schema operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class Types {
|
public final class Types {
|
||||||
|
|
||||||
private Types() {
|
private Types() {}
|
||||||
}
|
|
||||||
|
/** Says to use @DataType.Name.ASCII data type in schema Java type is @String */
|
||||||
/**
|
@Documented
|
||||||
* Says to use @DataType.Name.ASCII data type in schema Java type is @String
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
*/
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
public @interface Ascii {}
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
/** Says to use @DataType.Name.BIGINT data type in schema Java type is @Long */
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Documented
|
||||||
public @interface Ascii {
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
}
|
public @interface Bigint {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Says to use @DataType.Name.BIGINT data type in schema Java type is @Long
|
* Says to use @DataType.Name.BLOB data type in schema Java type is @ByteBuffer or @byte[] Using
|
||||||
*/
|
* by default
|
||||||
|
*/
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
public @interface Bigint {
|
public @interface Blob {}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Says to use @DataType.Name.LIST data type in schema with specific sub-type Java type is @List
|
||||||
/**
|
*
|
||||||
* Says to use @DataType.Name.BLOB data type in schema Java type is @ByteBuffer
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
* or @byte[] Using by default
|
* retrieval operation result can be a collection with another implementation.
|
||||||
*/
|
*
|
||||||
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
@Documented
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
*
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
* <p>For this type there are special operations: prepend, prependAll, setIdx, append, appendAll,
|
||||||
public @interface Blob {
|
* discard and discardAll in @UpdateOperation
|
||||||
|
*/
|
||||||
}
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
/**
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
* Says to use @DataType.Name.LIST data type in schema with specific sub-type
|
public @interface List {
|
||||||
* Java type is @List
|
|
||||||
*
|
/**
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
* Clarification of using the sub-type data type in the collection. It supports only simple data
|
||||||
* thereof data retrieval operation result can be a collection with another
|
* type (not Collection, UDT or Tuple)
|
||||||
* implementation.
|
*
|
||||||
*
|
* <p>In case if you need UDT sub-type in the list, consider @UDTList annotation
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
*
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
* @return data type name of the value
|
||||||
* types.
|
*/
|
||||||
*
|
DataType.Name value();
|
||||||
* For this type there are special operations: prepend, prependAll, setIdx,
|
}
|
||||||
* append, appendAll, discard and discardAll in @UpdateOperation
|
|
||||||
*/
|
/**
|
||||||
|
* Says to use @DataType.Name.MAP data type in schema with specific sub-types Java type is @Map
|
||||||
@Documented
|
*
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
* retrieval operation result can be a collection with another implementation.
|
||||||
public @interface List {
|
*
|
||||||
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
/**
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
* Clarification of using the sub-type data type in the collection. It supports
|
*
|
||||||
* only simple data type (not Collection, UDT or Tuple)
|
* <p>For this type there are special operations: put and putAll in @UpdateOperation.
|
||||||
*
|
*/
|
||||||
* In case if you need UDT sub-type in the list, consider @UDTList annotation
|
@Documented
|
||||||
*
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* @return data type name of the value
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
*/
|
public @interface Map {
|
||||||
|
|
||||||
DataType.Name value();
|
/**
|
||||||
|
* Clarification of using the sub-type data type in the collection. It supports only simple data
|
||||||
}
|
* type (not Collection, UDT or Tuple)
|
||||||
|
*
|
||||||
/**
|
* <p>In case if you need UDT key sub-type in the map, consider @UDTKeyMap or @UDTMap
|
||||||
* Says to use @DataType.Name.MAP data type in schema with specific sub-types
|
* annotations
|
||||||
* Java type is @Map
|
*
|
||||||
*
|
* @return data type name of the key
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
*/
|
||||||
* thereof data retrieval operation result can be a collection with another
|
DataType.Name key();
|
||||||
* implementation.
|
|
||||||
*
|
/**
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
* Clarification of using the sub-type data type in the collection. It supports only simple data
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
* type (not Collection, UDT or Tuple)
|
||||||
* types.
|
*
|
||||||
*
|
* <p>In case if you need UDT value sub-type in the map, consider @UDTValueMap or @UDTMap
|
||||||
* For this type there are special operations: put and putAll
|
* annotations
|
||||||
* in @UpdateOperation.
|
*
|
||||||
*
|
* @return data type name of the value
|
||||||
*/
|
*/
|
||||||
|
DataType.Name value();
|
||||||
@Documented
|
}
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
/**
|
||||||
public @interface Map {
|
* Says to use @DataType.Name.COUNTER type in schema Java type is @Long
|
||||||
|
*
|
||||||
/**
|
* <p>For this type there are special operations: increment and decrement in @UpdateOperation. You
|
||||||
* Clarification of using the sub-type data type in the collection. It supports
|
* do not need to initialize counter value, it will be done automatically by Cassandra.
|
||||||
* only simple data type (not Collection, UDT or Tuple)
|
*/
|
||||||
*
|
@Documented
|
||||||
* In case if you need UDT key sub-type in the map, consider @UDTKeyMap
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* or @UDTMap annotations
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
*
|
public @interface Counter {}
|
||||||
* @return data type name of the key
|
|
||||||
*/
|
/**
|
||||||
|
* Says to use @DataType.Name.SET data type in schema with specific sub-type Java type is @Set
|
||||||
DataType.Name key();
|
*
|
||||||
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
/**
|
* retrieval operation result can be a collection with another implementation.
|
||||||
* Clarification of using the sub-type data type in the collection. It supports
|
*
|
||||||
* only simple data type (not Collection, UDT or Tuple)
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
*
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
* In case if you need UDT value sub-type in the map, consider @UDTValueMap
|
*
|
||||||
* or @UDTMap annotations
|
* <p>For this type there are special operations: add, addAll, remove and removeAll
|
||||||
*
|
* in @UpdateOperation.
|
||||||
* @return data type name of the value
|
*/
|
||||||
*/
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
DataType.Name value();
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
public @interface Set {
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Clarification of using the sub-type data type in the collection. It supports only simple data
|
||||||
* Says to use @DataType.Name.COUNTER type in schema Java type is @Long
|
* type (not Collection, UDT or Tuple)
|
||||||
*
|
*
|
||||||
* For this type there are special operations: increment and decrement
|
* <p>In case if you need UDT sub-type in the set, consider @UDTSet annotation
|
||||||
* in @UpdateOperation. You do not need to initialize counter value, it will be
|
*
|
||||||
* done automatically by Cassandra.
|
* @return data type name of the value
|
||||||
*/
|
*/
|
||||||
|
DataType.Name value();
|
||||||
@Documented
|
}
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
/**
|
||||||
public @interface Counter {
|
* Says to use @DataType.Name.CUSTOM type in schema Java type is @ByteBuffer or @byte[]
|
||||||
|
*
|
||||||
}
|
* <p>Uses for custom user types that has special implementation. Helenus does not deal with this
|
||||||
|
* class directly for now, uses only in serialized form.
|
||||||
/**
|
*/
|
||||||
* Says to use @DataType.Name.SET data type in schema with specific sub-type
|
@Documented
|
||||||
* Java type is @Set
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
*
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
public @interface Custom {
|
||||||
* thereof data retrieval operation result can be a collection with another
|
|
||||||
* implementation.
|
/**
|
||||||
*
|
* Class name of the custom user type that is implementation of the type
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
*
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
* @return class name of the custom type implementation
|
||||||
* types.
|
*/
|
||||||
*
|
String className();
|
||||||
* For this type there are special operations: add, addAll, remove and removeAll
|
}
|
||||||
* in @UpdateOperation.
|
|
||||||
*
|
/** Says to use @DataType.Name.TEXT type in schema Java type is @String Using by default */
|
||||||
*/
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
public @interface Text {}
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
public @interface Set {
|
/** Says to use @DataType.Name.TIMESTAMP type in schema Java type is @Date Using by default */
|
||||||
|
@Documented
|
||||||
/**
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* Clarification of using the sub-type data type in the collection. It supports
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
* only simple data type (not Collection, UDT or Tuple)
|
public @interface Timestamp {}
|
||||||
*
|
|
||||||
* In case if you need UDT sub-type in the set, consider @UDTSet annotation
|
/** Says to use @DataType.Name.TIMEUUID type in schema Java type is @UUID or @Date */
|
||||||
*
|
@Documented
|
||||||
* @return data type name of the value
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
*/
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
|
public @interface Timeuuid {}
|
||||||
DataType.Name value();
|
|
||||||
|
/**
|
||||||
}
|
* Says to use @DataType.Name.TUPLE type in schema Java type is @TupleValue or model interface
|
||||||
|
* with @Tuple annotation
|
||||||
/**
|
*/
|
||||||
* Says to use @DataType.Name.CUSTOM type in schema Java type is @ByteBuffer
|
@Documented
|
||||||
* or @byte[]
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
*
|
public @interface Tuple {
|
||||||
* Uses for custom user types that has special implementation. Helenus does not
|
|
||||||
* deal with this class directly for now, uses only in serialized form.
|
/**
|
||||||
*/
|
* If Java type is the @TupleValue then this field is required. Any Cassandra Tuple is the
|
||||||
|
* sequence of Cassandra types. For now Helenus supports only simple data types in tuples
|
||||||
@Documented
|
* for @TupleValue Java type
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
*
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
* <p>In case if Java type is the model interface with @Tuple annotation then all methods in
|
||||||
public @interface Custom {
|
* this interface can have Types annotations that can be complex types as well.
|
||||||
|
*
|
||||||
/**
|
* @return data type name sequence
|
||||||
* Class name of the custom user type that is implementation of the type
|
*/
|
||||||
*
|
DataType.Name[] value() default {};
|
||||||
* @return class name of the custom type implementation
|
}
|
||||||
*/
|
|
||||||
|
/**
|
||||||
String className();
|
* Says to use @DataType.Name.UDT type in schema Java type is @UDTValue or model interface
|
||||||
|
* with @UDT annotation
|
||||||
}
|
*/
|
||||||
|
@Documented
|
||||||
/**
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* Says to use @DataType.Name.TEXT type in schema Java type is @String Using by
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
* default
|
public @interface UDT {
|
||||||
*/
|
|
||||||
|
/**
|
||||||
@Documented
|
* If Java type is the @UDTValue then this field is required. Any Cassandra UDT has name and
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* must be created before this use as a Cassandra Type.
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
*
|
||||||
public @interface Text {
|
* <p>This value is the UDT name of the Cassandra Type that was already created in the schema
|
||||||
|
*
|
||||||
}
|
* <p>In case of Java type is the model interface with @UDT annotation then this field is not
|
||||||
|
* using since model interface defines UserDefinedType with specific name
|
||||||
/**
|
*
|
||||||
* Says to use @DataType.Name.TIMESTAMP type in schema Java type is @Date Using
|
* @return UDT name
|
||||||
* by default
|
*/
|
||||||
*/
|
String value() default "";
|
||||||
|
|
||||||
@Documented
|
/**
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* Only used for JavaType @UDTValue
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
*
|
||||||
public @interface Timestamp {
|
* <p>In case if value() method returns reserved word that can not be used as a name of UDT then
|
||||||
|
* forceQuote will add additional quotes around this name in all CQL queries.
|
||||||
}
|
*
|
||||||
|
* <p>Default value is false.
|
||||||
/**
|
*
|
||||||
* Says to use @DataType.Name.TIMEUUID type in schema Java type is @UUID
|
* @return true if quotation is needed
|
||||||
* or @Date
|
*/
|
||||||
*/
|
boolean forceQuote() default false;
|
||||||
|
}
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
/**
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
* Says to use @DataType.Name.MAP data type in schema with specific UDT sub-type as a key and
|
||||||
public @interface Timeuuid {
|
* simple sub-type as a value Java type is @Map
|
||||||
|
*
|
||||||
}
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
|
* retrieval operation result can be a collection with another implementation.
|
||||||
/**
|
*
|
||||||
* Says to use @DataType.Name.TUPLE type in schema Java type is @TupleValue or
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
* model interface with @Tuple annotation
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
*/
|
*
|
||||||
|
* <p>For this type there are special operations: put and putAll in @UpdateOperation.
|
||||||
@Documented
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Documented
|
||||||
public @interface Tuple {
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
/**
|
public @interface UDTKeyMap {
|
||||||
* If Java type is the @TupleValue then this field is required. Any Cassandra
|
|
||||||
* Tuple is the sequence of Cassandra types. For now Helenus supports only
|
/**
|
||||||
* simple data types in tuples for @TupleValue Java type
|
* Clarification of using the UDT data type as a key sub-type in the collection.
|
||||||
*
|
*
|
||||||
* In case if Java type is the model interface with @Tuple annotation then all
|
* @return annotation of UDT type
|
||||||
* methods in this interface can have Types annotations that can be complex
|
*/
|
||||||
* types as well.
|
UDT key();
|
||||||
*
|
|
||||||
* @return data type name sequence
|
/**
|
||||||
*/
|
* Clarification of using the sub-type data type in the collection. It supports only simple data
|
||||||
|
* type (not Collection, UDT or Tuple)
|
||||||
DataType.Name[] value() default {};
|
*
|
||||||
|
* <p>In case if you need UDT value sub-type in the map, consider @UDTMap annotations
|
||||||
}
|
*
|
||||||
|
* @return data type name of the value
|
||||||
/**
|
*/
|
||||||
* Says to use @DataType.Name.UDT type in schema Java type is @UDTValue or model
|
DataType.Name value();
|
||||||
* interface with @UDT annotation
|
}
|
||||||
*/
|
|
||||||
|
/**
|
||||||
@Documented
|
* Says to use @DataType.Name.LIST data type in schema with specific UDT sub-type Java type
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
* is @List
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
*
|
||||||
public @interface UDT {
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
|
* retrieval operation result can be a collection with another implementation.
|
||||||
/**
|
*
|
||||||
* If Java type is the @UDTValue then this field is required. Any Cassandra UDT
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
* has name and must be created before this use as a Cassandra Type.
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
*
|
*
|
||||||
* This value is the UDT name of the Cassandra Type that was already created in
|
* <p>For this type there are special operations: prepend, prependAll, setIdx, append, appendAll,
|
||||||
* the schema
|
* discard and discardAll in @UpdateOperation
|
||||||
*
|
*/
|
||||||
* In case of Java type is the model interface with @UDT annotation then this
|
@Documented
|
||||||
* field is not using since model interface defines UserDefinedType with
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* specific name
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
*
|
public @interface UDTList {
|
||||||
* @return UDT name
|
|
||||||
*/
|
/**
|
||||||
|
* Clarification of using the UDT data type as a sub-type in the collection.
|
||||||
String value() default "";
|
*
|
||||||
|
* @return annotation of the UDT value
|
||||||
/**
|
*/
|
||||||
* Only used for JavaType @UDTValue
|
UDT value();
|
||||||
*
|
}
|
||||||
* In case if value() method returns reserved word that can not be used as a
|
|
||||||
* name of UDT then forceQuote will add additional quotes around this name in
|
/**
|
||||||
* all CQL queries.
|
* Says to use @DataType.Name.MAP data type in schema with specific UDT sub-types Java type
|
||||||
*
|
* is @Map
|
||||||
* Default value is false.
|
*
|
||||||
*
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
* @return true if quotation is needed
|
* retrieval operation result can be a collection with another implementation.
|
||||||
*/
|
*
|
||||||
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
boolean forceQuote() default false;
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
|
*
|
||||||
}
|
* <p>For this type there are special operations: put and putAll in @UpdateOperation.
|
||||||
|
*/
|
||||||
/**
|
@Documented
|
||||||
* Says to use @DataType.Name.MAP data type in schema with specific UDT sub-type
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* as a key and simple sub-type as a value Java type is @Map
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
*
|
public @interface UDTMap {
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
|
||||||
* thereof data retrieval operation result can be a collection with another
|
/**
|
||||||
* implementation.
|
* Clarification of using the UDT data type as a key sub-type in the collection.
|
||||||
*
|
*
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
* @return annotation of the UDT key
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
*/
|
||||||
* types.
|
UDT key();
|
||||||
*
|
|
||||||
* For this type there are special operations: put and putAll
|
/**
|
||||||
* in @UpdateOperation.
|
* Clarification of using the UDT data type as a value sub-type in the collection.
|
||||||
*
|
*
|
||||||
*/
|
* @return annotation of the UDT value
|
||||||
|
*/
|
||||||
@Documented
|
UDT value();
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
}
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
public @interface UDTKeyMap {
|
/**
|
||||||
|
* Says to use @DataType.Name.SET data type in schema with specific UDT sub-type Java type is @Set
|
||||||
/**
|
*
|
||||||
* Clarification of using the UDT data type as a key sub-type in the collection.
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
*
|
* retrieval operation result can be a collection with another implementation.
|
||||||
* @return annotation of UDT type
|
*
|
||||||
*/
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
UDT key();
|
*
|
||||||
|
* <p>For this type there are special operations: add, addAll, remove and removeAll
|
||||||
/**
|
* in @UpdateOperation.
|
||||||
* Clarification of using the sub-type data type in the collection. It supports
|
*/
|
||||||
* only simple data type (not Collection, UDT or Tuple)
|
@Documented
|
||||||
*
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* In case if you need UDT value sub-type in the map, consider @UDTMap
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
* annotations
|
public @interface UDTSet {
|
||||||
*
|
|
||||||
* @return data type name of the value
|
/**
|
||||||
*/
|
* Clarification of using the UDT data type as a sub-type in the collection.
|
||||||
|
*
|
||||||
DataType.Name value();
|
* @return annotation of the UDT value
|
||||||
|
*/
|
||||||
}
|
UDT value();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Says to use @DataType.Name.LIST data type in schema with specific UDT
|
/**
|
||||||
* sub-type Java type is @List
|
* Says to use @DataType.Name.MAP data type in schema with specific simple sub-type as a key and
|
||||||
*
|
* UDT sub-type as a value Java type is @Map
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
*
|
||||||
* thereof data retrieval operation result can be a collection with another
|
* <p>Helenus does not allow to use a specific implementation of the collection thereof data
|
||||||
* implementation.
|
* retrieval operation result can be a collection with another implementation.
|
||||||
*
|
*
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
* <p>This annotation is usually used only for sub-types clarification and only in case if
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
* sub-type is Java type that corresponds to multiple Cassandra data types.
|
||||||
* types.
|
*
|
||||||
*
|
* <p>For this type there are special operations: put and putAll in @UpdateOperation.
|
||||||
* For this type there are special operations: prepend, prependAll, setIdx,
|
*/
|
||||||
* append, appendAll, discard and discardAll in @UpdateOperation
|
@Documented
|
||||||
*/
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
@Documented
|
public @interface UDTValueMap {
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
/**
|
||||||
public @interface UDTList {
|
* Clarification of using the sub-type data type in the collection. It supports only simple data
|
||||||
|
* type (not Collection, UDT or Tuple)
|
||||||
/**
|
*
|
||||||
* Clarification of using the UDT data type as a sub-type in the collection.
|
* <p>In case if you need UDT key sub-type in the map, consider @UDTMap annotations
|
||||||
*
|
*
|
||||||
* @return annotation of the UDT value
|
* @return data type name of the key
|
||||||
*/
|
*/
|
||||||
|
DataType.Name key();
|
||||||
UDT value();
|
|
||||||
|
/**
|
||||||
}
|
* Clarification of using the UDT data type as a value sub-type in the collection.
|
||||||
|
*
|
||||||
/**
|
* @return annotation of the UDT value
|
||||||
* Says to use @DataType.Name.MAP data type in schema with specific UDT
|
*/
|
||||||
* sub-types Java type is @Map
|
UDT value();
|
||||||
*
|
}
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
|
||||||
* thereof data retrieval operation result can be a collection with another
|
/** Says to use @DataType.Name.UUID type in schema Java type is @UUID Using by default */
|
||||||
* implementation.
|
@Documented
|
||||||
*
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
public @interface Uuid {}
|
||||||
* types.
|
|
||||||
*
|
/** Says to use @DataType.Name.VARCHAR type in schema Java type is @String */
|
||||||
* For this type there are special operations: put and putAll
|
@Documented
|
||||||
* in @UpdateOperation.
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
*
|
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||||
*/
|
public @interface Varchar {}
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
public @interface UDTMap {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clarification of using the UDT data type as a key sub-type in the collection.
|
|
||||||
*
|
|
||||||
* @return annotation of the UDT key
|
|
||||||
*/
|
|
||||||
|
|
||||||
UDT key();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clarification of using the UDT data type as a value sub-type in the
|
|
||||||
* collection.
|
|
||||||
*
|
|
||||||
* @return annotation of the UDT value
|
|
||||||
*/
|
|
||||||
|
|
||||||
UDT value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Says to use @DataType.Name.SET data type in schema with specific UDT sub-type
|
|
||||||
* Java type is @Set
|
|
||||||
*
|
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
|
||||||
* thereof data retrieval operation result can be a collection with another
|
|
||||||
* implementation.
|
|
||||||
*
|
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
|
||||||
* types.
|
|
||||||
*
|
|
||||||
* For this type there are special operations: add, addAll, remove and removeAll
|
|
||||||
* in @UpdateOperation.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
public @interface UDTSet {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clarification of using the UDT data type as a sub-type in the collection.
|
|
||||||
*
|
|
||||||
* @return annotation of the UDT value
|
|
||||||
*/
|
|
||||||
|
|
||||||
UDT value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Says to use @DataType.Name.MAP data type in schema with specific simple
|
|
||||||
* sub-type as a key and UDT sub-type as a value Java type is @Map
|
|
||||||
*
|
|
||||||
* Helenus does not allow to use a specific implementation of the collection
|
|
||||||
* thereof data retrieval operation result can be a collection with another
|
|
||||||
* implementation.
|
|
||||||
*
|
|
||||||
* This annotation is usually used only for sub-types clarification and only in
|
|
||||||
* case if sub-type is Java type that corresponds to multiple Cassandra data
|
|
||||||
* types.
|
|
||||||
*
|
|
||||||
* For this type there are special operations: put and putAll
|
|
||||||
* in @UpdateOperation.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
public @interface UDTValueMap {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clarification of using the sub-type data type in the collection. It supports
|
|
||||||
* only simple data type (not Collection, UDT or Tuple)
|
|
||||||
*
|
|
||||||
* In case if you need UDT key sub-type in the map, consider @UDTMap annotations
|
|
||||||
*
|
|
||||||
* @return data type name of the key
|
|
||||||
*/
|
|
||||||
|
|
||||||
DataType.Name key();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clarification of using the UDT data type as a value sub-type in the
|
|
||||||
* collection.
|
|
||||||
*
|
|
||||||
* @return annotation of the UDT value
|
|
||||||
*/
|
|
||||||
|
|
||||||
UDT value();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Says to use @DataType.Name.UUID type in schema Java type is @UUID Using by
|
|
||||||
* default
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
public @interface Uuid {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Says to use @DataType.Name.VARCHAR type in schema Java type is @String
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
|
||||||
public @interface Varchar {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,14 @@
|
||||||
package net.helenus.mapping.annotation;
|
package net.helenus.mapping.annotation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity annotation
|
* Entity annotation
|
||||||
*
|
*
|
||||||
* UDT annotation is used to define the UDT (User Defined Type) mapping for some interface
|
* <p>UDT annotation is used to define the UDT (User Defined Type) mapping for some interface
|
||||||
*
|
*
|
||||||
* There are three types of Entity mapping annotations: @Table, @UDT, @Tuple
|
* <p>There are three types of Entity mapping annotations: @Table, @UDT, @Tuple
|
||||||
*
|
|
||||||
* For each annotated @UDT type Helenus will create/update/verify Cassandra Type on startup
|
|
||||||
*
|
*
|
||||||
|
* <p>For each annotated @UDT type Helenus will create/update/verify Cassandra Type on startup
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Inherited
|
@Inherited
|
||||||
|
@ -33,23 +31,20 @@ import java.lang.annotation.*;
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
public @interface UDT {
|
public @interface UDT {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value is the SimpleName of the interface normalized to underscore
|
* Default value is the SimpleName of the interface normalized to underscore
|
||||||
*
|
*
|
||||||
* @return name of the UDT type
|
* @return name of the UDT type
|
||||||
*/
|
*/
|
||||||
|
String value() default "";
|
||||||
String value() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For reserved words in Cassandra we need quotation in CQL queries. This
|
|
||||||
* property marks that the name of the UDT type needs to be quoted.
|
|
||||||
*
|
|
||||||
* Default value is false, we are quoting only selected names.
|
|
||||||
*
|
|
||||||
* @return true if name have to be quoted
|
|
||||||
*/
|
|
||||||
|
|
||||||
boolean forceQuote() default false;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For reserved words in Cassandra we need quotation in CQL queries. This property marks that the
|
||||||
|
* name of the UDT type needs to be quoted.
|
||||||
|
*
|
||||||
|
* <p>Default value is false, we are quoting only selected names.
|
||||||
|
*
|
||||||
|
* @return true if name have to be quoted
|
||||||
|
*/
|
||||||
|
boolean forceQuote() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package net.helenus.mapping.convert;
|
package net.helenus.mapping.convert;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
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.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
@ -25,54 +24,48 @@ import net.helenus.mapping.value.BeanColumnValueProvider;
|
||||||
|
|
||||||
public abstract class AbstractEntityValueWriter<V> {
|
public abstract class AbstractEntityValueWriter<V> {
|
||||||
|
|
||||||
abstract void writeColumn(V outValue, Object value, HelenusProperty prop);
|
abstract void writeColumn(V outValue, Object value, HelenusProperty prop);
|
||||||
|
|
||||||
final HelenusEntity entity;
|
final HelenusEntity entity;
|
||||||
|
|
||||||
public AbstractEntityValueWriter(Class<?> iface) {
|
public AbstractEntityValueWriter(Class<?> iface) {
|
||||||
this.entity = Helenus.entity(iface);
|
this.entity = Helenus.entity(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(V outValue, Object source) {
|
public void write(V outValue, Object source) {
|
||||||
|
|
||||||
if (source instanceof MapExportable) {
|
if (source instanceof MapExportable) {
|
||||||
|
|
||||||
MapExportable exportable = (MapExportable) source;
|
MapExportable exportable = (MapExportable) source;
|
||||||
|
|
||||||
Map<String, Object> propertyToValueMap = exportable.toMap();
|
Map<String, Object> propertyToValueMap = exportable.toMap();
|
||||||
|
|
||||||
for (Map.Entry<String, Object> entry : propertyToValueMap.entrySet()) {
|
for (Map.Entry<String, Object> entry : propertyToValueMap.entrySet()) {
|
||||||
|
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
HelenusProperty prop = entity.getProperty(entry.getKey());
|
HelenusProperty prop = entity.getProperty(entry.getKey());
|
||||||
|
|
||||||
if (prop != null) {
|
if (prop != null) {
|
||||||
|
|
||||||
writeColumn(outValue, value, prop);
|
writeColumn(outValue, value, prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
|
|
||||||
}
|
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
||||||
|
|
||||||
} else {
|
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(source, -1, prop);
|
||||||
|
|
||||||
for (HelenusProperty prop : entity.getOrderedProperties()) {
|
|
||||||
|
|
||||||
Object value = BeanColumnValueProvider.INSTANCE.getColumnValue(source, -1, prop);
|
|
||||||
|
|
||||||
if (value != null) {
|
|
||||||
writeColumn(outValue, value, prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
writeColumn(outValue, value, prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,15 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public enum ByteArrayToByteBufferConverter implements Function<byte[], ByteBuffer> {
|
public enum ByteArrayToByteBufferConverter implements Function<byte[], ByteBuffer> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
public ByteBuffer apply(byte[] t) {
|
||||||
|
|
||||||
@Override
|
if (t == null) {
|
||||||
public ByteBuffer apply(byte[] t) {
|
return null;
|
||||||
|
}
|
||||||
if (t == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ByteBuffer.wrap(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return ByteBuffer.wrap(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,15 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public enum ByteBufferToByteArrayConverter implements Function<ByteBuffer, byte[]> {
|
public enum ByteBufferToByteArrayConverter implements Function<ByteBuffer, byte[]> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
public byte[] apply(ByteBuffer t) {
|
||||||
|
|
||||||
@Override
|
if (t == null) {
|
||||||
public byte[] apply(ByteBuffer t) {
|
return null;
|
||||||
|
}
|
||||||
if (t == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return t.array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,22 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.mapping.convert;
|
package net.helenus.mapping.convert;
|
||||||
|
|
||||||
|
import com.google.common.base.CaseFormat;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
|
||||||
|
|
||||||
public enum CamelCaseToUnderscoreConverter implements Function<String, String> {
|
public enum CamelCaseToUnderscoreConverter implements Function<String, String> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
public String apply(String source) {
|
||||||
|
|
||||||
@Override
|
if (source == null) {
|
||||||
public String apply(String source) {
|
throw new IllegalArgumentException("empty parameter");
|
||||||
|
}
|
||||||
if (source == null) {
|
|
||||||
throw new IllegalArgumentException("empty parameter");
|
|
||||||
}
|
|
||||||
|
|
||||||
return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,22 +18,15 @@ package net.helenus.mapping.convert;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import net.helenus.support.Timeuuid;
|
import net.helenus.support.Timeuuid;
|
||||||
|
|
||||||
/**
|
/** Simple Date to TimeUUID Converter */
|
||||||
* Simple Date to TimeUUID Converter
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public enum DateToTimeuuidConverter implements Function<Date, UUID> {
|
public enum DateToTimeuuidConverter implements Function<Date, UUID> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
public UUID apply(Date source) {
|
||||||
@Override
|
long milliseconds = source.getTime();
|
||||||
public UUID apply(Date source) {
|
return Timeuuid.of(milliseconds);
|
||||||
long milliseconds = source.getTime();
|
}
|
||||||
return Timeuuid.of(milliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,12 @@ package net.helenus.mapping.convert;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/** Enum to String Converter */
|
||||||
* Enum to String Converter
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public enum EnumToStringConverter implements Function<Enum, String> {
|
public enum EnumToStringConverter implements Function<Enum, String> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
public String apply(Enum source) {
|
||||||
@Override
|
return source.name();
|
||||||
public String apply(Enum source) {
|
}
|
||||||
return source.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package net.helenus.mapping.convert;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import net.helenus.core.Helenus;
|
import net.helenus.core.Helenus;
|
||||||
import net.helenus.mapping.HelenusEntity;
|
import net.helenus.mapping.HelenusEntity;
|
||||||
import net.helenus.mapping.value.ColumnValueProvider;
|
import net.helenus.mapping.value.ColumnValueProvider;
|
||||||
|
@ -25,24 +24,23 @@ import net.helenus.mapping.value.ValueProviderMap;
|
||||||
|
|
||||||
public class ProxyValueReader<T> implements Function<T, Object> {
|
public class ProxyValueReader<T> implements Function<T, Object> {
|
||||||
|
|
||||||
private final Class<?> iface;
|
private final Class<?> iface;
|
||||||
private final HelenusEntity entity;
|
private final HelenusEntity entity;
|
||||||
private final ColumnValueProvider valueProvider;
|
private final ColumnValueProvider valueProvider;
|
||||||
|
|
||||||
public ProxyValueReader(Class<?> iface, ColumnValueProvider valueProvider) {
|
public ProxyValueReader(Class<?> iface, ColumnValueProvider valueProvider) {
|
||||||
this.iface = iface;
|
this.iface = iface;
|
||||||
this.entity = Helenus.entity(iface);
|
this.entity = Helenus.entity(iface);
|
||||||
this.valueProvider = valueProvider;
|
this.valueProvider = valueProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(T source) {
|
public Object apply(T source) {
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
Map<String, Object> map = new ValueProviderMap(source, valueProvider, entity);
|
Map<String, Object> map = new ValueProviderMap(source, valueProvider, entity);
|
||||||
|
|
||||||
return Helenus.map(iface, map);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return Helenus.map(iface, map);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,14 @@ import java.util.function.Function;
|
||||||
|
|
||||||
public class StringToEnumConverter implements Function<String, Enum> {
|
public class StringToEnumConverter implements Function<String, Enum> {
|
||||||
|
|
||||||
private final Class<? extends Enum> enumClass;
|
private final Class<? extends Enum> enumClass;
|
||||||
|
|
||||||
public StringToEnumConverter(Class<?> enumClass) {
|
public StringToEnumConverter(Class<?> enumClass) {
|
||||||
this.enumClass = (Class<? extends Enum>) enumClass;
|
this.enumClass = (Class<? extends Enum>) enumClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Enum apply(String source) {
|
|
||||||
return Enum.valueOf(enumClass, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enum apply(String source) {
|
||||||
|
return Enum.valueOf(enumClass, source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,13 @@ package net.helenus.mapping.convert;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import net.helenus.support.Timeuuid;
|
import net.helenus.support.Timeuuid;
|
||||||
|
|
||||||
public enum TimeuuidToDateConverter implements Function<UUID, Date> {
|
public enum TimeuuidToDateConverter implements Function<UUID, Date> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
INSTANCE;
|
@Override
|
||||||
|
public Date apply(UUID source) {
|
||||||
@Override
|
return new Date(Timeuuid.getTimestampMillis(source));
|
||||||
public Date apply(UUID source) {
|
}
|
||||||
return new Date(Timeuuid.getTimestampMillis(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue