From 23cad97b9a59171bb680b893687ba7bf689147dc Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sun, 4 Jan 2015 16:42:05 +0100 Subject: [PATCH] DATACMNS-626 - Added formatters for Point and Distance. Ported Spring Data REST's converters for Distance and Point and turned them into Formatter instances. Extended Metric interface to return an abbreviation. Added getUnit() to Distance and tweaked Jackson setup to ignore the additional property. We now automatically register the news introduced Formatters when using @EnableSpringDataWebSupport so that Point and Distance values can be parsed and printed from and to Strings out of the box. --- .../data/geo/CustomMetric.java | 29 +++- .../springframework/data/geo/Distance.java | 14 +- .../springframework/data/geo/GeoModule.java | 4 +- .../org/springframework/data/geo/Metric.java | 9 +- .../org/springframework/data/geo/Metrics.java | 18 ++- .../data/geo/format/DistanceFormatter.java | 126 ++++++++++++++++++ .../data/geo/format/PointFormatter.java | 82 ++++++++++++ .../config/SpringDataWebConfiguration.java | 7 +- .../data/geo/DistanceUnitTests.java | 10 +- .../format/DistanceFormatterUnitTests.java | 98 ++++++++++++++ .../geo/format/PointFormatterUnitTests.java | 104 +++++++++++++++ ...eSpringDataWebSupportIntegrationTests.java | 21 ++- 12 files changed, 511 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/springframework/data/geo/format/DistanceFormatter.java create mode 100644 src/main/java/org/springframework/data/geo/format/PointFormatter.java create mode 100644 src/test/java/org/springframework/data/geo/format/DistanceFormatterUnitTests.java create mode 100644 src/test/java/org/springframework/data/geo/format/PointFormatterUnitTests.java diff --git a/src/main/java/org/springframework/data/geo/CustomMetric.java b/src/main/java/org/springframework/data/geo/CustomMetric.java index 4aafb4cf2..251ee768e 100644 --- a/src/main/java/org/springframework/data/geo/CustomMetric.java +++ b/src/main/java/org/springframework/data/geo/CustomMetric.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2015 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. @@ -15,6 +15,8 @@ */ package org.springframework.data.geo; +import org.springframework.util.Assert; + /** * Value object to create custom {@link Metric}s on the fly. * @@ -27,6 +29,7 @@ public class CustomMetric implements Metric { private static final long serialVersionUID = -2972074177454114228L; private final double multiplier; + private final String abbreviation; /** * Creates a custom {@link Metric} using the given multiplier. @@ -34,7 +37,22 @@ public class CustomMetric implements Metric { * @param multiplier */ public CustomMetric(double multiplier) { + + this(multiplier, ""); + } + + /** + * Creates a custom {@link Metric} using the given multiplier and abbreviation. + * + * @param multiplier + * @param abbreviation must not be {@literal null}. + */ + public CustomMetric(double multiplier, String abbreviation) { + + Assert.notNull(abbreviation, "Abbreviation must not be null!"); + this.multiplier = multiplier; + this.abbreviation = abbreviation; } /* @@ -44,4 +62,13 @@ public class CustomMetric implements Metric { public double getMultiplier() { return multiplier; } + + /* + * (non-Javadoc) + * @see org.springframework.data.geo.Metric#getAbbreviation() + */ + @Override + public String getAbbreviation() { + return abbreviation; + } } diff --git a/src/main/java/org/springframework/data/geo/Distance.java b/src/main/java/org/springframework/data/geo/Distance.java index 621ff6fa0..a2095998f 100644 --- a/src/main/java/org/springframework/data/geo/Distance.java +++ b/src/main/java/org/springframework/data/geo/Distance.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2014 the original author or authors. + * Copyright 2010-2015 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. @@ -73,7 +73,7 @@ public class Distance implements Serializable { } /** - * Retruns the {@link Metric} of the {@link Distance}. + * Returns the {@link Metric} of the {@link Distance}. * * @return the metric */ @@ -81,6 +81,16 @@ public class Distance implements Serializable { return metric; } + /** + * Returns a {@link String} representation of the unit the distance is in. + * + * @return the unit + * @see Metric#getAbbreviation() + */ + public String getUnit() { + return metric.getAbbreviation(); + } + /** * Adds the given distance to the current one. The resulting {@link Distance} will be in the same metric as the * current one. diff --git a/src/main/java/org/springframework/data/geo/GeoModule.java b/src/main/java/org/springframework/data/geo/GeoModule.java index 108783eaa..38ff55387 100644 --- a/src/main/java/org/springframework/data/geo/GeoModule.java +++ b/src/main/java/org/springframework/data/geo/GeoModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2015 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. @@ -18,6 +18,7 @@ package org.springframework.data.geo; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -47,6 +48,7 @@ public class GeoModule extends SimpleModule { setMixInAnnotation(Polygon.class, PolygonMixin.class); } + @JsonIgnoreProperties("unit") static abstract class DistanceMixin { DistanceMixin(@JsonProperty("value") double value, diff --git a/src/main/java/org/springframework/data/geo/Metric.java b/src/main/java/org/springframework/data/geo/Metric.java index b8040b029..2530cac3e 100644 --- a/src/main/java/org/springframework/data/geo/Metric.java +++ b/src/main/java/org/springframework/data/geo/Metric.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014 the original author or authors. + * Copyright 2011-2015 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. @@ -32,4 +32,11 @@ public interface Metric extends Serializable { * @return */ double getMultiplier(); + + /** + * Returns the scientific abbreviation of the unit the {@link Metric} is in. + * + * @return + */ + String getAbbreviation(); } diff --git a/src/main/java/org/springframework/data/geo/Metrics.java b/src/main/java/org/springframework/data/geo/Metrics.java index e30c0ec25..6f1cfdfd6 100644 --- a/src/main/java/org/springframework/data/geo/Metrics.java +++ b/src/main/java/org/springframework/data/geo/Metrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014 the original author or authors. + * Copyright 2011-2015 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. @@ -24,17 +24,20 @@ package org.springframework.data.geo; */ public enum Metrics implements Metric { - KILOMETERS(6378.137), MILES(3963.191), NEUTRAL(1); + KILOMETERS(6378.137, "km"), MILES(3963.191, "mi"), NEUTRAL(1, ""); private final double multiplier; + private final String abbreviation; /** * Creates a new {@link Metrics} using the given muliplier. * * @param multiplier the earth radius at equator. */ - private Metrics(double multiplier) { + private Metrics(double multiplier, String abbreviation) { + this.multiplier = multiplier; + this.abbreviation = abbreviation; } /* @@ -44,4 +47,13 @@ public enum Metrics implements Metric { public double getMultiplier() { return multiplier; } + + /* + * (non-Javadoc) + * @see org.springframework.data.geo.Metric#getAbbreviation() + */ + @Override + public String getAbbreviation() { + return abbreviation; + } } diff --git a/src/main/java/org/springframework/data/geo/format/DistanceFormatter.java b/src/main/java/org/springframework/data/geo/format/DistanceFormatter.java new file mode 100644 index 000000000..55cf5cec7 --- /dev/null +++ b/src/main/java/org/springframework/data/geo/format/DistanceFormatter.java @@ -0,0 +1,126 @@ +/* + * Copyright 2014-2015 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 + * + * http://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.geo.format; + +import java.text.ParseException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Metric; +import org.springframework.data.geo.Metrics; +import org.springframework.format.Formatter; +import org.springframework.util.StringUtils; + +/** + * Converter to create {@link Distance} instances from {@link String} representations. The supported format is a decimal + * followed by whitespace and a metric abbreviation. We currently support the following abbreviations: + * {@value #SUPPORTED_METRICS}. + * + * @author Oliver Gierke + */ +public enum DistanceFormatter implements Converter, Formatter { + + INSTANCE; + + private static final Map SUPPORTED_METRICS; + private static final String INVALID_DISTANCE = "Expected double amount optionally followed by a metrics abbreviation (%s) but got '%s'!"; + + static { + + Map metrics = new LinkedHashMap(); + + for (Metric metric : Metrics.values()) { + metrics.put(metric.getAbbreviation(), metric); + metrics.put(metric.toString().toLowerCase(Locale.US), metric); + } + + SUPPORTED_METRICS = Collections.unmodifiableMap(metrics); + } + + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ + @Override + public final Distance convert(String source) { + return source == null ? null : doConvert(source.trim().toLowerCase(Locale.US)); + } + + /* + * (non-Javadoc) + * @see org.springframework.format.Printer#print(java.lang.Object, java.util.Locale) + */ + @Override + public String print(Distance distance, Locale locale) { + return distance == null ? null : String.format("%s%s", distance.getValue(), distance.getUnit().toLowerCase(locale)); + } + + /* + * (non-Javadoc) + * @see org.springframework.format.Parser#parse(java.lang.String, java.util.Locale) + */ + @Override + public Distance parse(String text, Locale locale) throws ParseException { + return !StringUtils.hasText(text) ? null : doConvert(text.trim().toLowerCase(locale)); + } + + /** + * Converts the given {@link String} source into a distance. Expects the source to reflect the {@link Metric} as held + * in the {@link #SUPPORTED_METRICS} map. + * + * @param source must not be {@literal null}. + * @return + */ + private static Distance doConvert(String source) { + + for (Entry metric : SUPPORTED_METRICS.entrySet()) { + if (source.endsWith(metric.getKey())) { + return fromString(source, metric); + } + } + + try { + return new Distance(Double.parseDouble(source)); + } catch (NumberFormatException o_O) { + throw new IllegalArgumentException(String.format(INVALID_DISTANCE, + StringUtils.collectionToCommaDelimitedString(SUPPORTED_METRICS.keySet()), source)); + } + } + + /** + * Creates a {@link Distance} from the given source String and the {@link Metric} detected. + * + * @param source the raw source {@link String}, must not be {@literal null} or empty. + * @param metric the {@link Metric} detected keyed by the keyword it was detected for, must not be {@literal null}. + * @return + */ + private static Distance fromString(String source, Entry metric) { + + String amountString = source.substring(0, source.indexOf(metric.getKey())); + + try { + return new Distance(Double.parseDouble(amountString), metric.getValue()); + } catch (NumberFormatException o_O) { + throw new IllegalArgumentException(String.format(INVALID_DISTANCE, + StringUtils.collectionToCommaDelimitedString(SUPPORTED_METRICS.keySet()), source)); + } + } +} diff --git a/src/main/java/org/springframework/data/geo/format/PointFormatter.java b/src/main/java/org/springframework/data/geo/format/PointFormatter.java new file mode 100644 index 000000000..959f1f18f --- /dev/null +++ b/src/main/java/org/springframework/data/geo/format/PointFormatter.java @@ -0,0 +1,82 @@ +/* + * Copyright 2014-2015 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 + * + * http://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.geo.format; + +import java.text.ParseException; +import java.util.Locale; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair; +import org.springframework.data.geo.Point; +import org.springframework.format.Formatter; +import org.springframework.util.StringUtils; + +/** + * Converter to parse two comma-separated doubles into a {@link Point}. + * + * @author Oliver Gierke + */ +public enum PointFormatter implements Converter, Formatter { + + INSTANCE; + + public static final ConvertiblePair CONVERTIBLE = new ConvertiblePair(String.class, Point.class); + + private static final String INVALID_FORMAT = "Expected two doubles separated by a semicolon but got '%s'!"; + + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ + @Override + public Point convert(String source) { + + String[] parts = source.split(","); + + if (parts.length != 2) { + throw new IllegalArgumentException(String.format(INVALID_FORMAT, source)); + } + + try { + + double latitude = Double.parseDouble(parts[0]); + double longitude = Double.parseDouble(parts[1]); + + return new Point(longitude, latitude); + + } catch (NumberFormatException o_O) { + throw new IllegalArgumentException(String.format(INVALID_FORMAT, source), o_O); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.format.Printer#print(java.lang.Object, java.util.Locale) + */ + @Override + public String print(Point point, Locale locale) { + return point == null ? null : String.format("%s,%s", point.getY(), point.getX()); + } + + /* + * (non-Javadoc) + * @see org.springframework.format.Parser#parse(java.lang.String, java.util.Locale) + */ + @Override + public Point parse(String text, Locale locale) throws ParseException { + return !StringUtils.hasText(text) ? null : convert(text); + } +} diff --git a/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java b/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java index b5bccb327..15033b943 100644 --- a/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java +++ b/src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2015 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. @@ -21,6 +21,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.geo.format.DistanceFormatter; +import org.springframework.data.geo.format.PointFormatter; import org.springframework.data.repository.support.DomainClassConverter; import org.springframework.data.web.PageableHandlerMethodArgumentResolver; import org.springframework.data.web.SortHandlerMethodArgumentResolver; @@ -66,6 +68,9 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter { @Override public void addFormatters(FormatterRegistry registry) { + registry.addFormatter(DistanceFormatter.INSTANCE); + registry.addFormatter(PointFormatter.INSTANCE); + if (!(registry instanceof FormattingConversionService)) { return; } diff --git a/src/test/java/org/springframework/data/geo/DistanceUnitTests.java b/src/test/java/org/springframework/data/geo/DistanceUnitTests.java index 91a93a428..7c1f9c583 100644 --- a/src/test/java/org/springframework/data/geo/DistanceUnitTests.java +++ b/src/test/java/org/springframework/data/geo/DistanceUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014 the original author or authors. + * Copyright 2011-2015 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. @@ -137,4 +137,12 @@ public class DistanceUnitTests { Distance serialized = (Distance) SerializationUtils.deserialize(SerializationUtils.serialize(dist)); assertThat(serialized, is(dist)); } + + /** + * @see DATACMNS-626 + */ + @Test + public void returnsMetricsAbbreviationAsUnit() { + assertThat(new Distance(10, KILOMETERS).getUnit(), is("km")); + } } diff --git a/src/test/java/org/springframework/data/geo/format/DistanceFormatterUnitTests.java b/src/test/java/org/springframework/data/geo/format/DistanceFormatterUnitTests.java new file mode 100644 index 000000000..40ab07da3 --- /dev/null +++ b/src/test/java/org/springframework/data/geo/format/DistanceFormatterUnitTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2014-2015 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 + * + * http://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.geo.format; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.springframework.data.geo.format.DistanceFormatter.*; + +import java.text.ParseException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Metrics; + +/** + * Unit tests for {@link DistanceFormatter}. + * + * @author Oliver Gierke + */ +@RunWith(Enclosed.class) +public class DistanceFormatterUnitTests { + + static Distance REFERENCE = new Distance(10.8, Metrics.KILOMETERS); + + public static class UnparameterizedTests { + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test(expected = IllegalArgumentException.class) + public void rejectsArbitraryNonsense() { + INSTANCE.convert("foo"); + } + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test(expected = IllegalArgumentException.class) + public void rejectsUnsupportedMetric() { + INSTANCE.convert("10.8cm"); + } + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test + public void printsDistance() { + assertThat(INSTANCE.print(REFERENCE, Locale.US), is("10.8km")); + } + } + + @RunWith(Parameterized.class) + public static class ParameterizedTests { + + @Parameters + public static Collection parameters() { + return Arrays.asList(new String[] { "10.8km" }, new String[] { " 10.8km" }, new String[] { " 10.8 km" }, + new String[] { " 10.8 km " }, new String[] { " 10.8 KM" }, new String[] { " 10.8 kilometers" }, + new String[] { " 10.8 KILOMETERS" }, new String[] { " 10.8 KILOMETERS " }); + } + + public @Parameter String source; + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test + public void parsesDistanceFromString() { + assertThat(INSTANCE.convert(source), is(REFERENCE)); + } + + @Test + public void parsesDistances() throws ParseException { + assertThat(INSTANCE.parse(source, Locale.US), is(REFERENCE)); + } + } +} diff --git a/src/test/java/org/springframework/data/geo/format/PointFormatterUnitTests.java b/src/test/java/org/springframework/data/geo/format/PointFormatterUnitTests.java new file mode 100644 index 000000000..281ce4449 --- /dev/null +++ b/src/test/java/org/springframework/data/geo/format/PointFormatterUnitTests.java @@ -0,0 +1,104 @@ +/* + * Copyright 2014-2015 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 + * + * http://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.geo.format; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.springframework.data.geo.format.PointFormatter.*; + +import java.text.ParseException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.springframework.data.geo.Point; + +/** + * Unit tests for {@link PointFormatter}. + * + * @author Oliver Gierke + */ +@RunWith(Enclosed.class) +public class PointFormatterUnitTests { + + static Point REFERENCE = new Point(20.9, 10.8); + + @Test + public void testname() { + // To make sure Maven picks up the tests + } + + public static class UnparameterizedTests { + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test(expected = IllegalArgumentException.class) + public void rejectsArbitraryNonsense() { + INSTANCE.convert("foo"); + } + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test(expected = IllegalArgumentException.class) + public void rejectsMoreThanTwoCoordinates() { + INSTANCE.convert("10.8,20.9,30.10"); + } + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test(expected = IllegalArgumentException.class) + public void rejectsInvalidCoordinate() { + INSTANCE.convert("10.8,foo"); + } + } + + @RunWith(Parameterized.class) + public static class ParameterizedTests { + + @Parameters + public static Collection parameters() { + return Arrays.asList(new String[] { "10.8,20.9" }, new String[] { " 10.8,20.9 " }, + new String[] { " 10.8 ,20.9" }, new String[] { " 10.8, 20.9 " }); + } + + public @Parameter String source; + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test + public void convertsPointFromString() { + assertThat(INSTANCE.convert(source), is(REFERENCE)); + } + + /** + * @see DATAREST-279, DATACMNS-626 + */ + @Test + public void parsesPoint() throws ParseException { + assertThat(INSTANCE.parse(source, Locale.US), is(REFERENCE)); + } + } +} diff --git a/src/test/java/org/springframework/data/web/config/EnableSpringDataWebSupportIntegrationTests.java b/src/test/java/org/springframework/data/web/config/EnableSpringDataWebSupportIntegrationTests.java index 7e19821ff..7af4fb17c 100644 --- a/src/test/java/org/springframework/data/web/config/EnableSpringDataWebSupportIntegrationTests.java +++ b/src/test/java/org/springframework/data/web/config/EnableSpringDataWebSupportIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2015 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. @@ -28,6 +28,9 @@ import org.junit.After; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Point; import org.springframework.data.web.PageableHandlerMethodArgumentResolver; import org.springframework.data.web.PagedResourcesAssemblerArgumentResolver; import org.springframework.data.web.SortHandlerMethodArgumentResolver; @@ -122,6 +125,22 @@ public class EnableSpringDataWebSupportIntegrationTests { assertThat(names, not(hasItem("jacksonGeoModule"))); } + /** + * @see DATACMNS-626 + */ + @Test + public void registersFormatters() { + + ApplicationContext context = WebTestUtils.createApplicationContext(SampleConfig.class); + + ConversionService conversionService = context.getBean(ConversionService.class); + + assertThat(conversionService.canConvert(String.class, Distance.class), is(true)); + assertThat(conversionService.canConvert(Distance.class, String.class), is(true)); + assertThat(conversionService.canConvert(String.class, Point.class), is(true)); + assertThat(conversionService.canConvert(Point.class, String.class), is(true)); + } + @SuppressWarnings("unchecked") private static void assertResolversRegistered(ApplicationContext context, Class... resolverTypes) {