diff --git a/src/main/java/org/springframework/data/convert/CustomConversions.java b/src/main/java/org/springframework/data/convert/CustomConversions.java index f2e26f860..59a787f72 100644 --- a/src/main/java/org/springframework/data/convert/CustomConversions.java +++ b/src/main/java/org/springframework/data/convert/CustomConversions.java @@ -33,6 +33,7 @@ import java.util.stream.Collectors; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.core.GenericTypeResolver; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.convert.converter.Converter; @@ -42,7 +43,6 @@ import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.convert.ConverterBuilder.ConverterAware; -import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.util.Predicates; import org.springframework.data.util.Streamable; @@ -183,35 +183,9 @@ public class CustomConversions { VavrCollectionConverters.getConvertersToRegister().forEach(it -> registerConverterIn(it, conversionService)); } - /** - * Delegate check if a {@link PropertyValueConverter} for the given {@literal property} is present via - * {@link PropertyValueConversions}. - * - * @param property must not be {@literal null}. - * @return {@literal true} if a specific {@link PropertyValueConverter} is available. - * @see PropertyValueConversions#hasValueConverter(PersistentProperty) - * @since 2.7 - */ - public boolean hasPropertyValueConverter(PersistentProperty property) { - return propertyValueConversions != null && propertyValueConversions.hasValueConverter(property); - } - - /** - * Delegate to obtain the {@link PropertyValueConverter} for the given {@literal property} from - * {@link PropertyValueConversions}. - * - * @param property must not be {@literal null}. - * @param domain-specific type - * @param store-native type - * @param conversion context type - * @return the suitable {@link PropertyValueConverter} or {@literal null} if none available. - * @see PropertyValueConversions#getValueConverter(PersistentProperty) - * @since 2.7 - */ @Nullable - public , VCC extends ValueConversionContext> PropertyValueConverter getPropertyValueConverter( - C property) { - return propertyValueConversions != null ? propertyValueConversions.getValueConverter(property) : null; + public PropertyValueConversions getPropertyValueConversions() { + return propertyValueConversions; } /** diff --git a/src/main/java/org/springframework/data/convert/PropertyValueConversionService.java b/src/main/java/org/springframework/data/convert/PropertyValueConversionService.java index 4df6bdeda..1c2854557 100644 --- a/src/main/java/org/springframework/data/convert/PropertyValueConversionService.java +++ b/src/main/java/org/springframework/data/convert/PropertyValueConversionService.java @@ -28,13 +28,14 @@ import org.springframework.util.Assert; */ public class PropertyValueConversionService { - private final CustomConversions conversions; + private final PropertyValueConversions conversions; public PropertyValueConversionService(CustomConversions conversions) { Assert.notNull(conversions, "CustomConversions must not be null"); - this.conversions = conversions; + PropertyValueConversions pvc = conversions.getPropertyValueConversions(); + this.conversions = pvc == null ? NoOpPropertyValueConversions.INSTANCE : pvc; } /** @@ -47,7 +48,7 @@ public class PropertyValueConversionService { * @return {@literal true} there is a converter registered for {@link PersistentProperty}. */ public boolean hasConverter(PersistentProperty property) { - return conversions.hasPropertyValueConverter(property); + return conversions.hasValueConverter(property); } /** @@ -64,7 +65,8 @@ public class PropertyValueConversionService { public

, VCC extends ValueConversionContext

> Object read(@Nullable Object value, P property, VCC context) { - PropertyValueConverter> converter = getRequiredConverter(property); + PropertyValueConverter> converter = conversions + .getValueConverter(property); if (value == null) { return converter.readNull(context); @@ -87,7 +89,8 @@ public class PropertyValueConversionService { public

, VCC extends ValueConversionContext

> Object write(@Nullable Object value, P property, VCC context) { - PropertyValueConverter> converter = getRequiredConverter(property); + PropertyValueConverter> converter = conversions + .getValueConverter(property); if (value == null) { return converter.writeNull(context); @@ -96,16 +99,19 @@ public class PropertyValueConversionService { return converter.write(value, context); } - private

> PropertyValueConverter> getRequiredConverter( - P property) { + enum NoOpPropertyValueConversions implements PropertyValueConversions { - PropertyValueConverter> converter = conversions - .getPropertyValueConverter(property); + INSTANCE; - if (converter == null) { - throw new IllegalArgumentException(String.format("No converter registered for property %s", property)); + @Override + public boolean hasValueConverter(PersistentProperty property) { + return false; } - return converter; + @Override + public , VCC extends ValueConversionContext

> PropertyValueConverter getValueConverter( + P property) { + throw new UnsupportedOperationException(); + } } } diff --git a/src/main/java/org/springframework/data/convert/PropertyValueConversions.java b/src/main/java/org/springframework/data/convert/PropertyValueConversions.java index cfb55190e..e3034da49 100644 --- a/src/main/java/org/springframework/data/convert/PropertyValueConversions.java +++ b/src/main/java/org/springframework/data/convert/PropertyValueConversions.java @@ -45,11 +45,13 @@ public interface PropertyValueConversions { * @param property must not be {@literal null}. * @param domain-specific type * @param store-native type - * @param conversion context type + * @param

conversion context type * @return the suitable {@link PropertyValueConverter}. + * @throws IllegalArgumentException if there is no converter available for {@code property}. + * @see #hasValueConverter(PersistentProperty) */ - , VCC extends ValueConversionContext> PropertyValueConverter getValueConverter( - C property); + , VCC extends ValueConversionContext

> PropertyValueConverter getValueConverter( + P property); /** * Helper that allows to create {@link PropertyValueConversions} instance with the configured diff --git a/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java b/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java index c87fa5216..93f0cd3f8 100644 --- a/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java +++ b/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java @@ -46,12 +46,12 @@ public interface PropertyValueConverterFactory { * @param property must not be {@literal null}. * @param domain-specific type. * @param store-native type. - * @param value conversion context to use. + * @param

value conversion context to use. * @return can be {@literal null}. */ @SuppressWarnings("unchecked") @Nullable - default > PropertyValueConverter getConverter( + default > PropertyValueConverter getConverter( PersistentProperty property) { AnnotatedPropertyValueConverterAccessor accessor = new AnnotatedPropertyValueConverterAccessor(property); @@ -60,7 +60,7 @@ public interface PropertyValueConverterFactory { return null; } - return getConverter((Class>) accessor.getValueConverterType()); + return getConverter((Class>) accessor.getValueConverterType()); } /** diff --git a/src/main/java/org/springframework/data/convert/SimplePropertyValueConversions.java b/src/main/java/org/springframework/data/convert/SimplePropertyValueConversions.java index e1a128f3a..bb58214be 100644 --- a/src/main/java/org/springframework/data/convert/SimplePropertyValueConversions.java +++ b/src/main/java/org/springframework/data/convert/SimplePropertyValueConversions.java @@ -105,11 +105,17 @@ public class SimplePropertyValueConversions implements PropertyValueConversions, return obtainConverterFactory().getConverter(property) != null; } - @Nullable @Override - public , D extends ValueConversionContext> PropertyValueConverter getValueConverter( - C property) { - return obtainConverterFactory().getConverter(property); + public , D extends ValueConversionContext

> PropertyValueConverter getValueConverter( + P property) { + + PropertyValueConverter converter = obtainConverterFactory().getConverter(property); + + if (converter == null) { + throw new IllegalArgumentException(String.format("No PropertyValueConverter registered for %s", property)); + } + + return converter; } /** diff --git a/src/test/java/org/springframework/data/convert/CustomConversionsUnitTests.java b/src/test/java/org/springframework/data/convert/CustomConversionsUnitTests.java index 9a337381a..041123222 100644 --- a/src/test/java/org/springframework/data/convert/CustomConversionsUnitTests.java +++ b/src/test/java/org/springframework/data/convert/CustomConversionsUnitTests.java @@ -42,7 +42,6 @@ import org.springframework.data.convert.CustomConversions.ConverterConfiguration import org.springframework.data.convert.CustomConversions.StoreConversions; import org.springframework.data.convert.Jsr310Converters.LocalDateTimeToDateConverter; import org.springframework.data.geo.Point; -import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.model.SimpleTypeHolder; /** @@ -267,30 +266,17 @@ class CustomConversionsUnitTests { ConfigurableConversionService conversionService = new DefaultConversionService(); - new CustomConversions(StoreConversions.NONE, Collections.emptyList()) - .registerConvertersIn(conversionService); + new CustomConversions(StoreConversions.NONE, Collections.emptyList()).registerConvertersIn(conversionService); assertThat(conversionService.canConvert(io.vavr.collection.List.class, List.class)).isTrue(); assertThat(conversionService.canConvert(List.class, io.vavr.collection.List.class)).isTrue(); } - @Test // GH-1484 - void allowsToRegisterPropertyConversions() { - - PropertyValueConversions propertyValueConversions = mock(PropertyValueConversions.class); - when(propertyValueConversions.getValueConverter(any())).thenReturn(mock(PropertyValueConverter.class)); - - CustomConversions conversions = new CustomConversions(new ConverterConfiguration(StoreConversions.NONE, - Collections.emptyList(), (it) -> true, propertyValueConversions)); - assertThat(conversions.getPropertyValueConverter(mock(PersistentProperty.class))).isNotNull(); - } - @Test // GH-1484 void doesNotFailIfPropertiesConversionIsNull() { - CustomConversions conversions = new CustomConversions(new ConverterConfiguration(StoreConversions.NONE, - Collections.emptyList(), (it) -> true, null)); - assertThat(conversions.getPropertyValueConverter(mock(PersistentProperty.class))).isNull(); + new CustomConversions( + new ConverterConfiguration(StoreConversions.NONE, Collections.emptyList(), (it) -> true, null)); } private static Class createProxyTypeFor(Class type) {