1
16 package org.springframework.data.geo.format;
17
18 import java.text.ParseException;
19 import java.util.Collections;
20 import java.util.LinkedHashMap;
21 import java.util.Locale;
22 import java.util.Map;
23 import java.util.Map.Entry;
24
25 import org.springframework.core.convert.converter.Converter;
26 import org.springframework.data.geo.Distance;
27 import org.springframework.data.geo.Metric;
28 import org.springframework.data.geo.Metrics;
29 import org.springframework.format.Formatter;
30 import org.springframework.lang.Nullable;
31 import org.springframework.util.StringUtils;
32
33
41 public enum DistanceFormatter implements Converter<String, Distance>, Formatter<Distance> {
42
43 INSTANCE;
44
45 private static final Map<String, Metric> SUPPORTED_METRICS;
46 private static final String INVALID_DISTANCE = "Expected double amount optionally followed by a metrics abbreviation (%s) but got '%s'!";
47
48 static {
49
50 Map<String, Metric> metrics = new LinkedHashMap<>();
51
52 for (Metric metric : Metrics.values()) {
53 metrics.put(metric.getAbbreviation(), metric);
54 metrics.put(metric.toString().toLowerCase(Locale.US), metric);
55 }
56
57 SUPPORTED_METRICS = Collections.unmodifiableMap(metrics);
58 }
59
60
64 @Nullable
65 @Override
66 public final Distance convert(String source) {
67 return source == null ? null : doConvert(source.trim().toLowerCase(Locale.US));
68 }
69
70
74 @Override
75 public String print(Distance distance, Locale locale) {
76 return distance == null ? null : String.format("%s%s", distance.getValue(), distance.getUnit().toLowerCase(locale));
77 }
78
79
83 @Override
84 public Distance parse(String text, Locale locale) throws ParseException {
85 return doConvert(text.trim().toLowerCase(locale));
86 }
87
88
95 private static Distance doConvert(String source) {
96
97 for (Entry<String, Metric> metric : SUPPORTED_METRICS.entrySet()) {
98 if (source.endsWith(metric.getKey())) {
99 return fromString(source, metric);
100 }
101 }
102
103 try {
104 return new Distance(Double.parseDouble(source));
105 } catch (NumberFormatException o_O) {
106 throw new IllegalArgumentException(String.format(INVALID_DISTANCE,
107 StringUtils.collectionToCommaDelimitedString(SUPPORTED_METRICS.keySet()), source));
108 }
109 }
110
111
118 private static Distance fromString(String source, Entry<String, Metric> metric) {
119
120 String amountString = source.substring(0, source.indexOf(metric.getKey()));
121
122 try {
123 return new Distance(Double.parseDouble(amountString), metric.getValue());
124 } catch (NumberFormatException o_O) {
125 throw new IllegalArgumentException(String.format(INVALID_DISTANCE,
126 StringUtils.collectionToCommaDelimitedString(SUPPORTED_METRICS.keySet()), source));
127 }
128 }
129 }
130