Geo: Makes coordinate validator in libs/geo plugable (#43657)

Moves coordinate validation from Geometry constructors into
parser.

Relates #43644
This commit is contained in:
Igor Motov 2019-06-27 13:34:33 -04:00
parent ce8771feb7
commit 3607876a71
31 changed files with 472 additions and 216 deletions

View File

@ -49,8 +49,6 @@ public class Circle implements Geometry {
if (radiusMeters < 0 ) { if (radiusMeters < 0 ) {
throw new IllegalArgumentException("Circle radius [" + radiusMeters + "] cannot be negative"); throw new IllegalArgumentException("Circle radius [" + radiusMeters + "] cannot be negative");
} }
GeometryUtils.checkLatitude(lat);
GeometryUtils.checkLongitude(lon);
} }
@Override @Override

View File

@ -1,78 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.geo.geometry;
/**
* Geometry-related utility methods
*/
public final class GeometryUtils {
/**
* Minimum longitude value.
*/
static final double MIN_LON_INCL = -180.0D;
/**
* Maximum longitude value.
*/
static final double MAX_LON_INCL = 180.0D;
/**
* Minimum latitude value.
*/
static final double MIN_LAT_INCL = -90.0D;
/**
* Maximum latitude value.
*/
static final double MAX_LAT_INCL = 90.0D;
// No instance:
private GeometryUtils() {
}
/**
* validates latitude value is within standard +/-90 coordinate bounds
*/
static void checkLatitude(double latitude) {
if (Double.isNaN(latitude) || latitude < MIN_LAT_INCL || latitude > MAX_LAT_INCL) {
throw new IllegalArgumentException(
"invalid latitude " + latitude + "; must be between " + MIN_LAT_INCL + " and " + MAX_LAT_INCL);
}
}
/**
* validates longitude value is within standard +/-180 coordinate bounds
*/
static void checkLongitude(double longitude) {
if (Double.isNaN(longitude) || longitude < MIN_LON_INCL || longitude > MAX_LON_INCL) {
throw new IllegalArgumentException(
"invalid longitude " + longitude + "; must be between " + MIN_LON_INCL + " and " + MAX_LON_INCL);
}
}
public static double checkAltitude(final boolean ignoreZValue, double zValue) {
if (ignoreZValue == false) {
throw new IllegalArgumentException("found Z value [" + zValue + "] but [ignore_z_value] "
+ "parameter is [" + ignoreZValue + "]");
}
return zValue;
}
}

View File

