package org.apache.lucene.spatial.composite;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.lucene.document.Field;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Query;
import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.spatial.query.SpatialOperation;
import org.apache.lucene.spatial.query.UnsupportedSpatialOperation;
import org.apache.lucene.spatial.serialized.SerializedDVStrategy;
import org.apache.lucene.spatial.util.ShapeValuesPredicate;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Shape;
public class CompositeSpatialStrategy extends SpatialStrategy {
private final RecursivePrefixTreeStrategy indexStrategy;
private final SerializedDVStrategy geometryStrategy;
private boolean optimizePredicates = true;
public CompositeSpatialStrategy(String fieldName,
RecursivePrefixTreeStrategy indexStrategy, SerializedDVStrategy geometryStrategy) {
super(indexStrategy.getSpatialContext(), fieldName);
this.indexStrategy = indexStrategy;
this.geometryStrategy = geometryStrategy;
}
public RecursivePrefixTreeStrategy getIndexStrategy() {
return indexStrategy;
}
public SerializedDVStrategy getGeometryStrategy() {
return geometryStrategy;
}
public boolean isOptimizePredicates() {
return optimizePredicates;
}
public void setOptimizePredicates(boolean optimizePredicates) {
this.optimizePredicates = optimizePredicates;
}
@Override
public Field[] createIndexableFields(Shape shape) {
List<Field> fields = new ArrayList<>();
Collections.addAll(fields, indexStrategy.createIndexableFields(shape));
Collections.addAll(fields, geometryStrategy.createIndexableFields(shape));
return fields.toArray(new Field[fields.size()]);
}
@Override
public DoubleValuesSource makeDistanceValueSource(Point queryPoint, double multiplier) {
throw new UnsupportedOperationException();
}
@Override
public Query makeQuery(SpatialArgs args) {
final SpatialOperation pred = args.getOperation();
if (pred == SpatialOperation.BBoxIntersects || pred == SpatialOperation.BBoxWithin) {
throw new UnsupportedSpatialOperation(pred);
}
if (pred == SpatialOperation.IsDisjointTo) {
throw new UnsupportedSpatialOperation(pred);
}
final ShapeValuesPredicate predicateValueSource =
new ShapeValuesPredicate(geometryStrategy.makeShapeValueSource(), pred, args.getShape());
if (pred == SpatialOperation.Intersects && optimizePredicates) {
final SpatialPrefixTree grid = indexStrategy.getGrid();
final int detailLevel = grid.getLevelForDistance(args.resolveDistErr(ctx, 0.0));
return new IntersectsRPTVerifyQuery(args.getShape(), indexStrategy.getFieldName(), grid,
detailLevel, indexStrategy.getPrefixGridScanLevel(), predicateValueSource);
} else {
SpatialArgs indexArgs;
if (pred == SpatialOperation.Contains) {
indexArgs = args;
} else {
indexArgs = new SpatialArgs(SpatialOperation.Intersects, args.getShape());
indexArgs.setDistErr(args.getDistErr());
indexArgs.setDistErrPct(args.getDistErrPct());
}
if (indexArgs.getDistErr() == null && indexArgs.getDistErrPct() == null) {
indexArgs.setDistErrPct(0.10);
}
final Query indexQuery = indexStrategy.makeQuery(indexArgs);
return new CompositeVerifyQuery(indexQuery, predicateValueSource);
}
}
}