Skip to content

Commit 3083185

Browse files
jxblummp911de
authored andcommitted
Fix test failures related to Joda Time and ThreeTenBackport type mappings.
Refactor and cleanup codebase. See #1170.
1 parent d9b032a commit 3083185

12 files changed

+191
-192
lines changed

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/AbstractCassandraConverter.java

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.springframework.data.cassandra.core.convert;
1717

18-
1918
import java.util.Collections;
2019

2120
import org.springframework.beans.factory.InitializingBean;

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraConverter.java

+1
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,5 @@ default Object convertToColumnType(Object value, TypeInformation<?> typeInformat
128128
* @param entity must not be {@literal null}.
129129
*/
130130
void write(Object source, Object sink, CassandraPersistentEntity<?> entity);
131+
131132
}

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraConverters.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ public enum RowToDateConverter implements Converter<Row, Date> {
9292

9393
@Override
9494
public Date convert(Row row) {
95-
return Date.from(row.getInstant(0));
95+
96+
Instant instant = row.getInstant(0);
97+
98+
return instant != null ? Date.from(instant) : null;
9699
}
97100
}
98101

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraCustomConversions.java

+4-17
Original file line numberDiff line numberDiff line change
@@ -64,31 +64,18 @@ public CassandraCustomConversions(List<?> converters) {
6464

6565
/**
6666
* Cassandra-specific extension to {@link org.springframework.data.convert.CustomConversions.ConverterConfiguration}.
67-
* This extension avoids {@link Converter} registrations that enforce date mapping to {@link Date} from JSR-310, Joda
68-
* Time and ThreeTenBackport.
67+
* This extension avoids {@link Converter} registrations that enforce date mapping to {@link Date} from JSR-310.
6968
*/
7069
static class CassandraConverterConfiguration extends ConverterConfiguration {
7170

72-
public CassandraConverterConfiguration(StoreConversions storeConversions, List<?> userConverters) {
71+
CassandraConverterConfiguration(StoreConversions storeConversions, List<?> userConverters) {
7372
super(storeConversions, userConverters, getConverterFilter());
7473
}
7574

7675
static Predicate<ConvertiblePair> getConverterFilter() {
7776

78-
return convertiblePair -> {
79-
80-
if (sourceMatches(convertiblePair, "org.joda.time") || sourceMatches(convertiblePair, "org.threeten.bp")
81-
|| Jsr310Converters.supports(convertiblePair.getSourceType())
82-
&& Date.class.isAssignableFrom(convertiblePair.getTargetType())) {
83-
return false;
84-
}
85-
86-
return true;
87-
};
88-
}
89-
90-
private static boolean sourceMatches(ConvertiblePair convertiblePair, String packagePrefix) {
91-
return convertiblePair.getSourceType().getName().startsWith(packagePrefix);
77+
return convertiblePair -> !(Jsr310Converters.supports(convertiblePair.getSourceType())
78+
&& Date.class.isAssignableFrom(convertiblePair.getTargetType()));
9279
}
9380
}
9481
}

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/CassandraJsr310Converters.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ private CassandraJsr310Converters() {}
5555
converters.add(LocalTimeToMillisOfDayConverter.INSTANCE);
5656

5757
converters.add(DateToInstantConverter.INSTANCE);
58-
converters.add(LocalDateToInstantConverter.INSTANCE);
58+
converters.add(LocalDateTimeToInstantConverter.INSTANCE);
5959

6060
return converters;
6161
}
@@ -117,7 +117,7 @@ public Instant convert(Date source) {
117117
* @since 3.0
118118
*/
119119
@WritingConverter
120-
enum LocalDateToInstantConverter implements Converter<LocalDateTime, Instant> {
120+
enum LocalDateTimeToInstantConverter implements Converter<LocalDateTime, Instant> {
121121

122122
INSTANCE;
123123

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/DefaultColumnTypeResolver.java

+10-16
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,11 @@ public CassandraColumnType resolve(TypeInformation<?> typeInformation) {
174174

175175
private CassandraColumnType resolve(TypeInformation<?> typeInformation, FrozenIndicator frozen) {
176176

177-
return getCustomWriteTarget(typeInformation).map(it -> {
178-
return createCassandraTypeDescriptor(tryResolve(it), ClassTypeInformation.from(it));
179-
}).orElseGet(() -> {
180-
181-
if (typeInformation.getType().isEnum()) {
182-
return ColumnType.create(String.class, DataTypes.TEXT);
183-
}
184-
185-
return createCassandraTypeDescriptor(typeInformation, frozen);
186-
});
177+
return getCustomWriteTarget(typeInformation)
178+
.map(it -> createCassandraTypeDescriptor(tryResolve(it), ClassTypeInformation.from(it)))
179+
.orElseGet(() -> typeInformation.getType().isEnum()
180+
? ColumnType.create(String.class, DataTypes.TEXT)
181+
: createCassandraTypeDescriptor(typeInformation, frozen));
187182
}
188183

189184
private Optional<Class<?>> getCustomWriteTarget(TypeInformation<?> typeInformation) {
@@ -203,9 +198,9 @@ private DataType tryResolve(Class<?> type) {
203198

204199
try {
205200
return getCodecRegistry().codecFor(type).getCqlType();
206-
} catch (CodecNotFoundException e) {
201+
} catch (CodecNotFoundException cause) {
207202
if (log.isDebugEnabled()) {
208-
log.debug(String.format("Cannot resolve Codec for %s", type.getName()), e);
203+
log.debug(String.format("Cannot resolve Codec for %s", type.getName()), cause);
209204
}
210205
return null;
211206
}
@@ -435,11 +430,10 @@ private CassandraColumnType createCassandraTypeDescriptor(TypeInformation<?> typ
435430
}
436431

437432
DataType dataType = tryResolve(typeInformation.getType());
438-
if (dataType == null) {
439-
return new UnresolvableCassandraType(typeInformation);
440-
}
441433

442-
return new DefaultCassandraColumnType(typeInformation, dataType);
434+
return dataType == null
435+
? new UnresolvableCassandraType(typeInformation)
436+
: new DefaultCassandraColumnType(typeInformation, dataType);
443437
}
444438

445439
private DataType getRequiredDataType(CassandraType annotation, int typeIndex) {

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java

+49-47
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,19 @@
3535
import org.springframework.core.convert.ConversionService;
3636
import org.springframework.core.convert.support.DefaultConversionService;
3737
import org.springframework.dao.InvalidDataAccessApiUsageException;
38-
import org.springframework.data.cassandra.core.mapping.*;
38+
import org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentEntity;
39+
import org.springframework.data.cassandra.core.mapping.BasicMapId;
40+
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
41+
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
42+
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
43+
import org.springframework.data.cassandra.core.mapping.Column;
44+
import org.springframework.data.cassandra.core.mapping.Element;
45+
import org.springframework.data.cassandra.core.mapping.Embedded;
3946
import org.springframework.data.cassandra.core.mapping.Embedded.OnEmpty;
47+
import org.springframework.data.cassandra.core.mapping.EmbeddedEntityOperations;
48+
import org.springframework.data.cassandra.core.mapping.MapId;
49+
import org.springframework.data.cassandra.core.mapping.MapIdentifiable;
50+
import org.springframework.data.cassandra.core.mapping.UserTypeResolver;
4051
import org.springframework.data.mapping.MappingException;
4152
import org.springframework.data.mapping.PersistentPropertyAccessor;
4253
import org.springframework.data.mapping.PreferredConstructor;
@@ -100,19 +111,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
100111
* Create a new {@link MappingCassandraConverter} with a {@link CassandraMappingContext}.
101112
*/
102113
public MappingCassandraConverter() {
103-
104-
super(newConversionService());
105-
106-
CassandraCustomConversions conversions = new CassandraCustomConversions(Collections.emptyList());
107-
108-
this.mappingContext = newDefaultMappingContext(conversions);
109-
this.codecRegistry = mappingContext.getCodecRegistry();
110-
this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE);
111-
this.cassandraTypeResolver = new DefaultColumnTypeResolver(mappingContext,
112-
userTypeName -> getUserTypeResolver().resolveType(userTypeName), this::getCodecRegistry,
113-
this::getCustomConversions);
114-
this.setCustomConversions(conversions);
115-
this.embeddedEntityOperations = new EmbeddedEntityOperations(mappingContext);
114+
this(newDefaultMappingContext(new CassandraCustomConversions(Collections.emptyList())));
116115
}
117116

118117
/**
@@ -126,31 +125,42 @@ public MappingCassandraConverter(CassandraMappingContext mappingContext) {
126125

127126
Assert.notNull(mappingContext, "CassandraMappingContext must not be null");
128127

128+
UserTypeResolver userTypeResolver = userTypeName -> getUserTypeResolver().resolveType(userTypeName);
129+
129130
this.mappingContext = mappingContext;
130-
this.codecRegistry = mappingContext.getCodecRegistry();
131-
this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE);
132-
this.cassandraTypeResolver = new DefaultColumnTypeResolver(mappingContext,
133-
userTypeName -> getUserTypeResolver().resolveType(userTypeName), this::getCodecRegistry,
134-
this::getCustomConversions);
131+
this.setCodecRegistry(mappingContext.getCodecRegistry());
135132
this.setCustomConversions(mappingContext.getCustomConversions());
133+
this.cassandraTypeResolver = new DefaultColumnTypeResolver(mappingContext, userTypeResolver,
134+
this::getCodecRegistry, this::getCustomConversions);
136135
this.embeddedEntityOperations = new EmbeddedEntityOperations(mappingContext);
136+
this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE);
137137
}
138138

139139
/**
140-
* Creates a new {@link ConversionContext}.
140+
* Constructs a new instance of {@link ConversionContext} with various converters to convert different Cassandra
141+
* value types.
141142
*
142143
* @return the {@link ConversionContext}.
144+
* @see ConversionContext
143145
*/
144146
protected ConversionContext getConversionContext() {
145147

146-
return new ConversionContext(getCustomConversions(), this::doReadRow, this::doReadTupleValue, this::doReadUdtValue,
148+
return new ConversionContext(this::doReadRow, this::doReadTupleValue, this::doReadUdtValue,
147149
this::readCollectionOrArray, this::readMap, this::getPotentiallyConvertedSimpleRead);
148150
}
149151

150152
private static ConversionService newConversionService() {
151153
return new DefaultConversionService();
152154
}
153155

156+
/**
157+
* Constructs a new instance of a {@link MappingContext} for Cassandra.
158+
*
159+
* @param conversions {@link CassandraCustomConversions} object encapsulating complex type conversion logic.
160+
* @return a new {@link CassandraMappingContext}.
161+
* @see org.springframework.data.cassandra.core.mapping.CassandraMappingContext
162+
* @see org.springframework.data.mapping.context.MappingContext
163+
*/
154164
private static CassandraMappingContext newDefaultMappingContext(CassandraCustomConversions conversions) {
155165

156166
CassandraMappingContext mappingContext = new CassandraMappingContext();
@@ -161,6 +171,7 @@ private static CassandraMappingContext newDefaultMappingContext(CassandraCustomC
161171
return mappingContext;
162172
}
163173

174+
164175
/* (non-Javadoc)
165176
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
166177
*/
@@ -202,12 +213,7 @@ public void setCodecRegistry(CodecRegistry codecRegistry) {
202213
*/
203214
@Override
204215
public CodecRegistry getCodecRegistry() {
205-
206-
if (this.codecRegistry == null) {
207-
return mappingContext.getCodecRegistry();
208-
}
209-
210-
return this.codecRegistry;
216+
return this.codecRegistry != null ? this.codecRegistry : getMappingContext().getCodecRegistry();
211217
}
212218

213219
/**
@@ -229,12 +235,7 @@ public void setUserTypeResolver(UserTypeResolver userTypeResolver) {
229235
* @since 3.0
230236
*/
231237
public UserTypeResolver getUserTypeResolver() {
232-
233-
if (this.userTypeResolver == null) {
234-
return this.mappingContext.getUserTypeResolver();
235-
}
236-
237-
return userTypeResolver;
238+
return this.userTypeResolver != null ? this.userTypeResolver : getMappingContext().getUserTypeResolver();
238239
}
239240

240241
/* (non-Javadoc)
@@ -367,8 +368,8 @@ protected <S> S doReadEntity(ConversionContext context, CassandraValueProvider v
367368
return (S) getConversionService().convert(valueProvider.getSource(), rawType);
368369
}
369370

370-
CassandraPersistentEntity<S> entity = (CassandraPersistentEntity<S>) getMappingContext()
371-
.getPersistentEntity(typeHint);
371+
CassandraPersistentEntity<S> entity =
372+
(CassandraPersistentEntity<S>) getMappingContext().getPersistentEntity(typeHint);
372373

373374
if (entity == null) {
374375
throw new MappingException(
@@ -393,8 +394,8 @@ private static Class<?> getRawSourceType(CassandraValueProvider valueProvider) {
393394
return UdtValue.class;
394395
}
395396

396-
throw new InvalidDataAccessApiUsageException(
397-
"Unsupported source type: " + ClassUtils.getDescriptiveType(valueProvider.getSource()));
397+
throw new InvalidDataAccessApiUsageException(String.format("Unsupported source type: %s",
398+
ClassUtils.getDescriptiveType(valueProvider.getSource())));
398399
}
399400

400401
private <S> S doReadEntity(ConversionContext context, CassandraValueProvider valueProvider,
@@ -405,8 +406,8 @@ private <S> S doReadEntity(ConversionContext context, CassandraValueProvider val
405406

406407
if (persistenceConstructor != null && persistenceConstructor.hasParameters()) {
407408
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(valueProvider.getSource(), spELContext);
408-
ParameterValueProvider<CassandraPersistentProperty> parameterValueProvider = newParameterValueProvider(context,
409-
entity, valueProvider);
409+
ParameterValueProvider<CassandraPersistentProperty> parameterValueProvider =
410+
newParameterValueProvider(context, entity, valueProvider);
410411
provider = new ConverterAwareSpELExpressionParameterValueProvider(evaluator, getConversionService(),
411412
parameterValueProvider, context);
412413
} else {
@@ -746,10 +747,7 @@ public Object getId(Object object, CassandraPersistentEntity<?> entity) {
746747

747748
/**
748749
* Check custom conversions for type override or fall back to
749-
* {@link #determineTargetType(CassandraPersistentProperty)}
750-
*
751-
* @param property
752-
* @return
750+
* {@link ColumnTypeResolver#resolve(CassandraPersistentProperty)}.
753751
*/
754752
private Class<?> getTargetType(CassandraPersistentProperty property) {
755753
return getCustomConversions().getCustomWriteTarget(property.getType())
@@ -794,17 +792,20 @@ private Object getWriteValue(@Nullable Object value, ColumnType columnType) {
794792

795793
if (getCustomConversions().hasCustomWriteTarget(value.getClass(), requestedTargetType)) {
796794

797-
Class<?> resolvedTargetType = getCustomConversions().getCustomWriteTarget(value.getClass(), requestedTargetType)
795+
Class<?> resolvedTargetType = getCustomConversions()
796+
.getCustomWriteTarget(value.getClass(), requestedTargetType)
798797
.orElse(requestedTargetType);
799798

800799
return getConversionService().convert(value, resolvedTargetType);
801800
}
802801

803802
if (getCustomConversions().hasCustomWriteTarget(value.getClass())) {
804803

805-
Class<?> resolvedTargetType = getCustomConversions().getCustomWriteTarget(value.getClass())
806-
.orElseThrow(() -> new IllegalStateException(String
807-
.format("Unable to determined custom write target for value type [%s]", value.getClass().getName())));
804+
Class<?> resolvedTargetType = getCustomConversions()
805+
.getCustomWriteTarget(value.getClass())
806+
.orElseThrow(() -> new IllegalStateException(
807+
String.format("Unable to determined custom write target for value type [%s]",
808+
value.getClass().getName())));
808809

809810
return getConversionService().convert(value, resolvedTargetType);
810811
}
@@ -988,6 +989,7 @@ private Object getReadValue(ConversionContext context, CassandraValueProvider va
988989
}
989990

990991
Object value = valueProvider.getPropertyValue(property);
992+
991993
return value == null ? null : context.convert(value, property.getTypeInformation());
992994
}
993995

0 commit comments

Comments
 (0)