DATACASS-487 - Polish.

This commit is contained in:
John Blum
2018-02-02 17:07:31 -08:00
parent 1f0c168470
commit 5414d51371
12 changed files with 400 additions and 323 deletions

View File

@@ -19,6 +19,7 @@ import java.util.List;
import org.springframework.data.cassandra.core.cql.CqlIdentifier;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.ColumnDefinitions;
@@ -51,50 +52,83 @@ public class ColumnReader {
* Returns the row's column value.
*/
@Nullable
public Object get(CqlIdentifier name) {
return get(name.toCql());
public Object get(CqlIdentifier columnName) {
return get(columnName.toCql());
}
/**
* Returns the row's column value.
*/
@Nullable
public Object get(String name) {
return get(getColumnIndex(name));
public Object get(String columnName) {
return get(getColumnIndex(columnName));
}
/**
* Read data from a Column using the {@code index}.
* Read data from Column at the given {@code index}.
*
* @param index
* @return
* @param columnIndex {@link Integer#TYPE index} of the Column.
* @return the value of the Column in at index in the Row, or {@literal null} if the Column contains no value.
*/
@Nullable
public Object get(int index) {
public Object get(int columnIndex) {
if (row.isNull(index)) {
if (row.isNull(columnIndex)) {
return null;
}
DataType type = columns.getType(index);
DataType type = columns.getType(columnIndex);
if (type.isCollection()) {
return getCollection(index, type);
return getCollection(columnIndex, type);
}
if (Name.TUPLE.equals(type.getName())) {
return row.getTupleValue(index);
return row.getTupleValue(columnIndex);
}
if (Name.UDT.equals(type.getName())) {
return row.getUDTValue(index);
return row.getUDTValue(columnIndex);
}
return row.getObject(index);
return row.getObject(columnIndex);
}
/**
* Returns the row's column value as an instance of the given type.
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@Nullable
public <T> T get(CqlIdentifier columnName, Class<T> requestedType) {
return get(columnName.toCql(), requestedType);
}
/**
* Returns the row's column value as an instance of the given type.
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@Nullable
public <T> T get(String columnName, Class<T> requestedType) {
return get(getColumnIndex(columnName), requestedType);
}
/**
* Returns the row's column value as an instance of the given type.
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@Nullable
public <T> T get(int columnIndex, Class<T> requestedType) {
Object value = get(columnIndex);
return requestedType.cast(value);
}
@Nullable
private Object getCollection(int i, DataType type) {
private Object getCollection(int index, DataType type) {
List<DataType> collectionTypes = type.getTypeArguments();
@@ -102,71 +136,36 @@ public class ColumnReader {
if (collectionTypes.size() == 1) {
DataType valueType = collectionTypes.get(0);
TypeCodec<Object> typeCodec = codecRegistry.codecFor(valueType);
if (type.equals(DataType.list(valueType))) {
return row.getList(i, typeCodec.getJavaType().getRawType());
return row.getList(index, typeCodec.getJavaType().getRawType());
}
if (type.equals(DataType.set(valueType))) {
return row.getSet(i, typeCodec.getJavaType().getRawType());
return row.getSet(index, typeCodec.getJavaType().getRawType());
}
}
// Map
if (type.getName() == Name.MAP) {
return row.getObject(i);
return row.getObject(index);
}
throw new IllegalStateException("Unknown Collection type encountered. Valid collections are Set, List and Map.");
throw new IllegalStateException("Unknown Collection type encountered; valid collections are List, Set and Map.");
}
private int getColumnIndex(String columnName) {
int index = columns.getIndexOf(columnName);
Assert.isTrue(index > -1, String.format("Column [%s] does not exist in table", columnName));
return index;
}
public Row getRow() {
return row;
}
/**
* Returns the row's column value as an instance of the given type.
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@Nullable
public <T> T get(CqlIdentifier name, Class<T> requestedType) {
return get(getColumnIndex(name.toCql()), requestedType);
}
/**
* Returns the row's column value as an instance of the given type.
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@Nullable
public <T> T get(String name, Class<T> requestedType) {
return get(columns.getIndexOf(name), requestedType);
}
/**
* Returns the row's column value as an instance of the given type.
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@Nullable
public <T> T get(int i, Class<T> requestedType) {
Object o = get(i);
if (o == null) {
return null;
}
return requestedType.cast(o);
}
private int getColumnIndex(String name) {
int indexOf = columns.getIndexOf(name);
if (indexOf == -1) {
throw new IllegalArgumentException("Column does not exist in Cassandra table: " + name);
}
return indexOf;
}
}

View File

@@ -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;
@@ -24,8 +22,8 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
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;
@@ -56,6 +54,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;
@@ -116,6 +117,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
private static CassandraMappingContext createMappingContext() {
CassandraMappingContext mappingContext = new CassandraMappingContext();
mappingContext.setCustomConversions(new CassandraCustomConversions(Collections.emptyList()));
return mappingContext;
@@ -142,7 +144,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
*/
@Override
public CassandraMappingContext getMappingContext() {
return mappingContext;
return this.mappingContext;
}
/**
@@ -173,8 +175,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return getConversionService().convert(row, type);
}
CassandraPersistentEntity<R> persistentEntity = (CassandraPersistentEntity<R>) getMappingContext()
.getRequiredPersistentEntity(typeInfo);
CassandraPersistentEntity<R> persistentEntity =
(CassandraPersistentEntity<R>) getMappingContext().getRequiredPersistentEntity(typeInfo);
return readEntityFromRow(persistentEntity, row);
}
@@ -185,10 +187,11 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
BasicCassandraRowValueProvider rowValueProvider = new BasicCassandraRowValueProvider(row, expressionEvaluator);
PersistentEntityParameterValueProvider<CassandraPersistentProperty> parameterValueProvider = new PersistentEntityParameterValueProvider<>(
entity, new MappingAndConvertingValueProvider(rowValueProvider), null);
PersistentEntityParameterValueProvider<CassandraPersistentProperty> parameterValueProvider =
getParameterValueProvider(entity, rowValueProvider);
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
S instance = instantiator.createInstance(entity, parameterValueProvider);
readPropertiesFromRow(entity, rowValueProvider, getConvertingAccessor(instance, entity));
@@ -200,13 +203,14 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
DefaultSpELExpressionEvaluator expressionEvaluator = new DefaultSpELExpressionEvaluator(udtValue, spELContext);
CassandraUDTValueProvider valueProvider = new CassandraUDTValueProvider(udtValue, CodecRegistry.DEFAULT_INSTANCE,
expressionEvaluator);
CassandraUDTValueProvider valueProvider =
new CassandraUDTValueProvider(udtValue, CodecRegistry.DEFAULT_INSTANCE, expressionEvaluator);
PersistentEntityParameterValueProvider<CassandraPersistentProperty> parameterValueProvider = getParameterValueProvider(
entity, valueProvider);
PersistentEntityParameterValueProvider<CassandraPersistentProperty> parameterValueProvider =
getParameterValueProvider(entity, valueProvider);
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
S instance = instantiator.createInstance(entity, parameterValueProvider);
readProperties(entity, valueProvider, getConvertingAccessor(instance, entity));
@@ -216,8 +220,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
private <S> PersistentEntityParameterValueProvider<CassandraPersistentProperty> getParameterValueProvider(
CassandraPersistentEntity<S> entity, CassandraValueProvider valueProvider) {
return new PersistentEntityParameterValueProvider<>(entity, new MappingAndConvertingValueProvider(valueProvider),
null);
return new PersistentEntityParameterValueProvider<>(entity,
new MappingAndConvertingValueProvider(valueProvider), null);
}
protected void readPropertiesFromRow(CassandraPersistentEntity<?> entity, CassandraRowValueProvider row,
@@ -244,7 +249,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
if (property.isCompositePrimaryKey()) {
CassandraPersistentEntity<?> keyEntity = mappingContext.getRequiredPersistentEntity(property);
CassandraPersistentEntity<?> keyEntity = getMappingContext().getRequiredPersistentEntity(property);
Object key = propertyAccessor.getProperty(property);
if (key == null) {
@@ -270,7 +276,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
protected Object instantiatePrimaryKey(CassandraPersistentEntity<?> entity, CassandraPersistentProperty keyProperty,
CassandraValueProvider propertyProvider) {
return instantiators.getInstantiatorFor(entity).createInstance(entity,
return this.instantiators.getInstantiatorFor(entity).createInstance(entity,
getParameterValueProvider(entity, propertyProvider));
}
@@ -314,6 +320,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Assert.notNull(source, "Value must not be null");
Class<?> beanClassLoaderClass = transformClassToBeanClassLoaderClass(source.getClass());
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(beanClassLoaderClass);
write(source, sink, entity);
@@ -321,9 +328,11 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
@SuppressWarnings("unchecked")
private <T> Class<T> transformClassToBeanClassLoaderClass(Class<T> entity) {
try {
return (Class<T>) ClassUtils.forName(entity.getName(), beanClassLoader);
} catch (ClassNotFoundException | LinkageError e) {
return (Class<T>) ClassUtils.forName(entity.getName(), this.beanClassLoader);
}
catch (ClassNotFoundException | LinkageError ignore) {
return entity;
}
}
@@ -359,6 +368,47 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
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.getColumnName().toCql(), value);
}
insert.value(property.getColumnName().toCql(), value);
}
}
private void writeMapFromWrapper(ConvertingPropertyAccessor accessor, Map<String, Object> insert,
CassandraPersistentEntity<?> entity) {
@@ -380,7 +430,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
continue;
}
CassandraPersistentEntity<?> compositePrimaryKey = mappingContext.getRequiredPersistentEntity(property);
CassandraPersistentEntity<?> compositePrimaryKey =
getMappingContext().getRequiredPersistentEntity(property);
writeMapFromWrapper(getConvertingAccessor(value, compositePrimaryKey), insert, compositePrimaryKey);
continue;
@@ -394,59 +446,21 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
}
}
protected void writeInsertFromWrapper(final ConvertingPropertyAccessor accessor, final Insert insert,
protected void writeUpdateFromObject(Object object, Update update, CassandraPersistentEntity<?> entity) {
writeUpdateFromWrapper(getConvertingAccessor(object, entity), update, entity);
}
protected void writeUpdateFromWrapper(ConvertingPropertyAccessor accessor, Update update,
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 = mappingContext.getRequiredPersistentEntity(property);
writeInsertFromWrapper(getConvertingAccessor(value, compositePrimaryKey), insert, compositePrimaryKey);
continue;
}
if (value == null) {
continue;
}
if (log.isDebugEnabled()) {
log.debug("Adding insert.value [{}] - [{}]", property.getColumnName().toCql(), value);
}
insert.value(property.getColumnName().toCql(), value);
}
}
protected void writeUpdateFromObject(final Object object, final Update update, CassandraPersistentEntity<?> entity) {
writeUpdateFromWrapper(getConvertingAccessor(object, entity), update, entity);
}
protected void writeUpdateFromWrapper(final ConvertingPropertyAccessor accessor, final Update update,
final CassandraPersistentEntity<?> entity) {
for (CassandraPersistentProperty property : entity) {
Object value = getWriteValue(property, accessor);
if (property.isCompositePrimaryKey()) {
CassandraPersistentEntity<?> compositePrimaryKey = mappingContext.getRequiredPersistentEntity(property);
CassandraPersistentEntity<?> compositePrimaryKey =
getMappingContext().getRequiredPersistentEntity(property);
if (value == null) {
continue;
@@ -481,8 +495,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Object value = getWriteValue(property, accessor);
if (log.isDebugEnabled()) {
log.debug("writeUDTValueWhereFromObject Property.type {}, Property.value {}", property.getType().getName(),
value);
log.debug("writeUDTValueWhereFromObject Property.type {}, Property.value {}", property.getType().getName(), value);
}
if (log.isDebugEnabled()) {
@@ -513,7 +526,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
if (id instanceof MapId) {
CassandraPersistentEntity<?> whereEntity = compositeIdProperty != null
? mappingContext.getRequiredPersistentEntity(compositeIdProperty)
? getMappingContext().getRequiredPersistentEntity(compositeIdProperty)
: entity;
return getWhereClauses(MapId.class.cast(id), whereEntity);
@@ -531,8 +544,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
String.format("Cannot use [%s] as composite Id for [%s]", id, entity.getName()));
}
CassandraPersistentEntity<?> compositePrimaryKey = mappingContext
.getRequiredPersistentEntity(compositeIdProperty);
CassandraPersistentEntity<?> compositePrimaryKey =
getMappingContext().getRequiredPersistentEntity(compositeIdProperty);
return getWhereClauses(getConvertingAccessor(id, compositePrimaryKey), compositePrimaryKey);
}
@@ -557,7 +570,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return source;
}
private Collection<Clause> getWhereClauses(final ConvertingPropertyAccessor accessor,
private Collection<Clause> getWhereClauses(ConvertingPropertyAccessor accessor,
CassandraPersistentEntity<?> entity) {
Assert.isTrue(entity.isCompositePrimaryKey(),
@@ -586,7 +599,8 @@ 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());
@@ -647,9 +661,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
*/
private ConvertingPropertyAccessor getConvertingAccessor(Object source, CassandraPersistentEntity<?> entity) {
PersistentPropertyAccessor propertyAccessor = (source instanceof PersistentPropertyAccessor
PersistentPropertyAccessor propertyAccessor = source instanceof PersistentPropertyAccessor
? (PersistentPropertyAccessor) source
: entity.getPropertyAccessor(source));
: entity.getPropertyAccessor(source);
return new ConvertingPropertyAccessor(propertyAccessor, getConversionService());
}
@@ -730,12 +744,23 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Class<?> requestedTargetType = typeInformation != null ? typeInformation.getType() : Object.class;
if (getCustomConversions().hasCustomWriteTarget(value.getClass(), requestedTargetType)) {
return getConversionService().convert(value, getCustomConversions()
.getCustomWriteTarget(value.getClass(), requestedTargetType).orElse(requestedTargetType));
Class<?> resolvedTargetType = getCustomConversions()
.getCustomWriteTarget(value.getClass(), requestedTargetType)
.orElse(requestedTargetType);
return getConversionService().convert(value, resolvedTargetType);
}
if (getCustomConversions().hasCustomWriteTarget(value.getClass())) {
return getConversionService().convert(value, getCustomConversions().getCustomWriteTarget(value.getClass()).get());
Class<?> resolvedTargetType = getCustomConversions()
.getCustomWriteTarget(value.getClass())
.orElseThrow(() -> new IllegalStateException(
String.format("Unable to determined custom write target for value type [%s]",
value.getClass().getName())));
return getConversionService().convert(value, resolvedTargetType);
}
if (getCustomConversions().isSimpleType(value.getClass())) {
@@ -743,7 +768,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
}
TypeInformation<?> type = typeInformation != null ? typeInformation
: ClassTypeInformation.from((Class) value.getClass());
: ClassTypeInformation.from((Class) value.getClass());
if (value instanceof Collection) {
return writeCollectionInternal((Collection<Object>) value, type);
@@ -754,6 +779,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
}
TypeInformation<?> actualType = type.getRequiredActualType();
BasicCassandraPersistentEntity<?> entity = getMappingContext().getPersistentEntity(actualType.getType());
if (entity != null && entity.isUserDefinedType()) {
@@ -771,6 +797,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
private Object writeCollectionInternal(Collection<Object> source, TypeInformation<?> type) {
Collection<Object> converted = CollectionFactory.createCollection(getCollectionType(type), source.size());
TypeInformation<?> actualType = type.getRequiredActualType();
for (Object element : source) {
@@ -788,9 +815,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
TypeInformation<?> valueType = type.getRequiredMapValueType();
for (Entry<Object, Object> entry : source.entrySet()) {
Object key = convertToColumnType(entry.getKey(), keyType);
converted.put(key, convertToColumnType(entry.getValue(), valueType));
converted.put(convertToColumnType(entry.getKey(), keyType),
convertToColumnType(entry.getValue(), valueType));
}
return converted;
@@ -888,20 +914,18 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
if (property.isCompositePrimaryKey()) {
CassandraPersistentEntity<?> keyEntity = mappingContext.getRequiredPersistentEntity(property);
CassandraPersistentEntity<?> keyEntity = getMappingContext().getRequiredPersistentEntity(property);
return instantiatePrimaryKey(keyEntity, property, row);
}
Object value = row.getPropertyValue(property);
if (value == null) {
return null;
}
return convertReadValue(value, property.getTypeInformation());
return value == null ? null : convertReadValue(value, property.getTypeInformation());
}
@Nullable
@SuppressWarnings("unchecked")
private Object convertReadValue(Object value, TypeInformation<?> typeInformation) {
if (getCustomConversions().hasCustomWriteTarget(typeInformation.getRequiredActualType().getType())
@@ -911,7 +935,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Collection<Object> original = (Collection<Object>) value;
Collection<Object> converted = CollectionFactory.createCollection(typeInformation.getType(), original.size());
Collection<Object> converted =
CollectionFactory.createCollection(typeInformation.getType(), original.size());
for (Object element : original) {
converted.add(getConversionService().convert(element, typeInformation.getRequiredActualType().getType()));
@@ -929,8 +954,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return readMapInternal((Map<Object, Object>) value, typeInformation);
}
BasicCassandraPersistentEntity<?> persistentEntity = getMappingContext()
.getPersistentEntity(typeInformation.getRequiredActualType());
BasicCassandraPersistentEntity<?> persistentEntity =
getMappingContext().getPersistentEntity(typeInformation.getRequiredActualType());
if (persistentEntity != null && persistentEntity.isUserDefinedType() && value instanceof UDTValue) {
return readEntityFromUdt(persistentEntity, (UDTValue) value);
@@ -942,84 +967,102 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
/**
* Reads the given {@link Collection} into a collection of the given {@link TypeInformation}.
*
* @param sourceValue must not be {@literal null}.
* @param source must not be {@literal null}.
* @param targetType must not be {@literal null}.
* @return the converted {@link Collection} or array, will never be {@literal null}.
*/
@Nullable
@SuppressWarnings({ "rawtypes", "unchecked" })
private Object readCollectionOrArrayInternal(Collection<?> sourceValue, TypeInformation<?> targetType) {
private Object readCollectionOrArrayInternal(Collection<?> source, TypeInformation<?> targetType) {
Assert.notNull(targetType, "Target type must not be null!");
Assert.notNull(targetType, "Target type must not be null");
Class<?> collectionType = targetType.getType();
Class<?> collectionType = resolveCollectionType(targetType);
Class<?> elementType = resolveElementType(targetType);
TypeInformation<?> componentType = targetType.getComponentType();
Class<?> rawComponentType = componentType != null ? componentType.getType() : List.class;
Collection<Object> collection = targetType.getType().isArray() ? new ArrayList<>()
: CollectionFactory.createCollection(collectionType, elementType, source.size());
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<>()
: CollectionFactory.createCollection(collectionType, rawComponentType, sourceValue.size());
if (sourceValue.isEmpty()) {
return getPotentiallyConvertedSimpleRead(items, collectionType);
if (source.isEmpty()) {
return getPotentiallyConvertedSimpleRead(collection, collectionType);
}
BasicCassandraPersistentEntity<?> entity = getMappingContext().getPersistentEntity(rawComponentType);
BasicCassandraPersistentEntity<?> entity = getMappingContext().getPersistentEntity(elementType);
if (entity != null && entity.isUserDefinedType()) {
for (Object udtValue : sourceValue) {
items.add(readEntityFromUdt(entity, (UDTValue) udtValue));
for (Object udtValue : source) {
collection.add(readEntityFromUdt(entity, (UDTValue) udtValue));
}
} else {
for (Object item : sourceValue) {
items.add(getPotentiallyConvertedSimpleRead(item, rawComponentType));
for (Object element : source) {
collection.add(getPotentiallyConvertedSimpleRead(element, elementType));
}
}
return getPotentiallyConvertedSimpleRead(items, targetType.getType());
return getPotentiallyConvertedSimpleRead(collection, targetType.getType());
}
private Class<?> resolveCollectionType(TypeInformation typeInformation) {
Class<?> collectionType = typeInformation.getType();
return Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
}
private Class<?> resolveElementType(TypeInformation typeInformation) {
TypeInformation<?> componentType = typeInformation.getComponentType();
return componentType != null ? componentType.getType() : Object.class;
}
/**
* Reads the given {@link Map} into a map of the given {@link TypeInformation}.
*
* @param sourceValue must not be {@literal null}.
* @param source must not be {@literal null}.
* @param targetType must not be {@literal null}.
* @return the converted {@link Collection} or array, will never be {@literal null}.
*/
@Nullable
@SuppressWarnings({ "rawtypes", "unchecked" })
private Object readMapInternal(Map<Object, Object> sourceValue, TypeInformation<?> targetType) {
private Object readMapInternal(Map<Object, Object> source, TypeInformation<?> targetType) {
Assert.notNull(targetType, "Target type must not be null!");
Assert.notNull(targetType, "Target type must not be null");
TypeInformation<?> keyType = targetType.getComponentType();
TypeInformation<?> valueType = targetType.getMapValueType();
Class<?> rawKeyType = keyType != null ? keyType.getType() : null;
Map<Object, Object> map = CollectionFactory.createMap(targetType.getType(), rawKeyType, sourceValue.size());
if (sourceValue.isEmpty()) {
Map<Object, Object> map = CollectionFactory.createMap(resolveMapType(targetType), rawKeyType, source.size());
if (source.isEmpty()) {
return map;
}
for (Entry<Object, Object> entry : sourceValue.entrySet()) {
for (Entry<Object, Object> entry : source.entrySet()) {
Object key = entry.getKey();
if (rawKeyType != null && !rawKeyType.isAssignableFrom(key.getClass())) {
if (key != null && rawKeyType != null && !rawKeyType.isAssignableFrom(key.getClass())) {
key = convertReadValue(key, keyType);
}
Object value = entry.getValue();
map.put(key, convertReadValue(value, valueType));
}
return map;
}
private Class<?> resolveMapType(TypeInformation<?> typeInformation) {
Class<?> mapType = typeInformation.getType();
return Map.class.isAssignableFrom(mapType) ? mapType : Map.class;
}
private TypeCodec<Object> getCodec(CassandraPersistentProperty property) {
return CodecRegistry.DEFAULT_INSTANCE.codecFor(mappingContext.getDataType(property));
}
@@ -1041,7 +1084,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
*/
@Override
public boolean hasProperty(CassandraPersistentProperty property) {
return parent.hasProperty(property);
return this.parent.hasProperty(property);
}
/* (non-Javadoc)
@@ -1051,7 +1094,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
@Override
@SuppressWarnings("unchecked")
public <T> T getPropertyValue(CassandraPersistentProperty property) {
return (T) getReadValue(parent, property);
return (T) getReadValue(this.parent, property);
}
}
}

View File

@@ -127,8 +127,8 @@ public class UpdateMapper extends QueryMapper {
Assert.state(op.getValue() != null,
() -> String.format("SetAtKeyOp for %s attempts to set null", field.getProperty()));
Optional<? extends TypeInformation<?>> typeInformation = field.getProperty()
.map(PersistentProperty::getTypeInformation);
Optional<? extends TypeInformation<?>> typeInformation =
field.getProperty().map(PersistentProperty::getTypeInformation);
Optional<TypeInformation<?>> keyType = typeInformation.map(TypeInformation::getComponentType);
Optional<TypeInformation<?>> valueType = typeInformation.map(TypeInformation::getMapValueType);
@@ -162,8 +162,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());

View File

@@ -45,7 +45,6 @@ import org.springframework.data.cassandra.core.mapping.UserTypeUtil.FrozenLitera
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.convert.CustomConversions.StoreConversions;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.AbstractMappingContext;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.Property;
@@ -78,32 +77,34 @@ public class CassandraMappingContext
extends AbstractMappingContext<BasicCassandraPersistentEntity<?>, CassandraPersistentProperty>
implements ApplicationContextAware, BeanClassLoaderAware {
private CassandraPersistentEntityMetadataVerifier verifier = new CompositeCassandraPersistentEntityMetadataVerifier();
private @Nullable ApplicationContext applicationContext;
private CustomConversions customConversions = new CustomConversions(
StoreConversions.of(CassandraSimpleTypeHolder.HOLDER), Collections.emptyList());
private @Nullable ClassLoader beanClassLoader;
private CassandraPersistentEntityMetadataVerifier verifier =
new CompositeCassandraPersistentEntityMetadataVerifier();
private CustomConversions customConversions =
new CustomConversions(StoreConversions.of(CassandraSimpleTypeHolder.HOLDER), Collections.emptyList());
private Mapping mapping = new Mapping();
private @Nullable UserTypeResolver userTypeResolver;
private @Nullable ApplicationContext applicationContext;
private @Nullable ClassLoader beanClassLoader;
// caches
private final Map<CqlIdentifier, Set<CassandraPersistentEntity<?>>> entitySetsByTableName = new HashMap<>();
private final Set<BasicCassandraPersistentEntity<?>> userDefinedTypes = new HashSet<>();
private final Set<BasicCassandraPersistentEntity<?>> tableEntities = new HashSet<>();
private final Set<BasicCassandraPersistentEntity<?>> userDefinedTypes = new HashSet<>();
/**
* Create a new {@link CassandraMappingContext}.
*/
public CassandraMappingContext() {
setCustomConversions(new CustomConversions(
StoreConversions.of(CassandraSimpleTypeHolder.HOLDER), Collections.emptyList()));
StoreConversions storeConversions = StoreConversions.of(CassandraSimpleTypeHolder.HOLDER);
setCustomConversions(new CustomConversions(storeConversions, Collections.emptyList()));
setSimpleTypeHolder(CassandraSimpleTypeHolder.HOLDER);
}
@@ -143,7 +144,7 @@ public class CassandraMappingContext
}
catch (ClassNotFoundException cause) {
throw new IllegalStateException(
String.format("Unknown persistent entity name [%s]", entityClassName), cause);
String.format("Unknown persistent entity type name [%s]", entityClassName), cause);
}
}
@@ -463,13 +464,11 @@ public class CassandraMappingContext
CreateUserTypeSpecification specification = CreateUserTypeSpecification.createType(entity.getTableName());
entity.doWithProperties((PropertyHandler<CassandraPersistentProperty>) property -> {
// Use frozen literal to not resolve types from Cassandra.
// At this stage, they might be not created yet.
for (CassandraPersistentProperty property : entity) {
// Use frozen literal to not resolve types from Cassandra; At this stage, they might be not created yet.
specification.field(property.getColumnName(),
getDataTypeWithUserTypeFactory(property, DataTypeProvider.FrozenLiteral));
});
getDataTypeWithUserTypeFactory(property, DataTypeProvider.FrozenLiteral));
}
if (specification.getFields().isEmpty()) {
throw new MappingException(String.format("No fields in user type [%s]", entity.getType()));
@@ -491,16 +490,8 @@ public class CassandraMappingContext
public DataType getDataType(Class<?> type) {
return this.customConversions.getCustomWriteTarget(type)
.map(CassandraSimpleTypeHolder::getDataTypeFor)
.orElseGet(() -> getDataTypeFor(type));
}
@Nullable
private DataType getDataType(@NonNull Class<?> type, DataTypeProvider dataTypeProvider) {
BasicCassandraPersistentEntity<?> entity = getPersistentEntity(type);
return entity != null && entity.isUserDefinedType() ? dataTypeProvider.getDataType(entity) : getDataType(type);
.map(CassandraSimpleTypeHolder::getDataTypeFor)
.orElseGet(() -> getDataTypeFor(type));
}
/**
@@ -556,10 +547,11 @@ public class CassandraMappingContext
return getDataTypeWithUserTypeFactory(property.getTypeInformation(), dataTypeProvider, property::getDataType);
}
private DataType getDataTypeWithUserTypeFactory(TypeInformation<?> typeInformation, DataTypeProvider dataTypeProvider,
Supplier<DataType> fallback) {
private DataType getDataTypeWithUserTypeFactory(TypeInformation<?> typeInformation,
DataTypeProvider dataTypeProvider, Supplier<DataType> fallback) {
BasicCassandraPersistentEntity<?> persistentEntity = getPersistentEntity(typeInformation.getRequiredActualType());
BasicCassandraPersistentEntity<?> persistentEntity =
getPersistentEntity(typeInformation.getRequiredActualType());
if (persistentEntity != null && persistentEntity.isUserDefinedType()) {
@@ -570,17 +562,16 @@ public class CassandraMappingContext
}
}
Optional<DataType> customWriteTarget = customConversions.getCustomWriteTarget(typeInformation.getType())
Optional<DataType> customWriteTarget = this.customConversions
.getCustomWriteTarget(typeInformation.getType())
.map(CassandraSimpleTypeHolder::getDataTypeFor);
DataType dataType = customWriteTarget.orElseGet(() -> {
return customConversions.getCustomWriteTarget(typeInformation.getRequiredActualType().getType()) //
.filter(it -> !typeInformation.isMap()) //
DataType dataType = customWriteTarget.orElseGet(() ->
this.customConversions.getCustomWriteTarget(typeInformation.getRequiredActualType().getType())
.filter(it -> !typeInformation.isMap())
.map(it -> {
if (typeInformation.isCollectionLike()) {
if (List.class.isAssignableFrom(typeInformation.getType())) {
return DataType.list(getDataTypeFor(it));
}
@@ -591,16 +582,14 @@ public class CassandraMappingContext
}
return getDataTypeFor(it);
}).orElse(null);
});
if (dataType != null) {
return dataType;
}
}).orElse(null));
return typeInformation.isMap() ? getMapDataType(typeInformation, dataTypeProvider) : fallback.get();
return dataType != null ? dataType
: typeInformation.isMap() ? getMapDataType(typeInformation, dataTypeProvider) : fallback.get();
}
@SuppressWarnings("all")
private DataType getMapDataType(TypeInformation<?> typeInformation, DataTypeProvider dataTypeProvider) {
TypeInformation<?> keyTypeInformation = typeInformation.getComponentType();
@@ -609,16 +598,18 @@ public class CassandraMappingContext
DataType keyType = getDataTypeWithUserTypeFactory(keyTypeInformation, dataTypeProvider, () -> {
DataType type = getDataTypeFor(keyTypeInformation.getType());
if (type != null) {
return type;
}
throw new MappingException("Cannot resolve key type for " + typeInformation + ".");
throw new MappingException(String.format("Cannot resolve key type for [%s]", typeInformation));
});
DataType valueType = getDataTypeWithUserTypeFactory(valueTypeInformation, dataTypeProvider, () -> {
DataType type = getDataTypeFor(valueTypeInformation.getType());
if (type != null) {
return type;
}

View File

@@ -90,21 +90,6 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
super(CASSANDRA_SIMPLE_TYPES, true);
}
/**
* @return the map between {@link Name} and {@link DataType}.
*/
private static Map<Name, DataType> nameToDataType() {
Map<Name, DataType> nameToDataType = new HashMap<>(16);
DataType.allPrimitiveTypes().forEach(dataType -> nameToDataType.put(dataType.getName(), dataType));
nameToDataType.put(Name.VARCHAR, DataType.varchar());
nameToDataType.put(Name.TEXT, DataType.text());
return nameToDataType;
}
/**
* @return the map between {@link Class} and {@link DataType}.
* @param codecRegistry the Cassandra codec registry.
@@ -139,6 +124,21 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
return classToDataType;
}
/**
* @return the map between {@link Name} and {@link DataType}.
*/
private static Map<Name, DataType> nameToDataType() {
Map<Name, DataType> nameToDataType = new HashMap<>(16);
DataType.allPrimitiveTypes().forEach(dataType -> nameToDataType.put(dataType.getName(), dataType));
nameToDataType.put(Name.VARCHAR, DataType.varchar());
nameToDataType.put(Name.TEXT, DataType.text());
return nameToDataType;
}
/**
* Returns a {@link Set} containing all Cassandra primitive types.
*
@@ -147,29 +147,32 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
*/
private static Set<Class<?>> getCassandraPrimitiveTypes(CodecRegistry codecRegistry) {
return DataType.allPrimitiveTypes().stream().map(codecRegistry::codecFor).map(TypeCodec::getJavaType)
.map(TypeToken::getRawType).collect(Collectors.toSet());
}
/**
* Returns the {@link DataType} for a {@link DataType.Name}.
*
* @param name must not be {@literal null}.
* @return the {@link DataType} for {@link DataType.Name}.
*/
public static DataType getDataTypeFor(DataType.Name name) {
return nameToDataType.get(name);
return DataType.allPrimitiveTypes().stream()
.map(codecRegistry::codecFor)
.map(TypeCodec::getJavaType)
.map(TypeToken::getRawType)
.collect(Collectors.toSet());
}
/**
* Returns the default {@link DataType} for a {@link Class}. This method resolves only simple types to a Cassandra
* {@link DataType}. Other types are resolved to {@literal null}.
*
* @param javaClass must not be {@literal null}.
* @param javaType must not be {@literal null}.
* @return the {@link DataType} for {@code javaClass} if resolvable, otherwise {@literal null}.
*/
@Nullable
public static DataType getDataTypeFor(Class<?> javaClass) {
return (javaClass.isEnum() ? DataType.varchar() : classToDataType.get(javaClass));
public static DataType getDataTypeFor(Class<?> javaType) {
return javaType.isEnum() ? DataType.varchar() : classToDataType.get(javaType);
}
/**
* Returns the {@link DataType} for a {@link DataType.Name}.
*
* @param dataTypeName must not be {@literal null}.
* @return the {@link DataType} for {@link DataType.Name}.
*/
public static DataType getDataTypeFor(DataType.Name dataTypeName) {
return nameToDataType.get(dataTypeName);
}
}

View File

@@ -15,14 +15,16 @@
*/
package org.springframework.data.cassandra.core.convert;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.BDDMockito.when;
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.cassandra.core.cql.CqlIdentifier;
import com.datastax.driver.core.ColumnDefinitions;
@@ -52,7 +54,7 @@ public class ColumnReaderUnitTests {
underTest = new ColumnReader(row);
}
@Test
@Test(expected = IllegalArgumentException.class)
public void throwsIllegalArgumentExceptionIfColumnDoesNotExistByName() {
when(columnDefinitions.getIndexOf(NON_EXISTENT_COLUMN)).thenReturn(-1);
@@ -60,34 +62,47 @@ public class ColumnReaderUnitTests {
try {
underTest.get(NON_EXISTENT_COLUMN);
fail("Expected illegal argument exception");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).isEqualTo("Column does not exist in Cassandra table: " + NON_EXISTENT_COLUMN);
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("Column [%s] does not exist in table", NON_EXISTENT_COLUMN);
assertThat(expected).hasNoCause();
throw expected;
}
}
@Test
@Test(expected = IllegalArgumentException.class)
public void throwsIllegalArgumentExceptionIfColumnDoesNotExistByCqlIdentifier() {
when(columnDefinitions.getIndexOf(NON_EXISTENT_COLUMN)).thenReturn(-1);
try {
underTest.get(CqlIdentifier.of(NON_EXISTENT_COLUMN));
fail("Expected illegal argument exception");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).isEqualTo("Column does not exist in Cassandra table: " + NON_EXISTENT_COLUMN);
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("Column [%s] does not exist in table", NON_EXISTENT_COLUMN);
assertThat(expected).hasNoCause();
throw expected;
}
}
@Test
@Test(expected = IllegalArgumentException.class)
public void throwsIllegalArgumentExceptionIfColumnDoesNotExistByCqlIdentifierAndType() {
when(columnDefinitions.getIndexOf(NON_EXISTENT_COLUMN)).thenReturn(-1);
try {
underTest.get(CqlIdentifier.of(NON_EXISTENT_COLUMN), String.class);
fail("Expected illegal argument exception");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).isEqualTo("Column does not exist in Cassandra table: " + NON_EXISTENT_COLUMN);
}
catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage("Column [%s] does not exist in table", NON_EXISTENT_COLUMN);
assertThat(expected).hasNoCause();
throw expected;
}
}
}

View File

@@ -15,11 +15,7 @@
*/
package org.springframework.data.cassandra.core.convert;
import static org.assertj.core.api.Assertions.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.Collections;
@@ -28,9 +24,14 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
@@ -399,11 +400,11 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
@Test // DATACASS-487
public void shouldReadUdtInMap() {
session.execute("INSERT INTO supplier (id,acceptedCurrencies) VALUES ('1',"
+ "{{name:'a good one'}:[{currency:'EUR'},{currency:'USD'}]});");
this.session.execute("INSERT INTO supplier (id, acceptedCurrencies)"
+ " VALUES ('1', {{name:'a good one'}:[{currency:'EUR'},{currency:'USD'}]});");
ResultSet resultSet = session.execute("SELECT * FROM supplier");
Supplier supplier = converter.read(Supplier.class, resultSet.one());
ResultSet resultSet = this.session.execute("SELECT * FROM supplier");
Supplier supplier = this.converter.read(Supplier.class, resultSet.one());
assertThat(supplier.getAcceptedCurrencies()).isNotEmpty();

View File

@@ -15,12 +15,9 @@
*/
package org.springframework.data.cassandra.core.convert;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.cassandra.test.util.RowMockUtil.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.data.cassandra.test.util.RowMockUtil.column;
import java.util.Arrays;
import java.util.Collections;
@@ -28,6 +25,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -35,6 +35,7 @@ import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.cassandra.core.cql.CqlIdentifier;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.core.mapping.UserDefinedType;
@@ -55,7 +56,6 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
* @author Mark Paluch
*/
@RunWith(MockitoJUnitRunner.Silent.class) // there are some unused stubbings in RowMockUtil but they're used in other
// tests
public class MappingCassandraConverterUDTUnitTests {
@Rule public final ExpectedException expectedException = ExpectedException.none();
@@ -90,16 +90,17 @@ public class MappingCassandraConverterUDTUnitTests {
UDTValue value2 = currency.newValue().setString("currency", "USD");
Map<UDTValue, List<UDTValue>> map = new HashMap<>();
map.put(key, Arrays.asList(value1, value2));
rowMock = RowMockUtil
.newRowMock(column("acceptedCurrencies", map, DataType.map(manufacturer, DataType.list(currency))));
rowMock = RowMockUtil.newRowMock(column("acceptedCurrencies", map, DataType.map(manufacturer, DataType.list(currency))));
Supplier supplier = mappingCassandraConverter.read(Supplier.class, rowMock);
assertThat(supplier.getAcceptedCurrencies()).isNotEmpty();
List<Currency> currencies = supplier.getAcceptedCurrencies().get(new Manufacturer("a good one"));
assertThat(currencies).contains(new Currency("EUR"), new Currency("USD"));
}
@@ -110,7 +111,9 @@ public class MappingCassandraConverterUDTUnitTests {
Arrays.asList(new Currency("EUR"), new Currency("USD")));
Supplier supplier = new Supplier(currencies);
Insert insert = QueryBuilder.insertInto("table");
mappingCassandraConverter.write(supplier, insert);
assertThat(insert.toString()).contains("VALUES ({{name:'a good one'}:[{currency:'EUR'},{currency:'USD'}]}");

View File

@@ -15,14 +15,10 @@
*/
package org.springframework.data.cassandra.core.convert;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import static org.springframework.data.cassandra.core.mapping.BasicMapId.*;
import static org.springframework.data.cassandra.test.util.RowMockUtil.*;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeTrue;
import static org.springframework.data.cassandra.core.mapping.BasicMapId.id;
import static org.springframework.data.cassandra.test.util.RowMockUtil.column;
import java.io.Serializable;
import java.math.BigDecimal;
@@ -33,12 +29,26 @@ import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.core.SpringVersion;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.data.cassandra.core.cql.PrimaryKeyType;
@@ -95,10 +105,10 @@ public class MappingCassandraConverterUnitTests {
@Before
public void setUp() throws Exception {
mappingContext = new CassandraMappingContext();
this.mappingContext = new CassandraMappingContext();
mappingCassandraConverter = new MappingCassandraConverter(mappingContext);
mappingCassandraConverter.afterPropertiesSet();
this.mappingCassandraConverter = new MappingCassandraConverter(mappingContext);
this.mappingCassandraConverter.afterPropertiesSet();
}
@Test // DATACASS-260
@@ -907,15 +917,18 @@ public class MappingCassandraConverterUnitTests {
LocalDate date1 = LocalDate.fromYearMonthDay(2018, 1, 1);
LocalDate date2 = LocalDate.fromYearMonthDay(2019, 1, 1);
Map<String, List<LocalDate>> times = Collections.singletonMap("Europe/Paris", Arrays.asList(date1, date2));
rowMock = RowMockUtil.newRowMock(
RowMockUtil.column("times", times, DataType.map(DataType.varchar(), DataType.list(DataType.date()))));
TypeWithConvertedMap converted = mappingCassandraConverter.read(TypeWithConvertedMap.class, rowMock);
TypeWithConvertedMap converted = this.mappingCassandraConverter.read(TypeWithConvertedMap.class, rowMock);
assertThat(converted.times).containsKeys(ZoneId.of("Europe/Paris"));
List<java.time.LocalDate> convertedTimes = converted.times.get(ZoneId.of("Europe/Paris"));
assertThat(convertedTimes).hasSize(2).hasOnlyElementsOfType(java.time.LocalDate.class);
}
@@ -926,13 +939,15 @@ public class MappingCassandraConverterUnitTests {
java.time.LocalDate date2 = java.time.LocalDate.of(2019, 1, 1);
TypeWithConvertedMap typeWithConvertedMap = new TypeWithConvertedMap();
typeWithConvertedMap.times = Collections.singletonMap(ZoneId.of("Europe/Paris"), Arrays.asList(date1, date2));
Insert insert = QueryBuilder.insertInto("table");
mappingCassandraConverter.write(typeWithConvertedMap, insert);
this.mappingCassandraConverter.write(typeWithConvertedMap, insert);
List<Object> values = getValues(insert);
assertThat(values).hasSize(1);
assertThat(values.get(0)).isInstanceOf(Map.class);

View File

@@ -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;
@@ -348,5 +349,4 @@ public class QueryMapperUnitTests {
enum State {
Active, Inactive;
}
}

View File

@@ -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;
@@ -96,6 +97,7 @@ public class UpdateMapperUnitTests {
public void shouldReplaceUdtMap() {
Manufacturer manufacturer = new Manufacturer("foobar");
Map<Manufacturer, Currency> map = Collections.singletonMap(manufacturer, currency);
Update update = updateMapper.getMappedObject(Update.empty().set("manufacturers", map), persistentEntity);
@@ -126,6 +128,7 @@ public class UpdateMapperUnitTests {
public void shouldCreateSetAtUdtKeyUpdate() {
Manufacturer manufacturer = new Manufacturer("foobar");
Update update = updateMapper.getMappedObject(Update.empty().set("manufacturers").atKey(manufacturer).to(currency),
persistentEntity);
@@ -146,6 +149,7 @@ public class UpdateMapperUnitTests {
public void shouldAddUdtToMap() {
Manufacturer manufacturer = new Manufacturer("foobar");
Update update = updateMapper.getMappedObject(Update.empty().addTo("manufacturers").entry(manufacturer, currency),
persistentEntity);

View File

@@ -250,16 +250,19 @@ public class CassandraMappingContextUnitTests {
public void shouldCreateTableForMappedAndConvertedColumn() {
UserType mappedudt = UserTypeBuilder.forName("mappedudt").withField("foo", DataType.ascii()).build();
mappingContext.setUserTypeResolver(typeName -> mappedudt);
mappingContext.setCustomConversions(
new CassandraCustomConversions(Collections.singletonList(HumanToStringConverter.INSTANCE)));
CassandraPersistentEntity<?> persistentEntity = mappingContext
.getRequiredPersistentEntity(WithMapOfMixedTypes.class);
this.mappingContext.setUserTypeResolver(typeName -> mappedudt);
this.mappingContext.setCustomConversions(new CassandraCustomConversions(
Collections.singletonList(HumanToStringConverter.INSTANCE)));
CreateTableSpecification tableSpecification = mappingContext.getCreateTableSpecificationFor(persistentEntity);
CassandraPersistentEntity<?> persistentEntity =
this.mappingContext.getRequiredPersistentEntity(WithMapOfMixedTypes.class);
CreateTableSpecification tableSpecification =
this.mappingContext.getCreateTableSpecificationFor(persistentEntity);
assertThat(tableSpecification.getColumns()).hasSize(2);
ColumnSpecification column = tableSpecification.getColumns().get(1);
assertThat(column.getType().toString()).isEqualTo("map<frozen<mappedudt>, list<text>>");