org.elasticsearch.index.mapper.AbstractPointGeometryFieldMapper Maven / Gradle / Ivy
Show all versions of elasticsearch Show documentation
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.index.mapper;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.CheckedBiFunction;
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeometryFormat;
import org.elasticsearch.common.geo.GeometryParser;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.geometry.Geometry;
import org.elasticsearch.geometry.Point;
import org.elasticsearch.index.mapper.Mapper.TypeParser.ParserContext;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
/** Base class for for spatial fields that only support indexing points */
public abstract class AbstractPointGeometryFieldMapper extends AbstractGeometryFieldMapper {
public static Parameter nullValueParam(Function initializer,
TriFunction parser,
Supplier def) {
return new Parameter<>("null_value", false, def, parser, initializer);
}
protected final ParsedPoint nullValue;
protected AbstractPointGeometryFieldMapper(String simpleName, MappedFieldType mappedFieldType,
MultiFields multiFields, Explicit ignoreMalformed,
Explicit ignoreZValue, ParsedPoint nullValue, CopyTo copyTo,
Indexer indexer, Parser parser) {
super(simpleName, mappedFieldType, ignoreMalformed, ignoreZValue, multiFields, copyTo, indexer, parser);
this.nullValue = nullValue;
}
@Override
public final boolean parsesArrayValue() {
return true;
}
public ParsedPoint getNullValue() {
return nullValue;
}
/** represents a Point that has been parsed by {@link PointParser} */
public interface ParsedPoint {
void validate(String fieldName);
void normalize(String fieldName);
void resetCoords(double x, double y);
Point asGeometry();
default boolean isNormalizable(double coord) {
return Double.isNaN(coord) == false && Double.isInfinite(coord) == false;
}
}
/** 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(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) throws IOException, ParseException {
if (parser.currentToken() == XContentParser.Token.START_ARRAY) {
XContentParser.Token token = parser.nextToken();
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(ignoreZValue, parser.doubleValue());
} else if (token != XContentParser.Token.END_ARRAY) {
throw new ElasticsearchParseException("field type does not accept > 3 dimensions");
}
point.resetCoords(x, y);
points.add(process(point));
} else {
while (token != XContentParser.Token.END_ARRAY) {
points.add(process(objectParser.apply(parser, point)));
point = pointSupplier.get();
token = parser.nextToken();
}
}
return points;
} else if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) {
return null;
} else {
return Collections.singletonList(nullValue);
}
} else {
return Collections.singletonList(process(objectParser.apply(parser, pointSupplier.get())));
}
}
@Override
public Object format(List
points, String format) {
List