Skip to content

Commit 5b6d18f

Browse files
osanaLangston Smith
authored andcommitted
First attempt at Shifter implementation (#903)
1 parent 7e0f916 commit 5b6d18f

8 files changed

Lines changed: 322 additions & 17 deletions

File tree

services-geojson/src/main/java/com/mapbox/geojson/Point.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
import com.google.gson.Gson;
1313
import com.google.gson.GsonBuilder;
1414
import com.google.gson.TypeAdapter;
15+
import com.google.gson.reflect.TypeToken;
1516
import com.mapbox.geojson.gson.BoundingBoxDeserializer;
1617
import com.mapbox.geojson.gson.BoundingBoxSerializer;
18+
import com.mapbox.geojson.gson.CoordinateTypeAdapter;
1719
import com.mapbox.geojson.gson.GeoJsonAdapterFactory;
20+
import com.mapbox.geojson.shifter.CoordinateShifterManager;
1821

1922
import java.io.Serializable;
20-
import java.util.Arrays;
2123
import java.util.List;
2224

2325
/**
@@ -72,6 +74,8 @@ public abstract class Point implements CoordinateContainer<List<Double>>, Serial
7274
public static Point fromJson(@NonNull String json) {
7375
GsonBuilder gson = new GsonBuilder();
7476
gson.registerTypeAdapterFactory(GeoJsonAdapterFactory.create());
77+
gson.registerTypeAdapter(new TypeToken<List<Double>>(){}.getType(),
78+
new CoordinateTypeAdapter());
7579
gson.registerTypeAdapter(BoundingBox.class, new BoundingBoxDeserializer());
7680
return gson.create().fromJson(json, Point.class);
7781
}
@@ -92,7 +96,9 @@ public static Point fromJson(@NonNull String json) {
9296
public static Point fromLngLat(
9397
@FloatRange(from = MIN_LONGITUDE, to = MAX_LONGITUDE) double longitude,
9498
@FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latitude) {
95-
List<Double> coordinates = Arrays.asList(longitude, latitude);
99+
100+
List<Double> coordinates =
101+
CoordinateShifterManager.getCoordinateShifter().shiftLonLat(longitude, latitude);
96102
return new AutoValue_Point(TYPE, null, coordinates);
97103
}
98104

@@ -115,7 +121,9 @@ public static Point fromLngLat(
115121
@FloatRange(from = MIN_LONGITUDE, to = MAX_LONGITUDE) double longitude,
116122
@FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latitude,
117123
@Nullable BoundingBox bbox) {
118-
List<Double> coordinates = Arrays.asList(longitude, latitude);
124+
125+
List<Double> coordinates =
126+
CoordinateShifterManager.getCoordinateShifter().shiftLonLat(longitude, latitude);
119127
return new AutoValue_Point(TYPE, bbox, coordinates);
120128
}
121129

@@ -139,9 +147,9 @@ public static Point fromLngLat(
139147
@FloatRange(from = MIN_LONGITUDE, to = MAX_LONGITUDE) double longitude,
140148
@FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latitude,
141149
double altitude) {
142-
List<Double> coordinates = Double.isNaN(altitude)
143-
? Arrays.asList(longitude, latitude) :
144-
Arrays.asList(longitude, latitude, altitude);
150+
151+
List<Double> coordinates =
152+
CoordinateShifterManager.getCoordinateShifter().shiftLonLatAlt(longitude, latitude, altitude);
145153
return new AutoValue_Point(TYPE, null, coordinates);
146154
}
147155

@@ -166,9 +174,9 @@ public static Point fromLngLat(
166174
@FloatRange(from = MIN_LONGITUDE, to = MAX_LONGITUDE) double longitude,
167175
@FloatRange(from = MIN_LATITUDE, to = MAX_LATITUDE) double latitude,
168176
double altitude, @Nullable BoundingBox bbox) {
169-
List<Double> coordinates = Double.isNaN(altitude)
170-
? Arrays.asList(longitude, latitude) :
171-
Arrays.asList(longitude, latitude, altitude);
177+
178+
List<Double> coordinates =
179+
CoordinateShifterManager.getCoordinateShifter().shiftLonLatAlt(longitude, latitude, altitude);
172180
return new AutoValue_Point(TYPE, bbox, coordinates);
173181
}
174182

@@ -284,6 +292,8 @@ public boolean hasAltitude() {
284292
@Override
285293
public String toJson() {
286294
GsonBuilder gson = new GsonBuilder();
295+
gson.registerTypeAdapter(new TypeToken<List<Double>>(){}.getType(),
296+
new CoordinateTypeAdapter());
287297
gson.registerTypeAdapter(BoundingBox.class, new BoundingBoxSerializer());
288298
return gson.create().toJson(this);
289299
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.mapbox.geojson.gson;
2+
3+
import com.google.gson.TypeAdapter;
4+
import com.google.gson.stream.JsonReader;
5+
import com.google.gson.stream.JsonWriter;
6+
import com.mapbox.geojson.shifter.CoordinateShifterManager;
7+
8+
import java.io.IOException;
9+
import java.math.BigDecimal;
10+
import java.math.RoundingMode;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
/**
15+
* Adapter to read and write coordinates for Point class.
16+
*
17+
* @since 4.1.0
18+
*/
19+
public class CoordinateTypeAdapter extends TypeAdapter<List<Double>> {
20+
@Override
21+
public void write(JsonWriter out, List<Double> value) throws IOException {
22+
23+
out.beginArray();
24+
25+
// Unshift coordinates
26+
List<Double> unshiftedCoordinates =
27+
CoordinateShifterManager.getCoordinateShifter().unshiftPoint(value);
28+
29+
BigDecimal lon = BigDecimal.valueOf(unshiftedCoordinates.get(0));
30+
String lonString = lon.setScale(7, RoundingMode.HALF_UP)
31+
.stripTrailingZeros().toPlainString();
32+
33+
BigDecimal lat = BigDecimal.valueOf(unshiftedCoordinates.get(1));
34+
String latString = lat.setScale(7, RoundingMode.HALF_UP)
35+
.stripTrailingZeros().toPlainString();
36+
37+
out.value(Double.valueOf(lonString));
38+
out.value(Double.valueOf(latString));
39+
40+
// Includes altitude
41+
if (value.size() > 2) {
42+
out.value(unshiftedCoordinates.get(2));
43+
}
44+
out.endArray();
45+
}
46+
47+
@Override
48+
public List<Double> read(JsonReader in) throws IOException {
49+
List<Double> coordinates = new ArrayList<Double>();
50+
in.beginArray();
51+
while (in.hasNext()) {
52+
coordinates.add(in.nextDouble());
53+
}
54+
in.endArray();
55+
56+
if (coordinates.size() > 2) {
57+
return CoordinateShifterManager.getCoordinateShifter()
58+
.shiftLonLatAlt(coordinates.get(0), coordinates.get(1), coordinates.get(2));
59+
}
60+
return CoordinateShifterManager.getCoordinateShifter()
61+
.shiftLonLat(coordinates.get(0), coordinates.get(1));
62+
}
63+
}

services-geojson/src/main/java/com/mapbox/geojson/gson/PointSerializer.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
import com.google.gson.JsonSerializationContext;
77
import com.google.gson.JsonSerializer;
88
import com.mapbox.geojson.Point;
9+
import com.mapbox.geojson.shifter.CoordinateShifterManager;
910

1011
import java.lang.reflect.Type;
1112
import java.math.BigDecimal;
1213
import java.math.RoundingMode;
14+
import java.util.List;
1315

1416
/**
1517
* Required to handle the special case where the altitude might be a Double.NaN, which isn't a valid
@@ -44,20 +46,24 @@ public PointSerializer() {
4446
public JsonElement serialize(Point src, Type typeOfSrc, JsonSerializationContext context) {
4547
JsonArray rawCoordinates = new JsonArray();
4648

47-
BigDecimal lat = BigDecimal.valueOf(src.latitude());
48-
String latString = lat.setScale(7, RoundingMode.HALF_UP)
49-
.stripTrailingZeros().toPlainString();
49+
// Unshift coordinates
50+
List<Double> unshiftedCoordinates =
51+
CoordinateShifterManager.getCoordinateShifter().unshiftPoint(src);
5052

51-
BigDecimal lon = BigDecimal.valueOf(src.longitude());
53+
BigDecimal lon = BigDecimal.valueOf(unshiftedCoordinates.get(0));
5254
String lonString = lon.setScale(7, RoundingMode.HALF_UP)
5355
.stripTrailingZeros().toPlainString();
5456

57+
BigDecimal lat = BigDecimal.valueOf(unshiftedCoordinates.get(1));
58+
String latString = lat.setScale(7, RoundingMode.HALF_UP)
59+
.stripTrailingZeros().toPlainString();
60+
5561
rawCoordinates.add(new JsonPrimitive(Double.valueOf(lonString)));
5662
rawCoordinates.add(new JsonPrimitive(Double.valueOf(latString)));
5763

5864
// Includes altitude
5965
if (src.hasAltitude()) {
60-
rawCoordinates.add(new JsonPrimitive(src.altitude()));
66+
rawCoordinates.add(new JsonPrimitive(unshiftedCoordinates.get(3)));
6167
}
6268

6369
return rawCoordinates;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.mapbox.geojson.shifter;
2+
3+
import com.mapbox.geojson.Point;
4+
5+
import java.util.List;
6+
7+
/**
8+
* ShifterManager allows to move all points according to some pluggable algorithm.
9+
* Once set it will be applied to all Point object created through this method.
10+
*
11+
* @since 4.1.0
12+
*/
13+
public interface CoordinateShifter {
14+
15+
/**
16+
* Shifted coordinate values according to its algorithm.
17+
*
18+
* @param lon unshifted longitude
19+
* @param lat unshifted latitude
20+
* @return shifted longitude, shifted latitude in the form of List of Double
21+
* @since 4.1.0
22+
*/
23+
List<Double> shiftLonLat(double lon, double lat);
24+
25+
/**
26+
* Shifted coordinate values according to its algorithm.
27+
*
28+
* @param lon unshifted longitude
29+
* @param lat unshifted latitude
30+
* @param altitude unshifted altitude
31+
* @return shifted longitude, shifted latitude, shifted altitude in the form of List of Double
32+
* @since 4.1.0
33+
*/
34+
List<Double> shiftLonLatAlt(double lon, double lat, double altitude);
35+
36+
/**
37+
* Unshifted coordinate values according to its algorithm.
38+
*
39+
* @param shiftedPoint shifted point
40+
* @return unshifted longitude, shifted latitude,
41+
* and altitude (if present) in the form of List of Double
42+
* @since 4.1.0
43+
*/
44+
List<Double> unshiftPoint(Point shiftedPoint);
45+
46+
47+
/**
48+
* Unshifted coordinate values according to its algorithm.
49+
*
50+
* @param shiftedCoordinates shifted point
51+
* @return unshifted longitude, shifted latitude,
52+
* and altitude (if present) in the form of List of Double
53+
* @since 4.1.0
54+
*/
55+
List<Double> unshiftPoint(List<Double> shiftedCoordinates);
56+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.mapbox.geojson.shifter;
2+
3+
import com.mapbox.geojson.Point;
4+
5+
import java.util.Arrays;
6+
import java.util.List;
7+
8+
/**
9+
* CoordinateShifterManager keeps track of currently set CoordinateShifter.
10+
*
11+
* @since 4.1.0
12+
*/
13+
public final class CoordinateShifterManager {
14+
15+
private static final CoordinateShifter DEFAULT = new CoordinateShifter() {
16+
@Override
17+
public List<Double> shiftLonLat(double lon, double lat) {
18+
return Arrays.asList(lon, lat);
19+
}
20+
21+
@Override
22+
public List<Double> shiftLonLatAlt(double lon, double lat, double alt) {
23+
return Double.isNaN(alt)
24+
? Arrays.asList(lon, lat) :
25+
Arrays.asList(lon, lat, alt);
26+
}
27+
28+
@Override
29+
public List<Double> unshiftPoint(Point point) {
30+
return point.coordinates();
31+
}
32+
33+
@Override
34+
public List<Double> unshiftPoint(List<Double> coordinates) {
35+
return coordinates;
36+
}
37+
};
38+
39+
private static volatile CoordinateShifter coordinateShifter = DEFAULT;
40+
41+
/**
42+
* Currently set CoordinateShifterManager.
43+
*
44+
* @return Currently set CoordinateShifterManager
45+
* @since 4.1.0
46+
*/
47+
public static CoordinateShifter getCoordinateShifter() {
48+
return coordinateShifter;
49+
}
50+
51+
/**
52+
* Sets CoordinateShifterManager.
53+
*
54+
* @param coordinateShifter CoordinateShifterManager to be set
55+
* @since 4.1.0
56+
*/
57+
public static void setCoordinateShifter(CoordinateShifter coordinateShifter) {
58+
CoordinateShifterManager.coordinateShifter =
59+
coordinateShifter == null ? DEFAULT : coordinateShifter;
60+
}
61+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* Contains Utility for univerally applying shiftign algorithm to all Geometry.
3+
*/
4+
package com.mapbox.geojson.shifter;

services-geojson/src/test/java/com/mapbox/geojson/gson/PointDeserializerTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.google.gson.JsonSyntaxException;
55
import com.google.gson.reflect.TypeToken;
66
import com.mapbox.core.TestUtils;
7-
import com.mapbox.core.exceptions.ServicesException;
87
import com.mapbox.geojson.Point;
98

109
import org.junit.Rule;
@@ -14,10 +13,9 @@
1413
import java.lang.reflect.Type;
1514
import java.util.List;
1615

17-
import static org.hamcrest.Matchers.containsString;
18-
import static org.hamcrest.Matchers.startsWith;
1916
import static org.junit.Assert.assertEquals;
2017

18+
2119
public class PointDeserializerTest extends TestUtils {
2220

2321
@Rule

0 commit comments

Comments
 (0)