DATACASS-296 - Polish.

Original pull request: #68.
This commit is contained in:
John Blum
2016-06-29 14:44:36 -07:00
parent 66a69c0926
commit 1c824f2965
17 changed files with 247 additions and 212 deletions

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2016 the original author or authors
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -37,7 +37,7 @@ import org.springframework.data.mapping.context.MappingContext;
/**
* Base class for Spring Data Cassandra configuration using JavaConfig.
*
*
* @author Alex Shvid
* @author Matthew T. Adams
* @author John Blum
@@ -65,24 +65,22 @@ public abstract class AbstractCassandraConfiguration extends AbstractClusterConf
}
/**
* Return the {@link MappingContext} instance to map Entities to properties.
* Creates a {@link CassandraConverter} using the configured {@link #cassandraMapping()}.
* Will apply all specified {@link #customConversions()}.
*
* @throws ClassNotFoundException
* @return {@link CassandraConverter} used to convert Java and Cassandra value types during the mapping process.
* @throws Exception if an error occurs initializing or registering the converter.
* @see #cassandraMapping()
* @see #customConversions()
*/
@Bean
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
public CassandraConverter cassandraConverter() throws Exception {
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
MappingCassandraConverter mappingCassandraConverter = new MappingCassandraConverter(cassandraMapping());
mappingContext.setBeanClassLoader(beanClassLoader);
mappingContext.setInitialEntitySet(CassandraEntityClassScanner.scan(getEntityBasePackages()));
mappingCassandraConverter.setCustomConversions(customConversions());
CustomConversions customConversions = customConversions();
mappingContext.setCustomConversions(customConversions);
mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder());
return mappingContext;
return mappingCassandraConverter;
}
/**
@@ -99,22 +97,26 @@ public abstract class AbstractCassandraConfiguration extends AbstractClusterConf
}
/**
* Creates a {@link CassandraConverter} using the configured {@link #cassandraMapping()}. Will get
* {@link #customConversions()} applied.
* Return the {@link MappingContext} instance to map Entities to properties.
*
* @see #customConversions()
* @see #cassandraMapping()
* @return
* @throws Exception
* @throws ClassNotFoundException if the Cassandra Entity class type identified by name
* cannot be found during the scan.
* @see CassandraMappingContext
*/
@Bean
public CassandraConverter cassandraConverter() throws Exception {
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
MappingCassandraConverter mappingCassandraConverter = new MappingCassandraConverter(cassandraMapping());
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
mappingCassandraConverter.setCustomConversions(customConversions());
mappingContext.setBeanClassLoader(beanClassLoader);
mappingContext.setInitialEntitySet(CassandraEntityClassScanner.scan(getEntityBasePackages()));
return mappingCassandraConverter;
CustomConversions customConversions = customConversions();
mappingContext.setCustomConversions(customConversions);
mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder());
return mappingContext;
}
/**

View File

@@ -49,22 +49,20 @@ abstract class CassandraConverters {
/**
* Returns the converters to be registered.
*
* @return
*/
public static Collection<Object> getConvertersToRegister() {
List<Object> converters = new ArrayList<Object>();
converters.add(RowToCassandraLocalDateConverter.INSTANCE);
converters.add(RowToNumberConverterFactory.INSTANCE);
converters.add(RowToBooleanConverter.INSTANCE);
converters.add(RowToDateConverter.INSTANCE);
converters.add(RowToInetAddressConverter.INSTANCE);
converters.add(RowToStringConverter.INSTANCE);
converters.add(RowToUuidConverter.INSTANCE);
converters.add(RowToListConverter.INSTANCE);
converters.add(RowToMapConverter.INSTANCE);
converters.add(RowToNumberConverterFactory.INSTANCE);
converters.add(RowToStringConverter.INSTANCE);
converters.add(RowToUuidConverter.INSTANCE);
return converters;
}
@@ -90,7 +88,6 @@ abstract class CassandraConverters {
@Override
public Date convert(Row row) {
return row.getTimestamp(0);
}
}
@@ -148,11 +145,9 @@ abstract class CassandraConverters {
public T convert(Row source) {
Object object = source.getObject(0);
if (object == null) {
return null;
}
return NumberUtils.convertNumberToTargetClass((Number) object, this.targetType);
return (object != null ? NumberUtils.convertNumberToTargetClass((Number) object, this.targetType)
: null);
}
}
}

View File

