@@ -16,7 +16,16 @@
|
||||
package org.springframework.data.convert;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
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 java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@@ -38,7 +47,6 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.CustomCollections;
|
||||
import org.springframework.data.util.Predicates;
|
||||
import org.springframework.data.util.Streamable;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -99,24 +107,20 @@ public class CustomConversions {
|
||||
private final Function<ConvertiblePair, Class<?>> getRawWriteTarget = convertiblePair -> getCustomTarget(
|
||||
convertiblePair.getSourceType(), null, writingPairs);
|
||||
|
||||
@Nullable
|
||||
private final PropertyValueConversions propertyValueConversions;
|
||||
@Nullable private final PropertyValueConversions propertyValueConversions;
|
||||
|
||||
/**
|
||||
* @param converterConfiguration the {@link ConverterConfiguration} to apply.
|
||||
* @since 2.3
|
||||
*/
|
||||
public CustomConversions(@NonNull ConverterConfiguration converterConfiguration) {
|
||||
public CustomConversions(ConverterConfiguration converterConfiguration) {
|
||||
|
||||
this.converterConfiguration = converterConfiguration;
|
||||
|
||||
List<Object> registeredConverters = collectPotentialConverterRegistrations(
|
||||
converterConfiguration.getStoreConversions(), converterConfiguration.getUserConverters()).stream()
|
||||
.filter(this::isSupportedConverter)
|
||||
.filter(this::shouldRegister)
|
||||
.map(ConverterRegistrationIntent::getConverterRegistration)
|
||||
.map(this::register)
|
||||
.distinct()
|
||||
.filter(this::isSupportedConverter).filter(this::shouldRegister)
|
||||
.map(ConverterRegistrationIntent::getConverterRegistration).map(this::register).distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Collections.reverse(registeredConverters);
|
||||
@@ -136,40 +140,47 @@ public class CustomConversions {
|
||||
* @param storeConversions must not be {@literal null}.
|
||||
* @param converters must not be {@literal null}.
|
||||
*/
|
||||
public CustomConversions(@NonNull StoreConversions storeConversions, @NonNull Collection<?> converters) {
|
||||
public CustomConversions(StoreConversions storeConversions, Collection<?> converters) {
|
||||
this(new ConverterConfiguration(storeConversions, new ArrayList<>(converters)));
|
||||
}
|
||||
|
||||
private static boolean hasAssignableSourceType(ConvertiblePair pair, Class<?> sourceType) {
|
||||
return pair.getSourceType().isAssignableFrom(sourceType);
|
||||
}
|
||||
|
||||
private static boolean requestedTargetTypeIsAssignable(@Nullable Class<?> requestedTargetType, Class<?> targetType) {
|
||||
|
||||
return requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying {@link SimpleTypeHolder}.
|
||||
*
|
||||
* @return the underlying {@link SimpleTypeHolder}.
|
||||
* @see SimpleTypeHolder
|
||||
*/
|
||||
public @NonNull SimpleTypeHolder getSimpleTypeHolder() {
|
||||
public SimpleTypeHolder getSimpleTypeHolder() {
|
||||
return simpleTypeHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given, required {@link PersistentProperty property} has a value-specific converter
|
||||
* registered. Returns {@literal false} if no {@link PropertyValueConversions} have been configured for the
|
||||
* underlying store.
|
||||
* registered. Returns {@literal false} if no {@link PropertyValueConversions} have been configured for the underlying
|
||||
* store.
|
||||
* <p>
|
||||
* This method protects against {@literal null} when not {@link PropertyValueConversions} have been configured for
|
||||
* the underlying data store, and is a shortcut for:
|
||||
*
|
||||
* <code>
|
||||
* This method protects against {@literal null} when not {@link PropertyValueConversions} have been configured for the
|
||||
* underlying data store, and is a shortcut for: <code>
|
||||
* customConversions.getPropertyValueConversions().hasValueConverter(property);
|
||||
* </code>
|
||||
*
|
||||
* @param property {@link PersistentProperty} to evaluate; must not be {@literal null}.
|
||||
* @return a boolean value indicating whether {@link PropertyValueConverter} has been configured and registered
|
||||
* for the {@link PersistentProperty property}.
|
||||
* @return a boolean value indicating whether {@link PropertyValueConverter} has been configured and registered for
|
||||
* the {@link PersistentProperty property}.
|
||||
* @see PropertyValueConversions#hasValueConverter(PersistentProperty)
|
||||
* @see #getPropertyValueConversions()
|
||||
* @see PersistentProperty
|
||||
*/
|
||||
public boolean hasValueConverter(@NonNull PersistentProperty<?> property) {
|
||||
public boolean hasValueConverter(PersistentProperty<?> property) {
|
||||
|
||||
PropertyValueConversions propertyValueConversions = getPropertyValueConversions();
|
||||
|
||||
@@ -184,10 +195,11 @@ public class CustomConversions {
|
||||
* @param type {@link Class} to evaluate as a simple type, such as a primitive type.
|
||||
* @return a boolean value indicating whether the given, required {@link Class type} is simple.
|
||||
*/
|
||||
// TODO: Technically, an 'isXyz(..)' method (returning a boolean to answer a user's question should not throw an Exception).
|
||||
// Rather, a null Class type argument should simply return false to indicate it is clearly not a "simple type".
|
||||
// How much data store specific code relies on the existing behavior?
|
||||
public boolean isSimpleType(@NonNull Class<?> type) {
|
||||
// TODO: Technically, an 'isXyz(..)' method (returning a boolean to answer a user's question should not throw an
|
||||
// Exception).
|
||||
// Rather, a null Class type argument should simply return false to indicate it is clearly not a "simple type".
|
||||
// How much data store specific code relies on the existing behavior?
|
||||
public boolean isSimpleType(Class<?> type) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null");
|
||||
|
||||
@@ -200,7 +212,7 @@ public class CustomConversions {
|
||||
* @param conversionService {@link ConverterRegistry} to populate; must not be {@literal null}.
|
||||
* @see ConverterRegistry
|
||||
*/
|
||||
public void registerConvertersIn(@NonNull ConverterRegistry conversionService) {
|
||||
public void registerConvertersIn(ConverterRegistry conversionService) {
|
||||
|
||||
Assert.notNull(conversionService, "ConversionService must not be null");
|
||||
|
||||
@@ -208,54 +220,6 @@ public class CustomConversions {
|
||||
CustomCollections.registerConvertersIn(conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the configured {@link PropertyValueConversions} if property value conversions
|
||||
* are supported by the underlying data store.
|
||||
*
|
||||
* @return a reference to the configured {@link PropertyValueConversions}; may be {@literal null}
|
||||
* if the underlying data store does not support property value conversions.
|
||||
* @see PropertyValueConversions
|
||||
*/
|
||||
@Nullable
|
||||
public PropertyValueConversions getPropertyValueConversions() {
|
||||
return propertyValueConversions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all converters and add origin information
|
||||
*
|
||||
* @param storeConversions collection of store-base conversions; must not be {@literal null}.
|
||||
* @param converters collections of custom, user-based converters; must not be {@literal null}.
|
||||
* @return a {@link List} of intended {@link ConverterRegistration ConverterRegistrations}.
|
||||
* @see ConverterRegistration
|
||||
* @since 2.3
|
||||
*/
|
||||
private List<ConverterRegistrationIntent> collectPotentialConverterRegistrations(
|
||||
@NonNull StoreConversions storeConversions, @NonNull Collection<?> converters) {
|
||||
|
||||
List<ConverterRegistrationIntent> converterRegistrations = new ArrayList<>();
|
||||
|
||||
converters.stream()
|
||||
.map(storeConversions::getRegistrationsFor)
|
||||
.flatMap(Streamable::stream)
|
||||
.map(ConverterRegistrationIntent::userConverters)
|
||||
.forEach(converterRegistrations::add);
|
||||
|
||||
storeConversions.getStoreConverters().stream()
|
||||
.map(storeConversions::getRegistrationsFor)
|
||||
.flatMap(Streamable::stream)
|
||||
.map(ConverterRegistrationIntent::storeConverters)
|
||||
.forEach(converterRegistrations::add);
|
||||
|
||||
DEFAULT_CONVERTERS.stream()
|
||||
.map(storeConversions::getRegistrationsFor)
|
||||
.flatMap(Streamable::stream)
|
||||
.map(ConverterRegistrationIntent::defaultConverters)
|
||||
.forEach(converterRegistrations::add);
|
||||
|
||||
return converterRegistrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given converter in the given {@link GenericConversionService}.
|
||||
*
|
||||
@@ -277,6 +241,46 @@ public class CustomConversions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the configured {@link PropertyValueConversions} if property value conversions are supported by
|
||||
* the underlying data store.
|
||||
*
|
||||
* @return a reference to the configured {@link PropertyValueConversions}; may be {@literal null} if the underlying
|
||||
* data store does not support property value conversions.
|
||||
* @see PropertyValueConversions
|
||||
*/
|
||||
@Nullable
|
||||
public PropertyValueConversions getPropertyValueConversions() {
|
||||
return propertyValueConversions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all converters and add origin information
|
||||
*
|
||||
* @param storeConversions collection of store-base conversions; must not be {@literal null}.
|
||||
* @param converters collections of custom, user-based converters; must not be {@literal null}.
|
||||
* @return a {@link List} of intended {@link ConverterRegistration ConverterRegistrations}.
|
||||
* @see ConverterRegistration
|
||||
* @since 2.3
|
||||
*/
|
||||
private List<ConverterRegistrationIntent> collectPotentialConverterRegistrations(StoreConversions storeConversions,
|
||||
Collection<?> converters) {
|
||||
|
||||
List<ConverterRegistrationIntent> converterRegistrations = new ArrayList<>();
|
||||
|
||||
converters.stream().map(storeConversions::getRegistrationsFor).flatMap(Streamable::stream)
|
||||
.map(ConverterRegistrationIntent::userConverters).forEach(converterRegistrations::add);
|
||||
|
||||
storeConversions.getStoreConverters().stream().map(storeConversions::getRegistrationsFor)
|
||||
.flatMap(Streamable::stream).map(ConverterRegistrationIntent::storeConverters)
|
||||
.forEach(converterRegistrations::add);
|
||||
|
||||
DEFAULT_CONVERTERS.stream().map(storeConversions::getRegistrationsFor).flatMap(Streamable::stream)
|
||||
.map(ConverterRegistrationIntent::defaultConverters).forEach(converterRegistrations::add);
|
||||
|
||||
return converterRegistrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link ConvertiblePair} as reading or writing pair depending on the type sides being basic
|
||||
* types.
|
||||
@@ -284,7 +288,7 @@ public class CustomConversions {
|
||||
* @param converterRegistration {@link ConverterRegistration} to register; must not be {@literal null}.
|
||||
* @see ConverterRegistration
|
||||
*/
|
||||
private Object register(@NonNull ConverterRegistration converterRegistration) {
|
||||
private Object register(ConverterRegistration converterRegistration) {
|
||||
|
||||
Assert.notNull(converterRegistration, "Converter registration must not be null");
|
||||
|
||||
@@ -321,7 +325,7 @@ public class CustomConversions {
|
||||
* @return {@literal true} if supported.
|
||||
* @since 2.3
|
||||
*/
|
||||
private boolean isSupportedConverter(@NonNull ConverterRegistrationIntent registrationIntent) {
|
||||
private boolean isSupportedConverter(ConverterRegistrationIntent registrationIntent) {
|
||||
|
||||
boolean register = registrationIntent.isUserConverter() || registrationIntent.isStoreConverter()
|
||||
|| (registrationIntent.isReading() && registrationIntent.isSimpleSourceType())
|
||||
@@ -348,7 +352,7 @@ public class CustomConversions {
|
||||
* @return {@literal false} if the given {@link ConverterRegistration} shall be skipped.
|
||||
* @since 2.3
|
||||
*/
|
||||
private boolean shouldRegister(@NonNull ConverterRegistrationIntent intent) {
|
||||
private boolean shouldRegister(ConverterRegistrationIntent intent) {
|
||||
return !intent.isDefaultConverter()
|
||||
|| converterConfiguration.shouldRegister(intent.getConverterRegistration().getConvertiblePair());
|
||||
}
|
||||
@@ -359,9 +363,9 @@ public class CustomConversions {
|
||||
*
|
||||
* @param sourceType must not be {@literal null}
|
||||
* @return the target type to convert to in case we have a custom conversion registered to convert the given source
|
||||
* type into a store native one.
|
||||
* type into a store native one.
|
||||
*/
|
||||
public Optional<Class<?>> getCustomWriteTarget(@NonNull Class<?> sourceType) {
|
||||
public Optional<Class<?>> getCustomWriteTarget(Class<?> sourceType) {
|
||||
|
||||
Assert.notNull(sourceType, "Source type must not be null");
|
||||
|
||||
@@ -379,7 +383,7 @@ public class CustomConversions {
|
||||
* @param requestedTargetType must not be {@literal null}.
|
||||
* @return the target type we can read an inject of the given source type to.
|
||||
*/
|
||||
public Optional<Class<?>> getCustomWriteTarget(@NonNull Class<?> sourceType, @NonNull Class<?> requestedTargetType) {
|
||||
public Optional<Class<?>> getCustomWriteTarget(Class<?> sourceType, Class<?> requestedTargetType) {
|
||||
|
||||
Assert.notNull(sourceType, "Source type must not be null");
|
||||
Assert.notNull(requestedTargetType, "Target type must not be null");
|
||||
@@ -396,7 +400,7 @@ public class CustomConversions {
|
||||
* @param sourceType must not be {@literal null}
|
||||
* @return whether we have a custom conversion registered to read {@code sourceType} into a native type.
|
||||
*/
|
||||
public boolean hasCustomWriteTarget(@NonNull Class<?> sourceType) {
|
||||
public boolean hasCustomWriteTarget(Class<?> sourceType) {
|
||||
|
||||
Assert.notNull(sourceType, "Source type must not be null");
|
||||
|
||||
@@ -409,10 +413,10 @@ public class CustomConversions {
|
||||
*
|
||||
* @param sourceType must not be {@literal null}.
|
||||
* @param targetType must not be {@literal null}.
|
||||
* @return whether we have a custom conversion registered to read an object of the given source type into an object
|
||||
* of the given native target type.
|
||||
* @return whether we have a custom conversion registered to read an object of the given source type into an object of
|
||||
* the given native target type.
|
||||
*/
|
||||
public boolean hasCustomWriteTarget(@NonNull Class<?> sourceType, @NonNull Class<?> targetType) {
|
||||
public boolean hasCustomWriteTarget(Class<?> sourceType, Class<?> targetType) {
|
||||
|
||||
Assert.notNull(sourceType, "Source type must not be null");
|
||||
Assert.notNull(targetType, "Target type must not be null");
|
||||
@@ -427,7 +431,7 @@ public class CustomConversions {
|
||||
* @param targetType must not be {@literal null}
|
||||
* @return whether we have a custom conversion registered to read the given source into the given target type.
|
||||
*/
|
||||
public boolean hasCustomReadTarget(@NonNull Class<?> sourceType, @NonNull Class<?> targetType) {
|
||||
public boolean hasCustomReadTarget(Class<?> sourceType, Class<?> targetType) {
|
||||
|
||||
Assert.notNull(sourceType, "Source type must not be null");
|
||||
Assert.notNull(targetType, "Target type must not be null");
|
||||
@@ -444,7 +448,7 @@ public class CustomConversions {
|
||||
* @return the actual target type for the given {@code sourceType} and {@code targetType}.
|
||||
*/
|
||||
@Nullable
|
||||
private Class<?> getCustomReadTarget(@NonNull Class<?> sourceType, @NonNull Class<?> targetType) {
|
||||
private Class<?> getCustomReadTarget(Class<?> sourceType, Class<?> targetType) {
|
||||
return customReadTargetTypes.computeIfAbsent(sourceType, targetType, getReadTarget);
|
||||
}
|
||||
|
||||
@@ -458,7 +462,7 @@ public class CustomConversions {
|
||||
* @return the base {@link Class type} for the (requested) {@link Class target type} if present.
|
||||
*/
|
||||
@Nullable
|
||||
private Class<?> getCustomTarget(@NonNull Class<?> sourceType, @Nullable Class<?> targetType,
|
||||
private Class<?> getCustomTarget(Class<?> sourceType, @Nullable Class<?> targetType,
|
||||
Collection<ConvertiblePair> pairs) {
|
||||
|
||||
if (targetType != null && pairs.contains(new ConvertiblePair(sourceType, targetType))) {
|
||||
@@ -483,16 +487,6 @@ public class CustomConversions {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean hasAssignableSourceType(@NonNull ConvertiblePair pair, @NonNull Class<?> sourceType) {
|
||||
return pair.getSourceType().isAssignableFrom(sourceType);
|
||||
}
|
||||
|
||||
private static boolean requestedTargetTypeIsAssignable(@Nullable Class<?> requestedTargetType,
|
||||
@NonNull Class<?> targetType) {
|
||||
|
||||
return requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Value object to cache custom conversion targets.
|
||||
*
|
||||
@@ -803,15 +797,14 @@ public class CustomConversions {
|
||||
|
||||
if (converter instanceof ConverterAware converterAware) {
|
||||
|
||||
return Streamable.of(() -> converterAware.getConverters().stream()
|
||||
.flatMap(it -> getRegistrationsFor(it).stream()));
|
||||
return Streamable
|
||||
.of(() -> converterAware.getConverters().stream().flatMap(it -> getRegistrationsFor(it).stream()));
|
||||
|
||||
} else if (converter instanceof GenericConverter genericConverter) {
|
||||
|
||||
Set<ConvertiblePair> convertibleTypes = genericConverter.getConvertibleTypes();
|
||||
|
||||
return convertibleTypes == null
|
||||
? Streamable.empty()
|
||||
return convertibleTypes == null ? Streamable.empty()
|
||||
: Streamable.of(convertibleTypes).map(it -> register(converter, it, isReading, isWriting));
|
||||
|
||||
} else if (converter instanceof ConverterFactory) {
|
||||
@@ -951,8 +944,8 @@ public class CustomConversions {
|
||||
* @param propertyValueConversions can be {@literal null}.
|
||||
* @since 2.7
|
||||
*/
|
||||
public ConverterConfiguration(@NonNull StoreConversions storeConversions, @NonNull List<?> userConverters,
|
||||
@NonNull Predicate<ConvertiblePair> converterRegistrationFilter,
|
||||
public ConverterConfiguration(StoreConversions storeConversions, List<?> userConverters,
|
||||
Predicate<ConvertiblePair> converterRegistrationFilter,
|
||||
@Nullable PropertyValueConversions propertyValueConversions) {
|
||||
|
||||
this.storeConversions = storeConversions;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.springframework.data.convert;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -42,7 +41,7 @@ public class PropertyValueConversionService {
|
||||
* @throws IllegalArgumentException if {@link CustomConversions} is {@literal null}.
|
||||
* @see CustomConversions
|
||||
*/
|
||||
public PropertyValueConversionService(@NonNull CustomConversions conversions) {
|
||||
public PropertyValueConversionService(CustomConversions conversions) {
|
||||
|
||||
Assert.notNull(conversions, "CustomConversions must not be null");
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.convert;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -48,8 +47,8 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
* operation.
|
||||
*
|
||||
* @param value value to read.
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata
|
||||
* used in the value conversion; never {@literal null}.
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata used in the value conversion;
|
||||
* never {@literal null}.
|
||||
* @return the converted value. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -59,8 +58,8 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
* Convert the given {@code null} value from the store into its domain value representation. Typically, a
|
||||
* {@literal read} operation. Returns {@code null} by default.
|
||||
*
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata
|
||||
* used in the value conversion; never {@literal null}.
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata used in the value conversion;
|
||||
* never {@literal null}.
|
||||
* @return the converted value. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -73,8 +72,8 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
* operation.
|
||||
*
|
||||
* @param value value to write; can be {@literal null}.
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata
|
||||
* used in the value conversion; never {@literal null}.
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata used in the value conversion;
|
||||
* never {@literal null}.
|
||||
* @return the converted value. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -84,8 +83,8 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
* Convert the given {@code null} value from the domain model into it's native store representation. Typically, a
|
||||
* {@literal write} operation. Returns {@code null} by default.
|
||||
*
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata
|
||||
* used in the value conversion; never {@literal null}.
|
||||
* @param context {@link ValueConversionContext} containing store-specific metadata used in the value conversion;
|
||||
* never {@literal null}.
|
||||
* @return the converted value. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -127,8 +126,8 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
private final BiFunction<DV, ValueConversionContext<P>, SV> writer;
|
||||
private final BiFunction<SV, ValueConversionContext<P>, DV> reader;
|
||||
|
||||
public FunctionPropertyValueConverter(@NonNull BiFunction<DV, ValueConversionContext<P>, SV> writer,
|
||||
@NonNull BiFunction<SV, ValueConversionContext<P>, DV> reader) {
|
||||
public FunctionPropertyValueConverter(BiFunction<DV, ValueConversionContext<P>, SV> writer,
|
||||
BiFunction<SV, ValueConversionContext<P>, DV> reader) {
|
||||
|
||||
this.writer = writer;
|
||||
this.reader = reader;
|
||||
@@ -136,23 +135,23 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SV write(@Nullable DV value, @NonNull ValueConversionContext<P> context) {
|
||||
public SV write(@Nullable DV value, ValueConversionContext<P> context) {
|
||||
return writer.apply(value, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SV writeNull(@NonNull ValueConversionContext<P> context) {
|
||||
public SV writeNull(ValueConversionContext<P> context) {
|
||||
return writer.apply(null, context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DV read(@Nullable SV value, @NonNull ValueConversionContext<P> context) {
|
||||
public DV read(@Nullable SV value, ValueConversionContext<P> context) {
|
||||
return reader.apply(value, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DV readNull(@NonNull ValueConversionContext<P> context) {
|
||||
public DV readNull(ValueConversionContext<P> context) {
|
||||
return reader.apply(null, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,10 +215,12 @@ final class PropertyValueConverterFactories {
|
||||
Map<PersistentProperty<?>, Optional<PropertyValueConverter<?, ?, ? extends ValueConversionContext<?>>>> perPropertyCache = new ConcurrentHashMap<>();
|
||||
Map<Class<?>, Optional<PropertyValueConverter<?, ?, ? extends ValueConversionContext<?>>>> typeCache = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
Optional<PropertyValueConverter<?, ?, ? extends ValueConversionContext<?>>> get(PersistentProperty<?> property) {
|
||||
return perPropertyCache.get(property);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Optional<PropertyValueConverter<?, ?, ? extends ValueConversionContext<?>>> get(Class<?> type) {
|
||||
return typeCache.get(type);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.function.Function;
|
||||
import org.springframework.data.convert.PropertyValueConverter.FunctionPropertyValueConverter;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.util.MethodInvocationRecorder;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -106,7 +105,7 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
* @throws IllegalArgumentException if the {@link ValueConverterRegistry} is {@literal null}.
|
||||
* @see ValueConverterRegistry
|
||||
*/
|
||||
public void registerConvertersIn(@NonNull ValueConverterRegistry<P> target) {
|
||||
public void registerConvertersIn(ValueConverterRegistry<P> target) {
|
||||
|
||||
Assert.notNull(target, "Target registry must not be null");
|
||||
|
||||
@@ -119,7 +118,7 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
*
|
||||
* @return new instance of {@link SimplePropertyValueConverterRegistry}.
|
||||
*/
|
||||
@NonNull
|
||||
|
||||
public ValueConverterRegistry<P> buildRegistry() {
|
||||
return new SimplePropertyValueConverterRegistry<>(registry);
|
||||
}
|
||||
@@ -135,7 +134,7 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
private final PropertyValueConverterRegistrar<P> config;
|
||||
|
||||
WritingConverterRegistrationBuilder(Class<T> type, String property,
|
||||
@NonNull PropertyValueConverterRegistrar<P> config) {
|
||||
PropertyValueConverterRegistrar<P> config) {
|
||||
|
||||
this.config = config;
|
||||
this.registration = converter -> config.registerConverter(type, property, converter);
|
||||
@@ -173,8 +172,8 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
private final WritingConverterRegistrationBuilder<T, S, P> origin;
|
||||
private final BiFunction<S, ValueConversionContext<P>, R> writer;
|
||||
|
||||
ReadingConverterRegistrationBuilder(@NonNull WritingConverterRegistrationBuilder<T, S, P> origin,
|
||||
@NonNull BiFunction<S, ValueConversionContext<P>, R> writer) {
|
||||
ReadingConverterRegistrationBuilder(WritingConverterRegistrationBuilder<T, S, P> origin,
|
||||
BiFunction<S, ValueConversionContext<P>, R> writer) {
|
||||
|
||||
this.origin = origin;
|
||||
this.writer = writer;
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.Optional;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.convert.PropertyValueConverterFactories.ChainedPropertyValueConverterFactory;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -44,8 +43,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class SimplePropertyValueConversions implements PropertyValueConversions, InitializingBean {
|
||||
|
||||
private static final String NO_CONVERTER_FACTORY_ERROR_MESSAGE =
|
||||
"PropertyValueConverterFactory is not set; Make sure to either set the converter factory or call afterPropertiesSet() to initialize the object";
|
||||
private static final String NO_CONVERTER_FACTORY_ERROR_MESSAGE = "PropertyValueConverterFactory is not set; Make sure to either set the converter factory or call afterPropertiesSet() to initialize the object";
|
||||
|
||||
private boolean converterCacheEnabled = true;
|
||||
|
||||
@@ -57,7 +55,7 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
* Set the {@link PropertyValueConverterFactory} responsible for creating the actual {@link PropertyValueConverter}.
|
||||
*
|
||||
* @param converterFactory {@link PropertyValueConverterFactory} used to create the actual
|
||||
* {@link PropertyValueConverter}.
|
||||
* {@link PropertyValueConverter}.
|
||||
* @see PropertyValueConverterFactory
|
||||
*/
|
||||
public void setConverterFactory(@Nullable PropertyValueConverterFactory converterFactory) {
|
||||
@@ -76,7 +74,7 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
return converterFactory;
|
||||
}
|
||||
|
||||
private @NonNull PropertyValueConverterFactory requireConverterFactory() {
|
||||
private PropertyValueConverterFactory requireConverterFactory() {
|
||||
|
||||
PropertyValueConverterFactory factory = getConverterFactory();
|
||||
|
||||
@@ -113,20 +111,20 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
/**
|
||||
* Configure whether to use converter the cache. Enabled by default.
|
||||
*
|
||||
* @param converterCacheEnabled set to {@literal true} to enable caching of
|
||||
* {@link PropertyValueConverter converter} instances.
|
||||
* @param converterCacheEnabled set to {@literal true} to enable caching of {@link PropertyValueConverter converter}
|
||||
* instances.
|
||||
*/
|
||||
public void setConverterCacheEnabled(boolean converterCacheEnabled) {
|
||||
this.converterCacheEnabled = converterCacheEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a {@link PropertyValueConverter} has been registered for
|
||||
* the given {@link PersistentProperty property}.
|
||||
* Determines whether a {@link PropertyValueConverter} has been registered for the given {@link PersistentProperty
|
||||
* property}.
|
||||
*
|
||||
* @param property {@link PersistentProperty} to evaluate.
|
||||
* @return {@literal true} if a {@link PropertyValueConverter} has been registered for
|
||||
* the given {@link PersistentProperty property}.
|
||||
* @return {@literal true} if a {@link PropertyValueConverter} has been registered for the given
|
||||
* {@link PersistentProperty property}.
|
||||
* @see PersistentProperty
|
||||
*/
|
||||
@Override
|
||||
@@ -134,7 +132,6 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
return requireConverterFactory().getConverter(property) != null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <DV, SV, P extends PersistentProperty<P>, D extends ValueConversionContext<P>> PropertyValueConverter<DV, SV, D> getValueConverter(
|
||||
P property) {
|
||||
@@ -155,8 +152,7 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
|
||||
factoryList.add(resolveConverterFactory());
|
||||
|
||||
resolveConverterRegistryAsConverterFactory()
|
||||
.ifPresent(factoryList::add);
|
||||
resolveConverterRegistryAsConverterFactory().ifPresent(factoryList::add);
|
||||
|
||||
PropertyValueConverterFactory targetFactory = factoryList.size() > 1
|
||||
? PropertyValueConverterFactory.chained(factoryList)
|
||||
@@ -166,18 +162,16 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
: targetFactory;
|
||||
}
|
||||
|
||||
private @NonNull PropertyValueConverterFactory resolveConverterFactory() {
|
||||
private PropertyValueConverterFactory resolveConverterFactory() {
|
||||
|
||||
PropertyValueConverterFactory converterFactory = getConverterFactory();
|
||||
|
||||
return converterFactory != null ? converterFactory
|
||||
: PropertyValueConverterFactory.simple();
|
||||
return converterFactory != null ? converterFactory : PropertyValueConverterFactory.simple();
|
||||
}
|
||||
|
||||
private Optional<PropertyValueConverterFactory> resolveConverterRegistryAsConverterFactory() {
|
||||
|
||||
return Optional.ofNullable(getValueConverterRegistry())
|
||||
.filter(it -> !it.isEmpty())
|
||||
return Optional.ofNullable(getValueConverterRegistry()).filter(it -> !it.isEmpty())
|
||||
.map(PropertyValueConverterFactory::configuredInstance);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.convert;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -47,7 +46,7 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
* @param value {@link Object value} to write; can be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @throws IllegalStateException if value cannot be written as an instance of the
|
||||
* {@link PersistentProperty#getTypeInformation() property type}.
|
||||
* {@link PersistentProperty#getTypeInformation() property type}.
|
||||
* @see PersistentProperty#getTypeInformation()
|
||||
* @see #write(Object, TypeInformation)
|
||||
*/
|
||||
@@ -67,7 +66,7 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
* @see TypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T write(@Nullable Object value, @NonNull Class<T> target) {
|
||||
default <T> T write(@Nullable Object value, Class<T> target) {
|
||||
return write(value, TypeInformation.of(target));
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
* @see TypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T write(@Nullable Object value, @NonNull TypeInformation<T> target) {
|
||||
default <T> T write(@Nullable Object value, TypeInformation<T> target) {
|
||||
|
||||
if (value == null || target.getType().isInstance(value)) {
|
||||
return target.getType().cast(value);
|
||||
@@ -97,7 +96,7 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
* @param value {@link Object value} to be read; can be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @throws IllegalStateException if value cannot be read as an instance of the
|
||||
* {@link PersistentProperty#getTypeInformation() property type}.
|
||||
* {@link PersistentProperty#getTypeInformation() property type}.
|
||||
* @see PersistentProperty#getTypeInformation()
|
||||
* @see #read(Object, TypeInformation)
|
||||
*/
|
||||
@@ -117,7 +116,7 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
* @see TypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T read(@Nullable Object value, @NonNull Class<T> target) {
|
||||
default <T> T read(@Nullable Object value, Class<T> target) {
|
||||
return read(value, TypeInformation.of(target));
|
||||
}
|
||||
|
||||
@@ -131,7 +130,7 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
* @see TypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T read(@Nullable Object value, @NonNull TypeInformation<T> target) {
|
||||
default <T> T read(@Nullable Object value, TypeInformation<T> target) {
|
||||
|
||||
if (value == null || target.getType().isInstance(value)) {
|
||||
return target.getType().cast(value);
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
@@ -110,7 +109,7 @@ public abstract class ClassUtils {
|
||||
* @deprecated Use {@link #getNumberOfOccurrences(Method, Class)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static int getNumberOfOccurences(@NonNull Method method, @NonNull Class<?> type) {
|
||||
public static int getNumberOfOccurences(Method method, Class<?> type) {
|
||||
return getNumberOfOccurrences(method, type);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user