diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/AbstractCassandraConfiguration.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/AbstractCassandraConfiguration.java index 16f36bcae..4e847faf0 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/AbstractCassandraConfiguration.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/AbstractCassandraConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.data.cassandra.config; import java.util.Collections; +import java.util.Optional; import java.util.Set; import org.springframework.beans.factory.BeanClassLoaderAware; @@ -64,9 +65,12 @@ public abstract class AbstractCassandraConfiguration extends AbstractClusterConf protected Session getRequiredSession() { CassandraSessionFactoryBean factoryBean = session(); - Assert.state(factoryBean.getObject() != null, "Session factory not initialized"); - return factoryBean.getObject(); + Session session = factoryBean.getObject(); + + Assert.state(session != null, "Session factory not initialized"); + + return session; } /** @@ -126,8 +130,8 @@ public abstract class AbstractCassandraConfiguration extends AbstractClusterConf mappingCassandraConverter.setCustomConversions(customConversions()); return mappingCassandraConverter; - } catch (ClassNotFoundException e) { - throw new IllegalStateException(e); + } catch (ClassNotFoundException cause) { + throw new IllegalStateException(cause); } } @@ -146,9 +150,7 @@ public abstract class AbstractCassandraConfiguration extends AbstractClusterConf CassandraMappingContext mappingContext = new CassandraMappingContext( new SimpleUserTypeResolver(cluster, getKeyspaceName()), new SimpleTupleTypeFactory(cluster)); - if (beanClassLoader != null) { - mappingContext.setBeanClassLoader(beanClassLoader); - } + Optional.ofNullable(this.beanClassLoader).ifPresent(mappingContext::setBeanClassLoader); mappingContext.setInitialEntitySet(getInitialEntitySet()); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/AbstractCassandraConverter.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/AbstractCassandraConverter.java index 909de9f92..577045ca5 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/AbstractCassandraConverter.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/AbstractCassandraConverter.java @@ -17,6 +17,8 @@ package org.springframework.data.cassandra.core.convert; import java.util.Collections; +import lombok.NonNull; + import org.springframework.beans.factory.InitializingBean; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.GenericConversionService; @@ -64,6 +66,12 @@ public abstract class AbstractCassandraConverter implements CassandraConverter, this.instantiators = instantiators; } + @NonNull + @Override + public ConversionService getConversionService() { + return this.conversionService; + } + /** * Registers the given custom conversions with the converter. */ @@ -76,7 +84,7 @@ public abstract class AbstractCassandraConverter implements CassandraConverter, */ @Override public CustomConversions getCustomConversions() { - return conversions; + return this.conversions; } /* (non-Javadoc) @@ -93,13 +101,10 @@ public abstract class AbstractCassandraConverter implements CassandraConverter, */ private void initializeConverters() { + ConversionService conversionService = getConversionService(); + if (conversionService instanceof GenericConversionService) { - conversions.registerConvertersIn((GenericConversionService) conversionService); + getCustomConversions().registerConvertersIn((GenericConversionService) conversionService); } } - - @Override - public ConversionService getConversionService() { - return conversionService; - } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/BasicCassandraRowValueProvider.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/BasicCassandraRowValueProvider.java index 3a4449aa2..235a4433b 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/BasicCassandraRowValueProvider.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/BasicCassandraRowValueProvider.java @@ -75,11 +75,10 @@ public class BasicCassandraRowValueProvider implements CassandraRowValueProvider public T getPropertyValue(CassandraPersistentProperty property) { String spelExpression = property.getSpelExpression(); - if (spelExpression != null) { - return evaluator.evaluate(spelExpression); - } - return (T) reader.get(property.getRequiredColumnName()); + return spelExpression != null + ? this.evaluator.evaluate(spelExpression) + : (T) this.reader.get(property.getRequiredColumnName()); } /* (non-Javadoc) @@ -87,7 +86,7 @@ public class BasicCassandraRowValueProvider implements CassandraRowValueProvider */ @Override public Row getRow() { - return reader.getRow(); + return this.reader.getRow(); } /* (non-Javadoc) diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraTupleValueProvider.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraTupleValueProvider.java index 5d3d68c00..66e93b83b 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraTupleValueProvider.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraTupleValueProvider.java @@ -32,12 +32,12 @@ import com.datastax.driver.core.TupleValue; */ public class CassandraTupleValueProvider implements CassandraValueProvider { - private final TupleValue tupleValue; - private final CodecRegistry codecRegistry; private final SpELExpressionEvaluator evaluator; + private final TupleValue tupleValue; + /** * Create a new {@link CassandraTupleValueProvider} with the given {@link TupleValue} and * {@link SpELExpressionEvaluator}. @@ -58,14 +58,6 @@ public class CassandraTupleValueProvider implements CassandraValueProvider { this.evaluator = evaluator; } - /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.convert.CassandraValueProvider#hasProperty(org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty) - */ - @Override - public boolean hasProperty(CassandraPersistentProperty property) { - return tupleValue.getType().getComponentTypes().size() >= property.getRequiredOrdinal(); - } - /* (non-Javadoc) * @see org.springframework.data.mapping.model.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty) */ @@ -74,6 +66,7 @@ public class CassandraTupleValueProvider implements CassandraValueProvider { public T getPropertyValue(CassandraPersistentProperty property) { String spelExpression = property.getSpelExpression(); + if (spelExpression != null) { return evaluator.evaluate(spelExpression); } @@ -83,4 +76,12 @@ public class CassandraTupleValueProvider implements CassandraValueProvider { return tupleValue.get(ordinal, codecRegistry.codecFor(elementType)); } + + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.convert.CassandraValueProvider#hasProperty(org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty) + */ + @Override + public boolean hasProperty(CassandraPersistentProperty property) { + return this.tupleValue.getType().getComponentTypes().size() >= property.getRequiredOrdinal(); + } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraUDTValueProvider.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraUDTValueProvider.java index f06b305a9..777ad687c 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraUDTValueProvider.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraUDTValueProvider.java @@ -71,6 +71,7 @@ public class CassandraUDTValueProvider implements CassandraValueProvider { @Deprecated public CassandraUDTValueProvider(UDTValue udtValue, CodecRegistry codecRegistry, DefaultSpELExpressionEvaluator evaluator) { + this(udtValue, codecRegistry, (SpELExpressionEvaluator) evaluator); } @@ -82,14 +83,15 @@ public class CassandraUDTValueProvider implements CassandraValueProvider { public T getPropertyValue(CassandraPersistentProperty property) { String spelExpression = property.getSpelExpression(); + if (spelExpression != null) { - return evaluator.evaluate(spelExpression); + return this.evaluator.evaluate(spelExpression); } String name = property.getRequiredColumnName().toCql(); - DataType fieldType = udtValue.getType().getFieldType(name); + DataType fieldType = this.udtValue.getType().getFieldType(name); - return udtValue.get(name, codecRegistry.codecFor(fieldType)); + return this.udtValue.get(name, this.codecRegistry.codecFor(fieldType)); } /* (non-Javadoc) @@ -97,6 +99,6 @@ public class CassandraUDTValueProvider implements CassandraValueProvider { */ @Override public boolean hasProperty(CassandraPersistentProperty property) { - return udtValue.getType().contains(property.getRequiredColumnName().toCql()); + return this.udtValue.getType().contains(property.getRequiredColumnName().toCql()); } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java index 892ab9a36..2e6706fcf 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java @@ -15,8 +15,6 @@ */ package org.springframework.data.cassandra.core.convert; -import lombok.AllArgsConstructor; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -25,13 +23,14 @@ import java.util.Map; import java.util.Map.Entry; import java.util.function.Function; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.AllArgsConstructor; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.CollectionFactory; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentEntity; @@ -58,6 +57,9 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.datastax.driver.core.CodecRegistry; import com.datastax.driver.core.DataType; import com.datastax.driver.core.Row; @@ -85,7 +87,7 @@ import com.datastax.driver.core.querybuilder.Update; * @author John Blum */ public class MappingCassandraConverter extends AbstractCassandraConverter - implements CassandraConverter, ApplicationContextAware, BeanClassLoaderAware { + implements ApplicationContextAware, BeanClassLoaderAware { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -95,11 +97,24 @@ public class MappingCassandraConverter extends AbstractCassandraConverter private SpELContext spELContext; + private static ConversionService newConversionService() { + return new DefaultConversionService(); + } + + private static CassandraMappingContext newDefaultMappingContext() { + + CassandraMappingContext mappingContext = new CassandraMappingContext(); + + mappingContext.setCustomConversions(new CassandraCustomConversions(Collections.emptyList())); + + return mappingContext; + } + /** * Create a new {@link MappingCassandraConverter} with a {@link CassandraMappingContext}. */ public MappingCassandraConverter() { - this(createMappingContext()); + this(newDefaultMappingContext()); } /** @@ -109,7 +124,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter */ public MappingCassandraConverter(CassandraMappingContext mappingContext) { - super(new DefaultConversionService()); + super(newConversionService()); Assert.notNull(mappingContext, "CassandraMappingContext must not be null"); @@ -117,15 +132,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE); } - private static CassandraMappingContext createMappingContext() { - - CassandraMappingContext mappingContext = new CassandraMappingContext(); - - mappingContext.setCustomConversions(new CassandraCustomConversions(Collections.emptyList())); - - return mappingContext; - } - /* (non-Javadoc) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ @@ -142,6 +148,14 @@ public class MappingCassandraConverter extends AbstractCassandraConverter this.beanClassLoader = classLoader; } + private TypeCodec getCodec(CassandraPersistentProperty property) { + return getCodecRegistry().codecFor(getMappingContext().getDataType(property)); + } + + private CodecRegistry getCodecRegistry() { + return CodecRegistry.DEFAULT_INSTANCE; + } + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.convert.CassandraConverter#getMappingContext() */ @@ -151,7 +165,56 @@ public class MappingCassandraConverter extends AbstractCassandraConverter } /** - * Read a {@link Row} into the requested target {@code type}. + * Create a new {@link ConvertingPropertyAccessor} for the given {@link Object source} + * and {@link CassandraPersistentEntity entity}. + * + * @param source {@link Object} containing the property values to access; must not be {@literal null}. + * @param entity {@link CassandraPersistentEntity} for the source; must not be {@literal null}. + * @return a new {@link ConvertingPropertyAccessor} for the given {@link Object source} + * and {@link CassandraPersistentEntity entity}. + * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity + */ + private ConvertingPropertyAccessor newConvertingPropertyAccessor(Object source, + CassandraPersistentEntity entity) { + + PersistentPropertyAccessor propertyAccessor = source instanceof PersistentPropertyAccessor + ? (PersistentPropertyAccessor) source : entity.getPropertyAccessor(source); + + return new ConvertingPropertyAccessor(propertyAccessor, getConversionService()); + } + + private PersistentEntityParameterValueProvider newParameterValueProvider( + CassandraPersistentEntity entity, CassandraValueProvider valueProvider) { + + return new PersistentEntityParameterValueProvider<>(entity, + new MappingAndConvertingValueProvider(valueProvider), null); + } + + @SuppressWarnings("unchecked") + private Class transformClassToBeanClassLoaderClass(Class entity) { + + try { + return (Class) ClassUtils.forName(entity.getName(), this.beanClassLoader); + } catch (ClassNotFoundException | LinkageError ignore) { + return entity; + } + } + + /* (non-Javadoc) + * @see org.springframework.data.convert.EntityReader#read(java.lang.Class, S) + */ + @Override + public R read(Class type, Object row) { + + if (row instanceof Row) { + return readRow(type, (Row) row); + } + + throw new MappingException(String.format("Unknown row object [%s]", ObjectUtils.nullSafeClassName(row))); + } + + /** + * Read a {@link Row} into the requested target {@link Class type}. * * @param type must not be {@literal null}. * @param row must not be {@literal null}. @@ -178,69 +241,59 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return getConversionService().convert(row, type); } - CassandraPersistentEntity persistentEntity = (CassandraPersistentEntity) getMappingContext() - .getRequiredPersistentEntity(typeInfo); + CassandraPersistentEntity persistentEntity = + (CassandraPersistentEntity) getMappingContext().getRequiredPersistentEntity(typeInfo); return readEntityFromRow(persistentEntity, row); } - protected S readEntityFromRow(CassandraPersistentEntity entity, Row row) { + private S readEntityFromRow(CassandraPersistentEntity entity, Row row) { return doRead(entity, row, expressionEvaluator -> new BasicCassandraRowValueProvider(row, expressionEvaluator)); } - protected S readEntityFromUdt(CassandraPersistentEntity entity, UDTValue udtValue) { + private S readEntityFromTuple(CassandraPersistentEntity entity, TupleValue tupleValue) { + + return doRead(entity, tupleValue, + expressionEvaluator -> new CassandraTupleValueProvider(tupleValue, getCodecRegistry(), expressionEvaluator)); + } + + private S readEntityFromUdt(CassandraPersistentEntity entity, UDTValue udtValue) { + return doRead(entity, udtValue, expressionEvaluator -> new CassandraUDTValueProvider(udtValue, getCodecRegistry(), expressionEvaluator)); } - protected S readEntityFromTuple(CassandraPersistentEntity entity, TupleValue tupleValue) { - return doRead(entity, tupleValue, - expressionEvaluator -> new CassandraTupleValueProvider(tupleValue, getCodecRegistry(), expressionEvaluator)); - } - - protected S doRead(CassandraPersistentEntity entity, V value, + private S doRead(CassandraPersistentEntity entity, V value, Function valueProviderSupplier) { - DefaultSpELExpressionEvaluator expressionEvaluator = new DefaultSpELExpressionEvaluator(value, spELContext); + SpELExpressionEvaluator expressionEvaluator = new DefaultSpELExpressionEvaluator(value, this.spELContext); CassandraValueProvider valueProvider = valueProviderSupplier.apply(expressionEvaluator); - PersistentEntityParameterValueProvider parameterValueProvider = getParameterValueProvider( - entity, valueProvider); + PersistentEntityParameterValueProvider parameterValueProvider = + newParameterValueProvider(entity, valueProvider); - EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity); + EntityInstantiator instantiator = this.instantiators.getInstantiatorFor(entity); S instance = instantiator.createInstance(entity, parameterValueProvider); - readProperties(entity, valueProvider, getConvertingAccessor(instance, entity)); + readProperties(entity, valueProvider, newConvertingPropertyAccessor(instance, entity)); return instance; } - private PersistentEntityParameterValueProvider getParameterValueProvider( - CassandraPersistentEntity entity, CassandraValueProvider valueProvider) { - - return new PersistentEntityParameterValueProvider<>(entity, new MappingAndConvertingValueProvider(valueProvider), - null); - } - - protected void readPropertiesFromRow(CassandraPersistentEntity entity, CassandraRowValueProvider row, - PersistentPropertyAccessor propertyAccessor) { - readProperties(entity, row, propertyAccessor); - } - - protected void readProperties(CassandraPersistentEntity entity, CassandraValueProvider valueProvider, + private void readProperties(CassandraPersistentEntity entity, CassandraValueProvider valueProvider, PersistentPropertyAccessor propertyAccessor) { for (CassandraPersistentProperty property : entity) { - MappingCassandraConverter.this.readProperty(entity, property, valueProvider, propertyAccessor); + readProperty(entity, property, valueProvider, propertyAccessor); } } - protected void readProperty(CassandraPersistentEntity entity, CassandraPersistentProperty property, + private void readProperty(CassandraPersistentEntity entity, CassandraPersistentProperty property, CassandraValueProvider valueProvider, PersistentPropertyAccessor propertyAccessor) { - // if true then skip; property was set in constructor + // if true then skip; property was set in the constructor if (entity.isConstructorArgument(property)) { return; } @@ -256,7 +309,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter } // now recurse on using the key this time - readProperties(keyEntity, valueProvider, getConvertingAccessor(key, keyEntity)); + readProperties(keyEntity, valueProvider, newConvertingPropertyAccessor(key, keyEntity)); // now that the key's properties have been populated, set the key property on the entity propertyAccessor.setProperty(property, key); @@ -271,24 +324,11 @@ public class MappingCassandraConverter extends AbstractCassandraConverter propertyAccessor.setProperty(property, getReadValue(valueProvider, property)); } - protected Object instantiatePrimaryKey(CassandraPersistentEntity entity, CassandraPersistentProperty keyProperty, + private Object instantiatePrimaryKey(CassandraPersistentEntity entity, CassandraPersistentProperty keyProperty, CassandraValueProvider propertyProvider) { return this.instantiators.getInstantiatorFor(entity).createInstance(entity, - getParameterValueProvider(entity, propertyProvider)); - } - - /* (non-Javadoc) - * @see org.springframework.data.convert.EntityReader#read(java.lang.Class, S) - */ - @Override - public R read(Class type, Object row) { - - if (row instanceof Row) { - return readRow(type, (Row) row); - } - - throw new MappingException("Unknown row object " + ObjectUtils.nullSafeClassName(row)); + newParameterValueProvider(entity, propertyProvider)); } /* (non-Javadoc) @@ -324,16 +364,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter write(source, sink, entity); } - @SuppressWarnings("unchecked") - private Class transformClassToBeanClassLoaderClass(Class entity) { - - try { - return (Class) ClassUtils.forName(entity.getName(), this.beanClassLoader); - } catch (ClassNotFoundException | LinkageError ignore) { - return entity; - } - } - @Override @SuppressWarnings("unchecked") public void write(Object source, Object sink, CassandraPersistentEntity entity) { @@ -345,65 +375,21 @@ public class MappingCassandraConverter extends AbstractCassandraConverter } if (sink instanceof Map) { - writeMapFromWrapper(getConvertingAccessor(source, entity), (Map) sink, entity); + writeMapFromWrapper(newConvertingPropertyAccessor(source, entity), (Map) sink, entity); } else if (sink instanceof Insert) { - writeInsertFromObject(source, (Insert) sink, entity); + writeInsertFromWrapper(newConvertingPropertyAccessor(source, entity), (Insert) sink, entity); } else if (sink instanceof Update) { - writeUpdateFromObject(source, (Update) sink, entity); + writeUpdateFromWrapper(newConvertingPropertyAccessor(source, entity), (Update) sink, entity); } else if (sink instanceof Select.Where) { writeSelectWhereFromObject(source, (Select.Where) sink, entity); } else if (sink instanceof Delete.Where) { writeDeleteWhereFromObject(source, (Delete.Where) sink, entity); - } else if (sink instanceof UDTValue) { - writeUDTValue(getConvertingAccessor(source, entity), (UDTValue) sink, entity); } else if (sink instanceof TupleValue) { - writeTupleValue(getConvertingAccessor(source, entity), (TupleValue) sink, entity); + writeTupleValue(newConvertingPropertyAccessor(source, entity), (TupleValue) sink, entity); + } else if (sink instanceof UDTValue) { + writeUDTValue(newConvertingPropertyAccessor(source, entity), (UDTValue) sink, entity); } else { - throw new MappingException("Unknown write target " + sink.getClass().getName()); - } - } - - private void writeInsertFromObject(Object object, Insert insert, CassandraPersistentEntity entity) { - writeInsertFromWrapper(getConvertingAccessor(object, entity), insert, entity); - } - - protected void writeInsertFromWrapper(ConvertingPropertyAccessor accessor, Insert insert, - CassandraPersistentEntity entity) { - - for (CassandraPersistentProperty property : entity) { - - Object value = getWriteValue(property, accessor); - - if (log.isDebugEnabled()) { - log.debug("doWithProperties Property.type {}, Property.value {}", property.getType().getName(), value); - } - - if (property.isCompositePrimaryKey()) { - - if (log.isDebugEnabled()) { - log.debug("Property is a compositeKey"); - } - - if (value == null) { - continue; - } - - CassandraPersistentEntity compositePrimaryKey = getMappingContext().getRequiredPersistentEntity(property); - - writeInsertFromWrapper(getConvertingAccessor(value, compositePrimaryKey), insert, compositePrimaryKey); - - continue; - } - - if (value == null) { - continue; - } - - if (log.isDebugEnabled()) { - log.debug("Adding insert.value [{}] - [{}]", property.getRequiredColumnName().toCql(), value); - } - - insert.value(property.getRequiredColumnName().toCql(), value); + throw new MappingException(String.format("Unknown write target [%s]", ObjectUtils.nullSafeClassName(sink))); } } @@ -430,7 +416,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter CassandraPersistentEntity compositePrimaryKey = getMappingContext().getRequiredPersistentEntity(property); - writeMapFromWrapper(getConvertingAccessor(value, compositePrimaryKey), insert, compositePrimaryKey); + writeMapFromWrapper(newConvertingPropertyAccessor(value, compositePrimaryKey), insert, compositePrimaryKey); continue; } @@ -443,16 +429,52 @@ public class MappingCassandraConverter extends AbstractCassandraConverter } } - protected void writeUpdateFromObject(Object object, Update update, CassandraPersistentEntity entity) { - writeUpdateFromWrapper(getConvertingAccessor(object, entity), update, entity); - } - - protected void writeUpdateFromWrapper(ConvertingPropertyAccessor accessor, Update update, + private void writeInsertFromWrapper(ConvertingPropertyAccessor propertyAccessor, Insert insert, CassandraPersistentEntity entity) { for (CassandraPersistentProperty property : entity) { - Object value = getWriteValue(property, accessor); + Object value = getWriteValue(property, propertyAccessor); + + if (log.isDebugEnabled()) { + log.debug("doWithProperties Property.type {}, Property.value {}", property.getType().getName(), value); + } + + if (property.isCompositePrimaryKey()) { + + if (log.isDebugEnabled()) { + log.debug("Property is a compositeKey"); + } + + if (value == null) { + continue; + } + + CassandraPersistentEntity compositePrimaryKey = getMappingContext().getRequiredPersistentEntity(property); + + writeInsertFromWrapper(newConvertingPropertyAccessor(value, compositePrimaryKey), insert, compositePrimaryKey); + + continue; + } + + if (value == null) { + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Adding insert.value [{}] - [{}]", property.getRequiredColumnName().toCql(), value); + } + + insert.value(property.getRequiredColumnName().toCql(), value); + } + } + + private void writeUpdateFromWrapper(ConvertingPropertyAccessor propertyAccessor, Update update, + CassandraPersistentEntity entity) { + + for (CassandraPersistentProperty property : entity) { + + Object value = getWriteValue(property, propertyAccessor); if (property.isCompositePrimaryKey()) { @@ -462,7 +484,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter continue; } - writeUpdateFromWrapper(getConvertingAccessor(value, compositePrimaryKey), update, compositePrimaryKey); + writeUpdateFromWrapper(newConvertingPropertyAccessor(value, compositePrimaryKey), update, compositePrimaryKey); continue; } @@ -475,55 +497,36 @@ public class MappingCassandraConverter extends AbstractCassandraConverter } } - protected void writeSelectWhereFromObject(Object object, Select.Where where, CassandraPersistentEntity entity) { + /** + * Returns whether the property is part of the primary key. + * + * @param property {@link CassandraPersistentProperty} to evaluate. + * @return a boolean value indicating whether the given property is party of a primary key. + */ + private boolean isPrimaryKeyPart(CassandraPersistentProperty property) { + return property.isCompositePrimaryKey() || property.isPrimaryKeyColumn() || property.isIdProperty(); + } + + private void writeSelectWhereFromObject(Object object, Select.Where where, CassandraPersistentEntity entity) { getWhereClauses(object, entity).forEach(where::and); } - protected void writeDeleteWhereFromObject(Object object, Delete.Where where, CassandraPersistentEntity entity) { + private void writeDeleteWhereFromObject(Object object, Delete.Where where, CassandraPersistentEntity entity) { getWhereClauses(object, entity).forEach(where::and); } - protected void writeUDTValue(ConvertingPropertyAccessor accessor, UDTValue udtValue, - CassandraPersistentEntity entity) { + @Nullable + private Object extractId(Object source, CassandraPersistentEntity entity) { - for (CassandraPersistentProperty property : entity) { - - Object value = getWriteValue(property, accessor); - - if (log.isDebugEnabled()) { - log.debug("writeUDTValueWhereFromObject Property.type {}, Property.value {}", property.getType().getName(), - value); - } - - if (log.isDebugEnabled()) { - log.debug("Adding udt.value [{}] - [{}]", property.getRequiredColumnName().toCql(), value); - } - - TypeCodec typeCodec = getCodecRegistry().codecFor(getMappingContext().getDataType(property)); - - udtValue.set(property.getRequiredColumnName().toCql(), value, typeCodec); + if (ClassUtils.isAssignableValue(entity.getType(), source)) { + return getId(source, entity); + } else if (source instanceof MapId) { + return source; + } else if (source instanceof MapIdentifiable) { + return ((MapIdentifiable) source).getMapId(); } - } - protected void writeTupleValue(ConvertingPropertyAccessor accessor, TupleValue tupleValue, - CassandraPersistentEntity entity) { - - for (CassandraPersistentProperty property : entity) { - - Object value = getWriteValue(property, accessor); - - if (log.isDebugEnabled()) { - log.debug("writeTupleValue Property.type {}, Property.value {}", property.getType().getName(), value); - } - - if (log.isDebugEnabled()) { - log.debug("Adding tuple value [{}] - [{}]", property.getOrdinal(), value); - } - - TypeCodec typeCodec = getCodecRegistry().codecFor(mappingContext.getDataType(property)); - - tupleValue.set(property.getRequiredOrdinal(), value, typeCodec); - } + return source; } private Collection getWhereClauses(Object source, CassandraPersistentEntity entity) { @@ -544,64 +547,34 @@ public class MappingCassandraConverter extends AbstractCassandraConverter if (id instanceof MapId) { CassandraPersistentEntity whereEntity = compositeIdProperty != null - ? getMappingContext().getRequiredPersistentEntity(compositeIdProperty) - : entity; + ? getMappingContext().getRequiredPersistentEntity(compositeIdProperty) + : entity; return getWhereClauses(MapId.class.cast(id), whereEntity); } if (idProperty == null) { throw new InvalidDataAccessApiUsageException( - String.format("Cannot obtain where clauses for entity [%s] using [%s]", entity.getName(), source)); + String.format("Cannot obtain where clauses for entity [%s] using [%s]", entity.getName(), source)); } if (compositeIdProperty != null) { if (!ClassUtils.isAssignableValue(compositeIdProperty.getType(), id)) { throw new InvalidDataAccessApiUsageException( - String.format("Cannot use [%s] as composite Id for [%s]", id, entity.getName())); + String.format("Cannot use [%s] as composite Id for [%s]", id, entity.getName())); } - CassandraPersistentEntity compositePrimaryKey = getMappingContext() - .getRequiredPersistentEntity(compositeIdProperty); + CassandraPersistentEntity compositePrimaryKey = + getMappingContext().getRequiredPersistentEntity(compositeIdProperty); - return getWhereClauses(getConvertingAccessor(id, compositePrimaryKey), compositePrimaryKey); + return getWhereClauses(newConvertingPropertyAccessor(id, compositePrimaryKey), compositePrimaryKey); } Class targetType = getTargetType(idProperty); return Collections.singleton(QueryBuilder.eq(idProperty.getRequiredColumnName().toCql(), - getPotentiallyConvertedSimpleValue(id, targetType))); - } - - @Nullable - private Object extractId(Object source, CassandraPersistentEntity entity) { - - if (ClassUtils.isAssignableValue(entity.getType(), source)) { - return getId(source, entity); - } else if (source instanceof MapId) { - return source; - } else if (source instanceof MapIdentifiable) { - return ((MapIdentifiable) source).getMapId(); - } - - return source; - } - - private Collection getWhereClauses(ConvertingPropertyAccessor accessor, CassandraPersistentEntity entity) { - - Assert.isTrue(entity.isCompositePrimaryKey(), - String.format("Entity [%s] is not a composite primary key", entity.getName())); - - Collection clauses = new ArrayList<>(); - - for (CassandraPersistentProperty property : entity) { - TypeCodec codec = getCodec(property); - Object value = accessor.getProperty(property, codec.getJavaType().getRawType()); - clauses.add(QueryBuilder.eq(property.getRequiredColumnName().toCql(), value)); - } - - return clauses; + getPotentiallyConvertedSimpleValue(id, targetType))); } private Collection getWhereClauses(MapId id, CassandraPersistentEntity entity) { @@ -616,7 +589,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter if (persistentProperty == null) { throw new IllegalArgumentException(String.format( - "MapId contains references [%s] that is an unknown property of [%s]", entry.getKey(), entity.getName())); + "MapId contains references [%s] that is an unknown property of [%s]", entry.getKey(), entity.getName())); } Object writeValue = getWriteValue(entry.getValue(), persistentProperty.getTypeInformation()); @@ -627,6 +600,65 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return clauses; } + private Collection getWhereClauses(ConvertingPropertyAccessor accessor, CassandraPersistentEntity entity) { + + Assert.isTrue(entity.isCompositePrimaryKey(), + String.format("Entity [%s] is not a composite primary key", entity.getName())); + + Collection clauses = new ArrayList<>(); + + for (CassandraPersistentProperty property : entity) { + TypeCodec codec = getCodec(property); + Object value = accessor.getProperty(property, codec.getJavaType().getRawType()); + clauses.add(QueryBuilder.eq(property.getRequiredColumnName().toCql(), value)); + } + + return clauses; + } + + private void writeTupleValue(ConvertingPropertyAccessor propertyAccessor, TupleValue tupleValue, + CassandraPersistentEntity entity) { + + for (CassandraPersistentProperty property : entity) { + + Object value = getWriteValue(property, propertyAccessor); + + if (log.isDebugEnabled()) { + log.debug("writeTupleValue Property.type {}, Property.value {}", property.getType().getName(), value); + } + + if (log.isDebugEnabled()) { + log.debug("Adding tuple value [{}] - [{}]", property.getOrdinal(), value); + } + + TypeCodec typeCodec = getCodec(property); + + tupleValue.set(property.getRequiredOrdinal(), value, typeCodec); + } + } + + private void writeUDTValue(ConvertingPropertyAccessor propertyAccessor, UDTValue udtValue, + CassandraPersistentEntity entity) { + + for (CassandraPersistentProperty property : entity) { + + Object value = getWriteValue(property, propertyAccessor); + + if (log.isDebugEnabled()) { + log.debug("writeUDTValueWhereFromObject Property.type {}, Property.value {}", property.getType().getName(), + value); + } + + if (log.isDebugEnabled()) { + log.debug("Adding udt.value [{}] - [{}]", property.getRequiredColumnName().toCql(), value); + } + + TypeCodec typeCodec = getCodec(property); + + udtValue.set(property.getRequiredColumnName().toCql(), value, typeCodec); + } + } + @Override @SuppressWarnings("unchecked") public Object getId(Object object, CassandraPersistentEntity entity) { @@ -634,10 +666,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter Assert.notNull(object, "Object instance must not be null"); Assert.notNull(entity, "CassandraPersistentEntity must not be null"); - ConvertingPropertyAccessor propertyAccessor = getConvertingAccessor(object, entity); + ConvertingPropertyAccessor propertyAccessor = newConvertingPropertyAccessor(object, entity); Assert.isTrue(entity.getType().isAssignableFrom(object.getClass()), - String.format("Given instance of type [%s] is not of compatible expected type [%s]", + String.format("Given instance of type [%s] is not compatible with expected type [%s]", object.getClass().getName(), entity.getType().getName())); if (object instanceof MapIdentifiable) { @@ -668,32 +700,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return id; } - /** - * Create a new {@link ConvertingPropertyAccessor} for the given source and entity. - * - * @param source must not be {@literal null}. - * @param entity must not be {@literal null}. - * @return a new {@link ConvertingPropertyAccessor} for the given source and entity. - */ - private ConvertingPropertyAccessor getConvertingAccessor(Object source, CassandraPersistentEntity entity) { - - PersistentPropertyAccessor propertyAccessor = source instanceof PersistentPropertyAccessor - ? (PersistentPropertyAccessor) source - : entity.getPropertyAccessor(source); - - return new ConvertingPropertyAccessor(propertyAccessor, getConversionService()); - } - - /** - * Returns whether the property is part of the primary key. - * - * @param property {@link CassandraPersistentProperty} to evaluate. - * @return a boolean value indicating whether the given property is party of a primary key. - */ - private boolean isPrimaryKeyPart(CassandraPersistentProperty property) { - return (property.isCompositePrimaryKey() || property.isPrimaryKeyColumn() || property.isIdProperty()); - } - private Class getTargetType(CassandraPersistentProperty property) { return getCustomConversions().getCustomWriteTarget(property.getType()).orElseGet(() -> { @@ -702,8 +708,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return getPropertyTargetType(property); } - if (property.isCompositePrimaryKey() || getCustomConversions().isSimpleType(property.getType()) - || property.isCollectionLike()) { + if (property.isCompositePrimaryKey() || property.isCollectionLike() + || getCustomConversions().isSimpleType(property.getType())) { return property.getType(); } @@ -721,7 +727,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return property.getType(); } - TypeCodec codec = getCodecRegistry().codecFor(getMappingContext().getDataType(property)); + TypeCodec codec = getCodecRegistry().codecFor(dataType); return codec.getJavaType().getRawType(); } @@ -731,13 +737,13 @@ public class MappingCassandraConverter extends AbstractCassandraConverter * {@link ConvertingPropertyAccessor} and perform optionally a conversion of collection element types. * * @param property the property. - * @param accessor the property accessor + * @param propertyAccessor the property accessor * @return the return value, may be {@literal null}. */ @Nullable @SuppressWarnings("unchecked") - private T getWriteValue(CassandraPersistentProperty property, ConvertingPropertyAccessor accessor) { - return (T) getWriteValue(accessor.getProperty(property, (Class) getTargetType(property)), + private T getWriteValue(CassandraPersistentProperty property, ConvertingPropertyAccessor propertyAccessor) { + return (T) getWriteValue(propertyAccessor.getProperty(property, (Class) getTargetType(property)), property.getTypeInformation()); } @@ -761,8 +767,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter if (getCustomConversions().hasCustomWriteTarget(value.getClass(), requestedTargetType)) { - Class resolvedTargetType = getCustomConversions().getCustomWriteTarget(value.getClass(), requestedTargetType) - .orElse(requestedTargetType); + Class resolvedTargetType = + getCustomConversions().getCustomWriteTarget(value.getClass(), requestedTargetType) + .orElse(requestedTargetType); return getConversionService().convert(value, resolvedTargetType); } @@ -770,8 +777,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter if (getCustomConversions().hasCustomWriteTarget(value.getClass())) { Class resolvedTargetType = getCustomConversions().getCustomWriteTarget(value.getClass()) - .orElseThrow(() -> new IllegalStateException(String - .format("Unable to determined custom write target for value type [%s]", value.getClass().getName()))); + .orElseThrow(() -> new IllegalStateException( + String.format("Unable to determined custom write target for value type [%s]", + value.getClass().getName()))); return getConversionService().convert(value, resolvedTargetType); } @@ -797,6 +805,15 @@ public class MappingCassandraConverter extends AbstractCassandraConverter if (entity != null) { + if (entity.isTupleType()) { + + TupleValue tupleValue = getMappingContext().getTupleType(entity).newValue(); + + write(value, tupleValue, entity); + + return tupleValue; + } + if (entity.isUserDefinedType()) { UDTValue udtValue = entity.getUserType().newValue(); @@ -805,15 +822,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return udtValue; } - - if (entity.isTupleType()) { - - TupleValue tupleValue = mappingContext.getTupleType(entity).newValue(); - - write(value, tupleValue, entity); - - return tupleValue; - } } return value; @@ -928,22 +936,22 @@ public class MappingCassandraConverter extends AbstractCassandraConverter * Retrieve the value to read for the given {@link CassandraPersistentProperty} from * {@link BasicCassandraRowValueProvider} and perform optionally a conversion of collection element types. * - * @param row the row. + * @param valueProvider the row. * @param property the property. * @return the return value, may be {@literal null}. */ @Nullable @SuppressWarnings("unchecked") - protected Object getReadValue(CassandraValueProvider row, CassandraPersistentProperty property) { + private Object getReadValue(CassandraValueProvider valueProvider, CassandraPersistentProperty property) { if (property.isCompositePrimaryKey()) { CassandraPersistentEntity keyEntity = getMappingContext().getRequiredPersistentEntity(property); - return instantiatePrimaryKey(keyEntity, property, row); + return instantiatePrimaryKey(keyEntity, property, valueProvider); } - Object value = row.getPropertyValue(property); + Object value = valueProvider.getPropertyValue(property); return value == null ? null : convertReadValue(value, property.getTypeInformation()); } @@ -977,26 +985,26 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return readMapInternal((Map) value, typeInformation); } - if (value instanceof UDTValue) { - - BasicCassandraPersistentEntity udtEntity = getMappingContext() - .getPersistentEntity(typeInformation.getRequiredActualType()); - - if (udtEntity != null && udtEntity.isUserDefinedType()) { - return readEntityFromUdt(udtEntity, (UDTValue) value); - } - } - if (value instanceof TupleValue) { - BasicCassandraPersistentEntity tupleEntity = getMappingContext() - .getPersistentEntity(typeInformation.getRequiredActualType()); + BasicCassandraPersistentEntity tupleEntity = + getMappingContext().getPersistentEntity(typeInformation.getRequiredActualType()); if (tupleEntity != null) { return readEntityFromTuple(tupleEntity, (TupleValue) value); } } + if (value instanceof UDTValue) { + + BasicCassandraPersistentEntity udtEntity = + getMappingContext().getPersistentEntity(typeInformation.getRequiredActualType()); + + if (udtEntity != null && udtEntity.isUserDefinedType()) { + return readEntityFromUdt(udtEntity, (UDTValue) value); + } + } + return getPotentiallyConvertedSimpleRead(value, typeInformation.getType()); } @@ -1105,14 +1113,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return Map.class.isAssignableFrom(mapType) ? mapType : Map.class; } - private TypeCodec getCodec(CassandraPersistentProperty property) { - return getCodecRegistry().codecFor(mappingContext.getDataType(property)); - } - - private static CodecRegistry getCodecRegistry() { - return CodecRegistry.DEFAULT_INSTANCE; - } - /** * {@link CassandraRowValueProvider} that delegates reads to {@link CassandraValueProvider} applying mapping and * custom conversion from {@link MappingCassandraConverter}. diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/QueryMapper.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/QueryMapper.java index f505ff8ff..aa78b2eec 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/QueryMapper.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/QueryMapper.java @@ -118,8 +118,6 @@ public class QueryMapper { Field field = createPropertyField(entity, criteriaDefinition.getColumnName()); - Predicate predicate = criteriaDefinition.getPredicate(); - field.getProperty().filter(CassandraPersistentProperty::isCompositePrimaryKey).ifPresent(it -> { throw new IllegalArgumentException( "Cannot use composite primary key directly. Reference a property of the composite primary key"); @@ -130,9 +128,13 @@ public class QueryMapper { String.format("Cannot reference tuple value elements, property [%s]", field.getMappedKey())); }); + Predicate predicate = criteriaDefinition.getPredicate(); + Object value = predicate.getValue(); - TypeInformation typeInformation = getTypeInformation(field, value); - Object mappedValue = value != null ? getConverter().convertToColumnType(value, typeInformation) : null; + + Object mappedValue = value != null + ? getConverter().convertToColumnType(value, getTypeInformation(field, value)) + : null; Predicate mappedPredicate = new Predicate(predicate.getOperator(), mappedValue); @@ -164,11 +166,9 @@ public class QueryMapper { Field field = createPropertyField(entity, column); - columns.getSelector(column).ifPresent(selector -> { - getCqlIdentifier(column, field).ifPresent(cqlIdentifier -> { - selectors.add(getMappedSelector(selector, cqlIdentifier)); - }); - }); + columns.getSelector(column).ifPresent(selector -> + getCqlIdentifier(column, field).ifPresent(cqlIdentifier -> + selectors.add(getMappedSelector(selector, cqlIdentifier)))); } if (columns.isEmpty()) { @@ -208,6 +208,7 @@ public class QueryMapper { FunctionCall functionCall = (FunctionCall) selector; List mappedParameters = functionCall.getParameters().stream().map(obj -> { + if (obj instanceof Selector) { return getMappedSelector((Selector) obj, cqlIdentifier); } @@ -254,11 +255,10 @@ public class QueryMapper { field.getProperty().ifPresent(seen::add); - columns.getSelector(column) // - .filter(selector -> selector instanceof ColumnSelector) // - .ifPresent(columnSelector -> { - getCqlIdentifier(column, field).map(CqlIdentifier::toCql).ifPresent(columnNames::add); - }); + columns.getSelector(column) + .filter(selector -> selector instanceof ColumnSelector) + .ifPresent(columnSelector -> + getCqlIdentifier(column, field).map(CqlIdentifier::toCql).ifPresent(columnNames::add)); } if (columns.isEmpty()) { @@ -308,12 +308,14 @@ public class QueryMapper { try { if (field.getProperty().isPresent()) { + return field.getProperty().map(cassandraPersistentProperty -> { if (cassandraPersistentProperty.isCompositePrimaryKey()) { throw new IllegalArgumentException( "Cannot use composite primary key directly. Reference a property of the composite primary key"); } + return cassandraPersistentProperty.getRequiredColumnName(); }); } @@ -324,13 +326,14 @@ public class QueryMapper { return column.getCqlIdentifier(); - } catch (IllegalStateException e) { - throw new IllegalArgumentException(e.getMessage(), e); + } catch (IllegalStateException cause) { + throw new IllegalArgumentException(cause.getMessage(), cause); } } - Field createPropertyField(CassandraPersistentEntity entity, ColumnName key) { - return Optional.of(entity). map(e -> new MetadataBackedField(key, e, getMappingContext())) + Field createPropertyField(@Nullable CassandraPersistentEntity entity, ColumnName key) { + + return Optional.ofNullable(entity).map(e -> new MetadataBackedField(key, e, getMappingContext())) .orElseGet(() -> new Field(key)); } @@ -452,17 +455,17 @@ public class QueryMapper { /** * Returns the {@link PersistentPropertyPath} for the given {@code pathExpression}. * - * @param pathExpression - * @return + * @param pathExpression {@link String} containing the path expression to evaluate + * @return the {@link PersistentPropertyPath} for the given {@code pathExpression}. */ private Optional> getPath(String pathExpression) { try { PropertyPath propertyPath = PropertyPath.from(pathExpression.replaceAll("\\.\\d", ""), - entity.getTypeInformation()); + this.entity.getTypeInformation()); - PersistentPropertyPath persistentPropertyPath = mappingContext - .getPersistentPropertyPath(propertyPath); + PersistentPropertyPath persistentPropertyPath = + this.mappingContext.getPersistentPropertyPath(propertyPath); return Optional.of(persistentPropertyPath); } catch (PropertyReferenceException e) { @@ -485,7 +488,7 @@ public class QueryMapper { */ @Override public Optional getProperty() { - return optionalProperty; + return this.optionalProperty; } /* diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/UpdateMapper.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/UpdateMapper.java index a7df63329..43bd505df 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/UpdateMapper.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/UpdateMapper.java @@ -132,8 +132,8 @@ public class UpdateMapper extends QueryMapper { Assert.state(op.getValue() != null, () -> String.format("SetAtKeyOp for %s attempts to set null", field.getProperty())); - Optional> typeInformation = field.getProperty() - .map(PersistentProperty::getTypeInformation); + Optional> typeInformation = + field.getProperty().map(PersistentProperty::getTypeInformation); Optional> keyType = typeInformation.map(TypeInformation::getComponentType); Optional> valueType = typeInformation.map(TypeInformation::getMapValueType); @@ -167,8 +167,8 @@ public class UpdateMapper extends QueryMapper { if (collection.isEmpty()) { - DataType.Name dataType = field.getProperty().map(property -> getMappingContext().getDataType(property)) - .map(DataType::getName).orElse(Name.LIST); + DataType.Name dataType = field.getProperty().map(property -> + getMappingContext().getDataType(property)).map(DataType::getName).orElse(Name.LIST); if (dataType == Name.SET) { return new SetOp(field.getMappedKey(), Collections.emptySet()); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntity.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntity.java index 34f460a8e..667befb07 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntity.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntity.java @@ -15,7 +15,7 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.springframework.data.cassandra.core.cql.CqlIdentifier.*; +import static org.springframework.data.cassandra.core.cql.CqlIdentifier.of; import java.util.Comparator; import java.util.Optional; @@ -51,16 +51,17 @@ import com.datastax.driver.core.UserType; public class BasicCassandraPersistentEntity extends BasicPersistentEntity implements CassandraPersistentEntity, ApplicationContextAware { - private static final CassandraPersistentEntityMetadataVerifier DEFAULT_VERIFIER = new CompositeCassandraPersistentEntityMetadataVerifier(); + private static final CassandraPersistentEntityMetadataVerifier DEFAULT_VERIFIER = + new CompositeCassandraPersistentEntityMetadataVerifier(); + + private Boolean forceQuote; private CassandraPersistentEntityMetadataVerifier verifier = DEFAULT_VERIFIER; + private CqlIdentifier tableName; + private @Nullable StandardEvaluationContext spelContext; - private Optional forceQuote = Optional.empty(); - - private Optional tableName = Optional.empty(); - /** * Create a new {@link BasicCassandraPersistentEntity} given {@link TypeInformation}. * @@ -102,6 +103,7 @@ public class BasicCassandraPersistentEntity extends BasicPersistentEntity extends BasicPersistentEntity SpelUtils.evaluate(value, it)) + .orElse(value); Assert.state(name != null, () -> String.format("Cannot determine default name for %s", this)); - return of(name, forceQuote); + return CqlIdentifier.of(name, forceQuote); } /* (non-Javadoc) @@ -158,9 +162,9 @@ public class BasicCassandraPersistentEntity extends BasicPersistentEntity extends BasicPersistentEntity v != forceQuote).isPresent(); + boolean changed = !Boolean.valueOf(forceQuote).equals(this.forceQuote); - this.forceQuote = Optional.of(forceQuote); + this.forceQuote = forceQuote; if (changed) { setTableName(of(getTableName().getUnquoted(), forceQuote)); @@ -201,7 +205,8 @@ public class BasicCassandraPersistentEntity extends BasicPersistentEntity extends BasicPersistentEntity extends BasicPersistentEntity extends BasicPersistentEntity implements CassandraPersistentProperty, ApplicationContextAware { - private final @Nullable UserTypeResolver userTypeResolver; + // Indicates whether this property has been explicitly instructed to force quoted column names. + private Boolean forceQuote; + + private @Nullable CqlIdentifier columnName; private @Nullable StandardEvaluationContext spelContext; - /** - * Whether this property has been explicitly instructed to force quote column names. - */ - private Optional forceQuote = Optional.empty(); - - /** - * An unmodifiable list of this property's column names. - */ - private @Nullable CqlIdentifier columnName; + private final @Nullable UserTypeResolver userTypeResolver; /** * Create a new {@link BasicCassandraPersistentProperty}. @@ -141,7 +134,8 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP this.columnName = determineColumnName(); } - Assert.state(this.columnName != null, () -> String.format("Cannot determine column name for %s", this)); + Assert.state(this.columnName != null, + () -> String.format("Cannot determine column name for %s", this)); return this.columnName; } @@ -164,7 +158,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP PrimaryKeyColumn annotation = findAnnotation(PrimaryKeyColumn.class); - return (annotation != null ? annotation.ordering() : null); + return annotation != null ? annotation.ordering() : null; } /* (non-Javadoc) @@ -178,7 +172,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP if (dataType == null) { throw new InvalidDataAccessApiUsageException(String.format( "Unknown type [%s] for property [%s] in entity [%s]; only primitive types and Collections or Maps of primitive types are allowed", - getType(), getName(), getOwner().getName())); + getType(), getName(), getOwner().getName())); } return dataType; @@ -197,7 +191,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP List> args = getTypeInformation().getTypeArguments(); - ensureTypeArguments(args.size(), 2); + assertTypeArguments(args.size(), 2); return DataType.map(getDataTypeFor(args.get(0).getType()), getDataTypeFor(args.get(1).getType())); } @@ -206,7 +200,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP List> args = getTypeInformation().getTypeArguments(); - ensureTypeArguments(args.size(), 1); + assertTypeArguments(args.size(), 1); if (Set.class.isAssignableFrom(getType())) { return DataType.set(getDataTypeFor(args.get(0).getType())); @@ -226,21 +220,17 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP switch (type) { case MAP: - ensureTypeArguments(annotation.typeArguments().length, 2); + assertTypeArguments(annotation.typeArguments().length, 2); return DataType.map(CassandraSimpleTypeHolder.getDataTypeFor(annotation.typeArguments()[0]), CassandraSimpleTypeHolder.getDataTypeFor(annotation.typeArguments()[1])); case LIST: - ensureTypeArguments(annotation.typeArguments().length, 1); - if (annotation.typeArguments()[0] == Name.UDT) { - return DataType.list(getUserType(annotation)); - } - return DataType.list(CassandraSimpleTypeHolder.getDataTypeFor(annotation.typeArguments()[0])); + assertTypeArguments(annotation.typeArguments().length, 1); + return annotation.typeArguments()[0] == Name.UDT ? DataType.list(getUserType(annotation)) + : DataType.list(CassandraSimpleTypeHolder.getDataTypeFor(annotation.typeArguments()[0])); case SET: - ensureTypeArguments(annotation.typeArguments().length, 1); - if (annotation.typeArguments()[0] == Name.UDT) { - return DataType.set(getUserType(annotation)); - } - return DataType.set(CassandraSimpleTypeHolder.getDataTypeFor(annotation.typeArguments()[0])); + assertTypeArguments(annotation.typeArguments().length, 1); + return annotation.typeArguments()[0] == Name.UDT ? DataType.set(getUserType(annotation)) + : DataType.set(CassandraSimpleTypeHolder.getDataTypeFor(annotation.typeArguments()[0])); case UDT: return getUserType(annotation); default: @@ -276,17 +266,18 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP if (dataType == null) { throw new InvalidDataAccessApiUsageException(String.format( "Only primitive types are allowed inside Collections for property [%1$s] of type ['%2$s'] in entity [%3$s]", - getName(), getType(), getOwner().getName())); + getName(), getType(), getOwner().getName())); } return dataType; } - private void ensureTypeArguments(int args, int expected) { + private void assertTypeArguments(int args, int expected) { + if (args != expected) { throw new InvalidDataAccessApiUsageException( - String.format("Expected [%1$s] typed arguments for property ['%2$s'] of type ['%3$s'] in entity [%4$s]", - expected, getName(), getType(), getOwner().getName())); + String.format("Expected [%1$s] type arguments for property ['%2$s'] of type ['%3$s'] in entity [%4$s]; actual was [%5$d]", + expected, getName(), getType(), getOwner().getName(), args)); } } @@ -295,26 +286,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP */ @Override public boolean isCompositePrimaryKey() { - return (AnnotatedElementUtils.findMergedAnnotation(getType(), PrimaryKeyClass.class) != null); - } - - /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isPrimaryKeyColumn() - */ - @Override - public boolean isPrimaryKeyColumn() { - return isAnnotationPresent(PrimaryKeyColumn.class); - } - - /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isPartitionKeyColumn() - */ - @Override - public boolean isPartitionKeyColumn() { - - PrimaryKeyColumn annotation = findAnnotation(PrimaryKeyColumn.class); - - return (annotation != null && PrimaryKeyType.PARTITIONED.equals(annotation.type())); + return AnnotatedElementUtils.findMergedAnnotation(getType(), PrimaryKeyClass.class) != null; } /* (non-Javadoc) @@ -325,7 +297,26 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP PrimaryKeyColumn annotation = findAnnotation(PrimaryKeyColumn.class); - return (annotation != null && PrimaryKeyType.CLUSTERED.equals(annotation.type())); + return annotation != null && PrimaryKeyType.CLUSTERED.equals(annotation.type()); + } + + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isPartitionKeyColumn() + */ + @Override + public boolean isPartitionKeyColumn() { + + PrimaryKeyColumn annotation = findAnnotation(PrimaryKeyColumn.class); + + return annotation != null && PrimaryKeyType.PARTITIONED.equals(annotation.type()); + } + + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isPrimaryKeyColumn() + */ + @Override + public boolean isPrimaryKeyColumn() { + return isAnnotationPresent(PrimaryKeyColumn.class); } @Nullable @@ -377,10 +368,10 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP String name = defaultName; if (StringUtils.hasText(overriddenName)) { - name = (this.spelContext != null ? SpelUtils.evaluate(overriddenName, this.spelContext) : overriddenName); + name = this.spelContext != null ? SpelUtils.evaluate(overriddenName, this.spelContext) : overriddenName; } - return name == null ? null : of(name, forceQuote); + return name != null ? CqlIdentifier.of(name, forceQuote) : null; } /* (non-Javadoc) @@ -400,14 +391,12 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP @Override public void setForceQuote(boolean forceQuote) { - boolean changed = !this.forceQuote.isPresent() || this.forceQuote.filter(v -> v != forceQuote).isPresent(); + boolean changed = !Boolean.valueOf(forceQuote).equals(this.forceQuote); - this.forceQuote = Optional.of(forceQuote); + this.forceQuote = forceQuote; if (changed) { - - CqlIdentifier columnName = getRequiredColumnName(); - setColumnName(of(columnName.getUnquoted(), forceQuote)); + setColumnName(CqlIdentifier.of(getRequiredColumnName().getUnquoted(), forceQuote)); } } @@ -441,8 +430,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP @Override public AnnotatedType findAnnotatedType(Class annotationType) { - return Optionals - .toStream(Optional.ofNullable(getField()).map(Field::getAnnotatedType), + return Optionals.toStream(Optional.ofNullable(getField()).map(Field::getAnnotatedType), Optional.ofNullable(getGetter()).map(Method::getAnnotatedReturnType), Optional.ofNullable(getSetter()).map(it -> it.getParameters()[0].getAnnotatedType())) .filter(it -> hasAnnotation(it, annotationType, getTypeInformation())).findFirst().orElse(null); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntity.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntity.java index 9013e69ff..bd245ab59 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntity.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntity.java @@ -54,14 +54,14 @@ public class BasicCassandraPersistentTupleEntity extends BasicCassandraPersis Assert.notNull(tupleTypeFactory, "TupleTypeFactory must not be null"); - this.tupleType = Lazy.of(() -> tupleTypeFactory.create(getTupleFieldTypes())); + this.tupleType = Lazy.of(() -> tupleTypeFactory.create(getTupleFieldDataTypes())); } - private List getTupleFieldTypes() { + private List getTupleFieldDataTypes() { - return StreamSupport.stream(spliterator(), false) // - .sorted(TuplePropertyComparator.INSTANCE) // - .map(CassandraPersistentProperty::getDataType) // + return StreamSupport.stream(spliterator(), false) + .sorted(TuplePropertyComparator.INSTANCE) + .map(CassandraPersistentProperty::getDataType) .collect(Collectors.toList()); } @@ -89,7 +89,7 @@ public class BasicCassandraPersistentTupleEntity extends BasicCassandraPersis */ @Override public TupleType getTupleType() { - return tupleType.get(); + return this.tupleType.get(); } /** @@ -106,8 +106,8 @@ public class BasicCassandraPersistentTupleEntity extends BasicCassandraPersis * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override - public int compare(CassandraPersistentProperty o1, CassandraPersistentProperty o2) { - return Integer.compare(o1.getRequiredOrdinal(), o2.getRequiredOrdinal()); + public int compare(CassandraPersistentProperty propertyOne, CassandraPersistentProperty propertyTwo) { + return Integer.compare(propertyOne.getRequiredOrdinal(), propertyTwo.getRequiredOrdinal()); } } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleProperty.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleProperty.java index dc44d76d4..140af1542 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleProperty.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleProperty.java @@ -42,6 +42,7 @@ public class BasicCassandraPersistentTupleProperty extends BasicCassandraPersist */ public BasicCassandraPersistentTupleProperty(Property property, CassandraPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { + this(property, owner, simpleTypeHolder, null); } @@ -72,16 +73,15 @@ public class BasicCassandraPersistentTupleProperty extends BasicCassandraPersist try { ordinal = getRequiredAnnotation(Element.class).value(); - } catch (IllegalStateException e) { + } catch (IllegalStateException cause) { throw new MappingException( - String.format("Missing @Element annotation in mapped tuple type for property [%s] in entity [%s]", getName(), - getOwner().getName()), - e); + String.format("Missing @Element annotation in mapped tuple type for property [%s] in entity [%s]", + getName(), getOwner().getName()), cause); } Assert.isTrue(ordinal >= 0, - String.format("Element ordinal must be greater or equal to zero for property [%s] in entity [%s]", getName(), - getOwner().getName())); + String.format("Element ordinal must be greater or equal to zero for property [%s] in entity [%s]", + getName(), getOwner().getName())); return ordinal; } @@ -100,7 +100,15 @@ public class BasicCassandraPersistentTupleProperty extends BasicCassandraPersist @Nullable @Override public Integer getOrdinal() { - return ordinal; + return this.ordinal; + } + + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isClusterKeyColumn() + */ + @Override + public boolean isClusterKeyColumn() { + return false; } /* (non-Javadoc) @@ -111,14 +119,6 @@ public class BasicCassandraPersistentTupleProperty extends BasicCassandraPersist return false; } - /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isPrimaryKeyColumn() - */ - @Override - public boolean isPrimaryKeyColumn() { - return false; - } - /* (non-Javadoc) * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isPartitionKeyColumn() */ @@ -128,10 +128,10 @@ public class BasicCassandraPersistentTupleProperty extends BasicCassandraPersist } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isClusterKeyColumn() + * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#isPrimaryKeyColumn() */ @Override - public boolean isClusterKeyColumn() { + public boolean isPrimaryKeyColumn() { return false; } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContext.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContext.java index c194c2934..9fcb9523e 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContext.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContext.java @@ -15,10 +15,20 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.springframework.data.cassandra.core.cql.keyspace.CreateTableSpecification.*; -import static org.springframework.data.cassandra.core.mapping.CassandraSimpleTypeHolder.*; +import static org.springframework.data.cassandra.core.cql.keyspace.CreateTableSpecification.createTable; +import static org.springframework.data.cassandra.core.mapping.CassandraSimpleTypeHolder.getDataTypeFor; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.function.Supplier; import java.util.stream.StreamSupport; @@ -67,19 +77,20 @@ public class CassandraMappingContext private @Nullable ApplicationContext applicationContext; + private CassandraPersistentEntityMetadataVerifier verifier = + new CompositeCassandraPersistentEntityMetadataVerifier(); + private @Nullable ClassLoader beanClassLoader; - private CassandraPersistentEntityMetadataVerifier verifier = new CompositeCassandraPersistentEntityMetadataVerifier(); - - private CustomConversions customConversions = new CustomConversions( - StoreConversions.of(CassandraSimpleTypeHolder.HOLDER), Collections.emptyList()); + private CustomConversions customConversions = + new CustomConversions(StoreConversions.of(CassandraSimpleTypeHolder.HOLDER), Collections.emptyList()); private Mapping mapping = new Mapping(); - private @Nullable UserTypeResolver userTypeResolver; - private TupleTypeFactory tupleTypeFactory = CodecRegistryTupleTypeFactory.DEFAULT; + private @Nullable UserTypeResolver userTypeResolver; + // caches private final Map>> entitySetsByTableName = new HashMap<>(); @@ -90,10 +101,6 @@ public class CassandraMappingContext * Create a new {@link CassandraMappingContext}. */ public CassandraMappingContext() { - - StoreConversions storeConversions = StoreConversions.of(CassandraSimpleTypeHolder.HOLDER); - - setCustomConversions(new CustomConversions(storeConversions, Collections.emptyList())); setSimpleTypeHolder(CassandraSimpleTypeHolder.HOLDER); } @@ -106,15 +113,8 @@ public class CassandraMappingContext */ public CassandraMappingContext(UserTypeResolver userTypeResolver, TupleTypeFactory tupleTypeFactory) { - Assert.notNull(userTypeResolver, "UserTypeResolver must not be null"); - Assert.notNull(tupleTypeFactory, "TupleTypeFactory must not be null"); - - StoreConversions storeConversions = StoreConversions.of(CassandraSimpleTypeHolder.HOLDER); - setUserTypeResolver(userTypeResolver); setTupleTypeFactory(tupleTypeFactory); - - setCustomConversions(new CustomConversions(storeConversions, Collections.emptyList())); setSimpleTypeHolder(CassandraSimpleTypeHolder.HOLDER); } @@ -123,7 +123,9 @@ public class CassandraMappingContext */ @Override public void initialize() { + super.initialize(); + processMappingOverrides(); } @@ -158,6 +160,7 @@ public class CassandraMappingContext } private static void processMappingOverrides(CassandraPersistentEntity entity, EntityMapping entityMapping) { + entityMapping.getPropertyMappings() .forEach((key, propertyMapping) -> processMappingOverride(entity, propertyMapping)); } @@ -233,6 +236,24 @@ public class CassandraMappingContext return Collections.unmodifiableSet(this.userDefinedTypes); } + /** + * Sets the {@link TupleTypeFactory}. + * + * @param tupleTypeFactory must not be {@literal null}. + * @since 2.1 + */ + public void setTupleTypeFactory(TupleTypeFactory tupleTypeFactory) { + + Assert.notNull(tupleTypeFactory, "TupleTypeFactory must not be null"); + + this.tupleTypeFactory = tupleTypeFactory; + } + + @NonNull + protected TupleTypeFactory getTupleTypeFactory() { + return this.tupleTypeFactory; + } + /** * Sets the {@link UserTypeResolver}. * @@ -246,17 +267,9 @@ public class CassandraMappingContext this.userTypeResolver = userTypeResolver; } - /** - * Sets the {@link TupleTypeFactory}. - * - * @param tupleTypeFactory must not be {@literal null}. - * @since 2.1 - */ - public void setTupleTypeFactory(TupleTypeFactory tupleTypeFactory) { - - Assert.notNull(tupleTypeFactory, "TupleTypeFactory must not be null"); - - this.tupleTypeFactory = tupleTypeFactory; + @Nullable + protected UserTypeResolver getUserTypeResolver() { + return this.userTypeResolver; } /** @@ -291,8 +304,8 @@ public class CassandraMappingContext } // now do some caching of the entity - Set> entities = this.entitySetsByTableName.computeIfAbsent(entity.getTableName(), - cqlIdentifier -> new HashSet<>()); + Set> entities = + this.entitySetsByTableName.computeIfAbsent(entity.getTableName(), cqlIdentifier -> new HashSet<>()); entities.add(entity); @@ -320,33 +333,29 @@ public class CassandraMappingContext @Override protected BasicCassandraPersistentEntity createPersistentEntity(TypeInformation typeInformation) { - BasicCassandraPersistentEntity entity = Optional.ofNullable(resolveUserDefinedType(typeInformation)) - .> map(resolvedUserDefinedType -> new CassandraUserTypePersistentEntity<>( - typeInformation, getVerifier(), resolveUserTypeResolver())) - .orElseGet(() -> { - boolean tuple = AnnotatedElementUtils.hasAnnotation(typeInformation.getType(), Tuple.class); - - if (tuple) { - return new BasicCassandraPersistentTupleEntity<>(typeInformation, tupleTypeFactory); - } - - return new BasicCassandraPersistentEntity<>(typeInformation, getVerifier()); - }); + BasicCassandraPersistentEntity entity = isUserDefinedType(typeInformation) + ? new CassandraUserTypePersistentEntity<>(typeInformation, getVerifier(), resolveUserTypeResolver()) + : isTuple(typeInformation) + ? new BasicCassandraPersistentTupleEntity<>(typeInformation, getTupleTypeFactory()) + : new BasicCassandraPersistentEntity<>(typeInformation, getVerifier()); Optional.ofNullable(this.applicationContext).ifPresent(entity::setApplicationContext); return entity; } - @Nullable - private UserDefinedType resolveUserDefinedType(TypeInformation typeInformation) { - return AnnotatedElementUtils.findMergedAnnotation(typeInformation.getType(), UserDefinedType.class); + private boolean isTuple(TypeInformation typeInformation) { + return AnnotatedElementUtils.hasAnnotation(typeInformation.getType(), Tuple.class); + } + + private boolean isUserDefinedType(TypeInformation typeInformation) { + return AnnotatedElementUtils.hasAnnotation(typeInformation.getType(), UserDefinedType.class); } @NonNull private UserTypeResolver resolveUserTypeResolver() { - UserTypeResolver resolvedUserTypeResolver = this.userTypeResolver; + UserTypeResolver resolvedUserTypeResolver = getUserTypeResolver(); Assert.state(resolvedUserTypeResolver != null, "UserTypeResolver must not be null"); @@ -360,15 +369,9 @@ public class CassandraMappingContext protected CassandraPersistentProperty createPersistentProperty(Property property, BasicCassandraPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { - BasicCassandraPersistentProperty persistentProperty; - - if (owner.isTupleType()) { - persistentProperty = new BasicCassandraPersistentTupleProperty(property, owner, simpleTypeHolder, - this.userTypeResolver); - } else { - persistentProperty = new BasicCassandraPersistentProperty(property, owner, simpleTypeHolder, - this.userTypeResolver); - } + BasicCassandraPersistentProperty persistentProperty = owner.isTupleType() + ? new BasicCassandraPersistentTupleProperty(property, owner, simpleTypeHolder, getUserTypeResolver()) + : new BasicCassandraPersistentProperty(property, owner, simpleTypeHolder, getUserTypeResolver()); Optional.ofNullable(this.applicationContext).ifPresent(persistentProperty::setApplicationContext); @@ -410,7 +413,9 @@ public class CassandraMappingContext return getPersistentEntities().stream().flatMap(entity -> StreamSupport.stream(entity.spliterator(), false)) .flatMap(it -> Optionals.toStream(Optional.ofNullable(it.findAnnotation(CassandraType.class)))) - .map(CassandraType::userTypeName).filter(StringUtils::hasText).map(CqlIdentifier::of) + .map(CassandraType::userTypeName) + .filter(StringUtils::hasText) + .map(CqlIdentifier::of) .anyMatch(identifier::equals); } @@ -520,7 +525,8 @@ public class CassandraMappingContext */ public DataType getDataType(Class type) { - return this.customConversions.getCustomWriteTarget(type).map(CassandraSimpleTypeHolder::getDataTypeFor) + return this.customConversions.getCustomWriteTarget(type) + .map(CassandraSimpleTypeHolder::getDataTypeFor) .orElseGet(() -> getDataTypeFor(type)); } @@ -555,10 +561,11 @@ public class CassandraMappingContext if (annotation.type() == Name.TUPLE) { - DataType[] dataTypes = Arrays.stream(annotation.typeArguments()).map(CassandraSimpleTypeHolder::getDataTypeFor) + DataType[] dataTypes = Arrays.stream(annotation.typeArguments()) + .map(CassandraSimpleTypeHolder::getDataTypeFor) .toArray(DataType[]::new); - return tupleTypeFactory.create(dataTypes); + return getTupleTypeFactory().create(dataTypes); } if (annotation.type() == Name.UDT) { @@ -633,11 +640,12 @@ public class CassandraMappingContext private TupleType getTupleType(DataTypeProvider dataTypeProvider, CassandraPersistentEntity persistentEntity) { List types = new ArrayList<>(); + for (CassandraPersistentProperty persistentProperty : persistentEntity) { types.add(getDataTypeWithUserTypeFactory(persistentProperty, dataTypeProvider)); } - return tupleTypeFactory.create(types); + return getTupleTypeFactory().create(types); } @SuppressWarnings("all") diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentEntity.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentEntity.java index 1116a7c15..d58aad037 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentEntity.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentEntity.java @@ -36,6 +36,13 @@ public interface CassandraPersistentEntity extends PersistentEntity extends PersistentEntity extends PersistentEntity, ApplicationContextAware { + /** + * If this property is mapped with a single column, set the column name to the given {@link CqlIdentifier}. If this + * property is not mapped by a single column, throws {@link IllegalStateException}. If the given column name is null, + * {@link IllegalArgumentException} is thrown. + * + * @param columnName must not be {@literal null}. + */ + void setColumnName(CqlIdentifier columnName); + /** * The name of the single column to which the property is persisted. */ @@ -55,13 +65,30 @@ public interface CassandraPersistentProperty CqlIdentifier columnName = getColumnName(); - if (columnName == null) { - throw new IllegalStateException("No column name available for this persistent property"); - } + Assert.state(columnName != null, + String.format("No column name available for this persistent property [%1$s.%2$s]", + getOwner().getName(), getName())); return columnName; } + /** + * The column's data type. Not valid for a composite primary key. + * + * @return the Cassandra {@link DataType} + * @throws InvalidDataAccessApiUsageException if the {@link DataType} cannot be resolved + * @see CassandraType + */ + DataType getDataType(); + + /** + * Whether to force-quote the column names of this property. + * + * @param forceQuote {@literal true} to enforce quoting. + * @see CassandraPersistentProperty#getColumnName() + */ + void setForceQuote(boolean forceQuote); + /** * The name of the element ordinal to which the property is persisted when the owning type is a mapped tuple. */ @@ -78,9 +105,9 @@ public interface CassandraPersistentProperty Integer ordinal = getOrdinal(); - if (ordinal == null) { - throw new IllegalStateException("No ordinal available for this persistent property"); - } + Assert.state(ordinal != null , + String.format("No ordinal available for this persistent property [%1$s.%2$s]", + getOwner().getName(), getName())); return ordinal; } @@ -93,19 +120,27 @@ public interface CassandraPersistentProperty Ordering getPrimaryKeyOrdering(); /** - * The column's data type. Not valid for a composite primary key. - * - * @return the Cassandra {@link DataType} - * @throws InvalidDataAccessApiUsageException if the {@link DataType} cannot be resolved - * @see CassandraType + * Whether the property is a cluster key column. */ - DataType getDataType(); + boolean isClusterKeyColumn(); /** * Whether the property is a composite primary key. */ boolean isCompositePrimaryKey(); + /** + * Returns whether the property is a {@link java.util.Map}. + * + * @return a boolean indicating whether this property type is a {@link java.util.Map}. + */ + boolean isMapLike(); + + /** + * Whether the property is a partition key column. + */ + boolean isPartitionKeyColumn(); + /** * Whether the property is a partition key column or a cluster key column * @@ -114,40 +149,6 @@ public interface CassandraPersistentProperty */ boolean isPrimaryKeyColumn(); - /** - * Whether the property is a partition key column. - */ - boolean isPartitionKeyColumn(); - - /** - * Whether the property is a cluster key column. - */ - boolean isClusterKeyColumn(); - - /** - * Whether to force-quote the column names of this property. - * - * @param forceQuote {@literal true} to enforce quoting. - * @see CassandraPersistentProperty#getColumnName() - */ - void setForceQuote(boolean forceQuote); - - /** - * If this property is mapped with a single column, set the column name to the given {@link CqlIdentifier}. If this - * property is not mapped by a single column, throws {@link IllegalStateException}. If the given column name is null, - * {@link IllegalArgumentException} is thrown. - * - * @param columnName must not be {@literal null}. - */ - void setColumnName(CqlIdentifier columnName); - - /** - * Returns whether the property is a {@link java.util.Map}. - * - * @return a boolean indicating whether this property type is a {@link java.util.Map}. - */ - boolean isMapLike(); - /** * Find an {@link AnnotatedType} by {@code annotationType} derived from the property type. Annotated type is looked up * by introspecting property field/accessors. Collection/Map-like types are introspected for type annotations within @@ -159,4 +160,5 @@ public interface CassandraPersistentProperty */ @Nullable AnnotatedType findAnnotatedType(Class annotationType); + } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentTupleMetadataVerifier.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentTupleMetadataVerifier.java index 6ad303206..54373c2e6 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentTupleMetadataVerifier.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentTupleMetadataVerifier.java @@ -53,14 +53,15 @@ enum CassandraPersistentTupleMetadataVerifier implements CassandraPersistentEnti } if (!ordinals.add(tupleProperty.getOrdinal())) { - throw new MappingException( - String.format("Duplicate ordinal [%d] in entity [%s]", tupleProperty.getOrdinal(), entity.getName())); + throw new MappingException(String.format("Duplicate ordinal [%d] in entity [%s]", + tupleProperty.getOrdinal(), entity.getName())); } } if (ordinals.isEmpty()) { - throw new MappingException(String.format( - "Mapped tuple contains no persistent elements annotated with @Element in entity [%s]", entity.getName())); + throw new MappingException( + String.format("Mapped tuple contains no persistent elements annotated with @Element in entity [%s]", + entity.getName())); } List missingMappings = IntStream.range(0, ordinals.size()).boxed().collect(Collectors.toList()); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraSimpleTypeHolder.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraSimpleTypeHolder.java index 70cf6f62b..30f7ef308 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraSimpleTypeHolder.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CassandraSimpleTypeHolder.java @@ -73,8 +73,8 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder { simpleTypes.add(Number.class); simpleTypes.add(Row.class); - simpleTypes.add(UDTValue.class); simpleTypes.add(TupleValue.class); + simpleTypes.add(UDTValue.class); classToDataType = Collections.unmodifiableMap(classToDataType(codecRegistry, primitiveWrappers)); nameToDataType = Collections.unmodifiableMap(nameToDataType()); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CodecRegistryTupleTypeFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CodecRegistryTupleTypeFactory.java index fa617afdd..146539ba9 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CodecRegistryTupleTypeFactory.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/CodecRegistryTupleTypeFactory.java @@ -39,10 +39,10 @@ public class CodecRegistryTupleTypeFactory implements TupleTypeFactory { */ public static final CodecRegistryTupleTypeFactory DEFAULT = new CodecRegistryTupleTypeFactory(); - private final ProtocolVersion protocolVersion; - private final CodecRegistry codecRegistry; + private final ProtocolVersion protocolVersion; + /** * Creates a new {@link CodecRegistryTupleTypeFactory} using newest protocol version and the default * {@link CodecRegistry}. @@ -66,19 +66,19 @@ public class CodecRegistryTupleTypeFactory implements TupleTypeFactory { this.codecRegistry = codecRegistry; } - /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.mapping.TupleTypeFactory#create(java.util.List) - */ - @Override - public TupleType create(List types) { - return create(types.toArray(new DataType[0])); - } - /* (non-Javadoc) * @see org.springframework.data.cassandra.core.mapping.TupleTypeFactory#create(com.datastax.driver.core.DataType[]) */ @Override public TupleType create(DataType... types) { - return TupleType.of(protocolVersion, codecRegistry, types); + return TupleType.of(this.protocolVersion, this.codecRegistry, types); + } + + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.mapping.TupleTypeFactory#create(java.util.List) + */ + @Override + public TupleType create(List types) { + return create(types.toArray(new DataType[types.size()])); } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactory.java index 9a2053fb5..8f5fcb703 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactory.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactory.java @@ -51,6 +51,6 @@ public class SimpleTupleTypeFactory implements TupleTypeFactory { */ @Override public TupleType create(List types) { - return cluster.getMetadata().newTupleType(types); + return this.cluster.getMetadata().newTupleType(types); } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/TupleTypeFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/TupleTypeFactory.java index 9d8cb4689..96ba7be62 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/TupleTypeFactory.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/TupleTypeFactory.java @@ -55,4 +55,5 @@ public interface TupleTypeFactory { * @return the {@link TupleType} representing the given {@link DataType tuple element types}. */ TupleType create(List types); + } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/ColumnName.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/ColumnName.java index aa67e0c8d..b03bf194a 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/ColumnName.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/ColumnName.java @@ -58,8 +58,7 @@ public abstract class ColumnName { */ public static ColumnName from(String columnName) { - Assert.notNull(columnName, "Column name must not be null"); - Assert.hasText(columnName, "Column name must not be empty"); + Assert.hasText(columnName, "Column name must not be null or empty"); return new StringColumnName(columnName); } @@ -144,7 +143,7 @@ public abstract class ColumnName { */ @Override public String toCql() { - return columnName; + return this.columnName; } /* (non-Javadoc) @@ -152,7 +151,7 @@ public abstract class ColumnName { */ @Override public String toString() { - return columnName; + return this.columnName; } } @@ -182,7 +181,7 @@ public abstract class ColumnName { */ @Override public Optional getCqlIdentifier() { - return Optional.of(cqlIdentifier); + return Optional.of(this.cqlIdentifier); } /* (non-Javadoc) @@ -190,7 +189,7 @@ public abstract class ColumnName { */ @Override public String toCql() { - return cqlIdentifier.toCql(); + return this.cqlIdentifier.toCql(); } /* (non-Javadoc) @@ -198,7 +197,7 @@ public abstract class ColumnName { */ @Override public String toString() { - return cqlIdentifier.toString(); + return this.cqlIdentifier.toString(); } } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/CriteriaDefinition.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/CriteriaDefinition.java index 98d09e34c..b07fd81ea 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/CriteriaDefinition.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/query/CriteriaDefinition.java @@ -100,8 +100,15 @@ public interface CriteriaDefinition { */ enum Operators implements Operator { - EQ("="), GT(">"), GTE(">="), LT("<"), LTE("<="), CONTAINS("CONTAINS"), CONTAINS_KEY("CONTAINS KEY"), IN("IN"), LIKE( - "LIKE"); + CONTAINS("CONTAINS"), + CONTAINS_KEY("CONTAINS KEY"), + EQ("="), + GT(">"), + GTE(">="), + LT("<"), + LTE("<="), + IN("IN"), + LIKE("LIKE"); private final String operator; diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterMappedTupleUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterMappedTupleUnitTests.java index 8bd8f355e..ddad7b540 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterMappedTupleUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterMappedTupleUnitTests.java @@ -15,24 +15,24 @@ */ package org.springframework.data.cassandra.core.convert; -import static org.assertj.core.api.Assertions.*; -import static org.springframework.data.cassandra.test.util.RowMockUtil.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.data.cassandra.test.util.RowMockUtil.column; import lombok.AllArgsConstructor; import lombok.Data; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentEntity; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; import org.springframework.data.cassandra.core.mapping.Element; import org.springframework.data.cassandra.core.mapping.Tuple; import org.springframework.data.cassandra.test.util.RowMockUtil; +import com.datastax.driver.core.DataType; import com.datastax.driver.core.Row; import com.datastax.driver.core.TupleValue; import com.datastax.driver.core.querybuilder.Insert; @@ -46,32 +46,36 @@ import com.datastax.driver.core.querybuilder.QueryBuilder; @RunWith(MockitoJUnitRunner.Silent.class) public class MappingCassandraConverterMappedTupleUnitTests { - @Rule public final ExpectedException expectedException = ExpectedException.none(); + CassandraMappingContext mappingContext; + + MappingCassandraConverter mappingCassandraConverter; Row rowMock; - CassandraMappingContext mappingContext; - MappingCassandraConverter mappingCassandraConverter; - @Before public void setUp() { - mappingContext = new CassandraMappingContext(); - - mappingCassandraConverter = new MappingCassandraConverter(mappingContext); - mappingCassandraConverter.afterPropertiesSet(); + this.mappingContext = new CassandraMappingContext(); + this.mappingCassandraConverter = new MappingCassandraConverter(mappingContext); + this.mappingCassandraConverter.afterPropertiesSet(); } @Test // DATACASS-523 public void shouldReadMappedTupleValue() { - BasicCassandraPersistentEntity entity = mappingContext.getRequiredPersistentEntity(MappedTuple.class); + BasicCassandraPersistentEntity entity = this.mappingContext.getRequiredPersistentEntity(MappedTuple.class); TupleValue value = entity.getTupleType().newValue("hello", 1); - rowMock = RowMockUtil.newRowMock(column("tuple", value, entity.getTupleType())); + this.rowMock = RowMockUtil.newRowMock( + column("name", "Jon Doe", DataType.text()), + column("tuple", value, entity.getTupleType()) + ); - Person person = mappingCassandraConverter.read(Person.class, rowMock); + Person person = this.mappingCassandraConverter.read(Person.class, rowMock); + + assertThat(person).isNotNull(); + assertThat(person.getName()).isEqualTo("Jon Doe"); MappedTuple tuple = person.getTuple(); @@ -83,18 +87,19 @@ public class MappingCassandraConverterMappedTupleUnitTests { public void shouldWriteMappedTuple() { MappedTuple tuple = new MappedTuple("hello", 1); - Person person = new Person(tuple); + Person person = new Person("Jon Doe", tuple); Insert insert = QueryBuilder.insertInto("table"); - mappingCassandraConverter.write(person, insert); + this.mappingCassandraConverter.write(person, insert); - assertThat(insert.toString()).contains("VALUES (('hello',1))"); + assertThat(insert.toString()).contains("VALUES ('Jon Doe',('hello',1))"); } @Data @AllArgsConstructor private static class Person { + String name; MappedTuple tuple; } @@ -102,9 +107,7 @@ public class MappingCassandraConverterMappedTupleUnitTests { @Data @AllArgsConstructor private static class MappedTuple { - @Element(0) String name; @Element(1) int position; } - } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterTupleIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterTupleIntegrationTests.java index 3efc452d6..b27e27de0 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterTupleIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterTupleIntegrationTests.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.*; import lombok.Data; import java.util.Arrays; +import java.util.Collections; import java.util.Currency; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -84,30 +85,30 @@ public class MappingCassandraConverterTupleIntegrationTests extends AbstractSpri } } - @Autowired Session session; @Autowired MappingCassandraConverter converter; + @Autowired Session session; @Before public void setUp() { if (initialized.compareAndSet(false, true)) { - session.execute("DROP TYPE IF EXISTS address;"); - session.execute("DROP TABLE IF EXISTS person;"); + this.session.execute("DROP TYPE IF EXISTS address;"); + this.session.execute("DROP TABLE IF EXISTS person;"); CassandraMappingContext mappingContext = converter.getMappingContext(); CreateUserTypeSpecification createAddress = mappingContext .getCreateUserTypeSpecificationFor(mappingContext.getRequiredPersistentEntity(AddressUserType.class)); - session.execute(CreateUserTypeCqlGenerator.toCql(createAddress)); + this.session.execute(CreateUserTypeCqlGenerator.toCql(createAddress)); CreateTableSpecification createPerson = mappingContext .getCreateTableSpecificationFor(mappingContext.getRequiredPersistentEntity(Person.class)); - session.execute(CreateTableCqlGenerator.toCql(createPerson)); + this.session.execute(CreateTableCqlGenerator.toCql(createPerson)); } else { - session.execute("TRUNCATE person;"); + this.session.execute("TRUNCATE person;"); } } @@ -115,35 +116,39 @@ public class MappingCassandraConverterTupleIntegrationTests extends AbstractSpri public void shouldInsertRowWithComplexTuple() { Person person = new Person(); + person.setId("foo"); - MappedTuple tuple = new MappedTuple(); AddressUserType userType = new AddressUserType(); + userType.setZip("myzip"); + + MappedTuple tuple = new MappedTuple(); + tuple.setAddressUserType(userType); tuple.setCurrency(Arrays.asList(Currency.getInstance("EUR"), Currency.getInstance("USD"))); tuple.setName("bar"); person.setMappedTuple(tuple); - person.setMappedTuples(Arrays.asList(tuple)); + person.setMappedTuples(Collections.singletonList(tuple)); Insert insert = QueryBuilder.insertInto("person"); - converter.write(person, insert); - session.execute(insert); + this.converter.write(person, insert); + this.session.execute(insert); } @Test // DATACASS-523 public void shouldReadRowWithComplexTuple() { - session.execute("INSERT INTO person (id,mappedtuple,mappedtuples) VALUES (" + // - "'foo'," // + this.session.execute("INSERT INTO person (id,mappedtuple,mappedtuples) VALUES (" + + "'foo'," // + "({zip:'myzip'},['EUR','USD'],'bar')," // + "[({zip:'myzip'},['EUR','USD'],'bar')]);\n"); - ResultSet resultSet = session.execute("SELECT * FROM person;"); + ResultSet resultSet = this.session.execute("SELECT * FROM person;"); - Person person = converter.read(Person.class, resultSet.one()); + Person person = this.converter.read(Person.class, resultSet.one()); assertThat(person.getMappedTuples()).hasSize(1); assertThat(person.getMappedTuple()).isNotNull(); diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/QueryMapperUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/QueryMapperUnitTests.java index b49e5ce88..258c69962 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/QueryMapperUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/QueryMapperUnitTests.java @@ -15,11 +15,9 @@ */ package org.springframework.data.cassandra.core.convert; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - -import lombok.AllArgsConstructor; +import static org.mockito.Mockito.when; import java.util.Collection; import java.util.Collections; @@ -28,11 +26,14 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import lombok.AllArgsConstructor; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.annotation.Id; import org.springframework.data.cassandra.core.cql.CqlIdentifier; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; @@ -70,14 +71,17 @@ import com.datastax.driver.core.UserType; public class QueryMapperUnitTests { CassandraMappingContext mappingContext = new CassandraMappingContext(); + CassandraPersistentEntity persistentEntity; + MappingCassandraConverter cassandraConverter; + QueryMapper queryMapper; - @Mock UserTypeResolver userTypeResolver; - UserType userType = UserTypeBuilder.forName("address").withField("street", DataType.varchar()).build(); + @Mock UserTypeResolver userTypeResolver; + @Before public void before() { @@ -333,18 +337,22 @@ public class QueryMapperUnitTests { Filter filter = Filter.from(Criteria.where("tuple").is(tuple)); - Filter mappedObject = queryMapper.getMappedObject(filter, mappingContext.getRequiredPersistentEntity(Person.class)); + Filter mappedObject = this.queryMapper.getMappedObject(filter, + this.mappingContext.getRequiredPersistentEntity(Person.class)); + + TupleValue tupleValue = this.mappingContext.getRequiredPersistentEntity(MappedTuple.class) + .getTupleType().newValue(); - TupleValue tupleValue = mappingContext.getRequiredPersistentEntity(MappedTuple.class).getTupleType().newValue(); tupleValue.setString(0, "foo"); + assertThat(mappedObject).contains(Criteria.where("tuple").is(tupleValue)); } @Test(expected = IllegalArgumentException.class) // DATACASS-523 public void referencingTupleElementsInQueryShouldFail() { - queryMapper.getMappedObject(Filter.from(Criteria.where("tuple.zip").is("")), - mappingContext.getRequiredPersistentEntity(Person.class)); + this.queryMapper.getMappedObject(Filter.from(Criteria.where("tuple.zip").is("123")), + this.mappingContext.getRequiredPersistentEntity(Person.class)); } static class Person { @@ -367,14 +375,12 @@ public class QueryMapperUnitTests { @Tuple @AllArgsConstructor static class MappedTuple { - @Element(0) String zip; } @UserDefinedType @AllArgsConstructor static class Address { - String street; } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/UpdateMapperUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/UpdateMapperUnitTests.java index 0fe1c12ca..af3306d68 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/UpdateMapperUnitTests.java @@ -15,11 +15,8 @@ */ package org.springframework.data.cassandra.core.convert; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import lombok.AllArgsConstructor; -import lombok.Data; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; import java.util.Collections; import java.util.Currency; @@ -27,11 +24,15 @@ import java.util.List; import java.util.Map; import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Data; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.annotation.Id; import org.springframework.data.cassandra.core.cql.CqlIdentifier; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; @@ -56,15 +57,19 @@ import com.datastax.driver.core.UserType; public class UpdateMapperUnitTests { CassandraMappingContext mappingContext = new CassandraMappingContext(); - CassandraPersistentEntity persistentEntity; - MappingCassandraConverter cassandraConverter; - UpdateMapper updateMapper; - @Mock UserTypeResolver userTypeResolver; + CassandraPersistentEntity persistentEntity; Currency currency = Currency.getInstance("EUR"); + + MappingCassandraConverter cassandraConverter; + + UpdateMapper updateMapper; + UserType manufacturer = UserTypeBuilder.forName("manufacturer").withField("name", DataType.varchar()).build(); + @Mock UserTypeResolver userTypeResolver; + @Before public void before() { @@ -226,7 +231,8 @@ public class UpdateMapperUnitTests { @Test // DATACASS-523 public void shouldMapTuple() { - Update update = updateMapper.getMappedObject(Update.empty().set("tuple", new MappedTuple("foo")), persistentEntity); + Update update = this.updateMapper.getMappedObject(Update.empty().set("tuple", new MappedTuple("foo")), + this.persistentEntity); assertThat(update.getUpdateOperations()).hasSize(1); assertThat(update.toString()).isEqualTo("tuple = ('foo')"); @@ -234,7 +240,7 @@ public class UpdateMapperUnitTests { @Test(expected = IllegalArgumentException.class) // DATACASS-523 public void referencingTupleElementsInQueryShouldFail() { - updateMapper.getMappedObject(Update.empty().set("tuple.zip", "bar"), persistentEntity); + this.updateMapper.getMappedObject(Update.empty().set("tuple.zip", "bar"), this.persistentEntity); } static class Person { diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntityUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntityUnitTests.java index de3bcb23c..09fbb0999 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntityUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentEntityUnitTests.java @@ -15,9 +15,13 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -29,6 +33,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.beans.DirectFieldAccessor; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AliasFor; @@ -51,17 +56,20 @@ public class BasicCassandraPersistentEntityUnitTests { @Test public void subclassInheritsAtDocumentAnnotation() { - BasicCassandraPersistentEntity entity = new BasicCassandraPersistentEntity<>( - ClassTypeInformation.from(Notification.class)); + BasicCassandraPersistentEntity entity = + new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(Notification.class)); + assertThat(entity.getTableName().toCql()).isEqualTo("messages"); } @Test public void evaluatesSpELExpression() { - BasicCassandraPersistentEntity entity = new BasicCassandraPersistentEntity<>( - ClassTypeInformation.from(Area.class)); - entity.setApplicationContext(context); + BasicCassandraPersistentEntity entity = + new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(Area.class)); + + entity.setApplicationContext(this.context); + assertThat(entity.getTableName().toCql()).isEqualTo("a123"); } @@ -71,8 +79,8 @@ public class BasicCassandraPersistentEntityUnitTests { TableNameHolderThingy bean = new TableNameHolderThingy(); bean.tableName = "my_user_line"; - when(context.getBean("tableNameHolderThingy")).thenReturn(bean); - when(context.containsBean("tableNameHolderThingy")).thenReturn(true); + when(this.context.getBean("tableNameHolderThingy")).thenReturn(bean); + when(this.context.containsBean("tableNameHolderThingy")).thenReturn(true); BasicCassandraPersistentEntity entity = new BasicCassandraPersistentEntity<>( ClassTypeInformation.from(UserLine.class)); @@ -84,32 +92,34 @@ public class BasicCassandraPersistentEntityUnitTests { @Test public void setForceQuoteCallsSetTableName() { - BasicCassandraPersistentEntity entitySpy = spy( - new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(Message.class))); + BasicCassandraPersistentEntity entitySpy = + spy(new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(Message.class))); - DirectFieldAccessor dfa = new DirectFieldAccessor(entitySpy); + DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(entitySpy); entitySpy.setTableName(CqlIdentifier.of("Messages", false)); - assertThat((Optional) dfa.getPropertyValue("forceQuote")).isNotPresent(); + assertThat(directFieldAccessor.getPropertyValue("forceQuote")).isNull(); entitySpy.setForceQuote(true); - assertThat((Optional) dfa.getPropertyValue("forceQuote")).contains(true); + assertThat(directFieldAccessor.getPropertyValue("forceQuote")).isEqualTo(true); verify(entitySpy, times(2)).setTableName(isA(CqlIdentifier.class)); } @Test public void setForceQuoteDoesNothing() { - BasicCassandraPersistentEntity entitySpy = spy( - new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(Message.class))); - DirectFieldAccessor dfa = new DirectFieldAccessor(entitySpy); - dfa.setPropertyValue("forceQuote", Optional.of(true)); + BasicCassandraPersistentEntity entitySpy = + spy(new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(Message.class))); + + DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(entitySpy); + + directFieldAccessor.setPropertyValue("forceQuote", true); entitySpy.setForceQuote(true); - assertThat((Optional) dfa.getPropertyValue("forceQuote")).contains(true); + assertThat(directFieldAccessor.getPropertyValue("forceQuote")).isEqualTo(true); verify(entitySpy, never()).setTableName(isA(CqlIdentifier.class)); } @@ -117,8 +127,8 @@ public class BasicCassandraPersistentEntityUnitTests { @Test // DATACASS-172 public void isUserDefinedTypeShouldReturnFalse() { - BasicCassandraPersistentEntity entity = new BasicCassandraPersistentEntity<>( - ClassTypeInformation.from(UserLine.class)); + BasicCassandraPersistentEntity entity = + new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(UserLine.class)); assertThat(entity.isUserDefinedType()).isFalse(); } @@ -126,8 +136,8 @@ public class BasicCassandraPersistentEntityUnitTests { @Test // DATACASS-259 public void shouldConsiderComposedTableAnnotation() { - BasicCassandraPersistentEntity entity = new BasicCassandraPersistentEntity<>( - ClassTypeInformation.from(TableWithComposedAnnotation.class)); + BasicCassandraPersistentEntity entity = + new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(TableWithComposedAnnotation.class)); assertThat(entity.getTableName()).isEqualTo(CqlIdentifier.of("mytable", true)); } @@ -135,8 +145,8 @@ public class BasicCassandraPersistentEntityUnitTests { @Test // DATACASS-259 public void shouldConsiderComposedPrimaryKeyClassAnnotation() { - BasicCassandraPersistentEntity entity = new BasicCassandraPersistentEntity<>( - ClassTypeInformation.from(PrimaryKeyClassWithComposedAnnotation.class)); + BasicCassandraPersistentEntity entity = + new BasicCassandraPersistentEntity<>(ClassTypeInformation.from(PrimaryKeyClassWithComposedAnnotation.class)); assertThat(entity.isCompositePrimaryKey()).isTrue(); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java index 06f49789e..fca6173db 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java @@ -15,7 +15,7 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -24,6 +24,7 @@ import java.util.Date; import java.util.UUID; import org.junit.Test; + import org.springframework.core.annotation.AliasFor; import org.springframework.data.cassandra.core.cql.CqlIdentifier; import org.springframework.data.mapping.model.Property; diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntityUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntityUnitTests.java index 991f36b0b..6f858aa26 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntityUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTupleEntityUnitTests.java @@ -15,8 +15,11 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.anyList; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Arrays; @@ -27,6 +30,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.annotation.Transient; import org.springframework.data.mapping.MappingException; @@ -49,13 +53,15 @@ public class BasicCassandraPersistentTupleEntityUnitTests { @Before public void before() { - mappingContext.setTupleTypeFactory(tupleTypeFactory); + this.mappingContext.setTupleTypeFactory(tupleTypeFactory); } @Test // DATACASS-523 public void shouldCreatePersistentTupleEntity() { - BasicCassandraPersistentEntity entity = mappingContext.getRequiredPersistentEntity(Address.class); + BasicCassandraPersistentEntity entity = this.mappingContext.getRequiredPersistentEntity(Address.class); + + assertThat(entity).isInstanceOf(BasicCassandraPersistentTupleEntity.class); entity.verify(); } @@ -65,12 +71,11 @@ public class BasicCassandraPersistentTupleEntityUnitTests { List propertyNames = new ArrayList<>(); - BasicCassandraPersistentEntity entity = mappingContext.getRequiredPersistentEntity(Address.class); + BasicCassandraPersistentEntity entity = this.mappingContext.getRequiredPersistentEntity(Address.class); + entity.verify(); - entity.forEach(it -> { - propertyNames.add(it.getName()); - }); + entity.forEach(it -> propertyNames.add(it.getName())); assertThat(propertyNames).containsSequence("street", "city", "sortOrder"); } @@ -78,10 +83,11 @@ public class BasicCassandraPersistentTupleEntityUnitTests { @Test // DATACASS-523 public void shouldCreateTupleType() { - when(tupleTypeFactory.create(anyList())).thenReturn(TupleType.of(ProtocolVersion.NEWEST_SUPPORTED, + when(this.tupleTypeFactory.create(anyList())).thenReturn(TupleType.of(ProtocolVersion.NEWEST_SUPPORTED, CodecRegistry.DEFAULT_INSTANCE, DataType.text(), DataType.text(), DataType.cint())); - BasicCassandraPersistentEntity entity = mappingContext.getRequiredPersistentEntity(Address.class); + BasicCassandraPersistentEntity entity = this.mappingContext.getRequiredPersistentEntity(Address.class); + entity.verify(); entity.getTupleType(); @@ -92,14 +98,14 @@ public class BasicCassandraPersistentTupleEntityUnitTests { @Test // DATACASS-523 public void shouldReportDuplicateMappings() { - assertThatThrownBy(() -> mappingContext.getRequiredPersistentEntity(DuplicateElement.class)) + assertThatThrownBy(() -> this.mappingContext.getRequiredPersistentEntity(DuplicateElement.class)) .isInstanceOf(MappingException.class).hasMessageContaining("Duplicate ordinal [0]"); } @Test // DATACASS-523 public void shouldReportMissingOrdinalMappings() { - assertThatThrownBy(() -> mappingContext.getRequiredPersistentEntity(MissingElementOrdinals.class)) + assertThatThrownBy(() -> this.mappingContext.getRequiredPersistentEntity(MissingElementOrdinals.class)) .isInstanceOf(MappingException.class).hasMessageContaining("Mapped tuple has no") .hasMessageContaining("for ordinal(s): 0"); } @@ -107,7 +113,7 @@ public class BasicCassandraPersistentTupleEntityUnitTests { @Test // DATACASS-523 public void shouldReportNegativeOrdinalIndex() { - assertThatThrownBy(() -> mappingContext.getRequiredPersistentEntity(NegativeIndex.class)) + assertThatThrownBy(() -> this.mappingContext.getRequiredPersistentEntity(NegativeIndex.class)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Element ordinal must be greater or equal to zero for property [street] in entity"); } @@ -115,7 +121,7 @@ public class BasicCassandraPersistentTupleEntityUnitTests { @Test // DATACASS-523 public void shouldReportNoElements() { - assertThatThrownBy(() -> mappingContext.getRequiredPersistentEntity(NoElements.class)) + assertThatThrownBy(() -> this.mappingContext.getRequiredPersistentEntity(NoElements.class)) .isInstanceOf(MappingException.class) .hasMessageContaining("Mapped tuple contains no persistent elements annotated"); } @@ -123,7 +129,7 @@ public class BasicCassandraPersistentTupleEntityUnitTests { @Test // DATACASS-523 public void shouldReportMissingAnnotations() { - assertThatThrownBy(() -> mappingContext.getRequiredPersistentEntity(MissingAnnotation.class)) + assertThatThrownBy(() -> this.mappingContext.getRequiredPersistentEntity(MissingAnnotation.class)) .isInstanceOf(MappingException.class) .hasMessageContaining("Missing @Element annotation in mapped tuple type for property [street]"); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTuplePropertyUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTuplePropertyUnitTests.java index 3413d8c3d..8ce051b3c 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTuplePropertyUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentTuplePropertyUnitTests.java @@ -15,7 +15,7 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Field; import java.util.Date; @@ -24,6 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.mapping.model.Property; import org.springframework.data.util.ClassTypeInformation; import org.springframework.util.ReflectionUtils; diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContextUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContextUnitTests.java index 686ce02b9..2b98edfa4 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContextUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraMappingContextUnitTests.java @@ -15,8 +15,10 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.Serializable; import java.util.Collection; @@ -27,6 +29,7 @@ import java.util.NoSuchElementException; import org.junit.Before; import org.junit.Test; + import org.springframework.core.convert.converter.Converter; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.annotation.Id; @@ -475,13 +478,14 @@ public class CassandraMappingContextUnitTests { @Test // DATACASS-523 public void shouldCreateMappedTupleType() { - CassandraPersistentEntity persistentEntity = mappingContext.getRequiredPersistentEntity(MappedTuple.class); + CassandraPersistentEntity persistentEntity = + this.mappingContext.getRequiredPersistentEntity(MappedTuple.class); assertThat(persistentEntity).isInstanceOf(BasicCassandraPersistentTupleEntity.class); - assertThat(mappingContext.getUserDefinedTypeEntities()).isEmpty(); - assertThat(mappingContext.getPersistentEntities()).hasSize(1); - assertThat(mappingContext.getTableEntities()).isEmpty(); + assertThat(this.mappingContext.getUserDefinedTypeEntities()).isEmpty(); + assertThat(this.mappingContext.getPersistentEntities()).hasSize(1); + assertThat(this.mappingContext.getTableEntities()).isEmpty(); } @Test // DATACASS-172 diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentPropertyComparatorUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentPropertyComparatorUnitTests.java index 40d038dd2..224045b79 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentPropertyComparatorUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CassandraPersistentPropertyComparatorUnitTests.java @@ -15,14 +15,18 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; -import static org.springframework.data.cassandra.core.mapping.CassandraPersistentPropertyComparator.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.springframework.data.cassandra.core.mapping.CassandraPersistentPropertyComparator.INSTANCE; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.cassandra.core.cql.CqlIdentifier; /** diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CreateTableSpecificationBasicCassandraMappingContextUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CreateTableSpecificationBasicCassandraMappingContextUnitTests.java index 25ede49b0..9715b39ae 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CreateTableSpecificationBasicCassandraMappingContextUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/CreateTableSpecificationBasicCassandraMappingContextUnitTests.java @@ -15,12 +15,9 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.IOException; import java.util.ArrayList; @@ -29,8 +26,13 @@ import java.util.List; import java.util.Map; import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + import org.junit.Before; import org.junit.Test; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.cassandra.core.convert.CassandraCustomConversions; diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactoryUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactoryUnitTests.java index ac8af130e..65aae7c4c 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactoryUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/SimpleTupleTypeFactoryUnitTests.java @@ -15,7 +15,8 @@ */ package org.springframework.data.cassandra.core.mapping; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.Collections; @@ -42,10 +43,10 @@ public class SimpleTupleTypeFactoryUnitTests { @Test // DATACASS-523 public void shouldCreateTupleTypes() { - when(cluster.getMetadata()).thenReturn(metadata); + when(this.cluster.getMetadata()).thenReturn(this.metadata); - new SimpleTupleTypeFactory(cluster).create(DataType.varchar()); + new SimpleTupleTypeFactory(this.cluster).create(DataType.varchar()); - verify(metadata).newTupleType(Collections.singletonList(DataType.varchar())); + verify(this.metadata).newTupleType(Collections.singletonList(DataType.varchar())); } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/util/RowMockUtil.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/util/RowMockUtil.java index 8e752db1d..6da082cfc 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/util/RowMockUtil.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/util/RowMockUtil.java @@ -17,7 +17,8 @@ package org.springframework.data.cassandra.test.util; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.util.Arrays; @@ -41,46 +42,49 @@ public class RowMockUtil { * @param columns * @return */ - public static Row newRowMock(final Column... columns) { + public static Row newRowMock(Column... columns) { Assert.notNull(columns, "Columns must not be null"); - Row rowMock = mock(Row.class); - ColumnDefinitions columnDefinitionsMock = mock(ColumnDefinitions.class); + Row mockRow = mock(Row.class); - when(rowMock.getColumnDefinitions()).thenReturn(columnDefinitionsMock); + ColumnDefinitions mockColumnDefinitions = mock(ColumnDefinitions.class); - when(columnDefinitionsMock.contains(anyString())).thenAnswer(invocation -> Arrays.stream(columns) + when(mockRow.getColumnDefinitions()).thenReturn(mockColumnDefinitions); + + when(mockColumnDefinitions.contains(anyString())).thenAnswer(invocation -> Arrays.stream(columns) .anyMatch(column -> column.name.equalsIgnoreCase((String) invocation.getArguments()[0]))); - when(columnDefinitionsMock.getIndexOf(anyString())).thenAnswer(invocation -> { + when(mockColumnDefinitions.getIndexOf(anyString())).thenAnswer(invocation -> { int counter = 0; + for (Column column : columns) { if (column.name.equalsIgnoreCase((String) invocation.getArguments()[0])) { return counter; } + counter++; } return -1; }); - when(columnDefinitionsMock.getType(anyInt())) + when(mockColumnDefinitions.getType(anyInt())) .thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].type); - when(rowMock.getObject(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - when(rowMock.getString(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - when(rowMock.getDate(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - when(rowMock.getBool(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - when(rowMock.getInet(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - when(rowMock.getTimestamp(anyInt())) - .thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - when(rowMock.getUUID(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - when(rowMock.getTupleValue(anyInt())) + when(mockRow.getBool(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); + when(mockRow.getDate(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); + when(mockRow.getInet(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); + when(mockRow.getObject(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); + when(mockRow.getString(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); + when(mockRow.getTimestamp(anyInt())) .thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); + when(mockRow.getTupleValue(anyInt())) + .thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); + when(mockRow.getUUID(anyInt())).thenAnswer(invocation -> columns[(Integer) invocation.getArguments()[0]].value); - return rowMock; + return mockRow; } /** @@ -111,5 +115,4 @@ public class RowMockUtil { this.type = type; } } - } diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 971cc97a3..ca084add1 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -415,7 +415,7 @@ thus allowing the name to be different than the field name of the class. Types are derived from the property declaration by default. * `@UserDefinedType` - applied at the type level to specify a Cassandra User-defined Data Type (UDT). Types are derived from the declaration by default. -* `@Tuple` - applied at the type level to use a type as mapped tuple. +* `@Tuple` - applied at the type level to use a type as a mapped tuple. * `@Element` - applied at the field level to specify element/field ordinals within a mapped tuple. Types are derived from the property declaration by default.