DATACASS-456 - Polishing.

Switch instance methods to static methods where possible. Reduce method visibility in CassandraMappingContext and CassandraSimpleTypeHolder.

Reorder methods in MappingCassandraConverter. Remove unused CassandraPersistentProperty.isIndexed/getOwner methods and PropertyToFieldNameConverter type.

Remove CassandraPersistentEntity.getApplicationContext() and inject application context to BasicCassandraPersistentProperty from CassandraMappingContext.
This commit is contained in:
Mark Paluch
2017-06-02 16:10:29 +02:00
parent 88d962b261
commit 61d9910048
12 changed files with 149 additions and 196 deletions

View File

@@ -46,7 +46,7 @@ public class CassandraCustomConversions extends org.springframework.data.convert
converters.addAll(CassandraThreeTenBackPortConverters.getConvertersToRegister());
STORE_CONVERTERS = Collections.unmodifiableList(converters);
STORE_CONVERSIONS = StoreConversions.of(new CassandraSimpleTypeHolder(), STORE_CONVERTERS);
STORE_CONVERSIONS = StoreConversions.of(CassandraSimpleTypeHolder.HOLDER, STORE_CONVERTERS);
}
/**

View File

@@ -122,6 +122,22 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
this.spELContext = new SpELContext(this.spELContext, applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang.ClassLoader)
*/
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.convert.CassandraConverter#getMappingContext()
*/
@Override
public CassandraMappingContext getMappingContext() {
return mappingContext;
}
@SuppressWarnings("unchecked")
public <R> R readRow(Class<R> type, Row row) {
@@ -291,6 +307,15 @@ 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 entity;
}
}
@Override
@SuppressWarnings("unchecked")
public void write(Object source, Object sink, CassandraPersistentEntity<?> entity) {
@@ -591,25 +616,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return id;
}
@SuppressWarnings("unchecked")
protected <T> Class<T> transformClassToBeanClassLoaderClass(Class<T> entity) {
try {
return (Class<T>) ClassUtils.forName(entity.getName(), beanClassLoader);
} catch (ClassNotFoundException | LinkageError e) {
return entity;
}
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override
public CassandraMappingContext getMappingContext() {
return mappingContext;
}
/**
* Create a new {@link ConvertingPropertyAccessor} for the given source and entity.
*
@@ -807,7 +813,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return getConversionService().convert(value, target);
}
private Class<?> getCollectionType(TypeInformation<?> type) {
private static Class<?> getCollectionType(TypeInformation<?> type) {
if (type.getType().isInterface()) {
return type.getType();

View File

@@ -98,6 +98,19 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
.orElseGet(this::determineDefaultName);
}
CqlIdentifier determineDefaultName() {
return cqlId(getType().getSimpleName(), false);
}
CqlIdentifier determineName(String value, boolean forceQuote) {
if (!StringUtils.hasText(value)) {
return cqlId(getType().getSimpleName(), forceQuote);
}
return cqlId(spelContext == null ? value : SpelUtils.evaluate(value, spelContext), forceQuote);
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.model.BasicPersistentEntity#addAssociation(org.springframework.data.mapping.Association)
*/
@@ -154,14 +167,6 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
spelContext.setRootObject(context);
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.mapping.CassandraPersistentEntity#getApplicationContext()
*/
@Override
public ApplicationContext getApplicationContext() {
return context;
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.mapping.CassandraPersistentEntity#setForceQuote(boolean)
*/
@@ -224,17 +229,4 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
public UserType getUserType() {
return null;
}
protected CqlIdentifier determineDefaultName() {
return cqlId(getType().getSimpleName(), false);
}
protected CqlIdentifier determineName(String value, boolean forceQuote) {
if (!StringUtils.hasText(value)) {
return cqlId(getType().getSimpleName(), forceQuote);
}
return cqlId(spelContext == null ? value : SpelUtils.evaluate(value, spelContext), forceQuote);
}
}

View File

@@ -81,8 +81,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
* @param simpleTypeHolder mapping of Java [simple|wrapper] types to Cassandra data types.
*/
public BasicCassandraPersistentProperty(Property property, CassandraPersistentEntity<?> owner,
CassandraSimpleTypeHolder simpleTypeHolder) {
SimpleTypeHolder simpleTypeHolder) {
this(property, owner, simpleTypeHolder, null);
}
@@ -100,10 +99,6 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
super(property, owner, simpleTypeHolder);
this.userTypeResolver = userTypeResolver;
if (owner.getApplicationContext() != null) {
setApplicationContext(owner.getApplicationContext());
}
}
/* (non-Javadoc)
@@ -247,12 +242,38 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
return userType;
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.mapping.CassandraPersistentProperty#isIndexed()
*/
@Override
public boolean isIndexed() {
return isAnnotationPresent(Indexed.class);
private DataType getDataTypeFor(DataType.Name dataTypeName) {
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(dataTypeName);
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()));
}
return dataType;
}
private DataType getDataTypeFor(Class<?> javaType) {
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(javaType);
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()));
}
return dataType;
}
private void ensureTypeArguments(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()));
}
}
/* (non-Javadoc)
@@ -291,40 +312,6 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
.filter(primaryKeyColumn -> PrimaryKeyType.CLUSTERED.equals(primaryKeyColumn.type())).isPresent();
}
protected DataType getDataTypeFor(DataType.Name dataTypeName) {
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(dataTypeName);
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()));
}
return dataType;
}
protected DataType getDataTypeFor(Class<?> javaType) {
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(javaType);
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()));
}
return dataType;
}
protected void ensureTypeArguments(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()));
}
}
private CqlIdentifier determineColumnName() {
if (isCompositePrimaryKey()) { // then the id type has @PrimaryKeyClass

View File

@@ -25,6 +25,7 @@ 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;
@@ -103,11 +104,10 @@ public class CassandraMappingContext
processMappingOverrides();
}
@SuppressWarnings("all")
protected void processMappingOverrides() {
private void processMappingOverrides() {
mapping.getEntityMappings().stream() //
.filter(entityMapping -> entityMapping != null) //
.filter(Objects::nonNull) //
.forEach(entityMapping -> {
Class<?> entityClass = getEntityClass(entityMapping.getEntityClassName());
@@ -132,12 +132,13 @@ public class CassandraMappingContext
}
}
protected void processMappingOverrides(CassandraPersistentEntity<?> entity, EntityMapping entityMapping) {
private static void processMappingOverrides(CassandraPersistentEntity<?> entity, EntityMapping entityMapping) {
entityMapping.getPropertyMappings()
.forEach((key, propertyMapping) -> processMappingOverride(entity, propertyMapping));
}
protected void processMappingOverride(CassandraPersistentEntity<?> entity, PropertyMapping mapping) {
private static void processMappingOverride(CassandraPersistentEntity<?> entity, PropertyMapping mapping) {
CassandraPersistentProperty property = entity.getRequiredPersistentProperty(mapping.getPropertyName());
@@ -178,6 +179,11 @@ public class CassandraMappingContext
this.customConversions = customConversions;
}
/**
* Sets the {@link Mapping}.
*
* @param mapping must not be {@literal null}.
*/
public void setMapping(Mapping mapping) {
Assert.notNull(mapping, "Mapping must not be null");
@@ -208,7 +214,6 @@ public class CassandraMappingContext
/**
* @return Returns the verifier.
*/
@SuppressWarnings("unused")
public CassandraPersistentEntityMetadataVerifier getVerifier() {
return verifier;
}
@@ -296,12 +301,20 @@ public class CassandraMappingContext
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.model.MutablePersistentEntity, org.springframework.data.mapping.model.SimpleTypeHolder)
* @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentProperty(org.springframework.data.mapping.model.Property, org.springframework.data.mapping.model.MutablePersistentEntity, org.springframework.data.mapping.model.SimpleTypeHolder)
*/
@Override
protected CassandraPersistentProperty createPersistentProperty(Property property,
BasicCassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
return new BasicCassandraPersistentProperty(property, owner, simpleTypeHolder, userTypeResolver);
BasicCassandraPersistentProperty cassandraProperty = new BasicCassandraPersistentProperty(property, owner,
simpleTypeHolder, userTypeResolver);
if (context != null) {
cassandraProperty.setApplicationContext(context);
}
return cassandraProperty;
}
/**
@@ -331,7 +344,7 @@ public class CassandraMappingContext
return hasMappedUserType(name) || hasReferencedUserType(name);
}
private boolean hasReferencedUserType(final CqlIdentifier identifier) {
private boolean hasReferencedUserType(CqlIdentifier identifier) {
return getPersistentEntities().stream() //
.flatMap(PersistentEntity::getPersistentProperties) //
@@ -559,7 +572,7 @@ public class CassandraMappingContext
* Return the data type for the {@link CassandraPersistentEntity}.
*
* @param entity must not be {@literal null}.
* @return
* @return the {@link DataType}.
*/
abstract DataType getDataType(CassandraPersistentEntity<?> entity);
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.data.cassandra.core.mapping;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.cql.core.CqlIdentifier;
import org.springframework.data.mapping.PersistentEntity;
@@ -69,7 +68,4 @@ public interface CassandraPersistentEntity<T>
* @see UserDefinedType
*/
UserType getUserType();
ApplicationContext getApplicationContext();
}