@ -59,10 +59,6 @@ public class Line implements Geometry {
if (alts != null && alts.length != lats.length) { if (alts != null && alts.length != lats.length) {
throw new IllegalArgumentException("alts and lats must be equal length"); throw new IllegalArgumentException("alts and lats must be equal length");
} }
for (int i = 0; i < lats.length; i++) {
GeometryUtils.checkLatitude(lats[i]);
GeometryUtils.checkLongitude(lons[i]);
}
} }
public int length() { public int length() {

View File

@ -42,8 +42,6 @@ public class Point implements Geometry {
} }
public Point(double lat, double lon, double alt) { public Point(double lat, double lon, double alt) {
GeometryUtils.checkLatitude(lat);
GeometryUtils.checkLongitude(lon);
this.lat = lat; this.lat = lat;
this.lon = lon; this.lon = lon;
this.alt = alt; this.alt = alt;

View File

@ -71,10 +71,6 @@ public class Rectangle implements Geometry {
* Constructs a bounding box by first validating the provided latitude and longitude coordinates * Constructs a bounding box by first validating the provided latitude and longitude coordinates
*/ */
public Rectangle(double minLat, double maxLat, double minLon, double maxLon, double minAlt, double maxAlt) { public Rectangle(double minLat, double maxLat, double minLon, double maxLon, double minAlt, double maxAlt) {
GeometryUtils.checkLatitude(minLat);
GeometryUtils.checkLatitude(maxLat);
GeometryUtils.checkLongitude(minLon);
GeometryUtils.checkLongitude(maxLon);
this.minLon = minLon; this.minLon = minLon;
this.maxLon = maxLon; this.maxLon = maxLon;
this.minLat = minLat; this.minLat = minLat;
@ -90,17 +86,6 @@ public class Rectangle implements Geometry {
} }
} }
public double getWidth() {
if (crossesDateline()) {
return GeometryUtils.MAX_LON_INCL - minLon + maxLon - GeometryUtils.MIN_LON_INCL;
}
return maxLon - minLon;
}
public double getHeight() {
return maxLat - minLat;
}
public double getMinLat() { public double getMinLat() {
return minLat; return minLat;
} }
@ -156,21 +141,6 @@ public class Rectangle implements Geometry {
return b.toString(); return b.toString();
} }
/**
* Returns true if this bounding box crosses the dateline
*/
public boolean crossesDateline() {
return maxLon < minLon;
}
/** returns true if rectangle (defined by minLat, maxLat, minLon, maxLon) contains the lat lon point */
public boolean containsPoint(final double lat, final double lon) {
if (lat >= minLat && lat <= maxLat) {
return crossesDateline() ? lon >= minLon || lon <= maxLon : lon >= minLon && lon <= maxLon;
}
return false;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@ -0,0 +1,178 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.geo.utils;
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.Line;
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 org.elasticsearch.geo.geometry.Polygon;
import org.elasticsearch.geo.geometry.Rectangle;
/**
* Validator that checks that lats are between -90 and +90 and lons are between -180 and +180 and altitude is present only if
* ignoreZValue is set to true
*/
public class GeographyValidator implements GeometryValidator {
/**
* Minimum longitude value.
*/
private static final double MIN_LON_INCL = -180.0D;
/**
* Maximum longitude value.
*/
private static final double MAX_LON_INCL = 180.0D;
/**
* Minimum latitude value.
*/
private static final double MIN_LAT_INCL = -90.0D;
/**
* Maximum latitude value.
*/
private static final double MAX_LAT_INCL = 90.0D;
private final boolean ignoreZValue;
public GeographyValidator(boolean ignoreZValue) {
this.ignoreZValue = ignoreZValue;
}
/**
* validates latitude value is within standard +/-90 coordinate bounds
*/
protected void checkLatitude(double latitude) {
if (Double.isNaN(latitude) || latitude < MIN_LAT_INCL || latitude > MAX_LAT_INCL) {
throw new IllegalArgumentException(
"invalid latitude " + latitude + "; must be between " + MIN_LAT_INCL + " and " + MAX_LAT_INCL);
}
}
/**
* validates longitude value is within standard +/-180 coordinate bounds
*/
protected void checkLongitude(double longitude) {
if (Double.isNaN(longitude) || longitude < MIN_LON_INCL || longitude > MAX_LON_INCL) {
throw new IllegalArgumentException(
"invalid longitude " + longitude + "; must be between " + MIN_LON_INCL + " and " + MAX_LON_INCL);
}
}
protected void checkAltitude(double zValue) {
if (ignoreZValue == false && Double.isNaN(zValue) == false) {
throw new IllegalArgumentException("found Z value [" + zValue + "] but [ignore_z_value] "
+ "parameter is [" + ignoreZValue + "]");
}
}
@Override
public void validate(Geometry geometry) {
geometry.visit(new GeometryVisitor<Void, RuntimeException>() {
@Override
public Void visit(Circle circle) throws RuntimeException {
checkLatitude(circle.getLat());
checkLongitude(circle.getLon());
checkAltitude(circle.getAlt());
return null;
}
@Override
public Void visit(GeometryCollection<?> collection) throws RuntimeException {
for (Geometry g : collection) {
g.visit(this);
}
return null;
}
@Override
public Void visit(Line line) throws RuntimeException {
for (int i = 0; i < line.length(); i++) {
checkLatitude(line.getLat(i));
checkLongitude(line.getLon(i));
checkAltitude(line.getAlt(i));
}
return null;
}
@Override
public Void visit(LinearRing ring) throws RuntimeException {
for (int i = 0; i < ring.length(); i++) {
checkLatitude(ring.getLat(i));
checkLongitude(ring.getLon(i));
checkAltitude(ring.getAlt(i));
}
return null;
}
@Override
public Void visit(MultiLine multiLine) throws RuntimeException {
return visit((GeometryCollection<?>) multiLine);
}
@Override
public Void visit(MultiPoint multiPoint) throws RuntimeException {
return visit((GeometryCollection<?>) multiPoint);
}
@Override
public Void visit(MultiPolygon multiPolygon) throws RuntimeException {
return visit((GeometryCollection<?>) multiPolygon);
}
@Override
public Void visit(Point point) throws RuntimeException {
checkLatitude(point.getLat());
checkLongitude(point.getLon());
checkAltitude(point.getAlt());
return null;
}
@Override
public Void visit(Polygon polygon) throws RuntimeException {
polygon.getPolygon().visit(this);
for (int i = 0; i < polygon.getNumberOfHoles(); i++) {
polygon.getHole(i).visit(this);
}
return null;
}
@Override
public Void visit(Rectangle rectangle) throws RuntimeException {
checkLatitude(rectangle.getMinLat());
checkLatitude(rectangle.getMaxLat());
checkLongitude(rectangle.getMinLon());
checkLongitude(rectangle.getMaxLon());
checkAltitude(rectangle.getMinAlt());
checkAltitude(rectangle.getMaxAlt());
return null;
}
});
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.geo.utils;
import org.elasticsearch.geo.geometry.Geometry;
/**
* Generic geometry validator that can be used by the parser to verify the validity of the parsed geometry
*/
public interface GeometryValidator {
/**
* Validates the geometry and throws IllegalArgumentException if the geometry is not valid
*/
void validate(Geometry geometry);
}

View File

@ -22,7 +22,6 @@ package org.elasticsearch.geo.utils;
import org.elasticsearch.geo.geometry.Circle; import org.elasticsearch.geo.geometry.Circle;
import org.elasticsearch.geo.geometry.Geometry; import org.elasticsearch.geo.geometry.Geometry;
import org.elasticsearch.geo.geometry.GeometryCollection; import org.elasticsearch.geo.geometry.GeometryCollection;
import org.elasticsearch.geo.geometry.GeometryUtils;
import org.elasticsearch.geo.geometry.GeometryVisitor; import org.elasticsearch.geo.geometry.GeometryVisitor;
import org.elasticsearch.geo.geometry.Line; import org.elasticsearch.geo.geometry.Line;
import org.elasticsearch.geo.geometry.LinearRing; import org.elasticsearch.geo.geometry.LinearRing;
@ -58,11 +57,11 @@ public class WellKnownText {
private final String EOL = "END-OF-LINE"; private final String EOL = "END-OF-LINE";
private final boolean coerce; private final boolean coerce;
private final boolean ignoreZValue; private final GeometryValidator validator;
public WellKnownText(boolean coerce, boolean ignoreZValue) { public WellKnownText(boolean coerce, GeometryValidator validator) {
this.coerce = coerce; this.coerce = coerce;
this.ignoreZValue = ignoreZValue; this.validator = validator;
} }
public String toWKT(Geometry geometry) { public String toWKT(Geometry geometry) {
@ -243,7 +242,9 @@ public class WellKnownText {
tokenizer.whitespaceChars('\r', '\r'); tokenizer.whitespaceChars('\r', '\r');
tokenizer.whitespaceChars('\n', '\n'); tokenizer.whitespaceChars('\n', '\n');
tokenizer.commentChar('#'); tokenizer.commentChar('#');
return parseGeometry(tokenizer); Geometry geometry = parseGeometry(tokenizer);
validator.validate(geometry);
return geometry;
} finally { } finally {
reader.close(); reader.close();
} }
@ -297,7 +298,7 @@ public class WellKnownText {
double lat = nextNumber(stream); double lat = nextNumber(stream);
Point pt; Point pt;
if (isNumberNext(stream)) { if (isNumberNext(stream)) {
pt = new Point(lat, lon, GeometryUtils.checkAltitude(ignoreZValue, nextNumber(stream))); pt = new Point(lat, lon, nextNumber(stream));
} else { } else {
pt = new Point(lat, lon); pt = new Point(lat, lon);
} }
@ -318,7 +319,7 @@ public class WellKnownText {
lons.add(nextNumber(stream)); lons.add(nextNumber(stream));
lats.add(nextNumber(stream)); lats.add(nextNumber(stream));
if (isNumberNext(stream)) { if (isNumberNext(stream)) {
alts.add(GeometryUtils.checkAltitude(ignoreZValue, nextNumber(stream))); alts.add(nextNumber(stream));
} }
if (alts.isEmpty() == false && alts.size() != lons.size()) { if (alts.isEmpty() == false && alts.size() != lons.size()) {
throw new ParseException("coordinate dimensions do not match: " + tokenString(stream), stream.lineno()); throw new ParseException("coordinate dimensions do not match: " + tokenString(stream), stream.lineno());

View File

@ -22,6 +22,7 @@ package org.elasticsearch.geo.geometry;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import org.elasticsearch.test.AbstractWireTestCase; import org.elasticsearch.test.AbstractWireTestCase;
@ -53,7 +54,7 @@ abstract class BaseGeometryTestCase<T extends Geometry> extends AbstractWireTest
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
protected T copyInstance(T instance, Version version) throws IOException { protected T copyInstance(T instance, Version version) throws IOException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
String text = wkt.toWKT(instance); String text = wkt.toWKT(instance);
try { try {
return (T) wkt.fromWKT(text); return (T) wkt.fromWKT(text);

View File

@ -19,6 +19,8 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -36,7 +38,7 @@ public class CircleTests extends BaseGeometryTestCase<Circle> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("circle (20.0 10.0 15.0)", wkt.toWKT(new Circle(10, 20, 15))); assertEquals("circle (20.0 10.0 15.0)", wkt.toWKT(new Circle(10, 20, 15)));
assertEquals(new Circle(10, 20, 15), wkt.fromWKT("circle (20.0 10.0 15.0)")); assertEquals(new Circle(10, 20, 15), wkt.fromWKT("circle (20.0 10.0 15.0)"));
@ -48,13 +50,14 @@ public class CircleTests extends BaseGeometryTestCase<Circle> {
} }
public void testInitValidation() { public void testInitValidation() {
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> new Circle(10, 20, -1)); GeometryValidator validator = new GeographyValidator(true);
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Circle(10, 20, -1)));
assertEquals("Circle radius [-1.0] cannot be negative", ex.getMessage()); assertEquals("Circle radius [-1.0] cannot be negative", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Circle(100, 20, 1)); ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Circle(100, 20, 1)));
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage()); assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Circle(10, 200, 1)); ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Circle(10, 200, 1)));
assertEquals("invalid longitude 200.0; must be between -180.0 and 180.0", ex.getMessage()); assertEquals("invalid longitude 200.0; must be between -180.0 and 180.0", ex.getMessage());
} }
} }

View File

@ -19,6 +19,7 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -35,7 +36,7 @@ public class GeometryCollectionTests extends BaseGeometryTestCase<GeometryCollec
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("geometrycollection (point (20.0 10.0),point EMPTY)", assertEquals("geometrycollection (point (20.0 10.0),point EMPTY)",
wkt.toWKT(new GeometryCollection<Geometry>(Arrays.asList(new Point(10, 20), Point.EMPTY)))); wkt.toWKT(new GeometryCollection<Geometry>(Arrays.asList(new Point(10, 20), Point.EMPTY))));

View File

@ -0,0 +1,127 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText;
import org.elasticsearch.test.ESTestCase;
public class GeometryValidatorTests extends ESTestCase {
public static class NoopValidator implements GeometryValidator {
@Override
public void validate(Geometry geometry) {
}
}
public static class OneValidator extends GeographyValidator {
/**
* Minimum longitude value.
*/
private static final double MIN_LON_INCL = -1D;
/**
* Maximum longitude value.
*/
private static final double MAX_LON_INCL = 1D;
/**
* Minimum latitude value.
*/
private static final double MIN_LAT_INCL = -1D;
/**
* Maximum latitude value.
*/
private static final double MAX_LAT_INCL = 1D;
/**
* Minimum altitude value.
*/
private static final double MIN_ALT_INCL = -1D;
/**
* Maximum altitude value.
*/
private static final double MAX_ALT_INCL = 1D;
public OneValidator() {
super(true);
}
@Override
protected void checkLatitude(double latitude) {
if (Double.isNaN(latitude) || latitude < MIN_LAT_INCL || latitude > MAX_LAT_INCL) {
throw new IllegalArgumentException(
"invalid latitude " + latitude + "; must be between " + MIN_LAT_INCL + " and " + MAX_LAT_INCL);
}
}
@Override
protected void checkLongitude(double longitude) {
if (Double.isNaN(longitude) || longitude < MIN_LON_INCL || longitude > MAX_LON_INCL) {
throw new IllegalArgumentException(
"invalid longitude " + longitude + "; must be between " + MIN_LON_INCL + " and " + MAX_LON_INCL);
}
}
@Override
protected void checkAltitude(double zValue) {
if (Double.isNaN(zValue) == false && (zValue < MIN_ALT_INCL || zValue > MAX_ALT_INCL)) {
throw new IllegalArgumentException(
"invalid altitude " + zValue + "; must be between " + MIN_ALT_INCL + " and " + MAX_ALT_INCL);
}
}
}
public void testNoopValidator() throws Exception {
WellKnownText parser = new WellKnownText(true, new NoopValidator());
parser.fromWKT("CIRCLE (10000 20000 30000)");
parser.fromWKT("POINT (10000 20000)");
parser.fromWKT("LINESTRING (10000 20000, 0 0)");
parser.fromWKT("POLYGON ((300 100, 400 200, 500 300, 300 100), (50 150, 250 150, 200 100))");
parser.fromWKT("MULTIPOINT (10000 20000, 20000 30000)");
}
public void testOneValidator() throws Exception {
WellKnownText parser = new WellKnownText(true, new OneValidator());
parser.fromWKT("POINT (0 1)");
parser.fromWKT("POINT (0 1 0.5)");
IllegalArgumentException ex;
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT("CIRCLE (1 2 3)"));
assertEquals("invalid latitude 2.0; must be between -1.0 and 1.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT("POINT (2 1)"));
assertEquals("invalid longitude 2.0; must be between -1.0 and 1.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT("LINESTRING (1 -1 0, 0 0 2)"));
assertEquals("invalid altitude 2.0; must be between -1.0 and 1.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT("POLYGON ((0.3 0.1, 0.4 0.2, 5 0.3, 0.3 0.1))"));
assertEquals("invalid longitude 5.0; must be between -1.0 and 1.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT(
"POLYGON ((0.3 0.1, 0.4 0.2, 0.5 0.3, 0.3 0.1), (0.5 1.5, 2.5 1.5, 2.0 1.0))"));
assertEquals("invalid latitude 1.5; must be between -1.0 and 1.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT("MULTIPOINT (0 1, -2 1)"));
assertEquals("invalid longitude -2.0; must be between -1.0 and 1.0", ex.getMessage());
}
}

View File

@ -19,6 +19,8 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -31,7 +33,7 @@ public class LineTests extends BaseGeometryTestCase<Line> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("linestring (3.0 1.0, 4.0 2.0)", wkt.toWKT(new Line(new double[]{1, 2}, new double[]{3, 4}))); assertEquals("linestring (3.0 1.0, 4.0 2.0)", wkt.toWKT(new Line(new double[]{1, 2}, new double[]{3, 4})));
assertEquals(new Line(new double[]{1, 2}, new double[]{3, 4}), wkt.fromWKT("linestring (3 1, 4 2)")); assertEquals(new Line(new double[]{1, 2}, new double[]{3, 4}), wkt.fromWKT("linestring (3 1, 4 2)"));
@ -45,19 +47,23 @@ public class LineTests extends BaseGeometryTestCase<Line> {
} }
public void testInitValidation() { public void testInitValidation() {
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> new Line(new double[]{1}, new double[]{3})); GeometryValidator validator = new GeographyValidator(true);
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new Line(new double[]{1}, new double[]{3})));
assertEquals("at least two points in the line is required", ex.getMessage()); assertEquals("at least two points in the line is required", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Line(new double[]{1, 2, 3, 1}, new double[]{3, 4, 500, 3})); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new Line(new double[]{1, 2, 3, 1}, new double[]{3, 4, 500, 3})));
assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage()); assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Line(new double[]{1, 100, 3, 1}, new double[]{3, 4, 5, 3})); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new Line(new double[]{1, 100, 3, 1}, new double[]{3, 4, 5, 3})));
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage()); assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
} }
public void testWKTValidation() { public void testWKTValidation() {
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> new WellKnownText(randomBoolean(), false).fromWKT("linestring (3 1 6, 4 2 5)")); () -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("linestring (3 1 6, 4 2 5)"));
assertEquals("found Z value [6.0] but [ignore_z_value] parameter is [false]", ex.getMessage()); assertEquals("found Z value [6.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
} }
} }

