All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.index.mapper.AbstractPointGeometryFieldMapper Maven / Gradle / Ivy

There is a newer version: 8.13.4
Show newest version
/*
 * 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 result = new ArrayList<>(); GeometryFormat geometryFormat = geometryParser.geometryFormat(format); for (ParsedPoint point : points) { Geometry geometry = point.asGeometry(); result.add(geometryFormat.toXContentAsObject(geometry)); } return result; } } }