From 90e1775a2ba8eb5682675a5bf247b07b06beaf25 Mon Sep 17 00:00:00 2001 From: Nicholas Knize Date: Fri, 10 Apr 2015 13:49:59 -0500 Subject: [PATCH] [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 --- .../common/geo/builders/ShapeBuilder.java | 3 ++ .../common/geo/GeoJSONShapeParserTests.java | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java b/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java index 98779c5f1a8..22b6ee074ff 100644 --- a/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java +++ b/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java @@ -251,6 +251,9 @@ public abstract class ShapeBuilder implements ToXContent { token = parser.nextToken(); double lat = parser.doubleValue(); token = parser.nextToken(); + while (token == XContentParser.Token.VALUE_NUMBER) { + token = parser.nextToken(); + } return new CoordinateNode(new Coordinate(lon, lat)); } else if (token == XContentParser.Token.VALUE_NULL) { throw new ElasticsearchIllegalArgumentException("coordinates cannot contain NULL values)"); diff --git a/src/test/java/org/elasticsearch/common/geo/GeoJSONShapeParserTests.java b/src/test/java/org/elasticsearch/common/geo/GeoJSONShapeParserTests.java index 28cc9f41cd1..2c767d645bd 100644 --- a/src/test/java/org/elasticsearch/common/geo/GeoJSONShapeParserTests.java +++ b/src/test/java/org/elasticsearch/common/geo/GeoJSONShapeParserTests.java @@ -115,6 +115,32 @@ public class GeoJSONShapeParserTests extends ElasticsearchTestCase { 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 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 { // test #1: envelope with expected coordinate order (TopLeft, BottomRight) String multilinesGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "envelope") @@ -567,11 +593,12 @@ public class GeoJSONShapeParserTests extends ElasticsearchTestCase { .endArray() .endObject().string(); + // add 3d point to test ISSUE #10501 List 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, 1)); - shellCoordinates.add(new Coordinate(100, 1)); + shellCoordinates.add(new Coordinate(100, 1, 10.0)); shellCoordinates.add(new Coordinate(100, 0)); List holeCoordinates = new ArrayList<>();