View File

@ -19,6 +19,8 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -26,30 +28,35 @@ public class LinearRingTests extends ESTestCase {
public void testBasicSerialization() { public void testBasicSerialization() {
UnsupportedOperationException ex = expectThrows(UnsupportedOperationException.class, UnsupportedOperationException ex = expectThrows(UnsupportedOperationException.class,
() -> new WellKnownText(true, true).toWKT(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3}))); () -> new WellKnownText(true, new GeographyValidator(true))
.toWKT(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3})));
assertEquals("line ring cannot be serialized using WKT", ex.getMessage()); assertEquals("line ring cannot be serialized using WKT", ex.getMessage());
} }
public void testInitValidation() { public void testInitValidation() {
GeometryValidator validator = new GeographyValidator(true);
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> new LinearRing(new double[]{1, 2, 3}, new double[]{3, 4, 5})); () -> validator.validate(new LinearRing(new double[]{1, 2, 3}, new double[]{3, 4, 5})));
assertEquals("first and last points of the linear ring must be the same (it must close itself): lats[0]=1.0 lats[2]=3.0 " + assertEquals("first and last points of the linear ring must be the same (it must close itself): lats[0]=1.0 lats[2]=3.0 " +
"lons[0]=3.0 lons[2]=5.0", "lons[0]=3.0 lons[2]=5.0",
ex.getMessage()); ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, ex = expectThrows(IllegalArgumentException.class,
() -> new LinearRing(new double[]{1, 2, 1}, new double[]{3, 4, 3}, new double[]{1, 2, 3})); () -> validator.validate(new LinearRing(new double[]{1, 2, 1}, new double[]{3, 4, 3}, new double[]{1, 2, 3})));
assertEquals("first and last points of the linear ring must be the same (it must close itself): lats[0]=1.0 lats[2]=1.0 " + assertEquals("first and last points of the linear ring must be the same (it must close itself): lats[0]=1.0 lats[2]=1.0 " +
"lons[0]=3.0 lons[2]=3.0 alts[0]=1.0 alts[2]=3.0", "lons[0]=3.0 lons[2]=3.0 alts[0]=1.0 alts[2]=3.0",
ex.getMessage()); ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new LinearRing(new double[]{1}, new double[]{3})); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new LinearRing(new double[]{1}, new double[]{3})));
assertEquals("at least two points in the line is required", ex.getMessage()); assertEquals("at least two points in the line is required", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 500, 3})); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 500, 3})));
assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage()); assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new LinearRing(new double[]{1, 100, 3, 1}, new double[]{3, 4, 5, 3})); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new LinearRing(new double[]{1, 100, 3, 1}, new double[]{3, 4, 5, 3})));
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage()); assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
} }