View File

@@ -18,7 +18,6 @@ package org.springframework.data.cassandra.core.mapping;
import java.util.Optional;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.cql.core.CqlIdentifier;
import org.springframework.data.cql.core.Ordering;
@@ -58,11 +57,6 @@ public interface CassandraPersistentProperty
*/
DataType getDataType();
/**
* Whether the property has a secondary index on this column.
*/
boolean isIndexed();
/**
* Whether the property is a composite primary key.
*/
@@ -86,13 +80,10 @@ public interface CassandraPersistentProperty
*/
boolean isClusterKeyColumn();
@Override
CassandraPersistentEntity<?> getOwner();
/**
* Whether to force-quote the column names of this property.
*
* @param forceQuote
* @param forceQuote {@literal true} to enforce quoting.
* @see CassandraPersistentProperty#getColumnName()
*/
void setForceQuote(boolean forceQuote);
@@ -112,14 +103,4 @@ public interface CassandraPersistentProperty
* @return a boolean indicating whether this property type is a {@link java.util.Map}.
*/
boolean isMapLike();
enum PropertyToFieldNameConverter implements Converter<CassandraPersistentProperty, String> {
INSTANCE;
@Override
public String convert(CassandraPersistentProperty property) {
return property.getColumnName().toCql();
}
}
}

