diff --git a/build.gradle b/build.gradle index c5611e8b453fb..4bd211a12b3b0 100644 --- a/build.gradle +++ b/build.gradle @@ -212,6 +212,7 @@ allprojects { "org.elasticsearch:elasticsearch-core:${version}": ':libs:core', "org.elasticsearch:elasticsearch-nio:${version}": ':libs:nio', "org.elasticsearch:elasticsearch-x-content:${version}": ':libs:x-content', + "org.elasticsearch:elasticsearch-geo:${version}": ':libs:elasticsearch-geo', "org.elasticsearch:elasticsearch-secure-sm:${version}": ':libs:secure-sm', "org.elasticsearch.client:elasticsearch-rest-client:${version}": ':client:rest', "org.elasticsearch.client:elasticsearch-rest-client-sniffer:${version}": ':client:sniffer', diff --git a/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Line.java b/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Line.java index 415dacfce9b3c..348537205af55 100644 --- a/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Line.java +++ b/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Line.java @@ -67,6 +67,14 @@ public double getLon(int i) { return lons[i]; } + public double[] getLats() { + return lats.clone(); + } + + public double[] getLons() { + return lons.clone(); + } + @Override public ShapeType type() { return ShapeType.LINESTRING; diff --git a/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Point.java b/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Point.java index d85d40c8dc789..c272261ee3a9c 100644 --- a/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Point.java +++ b/libs/geo/src/main/java/org/elasticsearch/geo/geometry/Point.java @@ -48,11 +48,11 @@ public ShapeType type() { return ShapeType.POINT; } - public double lat() { + public double getLat() { return lat; } - public double lon() { + public double getLon() { return lon; } diff --git a/libs/geo/src/main/java/org/elasticsearch/geo/utils/WellKnownText.java b/libs/geo/src/main/java/org/elasticsearch/geo/utils/WellKnownText.java index 5cf29065b006a..5fa585be28b24 100644 --- a/libs/geo/src/main/java/org/elasticsearch/geo/utils/WellKnownText.java +++ b/libs/geo/src/main/java/org/elasticsearch/geo/utils/WellKnownText.java @@ -123,12 +123,12 @@ public Void visit(MultiLine multiLine) { public Void visit(MultiPoint multiPoint) { // walk through coordinates: sb.append(LPAREN); - visitPoint(multiPoint.get(0).lon(), multiPoint.get(0).lat()); + visitPoint(multiPoint.get(0).getLon(), multiPoint.get(0).getLat()); for (int i = 1; i < multiPoint.size(); ++i) { sb.append(COMMA); sb.append(SPACE); Point point = multiPoint.get(i); - visitPoint(point.lon(), point.lat()); + visitPoint(point.getLon(), point.getLat()); } sb.append(RPAREN); return null; @@ -146,7 +146,7 @@ public Void visit(Point point) { sb.append(EMPTY); } else { sb.append(LPAREN); - visitPoint(point.lon(), point.lat()); + visitPoint(point.getLon(), point.getLat()); sb.append(RPAREN); } return null; diff --git a/server/build.gradle b/server/build.gradle index a3197acde4ad8..5e2ae5939dad0 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -77,7 +77,8 @@ dependencies { compile "org.elasticsearch:elasticsearch-core:${version}" compile "org.elasticsearch:elasticsearch-secure-sm:${version}" compile "org.elasticsearch:elasticsearch-x-content:${version}" - + compile "org.elasticsearch:elasticsearch-geo:${version}" + compileOnly project(':libs:plugin-classloader') testRuntime project(':libs:plugin-classloader') diff --git a/server/src/main/java/org/elasticsearch/common/geo/GeoShapeType.java b/server/src/main/java/org/elasticsearch/common/geo/GeoShapeType.java index 5022f66550c7f..aefd189edaf88 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/GeoShapeType.java +++ b/server/src/main/java/org/elasticsearch/common/geo/GeoShapeType.java @@ -258,7 +258,7 @@ CoordinateNode validate(CoordinateNode coordinates, boolean coerce) { }, GEOMETRYCOLLECTION("geometrycollection") { @Override - public ShapeBuilder getBuilder(CoordinateNode coordinates, DistanceUnit.Distance radius, + public ShapeBuilder getBuilder(CoordinateNode coordinates, DistanceUnit.Distance radius, Orientation orientation, boolean coerce) { // noop, handled in parser return null; @@ -298,7 +298,7 @@ public static GeoShapeType forName(String geoshapename) { throw new IllegalArgumentException("unknown geo_shape ["+geoshapename+"]"); } - public abstract ShapeBuilder getBuilder(CoordinateNode coordinates, DistanceUnit.Distance radius, + public abstract ShapeBuilder getBuilder(CoordinateNode coordinates, DistanceUnit.Distance radius, ShapeBuilder.Orientation orientation, boolean coerce); abstract CoordinateNode validate(CoordinateNode coordinates, boolean coerce); diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java index 5e2b6cc1c4453..ec4e01fa8c87e 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java @@ -34,7 +34,7 @@ import java.io.IOException; import java.util.Objects; -public class CircleBuilder extends ShapeBuilder { +public class CircleBuilder extends ShapeBuilder { public static final ParseField FIELD_RADIUS = new ParseField("radius"); public static final GeoShapeType TYPE = GeoShapeType.CIRCLE; @@ -164,7 +164,7 @@ public Circle buildS4J() { } @Override - public Object buildLucene() { + public org.elasticsearch.geo.geometry.Circle buildGeometry() { throw new UnsupportedOperationException("CIRCLE geometry is not supported"); } diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java index 5f69f4ad44dba..09fa2f7da5544 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java @@ -32,7 +32,7 @@ import java.io.IOException; import java.util.Objects; -public class EnvelopeBuilder extends ShapeBuilder { +public class EnvelopeBuilder extends ShapeBuilder { public static final GeoShapeType TYPE = GeoShapeType.ENVELOPE; @@ -113,8 +113,8 @@ public Rectangle buildS4J() { } @Override - public org.apache.lucene.geo.Rectangle buildLucene() { - return new org.apache.lucene.geo.Rectangle(bottomRight.y, topLeft.y, topLeft.x, bottomRight.x); + public org.elasticsearch.geo.geometry.Rectangle buildGeometry() { + return new org.elasticsearch.geo.geometry.Rectangle(bottomRight.y, topLeft.y, topLeft.x, bottomRight.x); } @Override diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java index fdf7073bd7454..fb3ff6203ed45 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java @@ -31,11 +31,11 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Objects; -public class GeometryCollectionBuilder extends ShapeBuilder { +public class GeometryCollectionBuilder extends ShapeBuilder, GeometryCollectionBuilder> { public static final GeoShapeType TYPE = GeoShapeType.GEOMETRYCOLLECTION; @@ -185,19 +185,14 @@ public Shape buildS4J() { } @Override - public Object buildLucene() { - List shapes = new ArrayList<>(this.shapes.size()); + public org.elasticsearch.geo.geometry.GeometryCollection buildGeometry() { + List shapes = new ArrayList<>(this.shapes.size()); for (ShapeBuilder shape : this.shapes) { - Object o = shape.buildLucene(); - if (o.getClass().isArray()) { - shapes.addAll(Arrays.asList((Object[])o)); - } else { - shapes.add(o); - } + shapes.add(shape.buildGeometry()); } - return shapes.toArray(new Object[shapes.size()]); + return new org.elasticsearch.geo.geometry.GeometryCollection<>(shapes); } @Override diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java index 07edb241cd76c..8e1e9d7a993b2 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java @@ -19,16 +19,16 @@ package org.elasticsearch.common.geo.builders; -import org.apache.lucene.geo.Line; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.GeometryFactory; -import org.locationtech.jts.geom.LineString; - import org.elasticsearch.common.geo.GeoShapeType; import org.elasticsearch.common.geo.parsers.ShapeParser; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.geo.geometry.Line; +import org.elasticsearch.geo.geometry.MultiLine; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.LineString; import org.locationtech.spatial4j.shape.jts.JtsGeometry; import java.io.IOException; @@ -39,7 +39,7 @@ import static org.elasticsearch.common.geo.GeoUtils.normalizeLat; import static org.elasticsearch.common.geo.GeoUtils.normalizeLon; -public class LineStringBuilder extends ShapeBuilder { +public class LineStringBuilder extends ShapeBuilder { public static final GeoShapeType TYPE = GeoShapeType.LINESTRING; /** @@ -125,15 +125,15 @@ public JtsGeometry buildS4J() { } @Override - public Object buildLucene() { + public org.elasticsearch.geo.geometry.Geometry buildGeometry() { // decompose linestrings crossing dateline into array of Lines Coordinate[] coordinates = this.coordinates.toArray(new Coordinate[this.coordinates.size()]); if (wrapdateline) { - ArrayList linestrings = decomposeLucene(coordinates, new ArrayList<>()); + List linestrings = decomposeGeometry(coordinates, new ArrayList<>()); if (linestrings.size() == 1) { return linestrings.get(0); } else { - return linestrings.toArray(new Line[linestrings.size()]); + return new MultiLine(linestrings); } } return new Line(Arrays.stream(coordinates).mapToDouble(i->normalizeLat(i.y)).toArray(), @@ -149,7 +149,7 @@ static ArrayList decomposeS4J(GeometryFactory factory, Coordinate[] return strings; } - static ArrayList decomposeLucene(Coordinate[] coordinates, ArrayList lines) { + static List decomposeGeometry(Coordinate[] coordinates, List lines) { for (Coordinate[] part : decompose(+DATELINE, coordinates)) { for (Coordinate[] line : decompose(-DATELINE, part)) { lines.add(new Line(Arrays.stream(line).mapToDouble(i->normalizeLat(i.y)).toArray(), diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java index 9902744fc3b2c..a283cda874528 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java @@ -19,25 +19,25 @@ package org.elasticsearch.common.geo.builders; -import org.apache.lucene.geo.Line; import org.elasticsearch.common.geo.GeoShapeType; import org.elasticsearch.common.geo.parsers.GeoWKTParser; import org.elasticsearch.common.geo.parsers.ShapeParser; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.LineString; - import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.geo.geometry.MultiLine; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.LineString; import org.locationtech.spatial4j.shape.jts.JtsGeometry; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Objects; -public class MultiLineStringBuilder extends ShapeBuilder { +public class MultiLineStringBuilder extends ShapeBuilder { public static final GeoShapeType TYPE = GeoShapeType.MULTILINESTRING; @@ -150,24 +150,24 @@ public JtsGeometry buildS4J() { } @Override - public Object buildLucene() { + public org.elasticsearch.geo.geometry.Geometry buildGeometry() { if (wrapdateline) { - ArrayList parts = new ArrayList<>(); + List parts = new ArrayList<>(); for (LineStringBuilder line : lines) { - LineStringBuilder.decomposeLucene(line.coordinates(false), parts); + LineStringBuilder.decomposeGeometry(line.coordinates(false), parts); } if (parts.size() == 1) { return parts.get(0); } - return parts.toArray(new Line[parts.size()]); + return new MultiLine(parts); } - Line[] linestrings = new Line[lines.size()]; + List linestrings = new ArrayList<>(lines.size()); for (int i = 0; i < lines.size(); ++i) { LineStringBuilder lsb = lines.get(i); - linestrings[i] = new Line(lsb.coordinates.stream().mapToDouble(c->c.y).toArray(), - lsb.coordinates.stream().mapToDouble(c->c.x).toArray()); + linestrings.add(new org.elasticsearch.geo.geometry.Line(lsb.coordinates.stream().mapToDouble(c->c.y).toArray(), + lsb.coordinates.stream().mapToDouble(c->c.x).toArray())); } - return linestrings; + return new MultiLine(linestrings); } @Override diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java index b559bb581179e..c92d67e8291ea 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java @@ -24,14 +24,16 @@ import org.elasticsearch.common.geo.parsers.ShapeParser; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.geo.geometry.MultiPoint; import org.locationtech.jts.geom.Coordinate; import org.locationtech.spatial4j.shape.Point; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; -public class MultiPointBuilder extends ShapeBuilder, MultiPointBuilder> { +public class MultiPointBuilder extends ShapeBuilder, MultiPoint, MultiPointBuilder> { public static final GeoShapeType TYPE = GeoShapeType.MULTIPOINT; @@ -74,14 +76,9 @@ public XShapeCollection buildS4J() { } @Override - public double[][] buildLucene() { - double[][] points = new double[coordinates.size()][]; - Coordinate coord; - for (int i = 0; i < coordinates.size(); ++i) { - coord = coordinates.get(i); - points[i] = new double[] {coord.x, coord.y}; - } - return points; + public MultiPoint buildGeometry() { + return new MultiPoint(coordinates.stream().map(coord -> new org.elasticsearch.geo.geometry.Point(coord.y, coord.x)) + .collect(Collectors.toList())); } @Override diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java index 95c2bbc6275a6..be0741306c097 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java @@ -26,17 +26,17 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.geo.geometry.MultiPolygon; import org.locationtech.jts.geom.Coordinate; import org.locationtech.spatial4j.shape.Shape; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Objects; -public class MultiPolygonBuilder extends ShapeBuilder { +public class MultiPolygonBuilder extends ShapeBuilder { public static final GeoShapeType TYPE = GeoShapeType.MULTIPOLYGON; @@ -185,31 +185,20 @@ public Shape buildS4J() { //note: ShapeCollection is probably faster than a Multi* geom. } + @SuppressWarnings({"unchecked"}) @Override - public Object buildLucene() { - List shapes = new ArrayList<>(this.polygons.size()); + public MultiPolygon buildGeometry() { + List shapes = new ArrayList<>(this.polygons.size()); Object poly; - if (wrapdateline) { - for (PolygonBuilder polygon : this.polygons) { - poly = polygon.buildLucene(); - if (poly instanceof org.apache.lucene.geo.Polygon[]) { - shapes.addAll(Arrays.asList((org.apache.lucene.geo.Polygon[])poly)); - } else { - shapes.add((org.apache.lucene.geo.Polygon)poly); - } - } - } else { - for (int i = 0; i < this.polygons.size(); ++i) { - PolygonBuilder pb = this.polygons.get(i); - poly = pb.buildLucene(); - if (poly instanceof org.apache.lucene.geo.Polygon[]) { - shapes.addAll(Arrays.asList((org.apache.lucene.geo.Polygon[])poly)); - } else { - shapes.add((org.apache.lucene.geo.Polygon)poly); - } + for (PolygonBuilder polygon : this.polygons) { + poly = polygon.buildGeometry(); + if (poly instanceof List) { + shapes.addAll((List) poly); + } else { + shapes.add((org.elasticsearch.geo.geometry.Polygon)poly); } } - return shapes.stream().toArray(org.apache.lucene.geo.Polygon[]::new); + return new MultiPolygon(shapes); } @Override diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java index c13eca936e492..6a4fcd064c5da 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java @@ -19,18 +19,16 @@ package org.elasticsearch.common.geo.builders; -import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoShapeType; import org.elasticsearch.common.geo.parsers.ShapeParser; -import org.locationtech.spatial4j.shape.Point; -import org.locationtech.jts.geom.Coordinate; - import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.spatial4j.shape.Point; import java.io.IOException; -public class PointBuilder extends ShapeBuilder { +public class PointBuilder extends ShapeBuilder { public static final GeoShapeType TYPE = GeoShapeType.POINT; /** @@ -90,8 +88,8 @@ public Point buildS4J() { } @Override - public GeoPoint buildLucene() { - return new GeoPoint(coordinates.get(0).y, coordinates.get(0).x); + public org.elasticsearch.geo.geometry.Point buildGeometry() { + return new org.elasticsearch.geo.geometry.Point(coordinates.get(0).y, coordinates.get(0).x); } @Override diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java index ac19642949c86..e4751de04bfe3 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java @@ -38,6 +38,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -55,7 +56,7 @@ * Methods to wrap polygons at the dateline and building shapes from the data held by the * builder. */ -public class PolygonBuilder extends ShapeBuilder { +public class PolygonBuilder extends ShapeBuilder { public static final GeoShapeType TYPE = GeoShapeType.POLYGON; @@ -233,14 +234,14 @@ public JtsGeometry buildS4J() { } @Override - public Object buildLucene() { + public org.elasticsearch.geo.geometry.Geometry buildGeometry() { if (wrapdateline) { Coordinate[][][] polygons = coordinates(); return polygons.length == 1 - ? polygonLucene(polygons[0]) - : multipolygonLucene(polygons); + ? polygonGeometry(polygons[0]) + : multipolygon(polygons); } - return toPolygonLucene(); + return toPolygonGeometry(); } protected XContentBuilder coordinatesArray(XContentBuilder builder, Params params) throws IOException { @@ -288,17 +289,19 @@ protected Polygon toPolygonS4J(GeometryFactory factory) { return factory.createPolygon(shell, holes); } - public Object toPolygonLucene() { - final org.apache.lucene.geo.Polygon[] holes = new org.apache.lucene.geo.Polygon[this.holes.size()]; - for (int i = 0; i < holes.length; ++i) { - holes[i] = linearRing(this.holes.get(i).coordinates); + public org.elasticsearch.geo.geometry.Polygon toPolygonGeometry() { + final List holes = new ArrayList<>(this.holes.size()); + for (int i = 0; i < this.holes.size(); ++i) { + holes.add(linearRing(this.holes.get(i).coordinates)); } - return new org.apache.lucene.geo.Polygon(this.shell.coordinates.stream().mapToDouble(i -> normalizeLat(i.y)).toArray(), - this.shell.coordinates.stream().mapToDouble(i -> normalizeLon(i.x)).toArray(), holes); + return new org.elasticsearch.geo.geometry.Polygon( + new org.elasticsearch.geo.geometry.LinearRing( + this.shell.coordinates.stream().mapToDouble(i -> normalizeLat(i.y)).toArray(), + this.shell.coordinates.stream().mapToDouble(i -> normalizeLon(i.x)).toArray()), holes); } - protected static org.apache.lucene.geo.Polygon linearRing(List coordinates) { - return new org.apache.lucene.geo.Polygon(coordinates.stream().mapToDouble(i -> normalizeLat(i.y)).toArray(), + protected static org.elasticsearch.geo.geometry.LinearRing linearRing(List coordinates) { + return new org.elasticsearch.geo.geometry.LinearRing(coordinates.stream().mapToDouble(i -> normalizeLat(i.y)).toArray(), coordinates.stream().mapToDouble(i -> normalizeLon(i.x)).toArray()); } @@ -335,13 +338,13 @@ protected static Polygon polygonS4J(GeometryFactory factory, Coordinate[][] poly return factory.createPolygon(shell, holes); } - protected static org.apache.lucene.geo.Polygon polygonLucene(Coordinate[][] polygon) { - org.apache.lucene.geo.Polygon[] holes; + protected static org.elasticsearch.geo.geometry.Polygon polygonGeometry(Coordinate[][] polygon) { + List holes; Coordinate[] shell = polygon[0]; if (polygon.length > 1) { - holes = new org.apache.lucene.geo.Polygon[polygon.length - 1]; - for (int i = 0; i < holes.length; ++i) { - Coordinate[] coords = polygon[i+1]; + holes = new ArrayList<>(polygon.length - 1); + for (int i = 1; i < polygon.length; ++i) { + Coordinate[] coords = polygon[i]; //We do not have holes on the dateline as they get eliminated //when breaking the polygon around it. double[] x = new double[coords.length]; @@ -350,10 +353,10 @@ protected static org.apache.lucene.geo.Polygon polygonLucene(Coordinate[][] poly x[c] = normalizeLon(coords[c].x); y[c] = normalizeLat(coords[c].y); } - holes[i] = new org.apache.lucene.geo.Polygon(y, x); + holes.add(new org.elasticsearch.geo.geometry.LinearRing(y, x)); } } else { - holes = new org.apache.lucene.geo.Polygon[0]; + holes = Collections.emptyList(); } double[] x = new double[shell.length]; @@ -365,7 +368,7 @@ protected static org.apache.lucene.geo.Polygon polygonLucene(Coordinate[][] poly y[i] = normalizeLat(shell[i].y); } - return new org.apache.lucene.geo.Polygon(y, x, holes); + return new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing(y, x), holes); } /** @@ -386,12 +389,12 @@ protected static MultiPolygon multipolygonS4J(GeometryFactory factory, Coordinat return factory.createMultiPolygon(polygonSet); } - protected static org.apache.lucene.geo.Polygon[] multipolygonLucene(Coordinate[][][] polygons) { - org.apache.lucene.geo.Polygon[] polygonSet = new org.apache.lucene.geo.Polygon[polygons.length]; - for (int i = 0; i < polygonSet.length; ++i) { - polygonSet[i] = polygonLucene(polygons[i]); + protected static org.elasticsearch.geo.geometry.MultiPolygon multipolygon(Coordinate[][][] polygons) { + List polygonSet = new ArrayList<>(polygons.length); + for (int i = 0; i < polygons.length; ++i) { + polygonSet.add(polygonGeometry(polygons[i])); } - return polygonSet; + return new org.elasticsearch.geo.geometry.MultiPolygon(polygonSet); } /** diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java index 365dddb70eab4..d6ba295be67e3 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java @@ -52,7 +52,8 @@ /** * Basic class for building GeoJSON shapes like Polygons, Linestrings, etc */ -public abstract class ShapeBuilder> implements NamedWriteable, ToXContentObject { +public abstract class ShapeBuilder> implements NamedWriteable, ToXContentObject { protected static final Logger LOGGER = LogManager.getLogger(ShapeBuilder.class); @@ -218,7 +219,7 @@ protected JtsGeometry jtsGeometry(Geometry geom) { * * @return GeoPoint, double[][], Line, Line[], Polygon, Polygon[], Rectangle, Object[] */ - public abstract Object buildLucene(); + public abstract G buildGeometry(); protected static Coordinate shift(Coordinate coordinate, double dateline) { if (dateline == 0) { @@ -484,7 +485,7 @@ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof ShapeBuilder)) return false; - ShapeBuilder that = (ShapeBuilder) o; + ShapeBuilder that = (ShapeBuilder) o; return Objects.equals(coordinates, that.coordinates); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java index 486ff0bbe4a70..72b3e68fa025e 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java @@ -22,13 +22,20 @@ import org.apache.lucene.document.LatLonShape; import org.apache.lucene.geo.Line; import org.apache.lucene.geo.Polygon; -import org.apache.lucene.geo.Rectangle; import org.apache.lucene.index.IndexableField; import org.elasticsearch.common.Explicit; -import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.parsers.ShapeParser; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.geo.geometry.Circle; +import org.elasticsearch.geo.geometry.Geometry; +import org.elasticsearch.geo.geometry.GeometryCollection; +import org.elasticsearch.geo.geometry.GeometryVisitor; +import org.elasticsearch.geo.geometry.LinearRing; +import org.elasticsearch.geo.geometry.MultiLine; +import org.elasticsearch.geo.geometry.MultiPoint; +import org.elasticsearch.geo.geometry.MultiPolygon; +import org.elasticsearch.geo.geometry.Point; import java.io.IOException; import java.util.ArrayList; @@ -107,7 +114,7 @@ public void parse(ParseContext context) throws IOException { if (shapeBuilder == null) { return; } - shape = shapeBuilder.buildLucene(); + shape = shapeBuilder.buildGeometry(); } indexShape(context, shape); } catch (Exception e) { @@ -120,45 +127,95 @@ public void parse(ParseContext context) throws IOException { } private void indexShape(ParseContext context, Object luceneShape) { - if (luceneShape instanceof GeoPoint) { - GeoPoint pt = (GeoPoint) luceneShape; - indexFields(context, LatLonShape.createIndexableFields(name(), pt.lat(), pt.lon())); - } else if (luceneShape instanceof double[]) { - double[] pt = (double[]) luceneShape; - indexFields(context, LatLonShape.createIndexableFields(name(), pt[1], pt[0])); - } else if (luceneShape instanceof Line) { - indexFields(context, LatLonShape.createIndexableFields(name(), (Line)luceneShape)); - } else if (luceneShape instanceof Polygon) { - indexFields(context, LatLonShape.createIndexableFields(name(), (Polygon) luceneShape)); - } else if (luceneShape instanceof double[][]) { - double[][] pts = (double[][])luceneShape; - for (int i = 0; i < pts.length; ++i) { - indexFields(context, LatLonShape.createIndexableFields(name(), pts[i][1], pts[i][0])); + if (luceneShape instanceof Geometry) { + ((Geometry) luceneShape).visit(new LuceneGeometryIndexer(context)); + } else { + throw new IllegalArgumentException("invalid shape type found [" + luceneShape.getClass() + "] while indexing shape"); + } + } + + private class LuceneGeometryIndexer implements GeometryVisitor { + private ParseContext context; + + private LuceneGeometryIndexer(ParseContext context) { + this.context = context; + } + + @Override + public Void visit(Circle circle) { + throw new IllegalArgumentException("invalid shape type found [Circle] while indexing shape"); + } + + @Override + public Void visit(GeometryCollection collection) { + for (Geometry geometry : collection) { + geometry.visit(this); } - } else if (luceneShape instanceof Line[]) { - Line[] lines = (Line[]) luceneShape; - for (int i = 0; i < lines.length; ++i) { - indexFields(context, LatLonShape.createIndexableFields(name(), lines[i])); + return null; + } + + @Override + public Void visit(org.elasticsearch.geo.geometry.Line line) { + indexFields(context, LatLonShape.createIndexableFields(name(), new Line(line.getLats(), line.getLons()))); + return null; + } + + @Override + public Void visit(LinearRing ring) { + throw new IllegalArgumentException("invalid shape type found [LinearRing] while indexing shape"); + } + + @Override + public Void visit(MultiLine multiLine) { + for (org.elasticsearch.geo.geometry.Line line : multiLine) { + visit(line); } - } else if (luceneShape instanceof Polygon[]) { - Polygon[] polys = (Polygon[]) luceneShape; - for (int i = 0; i < polys.length; ++i) { - indexFields(context, LatLonShape.createIndexableFields(name(), polys[i])); + return null; + } + + @Override + public Void visit(MultiPoint multiPoint) { + for(Point point : multiPoint) { + visit(point); } - } else if (luceneShape instanceof Rectangle) { - // index rectangle as a polygon - Rectangle r = (Rectangle) luceneShape; - Polygon p = new Polygon(new double[]{r.minLat, r.minLat, r.maxLat, r.maxLat, r.minLat}, - new double[]{r.minLon, r.maxLon, r.maxLon, r.minLon, r.minLon}); - indexFields(context, LatLonShape.createIndexableFields(name(), p)); - } else if (luceneShape instanceof Object[]) { - // recurse to index geometry collection - for (Object o : (Object[])luceneShape) { - indexShape(context, o); + return null; + } + + @Override + public Void visit(MultiPolygon multiPolygon) { + for(org.elasticsearch.geo.geometry.Polygon polygon : multiPolygon) { + visit(polygon); } - } else { - throw new IllegalArgumentException("invalid shape type found [" + luceneShape.getClass() + "] while indexing shape"); + return null; + } + + @Override + public Void visit(Point point) { + indexFields(context, LatLonShape.createIndexableFields(name(), point.getLat(), point.getLon())); + return null; + } + + @Override + public Void visit(org.elasticsearch.geo.geometry.Polygon polygon) { + indexFields(context, LatLonShape.createIndexableFields(name(), toLucenePolygon(polygon))); + return null; + } + + @Override + public Void visit(org.elasticsearch.geo.geometry.Rectangle r) { + Polygon p = new Polygon(new double[]{r.getMinLat(), r.getMinLat(), r.getMaxLat(), r.getMaxLat(), r.getMinLat()}, + new double[]{r.getMinLon(), r.getMaxLon(), r.getMaxLon(), r.getMinLon(), r.getMinLon()}); + indexFields(context, LatLonShape.createIndexableFields(name(), p)); + return null; + } + } + + public static Polygon toLucenePolygon(org.elasticsearch.geo.geometry.Polygon polygon) { + Polygon[] holes = new Polygon[polygon.getNumberOfHoles()]; + for(int i = 0; i() { + @Override + public Query visit(Circle circle) { + throw new QueryShardException(context, "Field [" + fieldName + "] found and unknown shape Circle"); + } + + @Override + public Query visit(GeometryCollection collection) { + BooleanQuery.Builder bqb = new BooleanQuery.Builder(); + visit(bqb, collection); + return bqb.build(); + } + + private void visit(BooleanQuery.Builder bqb, GeometryCollection collection) { + for (Geometry shape : collection) { + if (shape instanceof MultiPoint) { + // Flatten multipoints + visit(bqb, (GeometryCollection) shape); + } else { + bqb.add(shape.visit(this), BooleanClause.Occur.SHOULD); + } } } - return LatLonShape.newBoxQuery(fieldName, relation.getLuceneRelation(), pt[1], pt[1], pt[0], pt[0]); - } else if (queryShape instanceof Object[]) { - geoQuery = createGeometryCollectionQuery(context, (Object[]) queryShape); - } else { - throw new QueryShardException(context, "Field [" + fieldName + "] found and unknown shape"); - } - return geoQuery; - } - private Query createGeometryCollectionQuery(QueryShardContext context, Object... shapes) { - BooleanQuery.Builder bqb = new BooleanQuery.Builder(); - for (Object shape : shapes) { - bqb.add(getVectorQueryFromShape(context, shape), BooleanClause.Occur.SHOULD); - } - return bqb.build(); + @Override + public Query visit(org.elasticsearch.geo.geometry.Line line) { + return LatLonShape.newLineQuery(fieldName(), relation.getLuceneRelation(), new Line(line.getLats(), line.getLons())); + } + + @Override + public Query visit(LinearRing ring) { + throw new QueryShardException(context, "Field [" + fieldName + "] found and unsupported shape LinearRing"); + } + + @Override + public Query visit(MultiLine multiLine) { + Line[] lines = new Line[multiLine.size()]; + for (int i=0; ii.y).toArray(), - Arrays.stream(coordinates).mapToDouble(i->i.x).toArray()); + Arrays.stream(coordinates).mapToDouble(i->i.x).toArray() + )); assertGeometryEquals(p, polygonGeoJson, false); } @@ -502,7 +508,7 @@ public void testParseOGCPolygonWithoutHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 2: ccw poly crossing dateline @@ -527,7 +533,7 @@ public void testParseOGCPolygonWithoutHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 3: cw poly not crossing dateline @@ -552,7 +558,7 @@ public void testParseOGCPolygonWithoutHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 4: cw poly crossing dateline @@ -577,7 +583,7 @@ public void testParseOGCPolygonWithoutHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildGeometry(), false); } } @@ -610,7 +616,7 @@ public void testParseOGCPolygonWithHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 2: ccw poly crossing dateline @@ -641,7 +647,7 @@ public void testParseOGCPolygonWithHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 3: cw poly not crossing dateline @@ -672,7 +678,7 @@ public void testParseOGCPolygonWithHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 4: cw poly crossing dateline @@ -703,7 +709,7 @@ public void testParseOGCPolygonWithHoles() throws IOException { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildGeometry(), false); } } @@ -855,12 +861,12 @@ public void testParsePolygonWithHole() throws IOException { Polygon expected = GEOMETRY_FACTORY.createPolygon(shell, holes); assertGeometryEquals(jtsGeom(expected), polygonGeoJson, true); - org.apache.lucene.geo.Polygon hole = - new org.apache.lucene.geo.Polygon( + org.elasticsearch.geo.geometry.LinearRing hole = + new org.elasticsearch.geo.geometry.LinearRing( new double[] {0.8d, 0.2d, 0.2d, 0.8d, 0.8d}, new double[] {100.8d, 100.8d, 100.2d, 100.2d, 100.8d}); - org.apache.lucene.geo.Polygon p = - new org.apache.lucene.geo.Polygon( - new double[] {0d, 0d, 1d, 1d, 0d}, new double[] {100d, 101d, 101d, 100d, 100d}, hole); + org.elasticsearch.geo.geometry.Polygon p = + new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing( + new double[] {0d, 0d, 1d, 1d, 0d}, new double[] {100d, 101d, 101d, 100d, 100d}), Collections.singletonList(hole)); assertGeometryEquals(p, polygonGeoJson, false); } @@ -902,9 +908,9 @@ public void testParseMultiPoint() throws IOException { SPATIAL_CONTEXT.makePoint(101, 1.0)); assertGeometryEquals(expected, multiPointGeoJson, true); - assertGeometryEquals(new double[][]{ - new double[] {100d, 0d}, - new double[] {101d, 1d}}, multiPointGeoJson, false); + assertGeometryEquals(new MultiPoint(Arrays.asList( + new org.elasticsearch.geo.geometry.Point(0, 100), + new org.elasticsearch.geo.geometry.Point(1, 101))), multiPointGeoJson, false); } @Override @@ -975,16 +981,15 @@ public void testParseMultiPolygon() throws IOException { assertGeometryEquals(expected, multiPolygonGeoJson, true); - org.apache.lucene.geo.Polygon hole = - new org.apache.lucene.geo.Polygon( + org.elasticsearch.geo.geometry.LinearRing hole = new org.elasticsearch.geo.geometry.LinearRing( new double[] {0.8d, 0.2d, 0.2d, 0.8d, 0.8d}, new double[] {100.8d, 100.8d, 100.2d, 100.2d, 100.8d}); - org.apache.lucene.geo.Polygon[] polygons = new org.apache.lucene.geo.Polygon[] { - new org.apache.lucene.geo.Polygon( - new double[] {2d, 3d, 3d, 2d, 2d}, new double[] {103d, 103d, 102d, 102d, 103d}), - new org.apache.lucene.geo.Polygon( - new double[] {0d, 1d, 1d, 0d, 0d}, new double[] {101d, 101d, 100d, 100d, 101d}, hole) - }; + org.elasticsearch.geo.geometry.MultiPolygon polygons = new org.elasticsearch.geo.geometry.MultiPolygon(Arrays.asList( + new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing( + new double[] {2d, 3d, 3d, 2d, 2d}, new double[] {103d, 103d, 102d, 102d, 103d})), + new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing( + new double[] {0d, 1d, 1d, 0d, 0d}, new double[] {101d, 101d, 100d, 100d, 101d}), Collections.singletonList(hole)))); + assertGeometryEquals(polygons, multiPolygonGeoJson, false); // test #2: multipolygon; one polygon with one hole @@ -1034,14 +1039,13 @@ public void testParseMultiPolygon() throws IOException { assertGeometryEquals(jtsGeom(withHoles), multiPolygonGeoJson, true); - org.apache.lucene.geo.Polygon luceneHole = - new org.apache.lucene.geo.Polygon( + org.elasticsearch.geo.geometry.LinearRing luceneHole = + new org.elasticsearch.geo.geometry.LinearRing( new double[] {0.8d, 0.2d, 0.2d, 0.8d, 0.8d}, new double[] {100.8d, 100.8d, 100.2d, 100.2d, 100.8d}); - org.apache.lucene.geo.Polygon[] lucenePolygons = new org.apache.lucene.geo.Polygon[] { - new org.apache.lucene.geo.Polygon( - new double[] {0d, 0d, 1d, 1d, 0d}, new double[] {100d, 101d, 101d, 100d, 100d}, luceneHole) - }; + org.elasticsearch.geo.geometry.MultiPolygon lucenePolygons = new org.elasticsearch.geo.geometry.MultiPolygon( + Collections.singletonList(new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing( + new double[] {0d, 0d, 1d, 1d, 0d}, new double[] {100d, 101d, 101d, 100d, 100d}), Collections.singletonList(luceneHole)))); assertGeometryEquals(lucenePolygons, multiPolygonGeoJson, false); } @@ -1117,19 +1121,21 @@ public void testParseGeometryCollection() throws IOException { //equals returns true only if geometries are in the same order assertGeometryEquals(shapeCollection(expected), geometryCollectionGeoJson, true); - Object[] luceneExpected = new Object[] { - new Line(new double[] {0d, 1d}, new double[] {100d, 101d}), - new GeoPoint(2d, 102d), - new org.apache.lucene.geo.Polygon( - new double[] {-12.142857142857142d, 12.142857142857142d, 15d, 0d, -15d, -12.142857142857142d}, - new double[] {180d, 180d, 176d, 172d, 176d, 180d} - ), - new org.apache.lucene.geo.Polygon( - new double[] {12.142857142857142d, -12.142857142857142d, -10d, 10d, 12.142857142857142d}, - new double[] {-180d, -180d, -177d, -177d, -180d} - ) - }; - assertGeometryEquals(luceneExpected, geometryCollectionGeoJson, false); + GeometryCollection geometryExpected = new GeometryCollection<> (Arrays.asList( + new org.elasticsearch.geo.geometry.Line(new double[] {0d, 1d}, new double[] {100d, 101d}), + new org.elasticsearch.geo.geometry.Point(2d, 102d), + new org.elasticsearch.geo.geometry.MultiPolygon(Arrays.asList( + new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing( + new double[] {-12.142857142857142d, 12.142857142857142d, 15d, 0d, -15d, -12.142857142857142d}, + new double[] {180d, 180d, 176d, 172d, 176d, 180d} + )), + new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing( + new double[] {12.142857142857142d, -12.142857142857142d, -10d, 10d, 12.142857142857142d}, + new double[] {-180d, -180d, -177d, -177d, -180d} + )) + )) + )); + assertGeometryEquals(geometryExpected, geometryCollectionGeoJson, false); } public void testThatParserExtractsCorrectTypeAndCoordinatesFromArbitraryJson() throws IOException { @@ -1151,7 +1157,7 @@ public void testThatParserExtractsCorrectTypeAndCoordinatesFromArbitraryJson() t Point expected = GEOMETRY_FACTORY.createPoint(new Coordinate(100.0, 0.0)); assertGeometryEquals(new JtsPoint(expected, SPATIAL_CONTEXT), pointGeoJson, true); - GeoPoint expectedPt = new GeoPoint(0, 100); + org.elasticsearch.geo.geometry.Point expectedPt = new org.elasticsearch.geo.geometry.Point(0, 100); assertGeometryEquals(expectedPt, pointGeoJson, false); } @@ -1187,7 +1193,7 @@ public void testParseOrientationOption() throws IOException { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 2: valid ccw (right handed system) poly not crossing dateline (with 'ccw' field) @@ -1221,7 +1227,7 @@ public void testParseOrientationOption() throws IOException { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 3: valid ccw (right handed system) poly not crossing dateline (with 'counterclockwise' field) @@ -1255,7 +1261,7 @@ public void testParseOrientationOption() throws IOException { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 4: valid cw (left handed system) poly crossing dateline (with 'left' field) @@ -1289,7 +1295,7 @@ public void testParseOrientationOption() throws IOException { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 5: valid cw multipoly (left handed system) poly crossing dateline (with 'cw' field) @@ -1323,7 +1329,7 @@ public void testParseOrientationOption() throws IOException { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildGeometry(), false); } // test 6: valid cw multipoly (left handed system) poly crossing dateline (with 'clockwise' field) @@ -1357,7 +1363,7 @@ public void testParseOrientationOption() throws IOException { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildGeometry(), false); } } diff --git a/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java b/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java index 94c96e00d9236..f1d9b0f161570 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java @@ -19,7 +19,6 @@ package org.elasticsearch.common.geo; import org.apache.lucene.geo.GeoTestUtil; -import org.apache.lucene.geo.Line; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.Version; @@ -41,6 +40,9 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.geo.geometry.Line; +import org.elasticsearch.geo.geometry.MultiLine; +import org.elasticsearch.geo.geometry.MultiPoint; import org.elasticsearch.index.mapper.ContentPath; import org.elasticsearch.index.mapper.GeoShapeFieldMapper; import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper; @@ -61,6 +63,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.elasticsearch.common.geo.builders.ShapeBuilder.SPATIAL_CONTEXT; @@ -72,7 +75,7 @@ */ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { - private static XContentBuilder toWKTContent(ShapeBuilder builder, boolean generateMalformed) + private static XContentBuilder toWKTContent(ShapeBuilder builder, boolean generateMalformed) throws IOException { String wkt = builder.toWKT(); if (generateMalformed) { @@ -87,12 +90,12 @@ private static XContentBuilder toWKTContent(ShapeBuilder builder, boolean return XContentFactory.jsonBuilder().value(wkt); } - private void assertExpected(Object expected, ShapeBuilder builder, boolean useJTS) throws IOException { + private void assertExpected(Object expected, ShapeBuilder builder, boolean useJTS) throws IOException { XContentBuilder xContentBuilder = toWKTContent(builder, false); assertGeometryEquals(expected, xContentBuilder, useJTS); } - private void assertMalformed(ShapeBuilder builder) throws IOException { + private void assertMalformed(ShapeBuilder builder) throws IOException { XContentBuilder xContentBuilder = toWKTContent(builder, true); assertValidException(xContentBuilder, ElasticsearchParseException.class); } @@ -103,7 +106,7 @@ public void testParsePoint() throws IOException { Coordinate c = new Coordinate(p.lon(), p.lat()); Point expected = GEOMETRY_FACTORY.createPoint(c); assertExpected(new JtsPoint(expected, SPATIAL_CONTEXT), new PointBuilder().coordinate(c), true); - assertExpected(new GeoPoint(p.lat(), p.lon()), new PointBuilder().coordinate(c), false); + assertExpected(new org.elasticsearch.geo.geometry.Point(p.lat(), p.lon()), new PointBuilder().coordinate(c), false); assertMalformed(new PointBuilder().coordinate(c)); } @@ -123,13 +126,12 @@ public void testParseMultiPoint() throws IOException { ShapeCollection expected = shapeCollection(shapes); assertExpected(expected, new MultiPointBuilder(coordinates), true); - double[][] luceneShapes = new double[numPoints][2]; + List points = new ArrayList<>(numPoints); for (int i = 0; i < numPoints; ++i) { Coordinate c = coordinates.get(i); - luceneShapes[i][0] = c.x; - luceneShapes[i][1] = c.y; + points.add(new org.elasticsearch.geo.geometry.Point(c.y, c.x)); } - assertExpected(luceneShapes, new MultiPointBuilder(coordinates), false); + assertExpected(new MultiPoint(points), new MultiPointBuilder(coordinates), false); assertMalformed(new MultiPointBuilder(coordinates)); } @@ -175,13 +177,13 @@ public void testParseMultiLineString() throws IOException { lineStrings.toArray(new LineString[lineStrings.size()])); assertExpected(jtsGeom(expected), builder, true); - Line[] lines = new Line[lineStrings.size()]; + List lines = new ArrayList<>(lineStrings.size()); for (int j = 0; j < lineStrings.size(); ++j) { Coordinate[] c = lineStrings.get(j).getCoordinates(); - lines[j] = new Line(Arrays.stream(c).mapToDouble(i->i.y).toArray(), - Arrays.stream(c).mapToDouble(i->i.x).toArray()); + lines.add(new Line(Arrays.stream(c).mapToDouble(i->i.y).toArray(), + Arrays.stream(c).mapToDouble(i->i.x).toArray())); } - assertExpected(lines, builder, false); + assertExpected(new MultiLine(lines), builder, false); assertMalformed(builder); } @@ -245,12 +247,12 @@ public void testParsePolygonWithHole() throws IOException { Polygon expected = GEOMETRY_FACTORY.createPolygon(shell, holes); assertExpected(jtsGeom(expected), polygonWithHole, true); - org.apache.lucene.geo.Polygon hole = - new org.apache.lucene.geo.Polygon( + org.elasticsearch.geo.geometry.LinearRing hole = + new org.elasticsearch.geo.geometry.LinearRing( new double[] {0.8d, 0.8d, 0.2d, 0.2d, 0.8d}, new double[] {100.2d, 100.8d, 100.8d, 100.2d, 100.2d}); - org.apache.lucene.geo.Polygon p = - new org.apache.lucene.geo.Polygon( - new double[] {0d, 1d, 1d, 0d, 0d}, new double[] {101d, 101d, 100d, 100d, 101d}, hole); + org.elasticsearch.geo.geometry.Polygon p = + new org.elasticsearch.geo.geometry.Polygon(new org.elasticsearch.geo.geometry.LinearRing( + new double[] {0d, 1d, 1d, 0d, 0d}, new double[] {101d, 101d, 100d, 100d, 101d}), Collections.singletonList(hole)); assertExpected(p, polygonWithHole, false); assertMalformed(polygonWithHole); } @@ -357,7 +359,7 @@ public void testParsePolyWithStoredZ() throws IOException { final LegacyGeoShapeFieldMapper mapperBuilder = (LegacyGeoShapeFieldMapper)(new LegacyGeoShapeFieldMapper.Builder("test").ignoreZValue(true).build(mockBuilderContext)); - ShapeBuilder shapeBuilder = ShapeParser.parse(parser, mapperBuilder); + ShapeBuilder shapeBuilder = ShapeParser.parse(parser, mapperBuilder); assertEquals(shapeBuilder.numDimensions(), 3); } @@ -383,7 +385,7 @@ public void testParseOpenPolygon() throws IOException { final LegacyGeoShapeFieldMapper coercingMapperBuilder = (LegacyGeoShapeFieldMapper)(new LegacyGeoShapeFieldMapper.Builder("test").coerce(true).build(mockBuilderContext)); - ShapeBuilder shapeBuilder = ShapeParser.parse(parser, coercingMapperBuilder); + ShapeBuilder shapeBuilder = ShapeParser.parse(parser, coercingMapperBuilder); assertNotNull(shapeBuilder); assertEquals("polygon ((100.0 5.0, 100.0 10.0, 90.0 10.0, 90.0 5.0, 100.0 5.0))", shapeBuilder.toWKT()); } @@ -418,7 +420,7 @@ public void testParseEnvelope() throws IOException { Rectangle expected = SPATIAL_CONTEXT.makeRectangle(r.minLon, r.maxLon, r.minLat, r.maxLat); assertExpected(expected, builder, true); - assertExpected(r, builder, false); + assertExpected(new org.elasticsearch.geo.geometry.Rectangle(r.minLat, r.maxLat, r.minLon, r.maxLon), builder, false); assertMalformed(builder); } @@ -436,12 +438,12 @@ public void testParseGeometryCollection() throws IOException { if (randomBoolean()) { assertEquals(shapeCollection(expected).isEmpty(), builder.buildS4J().isEmpty()); } else { - assertEquals(shapeCollection(expected).isEmpty(), ((Object[])builder.buildLucene()).length == 0); + assertEquals(shapeCollection(expected).isEmpty(), builder.buildGeometry().size() == 0); } } else { GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); assertExpected(gcb.buildS4J(), gcb, true); - assertExpected(gcb.buildLucene(), gcb, false); + assertExpected(gcb.buildGeometry(), gcb, false); } } diff --git a/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java b/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java index 8b8bd2285ca3c..32f1b333c4ead 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java @@ -52,7 +52,7 @@ public void testNewPoint() { Point point = pb.buildS4J(); assertEquals(-100D, point.getX(), 0.0d); assertEquals(45D, point.getY(), 0.0d); - GeoPoint geoPoint = pb.buildLucene(); + org.elasticsearch.geo.geometry.Point geoPoint = pb.buildGeometry(); assertEquals(-100D, geoPoint.getLon(), 0.0d); assertEquals(45D, geoPoint.getLat(), 0.0d); } @@ -65,11 +65,11 @@ public void testNewRectangle() { assertEquals(45D, rectangle.getMaxX(), 0.0d); assertEquals(30D, rectangle.getMaxY(), 0.0d); - org.apache.lucene.geo.Rectangle luceneRectangle = eb.buildLucene(); - assertEquals(-45D, luceneRectangle.minLon, 0.0d); - assertEquals(-30D, luceneRectangle.minLat, 0.0d); - assertEquals(45D, luceneRectangle.maxLon, 0.0d); - assertEquals(30D, luceneRectangle.maxLat, 0.0d); + org.elasticsearch.geo.geometry.Rectangle luceneRectangle = eb.buildGeometry(); + assertEquals(-45D, luceneRectangle.getMinLon(), 0.0d); + assertEquals(-30D, luceneRectangle.getMinLat(), 0.0d); + assertEquals(45D, luceneRectangle.getMaxLon(), 0.0d); + assertEquals(30D, luceneRectangle.getMaxLat(), 0.0d); } public void testNewPolygon() { @@ -87,15 +87,15 @@ public void testNewPolygon() { assertEquals(exterior.getCoordinateN(2), new Coordinate(45, -30)); assertEquals(exterior.getCoordinateN(3), new Coordinate(-45, -30)); - org.apache.lucene.geo.Polygon lucenePoly = (org.apache.lucene.geo.Polygon)(pb.toPolygonLucene()); - assertEquals(lucenePoly.getPolyLat(0), 30, 0d); - assertEquals(lucenePoly.getPolyLon(0), -45, 0d); - assertEquals(lucenePoly.getPolyLat(1), 30, 0d); - assertEquals(lucenePoly.getPolyLon(1), 45, 0d); - assertEquals(lucenePoly.getPolyLat(2), -30, 0d); - assertEquals(lucenePoly.getPolyLon(2), 45, 0d); - assertEquals(lucenePoly.getPolyLat(3), -30, 0d); - assertEquals(lucenePoly.getPolyLon(3), -45, 0d); + org.elasticsearch.geo.geometry.LinearRing polygon = pb.toPolygonGeometry().getPolygon(); + assertEquals(polygon.getLat(0), 30, 0d); + assertEquals(polygon.getLon(0), -45, 0d); + assertEquals(polygon.getLat(1), 30, 0d); + assertEquals(polygon.getLon(1), 45, 0d); + assertEquals(polygon.getLat(2), -30, 0d); + assertEquals(polygon.getLon(2), 45, 0d); + assertEquals(polygon.getLat(3), -30, 0d); + assertEquals(polygon.getLon(3), -45, 0d); } public void testNewPolygon_coordinate() { @@ -113,15 +113,15 @@ public void testNewPolygon_coordinate() { assertEquals(exterior.getCoordinateN(2), new Coordinate(45, -30)); assertEquals(exterior.getCoordinateN(3), new Coordinate(-45, -30)); - org.apache.lucene.geo.Polygon lucenePoly = (org.apache.lucene.geo.Polygon)(pb.toPolygonLucene()); - assertEquals(lucenePoly.getPolyLat(0), 30, 0d); - assertEquals(lucenePoly.getPolyLon(0), -45, 0d); - assertEquals(lucenePoly.getPolyLat(1), 30, 0d); - assertEquals(lucenePoly.getPolyLon(1), 45, 0d); - assertEquals(lucenePoly.getPolyLat(2), -30, 0d); - assertEquals(lucenePoly.getPolyLon(2), 45, 0d); - assertEquals(lucenePoly.getPolyLat(3), -30, 0d); - assertEquals(lucenePoly.getPolyLon(3), -45, 0d); + org.elasticsearch.geo.geometry.LinearRing polygon = pb.toPolygonGeometry().getPolygon(); + assertEquals(polygon.getLat(0), 30, 0d); + assertEquals(polygon.getLon(0), -45, 0d); + assertEquals(polygon.getLat(1), 30, 0d); + assertEquals(polygon.getLon(1), 45, 0d); + assertEquals(polygon.getLat(2), -30, 0d); + assertEquals(polygon.getLon(2), 45, 0d); + assertEquals(polygon.getLat(3), -30, 0d); + assertEquals(polygon.getLon(3), -45, 0d); } public void testNewPolygon_coordinates() { @@ -137,15 +137,15 @@ public void testNewPolygon_coordinates() { assertEquals(exterior.getCoordinateN(2), new Coordinate(45, -30)); assertEquals(exterior.getCoordinateN(3), new Coordinate(-45, -30)); - org.apache.lucene.geo.Polygon lucenePoly = (org.apache.lucene.geo.Polygon)(pb.toPolygonLucene()); - assertEquals(lucenePoly.getPolyLat(0), 30, 0d); - assertEquals(lucenePoly.getPolyLon(0), -45, 0d); - assertEquals(lucenePoly.getPolyLat(1), 30, 0d); - assertEquals(lucenePoly.getPolyLon(1), 45, 0d); - assertEquals(lucenePoly.getPolyLat(2), -30, 0d); - assertEquals(lucenePoly.getPolyLon(2), 45, 0d); - assertEquals(lucenePoly.getPolyLat(3), -30, 0d); - assertEquals(lucenePoly.getPolyLon(3), -45, 0d); + org.elasticsearch.geo.geometry.LinearRing polygon = pb.toPolygonGeometry().getPolygon(); + assertEquals(polygon.getLat(0), 30, 0d); + assertEquals(polygon.getLon(0), -45, 0d); + assertEquals(polygon.getLat(1), 30, 0d); + assertEquals(polygon.getLon(1), 45, 0d); + assertEquals(polygon.getLat(2), -30, 0d); + assertEquals(polygon.getLon(2), 45, 0d); + assertEquals(polygon.getLat(3), -30, 0d); + assertEquals(polygon.getLon(3), -45, 0d); } public void testLineStringBuilder() { @@ -161,7 +161,7 @@ public void testLineStringBuilder() { .coordinate(-110.0, 55.0)); lsb.buildS4J(); - lsb.buildLucene(); + lsb.buildGeometry(); // Building a linestring that needs to be wrapped lsb = new LineStringBuilder(new CoordinatesBuilder() @@ -175,7 +175,7 @@ public void testLineStringBuilder() { .coordinate(130.0, 60.0)); lsb.buildS4J(); - lsb.buildLucene(); + lsb.buildGeometry(); // Building a lineString on the dateline lsb = new LineStringBuilder(new CoordinatesBuilder() @@ -185,7 +185,7 @@ public void testLineStringBuilder() { .coordinate(-180.0, -80.0)); lsb.buildS4J(); - lsb.buildLucene(); + lsb.buildGeometry(); // Building a lineString on the dateline lsb = new LineStringBuilder(new CoordinatesBuilder() @@ -195,7 +195,7 @@ public void testLineStringBuilder() { .coordinate(180.0, -80.0)); lsb.buildS4J(); - lsb.buildLucene(); + lsb.buildGeometry(); } public void testMultiLineString() { @@ -215,7 +215,7 @@ public void testMultiLineString() { ) ); mlsb.buildS4J(); - mlsb.buildLucene(); + mlsb.buildGeometry(); // LineString that needs to be wrapped new MultiLineStringBuilder() @@ -235,7 +235,7 @@ public void testMultiLineString() { ); mlsb.buildS4J(); - mlsb.buildLucene(); + mlsb.buildGeometry(); } public void testPolygonSelfIntersection() { @@ -283,7 +283,7 @@ public void testPolygonWrapping() { .close()); assertMultiPolygon(pb.buildS4J(), true); - assertMultiPolygon(pb.buildLucene(), false); + assertMultiPolygon(pb.buildGeometry(), false); } public void testLineStringWrapping() { @@ -295,7 +295,7 @@ public void testLineStringWrapping() { .close()); assertMultiLineString(lsb.buildS4J(), true); - assertMultiLineString(lsb.buildLucene(), false); + assertMultiLineString(lsb.buildGeometry(), false); } public void testDatelineOGC() { @@ -339,7 +339,7 @@ public void testDatelineOGC() { )); assertMultiPolygon(builder.close().buildS4J(), true); - assertMultiPolygon(builder.close().buildLucene(), false); + assertMultiPolygon(builder.close().buildGeometry(), false); } public void testDateline() { @@ -383,7 +383,7 @@ public void testDateline() { )); assertMultiPolygon(builder.close().buildS4J(), true); - assertMultiPolygon(builder.close().buildLucene(), false); + assertMultiPolygon(builder.close().buildGeometry(), false); } public void testComplexShapeWithHole() { @@ -458,7 +458,7 @@ public void testComplexShapeWithHole() { ) ); assertPolygon(builder.close().buildS4J(), true); - assertPolygon(builder.close().buildLucene(), false); + assertPolygon(builder.close().buildGeometry(), false); } public void testShapeWithHoleAtEdgeEndPoints() { @@ -480,7 +480,7 @@ public void testShapeWithHoleAtEdgeEndPoints() { .coordinate(4, 1) )); assertPolygon(builder.close().buildS4J(), true); - assertPolygon(builder.close().buildLucene(), false); + assertPolygon(builder.close().buildGeometry(), false); } public void testShapeWithPointOnDateline() { @@ -491,7 +491,7 @@ public void testShapeWithPointOnDateline() { .coordinate(180, 0) ); assertPolygon(builder.close().buildS4J(), true); - assertPolygon(builder.close().buildLucene(), false); + assertPolygon(builder.close().buildGeometry(), false); } public void testShapeWithEdgeAlongDateline() { @@ -504,7 +504,7 @@ public void testShapeWithEdgeAlongDateline() { ); assertPolygon(builder.close().buildS4J(), true); - assertPolygon(builder.close().buildLucene(), false); + assertPolygon(builder.close().buildGeometry(), false); // test case 2: test the negative side of the dateline builder = new PolygonBuilder(new CoordinatesBuilder() @@ -515,7 +515,7 @@ public void testShapeWithEdgeAlongDateline() { ); assertPolygon(builder.close().buildS4J(), true); - assertPolygon(builder.close().buildLucene(), false); + assertPolygon(builder.close().buildGeometry(), false); } public void testShapeWithBoundaryHoles() { @@ -537,7 +537,7 @@ public void testShapeWithBoundaryHoles() { )); assertMultiPolygon(builder.close().buildS4J(), true); - assertMultiPolygon(builder.close().buildLucene(), false); + assertMultiPolygon(builder.close().buildGeometry(), false); // test case 2: test the negative side of the dateline builder = new PolygonBuilder( @@ -560,7 +560,7 @@ public void testShapeWithBoundaryHoles() { )); assertMultiPolygon(builder.close().buildS4J(), true); - assertMultiPolygon(builder.close().buildLucene(), false); + assertMultiPolygon(builder.close().buildGeometry(), false); } public void testShapeWithTangentialHole() { @@ -582,7 +582,7 @@ public void testShapeWithTangentialHole() { )); assertMultiPolygon(builder.close().buildS4J(), true); - assertMultiPolygon(builder.close().buildLucene(), false); + assertMultiPolygon(builder.close().buildGeometry(), false); } public void testShapeWithInvalidTangentialHole() { @@ -606,7 +606,7 @@ public void testShapeWithInvalidTangentialHole() { e = expectThrows(InvalidShapeException.class, () -> builder.close().buildS4J()); assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); - e = expectThrows(InvalidShapeException.class, () -> builder.close().buildLucene()); + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildGeometry()); assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); } @@ -634,7 +634,7 @@ public void testBoundaryShapeWithTangentialHole() { .coordinate(172, 0) )); assertMultiPolygon(builder.close().buildS4J(), true); - assertMultiPolygon(builder.close().buildLucene(), false); + assertMultiPolygon(builder.close().buildGeometry(), false); } public void testBoundaryShapeWithInvalidTangentialHole() { @@ -657,7 +657,7 @@ public void testBoundaryShapeWithInvalidTangentialHole() { Exception e; e = expectThrows(InvalidShapeException.class, () -> builder.close().buildS4J()); assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); - e = expectThrows(InvalidShapeException.class, () -> builder.close().buildLucene()); + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildGeometry()); assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); } @@ -673,7 +673,7 @@ public void testBoundaryShape() { ); assertPolygon(builder.close().buildS4J(), true); - assertPolygon(builder.close().buildLucene(), false); + assertPolygon(builder.close().buildGeometry(), false); } public void testShapeWithAlternateOrientation() { @@ -686,7 +686,7 @@ public void testShapeWithAlternateOrientation() { ); assertPolygon(builder.close().buildS4J(), true); - assertPolygon(builder.close().buildLucene(), false); + assertPolygon(builder.close().buildGeometry(), false); // cw: geo core will convert to ccw across the dateline builder = new PolygonBuilder(new CoordinatesBuilder() @@ -697,7 +697,7 @@ public void testShapeWithAlternateOrientation() { ); assertMultiPolygon(builder.close().buildS4J(), true); - assertMultiPolygon(builder.close().buildLucene(), false); + assertMultiPolygon(builder.close().buildGeometry(), false); } public void testInvalidShapeWithConsecutiveDuplicatePoints() { @@ -711,7 +711,7 @@ public void testInvalidShapeWithConsecutiveDuplicatePoints() { Exception e = expectThrows(InvalidShapeException.class, () -> builder.close().buildS4J()); assertThat(e.getMessage(), containsString("duplicate consecutive coordinates at: (")); - e = expectThrows(InvalidShapeException.class, () -> builder.close().buildLucene()); + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildGeometry()); assertThat(e.getMessage(), containsString("duplicate consecutive coordinates at: (")); } diff --git a/server/src/test/java/org/elasticsearch/common/geo/builders/AbstractShapeBuilderTestCase.java b/server/src/test/java/org/elasticsearch/common/geo/builders/AbstractShapeBuilderTestCase.java index 20e159ded41e4..ffee74966530b 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/builders/AbstractShapeBuilderTestCase.java +++ b/server/src/test/java/org/elasticsearch/common/geo/builders/AbstractShapeBuilderTestCase.java @@ -37,7 +37,7 @@ import static org.elasticsearch.test.EqualsHashCodeTestUtils.checkEqualsAndHashCode; -public abstract class AbstractShapeBuilderTestCase> extends ESTestCase { +public abstract class AbstractShapeBuilderTestCase> extends ESTestCase { private static final int NUMBER_OF_TESTBUILDERS = 20; private static NamedWriteableRegistry namedWriteableRegistry; @@ -81,7 +81,7 @@ public void testFromXContent() throws IOException { XContentBuilder shuffled = shuffleXContent(builder); try (XContentParser shapeContentParser = createParser(shuffled)) { shapeContentParser.nextToken(); - ShapeBuilder parsedShape = ShapeParser.parse(shapeContentParser); + ShapeBuilder parsedShape = ShapeParser.parse(shapeContentParser); assertNotSame(testShape, parsedShape); assertEquals(testShape, parsedShape); assertEquals(testShape.hashCode(), parsedShape.hashCode()); diff --git a/server/src/test/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilderTests.java b/server/src/test/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilderTests.java index b44ba6769d79f..55ca2d907f6ff 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilderTests.java @@ -69,7 +69,7 @@ static GeometryCollectionBuilder mutate(GeometryCollectionBuilder original) thro GeometryCollectionBuilder mutation = copyShape(original); if (mutation.shapes.size() > 0) { int shapePosition = randomIntBetween(0, mutation.shapes.size() - 1); - ShapeBuilder shapeToChange = mutation.shapes.get(shapePosition); + ShapeBuilder shapeToChange = mutation.shapes.get(shapePosition); switch (shapeToChange.type()) { case POINT: shapeToChange = PointBuilderTests.mutate((PointBuilder) shapeToChange); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java b/server/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java index 2fb4cfeb81dbf..ea3125accd059 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java @@ -187,7 +187,7 @@ public void parse(ParseContext context) throws IOException { // Let's add a Dummy Shape PointBuilder pb = new PointBuilder(-100, 45); if (shapeMapper instanceof GeoShapeFieldMapper) { - shapeMapper.parse(context.createExternalValueContext(pb.buildLucene())); + shapeMapper.parse(context.createExternalValueContext(pb.buildGeometry())); } else { shapeMapper.parse(context.createExternalValueContext(pb.buildS4J())); } diff --git a/server/src/test/java/org/elasticsearch/index/query/GeoPolygonQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/GeoPolygonQueryBuilderTests.java index 83543c24f9bc1..92f017a7bdb7d 100644 --- a/server/src/test/java/org/elasticsearch/index/query/GeoPolygonQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/GeoPolygonQueryBuilderTests.java @@ -63,7 +63,7 @@ protected void doAssertLuceneQuery(GeoPolygonQueryBuilder queryBuilder, Query qu } private static List randomPolygon() { - ShapeBuilder shapeBuilder = null; + ShapeBuilder shapeBuilder = null; // This is a temporary fix because sometimes the RandomShapeGenerator // returns null. This is if there is an error generating the polygon. So // in this case keep trying until we successfully generate one diff --git a/server/src/test/java/org/elasticsearch/index/query/GeoShapeQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/GeoShapeQueryBuilderTests.java index 22f9705dcc5f9..4851387b1a497 100644 --- a/server/src/test/java/org/elasticsearch/index/query/GeoShapeQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/GeoShapeQueryBuilderTests.java @@ -63,7 +63,7 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase indexedShapeToReturn; + protected static ShapeBuilder indexedShapeToReturn; protected String fieldName() { return GEO_SHAPE_FIELD_NAME; @@ -88,7 +88,7 @@ protected GeoShapeQueryBuilder doCreateTestQueryBuilder(boolean indexedShape) { // LatLonShape does not support MultiPoint queries RandomShapeGenerator.ShapeType shapeType = randomFrom(ShapeType.POINT, ShapeType.LINESTRING, ShapeType.MULTILINESTRING, ShapeType.POLYGON); - ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); + ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); GeoShapeQueryBuilder builder; clearShapeFields(); if (indexedShape == false) { @@ -174,7 +174,7 @@ protected void doAssertLuceneQuery(GeoShapeQueryBuilder queryBuilder, Query quer } public void testNoFieldName() throws Exception { - ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null); + ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> new GeoShapeQueryBuilder(null, shape)); assertEquals("fieldName is required", e.getMessage()); } @@ -190,7 +190,7 @@ public void testNoIndexedShape() throws IOException { } public void testNoRelation() throws IOException { - ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null); + ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null); GeoShapeQueryBuilder builder = new GeoShapeQueryBuilder(fieldName(), shape); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> builder.relation(null)); assertEquals("No Shape Relation defined", e.getMessage()); @@ -255,7 +255,7 @@ public void testMultipleRewrite() throws IOException { public void testIgnoreUnmapped() throws IOException { ShapeType shapeType = ShapeType.randomType(random()); - ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); + ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); final GeoShapeQueryBuilder queryBuilder = new GeoShapeQueryBuilder("unmapped", shape); queryBuilder.ignoreUnmapped(true); Query query = queryBuilder.toQuery(createShardContext()); @@ -270,7 +270,7 @@ public void testIgnoreUnmapped() throws IOException { public void testWrongFieldType() throws IOException { ShapeType shapeType = ShapeType.randomType(random()); - ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); + ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); final GeoShapeQueryBuilder queryBuilder = new GeoShapeQueryBuilder(STRING_FIELD_NAME, shape); QueryShardException e = expectThrows(QueryShardException.class, () -> queryBuilder.toQuery(createShardContext())); assertThat(e.getMessage(), containsString("Field [mapped_string] is not of type [geo_shape] but of type [text]")); diff --git a/server/src/test/java/org/elasticsearch/index/query/LegacyGeoShapeFieldQueryTests.java b/server/src/test/java/org/elasticsearch/index/query/LegacyGeoShapeFieldQueryTests.java index 2dcf3245dfe15..dc2a4a0e3fffe 100644 --- a/server/src/test/java/org/elasticsearch/index/query/LegacyGeoShapeFieldQueryTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/LegacyGeoShapeFieldQueryTests.java @@ -51,7 +51,7 @@ protected Settings createTestIndexSettings() { @Override protected GeoShapeQueryBuilder doCreateTestQueryBuilder(boolean indexedShape) { ShapeType shapeType = ShapeType.randomType(random()); - ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); + ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType); GeoShapeQueryBuilder builder; clearShapeFields(); if (indexedShape == false) { @@ -93,7 +93,7 @@ protected GeoShapeQueryBuilder doCreateTestQueryBuilder(boolean indexedShape) { } public void testInvalidRelation() throws IOException { - ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null); + ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(random(), null); GeoShapeQueryBuilder builder = new GeoShapeQueryBuilder(GEO_SHAPE_FIELD_NAME, shape); builder.strategy(SpatialStrategy.TERM); expectThrows(IllegalArgumentException.class, () -> builder.relation(randomFrom(ShapeRelation.DISJOINT, ShapeRelation.WITHIN))); diff --git a/server/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchGeoAssertions.java b/server/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchGeoAssertions.java index daa04442535eb..a5b64597181cf 100644 --- a/server/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchGeoAssertions.java +++ b/server/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchGeoAssertions.java @@ -24,6 +24,7 @@ import org.elasticsearch.common.geo.parsers.ShapeParser; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.geo.geometry.MultiLine; import org.hamcrest.Matcher; import org.junit.Assert; import org.locationtech.jts.geom.Coordinate; @@ -221,7 +222,9 @@ public static void assertEquals(Object s1, Object s2) { || (s1 instanceof GeoPoint && s2 instanceof GeoPoint)) { Assert.assertEquals(s1, s2); } else if (s1 instanceof Object[] && s2 instanceof Object[]) { - Assert.assertArrayEquals((Object[])s1, (Object[])s2); + Assert.assertArrayEquals((Object[]) s1, (Object[]) s2); + } else if (s1 instanceof org.elasticsearch.geo.geometry.Geometry && s2 instanceof org.elasticsearch.geo.geometry.Geometry) { + Assert.assertEquals(s1, s2); } else { //We want to know the type of the shape because we test shape equality in a special way... //... in particular we test that one ring is equivalent to another ring even if the points are rotated or reversed. @@ -242,7 +245,7 @@ public static void assertMultiPolygon(Object shape, boolean useJTS) { unwrapJTS(shape) instanceof MultiPolygon); } else { assertTrue("expected Polygon[] but found " + shape.getClass().getName(), - shape instanceof org.apache.lucene.geo.Polygon[]); + shape instanceof org.elasticsearch.geo.geometry.MultiPolygon); } } @@ -252,7 +255,7 @@ public static void assertPolygon(Object shape, boolean useJTS) { + unwrapJTS(shape).getClass().getName(), unwrapJTS(shape) instanceof Polygon); } else { assertTrue("expected Polygon but found " + shape.getClass().getName(), - shape instanceof org.apache.lucene.geo.Polygon); + shape instanceof org.elasticsearch.geo.geometry.Polygon); } } @@ -262,7 +265,7 @@ public static void assertLineString(Object shape, boolean useJTS) { + unwrapJTS(shape).getClass().getName(), unwrapJTS(shape) instanceof LineString); } else { assertTrue("expected Line but found " + shape.getClass().getName(), - shape instanceof org.apache.lucene.geo.Line); + shape instanceof org.elasticsearch.geo.geometry.Line); } } @@ -272,7 +275,7 @@ public static void assertMultiLineString(Object shape, boolean useJTS) { + unwrapJTS(shape).getClass().getName(), unwrapJTS(shape) instanceof MultiLineString); } else { assertTrue("expected Line[] but found " + shape.getClass().getName(), - shape instanceof org.apache.lucene.geo.Line[]); + shape instanceof MultiLine); } }