@@ -16,36 +16,50 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Conversion service based on {@link CustomConversions} to convert domain and store values using
|
||||
* Conversion service based on {@link CustomConversions} used to convert domain and store values using
|
||||
* {@link PropertyValueConverter property-specific converters}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see PropertyValueConverter
|
||||
* @since 2.7
|
||||
*/
|
||||
public class PropertyValueConversionService {
|
||||
|
||||
private final PropertyValueConversions conversions;
|
||||
|
||||
public PropertyValueConversionService(CustomConversions conversions) {
|
||||
/**
|
||||
* Constructs a new instance of the {@link PropertyValueConversionService} initialized with the given,
|
||||
* required {@link CustomConversions} for resolving the {@link PropertyValueConversions} used to
|
||||
* convert {@link PersistentProperty} values during data access operations.
|
||||
*
|
||||
* @param conversions {@link CustomConversions} used to handle domain and store type conversions;
|
||||
* must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link CustomConversions} is {@literal null}.
|
||||
* @see CustomConversions
|
||||
*/
|
||||
public PropertyValueConversionService(@NonNull CustomConversions conversions) {
|
||||
|
||||
Assert.notNull(conversions, "CustomConversions must not be null");
|
||||
|
||||
PropertyValueConversions pvc = conversions.getPropertyValueConversions();
|
||||
this.conversions = pvc == null ? NoOpPropertyValueConversions.INSTANCE : pvc;
|
||||
PropertyValueConversions valueConversions = conversions.getPropertyValueConversions();
|
||||
|
||||
this.conversions = valueConversions != null ? valueConversions : NoOpPropertyValueConversions.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@literal true} there is a converter registered for {@link PersistentProperty}.
|
||||
* Return {@literal true} if a {@link PropertyValueConverter} is registered for the {@link PersistentProperty}.
|
||||
* <p>
|
||||
* If this method returns {@literal true}, it means {@link #read(Object, PersistentProperty, ValueConversionContext)}
|
||||
* and {@link #write(Object, PersistentProperty, ValueConversionContext)} are capable to invoke conversion.
|
||||
* and {@link #write(Object, PersistentProperty, ValueConversionContext)} are capable of handling conversions.
|
||||
*
|
||||
* @param property the underlying property.
|
||||
* @return {@literal true} there is a converter registered for {@link PersistentProperty}.
|
||||
* @param property {@link PersistentProperty property} to evaluate for registration.
|
||||
* @return {@literal true} if a {@link PropertyValueConverter} is registered for the {@link PersistentProperty}.
|
||||
* @see PersistentProperty
|
||||
*/
|
||||
public boolean hasConverter(PersistentProperty<?> property) {
|
||||
return conversions.hasValueConverter(property);
|
||||
@@ -68,11 +82,8 @@ public class PropertyValueConversionService {
|
||||
PropertyValueConverter<Object, Object, ValueConversionContext<P>> converter = conversions
|
||||
.getValueConverter(property);
|
||||
|
||||
if (value == null) {
|
||||
return converter.readNull(context);
|
||||
}
|
||||
|
||||
return converter.read(value, context);
|
||||
return value != null ? converter.read(value, context)
|
||||
: converter.readNull(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,11 +103,8 @@ public class PropertyValueConversionService {
|
||||
PropertyValueConverter<Object, Object, ValueConversionContext<P>> converter = conversions
|
||||
.getValueConverter(property);
|
||||
|
||||
if (value == null) {
|
||||
return converter.writeNull(context);
|
||||
}
|
||||
|
||||
return converter.write(value, context);
|
||||
return value != null ? converter.write(value, context)
|
||||
: converter.writeNull(context);
|
||||
}
|
||||
|
||||
enum NoOpPropertyValueConversions implements PropertyValueConversions {
|
||||
@@ -111,7 +119,7 @@ public class PropertyValueConversionService {
|
||||
@Override
|
||||
public <DV, SV, P extends PersistentProperty<P>, VCC extends ValueConversionContext<P>> PropertyValueConverter<DV, SV, VCC> getValueConverter(
|
||||
P property) {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("No PropertyValueConversions was configured");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,10 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
|
||||
/**
|
||||
* {@link PropertyValueConversions} provides access to {@link PropertyValueConverter converters} that may only be
|
||||
* applied to a specific property. Other than {@link org.springframework.core.convert.converter.Converter converters}
|
||||
* registered in {@link CustomConversions}, the property based variants accept and allow returning {@literal null}
|
||||
* values and provide access to a store specific {@link ValueConversionContext conversion context}.
|
||||
* applied to a specific {@link PersistentProperty property}. Other than
|
||||
* {@link org.springframework.core.convert.converter.Converter converters} registered in {@link CustomConversions},
|
||||
* the {@link PersistentProperty property} based variants accept and allow returning {@literal null} values
|
||||
* and provide access to a store-specific {@link ValueConversionContext conversion context}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.7
|
||||
@@ -32,30 +33,41 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
public interface PropertyValueConversions {
|
||||
|
||||
/**
|
||||
* Check if a {@link PropertyValueConverter} is present for the given {@literal property}.
|
||||
* Check if a {@link PropertyValueConverter converter} is registered for
|
||||
* the given {@link PersistentProperty property}.
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @return {@literal true} if a specific {@link PropertyValueConverter} is available.
|
||||
* @param property {@link PersistentProperty} to evaluate; must not be {@literal null}.
|
||||
* @return {@literal true} if a specific {@link PropertyValueConverter converter} is registered for
|
||||
* the given {@link PersistentProperty}.
|
||||
* @see PersistentProperty
|
||||
*/
|
||||
boolean hasValueConverter(PersistentProperty<?> property);
|
||||
|
||||
/**
|
||||
* Get the {@link PropertyValueConverter} for the given {@literal property}.
|
||||
* Get the {@link PropertyValueConverter converter} registered for the given {@link PersistentProperty property}.
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @param property {@link PersistentProperty} used to look up the registered {@link PropertyValueConverter};
|
||||
* must not be {@literal null}.
|
||||
* @param <DV> domain-specific type
|
||||
* @param <SV> store-native type
|
||||
* @param <P> conversion context type
|
||||
* @return the suitable {@link PropertyValueConverter}.
|
||||
* @throws IllegalArgumentException if there is no converter available for {@code property}.
|
||||
* @return the {@link PropertyValueConverter} registered for the given {@link PersistentProperty};
|
||||
* never {@literal null}.
|
||||
* @throws IllegalArgumentException if no {@link PropertyValueConverter} was registered for
|
||||
* the given {@link PersistentProperty}.
|
||||
* @see #hasValueConverter(PersistentProperty)
|
||||
* @see PropertyValueConverter
|
||||
* @see PersistentProperty
|
||||
*/
|
||||
<DV, SV, P extends PersistentProperty<P>, VCC extends ValueConversionContext<P>> PropertyValueConverter<DV, SV, VCC> getValueConverter(
|
||||
P property);
|
||||
|
||||
/**
|
||||
* Helper that allows to create {@link PropertyValueConversions} instance with the configured
|
||||
* {@link PropertyValueConverter converters} provided via the given callback.
|
||||
* Helper method used to create a {@link PropertyValueConversions} instance with the configured
|
||||
* {@link PropertyValueConverter converters} provided by the {@link Consumer callback}.
|
||||
*
|
||||
* @see PropertyValueConverterRegistrar
|
||||
* @see PropertyValueConversions
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
static <P extends PersistentProperty<P>> PropertyValueConversions simple(
|
||||
|
||||
@@ -18,6 +18,7 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,8 @@ import org.springframework.lang.Nullable;
|
||||
* @param <DV> domain-specific type.
|
||||
* @param <SV> store-native type.
|
||||
* @param <C> the store specific {@link ValueConversionContext conversion context}.
|
||||
* @see org.springframework.data.convert.ValueConversionContext
|
||||
* @see org.springframework.data.mapping.PersistentProperty
|
||||
* @since 2.7
|
||||
*/
|
||||
public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext<? extends PersistentProperty<?>>> {
|
||||
@@ -44,18 +47,20 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
* Convert the given store specific value into it's domain value representation. Typically, a {@literal read}
|
||||
* operation.
|
||||
*
|
||||
* @param value the value to read.
|
||||
* @param context never {@literal null}.
|
||||
* @param value value to read.
|
||||
* @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
|
||||
DV read(SV value, C context);
|
||||
|
||||
/**
|
||||
* Convert the given {@code null} value from the store into it's domain value representation. Typically, a
|
||||
* 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 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
|
||||
@@ -67,8 +72,9 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
* Convert the given domain-specific value into it's native store representation. Typically, a {@literal write}
|
||||
* operation.
|
||||
*
|
||||
* @param value the value to write.
|
||||
* @param context never {@literal null}.
|
||||
* @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}.
|
||||
* @return the converted value. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -78,7 +84,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 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
|
||||
@@ -120,8 +127,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(BiFunction<DV, ValueConversionContext<P>, SV> writer,
|
||||
BiFunction<SV, ValueConversionContext<P>, DV> reader) {
|
||||
public FunctionPropertyValueConverter(@NonNull BiFunction<DV, ValueConversionContext<P>, SV> writer,
|
||||
@NonNull BiFunction<SV, ValueConversionContext<P>, DV> reader) {
|
||||
|
||||
this.writer = writer;
|
||||
this.reader = reader;
|
||||
@@ -129,23 +136,23 @@ public interface PropertyValueConverter<DV, SV, C extends ValueConversionContext
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SV write(DV value, ValueConversionContext<P> context) {
|
||||
public SV write(@Nullable DV value, @NonNull ValueConversionContext<P> context) {
|
||||
return writer.apply(value, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SV writeNull(ValueConversionContext<P> context) {
|
||||
public SV writeNull(@NonNull ValueConversionContext<P> context) {
|
||||
return writer.apply(null, context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DV read(@Nullable SV value, ValueConversionContext<P> context) {
|
||||
public DV read(@Nullable SV value, @NonNull ValueConversionContext<P> context) {
|
||||
return reader.apply(value, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DV readNull(ValueConversionContext<P> context) {
|
||||
public DV readNull(@NonNull ValueConversionContext<P> context) {
|
||||
return reader.apply(null, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ final class PropertyValueConverterFactories {
|
||||
*/
|
||||
static class ChainedPropertyValueConverterFactory implements PropertyValueConverterFactory {
|
||||
|
||||
private List<PropertyValueConverterFactory> delegates;
|
||||
private final List<PropertyValueConverterFactory> delegates;
|
||||
|
||||
ChainedPropertyValueConverterFactory(List<PropertyValueConverterFactory> delegates) {
|
||||
this.delegates = Collections.unmodifiableList(delegates);
|
||||
@@ -58,8 +58,10 @@ final class PropertyValueConverterFactories {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A, B, C extends ValueConversionContext<?>> PropertyValueConverter<A, B, C> getConverter(
|
||||
PersistentProperty<?> property) {
|
||||
|
||||
return delegates.stream().map(it -> (PropertyValueConverter<A, B, C>) it.getConverter(property))
|
||||
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||
}
|
||||
@@ -67,6 +69,7 @@ final class PropertyValueConverterFactories {
|
||||
@Override
|
||||
public <S, T, C extends ValueConversionContext<?>> PropertyValueConverter<S, T, C> getConverter(
|
||||
Class<? extends PropertyValueConverter<S, T, C>> converterType) {
|
||||
|
||||
return delegates.stream().filter(it -> it.getConverter(converterType) != null).findFirst()
|
||||
.map(it -> it.getConverter(converterType)).orElse(null);
|
||||
}
|
||||
@@ -82,6 +85,7 @@ final class PropertyValueConverterFactories {
|
||||
static class SimplePropertyConverterFactory implements PropertyValueConverterFactory {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public <S, T, C extends ValueConversionContext<?>> PropertyValueConverter<S, T, C> getConverter(
|
||||
Class<? extends PropertyValueConverter<S, T, C>> converterType) {
|
||||
|
||||
@@ -90,6 +94,7 @@ final class PropertyValueConverterFactories {
|
||||
if (converterType.isEnum()) {
|
||||
return (PropertyValueConverter<S, T, C>) EnumSet.allOf((Class) converterType).iterator().next();
|
||||
}
|
||||
|
||||
return BeanUtils.instantiateClass(converterType);
|
||||
}
|
||||
}
|
||||
@@ -110,10 +115,11 @@ final class PropertyValueConverterFactories {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <DV, SV, C extends ValueConversionContext<?>> PropertyValueConverter<DV, SV, C> getConverter(
|
||||
Class<? extends PropertyValueConverter<DV, SV, C>> converterType) {
|
||||
|
||||
Assert.notNull(converterType, "ConverterType must not be null!");
|
||||
Assert.notNull(converterType, "ConverterType must not be null");
|
||||
|
||||
PropertyValueConverter<DV, SV, C> converter = beanFactory.getBeanProvider(converterType).getIfAvailable();
|
||||
|
||||
@@ -139,14 +145,17 @@ final class PropertyValueConverterFactories {
|
||||
|
||||
ConfiguredInstanceServingValueConverterFactory(ValueConverterRegistry<?> converterRegistry) {
|
||||
|
||||
Assert.notNull(converterRegistry, "ConversionsRegistrar must not be null!");
|
||||
Assert.notNull(converterRegistry, "ConversionsRegistrar must not be null");
|
||||
|
||||
this.converterRegistry = converterRegistry;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <DV, SV, C extends ValueConversionContext<?>> PropertyValueConverter<DV, SV, C> getConverter(
|
||||
PersistentProperty<?> property) {
|
||||
|
||||
return (PropertyValueConverter<DV, SV, C>) converterRegistry.getConverter(property.getOwner().getType(),
|
||||
property.getName());
|
||||
}
|
||||
@@ -154,6 +163,7 @@ final class PropertyValueConverterFactories {
|
||||
@Override
|
||||
public <S, T, C extends ValueConversionContext<?>> PropertyValueConverter<S, T, C> getConverter(
|
||||
Class<? extends PropertyValueConverter<S, T, C>> converterType) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -172,12 +182,14 @@ final class PropertyValueConverterFactories {
|
||||
|
||||
CachingPropertyValueConverterFactory(PropertyValueConverterFactory delegate) {
|
||||
|
||||
Assert.notNull(delegate, "Delegate must not be null!");
|
||||
Assert.notNull(delegate, "Delegate must not be null");
|
||||
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public <DV, SV, C extends ValueConversionContext<?>> PropertyValueConverter<DV, SV, C> getConverter(
|
||||
PersistentProperty<?> property) {
|
||||
|
||||
@@ -188,6 +200,7 @@ final class PropertyValueConverterFactories {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public <DV, SV, C extends ValueConversionContext<?>> PropertyValueConverter<DV, SV, C> getConverter(
|
||||
Class<? extends PropertyValueConverter<DV, SV, C>> converterType) {
|
||||
|
||||
@@ -218,15 +231,19 @@ final class PropertyValueConverterFactories {
|
||||
AnnotatedPropertyValueConverterAccessor accessor = new AnnotatedPropertyValueConverterAccessor(property);
|
||||
Class<? extends PropertyValueConverter<?, ?, ? extends ValueConversionContext<? extends PersistentProperty<?>>>> valueConverterType = accessor
|
||||
.getValueConverterType();
|
||||
|
||||
if (valueConverterType != null) {
|
||||
cache(valueConverterType, converter);
|
||||
}
|
||||
|
||||
return converter;
|
||||
}
|
||||
|
||||
<S, T, C extends ValueConversionContext<?>> PropertyValueConverter<S, T, C> cache(Class<?> type,
|
||||
@Nullable PropertyValueConverter<S, T, C> converter) {
|
||||
|
||||
typeCache.putIfAbsent(type, Optional.ofNullable(converter));
|
||||
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A factory that provides {@link PropertyValueConverter value converters}.
|
||||
* A factory providing {@link PropertyValueConverter value converters}.
|
||||
* <p>
|
||||
* Depending on the applications need {@link PropertyValueConverterFactory factories} can be {@link #chained(List)
|
||||
* Depending on the applications' need {@link PropertyValueConverterFactory factories} can be {@link #chained(List)
|
||||
* chained} and the resulting {@link PropertyValueConverter converter} may be
|
||||
* {@link #caching(PropertyValueConverterFactory) cached}.
|
||||
*
|
||||
@@ -129,7 +129,7 @@ public interface PropertyValueConverterFactory {
|
||||
*/
|
||||
static PropertyValueConverterFactory chained(List<PropertyValueConverterFactory> factoryList) {
|
||||
|
||||
Assert.noNullElements(factoryList, "FactoryList must not contain null elements.");
|
||||
Assert.noNullElements(factoryList, "FactoryList must not contain null elements");
|
||||
|
||||
if (factoryList.size() == 1) {
|
||||
return factoryList.iterator().next();
|
||||
|
||||
@@ -22,11 +22,12 @@ 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;
|
||||
|
||||
/**
|
||||
* Configuration class to register a {@link PropertyValueConverter} with a {@link SimplePropertyValueConverterRegistry}
|
||||
* that can be used with {@link PropertyValueConversions}.
|
||||
* Configuration class used to register a {@link PropertyValueConverter} with
|
||||
* a {@link SimplePropertyValueConverterRegistry} that can be used in {@link PropertyValueConversions}.
|
||||
* <p>
|
||||
* It is possible to register type safe converters via {@link #registerConverter(Class, Function)}
|
||||
*
|
||||
@@ -50,13 +51,14 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
* @param <T> the domain type
|
||||
* @param <S> the property type
|
||||
* @param type the domain type to obtain the property from
|
||||
* @param property a function to describe the property to be referenced. Usually a method handle to a getter.
|
||||
* @param property a {@link Function} to describe the property to be referenced.
|
||||
* Usually a method handle to a getter.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public <T, S> WritingConverterRegistrationBuilder<T, S, P> registerConverter(Class<T> type, Function<T, S> property) {
|
||||
|
||||
String propertyName = MethodInvocationRecorder.forProxyOf(type).record(property).getPropertyPath()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Cannot obtain property name!"));
|
||||
.orElseThrow(() -> new IllegalArgumentException("Cannot obtain property name"));
|
||||
|
||||
return new WritingConverterRegistrationBuilder<>(type, propertyName, this);
|
||||
}
|
||||
@@ -67,20 +69,23 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
* @param <T> the domain type
|
||||
* @param <S> the property type
|
||||
* @param type the domain type to obtain the property from
|
||||
* @param propertyName a function to describe the property to be referenced. Usually a method handle to a getter.
|
||||
* @param propertyName a {@link Function} to describe the property to be referenced.
|
||||
* Usually a method handle to a getter.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public <T, S> WritingConverterRegistrationBuilder<T, S, P> registerConverter(Class<T> type, String propertyName,
|
||||
@SuppressWarnings("unused") Class<S> propertyType) {
|
||||
|
||||
return new WritingConverterRegistrationBuilder<>(type, propertyName, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given converter for the types property identified via its name.
|
||||
* Register the given {@link PropertyValueConverter converter} for the given type and property identified by
|
||||
* its name.
|
||||
*
|
||||
* @param type the domain type to obtain the property from
|
||||
* @param path the property name.
|
||||
* @param converter the converter to apply.
|
||||
* @param converter the {@link PropertyValueConverter converter} to apply.
|
||||
* @return this.
|
||||
*/
|
||||
public PropertyValueConverterRegistrar<P> registerConverter(Class<?> type, String path,
|
||||
@@ -88,33 +93,39 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
|
||||
registry.registerConverter(type, path,
|
||||
(PropertyValueConverter<?, ?, ? extends ValueConversionContext<P>>) converter);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register collected {@link PropertyValueConverter converters} within the given
|
||||
* {@link ValueConverterRegistry registry}.
|
||||
*
|
||||
* @param target {@link ValueConverterRegistry} from which to register {@link PropertyValueConverter converters};
|
||||
* must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if the {@link ValueConverterRegistry} is {@literal null}.
|
||||
* @see ValueConverterRegistry
|
||||
*/
|
||||
public void registerConvertersIn(@NonNull ValueConverterRegistry<P> target) {
|
||||
|
||||
Assert.notNull(target, "Target registry must not be null!");
|
||||
|
||||
registry.getConverterRegistrationMap().forEach((key, value) ->
|
||||
target.registerConverter(key.type, key.path, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the {@link SimplePropertyValueConverterRegistry}.
|
||||
*
|
||||
* @return new instance of {@link SimplePropertyValueConverterRegistry}.
|
||||
*/
|
||||
@NonNull
|
||||
public ValueConverterRegistry<P> buildRegistry() {
|
||||
return new SimplePropertyValueConverterRegistry<>(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register collected {@link PropertyValueConverter converters} within the given {@link ValueConverterRegistry
|
||||
* registry}.
|
||||
*/
|
||||
public void registerConvertersIn(ValueConverterRegistry<P> target) {
|
||||
|
||||
Assert.notNull(target, "Target registry must not be null!");
|
||||
|
||||
registry.getConverterRegistrationMap().entrySet().forEach(entry -> {
|
||||
target.registerConverter(entry.getKey().type, entry.getKey().path, entry.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to build up a fluent registration API starting on
|
||||
* Helper class used to build up a fluent registration API starting with writing.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@@ -123,10 +134,11 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
private final Consumer<PropertyValueConverter<T, S, ValueConversionContext<P>>> registration;
|
||||
private final PropertyValueConverterRegistrar<P> config;
|
||||
|
||||
WritingConverterRegistrationBuilder(Class<T> type, String property, PropertyValueConverterRegistrar<P> config) {
|
||||
WritingConverterRegistrationBuilder(Class<T> type, String property,
|
||||
@NonNull PropertyValueConverterRegistrar<P> config) {
|
||||
|
||||
this.config = config;
|
||||
this.registration = (converter) -> config.registerConverter(type, property, converter);
|
||||
this.registration = converter -> config.registerConverter(type, property, converter);
|
||||
}
|
||||
|
||||
public ReadingConverterRegistrationBuilder<T, S, S, P> writingAsIs() {
|
||||
@@ -146,12 +158,13 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
*/
|
||||
public <R> ReadingConverterRegistrationBuilder<T, S, R, P> writing(
|
||||
BiFunction<S, ValueConversionContext<P>, R> writer) {
|
||||
|
||||
return new ReadingConverterRegistrationBuilder<>(this, writer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper to build a fluent API to register how to read a database value into a domain object property.
|
||||
* Helper class used to build a fluent API to register how to read a database value into a domain object property.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@@ -160,12 +173,14 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
private final WritingConverterRegistrationBuilder<T, S, P> origin;
|
||||
private final BiFunction<S, ValueConversionContext<P>, R> writer;
|
||||
|
||||
ReadingConverterRegistrationBuilder(WritingConverterRegistrationBuilder<T, S, P> origin,
|
||||
BiFunction<S, ValueConversionContext<P>, R> writer) {
|
||||
ReadingConverterRegistrationBuilder(@NonNull WritingConverterRegistrationBuilder<T, S, P> origin,
|
||||
@NonNull BiFunction<S, ValueConversionContext<P>, R> writer) {
|
||||
|
||||
this.origin = origin;
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValueConverterRegistrar<P> readingAsIs() {
|
||||
return reading((source, context) -> (S) source);
|
||||
}
|
||||
@@ -178,8 +193,9 @@ public class PropertyValueConverterRegistrar<P extends PersistentProperty<P>> {
|
||||
* Describes how to read a database value into a domain object's property value.
|
||||
*
|
||||
* @param reader must not be {@literal null}.
|
||||
* @return
|
||||
* @return the confiured {@link PropertyValueConverterRegistrar}.
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public PropertyValueConverterRegistrar<P> reading(BiFunction<R, ValueConversionContext<P>, S> reader) {
|
||||
|
||||
origin.registration.accept(new FunctionPropertyValueConverter(writer, reader));
|
||||
|
||||
@@ -17,73 +17,93 @@ package org.springframework.data.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
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;
|
||||
|
||||
/**
|
||||
* {@link PropertyValueConversions} implementation that allows to pick a {@link PropertyValueConverterFactory} serving
|
||||
* {@link PropertyValueConverter converters}. Activating {@link #setConverterCacheEnabled(boolean) cahing} allows to
|
||||
* reuse converters. Providing a {@link SimplePropertyValueConverterRegistry} adds path configured converter instances.
|
||||
* {@link PropertyValueConversions} implementation allowing a {@link PropertyValueConverterFactory} creating
|
||||
* {@link PropertyValueConverter converters} to be chosen. Activating {@link #setConverterCacheEnabled(boolean) cahing}
|
||||
* allows converters to be reused.
|
||||
* <p>
|
||||
* Should be {@link #afterPropertiesSet() initialized}. If not, {@link #init()} will be called of fist attempt of
|
||||
* {@link PropertyValueConverter converter} retrieval.
|
||||
* Providing a {@link SimplePropertyValueConverterRegistry} adds path configured converter instances.
|
||||
* <p>
|
||||
* This class should be {@link #afterPropertiesSet() initialized}. If not, {@link #init()} will be called on the first
|
||||
* attempt of {@link PropertyValueConverter converter} retrieval.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @see PropertyValueConversions
|
||||
* @see InitializingBean
|
||||
* @since 2.7
|
||||
*/
|
||||
public class SimplePropertyValueConversions implements PropertyValueConversions, InitializingBean {
|
||||
|
||||
private @Nullable PropertyValueConverterFactory converterFactory;
|
||||
private @Nullable ValueConverterRegistry<?> valueConverterRegistry;
|
||||
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;
|
||||
|
||||
private @Nullable PropertyValueConverterFactory converterFactory;
|
||||
|
||||
private @Nullable ValueConverterRegistry<?> valueConverterRegistry;
|
||||
|
||||
/**
|
||||
* Set the {@link PropertyValueConverterFactory factory} responsible for creating the actual
|
||||
* {@link PropertyValueConverter converter}.
|
||||
* Set the {@link PropertyValueConverterFactory} responsible for creating the actual {@link PropertyValueConverter}.
|
||||
*
|
||||
* @param converterFactory must not be {@literal null}.
|
||||
* @param converterFactory {@link PropertyValueConverterFactory} used to create the actual
|
||||
* {@link PropertyValueConverter}.
|
||||
* @see PropertyValueConverterFactory
|
||||
*/
|
||||
public void setConverterFactory(PropertyValueConverterFactory converterFactory) {
|
||||
public void setConverterFactory(@Nullable PropertyValueConverterFactory converterFactory) {
|
||||
this.converterFactory = converterFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured {@link PropertyValueConverterFactory} responsible for creating the actual
|
||||
* {@link PropertyValueConverter}.
|
||||
*
|
||||
* @return the configured {@link PropertyValueConverterFactory}; can be {@literal null}.
|
||||
* @see PropertyValueConverterFactory
|
||||
*/
|
||||
@Nullable
|
||||
public PropertyValueConverterFactory getConverterFactory() {
|
||||
return converterFactory;
|
||||
}
|
||||
|
||||
private PropertyValueConverterFactory obtainConverterFactory() {
|
||||
private @NonNull PropertyValueConverterFactory requireConverterFactory() {
|
||||
|
||||
PropertyValueConverterFactory factory = getConverterFactory();
|
||||
|
||||
if (factory == null) {
|
||||
throw new IllegalStateException(
|
||||
"PropertyValueConverterFactory is not set. Make sure to either set the converter factory or call afterPropertiesSet() to initialize the object.");
|
||||
}
|
||||
Assert.state(factory != null, NO_CONVERTER_FACTORY_ERROR_MESSAGE);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ValueConverterRegistry converter registry} for path configured converters. This is short for adding
|
||||
* a
|
||||
* Set the {@link ValueConverterRegistry converter registry} used for path configured converters.
|
||||
* <p>
|
||||
* This is short for adding a
|
||||
* {@link org.springframework.data.convert.PropertyValueConverterFactories.ConfiguredInstanceServingValueConverterFactory}
|
||||
* at the end of a {@link ChainedPropertyValueConverterFactory}.
|
||||
*
|
||||
* @param valueConverterRegistry must not be {@literal null}.
|
||||
* @param valueConverterRegistry registry of {@link PropertyValueConverter PropertyValueConverters}.
|
||||
* @see ValueConverterRegistry
|
||||
*/
|
||||
public void setValueConverterRegistry(ValueConverterRegistry<?> valueConverterRegistry) {
|
||||
public void setValueConverterRegistry(@Nullable ValueConverterRegistry<?> valueConverterRegistry) {
|
||||
this.valueConverterRegistry = valueConverterRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ValueConverterRegistry} used for path configured converters.
|
||||
*
|
||||
* @return can be {@literal null}.
|
||||
* @return the configured {@link ValueConverterRegistry}; can be {@literal null}.
|
||||
* @see ValueConverterRegistry
|
||||
*/
|
||||
@Nullable
|
||||
public ValueConverterRegistry<?> getValueConverterRegistry() {
|
||||
@@ -91,29 +111,37 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure whether to use converter cache. Enabled by default.
|
||||
* 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}.
|
||||
*
|
||||
* @param property {@link PersistentProperty} to evaluate.
|
||||
* @return {@literal true} if a {@link PropertyValueConverter} has been registered for
|
||||
* the given {@link PersistentProperty property}.
|
||||
* @see PersistentProperty
|
||||
*/
|
||||
@Override
|
||||
public boolean hasValueConverter(PersistentProperty<?> property) {
|
||||
return obtainConverterFactory().getConverter(property) != null;
|
||||
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) {
|
||||
|
||||
PropertyValueConverter<DV, SV, D> converter = obtainConverterFactory().getConverter(property);
|
||||
PropertyValueConverter<DV, SV, D> converter = requireConverterFactory().getConverter(property);
|
||||
|
||||
if (converter == null) {
|
||||
throw new IllegalArgumentException(String.format("No PropertyValueConverter registered for %s", property));
|
||||
}
|
||||
Assert.notNull(converter, String.format("No PropertyValueConverter registered for %s", property));
|
||||
|
||||
return converter;
|
||||
}
|
||||
@@ -125,15 +153,10 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
|
||||
List<PropertyValueConverterFactory> factoryList = new ArrayList<>(3);
|
||||
|
||||
if (converterFactory != null) {
|
||||
factoryList.add(converterFactory);
|
||||
} else {
|
||||
factoryList.add(PropertyValueConverterFactory.simple());
|
||||
}
|
||||
factoryList.add(resolveConverterFactory());
|
||||
|
||||
if ((valueConverterRegistry != null) && !valueConverterRegistry.isEmpty()) {
|
||||
factoryList.add(PropertyValueConverterFactory.configuredInstance(valueConverterRegistry));
|
||||
}
|
||||
resolveConverterRegistryAsConverterFactory()
|
||||
.ifPresent(factoryList::add);
|
||||
|
||||
PropertyValueConverterFactory targetFactory = factoryList.size() > 1
|
||||
? PropertyValueConverterFactory.chained(factoryList)
|
||||
@@ -143,6 +166,26 @@ public class SimplePropertyValueConversions implements PropertyValueConversions,
|
||||
: targetFactory;
|
||||
}
|
||||
|
||||
private @NonNull PropertyValueConverterFactory resolveConverterFactory() {
|
||||
|
||||
PropertyValueConverterFactory converterFactory = getConverterFactory();
|
||||
|
||||
return converterFactory != null ? converterFactory
|
||||
: PropertyValueConverterFactory.simple();
|
||||
}
|
||||
|
||||
private Optional<PropertyValueConverterFactory> resolveConverterRegistryAsConverterFactory() {
|
||||
|
||||
return Optional.ofNullable(getValueConverterRegistry())
|
||||
.filter(it -> !it.isEmpty())
|
||||
.map(PropertyValueConverterFactory::configuredInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this {@link SimplePropertyValueConversions} instance.
|
||||
*
|
||||
* @see #init()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
init();
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.convert;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,7 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Drotbohm
|
||||
* @see org.springframework.data.mapping.PersistentProperty
|
||||
*/
|
||||
public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
|
||||
@@ -36,14 +38,19 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
* Return the {@link PersistentProperty} to be handled.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
* @see org.springframework.data.mapping.PersistentProperty
|
||||
*/
|
||||
P getProperty();
|
||||
|
||||
/**
|
||||
* Write to whatever type is considered best for the given source.
|
||||
* Write the value as an instance of the {@link PersistentProperty#getTypeInformation() property type}.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
* @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}.
|
||||
* @see PersistentProperty#getTypeInformation()
|
||||
* @see #write(Object, TypeInformation)
|
||||
*/
|
||||
@Nullable
|
||||
default Object write(@Nullable Object value) {
|
||||
@@ -51,26 +58,31 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Write as the given type.
|
||||
* Write the value as an instance of {@link Class type}.
|
||||
*
|
||||
* @param value can be {@literal null}.
|
||||
* @param target must not be {@literal null}.
|
||||
* @param value {@link Object value} to write; can be {@literal null}.
|
||||
* @param target {@link Class type} of value to be written; must not be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @throws IllegalStateException if value cannot be written as an instance of {@link Class type}.
|
||||
* @see #write(Object, TypeInformation)
|
||||
* @see ClassTypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T write(@Nullable Object value, Class<T> target) {
|
||||
default <T> T write(@Nullable Object value, @NonNull Class<T> target) {
|
||||
return write(value, ClassTypeInformation.from(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write as the given type.
|
||||
* Write the value as an instance of {@link TypeInformation type}.
|
||||
*
|
||||
* @param value can be {@literal null}.
|
||||
* @param target must not be {@literal null}.
|
||||
* @param value {@link Object value} to write; can be {@literal null}.
|
||||
* @param target {@link TypeInformation type} of value to be written; must not be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @throws IllegalStateException if value cannot be written as an instance of {@link TypeInformation type}.
|
||||
* @see TypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T write(@Nullable Object value, TypeInformation<T> target) {
|
||||
default <T> T write(@Nullable Object value, @NonNull TypeInformation<T> target) {
|
||||
|
||||
if (value == null || target.getType().isInstance(value)) {
|
||||
return target.getType().cast(value);
|
||||
@@ -81,10 +93,14 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value into the type of the current property.
|
||||
* Reads the value as an instance of the {@link PersistentProperty#getTypeInformation() property type}.
|
||||
*
|
||||
* @param value can be {@literal null}.
|
||||
* @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}.
|
||||
* @see PersistentProperty#getTypeInformation()
|
||||
* @see #read(Object, TypeInformation)
|
||||
*/
|
||||
@Nullable
|
||||
default Object read(@Nullable Object value) {
|
||||
@@ -92,32 +108,37 @@ public interface ValueConversionContext<P extends PersistentProperty<P>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value as the given type.
|
||||
* Reads the value as an instance of {@link Class type}.
|
||||
*
|
||||
* @param value can be {@literal null}.
|
||||
* @param target must not be {@literal null}.
|
||||
* @param value {@link Object value} to be read; can be {@literal null}.
|
||||
* @param target {@link Class type} of value to be read; must not be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @throws IllegalStateException if value cannot be read as an instance of {@link Class type}.
|
||||
* @see #read(Object, TypeInformation)
|
||||
* @see ClassTypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T read(@Nullable Object value, Class<T> target) {
|
||||
default <T> T read(@Nullable Object value, @NonNull Class<T> target) {
|
||||
return read(value, ClassTypeInformation.from(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value as the given type.
|
||||
* Reads the value as an instance of {@link TypeInformation type}.
|
||||
*
|
||||
* @param value can be {@literal null}.
|
||||
* @param target must not be {@literal null}.
|
||||
* @param value {@link Object value} to be read; can be {@literal null}.
|
||||
* @param target {@link TypeInformation type} of value to be read; must not be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @throws IllegalStateException if value cannot be read as an instance of {@link TypeInformation type}.
|
||||
* @see TypeInformation
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T read(@Nullable Object value, TypeInformation<T> target) {
|
||||
default <T> T read(@Nullable Object value, @NonNull TypeInformation<T> target) {
|
||||
|
||||
if (value == null || target.getType().isInstance(value)) {
|
||||
return target.getType().cast(value);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format(
|
||||
"%s does not provide write function that allows value conversion to target type (%s).", getClass(), target));
|
||||
"%s does not provide read function that allows value conversion to target type (%s).", getClass(), target));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,17 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A registry of property-specific {@link PropertyValueConverter value converters} to convert only specific
|
||||
* properties/values of an object.
|
||||
* A registry of {@link PersistentProperty property-specific} {@link PropertyValueConverter value converters}
|
||||
* to convert only specific properties/values of an object.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @see PropertyValueConverter
|
||||
* @since 2.7
|
||||
*/
|
||||
public interface ValueConverterRegistry<P extends PersistentProperty<P>> {
|
||||
|
||||
/**
|
||||
* Register the {@link PropertyValueConverter} for the property of the given type.
|
||||
* Register the {@link PropertyValueConverter} for the {@link PersistentProperty property} of the given type.
|
||||
*
|
||||
* @param type the target type. Must not be {@literal null}.
|
||||
* @param path the property name. Must not be {@literal null}.
|
||||
@@ -38,12 +39,13 @@ public interface ValueConverterRegistry<P extends PersistentProperty<P>> {
|
||||
PropertyValueConverter<?, ?, ? extends ValueConversionContext<P>> converter);
|
||||
|
||||
/**
|
||||
* Obtain the converter registered for the given type, path combination or {@literal null} if none defined.
|
||||
* Obtain the {@link PropertyValueConverter} registered for the given type, path combination or {@literal null}
|
||||
* if none defined.
|
||||
*
|
||||
* @param type the target type. Must not be {@literal null}.
|
||||
* @param path the property name. Must not be {@literal null}.
|
||||
* @param <DV>
|
||||
* @param <SV>
|
||||
* @param <DV> domain-specific type.
|
||||
* @param <SV> store-specific type.
|
||||
* @return {@literal null} if no converter present for the given type/path combination.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -54,7 +56,7 @@ public interface ValueConverterRegistry<P extends PersistentProperty<P>> {
|
||||
*
|
||||
* @param type the target type. Must not be {@literal null}.
|
||||
* @param path the property name. Must not be {@literal null}.
|
||||
* @return {@literal false} if no converter present for the given type/path combination.
|
||||
* @return {@literal false} if no converter is present for the given type/path combination.
|
||||
*/
|
||||
default boolean containsConverterFor(Class<?> type, String path) {
|
||||
return getConverter(type, path) != null;
|
||||
@@ -68,10 +70,10 @@ public interface ValueConverterRegistry<P extends PersistentProperty<P>> {
|
||||
/**
|
||||
* Obtain a simple {@link ValueConverterRegistry}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param <P> {@link PersistentProperty} type.
|
||||
* @return new instance of {@link ValueConverterRegistry}.
|
||||
*/
|
||||
static <T extends PersistentProperty<T>> ValueConverterRegistry<T> simple() {
|
||||
static <P extends PersistentProperty<P>> ValueConverterRegistry<P> simple() {
|
||||
return new SimplePropertyValueConverterRegistry<>();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user