refactor existing classes

This commit is contained in:
Albert Shift 2015-03-30 22:06:40 -07:00
parent e7cd42577a
commit e40c40b49c
9 changed files with 242 additions and 122 deletions

View file

@ -26,18 +26,21 @@ import com.datastax.driver.core.DataType;
import com.datastax.driver.core.RegularStatement;
import com.datastax.driver.core.SimpleStatement;
import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.UserType;
import com.datastax.driver.core.schemabuilder.Alter;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.Create.Options;
import com.datastax.driver.core.schemabuilder.CreateType;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.core.schemabuilder.SchemaStatement;
import com.datastax.driver.core.schemabuilder.UDTType;
import com.noorq.casser.mapping.CasserEntityType;
import com.noorq.casser.mapping.CasserMappingEntity;
import com.noorq.casser.mapping.CasserMappingProperty;
import com.noorq.casser.mapping.CqlUtil;
import com.noorq.casser.mapping.OrderingDirection;
import com.noorq.casser.support.CasserMappingException;
import com.noorq.casser.support.Either;
public final class SchemaUtil {
@ -69,7 +72,18 @@ public final class SchemaUtil {
throw new CasserMappingException("primary key columns are not supported in UserDefinedType for column " + columnName + " in entity " + entity);
}
create.addColumn(columnName, prop.getDataType());
Either<DataType,String> type = prop.getColumnType();
if (type.isLeft()) {
create.addColumn(columnName, type.getLeft());
}
else if (type.isRight()) {
UDTType udtType = SchemaBuilder.frozen(type.getRight());
create.addUDTColumn(prop.getColumnName(), udtType);
}
else {
throwNoMapping(prop);
}
}
@ -110,16 +124,26 @@ public final class SchemaUtil {
OrdinalBasedPropertyComparator.INSTANCE);
for (CasserMappingProperty prop : partitionKeys) {
create.addPartitionKey(prop.getColumnName(), prop.getDataType());
Either<DataType,String> type = prop.getColumnType();
if (type.isRight()) {
throw new CasserMappingException("user defined type can not be a partition key for " + prop.getPropertyName() + " in " + prop.getEntity());
}
create.addPartitionKey(prop.getColumnName(), type.getLeft());
}
for (CasserMappingProperty prop : clusteringColumns) {
if (prop.getDataType() != null) {
create.addClusteringColumn(prop.getColumnName(), prop.getDataType());
Either<DataType,String> type = prop.getColumnType();
if (type.isLeft()) {
create.addClusteringColumn(prop.getColumnName(), type.getLeft());
}
else if (prop.getUDTType() != null) {
create.addUDTClusteringColumn(prop.getColumnName(), prop.getUDTType());
else if (type.isRight()) {
UDTType udtType = SchemaBuilder.frozen(type.getRight());
create.addUDTClusteringColumn(prop.getColumnName(), udtType);
}
else {
throwNoMapping(prop);
@ -129,13 +153,16 @@ public final class SchemaUtil {
for (CasserMappingProperty prop : columns) {
Either<DataType,String> type = prop.getColumnType();
if (prop.isStatic()) {
if (prop.getDataType() != null) {
create.addStaticColumn(prop.getColumnName(), prop.getDataType());
if (type.isLeft()) {
create.addStaticColumn(prop.getColumnName(), type.getLeft());
}
else if (prop.getUDTType() != null) {
create.addUDTStaticColumn(prop.getColumnName(), prop.getUDTType());
else if (type.isRight()) {
UDTType udtType = SchemaBuilder.frozen(type.getRight());
create.addUDTStaticColumn(prop.getColumnName(), udtType);
}
else {
throwNoMapping(prop);
@ -143,11 +170,12 @@ public final class SchemaUtil {
}
else {
if (prop.getDataType() != null) {
create.addColumn(prop.getColumnName(), prop.getDataType());
if (type.isLeft()) {
create.addColumn(prop.getColumnName(), type.getLeft());
}
else if (prop.getUDTType() != null) {
create.addUDTColumn(prop.getColumnName(), prop.getUDTType());
else if (type.isRight()) {
UDTType udtType = SchemaBuilder.frozen(type.getRight());
create.addUDTColumn(prop.getColumnName(), udtType);
}
else {
throwNoMapping(prop);
@ -187,37 +215,61 @@ public final class SchemaUtil {
for (CasserMappingProperty prop : entity.getMappingProperties()) {
String columnName = prop.getColumnName();
DataType columnDataType = prop.getDataType();
String loweredColumnName = columnName.toLowerCase();
if (dropRemovedColumns) {
visitedColumns.add(loweredColumnName);
}
ColumnMetadata columnMetadata = tmd.getColumn(loweredColumnName);
if (columnMetadata != null
&& columnDataType.equals(columnMetadata.getType())) {
continue;
}
if (prop.isPartitionKey() || prop.isClusteringColumn()) {
throw new CasserMappingException(
"unable to alter column that is a part of primary key '"
+ columnName + "' for entity "
+ entity);
}
Either<DataType,String> type = prop.getColumnType();
ColumnMetadata columnMetadata = tmd.getColumn(loweredColumnName);
if (columnMetadata == null) {
result.add(alter.addColumn(columnName).type(columnDataType));
if (columnMetadata != null) {
} else {
result.add(alter.alterColumn(columnName).type(columnDataType));
if (type.isLeft()) {
if (!type.getLeft().equals(columnMetadata.getType())) {
result.add(alter.alterColumn(columnName).type(type.getLeft()));
}
}
else if (type.isRight()) {
DataType metadataType = columnMetadata.getType();
if (metadataType.getName() == DataType.Name.UDT &&
metadataType instanceof UserType) {
UserType metadataUserType = (UserType) metadataType;
if (!type.getRight().equals(metadataUserType.getTypeName())) {
UDTType udtType = SchemaBuilder.frozen(type.getRight());
result.add(alter.alterColumn(columnName).udtType(udtType));
}
}
else {
throw new CasserMappingException("expected UserType in metadata " + metadataType + " for " + prop.getPropertyName() + " in " + prop.getEntity());
}
}
}
else if (type.isLeft()) {
result.add(alter.addColumn(columnName).type(type.getLeft()));
}
else if (type.isRight()) {
UDTType udtType = SchemaBuilder.frozen(type.getRight());
result.add(alter.addColumn(columnName).udtType(udtType));
}
}
if (dropRemovedColumns) {
@ -239,7 +291,16 @@ public final class SchemaUtil {
throw new CasserMappingException("expected table entity " + entity);
}
return SchemaBuilder.dropTable(entity.getName());
return SchemaBuilder.dropTable(entity.getName()).ifExists();
}
public static SchemaStatement createIndex(CasserMappingProperty prop) {
return SchemaBuilder.createIndex(prop.getIndexName().get())
.ifNotExists()
.onTable(prop.getEntity().getName())
.andColumn(prop.getColumnName());
}

View file

@ -45,6 +45,7 @@ public class SessionInitializer extends AbstractSessionOperations {
private CasserMappingRepository mappingRepository = new CasserMappingRepository();
private boolean dropRemovedColumns = false;
private boolean dropRemovedIndexes = false;
private KeyspaceMetadata keyspaceMetadata;
@ -106,7 +107,12 @@ public class SessionInitializer extends AbstractSessionOperations {
this.dropRemovedColumns = enabled;
return this;
}
public SessionInitializer dropRemovedIndexes(boolean enabled) {
this.dropRemovedIndexes = enabled;
return this;
}
@Override
public boolean isShowCql() {
return showCql;

View file

@ -16,6 +16,7 @@
package com.noorq.casser.core;
import java.util.List;
import java.util.stream.Collectors;
import com.datastax.driver.core.RegularStatement;
import com.datastax.driver.core.TableMetadata;
@ -36,7 +37,16 @@ public final class TableOperations {
}
public void createTable(CasserMappingEntity entity) {
sessionOps.execute(SchemaUtil.createTable(entity));
List<SchemaStatement> list = entity.getMappingProperties().stream()
.filter(p -> p.getIndexName().isPresent())
.map(p -> SchemaUtil.createIndex(p))
.collect(Collectors.toList());
executeBatch(list);
}
public void validateTable(TableMetadata tmd, CasserMappingEntity entity) {
@ -47,6 +57,8 @@ public final class TableOperations {
List<SchemaStatement> list = SchemaUtil.alterTable(tmd, entity, dropRemovedColumns);
addAlterIndexes(tmd, entity, list);
if (!list.isEmpty()) {
throw new CasserException("schema changed for entity " + entity.getMappingInterface() + ", apply this command: " + list);
}
@ -60,7 +72,18 @@ public final class TableOperations {
}
List<SchemaStatement> list = SchemaUtil.alterTable(tmd, entity, dropRemovedColumns);
addAlterIndexes(tmd, entity, list);
executeBatch(list);
}
private void addAlterIndexes(TableMetadata tmd, CasserMappingEntity entity, List<SchemaStatement> list) {
}
private void executeBatch(List<SchemaStatement> list) {
if (!list.isEmpty()) {
Batch b = QueryBuilder.batch(list.toArray(new RegularStatement[list.size()]));
sessionOps.execute(b);

View file

@ -21,12 +21,14 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.datastax.driver.core.DataType;
import com.noorq.casser.core.Casser;
import com.noorq.casser.mapping.CasserMappingEntity;
import com.noorq.casser.mapping.CasserMappingProperty;
import com.noorq.casser.support.CasserException;
import com.noorq.casser.support.CasserMappingException;
import com.noorq.casser.support.DslPropertyException;
import com.noorq.casser.support.Either;
public class DslInvocationHandler<E> implements InvocationHandler {
@ -46,7 +48,9 @@ public class DslInvocationHandler<E> implements InvocationHandler {
map.put(prop.getGetterMethod(), prop);
if (prop.getUDTType() != null) {
Either<DataType,String> type = prop.getColumnType();
if (type.isRight()) {
Object childDsl = Casser.dsl(prop.getJavaType(), classLoader,
Optional.of(new CasserPropertyNode(prop, parent)));
@ -69,7 +73,9 @@ public class DslInvocationHandler<E> implements InvocationHandler {
if (prop != null) {
if (prop.getUDTType() != null) {
Either<DataType,String> type = prop.getColumnType();
if (type.isRight()) {
Object childDsl = udtMap.get(method);

View file

@ -29,8 +29,6 @@ import java.util.function.Function;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.UDTValue;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.core.schemabuilder.UDTType;
import com.noorq.casser.mapping.convert.DateToTimeUUIDConverter;
import com.noorq.casser.mapping.convert.EntityToUDTValueConverter;
import com.noorq.casser.mapping.convert.EnumToStringConverter;
@ -39,6 +37,7 @@ import com.noorq.casser.mapping.convert.TimeUUIDToDateConverter;
import com.noorq.casser.mapping.convert.TypedConverter;
import com.noorq.casser.mapping.convert.UDTValueToEntityConverter;
import com.noorq.casser.support.CasserMappingException;
import com.noorq.casser.support.Either;
public class CasserMappingProperty implements CasserProperty {
@ -48,6 +47,8 @@ public class CasserMappingProperty implements CasserProperty {
private Optional<String> propertyName = Optional.empty();
private Optional<String> columnName = Optional.empty();
private Optional<String> indexName = null;
private boolean keyInfo = false;
private boolean isPartitionKey = false;
private boolean isClusteringColumn = false;
@ -55,11 +56,7 @@ public class CasserMappingProperty implements CasserProperty {
private OrderingDirection ordering = OrderingDirection.ASC;
private Optional<Class<?>> javaType = Optional.empty();
private boolean typeInfo = false;
private DataType dataType = null;
private UDTType udtType = null;
private String udtName = null;
private Optional<Either<DataType, String>> columnType = Optional.empty();
private Optional<Boolean> isStatic = Optional.empty();
@ -85,23 +82,13 @@ public class CasserMappingProperty implements CasserProperty {
}
@Override
public DataType getDataType() {
ensureTypeInfo();
return dataType;
public Either<DataType, String> getColumnType() {
if (!columnType.isPresent()) {
columnType = Optional.of(resolveColumnType());
}
return columnType.get();
}
@Override
public UDTType getUDTType() {
ensureTypeInfo();
return udtType;
}
@Override
public String getUDTName() {
ensureTypeInfo();
return udtName;
}
@Override
public boolean isPartitionKey() {
ensureKeyInfo();
@ -153,6 +140,16 @@ public class CasserMappingProperty implements CasserProperty {
return columnName.get();
}
@Override
public Optional<String> getIndexName() {
if (indexName == null) {
indexName = Optional.ofNullable(MappingUtil.getIndexName(getter));
}
return indexName;
}
@Override
public String getPropertyName() {
@ -180,7 +177,9 @@ public class CasserMappingProperty implements CasserProperty {
private Function<Object, Object> resolveReadConverter(CasserMappingRepository repository) {
if (getUDTType() != null) {
Either<DataType, String> columnType = getColumnType();
if (columnType.isRight()) {
Class<Object> javaType = (Class<Object>) getJavaType();
@ -190,26 +189,28 @@ public class CasserMappingProperty implements CasserProperty {
new UDTValueToEntityConverter(javaType, repository));
}
else {
Class<?> propertyType = getJavaType();
if (Enum.class.isAssignableFrom(propertyType)) {
return TypedConverter.create(
String.class,
Enum.class,
new StringToEnumConverter(propertyType));
Class<?> propertyType = getJavaType();
if (Enum.class.isAssignableFrom(propertyType)) {
return TypedConverter.create(
String.class,
Enum.class,
new StringToEnumConverter(propertyType));
}
DataType dataType = columnType.getLeft();
if (dataType.getName() == DataType.Name.TIMEUUID && propertyType == Date.class) {
return TypedConverter.create(
UUID.class,
Date.class,
TimeUUIDToDateConverter.INSTANCE);
}
return null;
}
DataType dataType = getDataType();
if (dataType.getName() == DataType.Name.TIMEUUID && propertyType == Date.class) {
return TypedConverter.create(
UUID.class,
Date.class,
TimeUUIDToDateConverter.INSTANCE);
}
return null;
}
@Override
@ -224,58 +225,57 @@ public class CasserMappingProperty implements CasserProperty {
private Function<Object, Object> resolveWriteConverter(CasserMappingRepository repository) {
if (getUDTType() != null) {
Either<DataType, String> columnType = getColumnType();
if (columnType.isRight()) {
Class<Object> javaType = (Class<Object>) getJavaType();
return TypedConverter.create(
javaType,
UDTValue.class,
new EntityToUDTValueConverter(javaType, getUDTName(), repository));
new EntityToUDTValueConverter(javaType, columnType.getRight(), repository));
}
else {
Class<?> propertyType = getJavaType();
if (Enum.class.isAssignableFrom(propertyType)) {
return TypedConverter.create(
Enum.class,
String.class,
EnumToStringConverter.INSTANCE);
}
DataType dataType = getDataType();
if (dataType.getName() == DataType.Name.TIMEUUID && propertyType == Date.class) {
return TypedConverter.create(
Date.class,
UUID.class,
DateToTimeUUIDConverter.INSTANCE);
}
return null;
}
Class<?> propertyType = getJavaType();
private void ensureTypeInfo() {
if (!typeInfo) {
dataType = resolveDataType();
if (dataType == null) {
if (Enum.class.isAssignableFrom(propertyType)) {
Class<?> propertyType = getJavaType();
this.udtName = MappingUtil.getUserDefinedTypeName(propertyType, false);
if (this.udtName != null) {
this.udtType = SchemaBuilder.frozen(udtName);
}
return TypedConverter.create(
Enum.class,
String.class,
EnumToStringConverter.INSTANCE);
}
typeInfo = true;
}
DataType dataType = columnType.getLeft();
if (dataType.getName() == DataType.Name.TIMEUUID && propertyType == Date.class) {
return TypedConverter.create(
Date.class,
UUID.class,
DateToTimeUUIDConverter.INSTANCE);
}
return null;
}
}
private Either<DataType, String> resolveColumnType() {
DataType dataType = resolveDataType();
if (dataType != null) {
return Either.left(dataType);
}
else {
Class<?> propertyType = getJavaType();
String udtName = MappingUtil.getUserDefinedTypeName(propertyType, false);
return Either.right(udtName);
}
}
private DataType resolveDataType() {

View file

@ -21,10 +21,11 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.UserType;
import com.datastax.driver.core.schemabuilder.UDTType;
import com.noorq.casser.support.CasserException;
import com.noorq.casser.support.CasserMappingException;
import com.noorq.casser.support.Either;
public class CasserMappingRepository {
@ -87,9 +88,9 @@ public class CasserMappingRepository {
for (CasserMappingProperty prop : props) {
UDTType type = prop.getUDTType();
Either<DataType,String> type = prop.getColumnType();
if (type != null) {
if (type.isRight()) {
add(prop.getJavaType(), OPTIONAL_UDT);

View file

@ -19,7 +19,7 @@ import java.util.Optional;
import java.util.function.Function;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.schemabuilder.UDTType;
import com.noorq.casser.support.Either;
public interface CasserProperty {
@ -29,14 +29,12 @@ public interface CasserProperty {
String getColumnName();
Optional<String> getIndexName();
Class<?> getJavaType();
DataType getDataType();
Either<DataType, String> getColumnType();
UDTType getUDTType();
String getUDTName();
boolean isPartitionKey();
boolean isClusteringColumn();

View file

@ -21,6 +21,11 @@ public final class CqlUtil {
}
public static String forceQuote(String identity) {
if (identity == null) {
return null;
}
if (identity.startsWith("\"")) {
return identity;
}

View file

@ -28,6 +28,26 @@ public final class MappingUtil {
private MappingUtil() {
}
public static String getIndexName(Method getterMethod) {
String indexName = null;
Index index = getterMethod.getDeclaredAnnotation(Index.class);
if (index != null) {
indexName = index.value();
if (index.forceQuote()) {
indexName = CqlUtil.forceQuote(indexName);
}
if (indexName == null || indexName.isEmpty()) {
indexName = getDefaultColumnName(getterMethod);
}
}
return indexName;
}
public static String getColumnName(Method getterMethod) {
String columnName = null;