@@ -51,9 +51,9 @@ public abstract class CassandraJodaTimeConverters {
}
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(CassandraLocalDateToLocalDateConverter.INSTANCE);
converters.add(LocalDateToCassandraLocalDateConverter.INSTANCE);
converters.add(CassandraLocalDateToDateMidnightConverter.INSTANCE);
converters.add(DateMidnightToCassandraLocalDateConverter.INSTANCE);
@@ -65,7 +65,7 @@ public abstract class CassandraJodaTimeConverters {
*
* @author Mark Paluch
*/
public static enum CassandraLocalDateToLocalDateConverter
public enum CassandraLocalDateToLocalDateConverter
implements Converter<com.datastax.driver.core.LocalDate, LocalDate> {
INSTANCE;
@@ -81,7 +81,7 @@ public abstract class CassandraJodaTimeConverters {
*
* @author Mark Paluch
*/
public static enum LocalDateToCassandraLocalDateConverter
public enum LocalDateToCassandraLocalDateConverter
implements Converter<LocalDate, com.datastax.driver.core.LocalDate> {
INSTANCE;
@@ -99,7 +99,7 @@ public abstract class CassandraJodaTimeConverters {
*
* @author Mark Paluch
*/
public static enum CassandraLocalDateToDateMidnightConverter
public enum CassandraLocalDateToDateMidnightConverter
implements Converter<com.datastax.driver.core.LocalDate, DateMidnight> {
INSTANCE;
@@ -116,7 +116,7 @@ public abstract class CassandraJodaTimeConverters {
*
* @author Mark Paluch
*/
public static enum DateMidnightToCassandraLocalDateConverter
public enum DateMidnightToCassandraLocalDateConverter
implements Converter<DateMidnight, com.datastax.driver.core.LocalDate> {
INSTANCE;

View File

@@ -52,6 +52,7 @@ public abstract class CassandraJsr310Converters {
}
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(CassandraLocalDateToLocalDateConverter.INSTANCE);
converters.add(LocalDateToCassandraLocalDateConverter.INSTANCE);
@@ -60,10 +61,10 @@ public abstract class CassandraJsr310Converters {
/**
* Simple singleton to convert {@link com.datastax.driver.core.LocalDate}s to their {@link LocalDate} representation.
*
*
* @author Mark Paluch
*/
public static enum CassandraLocalDateToLocalDateConverter
public enum CassandraLocalDateToLocalDateConverter
implements Converter<com.datastax.driver.core.LocalDate, LocalDate> {
INSTANCE;
@@ -79,7 +80,7 @@ public abstract class CassandraJsr310Converters {
*
* @author Mark Paluch
*/
public static enum LocalDateToCassandraLocalDateConverter
public enum LocalDateToCassandraLocalDateConverter
implements Converter<LocalDate, com.datastax.driver.core.LocalDate> {
INSTANCE;

View File

@@ -18,17 +18,12 @@ package org.springframework.data.cassandra.convert;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ThreeTenBackPortConverters;
import org.springframework.util.ClassUtils;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.ZoneId;
/**
* Helper class to register {@link Converter} implementations for the ThreeTen Backport project in case it's present on
@@ -58,6 +53,7 @@ public abstract class CassandraThreeTenBackPortConverters {
}
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(CassandraLocalDateToLocalDateConverter.INSTANCE);
converters.add(LocalDateToCassandraLocalDateConverter.INSTANCE);
@@ -69,7 +65,7 @@ public abstract class CassandraThreeTenBackPortConverters {
*
* @author Mark Paluch
*/
public static enum CassandraLocalDateToLocalDateConverter
public enum CassandraLocalDateToLocalDateConverter
implements Converter<com.datastax.driver.core.LocalDate, LocalDate> {
INSTANCE;
@@ -85,7 +81,7 @@ public abstract class CassandraThreeTenBackPortConverters {
*
* @author Mark Paluch
*/
public static enum LocalDateToCassandraLocalDateConverter
public enum LocalDateToCassandraLocalDateConverter
implements Converter<LocalDate, com.datastax.driver.core.LocalDate> {
INSTANCE;

View File

@@ -180,16 +180,17 @@ public class CustomConversions {
private void registerConversion(Object converter) {
Class<?> type = converter.getClass();
boolean isWriting = type.isAnnotationPresent(WritingConverter.class);
boolean isReading = type.isAnnotationPresent(ReadingConverter.class);
boolean isWriting = type.isAnnotationPresent(WritingConverter.class);
if (converter instanceof GenericConverter) {
GenericConverter genericConverter = (GenericConverter) converter;
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
register(new ConverterRegistration(pair, isReading, isWriting));
}
} else if (converter instanceof ConverterFactory) {
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), ConverterFactory.class);
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
} else if (converter instanceof Converter) {
@@ -354,6 +355,7 @@ public class CustomConversions {
for (ConvertiblePair typePair : pairs) {
if (typePair.getSourceType().isAssignableFrom(sourceType)) {
Class<?> targetType = typePair.getTargetType();
if (requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType)) {
return targetType;
}
@@ -381,7 +383,8 @@ public class CustomConversions {
}
Class<?> type = producer.get();
cache.put(key, CacheValue.<Class<?>> ofNullable(type));
cache.put(key, CacheValue.<Class<?>>ofNullable(type));
return type;
}

View File

@@ -56,6 +56,7 @@ import com.datastax.driver.core.TableMetadata;
* @author Alex Shvid
* @author Matthew T. Adams
* @author Mark Paluch
* @author John Blum
*/
public class BasicCassandraMappingContext
extends AbstractMappingContext<CassandraPersistentEntity<?>, CassandraPersistentProperty>
@@ -89,7 +90,7 @@ public class BasicCassandraMappingContext
/**
* Sets the {@link CustomConversions}.
*
*
* @param customConversions must not be {@literal null}.
* @since 1.5
*/
@@ -157,10 +158,10 @@ public class BasicCassandraMappingContext
if (entities == null) {
entities = new HashSet<CassandraPersistentEntity<?>>();
entitySetsByTableName.put(entity.getTableName(), entities);
}
entities.add(entity);
entitySetsByTableName.put(entity.getTableName(), entities);
if (entity.isCompositePrimaryKey()) {
primaryKeyEntities.add(entity);
@@ -193,11 +194,11 @@ public class BasicCassandraMappingContext
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
public void doWithPersistentProperty(CassandraPersistentProperty property) {
if (prop.isCompositePrimaryKey()) {
if (property.isCompositePrimaryKey()) {
CassandraPersistentEntity<?> pkEntity = getPersistentEntity(prop.getRawType());
CassandraPersistentEntity<?> pkEntity = getPersistentEntity(property.getRawType());
pkEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@@ -213,12 +214,12 @@ public class BasicCassandraMappingContext
});
} else {
if (prop.isIdProperty() || prop.isPartitionKeyColumn()) {
spec.partitionKeyColumn(prop.getColumnName(), getDataType(prop));
} else if (prop.isClusterKeyColumn()) {
spec.clusteredKeyColumn(prop.getColumnName(), getDataType(prop));
if (property.isIdProperty() || property.isPartitionKeyColumn()) {
spec.partitionKeyColumn(property.getColumnName(), getDataType(property));
} else if (property.isClusterKeyColumn()) {
spec.clusteredKeyColumn(property.getColumnName(), getDataType(property));
} else {
spec.column(prop.getColumnName(), getDataType(prop));
spec.column(property.getColumnName(), getDataType(property));
}
}
}
@@ -236,13 +237,10 @@ public class BasicCassandraMappingContext
* @see org.springframework.data.mapping.context.AbstractMappingContext#shouldCreatePersistentEntityFor(org.springframework.data.util.TypeInformation)
*/
@Override
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> typeInfo) {
if (customConversions.hasCustomWriteTarget(type.getType())) {
return false;
}
return super.shouldCreatePersistentEntityFor(type);
return (!customConversions.hasCustomWriteTarget(typeInfo.getType())
&& super.shouldCreatePersistentEntityFor(typeInfo));
}
/* (non-Javadoc)
@@ -252,11 +250,7 @@ public class BasicCassandraMappingContext
protected CassandraPersistentEntity<?> addPersistentEntity(TypeInformation<?> typeInformation) {
// Prevent conversion types created as CassandraPersistentEntity
if (shouldCreatePersistentEntityFor(typeInformation)) {
return super.addPersistentEntity(typeInformation);
}
return null;
return (shouldCreatePersistentEntityFor(typeInformation) ? super.addPersistentEntity(typeInformation) : null);
}
/* (non-Javadoc)
@@ -301,55 +295,51 @@ public class BasicCassandraMappingContext
@Override
public DataType getDataType(Class<?> type) {
if (customConversions.hasCustomWriteTarget(type)) {
return getDataTypeFor(customConversions.getCustomWriteTarget(type));
}
return getDataTypeFor(type);
return (customConversions.hasCustomWriteTarget(type)
? getDataTypeFor(customConversions.getCustomWriteTarget(type))
: getDataTypeFor(type));
}
public void setMapping(Mapping mapping) {
Assert.notNull(mapping);
Assert.notNull(mapping, "Mapping must not be null");
this.mapping = mapping;
}
protected void processMappingOverrides() {
if (mapping == null) {
return;
}
if (mapping != null) {
for (EntityMapping entityMapping : mapping.getEntityMappings()) {
for (EntityMapping entityMapping : mapping.getEntityMappings()) {
if (entityMapping == null) {
continue;
}
if (entityMapping == null) {
continue;
String entityClassName = entityMapping.getEntityClassName();
try {
Class<?> entityClass = ClassUtils.forName(entityClassName, beanClassLoader);
CassandraPersistentEntity<?> entity = getPersistentEntity(entityClass);
if (entity == null) {
throw new IllegalStateException(String.format("unknown persistent entity class name [%s]", entityClassName));
}
String tableName = entityMapping.getTableName();
if (StringUtils.hasText(tableName)) {
entity.setTableName(cqlId(tableName, Boolean.valueOf(entityMapping.getForceQuote())));
}
processMappingOverrides(entity, entityMapping);
} catch (ClassNotFoundException e) {
throw new IllegalStateException(String.format(
"unknown persistent entity name [%s]", entityClassName), e);
}
}
String entityClassName = entityMapping.getEntityClassName();
Class<?> entityClass;
try {
entityClass = ClassUtils.forName(entityClassName, beanClassLoader);
} catch (ClassNotFoundException e) {
throw new IllegalStateException(String.format("unknown persistent entity name [%s]", entityClassName), e);
}
CassandraPersistentEntity<?> entity = getPersistentEntity(entityClass);
if (entity == null) {
throw new IllegalStateException(String.format("unknown persistent entity class name [%s]", entityClassName));
}
String tableName = entityMapping.getTableName();
if (StringUtils.hasText(tableName)) {
entity.setTableName(cqlId(tableName, Boolean.valueOf(entityMapping.getForceQuote())));
}
processMappingOverrides(entity, entityMapping);
}
}
@@ -408,6 +398,7 @@ public class BasicCassandraMappingContext
/**
* @return Returns the verifier.
*/
@SuppressWarnings("unused")
public CassandraPersistentEntityMetadataVerifier getVerifier() {
return verifier;
}

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -40,12 +40,13 @@ import org.springframework.util.StringUtils;
/**
* Cassandra specific {@link BasicPersistentEntity} implementation that adds Cassandra specific metadata.
*
*
* @author Alex Shvid
* @author Matthew T. Adams
* @author John Blum
*/
public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T, CassandraPersistentProperty> implements
CassandraPersistentEntity<T>, ApplicationContextAware {
public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T, CassandraPersistentProperty>
implements CassandraPersistentEntity<T>, ApplicationContextAware {
protected static final CassandraPersistentEntityMetadataVerifier DEFAULT_VERIFIER = new BasicCassandraPersistentEntityMetadataVerifier();
@@ -63,7 +64,7 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
/**
* Creates a new {@link BasicCassandraPersistentEntity} with the given {@link TypeInformation}. Will default the table
* name to the entity's simple type name.
*
*
* @param typeInformation
*/
public BasicCassandraPersistentEntity(TypeInformation<T> typeInformation, CassandraMappingContext mappingContext) {
@@ -74,7 +75,7 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
/**
* Creates a new {@link BasicCassandraPersistentEntity} with the given {@link TypeInformation}. Will default the table
* name to the entity's simple type name.
*
*
* @param typeInformation
*/
public BasicCassandraPersistentEntity(TypeInformation<T> typeInformation, CassandraMappingContext mappingContext,
@@ -89,13 +90,14 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
protected CqlIdentifier determineTableName() {
Table anno = getType().getAnnotation(Table.class);
Table tableAnnotation = getType().getAnnotation(Table.class);
if (anno == null || !StringUtils.hasText(anno.value())) {
return cqlId(getType().getSimpleName(), anno == null ? false : anno.forceQuote());
if (tableAnnotation == null || !StringUtils.hasText(tableAnnotation.value())) {
return cqlId(getType().getSimpleName(), tableAnnotation != null && tableAnnotation.forceQuote());
}
return cqlId(spelContext == null ? anno.value() : SpelUtils.evaluate(anno.value(), spelContext), anno.forceQuote());
return cqlId(spelContext == null ? tableAnnotation.value()
: SpelUtils.evaluate(tableAnnotation.value(), spelContext), tableAnnotation.forceQuote());
}
@Override
@@ -111,7 +113,7 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
Assert.notNull(context);
Assert.notNull(context, "ApplicationContext must not be null");
this.context = context;
spelContext = new StandardEvaluationContext();
@@ -123,11 +125,9 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
@Override
public CqlIdentifier getTableName() {
if (tableName != null) {
return tableName;
}
tableName = (tableName != null ? tableName : determineTableName());
return tableName = determineTableName();
return tableName;
}
@Override
@@ -162,11 +162,11 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
@Override
public List<CassandraPersistentProperty> getCompositePrimaryKeyProperties() {
final List<CassandraPersistentProperty> properties = new ArrayList<CassandraPersistentProperty>();
List<CassandraPersistentProperty> properties = new ArrayList<CassandraPersistentProperty>();
if (!isCompositePrimaryKey()) {
throw new IllegalStateException(String.format("[%s] does not represent a composite primary key class", this
.getType().getName()));
throw new IllegalStateException(String.format("[%s] does not represent a composite primary key class",
this.getType().getName()));
}
addCompositePrimaryKeyProperties(this, properties);

View File

@@ -56,7 +56,11 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
implements CassandraPersistentProperty, ApplicationContextAware {
protected ApplicationContext context;
protected StandardEvaluationContext spelContext;
/**
* Whether this property has been explicitly instructed to force quote column names.
*/
protected Boolean forceQuote;
/**
* An unmodifiable list of this property's column names.
@@ -68,10 +72,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
*/
protected List<CqlIdentifier> explicitColumnNames;
/**
* Whether this property has been explicitly instructed to force quote column names.
*/
protected Boolean forceQuote;
protected StandardEvaluationContext spelContext;
/**
* Creates a new {@link BasicCassandraPersistentProperty}.
@@ -178,6 +179,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
if (isCollectionLike()) {
List<TypeInformation<?>> args = getTypeInformation().getTypeArguments();
ensureTypeArguments(args.size(), 1);
if (Set.class.isAssignableFrom(getType())) {
@@ -273,9 +275,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
@Override
public List<CqlIdentifier> getColumnNames() {
if (columnNames == null) {
columnNames = Collections.unmodifiableList(determineColumnNames());
}
columnNames = (columnNames != null ? columnNames : Collections.unmodifiableList(determineColumnNames()));
return columnNames;
}
@@ -319,7 +319,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
String name = defaultName;
if (StringUtils.hasText(overriddenName)) {
name = spelContext == null ? overriddenName : SpelUtils.evaluate(overriddenName, spelContext);
name = (spelContext == null ? overriddenName : SpelUtils.evaluate(overriddenName, spelContext));
}
return cqlId(name, forceQuote);
@@ -362,8 +362,8 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
columnNames.size()));
}
this.columnNames = this.explicitColumnNames = Collections
.unmodifiableList(new ArrayList<CqlIdentifier>(columnNames));
this.columnNames = this.explicitColumnNames =
Collections.unmodifiableList(new ArrayList<CqlIdentifier>(columnNames));
}
@Override
@@ -399,9 +399,11 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
@Override
public CassandraPersistentEntity<?> getCompositePrimaryKeyEntity() {
CassandraMappingContext mappingContext = getOwner().getMappingContext();
if (mappingContext == null) {
throw new IllegalStateException("need CassandraMappingContext");
throw new IllegalStateException("CassandraMappingContext needed");
}
return mappingContext.getPersistentEntity(getCompositePrimaryKeyTypeInformation());
}

View File

@@ -41,12 +41,17 @@ import com.datastax.driver.core.ResultSet;
*/
public class CassandraQueryMethod extends QueryMethod {
private final Method method;
private final CassandraMappingContext mappingContext;
private Query query;
private String queryString;
private boolean queryCached = false;
@SuppressWarnings("all")
private final CassandraMappingContext mappingContext;
private final Method method;
private Query query;
private String queryString;
/**
* Creates a new {@link CassandraQueryMethod} from the given {@link Method}.
*
@@ -60,7 +65,7 @@ public class CassandraQueryMethod extends QueryMethod {
super(method, metadata, factory);
Assert.notNull(mappingContext, "MappingContext must not be null!");
Assert.notNull(mappingContext, "MappingContext must not be null");
verify(method, metadata);
@@ -68,11 +73,15 @@ public class CassandraQueryMethod extends QueryMethod {
this.mappingContext = mappingContext;
}
/**
* Validates that this query is not a page or slice query.
*/
@SuppressWarnings("unused")
public void verify(Method method, RepositoryMetadata metadata) {
// TODO: support Page & Slice queries
if (isSliceQuery() || isPageQuery()) {
throw new InvalidDataAccessApiUsageException("Slice and Page queries are not supported.");
throw new InvalidDataAccessApiUsageException("Slice and Page queries are not supported");
}
}
@@ -92,6 +101,7 @@ public class CassandraQueryMethod extends QueryMethod {
query = AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
queryCached = true;
}
return query;
}
@@ -99,7 +109,7 @@ public class CassandraQueryMethod extends QueryMethod {
* Returns whether the method has an annotated query.
*/
public boolean hasAnnotatedQuery() {
return getAnnotatedQuery() != null;
return (getAnnotatedQuery() != null);
}
/**
@@ -110,7 +120,7 @@ public class CassandraQueryMethod extends QueryMethod {
if (!queryCached) {
queryString = (String) AnnotationUtils.getValue(getQueryAnnotation());
queryString = StringUtils.hasText(queryString) ? queryString : null;
queryString = (StringUtils.hasText(queryString) ? queryString : null);
}
return queryString;

View File

@@ -118,6 +118,7 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
}
DataType parameterType = getDataType(index);
if (parameterType == null) {
parameterType = cassandraConverter.getMappingContext().getDataType(getParameterType(index));
}
@@ -174,5 +175,4 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
delegate.remove();
}
}
}

View File

@@ -36,7 +36,8 @@ import com.datastax.driver.core.LocalDate;
*/
public class StringBasedCassandraQuery extends AbstractCassandraQuery {
@SuppressWarnings("unchecked") private static final Set<Class<?>> STRING_LIKE_PARAMETER_TYPES = new HashSet<Class<?>>(
@SuppressWarnings("unchecked")
private static final Set<Class<?>> STRING_LIKE_PARAMETER_TYPES = new HashSet<Class<?>>(
Arrays.asList(CharSequence.class, char.class, Character.class, char[].class));
private static final Pattern PLACEHOLDER = Pattern.compile("\\?(\\d+)");
@@ -99,14 +100,12 @@ public class StringBasedCassandraQuery extends AbstractCassandraQuery {
private boolean isStringLike(Object value) {
if (value == null) {
return false;
}
if (value != null) {
for (Class<?> type : STRING_LIKE_PARAMETER_TYPES) {
for (Class<?> type : STRING_LIKE_PARAMETER_TYPES) {
if (ClassUtils.isAssignableValue(type, value)) {
return true;
if (ClassUtils.isAssignableValue(type, value)) {
return true;
}
}
}

View File

@@ -417,6 +417,7 @@ public class MappingCassandraConverterUnitTests {
public void shouldReadDateCorrectly() {
LocalDate date = LocalDate.fromDaysSinceEpoch(1234);
when(rowMock.getDate(0)).thenReturn(date);
LocalDate result = mappingCassandraConverter.readRow(LocalDate.class, rowMock);
@@ -468,10 +469,11 @@ public class MappingCassandraConverterUnitTests {
typeWithLocalDate.localDate = now;
Insert insert = QueryBuilder.insertInto("table");
mappingCassandraConverter.write(typeWithLocalDate, insert);
assertThat(getValues(insert),
contains((Object) LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())));
assertThat(getValues(insert).contains(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())),
is(true));
}
/**
@@ -486,10 +488,11 @@ public class MappingCassandraConverterUnitTests {
typeWithLocalDate.localDate = now;
Update update = QueryBuilder.update("table");
mappingCassandraConverter.write(typeWithLocalDate, update);
assertThat(getAssignmentValues(update),
contains((Object) LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())));
assertThat(getAssignmentValues(update).contains(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())),
is(true));
}
/**
@@ -499,19 +502,18 @@ public class MappingCassandraConverterUnitTests {
public void shouldCreateInsertWithLocalDateListUsingCassandraDate() {
java.time.LocalDate now = java.time.LocalDate.now();
java.time.LocalDate localDate = java.time.LocalDate.of(2010, 7, 4);
TypeWithLocalDate typeWithLocalDate = new TypeWithLocalDate();
java.time.LocalDate localDate = java.time.LocalDate.of(2010, 7, 4);
typeWithLocalDate.list = Arrays.asList(now, localDate);
Insert insert = QueryBuilder.insertInto("table");
mappingCassandraConverter.write(typeWithLocalDate, insert);
List<Object> values = getValues(insert);
assertThat(values.get(0), is(instanceOf(List.class)));
List<LocalDate> dates = (List) values.get(0);
List<LocalDate> dates = getListValue(insert);
assertThat(dates, is(notNullValue(List.class)));
assertThat(dates, hasItem(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())));
assertThat(dates, hasItem(LocalDate.fromYearMonthDay(2010, 7, 4)));
}
@@ -523,19 +525,18 @@ public class MappingCassandraConverterUnitTests {
public void shouldCreateInsertWithLocalDateSetUsingCassandraDate() {
java.time.LocalDate now = java.time.LocalDate.now();
java.time.LocalDate localDate = java.time.LocalDate.of(2010, 7, 4);
TypeWithLocalDate typeWithLocalDate = new TypeWithLocalDate();
java.time.LocalDate localDate = java.time.LocalDate.of(2010, 7, 4);
typeWithLocalDate.set = new HashSet<java.time.LocalDate>(Arrays.asList(now, localDate));
Insert insert = QueryBuilder.insertInto("table");
mappingCassandraConverter.write(typeWithLocalDate, insert);
List<Object> values = getValues(insert);
assertThat(values.get(0), is(instanceOf(Set.class)));
Set<LocalDate> dates = (Set) values.get(0);
Set<LocalDate> dates = getSetValue(insert);
assertThat(dates, is(notNullValue(Set.class)));
assertThat(dates, hasItem(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())));
assertThat(dates, hasItem(LocalDate.fromYearMonthDay(2010, 7, 4)));
}
@@ -571,7 +572,7 @@ public class MappingCassandraConverterUnitTests {
mappingCassandraConverter.write(typeWithLocalDate, insert);
assertThat(getValues(insert), contains((Object) LocalDate.fromYearMonthDay(2010, 7, 4)));
assertThat(getValues(insert).contains(LocalDate.fromYearMonthDay(2010, 7, 4)), is(true));
}
/**
@@ -584,6 +585,7 @@ public class MappingCassandraConverterUnitTests {
typeWithLocalDate.localDate = java.time.LocalDate.of(2010, 7, 4);
Update update = QueryBuilder.update("table");
mappingCassandraConverter.write(typeWithLocalDate, update);
assertThat(getAssignmentValues(update), contains((Object) LocalDate.fromYearMonthDay(2010, 7, 4)));
@@ -650,8 +652,8 @@ public class MappingCassandraConverterUnitTests {
Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()),
column("localDate", LocalDate.fromYearMonthDay(2010, 7, 4), DataType.date()));
TypeWithJodaLocalDateMappedToDate result = mappingCassandraConverter
.readRow(TypeWithJodaLocalDateMappedToDate.class, rowMock);
TypeWithJodaLocalDateMappedToDate result =
mappingCassandraConverter.readRow(TypeWithJodaLocalDateMappedToDate.class, rowMock);
assertThat(result.localDate, is(notNullValue()));
assertThat(result.localDate.getYear(), is(2010));
@@ -669,9 +671,10 @@ public class MappingCassandraConverterUnitTests {
typeWithLocalDate.localDate = new org.joda.time.LocalDate(2010, 7, 4);
Insert insert = QueryBuilder.insertInto("table");
mappingCassandraConverter.write(typeWithLocalDate, insert);
assertThat(getValues(insert), contains((Object) LocalDate.fromYearMonthDay(2010, 7, 4)));
assertThat(getValues(insert).contains(LocalDate.fromYearMonthDay(2010, 7, 4)), is(true));
}
/**
@@ -684,6 +687,7 @@ public class MappingCassandraConverterUnitTests {
typeWithLocalDate.localDate = new org.joda.time.LocalDate(2010, 7, 4);
Update update = QueryBuilder.update("table");
mappingCassandraConverter.write(typeWithLocalDate, update);
assertThat(getAssignmentValues(update), contains((Object) LocalDate.fromYearMonthDay(2010, 7, 4)));
@@ -698,8 +702,8 @@ public class MappingCassandraConverterUnitTests {
Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()),
column("localDate", LocalDate.fromYearMonthDay(2010, 7, 4), DataType.date()));
TypeWithThreeTenBpLocalDateMappedToDate result = mappingCassandraConverter
.readRow(TypeWithThreeTenBpLocalDateMappedToDate.class, rowMock);
TypeWithThreeTenBpLocalDateMappedToDate result =
mappingCassandraConverter.readRow(TypeWithThreeTenBpLocalDateMappedToDate.class, rowMock);
assertThat(result.localDate, is(notNullValue()));
assertThat(result.localDate.getYear(), is(2010));
@@ -717,9 +721,10 @@ public class MappingCassandraConverterUnitTests {
typeWithLocalDate.localDate = org.threeten.bp.LocalDate.of(2010, 7, 4);
Insert insert = QueryBuilder.insertInto("table");
mappingCassandraConverter.write(typeWithLocalDate, insert);
assertThat(getValues(insert), contains((Object) LocalDate.fromYearMonthDay(2010, 7, 4)));
assertThat(getValues(insert).contains(LocalDate.fromYearMonthDay(2010, 7, 4)), is(true));
}
/**
@@ -737,6 +742,31 @@ public class MappingCassandraConverterUnitTests {
assertThat(getAssignmentValues(update), contains((Object) LocalDate.fromYearMonthDay(2010, 7, 4)));
}
@SuppressWarnings("unchecked")
private <T> List<T> getListValue(Insert statement) {
List<Object> values = getValues(statement);
for (Object value : values) {
if (value instanceof List) {
return (List<T>) value;
}
}
return null;
}
@SuppressWarnings("unchecked")
private <T> Set<T> getSetValue(Insert statement) {
List<Object> values = getValues(statement);
for (Object value : values) {
if (value instanceof Set) {
return (Set<T>) value;
}
}
return null;
}
@SuppressWarnings("unchecked")
private List<Object> getValues(Insert statement) {
@@ -875,7 +905,7 @@ public class MappingCassandraConverterUnitTests {
}
}
public static enum Condition {
public enum Condition {
MINT, USED;
}

View File

@@ -29,10 +29,8 @@ import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.cassandra.test.integration.mapping.types.CassandraTypeMappingIntegrationTest.Condition;
import org.threeten.bp.LocalDateTime;
import com.datastax.driver.core.DataType.Name;
import com.datastax.driver.core.LocalDate;
import lombok.Data;
import lombok.NoArgsConstructor;

View File

@@ -39,11 +39,11 @@ import org.springframework.data.util.ClassTypeInformation;
*/
public class MappingContextUnitTests {
BasicCassandraMappingContext ctx = new BasicCassandraMappingContext();
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
@Test(expected = MappingException.class)
public void testGetPersistentEntityOfTransientType() {
ctx.getPersistentEntity(Transient.class);
mappingContext.getPersistentEntity(Transient.class);
}
private static class Transient {}
@@ -51,11 +51,11 @@ public class MappingContextUnitTests {
@Test
public void testGetExistingPersistentEntityHappyPath() {
ctx.getPersistentEntity(X.class);
mappingContext.getPersistentEntity(X.class);
assertTrue(ctx.contains(X.class));
assertNotNull(ctx.getExistingPersistentEntity(X.class));
assertFalse(ctx.contains(Y.class));
assertTrue(mappingContext.contains(X.class));
assertNotNull(mappingContext.getExistingPersistentEntity(X.class));
assertFalse(mappingContext.contains(Y.class));
}
@Table
@@ -74,12 +74,14 @@ public class MappingContextUnitTests {
@Test
public void primaryKeyOnPropertyShouldWork() {
CassandraPersistentEntity<?> persistentEntity = ctx.getPersistentEntity(PrimaryKeyOnProperty.class);
CassandraPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(PrimaryKeyOnProperty.class);
CassandraPersistentProperty idProperty = persistentEntity.getIdProperty();
assertThat(idProperty.getColumnName().toCql(), is(equalTo("foo")));
List<CqlIdentifier> columnNames = idProperty.getColumnNames();
assertThat(columnNames, hasSize(1));
assertThat(columnNames.get(0).toCql(), is(equalTo("foo")));
}
@@ -105,17 +107,19 @@ public class MappingContextUnitTests {
@Test
public void primaryKeyColumnsOnPropertyShouldWork() {
CassandraPersistentEntity<?> persistentEntity = ctx.getPersistentEntity(PrimaryKeyColumnsOnProperty.class);
CassandraPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(PrimaryKeyColumnsOnProperty.class);
assertThat(persistentEntity.isCompositePrimaryKey(), is(false));
CassandraPersistentProperty firstname = persistentEntity.getPersistentProperty("firstname");
assertThat(firstname.isCompositePrimaryKey(), is(false));
assertThat(firstname.isPrimaryKeyColumn(), is(true));
assertThat(firstname.isPartitionKeyColumn(), is(true));
assertThat(firstname.getColumnName().toCql(), is(equalTo("firstname")));
CassandraPersistentProperty lastname = persistentEntity.getPersistentProperty("lastname");
assertThat(lastname.isPrimaryKeyColumn(), is(true));
assertThat(lastname.isClusterKeyColumn(), is(true));
assertThat(lastname.getColumnName().toCql(), is(equalTo("mylastname")));
@@ -152,10 +156,11 @@ public class MappingContextUnitTests {
@Test
public void primaryKeyClassWithprimaryKeyColumnsOnPropertyShouldWork() {
CassandraPersistentEntity<?> persistentEntity = ctx
.getPersistentEntity(PrimaryKeyOnPropertyWithPrimaryKeyClass.class);
CassandraPersistentEntity<?> primaryKeyClass = ctx
.getPersistentEntity(CompositePrimaryKeyClassWithProperties.class);
CassandraPersistentEntity<?> persistentEntity =
mappingContext.getPersistentEntity(PrimaryKeyOnPropertyWithPrimaryKeyClass.class);
CassandraPersistentEntity<?> primaryKeyClass =
mappingContext.getPersistentEntity(CompositePrimaryKeyClassWithProperties.class);
assertThat(persistentEntity.isCompositePrimaryKey(), is(false));
assertThat(persistentEntity.getPersistentProperty("key").isCompositePrimaryKey(), is(true));
@@ -164,12 +169,14 @@ public class MappingContextUnitTests {
assertThat(primaryKeyClass.getCompositePrimaryKeyProperties(), hasSize(2));
CassandraPersistentProperty firstname = primaryKeyClass.getPersistentProperty("firstname");
assertThat(firstname.isPrimaryKeyColumn(), is(true));
assertThat(firstname.isPartitionKeyColumn(), is(true));
assertThat(firstname.isClusterKeyColumn(), is(false));
assertThat(firstname.getColumnName().toCql(), is(equalTo("firstname")));
CassandraPersistentProperty lastname = primaryKeyClass.getPersistentProperty("lastname");
assertThat(lastname.isPrimaryKeyColumn(), is(true));
assertThat(lastname.isPartitionKeyColumn(), is(false));
assertThat(lastname.isClusterKeyColumn(), is(true));
@@ -222,8 +229,8 @@ public class MappingContextUnitTests {
@Test
public void shouldCreatePersistentEntityIfNoConversionRegistered() {
ctx.setCustomConversions(new CustomConversions(Collections.EMPTY_LIST));
assertThat(ctx.shouldCreatePersistentEntityFor(ClassTypeInformation.from(Human.class)), is(true));
mappingContext.setCustomConversions(new CustomConversions(Collections.EMPTY_LIST));
assertThat(mappingContext.shouldCreatePersistentEntityFor(ClassTypeInformation.from(Human.class)), is(true));
}
/**
@@ -233,13 +240,12 @@ public class MappingContextUnitTests {
public void shouldNotCreateEntitiesForCustomConvertedTypes() {
List<?> converters = Arrays.asList(new HumanToStringConverter());
ctx.setCustomConversions(new CustomConversions(converters));
mappingContext.setCustomConversions(new CustomConversions(converters));
assertThat(ctx.shouldCreatePersistentEntityFor(ClassTypeInformation.from(Human.class)), is(false));
assertThat(mappingContext.shouldCreatePersistentEntityFor(ClassTypeInformation.from(Human.class)), is(false));
}
private static class Human {
}
private static class HumanToStringConverter implements Converter<Human, String> {

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.data.cassandra.repository.isolated;
import static java.time.Instant.*;
import static java.time.ZoneId.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
@@ -25,7 +23,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
@@ -119,7 +117,8 @@ public class RepositoryQueryMethodParameterTypesIntegrationTests
@Test
public void shouldFindByAnnotatedDateParameter() {
CustomConversions customConversions = new CustomConversions(Arrays.asList(new DateToLocalDateConverter()));
CustomConversions customConversions = new CustomConversions(
Collections.singletonList(new DateToLocalDateConverter()));
mappingContext.setCustomConversions(customConversions);
converter.setCustomConversions(customConversions);
@@ -223,10 +222,10 @@ public class RepositoryQueryMethodParameterTypesIntegrationTests
@Override
public com.datastax.driver.core.LocalDate convert(Date source) {
LocalDate localDate = LocalDateTime.ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalDate();
LocalDate localDate = LocalDateTime.ofInstant(source.toInstant(), ZoneOffset.UTC.normalized()).toLocalDate();
return com.datastax.driver.core.LocalDate.fromYearMonthDay(localDate.getYear(), localDate.getMonthValue(),
localDate.getDayOfMonth());
}
}
}

View File

@@ -56,15 +56,18 @@ public class SchemaActionIntegrationTests extends AbstractEmbeddedCassandraInteg
protected static final String KEYSPACE_NAME = SchemaActionIntegrationTests.class.getSimpleName().toLowerCase();
protected static final String PERSON_TABLE_DEFINITION_CQL = String
.format("CREATE TABLE %s.person (id int, firstName text, lastName text, PRIMARY KEY(id));", KEYSPACE_NAME);
protected static final String PERSON_TABLE_DEFINITION_CQL = String.format(
"CREATE TABLE %s.person (id int, firstName text, lastName text, PRIMARY KEY(id));", KEYSPACE_NAME);
@Rule public ExpectedException exception = ExpectedException.none();
@Rule
public ExpectedException exception = ExpectedException.none();
@Rule public KeyspaceRule KEYSPACE_RULE = new KeyspaceRule(cassandraEnvironment, KEYSPACE_NAME);
@Rule
public KeyspaceRule KEYSPACE_RULE = new KeyspaceRule(cassandraEnvironment, KEYSPACE_NAME);
protected ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(annotatedClasses);
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(annotatedClasses);
applicationContext.registerShutdownHook();