Refactor PointParser to not take FieldMapper as a parameter (#62950)
Passing FieldMappers to point parsing functions makes trying to build source-only fields from MappedFieldTypes more complicated. This small refactoring changes things so that the relevant parsing and factory functions from AbstractGeometryFieldMapper are instead passed as lambdas to the PointParser constructor.
This commit is contained in:
parent
4d43fa8816
commit
a3ba24123e
|
@ -89,7 +89,7 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> 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<Parsed, Processed> 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<Parsed, Processed> extends Fie
|
|||
|
||||
AbstractGeometryFieldType<Parsed, Processed> mappedFieldType = fieldType();
|
||||
Parser<Parsed> geometryParser = mappedFieldType.geometryParser();
|
||||
Function<Object, Object> valueParser = value -> geometryParser.parseAndFormatObject(value, this, geoFormat);
|
||||
Function<Object, Object> valueParser = value -> geometryParser.parseAndFormatObject(value, geoFormat);
|
||||
|
||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
||||
@Override
|
||||
|
@ -340,7 +340,7 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> 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;
|
||||
}
|
||||
|
|
|
@ -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<Parsed, Processed> 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<Parsed, Processed> 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<P extends ParsedPoint> extends Parser<List<P>> {
|
||||
/**
|
||||
* Note that this parser is only used for formatting values.
|
||||
*/
|
||||
private final GeometryParser geometryParser;
|
||||
private final String field;
|
||||
private final Supplier<P> pointSupplier;
|
||||
private final CheckedBiFunction<XContentParser, P, P, IOException> objectParser;
|
||||
private final P nullValue;
|
||||
private final boolean ignoreZValue;
|
||||
private final boolean ignoreMalformed;
|
||||
|
||||
public PointParser() {
|
||||
public PointParser(String field,
|
||||
Supplier<P> pointSupplier,
|
||||
CheckedBiFunction<XContentParser, P, P, IOException> 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<P> parse(XContentParser parser, AbstractGeometryFieldMapper geometryMapper) throws IOException, ParseException {
|
||||
AbstractPointGeometryFieldMapper mapper = (AbstractPointGeometryFieldMapper) geometryMapper;
|
||||
public List<P> parse(XContentParser parser) throws IOException, ParseException {
|
||||
|
||||
if (parser.currentToken() == XContentParser.Token.START_ARRAY) {
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
P point = (P)(mapper.newParsedPoint());
|
||||
ArrayList<P> points = new ArrayList();
|
||||
P point = pointSupplier.get();
|
||||
ArrayList<P> 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<P> 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<P> points = new ArrayList();
|
||||
points.add(point);
|
||||
return points;
|
||||
return Collections.singletonList(process(objectParser.apply(parser, pointSupplier.get())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<List<P
|
|||
MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
Explicit<Boolean> 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<List<P
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses geopoint represented as an object or an array, ignores malformed geopoints if needed
|
||||
*/
|
||||
@Override
|
||||
protected void parsePointIgnoringMalformed(XContentParser parser, ParsedPoint point) throws IOException {
|
||||
GeoUtils.parseGeoPoint(parser, (GeoPoint)point, ignoreZValue().value());
|
||||
super.parsePointIgnoringMalformed(parser, point);
|
||||
}
|
||||
|
||||
public GeoPointFieldMapper(String simpleName, FieldType fieldType, MappedFieldType mappedFieldType,
|
||||
MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
Explicit<Boolean> ignoreZValue, ParsedPoint nullValue, CopyTo copyTo) {
|
||||
|
@ -166,11 +159,6 @@ public class GeoPointFieldMapper extends AbstractPointGeometryFieldMapper<List<P
|
|||
return (GeoPointFieldType)mappedFieldType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ParsedPoint newParsedPoint() {
|
||||
return new ParsedGeoPoint();
|
||||
}
|
||||
|
||||
public static class GeoPointFieldType extends AbstractPointGeometryFieldType<List<ParsedGeoPoint>, List<? extends GeoPoint>> {
|
||||
private GeoPointFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map<String, String> meta) {
|
||||
super(name, indexed, stored, hasDocValues, meta);
|
||||
|
@ -251,12 +239,8 @@ public class GeoPointFieldMapper extends AbstractPointGeometryFieldMapper<List<P
|
|||
GeoPoint o = (GeoPoint)other;
|
||||
oLat = o.lat();
|
||||
oLon = o.lon();
|
||||
} else if (other instanceof ParsedGeoPoint == false) {
|
||||
return false;
|
||||
} else {
|
||||
ParsedGeoPoint o = (ParsedGeoPoint)other;
|
||||
oLat = o.lat();
|
||||
oLon = o.lon();
|
||||
return false;
|
||||
}
|
||||
if (Double.compare(oLat, lat) != 0) return false;
|
||||
if (Double.compare(oLon, lon) != 0) return false;
|
||||
|
|
|
@ -41,7 +41,7 @@ public class GeoShapeParser extends AbstractGeometryFieldMapper.Parser<Geometry>
|
|||
}
|
||||
|
||||
@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<Geometry>
|
|||
}
|
||||
|
||||
@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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<List<Pars
|
|||
MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
Explicit<Boolean> 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<List<Pars
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ParsedPoint newParsedPoint() {
|
||||
return new ParsedCartesianPoint();
|
||||
}
|
||||
|
||||
public static class TypeParser extends AbstractPointGeometryFieldMapper.TypeParser<Builder> {
|
||||
@Override
|
||||
protected Builder newBuilder(String name, Map<String, Object> params) {
|
||||
|
@ -81,15 +77,6 @@ public class PointFieldMapper extends AbstractPointGeometryFieldMapper<List<Pars
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses geopoint represented as an object or an array, ignores malformed geopoints if needed
|
||||
*/
|
||||
@Override
|
||||
protected void parsePointIgnoringMalformed(XContentParser parser, ParsedPoint point) throws IOException {
|
||||
super.parsePointIgnoringMalformed(parser, point);
|
||||
CartesianPoint.parsePoint(parser, (CartesianPoint)point, ignoreZValue().value());
|
||||
}
|
||||
|
||||
public PointFieldMapper(String simpleName, FieldType fieldType, MappedFieldType mappedFieldType,
|
||||
MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
Explicit<Boolean> ignoreZValue, ParsedPoint nullValue, CopyTo copyTo) {
|
||||
|
|
Loading…
Reference in New Issue