DATACASS-521 - Apply custom converters for simple types.

We now apply custom converters if a type is considered a simple one before the actual simple type check. This change allows customizing simple type conversion.
This commit is contained in:
Mark Paluch
2018-01-25 11:10:34 +01:00
parent d88dabeced
commit a5281460fb
5 changed files with 106 additions and 12 deletions

View File

@@ -737,15 +737,22 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return null;
}
if (getCustomConversions().isSimpleType(value.getClass())) {
// Doesn't need conversion
return getPotentiallyConvertedSimpleValue(value, typeInformation.getType());
Class<?> requestedTargetType = typeInformation != null ? typeInformation.getType() : Object.class;
if (getCustomConversions().hasCustomWriteTarget(value.getClass(), requestedTargetType)) {
return getConversionService().convert(value,
getCustomConversions().getCustomWriteTarget(value.getClass(), requestedTargetType));
}
if (getCustomConversions().hasCustomWriteTarget(value.getClass())) {
return getConversionService().convert(value, getCustomConversions().getCustomWriteTarget(value.getClass()));
}
if (getCustomConversions().isSimpleType(value.getClass())) {
// Doesn't need conversion
return getPotentiallyConvertedSimpleValue(value, typeInformation.getType());
}
TypeInformation<?> type = (typeInformation != null ? typeInformation : ClassTypeInformation.from(value.getClass()));
TypeInformation<?> actualType = type.getActualType();

View File

@@ -19,8 +19,11 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
/**
* @author Mark Paluch
@@ -34,4 +37,43 @@ public class Person {
@Id String id;
String firstname;
String lastname;
private Kindness kindness;
public enum Kindness {
Nice("+"), Rude("-");
private final String identifier;
Kindness(String identifier) {
this.identifier = identifier;
}
public String getIdentifier() {
return identifier;
}
}
@WritingConverter
public enum KindnessToStringConverter implements Converter<Kindness, String> {
INSTANCE;
@Override
public String convert(Kindness source) {
return source.getIdentifier();
}
}
@ReadingConverter
public enum StringToKindnessConverter implements Converter<String, Kindness> {
INSTANCE;
@Override
public Kindness convert(String source) {
return "+".equals(source) ? Kindness.Nice : Kindness.Rude;
}
}
}

View File

@@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -28,7 +29,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.cassandra.convert.CustomConversions;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.domain.Person.Kindness;
import org.springframework.data.cassandra.domain.Person.KindnessToStringConverter;
import org.springframework.data.cassandra.domain.Person.StringToKindnessConverter;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.CassandraType;
@@ -43,7 +48,6 @@ import com.datastax.driver.core.DataType;
*
* @author Mark Paluch
*/
@SuppressWarnings("Since15")
@RunWith(MockitoJUnitRunner.class)
public class ConvertingParameterAccessorUnitTests {
@@ -56,7 +60,11 @@ public class ConvertingParameterAccessorUnitTests {
@Before
public void setUp() {
CustomConversions conversions = new CustomConversions(
Arrays.asList(KindnessToStringConverter.INSTANCE, StringToKindnessConverter.INSTANCE));
this.converter = new MappingCassandraConverter(new BasicCassandraMappingContext());
this.converter.setCustomConversions(conversions);
this.converter.afterPropertiesSet();
this.convertingParameterAccessor = new ConvertingParameterAccessor(converter, mockParameterAccessor);
}
@@ -69,6 +77,16 @@ public class ConvertingParameterAccessorUnitTests {
assertThat(accessor.getBindableValue(0)).isNull();
}
@Test // DATACASS-521
public void shouldApplyCustomConverters() {
when(mockParameterAccessor.getBindableValue(0)).thenReturn(Kindness.Nice);
ConvertingParameterAccessor accessor = new ConvertingParameterAccessor(converter, mockParameterAccessor);
assertThat(accessor.getBindableValue(0)).isEqualTo("+");
}
@Test // DATACASS-296
@SuppressWarnings({ "rawtypes", "unchecked" })
public void shouldReturnNativeBindableValue() {

View File

@@ -34,8 +34,12 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.data.cassandra.convert.CustomConversions;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.domain.Person.Kindness;
import org.springframework.data.cassandra.domain.Person.KindnessToStringConverter;
import org.springframework.data.cassandra.domain.Person.StringToKindnessConverter;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.UserTypeResolver;
import org.springframework.data.cassandra.repository.Query;
@@ -90,8 +94,12 @@ public class StringBasedCassandraQueryUnitTests {
@Before
public void setUp() {
CustomConversions conversions = new CustomConversions(
Arrays.asList(KindnessToStringConverter.INSTANCE, StringToKindnessConverter.INSTANCE));
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
mappingContext.setCustomConversions(conversions);
mappingContext.setUserTypeResolver(userTypeResolver);
mappingContext.afterPropertiesSet();
when(operations.getConverter()).thenReturn(converter);
when(operations.getSession()).thenReturn(session);
@@ -104,6 +112,7 @@ public class StringBasedCassandraQueryUnitTests {
this.converter = new MappingCassandraConverter(mappingContext);
this.factory = new SpelAwareProxyProjectionFactory();
this.converter.setCustomConversions(conversions);
this.converter.afterPropertiesSet();
}
@@ -344,6 +353,19 @@ public class StringBasedCassandraQueryUnitTests {
assertThat(stringQuery).isEqualTo("SELECT * FROM person WHERE address={city:NULL,country:NULL};");
}
@Test // DATACASS-521
public void convertsEnumValueCorrectly() {
StringBasedCassandraQuery cassandraQuery = getQueryMethod("findByCondition", Kindness.class);
CassandraParameterAccessor accessor = new ConvertingParameterAccessor(converter,
new CassandraParametersParameterAccessor(cassandraQuery.getQueryMethod(), Kindness.Nice));
String query = cassandraQuery.createQuery(accessor);
assertThat(query).isEqualTo("SELECT * FROM person WHERE kindness='+';");
}
private StringBasedCassandraQuery getQueryMethod(String name, Class<?>... args) {
Method method = ReflectionUtils.findMethod(SampleRepository.class, name, args);
CassandraQueryMethod queryMethod = new CassandraQueryMethod(method, metadata, factory,
@@ -420,6 +442,9 @@ public class StringBasedCassandraQueryUnitTests {
@Query("SELECT * FROM person WHERE address=?0;")
Person findByMainAddress(UDTValue udtValue);
@Query("SELECT * FROM person WHERE kindness=?0;")
Person findByCondition(Kindness udtValue);
@ComposedQueryAnnotation
Person findByComposedQueryAnnotation(String lastname);
}
@@ -428,4 +453,5 @@ public class StringBasedCassandraQueryUnitTests {
@Query("SELECT * FROM person WHERE lastname = ?0;")
@interface ComposedQueryAnnotation {
}
}

View File

@@ -31,6 +31,7 @@ import org.springframework.cassandra.test.integration.AbstractKeyspaceCreatingIn
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.domain.Person;
import org.springframework.data.cassandra.domain.Person.Kindness;
import org.springframework.data.cassandra.repository.TypedIdCassandraRepository;
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
import org.springframework.data.repository.query.DefaultEvaluationContextProvider;
@@ -88,10 +89,10 @@ public class SimpleCassandraRepositoryIntegrationTests extends AbstractKeyspaceC
repository.deleteAll();
dave = new Person("42", "Dave", "Matthews");
oliver = new Person("4", "Oliver August", "Matthews");
carter = new Person("49", "Carter", "Beauford");
boyd = new Person("45", "Boyd", "Tinsley");
dave = new Person("42", "Dave", "Matthews", Kindness.Nice);
oliver = new Person("4", "Oliver August", "Matthews", Kindness.Nice);
carter = new Person("49", "Carter", "Beauford", Kindness.Nice);
boyd = new Person("45", "Boyd", "Tinsley", Kindness.Nice);
repository.save(Arrays.asList(oliver, dave, carter, boyd));
}
@@ -165,7 +166,7 @@ public class SimpleCassandraRepositoryIntegrationTests extends AbstractKeyspaceC
repository.deleteAll();
Person person = new Person("36", "Homer", "Simpson");
Person person = new Person("36", "Homer", "Simpson", Kindness.Nice);
repository.insert(person);
@@ -201,7 +202,7 @@ public class SimpleCassandraRepositoryIntegrationTests extends AbstractKeyspaceC
@Test // DATACASS-445
public void saveEntityShouldInsertPartialEntity() {
Person justId = new Person("foo", null, null);
Person justId = new Person("foo", null, null, Kindness.Nice);
Person saved = repository.save(justId);
assertThat(saved).isEqualTo(saved);
@@ -215,7 +216,7 @@ public class SimpleCassandraRepositoryIntegrationTests extends AbstractKeyspaceC
@Test // DATACASS-445
public void saveEntityShouldInsertNewEntity() {
Person person = new Person("36", "Homer", "Simpson");
Person person = new Person("36", "Homer", "Simpson", Kindness.Nice);
Person saved = repository.save(person);
@@ -241,7 +242,7 @@ public class SimpleCassandraRepositoryIntegrationTests extends AbstractKeyspaceC
@Test // DATACASS-445
public void saveIterableOfMixedEntitiesShouldInsertEntity() {
Person person = new Person("36", "Homer", "Simpson");
Person person = new Person("36", "Homer", "Simpson", Kindness.Nice);
dave.setFirstname("Hello, Dave");
dave.setLastname("Bowman");