From 3392513d668825ac1bbeda1565f30673e0f19a68 Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Sun, 3 Oct 2021 18:09:35 +0200 Subject: [PATCH 1/3] minor refactorings --- .../{RangeTests.java => RangeUnitTests.java} | 52 +++++-------------- ...appingElasticsearchConverterUnitTests.java | 2 +- 2 files changed, 13 insertions(+), 41 deletions(-) rename src/test/java/org/springframework/data/elasticsearch/core/{RangeTests.java => RangeUnitTests.java} (87%) diff --git a/src/test/java/org/springframework/data/elasticsearch/core/RangeTests.java b/src/test/java/org/springframework/data/elasticsearch/core/RangeUnitTests.java similarity index 87% rename from src/test/java/org/springframework/data/elasticsearch/core/RangeTests.java rename to src/test/java/org/springframework/data/elasticsearch/core/RangeUnitTests.java index d4299a6b1..9642d329b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/RangeTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/RangeUnitTests.java @@ -26,14 +26,11 @@ * @author Sascha Woo * @since 4.3 */ -public class RangeTests { +public class RangeUnitTests { @Test public void shouldContainsLocalDate() { - // given - // when - // then assertThat(Range.open(LocalDate.of(2021, 1, 1), LocalDate.of(2021, 2, 1)).contains(LocalDate.of(2021, 1, 10))) .isTrue(); } @@ -41,21 +38,17 @@ public void shouldContainsLocalDate() { @Test public void shouldEqualToSameRange() { - // given Range range1 = Range.open(LocalDate.of(2021, 1, 1), LocalDate.of(2021, 2, 1)); Range range2 = Range.open(LocalDate.of(2021, 1, 1), LocalDate.of(2021, 2, 1)); - // when - // then + assertThat(range1).isEqualTo(range2); } @Test public void shouldHaveClosedBoundaries() { - // given Range range = Range.closed(1, 3); - // when - // then + assertThat(range.contains(1)).isTrue(); assertThat(range.contains(2)).isTrue(); assertThat(range.contains(3)).isTrue(); @@ -64,10 +57,8 @@ public void shouldHaveClosedBoundaries() { @Test public void shouldHaveJustOneValue() { - // given Range range = Range.just(2); - // when - // then + assertThat(range.contains(1)).isFalse(); assertThat(range.contains(2)).isTrue(); assertThat(range.contains(3)).isFalse(); @@ -76,10 +67,8 @@ public void shouldHaveJustOneValue() { @Test public void shouldHaveLeftOpenBoundary() { - // given Range range = Range.leftOpen(1, 3); - // when - // then + assertThat(range.contains(1)).isFalse(); assertThat(range.contains(2)).isTrue(); assertThat(range.contains(3)).isTrue(); @@ -88,10 +77,8 @@ public void shouldHaveLeftOpenBoundary() { @Test public void shouldHaveLeftUnboundedAndRightExclusive() { - // given Range range = Range.leftUnbounded(Range.Bound.exclusive(3)); - // when - // then + assertThat(range.contains(0)).isTrue(); assertThat(range.contains(1)).isTrue(); assertThat(range.contains(2)).isTrue(); @@ -101,10 +88,8 @@ public void shouldHaveLeftUnboundedAndRightExclusive() { @Test public void shouldHaveLeftUnboundedAndRightInclusive() { - // given Range range = Range.leftUnbounded(Range.Bound.inclusive(3)); - // when - // then + assertThat(range.contains(0)).isTrue(); assertThat(range.contains(1)).isTrue(); assertThat(range.contains(2)).isTrue(); @@ -114,10 +99,8 @@ public void shouldHaveLeftUnboundedAndRightInclusive() { @Test public void shouldHaveOpenBoundaries() { - // given Range range = Range.open(1, 3); - // when - // then + assertThat(range.contains(1)).isFalse(); assertThat(range.contains(2)).isTrue(); assertThat(range.contains(3)).isFalse(); @@ -126,10 +109,8 @@ public void shouldHaveOpenBoundaries() { @Test public void shouldHaveRightOpenBoundary() { - // given Range range = Range.rightOpen(1, 3); - // when - // then + assertThat(range.contains(1)).isTrue(); assertThat(range.contains(2)).isTrue(); assertThat(range.contains(3)).isFalse(); @@ -138,10 +119,8 @@ public void shouldHaveRightOpenBoundary() { @Test public void shouldHaveRightUnboundedAndLeftExclusive() { - // given Range range = Range.rightUnbounded(Range.Bound.exclusive(1)); - // when - // then + assertThat(range.contains(1)).isFalse(); assertThat(range.contains(2)).isTrue(); assertThat(range.contains(3)).isTrue(); @@ -151,10 +130,8 @@ public void shouldHaveRightUnboundedAndLeftExclusive() { @Test public void shouldHaveRightUnboundedAndLeftInclusive() { - // given Range range = Range.rightUnbounded(Range.Bound.inclusive(1)); - // when - // then + assertThat(range.contains(1)).isTrue(); assertThat(range.contains(2)).isTrue(); assertThat(range.contains(3)).isTrue(); @@ -164,12 +141,7 @@ public void shouldHaveRightUnboundedAndLeftInclusive() { @Test public void shouldThrowExceptionIfNotComparable() { - // given - // when - Throwable thrown = catchThrowable(() -> Range.just(Collections.singletonList("test"))); - // then - assertThat(thrown).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> Range.just(Collections.singletonList("test"))).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("value must implements Comparable!"); } - } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java index aab41993b..82e4835ad 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java @@ -893,7 +893,7 @@ void shouldWriteNullValueIfConfigured() throws JSONException { class RangeTests { static final String JSON = "{" - + "\"_class\":\"org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$RangeTests$RangeEntity\"," + + "\"_class\":\"org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$RangeUnitTests$RangeEntity\"," + "\"integerRange\":{\"gt\":\"1\",\"lt\":\"10\"}," // + "\"floatRange\":{\"gte\":\"1.2\",\"lte\":\"2.5\"}," // + "\"longRange\":{\"gt\":\"2\",\"lte\":\"5\"}," // From 93d6282e7e6966e62d93f743689413de7a503e8a Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Tue, 5 Oct 2021 07:46:41 +0200 Subject: [PATCH 2/3] rename to PropertyValueConverter --- ...elasticsearch-migration-guide-4.2-4.3.adoc | 5 +++ ...va => AbstractPropertyValueConverter.java} | 6 ++-- ... AbstractRangePropertyValueConverter.java} | 4 +-- ...r.java => DatePropertyValueConverter.java} | 7 ++-- ...a => DateRangePropertyValueConverter.java} | 6 ++-- .../core/convert/ElasticsearchConverter.java | 4 +-- .../MappingElasticsearchConverter.java | 36 +++++++++---------- ...=> NumberRangePropertyValueConverter.java} | 4 +-- ...va => TemporalPropertyValueConverter.java} | 6 ++-- ... TemporalRangePropertyValueConverter.java} | 7 ++-- .../ElasticsearchPersistentProperty.java | 6 ++-- ...erter.java => PropertyValueConverter.java} | 14 ++++---- ...SimpleElasticsearchPersistentProperty.java | 26 +++++++------- ...appingElasticsearchConverterUnitTests.java | 2 +- ...sticsearchPersistentPropertyUnitTests.java | 16 ++++----- 15 files changed, 76 insertions(+), 73 deletions(-) rename src/main/java/org/springframework/data/elasticsearch/core/convert/{AbstractPersistentPropertyConverter.java => AbstractPropertyValueConverter.java} (78%) rename src/main/java/org/springframework/data/elasticsearch/core/convert/{AbstractRangePersistentPropertyConverter.java => AbstractRangePropertyValueConverter.java} (94%) rename src/main/java/org/springframework/data/elasticsearch/core/convert/{DatePersistentPropertyConverter.java => DatePropertyValueConverter.java} (87%) rename src/main/java/org/springframework/data/elasticsearch/core/convert/{DateRangePersistentPropertyConverter.java => DateRangePropertyValueConverter.java} (87%) rename src/main/java/org/springframework/data/elasticsearch/core/convert/{NumberRangePersistentPropertyConverter.java => NumberRangePropertyValueConverter.java} (88%) rename src/main/java/org/springframework/data/elasticsearch/core/convert/{TemporalPersistentPropertyConverter.java => TemporalPropertyValueConverter.java} (90%) rename src/main/java/org/springframework/data/elasticsearch/core/convert/{TemporalRangePersistentPropertyConverter.java => TemporalRangePropertyValueConverter.java} (88%) rename src/main/java/org/springframework/data/elasticsearch/core/mapping/{ElasticsearchPersistentPropertyConverter.java => PropertyValueConverter.java} (64%) diff --git a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.2-4.3.adoc b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.2-4.3.adoc index 1b98c5cee..2458de686 100644 --- a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.2-4.3.adoc +++ b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.2-4.3.adoc @@ -71,3 +71,8 @@ Spring Data Elasticsearch now uses `org.springframework.data.elasticsearch.core. === Completion classes The classes from the package `org.springframework.data.elasticsearch.core.completion` have been moved to `org.springframework.data.elasticsearch.core.suggest`. + +=== Other renamings + +The `org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter` interface has been renamed to `org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter`. +Likewise the implementations classes named _XXPersistentPropertyConverter_ have been renamed to _XXPropertyValueConverter_. diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractPersistentPropertyConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractPropertyValueConverter.java similarity index 78% rename from src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractPersistentPropertyConverter.java rename to src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractPropertyValueConverter.java index 44a06beb5..65381ccf1 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractPersistentPropertyConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractPropertyValueConverter.java @@ -15,7 +15,7 @@ */ package org.springframework.data.elasticsearch.core.convert; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter; +import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter; import org.springframework.data.mapping.PersistentProperty; import org.springframework.util.Assert; @@ -23,11 +23,11 @@ * @author Sascha Woo * @since 4.3 */ -public abstract class AbstractPersistentPropertyConverter implements ElasticsearchPersistentPropertyConverter { +public abstract class AbstractPropertyValueConverter implements PropertyValueConverter { private final PersistentProperty property; - public AbstractPersistentPropertyConverter(PersistentProperty property) { + public AbstractPropertyValueConverter(PersistentProperty property) { Assert.notNull(property, "property must not be null."); this.property = property; diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractRangePersistentPropertyConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractRangePropertyValueConverter.java similarity index 94% rename from src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractRangePersistentPropertyConverter.java rename to src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractRangePropertyValueConverter.java index 223f82f4f..09a89db09 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractRangePersistentPropertyConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/AbstractRangePropertyValueConverter.java @@ -26,14 +26,14 @@ * @author Sascha Woo * @since 4.3 */ -public abstract class AbstractRangePersistentPropertyConverter extends AbstractPersistentPropertyConverter { +public abstract class AbstractRangePropertyValueConverter extends AbstractPropertyValueConverter { protected static final String LT_FIELD = "lt"; protected static final String LTE_FIELD = "lte"; protected static final String GT_FIELD = "gt"; protected static final String GTE_FIELD = "gte"; - public AbstractRangePersistentPropertyConverter(PersistentProperty property) { + public AbstractRangePropertyValueConverter(PersistentProperty property) { super(property); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/DatePersistentPropertyConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/DatePropertyValueConverter.java similarity index 87% rename from src/main/java/org/springframework/data/elasticsearch/core/convert/DatePersistentPropertyConverter.java rename to src/main/java/org/springframework/data/elasticsearch/core/convert/DatePropertyValueConverter.java index 27b0bc635..1bc8b3685 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/DatePersistentPropertyConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/DatePropertyValueConverter.java @@ -26,14 +26,13 @@ * @author Sascha Woo * @since 4.3 */ -public class DatePersistentPropertyConverter extends AbstractPersistentPropertyConverter { +public class DatePropertyValueConverter extends AbstractPropertyValueConverter { - private static final Logger LOGGER = LoggerFactory.getLogger(DatePersistentPropertyConverter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DatePropertyValueConverter.class); private final List dateConverters; - public DatePersistentPropertyConverter(PersistentProperty property, - List dateConverters) { + public DatePropertyValueConverter(PersistentProperty property, List dateConverters) { super(property); this.dateConverters = dateConverters; diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/DateRangePersistentPropertyConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/DateRangePropertyValueConverter.java similarity index 87% rename from src/main/java/org/springframework/data/elasticsearch/core/convert/DateRangePersistentPropertyConverter.java rename to src/main/java/org/springframework/data/elasticsearch/core/convert/DateRangePropertyValueConverter.java index b628a79f1..e4cf4f37f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/DateRangePersistentPropertyConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/DateRangePropertyValueConverter.java @@ -26,13 +26,13 @@ * @author Sascha Woo * @since 4.3 */ -public class DateRangePersistentPropertyConverter extends AbstractRangePersistentPropertyConverter { +public class DateRangePropertyValueConverter extends AbstractRangePropertyValueConverter { - private static final Logger LOGGER = LoggerFactory.getLogger(DateRangePersistentPropertyConverter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DateRangePropertyValueConverter.class); private final List dateConverters; - public DateRangePersistentPropertyConverter(PersistentProperty property, + public DateRangePropertyValueConverter(PersistentProperty property, List dateConverters) { super(property); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java index 284543220..ab1b7cdb1 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchConverter.java @@ -19,6 +19,7 @@ import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; +import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter; import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; @@ -93,8 +94,7 @@ default Document mapObject(@Nullable Object source) { /** * Updates a {@link Query} by renaming the property names in the query to the correct mapped field names and the * values to the converted values if the {@link ElasticsearchPersistentProperty} for a property has a - * {@link org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter}. If - * domainClass is null it's a noop. + * {@link PropertyValueConverter}. If domainClass is null it's a noop. * * @param query the query that is internally updated, must not be {@literal null} * @param domainClass the class of the object that is searched with the query diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java index 3189cacb2..ba2dc18dc 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java @@ -39,7 +39,7 @@ import org.springframework.data.elasticsearch.core.document.SearchDocument; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; -import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter; +import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter; import org.springframework.data.elasticsearch.core.query.Criteria; import org.springframework.data.elasticsearch.core.query.CriteriaQuery; import org.springframework.data.elasticsearch.core.query.FetchSourceFilter; @@ -426,7 +426,8 @@ protected R readValue(@Nullable Object value, ElasticsearchPersistentPropert Class rawType = type.getType(); if (property.hasPropertyConverter()) { - value = propertyConverterRead(property, value); + // noinspection unchecked + return (R) propertyConverterRead(property, value); } else if (TemporalAccessor.class.isAssignableFrom(property.getType()) && !conversions.hasCustomReadTarget(value.getClass(), rawType)) { @@ -466,8 +467,7 @@ private T readValue(Object value, TypeInformation type) { } private Object propertyConverterRead(ElasticsearchPersistentProperty property, Object source) { - ElasticsearchPersistentPropertyConverter propertyConverter = Objects - .requireNonNull(property.getPropertyConverter()); + PropertyValueConverter propertyValueConverter = Objects.requireNonNull(property.getPropertyValueConverter()); if (source instanceof String[]) { // convert to a List @@ -475,18 +475,19 @@ private Object propertyConverterRead(ElasticsearchPersistentProperty property, O } if (source instanceof List) { - source = ((List) source).stream().map(it -> convertOnRead(propertyConverter, it)) + source = ((List) source).stream().map(it -> convertOnRead(propertyValueConverter, it)) .collect(Collectors.toList()); } else if (source instanceof Set) { - source = ((Set) source).stream().map(it -> convertOnRead(propertyConverter, it)).collect(Collectors.toSet()); + source = ((Set) source).stream().map(it -> convertOnRead(propertyValueConverter, it)) + .collect(Collectors.toSet()); } else { - source = convertOnRead(propertyConverter, source); + source = convertOnRead(propertyValueConverter, source); } return source; } - private Object convertOnRead(ElasticsearchPersistentPropertyConverter propertyConverter, Object source) { - return propertyConverter.read(source); + private Object convertOnRead(PropertyValueConverter propertyValueConverter, Object source) { + return propertyValueConverter.read(source); } /** @@ -1070,15 +1071,14 @@ private Object getPotentiallyConvertedSimpleWrite(@Nullable Object value, @Nulla } private Object propertyConverterWrite(ElasticsearchPersistentProperty property, Object value) { - ElasticsearchPersistentPropertyConverter propertyConverter = Objects - .requireNonNull(property.getPropertyConverter()); + PropertyValueConverter propertyValueConverter = Objects.requireNonNull(property.getPropertyValueConverter()); if (value instanceof List) { - value = ((List) value).stream().map(propertyConverter::write).collect(Collectors.toList()); + value = ((List) value).stream().map(propertyValueConverter::write).collect(Collectors.toList()); } else if (value instanceof Set) { - value = ((Set) value).stream().map(propertyConverter::write).collect(Collectors.toSet()); + value = ((Set) value).stream().map(propertyValueConverter::write).collect(Collectors.toSet()); } else { - value = propertyConverter.write(value); + value = propertyValueConverter.write(value); } return value; } @@ -1253,17 +1253,17 @@ private void updateCriteria(Criteria criteria, ElasticsearchPersistentEntity if (persistentProperty != null) { if (persistentProperty.hasPropertyConverter()) { - ElasticsearchPersistentPropertyConverter propertyConverter = Objects - .requireNonNull(persistentProperty.getPropertyConverter()); + PropertyValueConverter propertyValueConverter = Objects + .requireNonNull(persistentProperty.getPropertyValueConverter()); criteria.getQueryCriteriaEntries().forEach(criteriaEntry -> { Object value = criteriaEntry.getValue(); if (value.getClass().isArray()) { Object[] objects = (Object[]) value; for (int i = 0; i < objects.length; i++) { - objects[i] = propertyConverter.write(objects[i]); + objects[i] = propertyValueConverter.write(objects[i]); } } else { - criteriaEntry.setValue(propertyConverter.write(value)); + criteriaEntry.setValue(propertyValueConverter.write(value)); } }); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/NumberRangePersistentPropertyConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/NumberRangePropertyValueConverter.java similarity index 88% rename from src/main/java/org/springframework/data/elasticsearch/core/convert/NumberRangePersistentPropertyConverter.java rename to src/main/java/org/springframework/data/elasticsearch/core/convert/NumberRangePropertyValueConverter.java index 76b819e69..78255e74f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/NumberRangePersistentPropertyConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/NumberRangePropertyValueConverter.java @@ -21,9 +21,9 @@ * @author Sascha Woo * @since 4.3 */ -public class NumberRangePersistentPropertyConverter extends AbstractRangePersistentPropertyConverter { +public class NumberRangePropertyValueConverter extends AbstractRangePropertyValueConverter { - public NumberRangePersistentPropertyConverter(PersistentProperty property) { + public NumberRangePropertyValueConverter(PersistentProperty property) { super(property); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalPersistentPropertyConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalPropertyValueConverter.java similarity index 90% rename from src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalPersistentPropertyConverter.java rename to src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalPropertyValueConverter.java index 2cdd167e9..357b49dde 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalPersistentPropertyConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalPropertyValueConverter.java @@ -26,13 +26,13 @@ * @author Sascha Woo * @since 4.3 */ -public class TemporalPersistentPropertyConverter extends AbstractPersistentPropertyConverter { +public class TemporalPropertyValueConverter extends AbstractPropertyValueConverter { - private static final Logger LOGGER = LoggerFactory.getLogger(TemporalPersistentPropertyConverter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(TemporalPropertyValueConverter.class); private final List dateConverters; - public TemporalPersistentPropertyConverter(PersistentProperty property, + public TemporalPropertyValueConverter(PersistentProperty property, List dateConverters) { super(property); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalRangePersistentPropertyConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalRangePropertyValueConverter.java similarity index 88% rename from src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalRangePersistentPropertyConverter.java rename to src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalRangePropertyValueConverter.java index 6111846eb..39cb85dd6 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalRangePersistentPropertyConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/TemporalRangePropertyValueConverter.java @@ -27,14 +27,13 @@ * @author Sascha Woo * @since 4.3 */ -public class TemporalRangePersistentPropertyConverter - extends AbstractRangePersistentPropertyConverter { +public class TemporalRangePropertyValueConverter extends AbstractRangePropertyValueConverter { - private static final Logger LOGGER = LoggerFactory.getLogger(TemporalRangePersistentPropertyConverter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(TemporalRangePropertyValueConverter.class); private final List dateConverters; - public TemporalRangePersistentPropertyConverter(PersistentProperty property, + public TemporalRangePropertyValueConverter(PersistentProperty property, List dateConverters) { super(property); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java index 1195ad33a..0c48c4e77 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java @@ -48,17 +48,17 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty genericType = getTypeInformation().getTypeArguments().get(0).getType(); if (TemporalAccessor.class.isAssignableFrom(genericType)) { - propertyConverter = new TemporalRangePersistentPropertyConverter(this, dateConverters); + propertyConverter = new TemporalRangePropertyValueConverter(this, dateConverters); } else if (Date.class.isAssignableFrom(genericType)) { - propertyConverter = new DateRangePersistentPropertyConverter(this, dateConverters); + propertyConverter = new DateRangePropertyValueConverter(this, dateConverters); } else { LOGGER.warn("Unsupported generic type '{}' for date range property '{}'.", genericType, getName()); } @@ -205,7 +205,7 @@ private void initPropertyConverter() { return; } - propertyConverter = new NumberRangePersistentPropertyConverter(this); + propertyConverter = new NumberRangePropertyValueConverter(this); break; } case Ip_Range: { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java index 82e4835ad..aab41993b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java @@ -893,7 +893,7 @@ void shouldWriteNullValueIfConfigured() throws JSONException { class RangeTests { static final String JSON = "{" - + "\"_class\":\"org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$RangeUnitTests$RangeEntity\"," + + "\"_class\":\"org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$RangeTests$RangeEntity\"," + "\"integerRange\":{\"gt\":\"1\",\"lt\":\"10\"}," // + "\"floatRange\":{\"gte\":\"1.2\",\"lte\":\"2.5\"}," // + "\"longRange\":{\"gt\":\"2\",\"lte\":\"5\"}," // diff --git a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java index fcf02f7c5..d930d5b76 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java @@ -93,19 +93,19 @@ void shouldSetPropertyConverters() { ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate"); assertThat(persistentProperty.hasPropertyConverter()).isTrue(); - assertThat(persistentProperty.getPropertyConverter()).isNotNull(); + assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); persistentProperty = persistentEntity.getRequiredPersistentProperty("localDateTime"); assertThat(persistentProperty.hasPropertyConverter()).isTrue(); - assertThat(persistentProperty.getPropertyConverter()).isNotNull(); + assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); persistentProperty = persistentEntity.getRequiredPersistentProperty("legacyDate"); assertThat(persistentProperty.hasPropertyConverter()).isTrue(); - assertThat(persistentProperty.getPropertyConverter()).isNotNull(); + assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); persistentProperty = persistentEntity.getRequiredPersistentProperty("localDateList"); assertThat(persistentProperty.hasPropertyConverter()).isTrue(); - assertThat(persistentProperty.getPropertyConverter()).isNotNull(); + assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); } @Test // DATAES-716 @@ -114,7 +114,7 @@ void shouldConvertFromLocalDate() { ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate"); LocalDate localDate = LocalDate.of(2019, 12, 27); - String converted = persistentProperty.getPropertyConverter().write(localDate).toString(); + String converted = persistentProperty.getPropertyValueConverter().write(localDate).toString(); assertThat(converted).isEqualTo("27.12.2019"); } @@ -124,7 +124,7 @@ void shouldConvertToLocalDate() { SimpleElasticsearchPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class); ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate"); - Object converted = persistentProperty.getPropertyConverter().read("27.12.2019"); + Object converted = persistentProperty.getPropertyValueConverter().read("27.12.2019"); assertThat(converted).isInstanceOf(LocalDate.class); assertThat(converted).isEqualTo(LocalDate.of(2019, 12, 27)); @@ -138,7 +138,7 @@ void shouldConvertFromLegacyDate() { .from(ZonedDateTime.of(LocalDateTime.of(2020, 4, 19, 19, 44), ZoneId.of("UTC"))); Date legacyDate = calendar.getTime(); - String converted = persistentProperty.getPropertyConverter().write(legacyDate).toString(); + String converted = persistentProperty.getPropertyValueConverter().write(legacyDate).toString(); assertThat(converted).isEqualTo("20200419T194400.000Z"); } @@ -148,7 +148,7 @@ void shouldConvertToLegacyDate() { SimpleElasticsearchPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class); ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("legacyDate"); - Object converted = persistentProperty.getPropertyConverter().read("20200419T194400.000Z"); + Object converted = persistentProperty.getPropertyValueConverter().read("20200419T194400.000Z"); assertThat(converted).isInstanceOf(Date.class); GregorianCalendar calendar = GregorianCalendar From 07b558e54866be5f824b723441bf055334ed9e5c Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Tue, 5 Oct 2021 20:51:03 +0200 Subject: [PATCH 3/3] Add custom property value converters --- .../elasticsearch-object-mapping.adoc | 5 + .../annotations/ValueConverter.java | 48 +++++++ .../MappingElasticsearchConverter.java | 6 +- .../ElasticsearchPersistentProperty.java | 2 +- ...SimpleElasticsearchPersistentProperty.java | 50 +++++-- ...appingElasticsearchConverterUnitTests.java | 127 ++++++++++++++++++ ...sticsearchPersistentPropertyUnitTests.java | 58 +++++++- 7 files changed, 277 insertions(+), 19 deletions(-) create mode 100644 src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java diff --git a/src/main/asciidoc/reference/elasticsearch-object-mapping.adoc b/src/main/asciidoc/reference/elasticsearch-object-mapping.adoc index 5c249ad97..e7b44517d 100644 --- a/src/main/asciidoc/reference/elasticsearch-object-mapping.adoc +++ b/src/main/asciidoc/reference/elasticsearch-object-mapping.adoc @@ -56,6 +56,8 @@ This means, that no mapping entry is written for the property and that Elasticse ** `analyzer`, `searchAnalyzer`, `normalizer` for specifying custom analyzers and normalizer. * `@GeoPoint`: Marks a field as _geo_point_ datatype. Can be omitted if the field is an instance of the `GeoPoint` class. +* `@ValueConverter` defines a class to be used to convert the given property. +In difference to a registered Spring `Converter` this only converts the annotated property and not every property of the given type. The mapping metadata infrastructure is defined in a separate spring-data-commons project that is technology agnostic. @@ -184,6 +186,7 @@ public class Person { <1> "lastname" : "Connor" } ---- + <1> By default the domain types class name is used for the type hint. ==== @@ -211,6 +214,7 @@ public class Person { "id" : ... } ---- + <1> The configured alias is used when writing the entity. ==== @@ -421,6 +425,7 @@ public class Config extends AbstractElasticsearchConfiguration { "localidad" : { "lat" : 34.118347, "lon" : -118.3026284 } } ---- + <1> Add `Converter` implementations. <2> Set up the `Converter` used for writing `DomainType` to Elasticsearch. <3> Set up the `Converter` used for reading `DomainType` from search result. diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java b/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java new file mode 100644 index 000000000..a76c6d937 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/ValueConverter.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter; + +/** + * Annotation to put on a property of an entity to define a value converter which can convert the property to a type + * that Elasticsearch understands and back. + * + * @author Peter-Josef Meisch + * @since 4.3 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE }) +@Documented +@Inherited +public @interface ValueConverter { + + /** + * Defines the class implementing the {@link PropertyValueConverter} interface. If this is a normal class, it must + * provide a default constructor with no arguments. If this is an enum and thus implementing a singleton by enum it + * must only have one enum value. + * + * @return the class to use for conversion + */ + Class value(); +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java index ba2dc18dc..ca26df40e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java @@ -425,7 +425,7 @@ protected R readValue(@Nullable Object value, ElasticsearchPersistentPropert Class rawType = type.getType(); - if (property.hasPropertyConverter()) { + if (property.hasPropertyValueConverter()) { // noinspection unchecked return (R) propertyConverterRead(property, value); } else if (TemporalAccessor.class.isAssignableFrom(property.getType()) @@ -898,7 +898,7 @@ private void writeProperties(ElasticsearchPersistentEntity entity, Persistent continue; } - if (property.hasPropertyConverter()) { + if (property.hasPropertyValueConverter()) { value = propertyConverterWrite(property, value); sink.set(property, value); } else if (TemporalAccessor.class.isAssignableFrom(property.getActualType()) @@ -1252,7 +1252,7 @@ private void updateCriteria(Criteria criteria, ElasticsearchPersistentEntity if (persistentProperty != null) { - if (persistentProperty.hasPropertyConverter()) { + if (persistentProperty.hasPropertyValueConverter()) { PropertyValueConverter propertyValueConverter = Objects .requireNonNull(persistentProperty.getPropertyValueConverter()); criteria.getQueryCriteriaEntries().forEach(criteriaEntry -> { diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java index 0c48c4e77..498eca56e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java @@ -51,7 +51,7 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty actualType = getActualTypeOrNull(); if (actualType == null) { @@ -158,9 +166,9 @@ private void initPropertyConverter() { } if (TemporalAccessor.class.isAssignableFrom(actualType)) { - propertyConverter = new TemporalPropertyValueConverter(this, dateConverters); + propertyValueConverter = new TemporalPropertyValueConverter(this, dateConverters); } else if (Date.class.isAssignableFrom(actualType)) { - propertyConverter = new DatePropertyValueConverter(this, dateConverters); + propertyValueConverter = new DatePropertyValueConverter(this, dateConverters); } else { LOGGER.warn("Unsupported type '{}' for date property '{}'.", actualType, getName()); } @@ -179,9 +187,9 @@ private void initPropertyConverter() { Class genericType = getTypeInformation().getTypeArguments().get(0).getType(); if (TemporalAccessor.class.isAssignableFrom(genericType)) { - propertyConverter = new TemporalRangePropertyValueConverter(this, dateConverters); + propertyValueConverter = new TemporalRangePropertyValueConverter(this, dateConverters); } else if (Date.class.isAssignableFrom(genericType)) { - propertyConverter = new DateRangePropertyValueConverter(this, dateConverters); + propertyValueConverter = new DateRangePropertyValueConverter(this, dateConverters); } else { LOGGER.warn("Unsupported generic type '{}' for date range property '{}'.", genericType, getName()); } @@ -205,7 +213,7 @@ private void initPropertyConverter() { return; } - propertyConverter = new NumberRangePropertyValueConverter(this); + propertyValueConverter = new NumberRangePropertyValueConverter(this); break; } case Ip_Range: { @@ -216,6 +224,26 @@ private void initPropertyConverter() { } } + private void initPropertyValueConverterFromAnnotation() { + + ValueConverter annotation = findAnnotation(ValueConverter.class); + + if (annotation != null) { + Class clazz = annotation.value(); + + if (Enum.class.isAssignableFrom(clazz)) { + PropertyValueConverter[] enumConstants = clazz.getEnumConstants(); + + if (enumConstants == null || enumConstants.length != 1) { + throw new IllegalArgumentException(clazz + " is an enum with more than 1 constant and cannot be used here"); + } + propertyValueConverter = enumConstants[0]; + } else { + propertyValueConverter = BeanUtils.instantiateClass(clazz); + } + } + } + private List getDateConverters(Field field, Class actualType) { DateFormat[] dateFormats = field.format(); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java index aab41993b..23e52bee3 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java @@ -52,6 +52,7 @@ import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; import org.springframework.data.elasticsearch.annotations.GeoPointField; +import org.springframework.data.elasticsearch.annotations.ValueConverter; import org.springframework.data.elasticsearch.core.Range; import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.geo.GeoJsonEntity; @@ -63,6 +64,7 @@ import org.springframework.data.elasticsearch.core.geo.GeoJsonPoint; import org.springframework.data.elasticsearch.core.geo.GeoJsonPolygon; import org.springframework.data.elasticsearch.core.geo.GeoPoint; +import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm; import org.springframework.data.geo.Box; @@ -71,6 +73,7 @@ import org.springframework.data.geo.Polygon; import org.springframework.data.mapping.context.MappingContext; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * Unit tests for {@link MappingElasticsearchConverter}. @@ -1446,6 +1449,53 @@ void shouldNotWriteTypeHintsIfNotConfigured() throws JSONException { assertEquals(expected, document.toJson(), true); } + @Test // #1945 + @DisplayName("should write using ValueConverters") + void shouldWriteUsingValueConverters() throws JSONException { + + EntityWithCustomValueConverters entity = new EntityWithCustomValueConverters(); + entity.setId("42"); + entity.setFieldWithClassBasedConverter("classbased"); + entity.setFieldWithEnumBasedConverter("enumbased"); + entity.setDontConvert("Monty Python's Flying Circus"); + + String expected = "{\n" + // + " \"id\": \"42\",\n" + // + " \"fieldWithClassBasedConverter\": \"desabssalc\",\n" + // + " \"fieldWithEnumBasedConverter\": \"desabmune\",\n" + // + " \"dontConvert\": \"Monty Python's Flying Circus\"\n" + // + "}\n"; // + + Document document = Document.create(); + + mappingElasticsearchConverter.write(entity, document); + + assertEquals(expected, document.toJson(), false); + } + + @Test // #1945 + @DisplayName("should read using ValueConverters") + void shouldReadUsingValueConverters() throws JSONException { + + String json = "{\n" + // + " \"id\": \"42\",\n" + // + " \"fieldWithClassBasedConverter\": \"desabssalc\",\n" + // + " \"fieldWithEnumBasedConverter\": \"desabmune\",\n" + // + " \"dontConvert\": \"Monty Python's Flying Circus\"\n" + // + "}\n"; // + + Document source = Document.parse(json); + + // when + EntityWithCustomValueConverters entity = mappingElasticsearchConverter.read(EntityWithCustomValueConverters.class, + source); + + assertThat(entity.getId()).isEqualTo("42"); + assertThat(entity.getFieldWithClassBasedConverter()).isEqualTo("classbased"); + assertThat(entity.getFieldWithEnumBasedConverter()).isEqualTo("enumbased"); + assertThat(entity.getDontConvert()).isEqualTo("Monty Python's Flying Circus"); + } + private Map writeToMap(Object source) { Document sink = Document.create(); @@ -2309,5 +2359,82 @@ public void setCars(@Nullable List cars) { this.cars = cars; } } + + private static class EntityWithCustomValueConverters { + @Nullable @Id private String id; + @Nullable @ValueConverter(ClassBasedValueConverter.class) private String fieldWithClassBasedConverter; + @Nullable @ValueConverter(EnumBasedValueConverter.class) private String fieldWithEnumBasedConverter; + @Nullable private String dontConvert; + + @Nullable + public String getId() { + return id; + } + + public void setId(@Nullable String id) { + this.id = id; + } + + @Nullable + public String getFieldWithClassBasedConverter() { + return fieldWithClassBasedConverter; + } + + public void setFieldWithClassBasedConverter(@Nullable String fieldWithClassBasedConverter) { + this.fieldWithClassBasedConverter = fieldWithClassBasedConverter; + } + + @Nullable + public String getFieldWithEnumBasedConverter() { + return fieldWithEnumBasedConverter; + } + + public void setFieldWithEnumBasedConverter(@Nullable String fieldWithEnumBasedConverter) { + this.fieldWithEnumBasedConverter = fieldWithEnumBasedConverter; + } + + @Nullable + public String getDontConvert() { + return dontConvert; + } + + public void setDontConvert(@Nullable String dontConvert) { + this.dontConvert = dontConvert; + } + } + + private static class ClassBasedValueConverter implements PropertyValueConverter { + + @Override + public Object write(Object value) { + return reverse(value); + } + + @Override + public Object read(Object value) { + return reverse(value); + } + } + + private enum EnumBasedValueConverter implements PropertyValueConverter { + INSTANCE; + + @Override + public Object write(Object value) { + return reverse(value); + } + + @Override + public Object read(Object value) { + return reverse(value); + } + } + + private static String reverse(Object o) { + + Assert.notNull(o, "o must not be null"); + + return new StringBuilder().append(o.toString()).reverse().toString(); + } // endregion } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java index d930d5b76..35c5a04e6 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java @@ -27,11 +27,13 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; import org.springframework.data.elasticsearch.annotations.InnerField; import org.springframework.data.elasticsearch.annotations.MultiField; +import org.springframework.data.elasticsearch.annotations.ValueConverter; import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm; import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.model.FieldNamingStrategy; @@ -92,19 +94,19 @@ void shouldSetPropertyConverters() { SimpleElasticsearchPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class); ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate"); - assertThat(persistentProperty.hasPropertyConverter()).isTrue(); + assertThat(persistentProperty.hasPropertyValueConverter()).isTrue(); assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); persistentProperty = persistentEntity.getRequiredPersistentProperty("localDateTime"); - assertThat(persistentProperty.hasPropertyConverter()).isTrue(); + assertThat(persistentProperty.hasPropertyValueConverter()).isTrue(); assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); persistentProperty = persistentEntity.getRequiredPersistentProperty("legacyDate"); - assertThat(persistentProperty.hasPropertyConverter()).isTrue(); + assertThat(persistentProperty.hasPropertyValueConverter()).isTrue(); assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); persistentProperty = persistentEntity.getRequiredPersistentProperty("localDateList"); - assertThat(persistentProperty.hasPropertyConverter()).isTrue(); + assertThat(persistentProperty.hasPropertyValueConverter()).isTrue(); assertThat(persistentProperty.getPropertyValueConverter()).isNotNull(); } @@ -246,6 +248,21 @@ void shouldUseCustomFieldNamingStrategy() { assertThat(property.getFieldName()).isEqualTo("CUStomFIEldnAME"); } + @Test // #1945 + @DisplayName("should use ValueConverter annotation") + void shouldUseValueConverterAnnotation() { + + SimpleElasticsearchPersistentEntity persistentEntity = context + .getRequiredPersistentEntity(EntityWithCustomValueConverters.class); + + assertThat( + persistentEntity.getRequiredPersistentProperty("fieldWithClassBasedConverter").getPropertyValueConverter()) + .isInstanceOf(ClassBasedValueConverter.class); + assertThat( + persistentEntity.getRequiredPersistentProperty("fieldWithEnumBasedConverter").getPropertyValueConverter()) + .isInstanceOf(EnumBasedValueConverter.class); + } + // region entities static class FieldNameProperty { @Nullable @Field(name = "by-name") String fieldProperty; @@ -324,5 +341,38 @@ public void setWithCustomFieldName(String withCustomFieldName) { this.withCustomFieldName = withCustomFieldName; } } + + private static class EntityWithCustomValueConverters { + @Id private String id; + @Nullable @ValueConverter(ClassBasedValueConverter.class) private String fieldWithClassBasedConverter; + @Nullable @ValueConverter(EnumBasedValueConverter.class) private String fieldWithEnumBasedConverter; + } + + private static class ClassBasedValueConverter implements PropertyValueConverter { + + @Override + public Object write(Object value) { + return value; + } + + @Override + public Object read(Object value) { + return value; + } + } + + private enum EnumBasedValueConverter implements PropertyValueConverter { + INSTANCE; + + @Override + public Object write(Object value) { + return value; + } + + @Override + public Object read(Object value) { + return value; + } + } // endregion }