View File

@ -19,6 +19,7 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -40,7 +41,7 @@ public class MultiLineTests extends BaseGeometryTestCase<MultiLine> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("multilinestring ((3.0 1.0, 4.0 2.0))", wkt.toWKT( assertEquals("multilinestring ((3.0 1.0, 4.0 2.0))", wkt.toWKT(
new MultiLine(Collections.singletonList(new Line(new double[]{1, 2}, new double[]{3, 4}))))); new MultiLine(Collections.singletonList(new Line(new double[]{1, 2}, new double[]{3, 4})))));
assertEquals(new MultiLine(Collections.singletonList(new Line(new double[]{1, 2}, new double[]{3, 4}))), assertEquals(new MultiLine(Collections.singletonList(new Line(new double[]{1, 2}, new double[]{3, 4}))),

View File

@ -19,6 +19,7 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -41,7 +42,7 @@ public class MultiPointTests extends BaseGeometryTestCase<MultiPoint> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("multipoint (2.0 1.0)", wkt.toWKT( assertEquals("multipoint (2.0 1.0)", wkt.toWKT(
new MultiPoint(Collections.singletonList(new Point(1, 2))))); new MultiPoint(Collections.singletonList(new Point(1, 2)))));
assertEquals(new MultiPoint(Collections.singletonList(new Point(1 ,2))), assertEquals(new MultiPoint(Collections.singletonList(new Point(1 ,2))),

View File

@ -19,6 +19,7 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -40,7 +41,7 @@ public class MultiPolygonTests extends BaseGeometryTestCase<MultiPolygon> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("multipolygon (((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0)))", assertEquals("multipolygon (((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0)))",
wkt.toWKT(new MultiPolygon(Collections.singletonList( wkt.toWKT(new MultiPolygon(Collections.singletonList(
new Polygon(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3})))))); new Polygon(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3}))))));

View File

