[GEO] Correct ShapeBuilder coordinate parser to ignore values in 3rd+ dimension

ShapeBuilder's coordinate parser expected 2 double values for every coordinate array. If > 2 doubles were provided the parser terminated parsing of the coordinate array. This resulted in an invalid Shape state leaving LineStrings, LinearRings, and Polygons with a single coordinate. An incorrect parse exception was thrown. This corrects the parser to ignore those values in the 3rd+ dimension, correctly parsing the rest of the coordinate array.

Unit tests have been updated to verify the fix.

closes #10510
This commit is contained in:
Nicholas Knize 2015-04-10 13:49:59 -05:00
parent 754856289e
commit 90e1775a2b
2 changed files with 32 additions and 2 deletions

View File

@ -251,6 +251,9 @@ public abstract class ShapeBuilder implements ToXContent {
token = parser.nextToken(); token = parser.nextToken();
double lat = parser.doubleValue(); double lat = parser.doubleValue();
token = parser.nextToken(); token = parser.nextToken();
while (token == XContentParser.Token.VALUE_NUMBER) {
token = parser.nextToken();
}
return new CoordinateNode(new Coordinate(lon, lat)); return new CoordinateNode(new Coordinate(lon, lat));
} else if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_NULL) {
throw new ElasticsearchIllegalArgumentException("coordinates cannot contain NULL values)"); throw new ElasticsearchIllegalArgumentException("coordinates cannot contain NULL values)");

View File

@ -115,6 +115,32 @@ public class GeoJSONShapeParserTests extends ElasticsearchTestCase {
assertGeometryEquals(expected, multilinesGeoJson); assertGeometryEquals(expected, multilinesGeoJson);
} }
public void testParse_multiDimensionShapes() throws IOException {
// multi dimension point
String pointGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "Point")
.startArray("coordinates").value(100.0).value(0.0).value(15.0).value(18.0).endArray()
.endObject().string();
Point expectedPt = GEOMETRY_FACTORY.createPoint(new Coordinate(100.0, 0.0));
assertGeometryEquals(new JtsPoint(expectedPt, SPATIAL_CONTEXT), pointGeoJson);
// multi dimension linestring
String lineGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "LineString")
.startArray("coordinates")
.startArray().value(100.0).value(0.0).value(15.0).endArray()
.startArray().value(101.0).value(1.0).value(18.0).value(19.0).endArray()
.endArray()
.endObject().string();
List<Coordinate> lineCoordinates = new ArrayList<>();
lineCoordinates.add(new Coordinate(100, 0));
lineCoordinates.add(new Coordinate(101, 1));
LineString expectedLS = GEOMETRY_FACTORY.createLineString(
lineCoordinates.toArray(new Coordinate[lineCoordinates.size()]));
assertGeometryEquals(jtsGeom(expectedLS), lineGeoJson);
}
public void testParse_envelope() throws IOException { public void testParse_envelope() throws IOException {
// test #1: envelope with expected coordinate order (TopLeft, BottomRight) // test #1: envelope with expected coordinate order (TopLeft, BottomRight)
String multilinesGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "envelope") String multilinesGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "envelope")
@ -567,11 +593,12 @@ public class GeoJSONShapeParserTests extends ElasticsearchTestCase {
.endArray() .endArray()
.endObject().string(); .endObject().string();
// add 3d point to test ISSUE #10501
List<Coordinate> shellCoordinates = new ArrayList<>(); List<Coordinate> shellCoordinates = new ArrayList<>();
shellCoordinates.add(new Coordinate(100, 0)); shellCoordinates.add(new Coordinate(100, 0, 15.0));
shellCoordinates.add(new Coordinate(101, 0)); shellCoordinates.add(new Coordinate(101, 0));
shellCoordinates.add(new Coordinate(101, 1)); shellCoordinates.add(new Coordinate(101, 1));
shellCoordinates.add(new Coordinate(100, 1)); shellCoordinates.add(new Coordinate(100, 1, 10.0));
shellCoordinates.add(new Coordinate(100, 0)); shellCoordinates.add(new Coordinate(100, 0));
List<Coordinate> holeCoordinates = new ArrayList<>(); List<Coordinate> holeCoordinates = new ArrayList<>();