View File

@@ -17,15 +17,12 @@ package org.springframework.data.cassandra.core.mapping;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.DataType;
@@ -77,6 +74,13 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
public static final SimpleTypeHolder HOLDER = new CassandraSimpleTypeHolder();
/**
* Create a new {@link CassandraSimpleTypeHolder} instance.
*/
private CassandraSimpleTypeHolder() {
super(CASSANDRA_SIMPLE_TYPES, true);
}
/**
* @return the map between {@link Name} and {@link DataType}.
*/
@@ -136,7 +140,7 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
/**
* Returns the {@link DataType} for a {@link DataType.Name}.
*
* @param name
* @param name must not be {@literal null}.
* @return
*/
public static DataType getDataTypeFor(DataType.Name name) {
@@ -146,7 +150,7 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
/**
* Returns the default {@link DataType} for a {@link Class}.
*
* @param javaClass
* @param javaClass must not be {@literal null}.
* @return
*/
public static DataType getDataTypeFor(Class<?> javaClass) {
@@ -158,26 +162,4 @@ public class CassandraSimpleTypeHolder extends SimpleTypeHolder {
return classToDataType.get(javaClass);
}
public static DataType.Name[] getDataTypeNamesFrom(List<TypeInformation<?>> arguments) {
DataType.Name[] array = new DataType.Name[arguments.size()];
for (int i = 0; i != array.length; i++) {
TypeInformation<?> typeInfo = arguments.get(i);
DataType dataType = getDataTypeFor(typeInfo.getType());
if (dataType == null) {
throw new InvalidDataAccessApiUsageException(
String.format("Did not find appropriate primitive DataType for type '%s'", typeInfo.getType()));
}
array[i] = dataType.getName();
}
return array;
}
public CassandraSimpleTypeHolder() {
super(CASSANDRA_SIMPLE_TYPES, true);
}
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.data.cassandra.core.mapping;
import java.util.Optional;
import org.springframework.data.cql.core.CqlIdentifier;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.util.TypeInformation;
@@ -63,8 +61,8 @@ public class CassandraUserTypePersistentEntity<T> extends BasicCassandraPersiste
@Override
protected CqlIdentifier determineTableName() {
Optional<UserDefinedType> typeAnnotation = findAnnotation(UserDefinedType.class);
return typeAnnotation.map(userDefinedType -> determineName(userDefinedType.value(), userDefinedType.forceQuote()))
return findAnnotation(UserDefinedType.class) //
.map(userDefinedType -> determineName(userDefinedType.value(), userDefinedType.forceQuote())) //
.orElseGet(super::determineDefaultName);
}

View File

@@ -99,7 +99,7 @@ public class BasicCassandraPersistentPropertyUnitTests {
Field field = ReflectionUtils.findField(type, fieldName);
return new BasicCassandraPersistentProperty(Property.of(field), getEntity(type), new CassandraSimpleTypeHolder());
return new BasicCassandraPersistentProperty(Property.of(field), getEntity(type), CassandraSimpleTypeHolder.HOLDER);
}
private <T> BasicCassandraPersistentEntity<T> getEntity(Class<T> type) {

View File

@@ -43,7 +43,45 @@ import com.datastax.driver.core.DataType;
*/
public class CassandraCompositePrimaryKeyUnitTests {
private static final CassandraSimpleTypeHolder SIMPLE_TYPE_HOLDER = new CassandraSimpleTypeHolder();
CassandraMappingContext context;
CassandraPersistentEntity<?> entity;
CassandraPersistentEntity<?> key;
@Before
public void setup() {
context = new CassandraMappingContext();
entity = context.getRequiredPersistentEntity(ClassTypeInformation.from(TypeWithCompositeKey.class));
key = context.getRequiredPersistentEntity(ClassTypeInformation.from(CompositeKey.class));
}
@Test
public void validateMappingInfo() {
Field field = ReflectionUtils.findField(TypeWithCompositeKey.class, "id");
CassandraPersistentProperty property = new BasicCassandraPersistentProperty(Property.of(field), entity,
CassandraSimpleTypeHolder.HOLDER);
assertThat(property.isIdProperty()).isTrue();
assertThat(property.isCompositePrimaryKey()).isTrue();
CreateTableSpecification spec = context.getCreateTableSpecificationFor(entity);
List<ColumnSpecification> partitionKeyColumns = spec.getPartitionKeyColumns();
assertThat(partitionKeyColumns).hasSize(1);
ColumnSpecification partitionKeyColumn = partitionKeyColumns.get(0);
assertThat(partitionKeyColumn.getName().toCql()).isEqualTo("z");
assertThat(partitionKeyColumn.getKeyType()).isEqualTo(PrimaryKeyType.PARTITIONED);
assertThat(partitionKeyColumn.getType()).isEqualTo(DataType.text());
List<ColumnSpecification> clusteredKeyColumns = spec.getClusteredKeyColumns();
assertThat(clusteredKeyColumns).hasSize(1);
ColumnSpecification clusteredKeyColumn = clusteredKeyColumns.get(0);
assertThat(clusteredKeyColumn.getName().toCql()).isEqualTo("a");
assertThat(clusteredKeyColumn.getKeyType()).isEqualTo(PrimaryKeyType.CLUSTERED);
assertThat(partitionKeyColumn.getType()).isEqualTo(DataType.text());
}
@PrimaryKeyClass
@EqualsAndHashCode
@@ -65,44 +103,4 @@ public class CassandraCompositePrimaryKeyUnitTests {
@Column("message") String text;
}
CassandraMappingContext context;
CassandraPersistentEntity<?> entity;
CassandraPersistentEntity<?> key;
@Before
public void setup() {
context = new CassandraMappingContext();
entity = context.getRequiredPersistentEntity(ClassTypeInformation.from(TypeWithCompositeKey.class));
key = context.getRequiredPersistentEntity(ClassTypeInformation.from(CompositeKey.class));
}
@Test
public void validateMappingInfo() {
Field field = ReflectionUtils.findField(TypeWithCompositeKey.class, "id");
CassandraPersistentProperty property = new BasicCassandraPersistentProperty(Property.of(field), entity,
SIMPLE_TYPE_HOLDER);
assertThat(property.isIdProperty()).isTrue();
assertThat(property.isCompositePrimaryKey()).isTrue();
CreateTableSpecification spec = context.getCreateTableSpecificationFor(entity);
List<ColumnSpecification> partitionKeyColumns = spec.getPartitionKeyColumns();
assertThat(partitionKeyColumns).hasSize(1);
ColumnSpecification partitionKeyColumn = partitionKeyColumns.get(0);
assertThat(partitionKeyColumn.getName().toCql()).isEqualTo("z");
assertThat(partitionKeyColumn.getKeyType()).isEqualTo(PrimaryKeyType.PARTITIONED);
assertThat(partitionKeyColumn.getType()).isEqualTo(DataType.text());
List<ColumnSpecification> clusteredKeyColumns = spec.getClusteredKeyColumns();
assertThat(clusteredKeyColumns).hasSize(1);
ColumnSpecification clusteredKeyColumn = clusteredKeyColumns.get(0);
assertThat(clusteredKeyColumn.getName().toCql()).isEqualTo("a");
assertThat(clusteredKeyColumn.getKeyType()).isEqualTo(PrimaryKeyType.CLUSTERED);
assertThat(partitionKeyColumn.getType()).isEqualTo(DataType.text());
}
}

View File

@@ -69,6 +69,6 @@ public class CompoundPrimaryKeyUnitTests {
}
private CassandraPersistentProperty getPropertyFor(Property property) {
return new BasicCassandraPersistentProperty(property, entity, new CassandraSimpleTypeHolder());
return new BasicCassandraPersistentProperty(property, entity, CassandraSimpleTypeHolder.HOLDER);
}
}