@ -19,6 +19,8 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -31,7 +33,7 @@ public class PointTests extends BaseGeometryTestCase<Point> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("point (20.0 10.0)", wkt.toWKT(new Point(10, 20))); assertEquals("point (20.0 10.0)", wkt.toWKT(new Point(10, 20)));
assertEquals(new Point(10, 20), wkt.fromWKT("point (20.0 10.0)")); assertEquals(new Point(10, 20), wkt.fromWKT("point (20.0 10.0)"));
@ -43,16 +45,17 @@ public class PointTests extends BaseGeometryTestCase<Point> {
} }
public void testInitValidation() { public void testInitValidation() {
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> new Point(100, 10)); GeometryValidator validator = new GeographyValidator(true);
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Point(100, 10)));
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage()); assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Point(10, 500)); ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Point(10, 500)));
assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage()); assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage());
} }
public void testWKTValidation() { public void testWKTValidation() {
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> new WellKnownText(randomBoolean(), false).fromWKT("point (20.0 10.0 100.0)")); () -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("point (20.0 10.0 100.0)"));
assertEquals("found Z value [100.0] but [ignore_z_value] parameter is [false]", ex.getMessage()); assertEquals("found Z value [100.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
} }
} }

View File

@ -19,6 +19,7 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -32,7 +33,7 @@ public class PolygonTests extends BaseGeometryTestCase<Polygon> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("polygon ((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0))", assertEquals("polygon ((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0))",
wkt.toWKT(new Polygon(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3})))); wkt.toWKT(new Polygon(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3}))));
assertEquals(new Polygon(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3})), assertEquals(new Polygon(new LinearRing(new double[]{1, 2, 3, 1}, new double[]{3, 4, 5, 3})),
@ -73,16 +74,17 @@ public class PolygonTests extends BaseGeometryTestCase<Polygon> {
public void testWKTValidation() { public void testWKTValidation() {
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> new WellKnownText(false, true).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3))")); () -> new WellKnownText(false, new GeographyValidator(true)).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3))"));
assertEquals("first and last points of the linear ring must be the same (it must close itself): " + assertEquals("first and last points of the linear ring must be the same (it must close itself): " +
"lats[0]=1.0 lats[2]=3.0 lons[0]=3.0 lons[2]=5.0 alts[0]=5.0 alts[2]=3.0", ex.getMessage()); "lats[0]=1.0 lats[2]=3.0 lons[0]=3.0 lons[2]=5.0 alts[0]=5.0 alts[2]=3.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, ex = expectThrows(IllegalArgumentException.class,
() -> new WellKnownText(randomBoolean(), false).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3, 3 1 5))")); () -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3, 3 1 5))"));
assertEquals("found Z value [5.0] but [ignore_z_value] parameter is [false]", ex.getMessage()); assertEquals("found Z value [5.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, ex = expectThrows(IllegalArgumentException.class,
() -> new WellKnownText(false, randomBoolean()).fromWKT("polygon ((3 1, 4 2, 5 3, 3 1), (0.5 1.5, 2.5 1.5, 2.0 1.0))")); () -> new WellKnownText(false, new GeographyValidator(randomBoolean())).fromWKT(
"polygon ((3 1, 4 2, 5 3, 3 1), (0.5 1.5, 2.5 1.5, 2.0 1.0))"));
assertEquals("first and last points of the linear ring must be the same (it must close itself): " + assertEquals("first and last points of the linear ring must be the same (it must close itself): " +
"lats[0]=1.5 lats[2]=1.0 lons[0]=0.5 lons[2]=2.0", ex.getMessage()); "lats[0]=1.5 lats[2]=1.0 lons[0]=0.5 lons[2]=2.0", ex.getMessage());
} }

View File

@ -19,6 +19,8 @@
package org.elasticsearch.geo.geometry; package org.elasticsearch.geo.geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -32,7 +34,7 @@ public class RectangleTests extends BaseGeometryTestCase<Rectangle> {
} }
public void testBasicSerialization() throws IOException, ParseException { public void testBasicSerialization() throws IOException, ParseException {
WellKnownText wkt = new WellKnownText(true, true); WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
assertEquals("bbox (10.0, 20.0, 40.0, 30.0)", wkt.toWKT(new Rectangle(30, 40, 10, 20))); assertEquals("bbox (10.0, 20.0, 40.0, 30.0)", wkt.toWKT(new Rectangle(30, 40, 10, 20)));
assertEquals(new Rectangle(30, 40, 10, 20), wkt.fromWKT("bbox (10.0, 20.0, 40.0, 30.0)")); assertEquals(new Rectangle(30, 40, 10, 20), wkt.fromWKT("bbox (10.0, 20.0, 40.0, 30.0)"));
@ -41,16 +43,21 @@ public class RectangleTests extends BaseGeometryTestCase<Rectangle> {
} }
public void testInitValidation() { public void testInitValidation() {
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> new Rectangle(100, 1, 2, 3)); GeometryValidator validator = new GeographyValidator(true);
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new Rectangle(1, 100, 2, 3)));
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage()); assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Rectangle(1, 2, 200, 3)); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new Rectangle(1, 2, 200, 3)));
assertEquals("invalid longitude 200.0; must be between -180.0 and 180.0", ex.getMessage()); assertEquals("invalid longitude 200.0; must be between -180.0 and 180.0", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Rectangle(2, 1, 2, 3)); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new Rectangle(2, 1, 2, 3)));
assertEquals("max lat cannot be less than min lat", ex.getMessage()); assertEquals("max lat cannot be less than min lat", ex.getMessage());
ex = expectThrows(IllegalArgumentException.class, () -> new Rectangle(1, 2, 2, 3, 5, Double.NaN)); ex = expectThrows(IllegalArgumentException.class,
() -> validator.validate(new Rectangle(1, 2, 2, 3, 5, Double.NaN)));
assertEquals("only one altitude value is specified", ex.getMessage()); assertEquals("only one altitude value is specified", ex.getMessage());
} }
} }

View File

