diff --git a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java index d094b8b4a6d..a45ebfd3dce 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java @@ -89,7 +89,7 @@ public abstract class AbstractGeometryFieldMapper extends Fie * Parse the given xContent value to an object of type {@link Parsed}. The value can be * in any supported format. */ - public abstract Parsed parse(XContentParser parser, AbstractGeometryFieldMapper mapper) throws IOException, ParseException; + public abstract Parsed parse(XContentParser parser) throws IOException, ParseException; /** * Given a parsed value and a format string, formats the value into a plain Java object. @@ -106,14 +106,14 @@ public abstract class AbstractGeometryFieldMapper extends Fie * it with {@link Parser#format}. However some {@link Parser} implementations override this * as they can avoid parsing the value if it is already in the right format. */ - public Object parseAndFormatObject(Object value, AbstractGeometryFieldMapper mapper, String format) { + public Object parseAndFormatObject(Object value, String format) { Parsed geometry; try (XContentParser parser = new MapXContentParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, Collections.singletonMap("dummy_field", value), XContentType.JSON)) { parser.nextToken(); // start object parser.nextToken(); // field name parser.nextToken(); // field value - geometry = parse(parser, mapper); + geometry = parse(parser); } catch (IOException e) { throw new UncheckedIOException(e); } catch (ParseException e) { @@ -188,7 +188,7 @@ public abstract class AbstractGeometryFieldMapper extends Fie AbstractGeometryFieldType mappedFieldType = fieldType(); Parser geometryParser = mappedFieldType.geometryParser(); - Function valueParser = value -> geometryParser.parseAndFormatObject(value, this, geoFormat); + Function valueParser = value -> geometryParser.parseAndFormatObject(value, geoFormat); return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) { @Override @@ -340,7 +340,7 @@ public abstract class AbstractGeometryFieldMapper extends Fie try { Processed shape = context.parseExternalValue(geometryIndexer.processedClass()); if (shape == null) { - Parsed geometry = geometryParser.parse(context.parser(), this); + Parsed geometry = geometryParser.parse(context.parser()); if (geometry == null) { return; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/AbstractPointGeometryFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/AbstractPointGeometryFieldMapper.java index f7079dbf3c5..fcf6b3a0738 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/AbstractPointGeometryFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/AbstractPointGeometryFieldMapper.java @@ -20,6 +20,7 @@ package org.elasticsearch.index.mapper; import org.apache.lucene.document.FieldType; import org.elasticsearch.ElasticsearchParseException; +import org.elasticsearch.common.CheckedBiFunction; import org.elasticsearch.common.Explicit; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.geo.GeoPoint; @@ -34,9 +35,11 @@ import org.elasticsearch.geometry.Point; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import static org.elasticsearch.index.mapper.TypeParsers.parseField; @@ -154,8 +157,6 @@ public abstract class AbstractPointGeometryFieldMapper extend return nullValue; } - protected abstract ParsedPoint newParsedPoint(); - /** represents a Point that has been parsed by {@link PointParser} */ public interface ParsedPoint { void validate(String fieldName); @@ -167,87 +168,80 @@ public abstract class AbstractPointGeometryFieldMapper extend } } - protected void parsePointIgnoringMalformed(XContentParser parser, ParsedPoint point) throws IOException { - try { - if (ignoreMalformed.value() == false) { - point.validate(name()); - } else { - point.normalize(name()); - } - } catch (ElasticsearchParseException e) { - if (ignoreMalformed.value() == false) { - throw e; - } - } - } - /** A parser implementation that can parse the various point formats */ public static class PointParser

extends Parser> { /** * Note that this parser is only used for formatting values. */ private final GeometryParser geometryParser; + private final String field; + private final Supplier

pointSupplier; + private final CheckedBiFunction objectParser; + private final P nullValue; + private final boolean ignoreZValue; + private final boolean ignoreMalformed; - public PointParser() { + public PointParser(String field, + Supplier

pointSupplier, + CheckedBiFunction objectParser, + P nullValue, + boolean ignoreZValue, + boolean ignoreMalformed) { + this.field = field; + this.pointSupplier = pointSupplier; + this.objectParser = objectParser; + this.nullValue = nullValue; + this.ignoreZValue = ignoreZValue; + this.ignoreMalformed = ignoreMalformed; this.geometryParser = new GeometryParser(true, true, true); } + private P process(P in) { + if (ignoreMalformed == false) { + in.validate(field); + } else { + in.normalize(field); + } + return in; + } + @Override - public List

parse(XContentParser parser, AbstractGeometryFieldMapper geometryMapper) throws IOException, ParseException { - AbstractPointGeometryFieldMapper mapper = (AbstractPointGeometryFieldMapper) geometryMapper; + public List

parse(XContentParser parser) throws IOException, ParseException { if (parser.currentToken() == XContentParser.Token.START_ARRAY) { XContentParser.Token token = parser.nextToken(); - P point = (P)(mapper.newParsedPoint()); - ArrayList

points = new ArrayList(); + P point = pointSupplier.get(); + ArrayList

points = new ArrayList<>(); if (token == XContentParser.Token.VALUE_NUMBER) { double x = parser.doubleValue(); parser.nextToken(); double y = parser.doubleValue(); token = parser.nextToken(); if (token == XContentParser.Token.VALUE_NUMBER) { - GeoPoint.assertZValue((Boolean)(mapper.ignoreZValue().value()), parser.doubleValue()); + GeoPoint.assertZValue(ignoreZValue, parser.doubleValue()); } else if (token != XContentParser.Token.END_ARRAY) { - throw new ElasticsearchParseException("[{}] field type does not accept > 3 dimensions", - mapper.contentType()); + throw new ElasticsearchParseException("field type does not accept > 3 dimensions"); } point.resetCoords(x, y); - if ((Boolean)(mapper.ignoreMalformed().value()) == false) { - point.validate(mapper.name()); - } else { - point.normalize(mapper.name()); - } - points.add(point); + points.add(process(point)); } else { while (token != XContentParser.Token.END_ARRAY) { - mapper.parsePointIgnoringMalformed(parser, point); - points.add(point); - point = (P)(mapper.newParsedPoint()); + points.add(process(objectParser.apply(parser, point))); + point = pointSupplier.get(); token = parser.nextToken(); } } return points; } else if (parser.currentToken() == XContentParser.Token.VALUE_NULL) { - P point = null; - ArrayList

points = null; - if (mapper.nullValue != null) { - point = (P)(mapper.nullValue); - if ((Boolean)(mapper.ignoreMalformed().value()) == false) { - point.validate(mapper.name()); - } else { - point.normalize(mapper.name()); - } - points = new ArrayList<>(); - points.add(point); + if (nullValue == null) { + return Collections.emptyList(); + } + else { + return Collections.singletonList(nullValue); } - return points; } else { - P point = (P)mapper.newParsedPoint(); - mapper.parsePointIgnoringMalformed(parser, point); - ArrayList

points = new ArrayList(); - points.add(point); - return points; + return Collections.singletonList(process(objectParser.apply(parser, pointSupplier.get()))); } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java index 29910e4edb3..568c638c8c0 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java @@ -30,7 +30,6 @@ import org.elasticsearch.common.Explicit; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.unit.DistanceUnit; -import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.geometry.Point; import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.plain.AbstractLatLonPointIndexFieldData; @@ -75,7 +74,10 @@ public class GeoPointFieldMapper extends AbstractPointGeometryFieldMapper ignoreMalformed, Explicit ignoreZValue, ParsedPoint nullValue, CopyTo copyTo) { GeoPointFieldType ft = new GeoPointFieldType(buildFullName(context), indexed, fieldType.stored(), hasDocValues, meta); - ft.setGeometryParser(new PointParser<>()); + ft.setGeometryParser(new PointParser<>(name, ParsedGeoPoint::new, (parser, point) -> { + GeoUtils.parseGeoPoint(parser, point, ignoreZValue().value()); + return point; + }, (ParsedGeoPoint) nullValue, ignoreZValue.value(), ignoreMalformed.value())); ft.setGeometryIndexer(new GeoPointIndexer(ft)); ft.setGeometryQueryBuilder(new VectorGeoPointShapeQueryProcessor()); return new GeoPointFieldMapper(name, fieldType, ft, multiFields, ignoreMalformed, ignoreZValue, nullValue, copyTo); @@ -105,15 +107,6 @@ public class GeoPointFieldMapper extends AbstractPointGeometryFieldMapper ignoreMalformed, Explicit ignoreZValue, ParsedPoint nullValue, CopyTo copyTo) { @@ -166,11 +159,6 @@ public class GeoPointFieldMapper extends AbstractPointGeometryFieldMapper, List> { private GeoPointFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map meta) { super(name, indexed, stored, hasDocValues, meta); @@ -251,12 +239,8 @@ public class GeoPointFieldMapper extends AbstractPointGeometryFieldMapper } @Override - public Geometry parse(XContentParser parser, AbstractGeometryFieldMapper mapper) throws IOException, ParseException { + public Geometry parse(XContentParser parser) throws IOException, ParseException { return geometryParser.parse(parser); } @@ -51,7 +51,7 @@ public class GeoShapeParser extends AbstractGeometryFieldMapper.Parser } @Override - public Object parseAndFormatObject(Object value, AbstractGeometryFieldMapper mapper, String format) { + public Object parseAndFormatObject(Object value, String format) { try (XContentParser parser = new MapXContentParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, Collections.singletonMap("dummy_field", value), XContentType.JSON)) { parser.nextToken(); // start object diff --git a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java index 59f9a3969ed..c80e58bdeae 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java @@ -298,7 +298,7 @@ public class LegacyGeoShapeFieldMapper extends AbstractShapeGeometryFieldMapper< } @Override - public ShapeBuilder parse(XContentParser parser, AbstractGeometryFieldMapper mapper) throws IOException, ParseException { + public ShapeBuilder parse(XContentParser parser) throws IOException, ParseException { return ShapeParser.parse(parser); } diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java index 31abfba4f71..7793694f2f5 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java @@ -11,7 +11,6 @@ import org.apache.lucene.document.XYDocValuesField; import org.apache.lucene.document.XYPointField; import org.apache.lucene.index.IndexableField; import org.elasticsearch.common.Explicit; -import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.geometry.Point; import org.elasticsearch.index.mapper.AbstractPointGeometryFieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; @@ -20,7 +19,6 @@ import org.elasticsearch.xpack.spatial.common.CartesianPoint; import org.elasticsearch.xpack.spatial.index.mapper.PointFieldMapper.ParsedCartesianPoint; import org.elasticsearch.xpack.spatial.index.query.ShapeQueryPointProcessor; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -45,7 +43,10 @@ public class PointFieldMapper extends AbstractPointGeometryFieldMapper ignoreMalformed, Explicit ignoreZValue, ParsedPoint nullValue, CopyTo copyTo) { PointFieldType ft = new PointFieldType(buildFullName(context), indexed, fieldType.stored(), hasDocValues, meta); - ft.setGeometryParser(new PointParser<>()); + ft.setGeometryParser(new PointParser<>(name, ParsedCartesianPoint::new, (parser, point) -> { + ParsedCartesianPoint.parsePoint(parser, point, ignoreZValue.value()); + return point; + }, (ParsedCartesianPoint) nullValue, ignoreZValue.value(), ignoreMalformed.value())); ft.setGeometryIndexer(new PointIndexer(ft)); ft.setGeometryQueryBuilder(new ShapeQueryPointProcessor()); return new PointFieldMapper(simpleName, fieldType, ft, multiFields, @@ -54,11 +55,6 @@ public class PointFieldMapper extends AbstractPointGeometryFieldMapper { @Override protected Builder newBuilder(String name, Map params) { @@ -81,15 +77,6 @@ public class PointFieldMapper extends AbstractPointGeometryFieldMapper ignoreMalformed, Explicit ignoreZValue, ParsedPoint nullValue, CopyTo copyTo) {