DATACASS-438 - Adapt to moved CustomConversions to Spring Data Commons.
Introduce CassandraCustomConversions extending o.s.d.convert.CustomConversions. Remove o.s.d.cassandra.convert.CustomConversions implementation and utility classes, extend CassandraCustomConversions. Replace references to o.s.d.c.c.CustomConversions with o.s.d.convert.CustomConversions. Adapt tests and MappingCassandraConverter to CassandraCustomConversions. Related ticket: DATACMNS-1035.
This commit is contained in:
@@ -28,7 +28,7 @@ import org.springframework.data.cassandra.config.CassandraEntityClassScanner;
|
||||
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
|
||||
import org.springframework.data.cassandra.config.SchemaAction;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.convert.CassandraCustomConversions;
|
||||
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.core.CassandraAdminOperations;
|
||||
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
|
||||
@@ -36,6 +36,7 @@ import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.SimpleUserTypeResolver;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
|
||||
/**
|
||||
@@ -126,7 +127,7 @@ public abstract class AbstractCassandraConfiguration extends AbstractClusterConf
|
||||
*/
|
||||
@Bean
|
||||
public CustomConversions customConversions() {
|
||||
return new CustomConversions(Collections.emptyList());
|
||||
return new CassandraCustomConversions(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors
|
||||
* Copyright 2013-2017 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
|
||||
/**
|
||||
@@ -34,7 +37,9 @@ import org.springframework.data.convert.EntityInstantiators;
|
||||
public abstract class AbstractCassandraConverter implements CassandraConverter, InitializingBean {
|
||||
|
||||
protected final ConversionService conversionService;
|
||||
protected CustomConversions conversions = new CustomConversions();
|
||||
|
||||
protected CustomConversions conversions = new CassandraCustomConversions(Collections.emptyList());
|
||||
|
||||
protected EntityInstantiators instantiators = new EntityInstantiators();
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Optional;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.convert.EntityConverter;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.CassandraSimpleTypeHolder;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
/**
|
||||
* Value object to capture custom conversion. {@link CassandraCustomConversions} also act as factory for
|
||||
* {@link SimpleTypeHolder}
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
* @see org.springframework.data.convert.CustomConversions
|
||||
* @see SimpleTypeHolder
|
||||
*/
|
||||
public class CassandraCustomConversions extends org.springframework.data.convert.CustomConversions {
|
||||
|
||||
private static final StoreConversions STORE_CONVERSIONS;
|
||||
|
||||
private static final List<Object> STORE_CONVERTERS;
|
||||
|
||||
static {
|
||||
|
||||
List<Object> converters = new ArrayList<>();
|
||||
|
||||
converters.addAll(CassandraConverters.getConvertersToRegister());
|
||||
converters.addAll(CassandraJodaTimeConverters.getConvertersToRegister());
|
||||
converters.addAll(CassandraJsr310Converters.getConvertersToRegister());
|
||||
converters.addAll(CassandraThreeTenBackPortConverters.getConvertersToRegister());
|
||||
|
||||
STORE_CONVERTERS = Collections.unmodifiableList(converters);
|
||||
STORE_CONVERSIONS = StoreConversions.of(new CassandraSimpleTypeHolder(), STORE_CONVERTERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link CassandraCustomConversions} instance registering the given converters.
|
||||
*
|
||||
* @param converters must not be {@literal null}.
|
||||
*/
|
||||
public CassandraCustomConversions(List<?> converters) {
|
||||
super(STORE_CONVERSIONS, converters);
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.data.cassandra.mapping.CassandraSimpleTypeHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Conversion registration information.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.5
|
||||
*/
|
||||
class ConverterRegistration {
|
||||
|
||||
private final ConvertiblePair convertiblePair;
|
||||
|
||||
private final boolean reading;
|
||||
|
||||
private final boolean writing;
|
||||
|
||||
/**
|
||||
* Create a new {@link ConverterRegistration}.
|
||||
*
|
||||
* @param convertiblePair must not be {@literal null}.
|
||||
* @param isReading whether to force to consider the converter for reading.
|
||||
* @param isWriting whether to force to consider the converter for reading.
|
||||
*/
|
||||
public ConverterRegistration(ConvertiblePair convertiblePair, boolean isReading, boolean isWriting) {
|
||||
|
||||
Assert.notNull(convertiblePair, "ConvertiblePair must not be null");
|
||||
|
||||
this.convertiblePair = convertiblePair;
|
||||
this.reading = isReading;
|
||||
this.writing = isWriting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ConverterRegistration} from the given source and target type and read/write flags.
|
||||
*
|
||||
* @param source the source type to be converted from, must not be {@literal null}.
|
||||
* @param target the target type to be converted to, must not be {@literal null}.
|
||||
* @param isReading whether to force to consider the converter for reading.
|
||||
* @param isWriting whether to force to consider the converter for writing.
|
||||
*/
|
||||
public ConverterRegistration(Class<?> source, Class<?> target, boolean isReading, boolean isWriting) {
|
||||
this(new ConvertiblePair(source, target), isReading, isWriting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the converter shall be used for writing.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isWriting() {
|
||||
return writing || (!reading && isSimpleTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the converter shall be used for reading.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isReading() {
|
||||
return reading || (!writing && isSimpleSourceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual conversion pair.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ConvertiblePair getConvertiblePair() {
|
||||
return convertiblePair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the source type is a Cassandra simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSimpleSourceType() {
|
||||
return isCassandraBasicType(convertiblePair.getSourceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the target type is a Cassandra simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSimpleTargetType() {
|
||||
return isCassandraBasicType(convertiblePair.getTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is a type that Cassandra can handle basically.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private static boolean isCassandraBasicType(Class<?> type) {
|
||||
return CassandraSimpleTypeHolder.HOLDER.isSimpleType(type);
|
||||
}
|
||||
}
|
||||
@@ -15,32 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.cassandra.mapping.CassandraSimpleTypeHolder;
|
||||
import org.springframework.data.convert.JodaTimeConverters;
|
||||
import org.springframework.data.convert.Jsr310Converters;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.ThreeTenBackPortConverters;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to capture custom conversion. That is essentially a {@link List} of converters and some additional logic
|
||||
@@ -50,293 +27,18 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.5
|
||||
* @deprecated since 2.0, use {@link CassandraCustomConversions}.
|
||||
*/
|
||||
public class CustomConversions {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CustomConversions.class);
|
||||
private static final String READ_CONVERTER_NOT_SIMPLE = "Registering converter from %s to %s as reading converter although it doesn't convert from a Cassandra supported type! You might wanna check you annotation setup at the converter implementation.";
|
||||
private static final String WRITE_CONVERTER_NOT_SIMPLE = "Registering converter from %s to %s as writing converter although it doesn't convert to a Cassandra supported type! You might wanna check you annotation setup at the converter implementation.";
|
||||
|
||||
private final Set<ConvertiblePair> readingPairs;
|
||||
private final Set<ConvertiblePair> writingPairs;
|
||||
private final CassandraSimpleTypeHolder simpleTypeHolder;
|
||||
|
||||
private final List<Object> converters;
|
||||
|
||||
private final Map<ConvertiblePair, Optional<Class<?>>> customReadTargetTypes;
|
||||
private final Map<ConvertiblePair, Optional<Class<?>>> customWriteTargetTypes;
|
||||
private final Map<Class<?>, Optional<Class<?>>> rawWriteTargetTypes;
|
||||
|
||||
/**
|
||||
* Creates an empty {@link CustomConversions} object.
|
||||
*/
|
||||
CustomConversions() {
|
||||
this(new ArrayList<>());
|
||||
}
|
||||
@Deprecated
|
||||
public class CustomConversions extends CassandraCustomConversions {
|
||||
|
||||
/**
|
||||
* Create a new {@link CustomConversions} instance registering the given converters.
|
||||
*
|
||||
* @param converters
|
||||
*/
|
||||
public CustomConversions(List<?> converters) {
|
||||
private CustomConversions(List<?> converters) {
|
||||
super(converters);
|
||||
|
||||
Assert.notNull(converters, "List of converters must not be null");
|
||||
|
||||
this.readingPairs = new LinkedHashSet<>();
|
||||
this.writingPairs = new LinkedHashSet<>();
|
||||
this.customReadTargetTypes = new ConcurrentHashMap<>();
|
||||
this.customWriteTargetTypes = new ConcurrentHashMap<>();
|
||||
this.rawWriteTargetTypes = new ConcurrentHashMap<>();
|
||||
|
||||
List<Object> toRegister = new ArrayList<>();
|
||||
|
||||
// Add user provided converters to make sure they can override the defaults
|
||||
toRegister.addAll(converters);
|
||||
toRegister.addAll(CassandraConverters.getConvertersToRegister());
|
||||
|
||||
toRegister.addAll(CassandraJodaTimeConverters.getConvertersToRegister());
|
||||
toRegister.addAll(CassandraJsr310Converters.getConvertersToRegister());
|
||||
toRegister.addAll(CassandraThreeTenBackPortConverters.getConvertersToRegister());
|
||||
|
||||
toRegister.addAll(JodaTimeConverters.getConvertersToRegister());
|
||||
toRegister.addAll(Jsr310Converters.getConvertersToRegister());
|
||||
toRegister.addAll(ThreeTenBackPortConverters.getConvertersToRegister());
|
||||
|
||||
toRegister.forEach(this::registerConversion);
|
||||
|
||||
Collections.reverse(toRegister);
|
||||
|
||||
this.converters = Collections.unmodifiableList(toRegister);
|
||||
this.simpleTypeHolder = new CassandraSimpleTypeHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying {@link SimpleTypeHolder}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public SimpleTypeHolder getSimpleTypeHolder() {
|
||||
return simpleTypeHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is considered to be simple. That means it's either a general simple type or we have
|
||||
* a writing {@link Converter} registered for a particular type.
|
||||
*
|
||||
* @see SimpleTypeHolder#isSimpleType(Class)
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public boolean isSimpleType(Class<?> type) {
|
||||
return simpleTypeHolder.isSimpleType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the given {@link GenericConversionService} with the registered converters.
|
||||
*
|
||||
* @param conversionService
|
||||
*/
|
||||
public void registerConvertersIn(GenericConversionService conversionService) {
|
||||
|
||||
for (Object converter : converters) {
|
||||
|
||||
boolean added = false;
|
||||
|
||||
if (converter instanceof Converter) {
|
||||
conversionService.addConverter((Converter<?, ?>) converter);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (converter instanceof ConverterFactory) {
|
||||
conversionService.addConverterFactory((ConverterFactory<?, ?>) converter);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (converter instanceof GenericConverter) {
|
||||
conversionService.addConverter((GenericConverter) converter);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (!added) {
|
||||
throw new IllegalArgumentException(
|
||||
"Given set contains element that is neither Converter nor ConverterFactory!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a conversion for the given converter. Inspects either generics of {@link Converter} and
|
||||
* {@link ConverterFactory} or the {@link ConvertiblePair}s returned by a {@link GenericConverter}.
|
||||
*
|
||||
* @param converter
|
||||
*/
|
||||
private void registerConversion(Object converter) {
|
||||
|
||||
Class<?> type = converter.getClass();
|
||||
|
||||
boolean isReading = type.isAnnotationPresent(ReadingConverter.class);
|
||||
boolean isWriting = type.isAnnotationPresent(WritingConverter.class);
|
||||
|
||||
if (converter instanceof GenericConverter) {
|
||||
GenericConverter genericConverter = (GenericConverter) converter;
|
||||
|
||||
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
||||
register(new ConverterRegistration(pair, isReading, isWriting));
|
||||
}
|
||||
} else if (converter instanceof ConverterFactory) {
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), ConverterFactory.class);
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
} else if (converter instanceof Converter) {
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported Converter type!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link ConvertiblePair} as reading or writing pair depending on the type sides being basic
|
||||
* Cassandra types.
|
||||
*
|
||||
* @param converterRegistration
|
||||
*/
|
||||
private void register(ConverterRegistration converterRegistration) {
|
||||
|
||||
ConvertiblePair pair = converterRegistration.getConvertiblePair();
|
||||
|
||||
if (converterRegistration.isReading()) {
|
||||
|
||||
readingPairs.add(pair);
|
||||
|
||||
if (LOG.isWarnEnabled() && !converterRegistration.isSimpleSourceType()) {
|
||||
LOG.warn(String.format(READ_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||
}
|
||||
}
|
||||
|
||||
if (converterRegistration.isWriting()) {
|
||||
|
||||
writingPairs.add(pair);
|
||||
|
||||
if (LOG.isWarnEnabled() && !converterRegistration.isSimpleTargetType()) {
|
||||
LOG.warn(String.format(WRITE_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target type to convert to in case we have a custom conversion registered to convert the given source
|
||||
* type into a Cassandra native one.
|
||||
*
|
||||
* @param sourceType must not be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getCustomWriteTarget(final Class<?> sourceType) {
|
||||
|
||||
return rawWriteTargetTypes.computeIfAbsent(sourceType, it -> getCustomTarget(sourceType, null, writingPairs))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target type we can inject of the given source type to. The returned type might be a subclass of the
|
||||
* given expected type though. If {@code expectedTargetType} is {@literal null} we will simply return the first target
|
||||
* type matching or {@literal null} if no conversion can be found.
|
||||
*
|
||||
* @param sourceType must not be {@literal null}
|
||||
* @param requestedTargetType
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getCustomWriteTarget(final Class<?> sourceType, final Class<?> requestedTargetType) {
|
||||
|
||||
if (requestedTargetType == null) {
|
||||
return getCustomWriteTarget(sourceType);
|
||||
}
|
||||
|
||||
return customWriteTargetTypes.computeIfAbsent(new ConvertiblePair(sourceType, requestedTargetType),
|
||||
it -> getCustomTarget(sourceType, requestedTargetType, writingPairs)).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we have a custom conversion registered into a Cassandra native type. The returned type might be a
|
||||
* subclass of the given expected type though.
|
||||
*
|
||||
* @param sourceType must not be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
public boolean hasCustomWriteTarget(Class<?> sourceType) {
|
||||
return hasCustomWriteTarget(sourceType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we have a custom conversion registered to an object of the given source type into an object of the
|
||||
* given Cassandra native target type.
|
||||
*
|
||||
* @param sourceType must not be {@literal null}.
|
||||
* @param requestedTargetType
|
||||
* @return
|
||||
*/
|
||||
public boolean hasCustomWriteTarget(Class<?> sourceType, Class<?> requestedTargetType) {
|
||||
return getCustomWriteTarget(sourceType, requestedTargetType) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we have a custom conversion registered to the given source into the given target type.
|
||||
*
|
||||
* @param sourceType must not be {@literal null}
|
||||
* @param requestedTargetType must not be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
public boolean hasCustomReadTarget(Class<?> sourceType, Class<?> requestedTargetType) {
|
||||
return getCustomReadTarget(sourceType, requestedTargetType) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual target type for the given {@code sourceType} and {@code requestedTargetType}. Note that the
|
||||
* returned {@link Class} could be an assignable type to the given {@code requestedTargetType}.
|
||||
*
|
||||
* @param sourceType must not be {@literal null}.
|
||||
* @param requestedTargetType can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private Class<?> getCustomReadTarget(final Class<?> sourceType, final Class<?> requestedTargetType) {
|
||||
|
||||
if (requestedTargetType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return customReadTargetTypes.computeIfAbsent(new ConvertiblePair(sourceType, requestedTargetType),
|
||||
it -> getCustomTarget(sourceType, requestedTargetType, readingPairs)).orElse(null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the given {@link ConvertiblePair}s for ones that have a source compatible type as source. Additionally
|
||||
* checks assignability of the target type if one is given.
|
||||
*
|
||||
* @param sourceType must not be {@literal null}.
|
||||
* @param requestedTargetType can be {@literal null}.
|
||||
* @param pairs must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static Optional<Class<?>> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
|
||||
Collection<ConvertiblePair> pairs) {
|
||||
|
||||
Assert.notNull(sourceType, "Source Class must not be null");
|
||||
Assert.notNull(pairs, "Collection of ConvertiblePair must not be null");
|
||||
|
||||
if (requestedTargetType != null && pairs.contains(new ConvertiblePair(sourceType, requestedTargetType))) {
|
||||
return Optional.of(requestedTargetType);
|
||||
}
|
||||
|
||||
for (ConvertiblePair typePair : pairs) {
|
||||
if (typePair.getSourceType().isAssignableFrom(sourceType)) {
|
||||
Class<?> targetType = typePair.getTargetType();
|
||||
if (requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType)) {
|
||||
return Optional.of(targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,21 +605,21 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
private Class<?> getTargetType(CassandraPersistentProperty property) {
|
||||
|
||||
if (getCustomConversions().hasCustomWriteTarget(property.getType())) {
|
||||
return getCustomConversions().getCustomWriteTarget(property.getType());
|
||||
}
|
||||
return getCustomConversions().getCustomWriteTarget(property.getType()).orElseGet(() -> {
|
||||
|
||||
if (property.findAnnotation(CassandraType.class).isPresent()) {
|
||||
return getPropertyTargetType(property);
|
||||
}
|
||||
|
||||
if (property.isCompositePrimaryKey() || getCustomConversions().isSimpleType(property.getType())
|
||||
|| property.isCollectionLike()) {
|
||||
|
||||
return property.getType();
|
||||
}
|
||||
|
||||
if (property.findAnnotation(CassandraType.class).isPresent()) {
|
||||
return getPropertyTargetType(property);
|
||||
}
|
||||
});
|
||||
|
||||
if (property.isCompositePrimaryKey() || getCustomConversions().isSimpleType(property.getType())
|
||||
|| property.isCollectionLike()) {
|
||||
|
||||
return property.getType();
|
||||
}
|
||||
|
||||
return getPropertyTargetType(property);
|
||||
}
|
||||
|
||||
private Class<?> getPropertyTargetType(CassandraPersistentProperty property) {
|
||||
@@ -673,8 +673,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
if (getCustomConversions().hasCustomWriteTarget(value.getClass())) {
|
||||
|
||||
return Optional.ofNullable(getConversionService().convert(value,
|
||||
(Class<O>) getCustomConversions().getCustomWriteTarget(value.getClass())));
|
||||
return getCustomConversions().getCustomWriteTarget(value.getClass()).map(it -> {
|
||||
|
||||
return getConversionService().convert(value, (Class<O>) it);
|
||||
});
|
||||
}
|
||||
|
||||
TypeInformation<?> type = (typeInformation != null ? typeInformation : ClassTypeInformation.from(value.getClass()));
|
||||
@@ -726,9 +728,13 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
if (optionalValue.isPresent()) {
|
||||
|
||||
Object value = optionalValue.get();
|
||||
if (getCustomConversions().hasCustomWriteTarget(value.getClass(), requestedTargetType)) {
|
||||
return Optional.ofNullable((O) getConversionService().convert(value,
|
||||
getCustomConversions().getCustomWriteTarget(value.getClass(), requestedTargetType)));
|
||||
|
||||
if (getCustomConversions().hasCustomWriteTarget(value.getClass())) {
|
||||
|
||||
return getCustomConversions().getCustomWriteTarget(value.getClass()).map(it -> {
|
||||
|
||||
return getConversionService().convert(value, (Class<O>) it);
|
||||
});
|
||||
}
|
||||
|
||||
// Cassandra has no default enum handling - convert it either to string
|
||||
|
||||
@@ -35,8 +35,9 @@ import org.springframework.cassandra.core.keyspace.CreateUserTypeSpecification;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.convert.CassandraCustomConversions;
|
||||
import org.springframework.data.cassandra.mapping.UserTypeUtil.FrozenLiteralDataType;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
@@ -93,7 +94,7 @@ public class BasicCassandraMappingContext
|
||||
*/
|
||||
public BasicCassandraMappingContext() {
|
||||
|
||||
setCustomConversions(new CustomConversions(Collections.EMPTY_LIST));
|
||||
setCustomConversions(new CassandraCustomConversions(Collections.EMPTY_LIST));
|
||||
setSimpleTypeHolder(CassandraSimpleTypeHolder.HOLDER);
|
||||
}
|
||||
|
||||
@@ -304,11 +305,6 @@ public class BasicCassandraMappingContext
|
||||
@Override
|
||||
protected CassandraPersistentProperty createPersistentProperty(Property property, CassandraPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
return createPersistentProperty(property, owner, (CassandraSimpleTypeHolder) simpleTypeHolder);
|
||||
}
|
||||
|
||||
public CassandraPersistentProperty createPersistentProperty(Property property, CassandraPersistentEntity<?> owner,
|
||||
CassandraSimpleTypeHolder simpleTypeHolder) {
|
||||
return new BasicCassandraPersistentProperty(property, owner, simpleTypeHolder, userTypeResolver);
|
||||
}
|
||||
|
||||
@@ -468,29 +464,26 @@ public class BasicCassandraMappingContext
|
||||
}
|
||||
}
|
||||
|
||||
if (customConversions.hasCustomWriteTarget(property.getType())) {
|
||||
return getDataTypeFor(customConversions.getCustomWriteTarget(property.getType()));
|
||||
}
|
||||
return customConversions.getCustomWriteTarget(property.getType()) //
|
||||
.map(CassandraSimpleTypeHolder::getDataTypeFor) //
|
||||
.orElseGet(() -> customConversions.getCustomWriteTarget(property.getActualType()) //
|
||||
.map(it -> {
|
||||
|
||||
if (customConversions.hasCustomWriteTarget(property.getActualType())) {
|
||||
if (property.isCollectionLike()) {
|
||||
|
||||
Class<?> targetType = customConversions.getCustomWriteTarget(property.getActualType());
|
||||
if (List.class.isAssignableFrom(property.getType())) {
|
||||
return DataType.list(getDataTypeFor(it));
|
||||
}
|
||||
|
||||
if (property.isCollectionLike()) {
|
||||
if (Set.class.isAssignableFrom(property.getType())) {
|
||||
return DataType.set(getDataTypeFor(it));
|
||||
}
|
||||
}
|
||||
|
||||
if (List.class.isAssignableFrom(property.getType())) {
|
||||
return DataType.list(getDataTypeFor(targetType));
|
||||
}
|
||||
return getDataTypeFor(it);
|
||||
}).orElseGet(property::getDataType)
|
||||
|
||||
if (Set.class.isAssignableFrom(property.getType())) {
|
||||
return DataType.set(getDataTypeFor(targetType));
|
||||
}
|
||||
}
|
||||
|
||||
return getDataTypeFor(targetType);
|
||||
}
|
||||
|
||||
return property.getDataType();
|
||||
);
|
||||
}
|
||||
|
||||
private DataType getUserDataType(CassandraPersistentProperty property, DataTypeProvider dataTypeProvider,
|
||||
@@ -521,8 +514,10 @@ public class BasicCassandraMappingContext
|
||||
*/
|
||||
@Override
|
||||
public DataType getDataType(Class<?> type) {
|
||||
return (customConversions.hasCustomWriteTarget(type) ? getDataTypeFor(customConversions.getCustomWriteTarget(type))
|
||||
: getDataTypeFor(type));
|
||||
|
||||
return customConversions.getCustomWriteTarget(type) //
|
||||
.map(CassandraSimpleTypeHolder::getDataTypeFor) //
|
||||
.orElseGet(() -> getDataTypeFor(type));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
@@ -105,7 +106,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
* @param userTypeResolver resolver for user-defined types.
|
||||
*/
|
||||
public BasicCassandraPersistentProperty(Property property, CassandraPersistentEntity<?> owner,
|
||||
CassandraSimpleTypeHolder simpleTypeHolder, UserTypeResolver userTypeResolver) {
|
||||
SimpleTypeHolder simpleTypeHolder, UserTypeResolver userTypeResolver) {
|
||||
|
||||
super(property, owner, simpleTypeHolder);
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.util.Collection;
|
||||
|
||||
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
|
||||
import org.springframework.cassandra.core.keyspace.CreateUserTypeSpecification;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
@@ -137,11 +136,11 @@ public interface CassandraMappingContext
|
||||
|
||||
/**
|
||||
* Retrieve the data type of the property. Cassandra {@link DataType types} are determined using simple types and
|
||||
* configured {@link CustomConversions}.
|
||||
* configured {@link org.springframework.data.convert.CustomConversions}.
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @return the Cassandra {@link DataType type}.
|
||||
* @see CustomConversions
|
||||
* @see org.springframework.data.convert.CustomConversions
|
||||
* @see CassandraSimpleTypeHolder
|
||||
* @since 1.5
|
||||
*/
|
||||
@@ -149,11 +148,11 @@ public interface CassandraMappingContext
|
||||
|
||||
/**
|
||||
* Retrieve the data type based on the given {@code type}. Cassandra {@link DataType types} are determined using
|
||||
* simple types and configured {@link CustomConversions}.
|
||||
* simple types and configured {@link org.springframework.data.convert.CustomConversions}.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return the Cassandra {@link DataType type}.
|
||||
* @see CustomConversions
|
||||
* @see org.springframework.data.convert.CustomConversions
|
||||
* @see CassandraSimpleTypeHolder
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.CollectionExecution;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.ResultProcessingConverter;
|
||||
@@ -39,6 +38,7 @@ import org.springframework.data.cassandra.repository.query.CassandraQueryExecuti
|
||||
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.ResultSetQuery;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.SingleEntityExecution;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.StreamExecution;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,18 +17,19 @@ package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Represents a {@link ReturnedType} in the context of Spring Data Cassandra.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class CassandraReturnedType {
|
||||
|
||||
private final ReturnedType returnedType;
|
||||
|
||||
private final CustomConversions customConversions;
|
||||
|
||||
CassandraReturnedType(ReturnedType returnedType, CustomConversions customConversions) {
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.cassandra.domain.Person;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ConverterRegistration}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ConverterRegistrationUnitTests {
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void considersNotExplicitlyReadingDependingOnTypes() {
|
||||
|
||||
ConverterRegistration context = new ConverterRegistration(Person.class, String.class, false, false);
|
||||
assertThat(context.isWriting()).isTrue();
|
||||
assertThat(context.isReading()).isFalse();
|
||||
|
||||
context = new ConverterRegistration(String.class, Person.class, false, false);
|
||||
assertThat(context.isWriting()).isFalse();
|
||||
assertThat(context.isReading()).isTrue();
|
||||
|
||||
context = new ConverterRegistration(String.class, Class.class, false, false);
|
||||
assertThat(context.isWriting()).isTrue();
|
||||
assertThat(context.isReading()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void forcesReadWriteOnlyIfAnnotated() {
|
||||
|
||||
ConverterRegistration context = new ConverterRegistration(String.class, Class.class, false, true);
|
||||
assertThat(context.isWriting()).isTrue();
|
||||
assertThat(context.isReading()).isFalse();
|
||||
|
||||
context = new ConverterRegistration(String.class, Class.class, true, false);
|
||||
assertThat(context.isWriting()).isFalse();
|
||||
assertThat(context.isReading()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void considersConverterForReadAndWriteIfBothAnnotated() {
|
||||
|
||||
ConverterRegistration context = new ConverterRegistration(String.class, Class.class, true, true);
|
||||
assertThat(context.isWriting()).isTrue();
|
||||
assertThat(context.isReading()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import org.springframework.data.cassandra.core.CassandraTemplate;
|
||||
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
import org.springframework.data.cassandra.test.integration.support.SchemaTestUtils;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.Row;
|
||||
@@ -59,7 +60,7 @@ public class CustomConversionIntegrationTests extends AbstractKeyspaceCreatingIn
|
||||
List<Converter<?, ?>> converters = new ArrayList<>();
|
||||
converters.add(new PersonReadConverter());
|
||||
converters.add(new PersonWriteConverter());
|
||||
CustomConversions customConversions = new CustomConversions(converters);
|
||||
CustomConversions customConversions = new CassandraCustomConversions(converters);
|
||||
|
||||
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
|
||||
mappingContext.setCustomConversions(customConversions);
|
||||
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.text.DateFormat;
|
||||
import java.text.Format;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CustomConversions}.
|
||||
*
|
||||
* @soundtrack Atc - Why Oh Why (Extended Version)
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CustomConversionsUnitTests {
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void findsBasicReadAndWriteConversions() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(
|
||||
Arrays.asList(FormatToStringConverter.INSTANCE, StringToFormatConverter.INSTANCE));
|
||||
|
||||
assertThat(conversions.getCustomWriteTarget(Format.class, null)).isAssignableFrom(String.class);
|
||||
assertThat(conversions.getCustomWriteTarget(String.class, null)).isNull();
|
||||
|
||||
assertThat(conversions.hasCustomReadTarget(String.class, Format.class)).isTrue();
|
||||
assertThat(conversions.hasCustomReadTarget(String.class, Locale.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void considersSubtypesCorrectly() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(
|
||||
Arrays.asList(NumberToStringConverter.INSTANCE, StringToNumberConverter.INSTANCE));
|
||||
|
||||
assertThat(conversions.getCustomWriteTarget(Long.class, null)).isAssignableFrom(String.class);
|
||||
assertThat(conversions.hasCustomReadTarget(String.class, Long.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void considersTypesWeRegisteredConvertersForAsSimple() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Collections.singletonList(FormatToStringConverter.INSTANCE));
|
||||
assertThat(conversions.isSimpleType(UUID.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void populatesConversionServiceCorrectly() {
|
||||
|
||||
GenericConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Collections.singletonList(StringToFormatConverter.INSTANCE));
|
||||
conversions.registerConvertersIn(conversionService);
|
||||
|
||||
assertThat(conversionService.canConvert(String.class, Format.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void doesNotConsiderTypeSimpleIfOnlyReadConverterIsRegistered() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Collections.singletonList(StringToFormatConverter.INSTANCE));
|
||||
assertThat(conversions.isSimpleType(Format.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void discoversConvertersForSubtypesOfCassandraTypes() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Collections.singletonList(StringToIntegerConverter.INSTANCE));
|
||||
assertThat(conversions.hasCustomReadTarget(String.class, Integer.class)).isTrue();
|
||||
assertThat(conversions.hasCustomWriteTarget(String.class, Integer.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void considersUUIDASimpleType() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions();
|
||||
assertThat(conversions.isSimpleType(UUID.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void considersInetAddressASimpleType() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions();
|
||||
assertThat(conversions.isSimpleType(InetAddress.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void considersRowASimpleType() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions();
|
||||
assertThat(conversions.isSimpleType(Row.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void favorsCustomConverterForIndeterminedTargetType() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(
|
||||
Collections.singletonList(DateTimeToStringConverter.INSTANCE));
|
||||
assertThat(conversions.getCustomWriteTarget(DateTime.class, null)).isEqualTo((Class) String.class);
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void customConverterOverridesDefault() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Collections.singletonList(CustomDateTimeConverter.INSTANCE));
|
||||
GenericConversionService conversionService = new DefaultConversionService();
|
||||
conversions.registerConvertersIn(conversionService);
|
||||
|
||||
assertThat(conversionService.convert(new DateTime(), Date.class)).isEqualTo(new Date(0));
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void shouldSelectPropertCustomWriteTargetForCglibProxiedType() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Collections.singletonList(FormatToStringConverter.INSTANCE));
|
||||
assertThat(conversions.getCustomWriteTarget(createProxyTypeFor(Format.class))).isAssignableFrom(String.class);
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void shouldSelectPropertyCustomReadTargetForCglibProxiedType() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(
|
||||
Collections.singletonList(CustomObjectToStringConverter.INSTANCE));
|
||||
assertThat(conversions.hasCustomReadTarget(createProxyTypeFor(Object.class), String.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-280
|
||||
public void registersConverterFactoryCorrectly() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions(
|
||||
Collections.singletonList(new FormatConverterFactory()));
|
||||
|
||||
assertThat(customConversions.getCustomWriteTarget(String.class, SimpleDateFormat.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATACASS-296
|
||||
public void registersConvertersForJsr310() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions();
|
||||
|
||||
assertThat(customConversions.hasCustomWriteTarget(java.time.LocalDateTime.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-296
|
||||
public void registersConvertersForThreeTenBackPort() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions();
|
||||
|
||||
assertThat(customConversions.hasCustomWriteTarget(org.threeten.bp.LocalDateTime.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-296
|
||||
public void registersConvertersForJoda() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions();
|
||||
|
||||
assertThat(customConversions.hasCustomWriteTarget(org.joda.time.LocalDate.class)).isTrue();
|
||||
}
|
||||
|
||||
private static Class<?> createProxyTypeFor(Class<?> type) {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
factory.setProxyTargetClass(true);
|
||||
factory.setTargetClass(type);
|
||||
|
||||
return factory.getProxy().getClass();
|
||||
}
|
||||
|
||||
enum FormatToStringConverter implements Converter<Format, String> {
|
||||
INSTANCE;
|
||||
|
||||
public String convert(Format source) {
|
||||
return source.toString();
|
||||
}
|
||||
}
|
||||
|
||||
enum StringToFormatConverter implements Converter<String, Format> {
|
||||
INSTANCE;
|
||||
public Format convert(String source) {
|
||||
return DateFormat.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
enum NumberToStringConverter implements Converter<Number, String> {
|
||||
INSTANCE;
|
||||
public String convert(Number source) {
|
||||
return source.toString();
|
||||
}
|
||||
}
|
||||
|
||||
enum StringToNumberConverter implements Converter<String, Number> {
|
||||
INSTANCE;
|
||||
public Number convert(String source) {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
enum StringToIntegerConverter implements Converter<String, Integer> {
|
||||
INSTANCE;
|
||||
public Integer convert(String source) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
enum DateTimeToStringConverter implements Converter<DateTime, String> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public String convert(DateTime source) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
enum CustomDateTimeConverter implements Converter<DateTime, Date> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Date convert(DateTime source) {
|
||||
return new Date(0);
|
||||
}
|
||||
}
|
||||
|
||||
enum CustomObjectToStringConverter implements Converter<Object, String> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public String convert(Object source) {
|
||||
return source != null ? source.toString() : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
static class FormatConverterFactory implements ConverterFactory<String, Format> {
|
||||
|
||||
@Override
|
||||
public <T extends Format> Converter<String, T> getConverter(Class<T> targetType) {
|
||||
return new StringToFormat<>(targetType);
|
||||
}
|
||||
|
||||
private static final class StringToFormat<T extends Format> implements Converter<String, T> {
|
||||
|
||||
private final Class<T> targetType;
|
||||
|
||||
public StringToFormat(Class<T> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convert(String source) {
|
||||
|
||||
if (source.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return targetType.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import org.springframework.data.cassandra.mapping.UserDefinedType;
|
||||
import org.springframework.data.cassandra.mapping.UserTypeResolver;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -83,7 +84,7 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
|
||||
|
||||
@Override
|
||||
public CustomConversions customConversions() {
|
||||
return new CustomConversions(Arrays.asList(new UDTToCurrencyConverter(),
|
||||
return new CassandraCustomConversions(Arrays.asList(new UDTToCurrencyConverter(),
|
||||
new CurrencyToUDTConverter(new SimpleUserTypeResolver(cluster().getObject(), getKeyspaceName()))));
|
||||
}
|
||||
}
|
||||
@@ -301,8 +302,7 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
|
||||
Insert insert = QueryBuilder.insertInto("bank");
|
||||
converter.write(bank, insert);
|
||||
|
||||
assertThat(insert.toString())
|
||||
.isEqualTo("INSERT INTO bank (currency) VALUES ({currency:'EUR'});");
|
||||
assertThat(insert.toString()).isEqualTo("INSERT INTO bank (currency) VALUES ({currency:'EUR'});");
|
||||
}
|
||||
|
||||
@Test // DATACASS-172
|
||||
@@ -360,8 +360,7 @@ public class MappingCassandraConverterUDTIntegrationTests extends AbstractSpring
|
||||
Insert insert = QueryBuilder.insertInto("bank");
|
||||
converter.write(bank, insert);
|
||||
|
||||
assertThat(insert.toString())
|
||||
.isEqualTo("INSERT INTO bank (othercurrencies) VALUES ([{currency:'EUR'}]);");
|
||||
assertThat(insert.toString()).isEqualTo("INSERT INTO bank (othercurrencies) VALUES ([{currency:'EUR'}]);");
|
||||
}
|
||||
|
||||
@Test // DATACASS-172
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.convert.CassandraCustomConversions;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
@@ -305,15 +305,15 @@ public class BasicCassandraMappingContextUnitTests {
|
||||
@Test // DATACASS-296
|
||||
public void shouldCreatePersistentEntityIfNoConversionRegistered() {
|
||||
|
||||
mappingContext.setCustomConversions(new CustomConversions(Collections.EMPTY_LIST));
|
||||
mappingContext.setCustomConversions(new CassandraCustomConversions(Collections.EMPTY_LIST));
|
||||
assertThat(mappingContext.shouldCreatePersistentEntityFor(ClassTypeInformation.from(Human.class))).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACASS-296
|
||||
public void shouldNotCreateEntitiesForCustomConvertedTypes() {
|
||||
|
||||
mappingContext
|
||||
.setCustomConversions(new CustomConversions(Collections.singletonList(HumanToStringConverter.INSTANCE)));
|
||||
mappingContext.setCustomConversions(
|
||||
new CassandraCustomConversions(Collections.singletonList(HumanToStringConverter.INSTANCE)));
|
||||
|
||||
assertThat(mappingContext.shouldCreatePersistentEntityFor(ClassTypeInformation.from(Human.class))).isFalse();
|
||||
}
|
||||
@@ -321,8 +321,8 @@ public class BasicCassandraMappingContextUnitTests {
|
||||
@Test // DATACASS-349
|
||||
public void propertyTypeShouldConsiderRegisteredConverterForPropertyType() {
|
||||
|
||||
mappingContext
|
||||
.setCustomConversions(new CustomConversions(Collections.singletonList(StringMapToStringConverter.INSTANCE)));
|
||||
mappingContext.setCustomConversions(
|
||||
new CassandraCustomConversions(Collections.singletonList(StringMapToStringConverter.INSTANCE)));
|
||||
|
||||
CassandraPersistentEntity<?> persistentEntity = mappingContext
|
||||
.getRequiredPersistentEntity(TypeWithCustomConvertedMap.class);
|
||||
@@ -337,8 +337,8 @@ public class BasicCassandraMappingContextUnitTests {
|
||||
@Test // DATACASS-349
|
||||
public void propertyTypeShouldConsiderRegisteredConverterForCollectionComponentType() {
|
||||
|
||||
mappingContext
|
||||
.setCustomConversions(new CustomConversions(Collections.singletonList(HumanToStringConverter.INSTANCE)));
|
||||
mappingContext.setCustomConversions(
|
||||
new CassandraCustomConversions(Collections.singletonList(HumanToStringConverter.INSTANCE)));
|
||||
|
||||
CassandraPersistentEntity<?> persistentEntity = mappingContext
|
||||
.getRequiredPersistentEntity(TypeWithListOfHumans.class);
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.springframework.cassandra.core.keyspace.ColumnSpecification;
|
||||
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.convert.CassandraCustomConversions;
|
||||
import org.springframework.data.cassandra.domain.AllPossibleTypes;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -64,7 +64,7 @@ public class CreateTableSpecificationBasicCassandraMappingContextUnitTests {
|
||||
converters.add(new PersonReadConverter());
|
||||
converters.add(new PersonWriteConverter());
|
||||
|
||||
CustomConversions customConversions = new CustomConversions(converters);
|
||||
CassandraCustomConversions customConversions = new CassandraCustomConversions(converters);
|
||||
ctx.setCustomConversions(customConversions);
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ public class CreateTableSpecificationBasicCassandraMappingContextUnitTests {
|
||||
|
||||
private CreateTableSpecification getCreateTableSpecificationFor(Class<?> persistentEntityClass) {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions(Collections.EMPTY_LIST);
|
||||
CassandraCustomConversions customConversions = new CassandraCustomConversions(Collections.EMPTY_LIST);
|
||||
ctx.setCustomConversions(customConversions);
|
||||
|
||||
CassandraPersistentEntity<?> persistentEntity = ctx.getRequiredPersistentEntity(persistentEntityClass);
|
||||
|
||||
@@ -31,9 +31,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
|
||||
import org.springframework.data.cassandra.config.SchemaAction;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.convert.CassandraCustomConversions;
|
||||
import org.springframework.data.cassandra.core.CassandraAdminOperations;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.mapping.SimpleUserTypeResolver;
|
||||
@@ -34,6 +34,7 @@ import org.springframework.data.cassandra.mapping.UserTypeResolver;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
@@ -76,7 +77,7 @@ abstract class ParameterConversionTestSupport extends AbstractSpringDataEmbedded
|
||||
|
||||
@Override
|
||||
public CustomConversions customConversions() {
|
||||
return new CustomConversions(
|
||||
return new CassandraCustomConversions(
|
||||
Arrays.asList(AddressReadConverter.INSTANCE, AddressWriteConverter.INSTANCE, PhoneReadConverter.INSTANCE,
|
||||
new PhoneWriteConverter(new SimpleUserTypeResolver(cluster().getObject(), getKeyspaceName()))));
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.cassandra.support.exception.CassandraInvalidQueryExce
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.cassandra.config.SchemaAction;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.cassandra.convert.CassandraCustomConversions;
|
||||
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.domain.AllPossibleTypes;
|
||||
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
|
||||
@@ -44,6 +44,7 @@ import org.springframework.data.cassandra.repository.Query;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -109,7 +110,7 @@ public class RepositoryQueryMethodParameterTypesIntegrationTests
|
||||
@Test // DATACASS-296
|
||||
public void shouldFindByAnnotatedDateParameter() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions(
|
||||
CustomConversions customConversions = new CassandraCustomConversions(
|
||||
Collections.singletonList(new DateToLocalDateConverter()));
|
||||
|
||||
mappingContext.setCustomConversions(customConversions);
|
||||
|
||||
Reference in New Issue
Block a user