@ -44,6 +44,7 @@ import org.elasticsearch.geo.geometry.Point;
import org.elasticsearch.geo.geometry.Polygon; import org.elasticsearch.geo.geometry.Polygon;
import org.elasticsearch.geo.geometry.Rectangle; import org.elasticsearch.geo.geometry.Rectangle;
import org.elasticsearch.geo.geometry.ShapeType; import org.elasticsearch.geo.geometry.ShapeType;
import org.elasticsearch.geo.utils.GeometryValidator;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -66,18 +67,20 @@ public final class GeoJson {
private final boolean rightOrientation; private final boolean rightOrientation;
private final boolean coerce; private final boolean coerce;
private final boolean ignoreZValue; private final GeometryValidator validator;
public GeoJson(boolean rightOrientation, boolean coerce, boolean ignoreZValue) { public GeoJson(boolean rightOrientation, boolean coerce, GeometryValidator validator) {
this.rightOrientation = rightOrientation; this.rightOrientation = rightOrientation;
this.coerce = coerce; this.coerce = coerce;
this.ignoreZValue = ignoreZValue; this.validator = validator;
} }
public Geometry fromXContent(XContentParser parser) public Geometry fromXContent(XContentParser parser)
throws IOException { throws IOException {
try (XContentSubParser subParser = new XContentSubParser(parser)) { try (XContentSubParser subParser = new XContentSubParser(parser)) {
return PARSER.apply(subParser, this); Geometry geometry = PARSER.apply(subParser, this);
validator.validate(geometry);
return geometry;
} }
} }
@ -215,7 +218,7 @@ public final class GeoJson {
static { static {
PARSER.declareString(constructorArg(), FIELD_TYPE); PARSER.declareString(constructorArg(), FIELD_TYPE);
PARSER.declareField(optionalConstructorArg(), (p, c) -> parseCoordinates(p, c.ignoreZValue), FIELD_COORDINATES, PARSER.declareField(optionalConstructorArg(), (p, c) -> parseCoordinates(p), FIELD_COORDINATES,
ObjectParser.ValueType.VALUE_ARRAY); ObjectParser.ValueType.VALUE_ARRAY);
PARSER.declareObjectArray(optionalConstructorArg(), PARSER, FIELD_GEOMETRIES); PARSER.declareObjectArray(optionalConstructorArg(), PARSER, FIELD_GEOMETRIES);
PARSER.declareString(optionalConstructorArg(), FIELD_ORIENTATION); PARSER.declareString(optionalConstructorArg(), FIELD_ORIENTATION);
@ -298,20 +301,20 @@ public final class GeoJson {
* Recursive method which parses the arrays of coordinates used to define * Recursive method which parses the arrays of coordinates used to define
* Shapes * Shapes
*/ */
private static CoordinateNode parseCoordinates(XContentParser parser, boolean ignoreZValue) throws IOException { private static CoordinateNode parseCoordinates(XContentParser parser) throws IOException {
XContentParser.Token token = parser.nextToken(); XContentParser.Token token = parser.nextToken();
// Base cases // Base cases
if (token != XContentParser.Token.START_ARRAY && if (token != XContentParser.Token.START_ARRAY &&
token != XContentParser.Token.END_ARRAY && token != XContentParser.Token.END_ARRAY &&
token != XContentParser.Token.VALUE_NULL) { token != XContentParser.Token.VALUE_NULL) {
return new CoordinateNode(parseCoordinate(parser, ignoreZValue)); return new CoordinateNode(parseCoordinate(parser));
} else if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_NULL) {
throw new IllegalArgumentException("coordinates cannot contain NULL values)"); throw new IllegalArgumentException("coordinates cannot contain NULL values)");
} }
List<CoordinateNode> nodes = new ArrayList<>(); List<CoordinateNode> nodes = new ArrayList<>();
while (token != XContentParser.Token.END_ARRAY) { while (token != XContentParser.Token.END_ARRAY) {
CoordinateNode node = parseCoordinates(parser, ignoreZValue); CoordinateNode node = parseCoordinates(parser);
if (nodes.isEmpty() == false && nodes.get(0).numDimensions() != node.numDimensions()) { if (nodes.isEmpty() == false && nodes.get(0).numDimensions() != node.numDimensions()) {
throw new ElasticsearchParseException("Exception parsing coordinates: number of dimensions do not match"); throw new ElasticsearchParseException("Exception parsing coordinates: number of dimensions do not match");
} }
@ -325,7 +328,7 @@ public final class GeoJson {
/** /**
* Parser a singe set of 2 or 3 coordinates * Parser a singe set of 2 or 3 coordinates
*/ */
private static Point parseCoordinate(XContentParser parser, boolean ignoreZValue) throws IOException { private static Point parseCoordinate(XContentParser parser) throws IOException {
// Add support for coerce here // Add support for coerce here
if (parser.currentToken() != XContentParser.Token.VALUE_NUMBER) { if (parser.currentToken() != XContentParser.Token.VALUE_NUMBER) {
throw new ElasticsearchParseException("geo coordinates must be numbers"); throw new ElasticsearchParseException("geo coordinates must be numbers");
@ -339,7 +342,7 @@ public final class GeoJson {
// alt (for storing purposes only - future use includes 3d shapes) // alt (for storing purposes only - future use includes 3d shapes)
double alt = Double.NaN; double alt = Double.NaN;
if (token == XContentParser.Token.VALUE_NUMBER) { if (token == XContentParser.Token.VALUE_NUMBER) {
alt = GeoPoint.assertZValue(ignoreZValue, parser.doubleValue()); alt = parser.doubleValue();
parser.nextToken(); parser.nextToken();
} }
// do not support > 3 dimensions // do not support > 3 dimensions

View File

@ -22,6 +22,8 @@ package org.elasticsearch.common.geo;
import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.geo.geometry.Geometry; import org.elasticsearch.geo.geometry.Geometry;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import java.io.IOException; import java.io.IOException;
@ -34,10 +36,12 @@ public final class GeometryParser {
private final GeoJson geoJsonParser; private final GeoJson geoJsonParser;
private final WellKnownText wellKnownTextParser; private final WellKnownText wellKnownTextParser;
private final GeometryValidator validator;
public GeometryParser(boolean rightOrientation, boolean coerce, boolean ignoreZValue) { public GeometryParser(boolean rightOrientation, boolean coerce, boolean ignoreZValue) {
geoJsonParser = new GeoJson(rightOrientation, coerce, ignoreZValue); validator = new GeographyValidator(ignoreZValue);
wellKnownTextParser = new WellKnownText(coerce, ignoreZValue); geoJsonParser = new GeoJson(rightOrientation, coerce, validator);
wellKnownTextParser = new WellKnownText(coerce, validator);
} }
/** /**
@ -50,7 +54,6 @@ public final class GeometryParser {
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) { } else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
return geoJsonParser.fromXContent(parser); return geoJsonParser.fromXContent(parser);
} else if (parser.currentToken() == XContentParser.Token.VALUE_STRING) { } else if (parser.currentToken() == XContentParser.Token.VALUE_STRING) {
// TODO: Add support for ignoreZValue and coerce to WKT
return wellKnownTextParser.fromWKT(parser.text()); return wellKnownTextParser.fromWKT(parser.text());
} }
throw new ElasticsearchParseException("shape must be an object consisting of type and coordinates"); throw new ElasticsearchParseException("shape must be an object consisting of type and coordinates");

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.geo;
import org.elasticsearch.common.geo.parsers.ShapeParser; import org.elasticsearch.common.geo.parsers.ShapeParser;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.hamcrest.ElasticsearchGeoAssertions; import org.elasticsearch.test.hamcrest.ElasticsearchGeoAssertions;
import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Geometry;
@ -70,7 +71,7 @@ abstract class BaseGeoParsingTestCase extends ESTestCase {
protected void assertGeometryEquals(org.elasticsearch.geo.geometry.Geometry expected, XContentBuilder geoJson) throws IOException { protected void assertGeometryEquals(org.elasticsearch.geo.geometry.Geometry expected, XContentBuilder geoJson) throws IOException {
try (XContentParser parser = createParser(geoJson)) { try (XContentParser parser = createParser(geoJson)) {
parser.nextToken(); parser.nextToken();
assertEquals(expected, new GeoJson(true, false, false).fromXContent(parser)); assertEquals(expected, new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
} }
} }

View File

@ -21,7 +21,6 @@ package org.elasticsearch.common.geo;
import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.geo.geometry.Rectangle;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import java.io.IOException; import java.io.IOException;
@ -67,22 +66,6 @@ public class GeoDistanceTests extends ESTestCase {
} }
} }
public void testDistanceCheck() {
// Note, is within is an approximation, so, even though 0.52 is outside 50mi, we still get "true"
double radius = DistanceUnit.convert(50, DistanceUnit.MILES, DistanceUnit.METERS);
org.apache.lucene.geo.Rectangle r = org.apache.lucene.geo.Rectangle.fromPointDistance(0, 0, radius);
Rectangle box = new Rectangle(r.minLat, r.maxLat, r.minLon, r.maxLon);
assertThat(box.containsPoint(0.5, 0.5), equalTo(true));
assertThat(box.containsPoint(0.52, 0.52), equalTo(true));
assertThat(box.containsPoint(1, 1), equalTo(false));
radius = DistanceUnit.convert(200, DistanceUnit.MILES, DistanceUnit.METERS);
r = org.apache.lucene.geo.Rectangle.fromPointDistance(0, 179, radius);
box = new Rectangle(r.minLat, r.maxLat, r.minLon, r.maxLon);
assertThat(box.containsPoint(0, -179), equalTo(true));
assertThat(box.containsPoint(0, -178), equalTo(false));
}
private static double arcDistance(GeoPoint p1, GeoPoint p2) { private static double arcDistance(GeoPoint p1, GeoPoint p2) {
return GeoDistance.ARC.calculate(p1.lat(), p1.lon(), p2.lat(), p2.lon(), DistanceUnit.METERS); return GeoDistance.ARC.calculate(p1.lat(), p1.lon(), p2.lat(), p2.lon(), DistanceUnit.METERS);
} }

View File

@ -36,6 +36,7 @@ import org.elasticsearch.geo.geometry.MultiPolygon;
import org.elasticsearch.geo.geometry.Point; import org.elasticsearch.geo.geometry.Point;
import org.elasticsearch.geo.geometry.Polygon; import org.elasticsearch.geo.geometry.Polygon;
import org.elasticsearch.geo.geometry.Rectangle; import org.elasticsearch.geo.geometry.Rectangle;
import org.elasticsearch.geo.utils.GeographyValidator;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
@ -72,7 +73,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
Line expected = new Line(new double[] {0.0, 1.0}, new double[] { 100.0, 101.0}); Line expected = new Line(new double[] {0.0, 1.0}, new double[] { 100.0, 101.0});
try (XContentParser parser = createParser(lineGeoJson)) { try (XContentParser parser = createParser(lineGeoJson)) {
parser.nextToken(); parser.nextToken();
assertEquals(expected, new GeoJson(false, false, true).fromXContent(parser)); assertEquals(expected, new GeoJson(false, false, new GeographyValidator(true)).fromXContent(parser));
} }
} }
@ -124,7 +125,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(pointGeoJson)) { try (XContentParser parser = createParser(pointGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(false, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(false, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -140,7 +141,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(lineGeoJson)) { try (XContentParser parser = createParser(lineGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(false, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(false, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -178,7 +179,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(multilinesGeoJson)) { try (XContentParser parser = createParser(multilinesGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(false, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(false, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -189,7 +190,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(multilinesGeoJson)) { try (XContentParser parser = createParser(multilinesGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(false, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(false, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -239,7 +240,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
)); ));
try (XContentParser parser = createParser(polygonGeoJson)) { try (XContentParser parser = createParser(polygonGeoJson)) {
parser.nextToken(); parser.nextToken();
assertEquals(expected, new GeoJson(true, false, true).fromXContent(parser)); assertEquals(expected, new GeoJson(true, false, new GeographyValidator(true)).fromXContent(parser));
} }
} }
@ -259,7 +260,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(polygonGeoJson)) { try (XContentParser parser = createParser(polygonGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, true).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(true)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -275,7 +276,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(invalidPoint1)) { try (XContentParser parser = createParser(invalidPoint1)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -288,7 +289,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(invalidPoint2)) { try (XContentParser parser = createParser(invalidPoint2)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -302,7 +303,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(invalidMultipoint1)) { try (XContentParser parser = createParser(invalidMultipoint1)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -315,7 +316,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(invalidMultipoint2)) { try (XContentParser parser = createParser(invalidMultipoint2)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -329,7 +330,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject(); .endObject();
try (XContentParser parser = createParser(invalidMultipoint3)) { try (XContentParser parser = createParser(invalidMultipoint3)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -370,7 +371,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, multiPolygonGeoJson)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, multiPolygonGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -391,7 +392,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
.endObject()); .endObject());
try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -406,7 +407,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -421,7 +422,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -436,7 +437,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -449,7 +450,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -460,7 +461,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -473,7 +474,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) { try (XContentParser parser = createParser(JsonXContent.jsonXContent, invalidPoly)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -710,7 +711,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(tooLittlePointGeoJson)) { try (XContentParser parser = createParser(tooLittlePointGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
@ -723,7 +724,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
try (XContentParser parser = createParser(emptyPointGeoJson)) { try (XContentParser parser = createParser(emptyPointGeoJson)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertNull(parser.nextToken()); assertNull(parser.nextToken());
} }
} }
@ -749,7 +750,7 @@ public class GeoJsonParserTests extends BaseGeoParsingTestCase {
parser.nextToken(); // foo parser.nextToken(); // foo
parser.nextToken(); // start object parser.nextToken(); // start object
parser.nextToken(); // start object parser.nextToken(); // start object
expectThrows(XContentParseException.class, () -> new GeoJson(true, false, false).fromXContent(parser)); expectThrows(XContentParseException.class, () -> new GeoJson(true, false, new GeographyValidator(false)).fromXContent(parser));
assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken()); // end of the document assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken()); // end of the document
assertNull(parser.nextToken()); // no more elements afterwards assertNull(parser.nextToken()); // no more elements afterwards
} }

View File

@ -34,6 +34,7 @@ import org.elasticsearch.geo.geometry.MultiPolygon;
import org.elasticsearch.geo.geometry.Point; import org.elasticsearch.geo.geometry.Point;
import org.elasticsearch.geo.geometry.Polygon; import org.elasticsearch.geo.geometry.Polygon;
import org.elasticsearch.geo.geometry.Rectangle; import org.elasticsearch.geo.geometry.Rectangle;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.test.AbstractXContentTestCase; import org.elasticsearch.test.AbstractXContentTestCase;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -49,7 +50,7 @@ public class GeoJsonSerializationTests extends ESTestCase {
private static class GeometryWrapper implements ToXContentObject { private static class GeometryWrapper implements ToXContentObject {
private Geometry geometry; private Geometry geometry;
private static GeoJson PARSER = new GeoJson(true, false, true); private static GeoJson PARSER = new GeoJson(true, false, new GeographyValidator(true));
GeometryWrapper(Geometry geometry) { GeometryWrapper(Geometry geometry) {
this.geometry = geometry; this.geometry = geometry;

View File

@ -61,7 +61,7 @@ public class GeometryParserTests extends ESTestCase {
try (XContentParser parser = createParser(pointGeoJsonWithZ)) { try (XContentParser parser = createParser(pointGeoJsonWithZ)) {
parser.nextToken(); parser.nextToken();
expectThrows(XContentParseException.class, () -> new GeometryParser(true, randomBoolean(), false).parse(parser)); expectThrows(IllegalArgumentException.class, () -> new GeometryParser(true, randomBoolean(), false).parse(parser));
} }
XContentBuilder polygonGeoJson = XContentFactory.jsonBuilder() XContentBuilder polygonGeoJson = XContentFactory.jsonBuilder()

View File

@ -9,6 +9,7 @@ import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.geo.geometry.Geometry; import org.elasticsearch.geo.geometry.Geometry;
import org.elasticsearch.geo.geometry.Point; import org.elasticsearch.geo.geometry.Point;
import org.elasticsearch.geo.geometry.ShapeType; import org.elasticsearch.geo.geometry.ShapeType;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
@ -126,7 +127,7 @@ public abstract class ExtractedField {
} }
private static class GeoShapeField extends FromSource { private static class GeoShapeField extends FromSource {
private static final WellKnownText wkt = new WellKnownText(true, true); private static final WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
GeoShapeField(String alias, String name) { GeoShapeField(String alias, String name) {
super(alias, name); super(alias, name);

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.xpack.sql.jdbc; package org.elasticsearch.xpack.sql.jdbc;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import org.elasticsearch.xpack.sql.proto.StringUtils; import org.elasticsearch.xpack.sql.proto.StringUtils;
@ -54,7 +55,7 @@ import static org.elasticsearch.xpack.sql.jdbc.JdbcDateUtils.timeAsTime;
*/ */
final class TypeConverter { final class TypeConverter {
private static WellKnownText WKT = new WellKnownText(true, true); private static WellKnownText WKT = new WellKnownText(true, new GeographyValidator(true));
private TypeConverter() {} private TypeConverter() {}

View File

@ -10,6 +10,7 @@ import com.carrotsearch.hppc.IntObjectHashMap;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.elasticsearch.geo.geometry.Geometry; import org.elasticsearch.geo.geometry.Geometry;
import org.elasticsearch.geo.geometry.Point; import org.elasticsearch.geo.geometry.Point;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import org.elasticsearch.xpack.sql.jdbc.EsType; import org.elasticsearch.xpack.sql.jdbc.EsType;
import org.elasticsearch.xpack.sql.proto.StringUtils; import org.elasticsearch.xpack.sql.proto.StringUtils;
@ -51,7 +52,7 @@ public class JdbcAssert {
private static final IntObjectHashMap<EsType> SQL_TO_TYPE = new IntObjectHashMap<>(); private static final IntObjectHashMap<EsType> SQL_TO_TYPE = new IntObjectHashMap<>();
private static final WellKnownText WKT = new WellKnownText(true, true); private static final WellKnownText WKT = new WellKnownText(true, new GeographyValidator(true));
static { static {
for (EsType type : EsType.values()) { for (EsType type : EsType.values()) {

View File

@ -29,6 +29,8 @@ import org.elasticsearch.geo.geometry.MultiPolygon;
import org.elasticsearch.geo.geometry.Point; import org.elasticsearch.geo.geometry.Point;
import org.elasticsearch.geo.geometry.Polygon; import org.elasticsearch.geo.geometry.Polygon;
import org.elasticsearch.geo.geometry.Rectangle; import org.elasticsearch.geo.geometry.Rectangle;
import org.elasticsearch.geo.utils.GeographyValidator;
import org.elasticsearch.geo.utils.GeometryValidator;
import org.elasticsearch.geo.utils.WellKnownText; import org.elasticsearch.geo.utils.WellKnownText;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
@ -49,9 +51,11 @@ public class GeoShape implements ToXContentFragment, NamedWriteable {
private final Geometry shape; private final Geometry shape;
private static final GeometryValidator validator = new GeographyValidator(true);
private static final GeometryParser GEOMETRY_PARSER = new GeometryParser(true, true, true); private static final GeometryParser GEOMETRY_PARSER = new GeometryParser(true, true, true);
private static final WellKnownText WKT_PARSER = new WellKnownText(true, true); private static final WellKnownText WKT_PARSER = new WellKnownText(true, validator);
public GeoShape(double lon, double lat) { public GeoShape(double lon, double lat) {
shape = new Point(lat, lon); shape = new Point(lat, lon);