http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/ElasticSearchSpatialIndexer.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/ElasticSearchSpatialIndexer.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/ElasticSearchSpatialIndexer.java index 5799d6a..e77e6fe 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/ElasticSearchSpatialIndexer.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/ElasticSearchSpatialIndexer.java @@ -1,5 +1,3 @@ -package org.qi4j.index.elasticsearch.extensions.spatial; - /* * Copyright 2014 Jiri Jetmar. * @@ -18,6 +16,8 @@ package org.qi4j.index.elasticsearch.extensions.spatial; * limitations under the License. */ +package org.qi4j.index.elasticsearch.extensions.spatial; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -31,72 +31,66 @@ import org.qi4j.index.elasticsearch.extensions.spatial.mappings.SpatialIndexMapp import org.qi4j.library.spatial.v2.projections.ProjectionsRegistry; import java.util.HashMap; +import java.util.ListIterator; import java.util.Map; +import java.util.Stack; -import static org.qi4j.index.elasticsearch.extensions.spatial.mappings.SpatialIndexMapper.*; -import static org.qi4j.library.spatial.v2.transformations.TTransformations.*; +import static org.qi4j.index.elasticsearch.extensions.spatial.mappings.SpatialIndexMapper.IndexMappingCache; +import static org.qi4j.library.spatial.v2.transformations.TTransformations.Transform; public final class ElasticSearchSpatialIndexer { private static final String EPSG_4326 = "EPSG:4326"; private static final String DefaultSupportedProjection = EPSG_4326; private static final double DefaultProjectionConversionPrecisionInMeters = 2.00; + private Module module; - public static void toJSON(ElasticSearchSupport support, TGeometry geometry, String property, String propertyWithDepth, JSONObject json, Module module) throws ElasticSearchIndexException { + private ElasticSearchSpatialIndexer() { + } + + public static void toJSON(ElasticSearchSupport support, TGeometry geometry, String property, String deepProperty, JSONObject json, Module module) throws ElasticSearchIndexException { // Spatial Mappings { - if (SpatialConfiguration.isEnabled(support.spatialConfiguration())) - { - SpatialIndexMapper.createIfNotExist(support, geometry, propertyWithDepth); - } - else throw new ElasticSearchIndexException("Spatial support is disabled. No spatial indexing available"); + if (SpatialConfiguration.isEnabled(support.spatialConfiguration())) { + SpatialIndexMapper.createIfNotExist(support, geometry, deepProperty); + } else throw new ElasticSearchIndexException("Spatial support is disabled. No spatial indexing available"); } // Spatial Transformations { - if (new ProjectionsRegistry().getCRS(geometry.getCRS()) == null) throw new ElasticSearchIndexException("Project with the CRS Identity " + geometry.getCRS() + " is unknown. Supported projections are JJ TODO"); - if (SpatialConfiguration.isIndexerProjectionConversionEnabled(support.spatialConfiguration())) - { + if (SpatialConfiguration.isIndexerProjectionConversionEnabled(support.spatialConfiguration())) { Transform(module).from(geometry).to(DefaultSupportedProjection, SpatialConfiguration.getIndexerProjectionConversionAccuracy(support.spatialConfiguration())); - } + } else if (!geometry.getCRS().equalsIgnoreCase(DefaultSupportedProjection)) + throw new ElasticSearchIndexException("Project with the CRS Identity " + geometry.getCRS() + " is not supported by ElasticSearch and projection conversion is " + + "disabled in the configuration."); } - try { - if (geometry instanceof TPoint) - { - if (IndexMappingCache.isMappedAsGeoPoint(support.index(), support.entitiesType(), propertyWithDepth)) - { - createESGeoPointIndexAsGeoPointValue(property, json, (TPoint) geometry); - } - else if (IndexMappingCache.isMappedAsGeoShape(support.index(), support.entitiesType(), propertyWithDepth)) - { - createESGeoPointIndexAsShapeValue(property, json, (TPoint) geometry); - } - else new ElasticSearchIndexException("No spatial mapping for property " + propertyWithDepth + " available."); - - } else if (geometry instanceof TMultiPoint) - { - createESGeoMultiPointAsShapeIndexValue(property, json, (TMultiPoint) geometry); - } else if (geometry instanceof TLineString) - { - createESGeoLineStringIndexValue(property, json, (TLineString) geometry); - } else if (geometry instanceof TPolygon) - { - createESGeoPolygonAsShapeIndexValue(property, json, (TPolygon) geometry); - } else if (geometry instanceof TMultiPolygon) - { - throw new ElasticSearchIndexException("JJ TODO"); - } else if (geometry instanceof TFeature) - { - throw new ElasticSearchIndexException("JJ TODO"); - } else if (geometry instanceof TFeatureCollection) - { - throw new ElasticSearchIndexException("JJ TODO"); + if (geometry.isPoint()) { + if (IndexMappingCache.isMappedAsGeoPoint(support.index(), support.entitiesType(), deepProperty)) { + createIndexPointAsGeoPointType(property, json, (TPoint) geometry); + } else if (IndexMappingCache.isMappedAsGeoShape(support.index(), support.entitiesType(), deepProperty)) { + createIndexPointAsGeoShapeType(property, json, (TPoint) geometry); + } else + new ElasticSearchIndexException("No spatial mapping for property " + deepProperty + " available."); + } else if (geometry.isMultiPoint()) { + createIndexMultiPoint(property, json, (TMultiPoint) geometry); + } else if (geometry.isLineString()) { + createIndexLineString(property, json, (TLineString) geometry); + } else if (geometry.isMultiLineString()) { + createIndexMultiLineString(property, json, (TMultiLineString) geometry); + } else if (geometry.isPolygon()) { + createIndexPolygon(property, json, (TPolygon) geometry); + } else if (geometry.isMultiPolygon()) { + createIndexMultiPolygon(property, json, (TMultiPolygon) geometry); + } else if (geometry.isFeature()) { + createIndexFeature(property, json, (TFeature) geometry); + } else if (geometry.isFeatureCollection()) { + createIndexFeatureCollection(property, json, (TFeatureCollection) geometry); } else new ElasticSearchIndexException("Unsupported Geometry : " + geometry.getClass()); } catch (JSONException _ex) { @@ -104,40 +98,36 @@ public final class ElasticSearchSpatialIndexer { } } + private static void createIndexMultiPoint(String property, JSONObject json, TMultiPoint tMultiPoint) throws JSONException { - private static void createESGeoMultiPointAsShapeIndexValue(String property, JSONObject json, TMultiPoint tMultiPoint) throws JSONException { - - Map tMultiPointMap = new HashMap(); - tMultiPointMap.put("type", "multipoint"); + Map tMultiPointMap = new HashMap(); + tMultiPointMap.put("type", "multipoint"); - JSONArray points = new JSONArray(); - for (int i = 0; i < tMultiPoint.getNumPoints(); i++) { - TPoint point = (TPoint) tMultiPoint.getGeometryN(i); - points.put(new JSONArray().put(point.y()).put(point.x())); - } + JSONArray points = new JSONArray(); + for (int i = 0; i < tMultiPoint.getNumPoints(); i++) { + TPoint point = (TPoint) tMultiPoint.getGeometryN(i); + points.put(new JSONArray().put(point.y()).put(point.x())); + } - tMultiPointMap.put("coordinates", points); - json.put(property, tMultiPointMap); + tMultiPointMap.put("coordinates", points); + json.put(property, tMultiPointMap); } - private static void createESGeoLineStringIndexValue(String property, JSONObject json, TLineString tLineString) throws JSONException { - - Map tLineStringMap = new HashMap(); - tLineStringMap.put("type", "linestring"); + private static void createIndexLineString(String property, JSONObject json, TLineString tLineString) throws JSONException { + Map tLineStringMap = new HashMap(); + tLineStringMap.put("type", "linestring"); - JSONArray points = new JSONArray(); - for (int i = 0; i < tLineString.getNumPoints(); i++) { - TPoint point = (TPoint) tLineString.getPointN(i); - points.put(new JSONArray().put(point.y()).put(point.x())); - } - - tLineStringMap.put("coordinates", points); - json.put(property, tLineStringMap); + JSONArray points = new JSONArray(); + for (int i = 0; i < tLineString.getNumPoints(); i++) { + TPoint point = (TPoint) tLineString.getPointN(i); + points.put(new JSONArray().put(point.y()).put(point.x())); + } + tLineStringMap.put("coordinates", points); + json.put(property, tLineStringMap); } - /** * !! ATTENTION !! * <p/> @@ -170,78 +160,187 @@ public final class ElasticSearchSpatialIndexer { * @param tPoint * @throws Exception */ - private static void createESGeoPointIndexAsGeoPointValue(String property, JSONObject json, TPoint tPoint) throws JSONException - { - Map tPointMap = new HashMap(); - tPointMap.put("lat", tPoint.y()); - tPointMap.put("lon", tPoint.x()); + private static void createIndexPointAsGeoPointType(String property, JSONObject json, TPoint tPoint) throws JSONException { + Map tPointMap = new HashMap(); + tPointMap.put("lat", tPoint.y()); + tPointMap.put("lon", tPoint.x()); - json.put(property, tPointMap); + json.put(property, tPointMap); } - private static void createESGeoPointIndexAsShapeValue(String property, JSONObject json, TPoint tPoint) throws JSONException { - Map tPointMap = new HashMap(); - // Lat = Y Long = X - tPointMap.put("type", "point"); - tPointMap.put("coordinates", new JSONArray().put(tPoint.x()).put(tPoint.y())); + private static void createIndexPointAsGeoShapeType(String property, JSONObject json, TPoint tPoint) throws JSONException { + Map tPointMap = new HashMap(); + tPointMap.put("type", "point"); + tPointMap.put("coordinates", new JSONArray().put(tPoint.x()).put(tPoint.y())); - json.put(property, tPointMap); + json.put(property, tPointMap); + } + private static void createIndexMultiLineString(String property, JSONObject json, TMultiLineString tMultiLineString) throws JSONException { + Map tMultiLineStringMap = new HashMap(); + tMultiLineStringMap.put("type", "multilinestring"); + + JSONArray coordinates = new JSONArray(); + + for (int i = 0; i < tMultiLineString.geometries().get().size(); i++) { + JSONArray p = new JSONArray(); + int nPoints = ((TLineString) tMultiLineString.getGeometryN(i)).getNumPoints(); + + JSONArray line = new JSONArray(); + for (int j = 0; j < nPoints; j++) { + JSONArray xy = new JSONArray(); + xy.put(((TLineString) tMultiLineString.getGeometryN(i)).getPointN(j).x()); + xy.put(((TLineString) tMultiLineString.getGeometryN(i)).getPointN(j).y()); + line.put(xy); + } + coordinates.put(line); + } + tMultiLineStringMap.put("coordinates", coordinates); + json.put(property, tMultiLineStringMap); } + private static void createIndexPolygon(String property, JSONObject json, TPolygon tPolygon) throws JSONException { + if (!tPolygon.shell().get().isValid()) + throw new ElasticSearchIndexException("Polygon shell has to be closed - first and last point must match. "); - private static void createESGeoPolygonAsShapeIndexValue(String property, JSONObject json, TPolygon tPolygon) throws JSONException { + Map tPolygonMap = new HashMap(); + tPolygonMap.put("type", "polygon"); + JSONArray coordinates = new JSONArray(); - if (!tPolygon.shell().get().isValid()) - throw new ElasticSearchIndexException("Polygon shell has to be closed - first and last point must match. "); + // shell + { + JSONArray shell = new JSONArray(); + for (int i = 0; i < tPolygon.shell().get().getNumPoints(); i++) { + JSONArray p = new JSONArray(); - Map tPolygonMap = new HashMap(); - tPolygonMap.put("type", "polygon"); + p.put(tPolygon.shell().get().getPointN(i).x()); + p.put(tPolygon.shell().get().getPointN(i).y()); - JSONArray coordinates = new JSONArray(); + shell.put(p); + } + coordinates.put(shell); + } + // wholes + { + for (int i = 0; i < tPolygon.holes().get().size(); i++) { + JSONArray whole = new JSONArray(); + // TLinearRing whole = tPolygon.holes().get().get(i); + for (int j = 0; j < tPolygon.holes().get().get(i).getNumPoints(); j++) { + if (!tPolygon.holes().get().get(i).isValid()) + throw new ElasticSearchIndexException("Polygon whole has to be closed - first and last point must match. "); - // shell - { - JSONArray shell = new JSONArray(); - for (int i = 0; i < tPolygon.shell().get().getNumPoints(); i++) { JSONArray p = new JSONArray(); - p.put(tPolygon.shell().get().getPointN(i).x()); - p.put(tPolygon.shell().get().getPointN(i).y()); + p.put(tPolygon.holes().get().get(i).getPointN(j).x()); + p.put(tPolygon.holes().get().get(i).getPointN(j).y()); - shell.put(p); + whole.put(p); } - coordinates.put(shell); + coordinates.put(whole); } + } - // wholes - { - for (int i = 0; i < tPolygon.holes().get().size(); i++) { - JSONArray whole = new JSONArray(); - // TLinearRing whole = tPolygon.holes().get().get(i); - for (int j = 0; j < tPolygon.holes().get().get(i).getNumPoints(); j++) { - if (!tPolygon.holes().get().get(i).isValid()) - throw new ElasticSearchIndexException("Polygon whole has to be closed - first and last point must match. "); + tPolygonMap.put("coordinates", coordinates); + json.put(property, tPolygonMap); + } - JSONArray p = new JSONArray(); + private static void createIndexMultiPolygon(String property, JSONObject json, TMultiPolygon tMultiPolygon) throws JSONException { + Map tMultiPolygonMap = new HashMap(); + tMultiPolygonMap.put("type", "multipolygon"); + JSONArray coordinates = new JSONArray(); - p.put(tPolygon.holes().get().get(i).getPointN(j).x()); - p.put(tPolygon.holes().get().get(i).getPointN(j).y()); + for (int i = 0; i < tMultiPolygon.geometries().get().size(); i++) { + JSONObject _json = new JSONObject(); + createIndexPolygon(property, _json, (TPolygon) tMultiPolygon.getGeometryN(i)); + coordinates.put(((JSONObject) _json.get(property)).get("coordinates")); + } + tMultiPolygonMap.put("coordinates", coordinates); + json.put(property, tMultiPolygonMap); + } - whole.put(p); - } - coordinates.put(whole); - } + private static void createIndexFeatureCollection(String property, JSONObject json, TFeatureCollection tFeatureCollection) throws JSONException { + Map tFeatureMap = new HashMap(); + tFeatureMap.put("type", "geometrycollection"); + + JSONArray geometries = new JSONArray(); + JSONObject _json = new JSONObject(); + + for (TGeometry tGeometry : tFeatureCollection.geometries().get()) { + TFeature tFeature = (TFeature) tGeometry; + switch (tFeature.asGeometry().getType()) { + case POINT: + createIndexPointAsGeoShapeType(property, _json, (TPoint) tFeature.asGeometry()); + break; + case MULTIPOINT: + createIndexMultiPoint(property, _json, (TMultiPoint) tFeature.asGeometry()); + break; + case LINESTRING: + createIndexLineString(property, _json, (TLineString) tFeature.asGeometry()); + break; + case MULTILINESTRING: + createIndexMultiLineString(property, _json, (TMultiLineString) tFeature.asGeometry()); + break; + case POLYGON: + createIndexPolygon(property, _json, (TPolygon) tFeature.asGeometry()); + break; + case MULTIPOLYGON: + createIndexMultiPolygon(property, _json, (TMultiPolygon) tFeature.asGeometry()); + break; } + geometries.put(_json.get(property)); + } - tPolygonMap.put("coordinates", coordinates); - json.put(property, tPolygonMap); + tFeatureMap.put("geometries", geometries); + json.put(property, tFeatureMap); } + private static void createIndexFeature(String property, JSONObject json, TFeature tFeature) throws JSONException { + Map tFeatureMap = new HashMap(); + tFeatureMap.put("type", "geometrycollection"); + + JSONArray geometries = new JSONArray(); + JSONObject _json = new JSONObject(); + + switch (tFeature.asGeometry().getType()) { + case POINT: + createIndexPointAsGeoShapeType(property, _json, (TPoint) tFeature.asGeometry()); + break; + case MULTIPOINT: + createIndexMultiPoint(property, _json, (TMultiPoint) tFeature.asGeometry()); + break; + case LINESTRING: + createIndexLineString(property, _json, (TLineString) tFeature.asGeometry()); + break; + case MULTILINESTRING: + createIndexMultiLineString(property, _json, (TMultiLineString) tFeature.asGeometry()); + break; + case POLYGON: + createIndexPolygon(property, _json, (TPolygon) tFeature.asGeometry()); + break; + case MULTIPOLYGON: + createIndexMultiPolygon(property, _json, (TMultiPolygon) tFeature.asGeometry()); + break; + } + + geometries.put(_json.get(property)); - private ElasticSearchSpatialIndexer() { + tFeatureMap.put("geometries", geometries); + json.put(property, tFeatureMap); + } + + public static String spatialMappingPropertyName(Stack<String> stack) { + ListIterator<String> it = stack.listIterator(); + if (!it.hasNext()) return ""; + StringBuilder sb = new StringBuilder(); + for (; ; ) { + String s = it.next(); + sb.append(s); + if (!it.hasNext()) + return sb.toString(); + sb.append('.'); + } } }
http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialConfiguration.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialConfiguration.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialConfiguration.java index 5c0bca2..d9c37ff 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialConfiguration.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialConfiguration.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2014, Jiri Jetmar. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package org.qi4j.index.elasticsearch.extensions.spatial.configuration; import org.qi4j.api.common.Optional; @@ -7,92 +21,90 @@ import org.qi4j.api.value.ValueComposite; /** * Created by jj on 22.12.14. */ -public class SpatialConfiguration -{ - - public static enum INDEXING_METHOD {GEO_POINT, GEO_SHAPE} +public class SpatialConfiguration { - public interface Configuration extends ValueComposite - { - @Optional Property<Boolean> Enabled(); - @Optional Property<IndexerConfiguration> Indexer(); - @Optional Property<FinderConfiguration> Finder (); + public static boolean isEnabled(Configuration config) { + return config.Enabled().get().booleanValue(); } - public interface IndexerConfiguration extends ValueComposite - { - // Property<INDEXING_METHOD> Type(); - @Optional Property<IndexingMethod> Method(); - @Optional Property<ProjectionSupport> Projection(); + public static INDEXING_METHOD getMethod(Configuration config) { + return config.Indexer().get().Method().get().Type().get(); } - public interface FinderConfiguration extends ValueComposite - { - @Optional Property<ProjectionSupport> Projection(); + public static boolean isMethodGeoPoint(Configuration config) { + return config.Indexer().get().Method().get().Type().get() == INDEXING_METHOD.GEO_POINT ? true : false; } - public interface IndexingMethod extends ValueComposite - { - @Optional Property<INDEXING_METHOD> Type(); - @Optional Property<String> Precision(); + public static boolean isMethodGeoShape(Configuration config) { + return config.Indexer().get().Method().get().Type().get() == INDEXING_METHOD.GEO_SHAPE ? true : false; } - public interface ProjectionSupport extends ValueComposite - { - @Optional Property<Boolean> ConversionEnabled(); - @Optional Property<String> ConversionAccuracy(); + public static boolean isIndexerProjectionConversionEnabled(Configuration config) { + return config.Indexer().get().Projection().get().ConversionEnabled().get().booleanValue(); } - - public static boolean isEnabled(Configuration config) - { - return config.Enabled().get().booleanValue(); + public static double getIndexerProjectionConversionAccuracy(Configuration config) { + // return config.Indexer().get().Projection().get(). + return 2; } - public static INDEXING_METHOD getMethod(Configuration config) - { - return config.Indexer().get().Method().get().Type().get(); + public static String getIndexerPrecision(Configuration config) { + return config.Indexer().get().Method().get().Precision().get(); } - public static boolean isMethodGeoPoint(Configuration config) - { - return config.Indexer().get().Method().get().Type().get() == INDEXING_METHOD.GEO_POINT ? true : false; - // return config.Indexer().get().Type().get() == INDEXING_METHOD.GEO_POINT ? true : false; + public static boolean isFinderProjectionConversionEnabled(Configuration config) { + return config.Finder().get().Projection().get().ConversionEnabled().get().booleanValue(); } - public static boolean isMethodGeoShape(Configuration config) - { - return config.Indexer().get().Method().get().Type().get() == INDEXING_METHOD.GEO_SHAPE ? true : false; - //return config.Indexer().get().Type().get() == INDEXING_METHOD.GEO_SHAPE ? true : false; + public static double getFinderProjectionConversionAccuracy(Configuration config) { + return 2; } - public String getMethodAccuracy(Configuration config) - { + public String getMethodAccuracy(Configuration config) { return config.Indexer().get().Method().get().Precision().get(); } - public static boolean isIndexerProjectionConversionEnabled(Configuration config) - { - return config.Indexer().get().Projection().get().ConversionEnabled().get().booleanValue(); + public static enum INDEXING_METHOD {GEO_POINT, GEO_SHAPE} + + public interface Configuration extends ValueComposite { + @Optional + Property<Boolean> Enabled(); + + @Optional + Property<IndexerConfiguration> Indexer(); + + @Optional + Property<FinderConfiguration> Finder(); } - public static double getIndexerProjectionConversionAccuracy(Configuration config) - { - // return config.Indexer().get().Projection().get(). - return 2; + public interface IndexerConfiguration extends ValueComposite { + @Optional + Property<IndexingMethod> Method(); + + @Optional + Property<ProjectionSupport> Projection(); } - public static boolean isFinderProjectionConversionEnabled(Configuration config) - { - return config.Finder().get().Projection().get().ConversionEnabled().get().booleanValue(); + public interface FinderConfiguration extends ValueComposite { + @Optional + Property<ProjectionSupport> Projection(); } - public static double getFinderProjectionConversionAccuracy(Configuration config) - { - return 2; + public interface IndexingMethod extends ValueComposite { + @Optional + Property<INDEXING_METHOD> Type(); + + @Optional + Property<String> Precision(); } + public interface ProjectionSupport extends ValueComposite { + @Optional + Property<Boolean> ConversionEnabled(); + @Optional + Property<String> ConversionAccuracy(); + } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialExceptionConfiguration.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialExceptionConfiguration.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialExceptionConfiguration.java deleted file mode 100644 index 421375a..0000000 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialExceptionConfiguration.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.qi4j.index.elasticsearch.extensions.spatial.configuration; - -import org.qi4j.api.common.Optional; -import org.qi4j.api.configuration.ConfigurationComposite; -import org.qi4j.api.property.Property; - -/** - * Created by jj on 25.12.14. - */ -public interface SpatialExceptionConfiguration extends ConfigurationComposite -{ - - @Optional - Property<Integer> index(); -} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialFunctionsSupportMatrix.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialFunctionsSupportMatrix.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialFunctionsSupportMatrix.java index c51d31a..fdc29ba 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialFunctionsSupportMatrix.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/configuration/SpatialFunctionsSupportMatrix.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2014, Jiri Jetmar. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package org.qi4j.index.elasticsearch.extensions.spatial.configuration; import com.google.common.collect.HashBasedTable; @@ -5,8 +19,8 @@ import com.google.common.collect.Table; import org.qi4j.api.geometry.TPoint; import org.qi4j.api.geometry.TPolygon; import org.qi4j.api.geometry.internal.TGeometry; -import org.qi4j.api.query.grammar.extensions.spatial.convert.ST_GeomFromTextSpecification; import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_DisjointSpecification; +import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_IntersectsSpecification; import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_WithinSpecification; import java.lang.reflect.Array; @@ -17,102 +31,112 @@ import java.util.List; /** * Created by jj on 22.12.14. */ -public class SpatialFunctionsSupportMatrix -{ - +public class SpatialFunctionsSupportMatrix { private static Boolean OrderBy = true; private static Class<? extends TGeometry> AnyGeometry = TGeometry.class; - public static Class WKT = ST_GeomFromTextSpecification.class; - - public static enum INDEX_MAPPING_TPOINT_METHOD {TPOINT_AS_GEOPOINT, TPOINT_AS_GEOSHAPE} - - private static final Table<String, SpatialConfiguration.INDEXING_METHOD, ConfigurationEntry> SPATIAL_SUPPORT_MATRIX = HashBasedTable.create(); - - static { // ST_Within - // supports(enable(ST_WithinSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), enable(OrderBy), INDEX_MAPPING_TPOINT_METHOD.TPOINT_AS_GEOPOINT); - // supports(enable(ST_WithinSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), disable(OrderBy), INDEX_MAPPING_TPOINT_METHOD.TPOINT_AS_GEOSHAPE); - supports(enable(ST_WithinSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), enable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_POINT); supports(enable(ST_WithinSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), disable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_SHAPE); + // ST_Disjoint + supports(disable(ST_DisjointSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), enable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_POINT); + supports(enable(ST_DisjointSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), disable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_SHAPE); - // supports(ST_WithinV2.class, propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), OrderBy, INDEXING_METHOD.TPOINT_AS_GEOPOINT); - //supports(ST_WithinV2.class, propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), disable(OrderBy), INDEXING_METHOD.TPOINT_AS_GEOSHAPE); - // ST_Disjoint - supports(enable(ST_DisjointSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), enable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_POINT); - supports(enable(ST_DisjointSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), disable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_SHAPE); + // ST_Intersects + supports(disable(ST_IntersectsSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), enable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_POINT); + supports(enable(ST_IntersectsSpecification.class), propertyOf(AnyGeometry), filterOf(TPoint.class, TPolygon.class), disable(OrderBy), SpatialConfiguration.INDEXING_METHOD.GEO_SHAPE); + } - // ST_Disjoint - // supports(not(ST_Disjoint.class), AnyGeometry, AnyGeometry, OrderBy, INDEXING_METHOD.TPOINT_AS_GEOPOINT); - // supports(ST_Disjoint.class, TGeometry.class, TGeometry.class, not(OrderBy), INDEXING_METHOD.TPOINT_AS_GEOSHAPE); + public static boolean isSupported(Class expression, Class<? extends TGeometry> geometryOfProperty, Class<? extends TGeometry> geometryOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method, Boolean verifyOrderBy) { + System.out.println(SPATIAL_SUPPORT_MATRIX.toString()); - // ST_Intersects - // supports(not(ST_Intersects.class), AnyGeometry, AnyGeometry, OrderBy, INDEXING_METHOD.TPOINT_AS_GEOPOINT); - // supports(not(ST_Intersects.class), TGeometry.class, TGeometry.class, not(OrderBy), INDEXING_METHOD.TPOINT_AS_GEOSHAPE); + System.out.println("isSupported " + expression + " " + geometryOfProperty + " " + geometryOfFilter + " Type " + method); + System.out.println("Contains " + SPATIAL_SUPPORT_MATRIX.contains(expression.getName(), method)); + if (SPATIAL_SUPPORT_MATRIX.contains(expression.getName(), method)) + return SPATIAL_SUPPORT_MATRIX.get(expression.getName(), method).isSupported(geometryOfProperty, geometryOfFilter, orderBy, verifyOrderBy); + else + return false; + } + + public static boolean isSupported(Class expression, Class<? extends TGeometry> geometryOfProperty, Class<? extends TGeometry> geometryOfFilter, SpatialConfiguration.INDEXING_METHOD method) { + return isSupported(expression, geometryOfProperty, geometryOfFilter, false, method, false); + } + + private static void supports(Class expression, Class<? extends TGeometry> geometryOfProperty, Class<? extends TGeometry> geometryOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method) { + supports + ( + expression, + (Class<? extends TGeometry>[]) Array.newInstance(geometryOfProperty, 1), + (Class<? extends TGeometry>[]) Array.newInstance(geometryOfFilter, 1), + orderBy, method + ); } + private static void supports(Class expression, Class<? extends TGeometry>[] geometriesOfProperty, Class<? extends TGeometry>[] geometriesOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method) { + SPATIAL_SUPPORT_MATRIX.put(expression.getName(), method, new ConfigurationEntry(geometriesOfProperty, geometriesOfFilter, orderBy, method)); + } + private static Class disable(Class clazz) { + return Object.class; + } + private static Class enable(Class clazz) { + return clazz; + } - private static class ConfigurationEntry - { + private static Boolean disable(Boolean bool) { + return false; + } + + private static Boolean enable(Boolean bool) { + return true; + } + + private static Class<? extends TGeometry>[] filterOf(Class<? extends TGeometry>... geometryOfFilters) { + return geometryOfFilters; + } + + private static Class<? extends TGeometry>[] propertyOf(Class<? extends TGeometry>... geometryOfProperty) { + return geometryOfProperty; + } + + private static class ConfigurationEntry { private SpatialConfiguration.INDEXING_METHOD method; private Boolean orderBy; - private List<Class<? extends TGeometry>> supportedPropertyGeometries = new LinkedList<>(); - private List<Class<? extends TGeometry>> supportedFilterGeometries = new LinkedList<>(); + private List<Class<? extends TGeometry>> supportedPropertyGeometries = new LinkedList<>(); + private List<Class<? extends TGeometry>> supportedFilterGeometries = new LinkedList<>(); - public ConfigurationEntry(Class<? extends TGeometry>[] geometriesOfProperty, Class<? extends TGeometry>[] geometriesOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method) - { + public ConfigurationEntry(Class<? extends TGeometry>[] geometriesOfProperty, Class<? extends TGeometry>[] geometriesOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method) { this.supportedPropertyGeometries = Arrays.asList(geometriesOfProperty); - this.supportedFilterGeometries = Arrays.asList(geometriesOfFilter); + this.supportedFilterGeometries = Arrays.asList(geometriesOfFilter); this.orderBy = orderBy; - this.method = method; + this.method = method; } - public boolean isSupported( Class<? extends TGeometry> geometryOfProperty, Class<? extends TGeometry> geometryOfFilter, Boolean orderBy, Boolean verifyOrderBy) - { + public boolean isSupported(Class<? extends TGeometry> geometryOfProperty, Class<? extends TGeometry> geometryOfFilter, Boolean orderBy, Boolean verifyOrderBy) { System.out.println("geometryOfProperty " + geometryOfProperty); System.out.println("geometryOfFilter " + geometryOfFilter); System.out.println("OrderBy " + orderBy); - if (supportsProperty(geometryOfProperty) && supportsFilter(geometryOfFilter)) - { + if (supportsProperty(geometryOfProperty) && supportsFilter(geometryOfFilter)) { if (verifyOrderBy) { if (this.orderBy && orderBy) return true; if (this.orderBy && !orderBy) return true; if (!this.orderBy && !orderBy) return true; if (!this.orderBy && orderBy) return false; } else return true; - } - else return false; - + } else return false; return false; - - -/** - if (supportsProperty(geometryOfProperty) && supportsFilter(geometryOfFilter)) - if (orderBy && (this.orderBy != orderBy)) // <- when we validate against orderBy, the it has to match. Otherwise ignore. - return false; - else - if (!orderBy && (this.orderBy != orderBy) ) - return true; - else - return false; - else - return false; - */ } - private boolean supportsProperty(Class<? extends TGeometry> geometryOfProperty) - { - if (supportedPropertyGeometries.contains(TGeometry.class) ) + private boolean supportsProperty(Class<? extends TGeometry> geometryOfProperty) { + if (supportedPropertyGeometries.contains(TGeometry.class)) return true; else if (supportedPropertyGeometries.contains(geometryOfProperty)) return true; @@ -120,9 +144,8 @@ public class SpatialFunctionsSupportMatrix return false; } - private boolean supportsFilter(Class<? extends TGeometry> geometryOfFilter) - { - if (supportedFilterGeometries.contains(TGeometry.class) ) + private boolean supportsFilter(Class<? extends TGeometry> geometryOfFilter) { + if (supportedFilterGeometries.contains(TGeometry.class)) return true; else if (supportedFilterGeometries.contains(geometryOfFilter)) return true; @@ -130,73 +153,4 @@ public class SpatialFunctionsSupportMatrix return false; } } - - - public static boolean isSupported(Class expression, Class<? extends TGeometry> geometryOfProperty,Class<? extends TGeometry> geometryOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method, Boolean verifyOrderBy ) - { - System.out.println(SPATIAL_SUPPORT_MATRIX.toString()); - - System.out.println("isSupported " +expression + " " + geometryOfProperty + " " + geometryOfFilter + " Type " + method); - System.out.println("Contains " + SPATIAL_SUPPORT_MATRIX.contains(expression.getName(), method) ); - if (SPATIAL_SUPPORT_MATRIX.contains(expression.getName(), method)) - return SPATIAL_SUPPORT_MATRIX.get(expression.getName(), method).isSupported(geometryOfProperty, geometryOfFilter, orderBy, verifyOrderBy); - else - return false; - } - - - public static boolean isSupported(Class expression, Class<? extends TGeometry> geometryOfProperty,Class<? extends TGeometry> geometryOfFilter, SpatialConfiguration.INDEXING_METHOD method ) - { - return isSupported(expression, geometryOfProperty, geometryOfFilter, false, method, false); - } - - private static void supports (Class expression, Class<? extends TGeometry> geometryOfProperty,Class<? extends TGeometry> geometryOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method) - { - supports - ( - expression, - (Class < ?extends TGeometry >[])Array.newInstance(geometryOfProperty, 1), - (Class<? extends TGeometry>[]) Array.newInstance(geometryOfFilter, 1), - orderBy, method - ); - } - - private static void supports (Class expression, Class<? extends TGeometry>[] geometriesOfProperty,Class<? extends TGeometry>[] geometriesOfFilter, Boolean orderBy, SpatialConfiguration.INDEXING_METHOD method) - { - SPATIAL_SUPPORT_MATRIX.put(expression.getName(), method, new ConfigurationEntry(geometriesOfProperty, geometriesOfFilter,orderBy, method)); - } - - - - private static Class disable(Class clazz) - { - return Object.class; - } - private static Class enable(Class clazz) - { - return clazz; - } - - - private static Boolean disable(Boolean bool) - { - return false; - } - - private static Boolean enable(Boolean bool) - { - return true; - } - - - - private static Class<? extends TGeometry>[] filterOf(Class<? extends TGeometry>... geometryOfFilters) - { - return geometryOfFilters; - } - - private static Class<? extends TGeometry>[] propertyOf(Class<? extends TGeometry>... geometryOfProperty) - { - return geometryOfProperty; - } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ConvertFinderSupport.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ConvertFinderSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ConvertFinderSupport.java index 8906f02..a6e4f11 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ConvertFinderSupport.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ConvertFinderSupport.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2014, Jiri Jetmar. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package org.qi4j.index.elasticsearch.extensions.spatial.functions.convert; import org.elasticsearch.index.query.FilterBuilder; @@ -12,58 +26,45 @@ import org.qi4j.spi.query.EntityFinderException; import java.util.HashMap; import java.util.Map; -/** - * Created by jj on 20.11.14. - */ -public class ConvertFinderSupport implements ElasticSearchSpatialFinder.SpatialQuerySpecSupport { - private static final Map<Class<?>, ConvertFinderSupport.ConvertSpecification> SPATIAL_CONVERT_OPERATIONS = new HashMap<>( 2 ); +public class ConvertFinderSupport implements ElasticSearchSpatialFinder.SpatialQuerySpecSupport { - static - { + private static final Map<Class<?>, ConvertFinderSupport.ConvertSpecification> SPATIAL_CONVERT_OPERATIONS = new HashMap<>(2); + static { SPATIAL_CONVERT_OPERATIONS.put(ST_GeomFromTextSpecification.class, new ST_GeometryFromText()); } + private Module module; + private ElasticSearchSupport support; - public static interface ConvertSpecification extends ElasticSearchSpatialFinder.ModuleHelper - { - void processSpecification(FilterBuilder filterBuilder, SpatialConvertSpecification<?> spec, Map<String, Object> variables) throws EntityFinderException; - } - - - - Module module; - ElasticSearchSupport support; - - public void setModule(Module module, ElasticSearchSupport support) { - + public ElasticSearchSpatialFinder.SpatialQuerySpecSupport support(Module module, ElasticSearchSupport support) { this.module = module; this.support = support; - } + return this; + } + public void processSpecification(FilterBuilder filterBuilder, + Specification<?> spec, + Map<String, Object> variables) + throws EntityFinderException { - public void processSpecification( FilterBuilder filterBuilder, - // SpatialPredicatesSpecification<?> spec, - Specification<?> spec, - Map<String, Object> variables ) - throws EntityFinderException - { - System.out.println("ElasticSearchSpatialPredicateFinderSupport::processSpecification() " + spec.getClass() ); - - - if( SPATIAL_CONVERT_OPERATIONS.get( spec.getClass() ) != null ) { - - ConvertSpecification ConvertSpecification = SPATIAL_CONVERT_OPERATIONS.get( spec.getClass()); - ConvertSpecification.setModule(module, support); - ConvertSpecification.processSpecification(filterBuilder, (SpatialConvertSpecification)spec, variables); - + if (SPATIAL_CONVERT_OPERATIONS.get(spec.getClass()) != null) { + SPATIAL_CONVERT_OPERATIONS.get(spec.getClass()).support(module, support).processSpecification(filterBuilder, (SpatialConvertSpecification) spec, variables); } else { - throw new UnsupportedOperationException( "Spatial predicates specification unsupported by Elastic Search " + throw new UnsupportedOperationException("Spatial predicates specification unsupported by Elastic Search " + "(New Query API support missing?): " - + spec.getClass() + ": " + spec ); + + spec.getClass() + ": " + spec); } } + public interface Support { + ConvertSpecification support(Module module, ElasticSearchSupport support); + } + + public static interface ConvertSpecification extends Support { + void processSpecification(FilterBuilder filterBuilder, SpatialConvertSpecification<?> spec, Map<String, Object> variables) throws EntityFinderException; + } + } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ST_GeometryFromText.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ST_GeometryFromText.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ST_GeometryFromText.java index dbb7035..04722c5 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ST_GeometryFromText.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/convert/ST_GeometryFromText.java @@ -1,7 +1,23 @@ +/* + * Copyright (c) 2014, Jiri Jetmar. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package org.qi4j.index.elasticsearch.extensions.spatial.functions.convert; import org.elasticsearch.index.query.FilterBuilder; import org.qi4j.api.query.grammar.extensions.spatial.convert.SpatialConvertSpecification; +import org.qi4j.api.structure.Module; +import org.qi4j.index.elasticsearch.ElasticSearchSupport; import org.qi4j.index.elasticsearch.extensions.spatial.internal.AbstractElasticSearchSpatialFunction; import org.qi4j.spi.query.EntityFinderException; @@ -9,27 +25,20 @@ import java.util.Map; import static org.qi4j.library.spatial.v2.conversions.TConversions.Convert; -/** - * Created by jj on 20.11.14. - */ -public class ST_GeometryFromText extends AbstractElasticSearchSpatialFunction implements ConvertFinderSupport.ConvertSpecification { - - - public void processSpecification(FilterBuilder filterBuilder, SpatialConvertSpecification<?> spec, Map<String, Object> variables) throws EntityFinderException - { - System.out.println("ST_GeometryFromTextFunction()"); - -try { - spec.setGeometry(Convert(module).from(spec.property()).toTGeometry()); - - // return Convert(module).from(spec.property()).toTGeometry(); - - // return spec.convert(module); -} catch(Exception _ex) { - _ex.printStackTrace(); -} +public class ST_GeometryFromText extends AbstractElasticSearchSpatialFunction implements ConvertFinderSupport.ConvertSpecification { + public void processSpecification(FilterBuilder filterBuilder, SpatialConvertSpecification<?> spec, Map<String, Object> variables) throws EntityFinderException { + try + { + spec.setGeometry(Convert(module).from(spec.property()).toTGeometry()); + } catch (Exception _ex) { + throw new EntityFinderException(_ex); + } + } - // return null; + public ConvertFinderSupport.ConvertSpecification support(Module module, ElasticSearchSupport support) { + this.module = module; + this.support = support; + return this; } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/PredicateFinderSupport.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/PredicateFinderSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/PredicateFinderSupport.java index 2adcb64..d0e3766 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/PredicateFinderSupport.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/PredicateFinderSupport.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2014, Jiri Jetmar. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package org.qi4j.index.elasticsearch.extensions.spatial.functions.predicates; import org.elasticsearch.index.query.FilterBuilder; @@ -14,62 +28,49 @@ import org.qi4j.spi.query.EntityFinderException; import java.util.HashMap; import java.util.Map; -/** - * Created by jj on 19.11.14. - */ -public class PredicateFinderSupport implements ElasticSearchSpatialFinder.SpatialQuerySpecSupport { - - - private static final Map<Class<?>, PredicateFinderSupport.PredicateSpecification> SPATIAL_PREDICATE_OPERATIONS = new HashMap<>( 3 ); - - public static interface PredicateSpecification extends ElasticSearchSpatialFinder.ModuleHelper - { - void processSpecification(FilterBuilder filterBuilder, SpatialPredicatesSpecification<?> spec, Map<String, Object> variables) throws EntityFinderException; - } - - static - { - SPATIAL_PREDICATE_OPERATIONS.put(ST_WithinSpecification.class, new ST_Within()); - SPATIAL_PREDICATE_OPERATIONS.put(ST_DisjointSpecification.class, new ST_DisjointV3()); - SPATIAL_PREDICATE_OPERATIONS.put(ST_IntersectsSpecification.class, new ST_Intersects()); - } +public class PredicateFinderSupport implements ElasticSearchSpatialFinder.SpatialQuerySpecSupport { + private static final Map<Class<?>, PredicateFinderSupport.PredicateSpecification> SPATIAL_PREDICATE_OPERATIONS = new HashMap<>(3); - Module module; - ElasticSearchSupport support; + private Module module; + private ElasticSearchSupport support; - public void setModule(Module module, ElasticSearchSupport support) - { + public ElasticSearchSpatialFinder.SpatialQuerySpecSupport support(Module module, ElasticSearchSupport support) { this.module = module; this.support = support; - } + return this; + } + public void processSpecification(FilterBuilder filterBuilder, + Specification<?> spec, + Map<String, Object> variables) + throws EntityFinderException { - public void processSpecification( FilterBuilder filterBuilder, - // SpatialPredicatesSpecification<?> spec, - Specification<?> spec, - Map<String, Object> variables ) - throws EntityFinderException - { - System.out.println("ElasticSearchSpatialPredicateFinderSupport::processSpecification() " + spec.getClass() ); - - - if( SPATIAL_PREDICATE_OPERATIONS.get( spec.getClass() ) != null ) { - - PredicateSpecification PredicateSpecification = SPATIAL_PREDICATE_OPERATIONS.get( spec.getClass()); - PredicateSpecification.setModule(module, support); - PredicateSpecification.processSpecification(filterBuilder, (SpatialPredicatesSpecification)spec, variables); - + if (SPATIAL_PREDICATE_OPERATIONS.get(spec.getClass()) != null) { + SPATIAL_PREDICATE_OPERATIONS.get(spec.getClass()).support(module, support).processSpecification(filterBuilder, (SpatialPredicatesSpecification) spec, variables); } else { - throw new UnsupportedOperationException( "Spatial predicates specification unsupported by Elastic Search " + throw new UnsupportedOperationException("Spatial predicates specification unsupported by Elastic Search " + "(New Query API support missing?): " - + spec.getClass() + ": " + spec ); - + + spec.getClass() + ": " + spec); } } + public interface Support { + PredicateSpecification support(Module module, ElasticSearchSupport support); + } + + + public static interface PredicateSpecification extends Support { + void processSpecification(FilterBuilder filterBuilder, SpatialPredicatesSpecification<?> spec, Map<String, Object> variables) throws EntityFinderException; + } + static { + SPATIAL_PREDICATE_OPERATIONS.put(ST_WithinSpecification.class, new ST_Within()); + SPATIAL_PREDICATE_OPERATIONS.put(ST_DisjointSpecification.class, new ST_Disjoint()); + SPATIAL_PREDICATE_OPERATIONS.put(ST_IntersectsSpecification.class, new ST_Intersects()); + } + } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Disjoint.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Disjoint.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Disjoint.java index e72eead..b0164b4 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Disjoint.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Disjoint.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2014, Jiri Jetmar. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package org.qi4j.index.elasticsearch.extensions.spatial.functions.predicates; import org.elasticsearch.common.geo.ShapeRelation; @@ -9,78 +23,41 @@ import org.qi4j.api.geometry.TPolygon; import org.qi4j.api.geometry.internal.TGeometry; import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_DisjointSpecification; import org.qi4j.api.query.grammar.extensions.spatial.predicate.SpatialPredicatesSpecification; +import org.qi4j.api.structure.Module; +import org.qi4j.index.elasticsearch.ElasticSearchSupport; import org.qi4j.index.elasticsearch.extensions.spatial.internal.AbstractElasticSearchSpatialFunction; import org.qi4j.spi.query.EntityFinderException; import java.util.Map; -import static org.elasticsearch.index.query.FilterBuilders.*; +import static org.elasticsearch.index.query.FilterBuilders.notFilter; + -/** - * Created by jj on 19.11.14. - */ public class ST_Disjoint extends AbstractElasticSearchSpatialFunction implements PredicateFinderSupport.PredicateSpecification { + public void processSpecification(FilterBuilder filterBuilder, + SpatialPredicatesSpecification<?> spec, + Map<String, Object> variables) + throws EntityFinderException { + TGeometry geomOfFilterProperty = resolveGeometry(filterBuilder, spec, module); + + if (!isValid(spec)) + throw new EntityFinderException(spec.getClass() + " expression invalid."); + + if (!isMapped(spec.property())) + throw new EntityFinderException(spec.getClass() + " expression invalid. No spatial mapping available for property " + spec.property()); + + if (!isSupported(spec, geomOfFilterProperty)) + throw new EntityFinderException(spec.getClass() + " expression unsupported by ElasticSearch. Pls specify a supported expression."); - public void processSpecification( FilterBuilder filterBuilder, - SpatialPredicatesSpecification<?> spec, - Map<String, Object> variables ) - throws EntityFinderException - { - if ((spec.value() == null && spec.operator() == null)) - throw new EntityFinderException("Insufficient data provided. ST_Disjoint specification requires " + - "valid filter geometry of type " + TGeometry.class.getSimpleName()); - - System.out.println("ST_Disjoint"); - - TGeometry filterGeometry = resolveGeometry(filterBuilder,spec, module); - - /** - * When the geometry used in the ST_Disjoint expression is of type TPoint and a distance is specified, e.g. - * - * TPoint filterGeometry = TPoint(module).x(..).y(..); - * ST_Disjoint (templateFor(x.class).propertyOfTypeTPoint(), filterGeometry, 1, TUnit.METER) - * - * then a ES GeoDistanceFilter together with a negotiation (notFilter) is used. - * - */ - - if (isMappedAsGeoPoint(spec.property())) - throw new EntityFinderException("ST_Disjoint can not be used on values with geo_point mappings. Pls use geo_shape mappings."); - - // if (Mappings(support).onIndex(support.index()).andType(support.entitiesType()).isGeoPoint(spec.property().toString())) - // throw new EntityFinderException("ST_Disjoint can not be used on values with geo_point mappings. Pls use geo_shape mappings."); - - - /** - * When the template property is of type TPoint then the filter property has to have an area. - * Currently only filter geometries of type TPolygon are supported. E.g. - * - * TPolygon polygon = TPolygon(module).shell(..) - * ST_Within (templateFor(x.class).propertyOfTypeTPoint(), polygon); - * - * - */ - else if (isPropertyOfTypeTPoint(spec.property())) - { - - if (filterGeometry instanceof TPolygon) - { - /** - * This must not happen, but in case the expression is defined using WTK like : - * - * ST_Within (templateFor(x.class).propertyOfTypeTPoint(), - * POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)), - * 1, TUnit.METER) // <- This is invalid !! - * - * we have to check it here. - * - */ - if (((ST_DisjointSpecification)spec).getDistance() > 0) + if (isPropertyOfType(TPoint.class, spec.property()) && isMappedAsGeoShape(spec.property())) { + if (geomOfFilterProperty instanceof TPolygon) { + + if (((ST_DisjointSpecification) spec).getDistance() > 0) throw new EntityFinderException("Invalid ST_Disjoint expression. A " + TPolygon.class.getSimpleName() + " can " + "not be combined with distance."); - TPolygon polygonFilter = (TPolygon)verifyProjection(filterGeometry); + TPolygon polygonFilter = (TPolygon) verifyProjection(geomOfFilterProperty); GeoPolygonFilterBuilder geoPolygonFilterBuilder = FilterBuilders.geoPolygonFilter(spec.property().toString()); @@ -88,54 +65,23 @@ public class ST_Disjoint extends AbstractElasticSearchSpatialFunction implements TPoint point = polygonFilter.shell().get().getPointN(i); geoPolygonFilterBuilder.addPoint(point.x(), point.y()); } - addFilter(notFilter(geoPolygonFilterBuilder), filterBuilder); // TODO NOT + addFilter(notFilter(geoPolygonFilterBuilder), filterBuilder); + } else if (geomOfFilterProperty instanceof TPoint && ((ST_DisjointSpecification) spec).getDistance() > 0) { + double radiusInMeters = convertDistanceToMeters(((ST_DisjointSpecification) spec).getDistance(), ((ST_DisjointSpecification) spec).getUnit()); + TPolygon polygonizedCircleFilter = polygonizeCircle((TPoint) verifyProjection(geomOfFilterProperty), radiusInMeters); + addFilter(createShapeFilter(spec.property().toString(), polygonizedCircleFilter, ShapeRelation.DISJOINT), filterBuilder); } - else - throw new EntityFinderException("Invalid ST_Disjoint expression. Unsupported type " + filterGeometry.getType() + - " On properties of type " + TPoint.class.getSimpleName() + - " only filters of type distance or polygon are supported."); - } - else - { - /** - * In all other cases we are using a shape filter. - */ - addFilter(createShapeFilter(spec.property().toString(), filterGeometry, ShapeRelation.DISJOINT), filterBuilder); + } else { + addFilter(createShapeFilter(spec.property().toString(), geomOfFilterProperty, ShapeRelation.DISJOINT), filterBuilder); } } + public PredicateFinderSupport.PredicateSpecification support(Module module, ElasticSearchSupport support) { + this.module = module; + this.support = support; - - - - - - - - - - - - - public void _processSpecification( FilterBuilder filterBuilder, - SpatialPredicatesSpecification<?> spec, - Map<String, Object> variables ) - throws EntityFinderException - { - if (spec.value() == null && spec.operator() == null) - throw new UnsupportedOperationException("ST_Within specification ...todo :" - + spec.getClass() + ": " + spec); - - System.out.println("ST_DisjointFunction Spec"); - - try { - TGeometry geometry = resolveGeometry(filterBuilder,spec, module); - addFilter(createShapeFilter(spec.property().toString(), geometry, ShapeRelation.DISJOINT), filterBuilder); - } catch(Exception _ex) { - _ex.printStackTrace(); - } + return this; } - } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV2.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV2.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV2.java deleted file mode 100644 index 97754c1..0000000 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV2.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.qi4j.index.elasticsearch.extensions.spatial.functions.predicates; - -import com.spatial4j.core.distance.DistanceUtils; -import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.index.query.FilterBuilder; -import org.elasticsearch.index.query.FilterBuilders; -import org.elasticsearch.index.query.GeoPolygonFilterBuilder; -import org.qi4j.api.geometry.TPoint; -import org.qi4j.api.geometry.TPolygon; -import org.qi4j.api.geometry.internal.TCircle; -import org.qi4j.api.geometry.internal.TGeometry; -import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_DisjointSpecification; -import org.qi4j.api.query.grammar.extensions.spatial.predicate.SpatialPredicatesSpecification; -import org.qi4j.index.elasticsearch.extensions.spatial.internal.AbstractElasticSearchSpatialFunction; -import org.qi4j.spi.query.EntityFinderException; - -import java.util.Map; - -import static org.elasticsearch.index.query.FilterBuilders.notFilter; - -/** - * Created by jj on 23.12.14. - */ -public class ST_DisjointV2 extends AbstractElasticSearchSpatialFunction implements PredicateFinderSupport.PredicateSpecification -{ - public void processSpecification(FilterBuilder filterBuilder, - SpatialPredicatesSpecification<?> spec, - Map<String, Object> variables) - throws EntityFinderException - { - TGeometry geomOfFilterProperty = resolveGeometry(filterBuilder, spec, module); - - if (!isValid(spec)) - throw new EntityFinderException(spec.getClass() + " expression invalid."); - - if (!isMapped(spec.property())) - throw new EntityFinderException(spec.getClass() + " expression invalid. No spatial mapping available for property " + spec.property()); - - if (!isSupported(spec, geomOfFilterProperty)) - throw new EntityFinderException(spec.getClass() + " expression unsupported by ElasticSearch. Pls specify a supported expression."); - - - if (isPropertyOfType(TPoint.class, spec.property()) && isMappedAsGeoShape(spec.property())) - { - if (geomOfFilterProperty instanceof TPolygon) - { - /** - * This must not happen, but in case the expression is defined using WTK like : - * - * ST_Within (templateFor(x.class).propertyOfTypeTPoint(), - * POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)), - * 1, TUnit.METER) // <- This is invalid !! - * - * we have to check it here. - * - */ - if (((ST_DisjointSpecification)spec).getDistance() > 0) - throw new EntityFinderException("Invalid ST_Disjoint expression. A " + TPolygon.class.getSimpleName() + " can " + - "not be combined with distance."); - - TPolygon polygonFilter = (TPolygon)verifyProjection(geomOfFilterProperty); - - GeoPolygonFilterBuilder geoPolygonFilterBuilder = FilterBuilders.geoPolygonFilter(spec.property().toString()); - - for (int i = 0; i < polygonFilter.shell().get().getNumPoints(); i++) { - TPoint point = polygonFilter.shell().get().getPointN(i); - geoPolygonFilterBuilder.addPoint(point.x(), point.y()); - } - addFilter(notFilter(geoPolygonFilterBuilder), filterBuilder); // TODO NOT - } - else if (geomOfFilterProperty instanceof TPoint && ((ST_DisjointSpecification)spec).getDistance() > 0 ) - { - - double distanceMeters = convertDistanceToMeters(((ST_DisjointSpecification)spec).getDistance() , ((ST_DisjointSpecification)spec).getUnit()); - System.out.println("Distance in Meters " + distanceMeters); - double distanceDegrees = DistanceUtils.dist2Degrees(distanceMeters, DistanceUtils.EARTH_MEAN_RADIUS_KM * 1000); - // This is a special case. We are using polygon substitution to support a circle. ATTENTION - this is just a approximation !! - TPoint circlePoint = (TPoint)verifyProjection(geomOfFilterProperty); - TCircle tCircle = module.newValueBuilder(TCircle.class).prototype().of(circlePoint, distanceDegrees); - TPolygon polygonizedCircleFilter = tCircle.polygonize(360); - addFilter(createShapeFilter(spec.property().toString(), polygonizedCircleFilter, ShapeRelation.DISJOINT), filterBuilder); - } - - - } - else - { - /** - * In all other cases we are using a shape filter. - */ - addFilter(createShapeFilter(spec.property().toString(), geomOfFilterProperty, ShapeRelation.DISJOINT), filterBuilder); - } - - - } -} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV3.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV3.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV3.java deleted file mode 100644 index c89804d..0000000 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_DisjointV3.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.qi4j.index.elasticsearch.extensions.spatial.functions.predicates; - -import com.spatial4j.core.distance.DistanceUtils; -import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.index.query.FilterBuilder; -import org.elasticsearch.index.query.FilterBuilders; -import org.elasticsearch.index.query.GeoPolygonFilterBuilder; -import org.qi4j.api.geometry.TPoint; -import org.qi4j.api.geometry.TPolygon; -import org.qi4j.api.geometry.internal.TCircle; -import org.qi4j.api.geometry.internal.TGeometry; -import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_DisjointSpecification; -import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_WithinSpecification; -import org.qi4j.api.query.grammar.extensions.spatial.predicate.SpatialPredicatesSpecification; -import org.qi4j.index.elasticsearch.extensions.spatial.internal.AbstractElasticSearchSpatialFunction; -import org.qi4j.spi.query.EntityFinderException; - -import java.util.Map; - -import static org.elasticsearch.index.query.FilterBuilders.andFilter; -import static org.elasticsearch.index.query.FilterBuilders.notFilter; -import static org.elasticsearch.index.query.FilterBuilders.termFilter; - -/** - * Created by jj on 23.12.14. - */ -public class ST_DisjointV3 extends AbstractElasticSearchSpatialFunction implements PredicateFinderSupport.PredicateSpecification -{ - public void processSpecification(FilterBuilder filterBuilder, - SpatialPredicatesSpecification<?> spec, - Map<String, Object> variables) - throws EntityFinderException - { - TGeometry geomOfFilterProperty = resolveGeometry(filterBuilder, spec, module); - - if (!isValid(spec)) - throw new EntityFinderException(spec.getClass() + " expression invalid."); - - if (!isMapped(spec.property())) - throw new EntityFinderException(spec.getClass() + " expression invalid. No spatial mapping available for property " + spec.property()); - - if (!isSupported(spec, geomOfFilterProperty)) - throw new EntityFinderException(spec.getClass() + " expression unsupported by ElasticSearch. Pls specify a supported expression."); - - - - - /** - * When the geometry used in the ST_Within expression is of type TPoint and a distance is specified, e.g. - * - * TPoint point = TPoint(module).x(..).y(..); - * ST_Within (templateFor(x.class).propertyOfTypeTPoint(), point, 1, TUnit.METER) - * - * then a ES GeoDistanceFilter is used. - * - */ - if ( - isTPoint(geomOfFilterProperty) && - isMappedAsGeoPoint(spec.property()) && - ((ST_DisjointSpecification) spec).getDistance() > 0 - ) - { - addFilter(andFilter(notFilter(createGeoDistanceFilter - ( - spec.property().toString(), - (TPoint) verifyProjection(geomOfFilterProperty), - ((ST_DisjointSpecification) spec).getDistance(), - ((ST_DisjointSpecification) spec).getUnit() - )), null), - // )termFilter( "point.type", "point" )), - filterBuilder - ); - } - - - - - else if (isPropertyOfType(TPoint.class, spec.property()) && isMappedAsGeoShape(spec.property())) - { - if (geomOfFilterProperty instanceof TPolygon) - { - /** - * This must not happen, but in case the expression is defined using WTK like : - * - * ST_Within (templateFor(x.class).propertyOfTypeTPoint(), - * POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)), - * 1, TUnit.METER) // <- This is invalid !! - * - * we have to check it here. - * - */ - if (((ST_DisjointSpecification)spec).getDistance() > 0) - throw new EntityFinderException("Invalid ST_Disjoint expression. A " + TPolygon.class.getSimpleName() + " can " + - "not be combined with distance."); - - TPolygon polygonFilter = (TPolygon)verifyProjection(geomOfFilterProperty); - - GeoPolygonFilterBuilder geoPolygonFilterBuilder = FilterBuilders.geoPolygonFilter(spec.property().toString()); - - for (int i = 0; i < polygonFilter.shell().get().getNumPoints(); i++) { - TPoint point = polygonFilter.shell().get().getPointN(i); - geoPolygonFilterBuilder.addPoint(point.x(), point.y()); - } - addFilter(notFilter(geoPolygonFilterBuilder), filterBuilder); // TODO NOT - } - else if (geomOfFilterProperty instanceof TPoint && ((ST_DisjointSpecification)spec).getDistance() > 0 ) - { - - double distanceMeters = convertDistanceToMeters(((ST_DisjointSpecification)spec).getDistance() , ((ST_DisjointSpecification)spec).getUnit()); - System.out.println("Distance in Meters " + distanceMeters); - double distanceDegrees = DistanceUtils.dist2Degrees(distanceMeters, DistanceUtils.EARTH_MEAN_RADIUS_KM * 1000); - // This is a special case. We are using polygon substitution to support a circle. ATTENTION - this is just a approximation !! - TPoint circlePoint = (TPoint)verifyProjection(geomOfFilterProperty); - TCircle tCircle = module.newValueBuilder(TCircle.class).prototype().of(circlePoint, distanceDegrees); - TPolygon polygonizedCircleFilter = tCircle.polygonize(360); - addFilter(createShapeFilter(spec.property().toString(), polygonizedCircleFilter, ShapeRelation.DISJOINT), filterBuilder); - } - - - } - else - { - /** - * In all other cases we are using a shape filter. - */ - addFilter(createShapeFilter(spec.property().toString(), geomOfFilterProperty, ShapeRelation.DISJOINT), filterBuilder); - } - - - } -} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/9d71ec3c/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Intersects.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Intersects.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Intersects.java index b3aae19..a85c66e 100644 --- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Intersects.java +++ b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/extensions/spatial/functions/predicates/ST_Intersects.java @@ -1,40 +1,92 @@ +/* + * Copyright (c) 2014, Jiri Jetmar. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package org.qi4j.index.elasticsearch.extensions.spatial.functions.predicates; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.index.query.FilterBuilder; +import org.elasticsearch.index.query.FilterBuilders; +import org.elasticsearch.index.query.GeoPolygonFilterBuilder; import org.qi4j.api.geometry.TPoint; +import org.qi4j.api.geometry.TPolygon; import org.qi4j.api.geometry.internal.TGeometry; +import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_DisjointSpecification; +import org.qi4j.api.query.grammar.extensions.spatial.predicate.ST_IntersectsSpecification; import org.qi4j.api.query.grammar.extensions.spatial.predicate.SpatialPredicatesSpecification; +import org.qi4j.api.structure.Module; +import org.qi4j.index.elasticsearch.ElasticSearchSupport; import org.qi4j.index.elasticsearch.extensions.spatial.internal.AbstractElasticSearchSpatialFunction; import org.qi4j.spi.query.EntityFinderException; import java.util.Map; -/** - * Created by jj on 04.12.14. - */ -public class ST_Intersects extends AbstractElasticSearchSpatialFunction implements PredicateFinderSupport.PredicateSpecification -{ +import static org.elasticsearch.index.query.FilterBuilders.notFilter; + + +public class ST_Intersects extends AbstractElasticSearchSpatialFunction implements PredicateFinderSupport.PredicateSpecification { public void processSpecification(FilterBuilder filterBuilder, SpatialPredicatesSpecification<?> spec, Map<String, Object> variables) throws EntityFinderException { - if ((spec.value() == null && spec.operator() == null)) - throw new EntityFinderException("Insufficient data provided. ST_Intersects specification requires " + - "valid filter geometry of type " + TGeometry.class.getSimpleName()); + TGeometry geomOfFilterProperty = resolveGeometry(filterBuilder, spec, module); - TGeometry filterGeometry = resolveGeometry(filterBuilder, spec, module); + System.out.println("Spec " + spec); - if (isPropertyOfTypeTPoint(spec.property())) - { - throw new EntityFinderException("Invalid ST_Intersects expression. Property on type " + - TPoint.class.getSimpleName() + " not supported."); - } - else - { - addFilter(createShapeFilter(spec.property().toString(), filterGeometry, ShapeRelation.INTERSECTS), filterBuilder); + if (!isValid(spec)) + throw new EntityFinderException(spec.getClass() + " expression invalid."); + + if (!isMapped(spec.property())) + throw new EntityFinderException(spec.getClass() + " expression invalid. No spatial mapping available for property " + spec.property()); + + if (!isSupported(spec, geomOfFilterProperty)) + throw new EntityFinderException(spec.getClass() + " expression unsupported by ElasticSearch. Pls specify a supported expression."); + + + if (isPropertyOfType(TPoint.class, spec.property())) { + if (geomOfFilterProperty instanceof TPolygon) { + + if (((ST_DisjointSpecification) spec).getDistance() > 0) + throw new EntityFinderException("Invalid ST_Disjoint expression. A " + TPolygon.class.getSimpleName() + " can " + + "not be combined with distance."); + + TPolygon polygonFilter = (TPolygon) verifyProjection(geomOfFilterProperty); + + GeoPolygonFilterBuilder geoPolygonFilterBuilder = FilterBuilders.geoPolygonFilter(spec.property().toString()); + + for (int i = 0; i < polygonFilter.shell().get().getNumPoints(); i++) { + TPoint point = polygonFilter.shell().get().getPointN(i); + geoPolygonFilterBuilder.addPoint(point.x(), point.y()); + } + addFilter(notFilter(geoPolygonFilterBuilder), filterBuilder); + } else if (geomOfFilterProperty instanceof TPoint && ((ST_IntersectsSpecification) spec).getDistance() > 0) { + double radiusInMeters = convertDistanceToMeters(((ST_IntersectsSpecification) spec).getDistance(), ((ST_IntersectsSpecification) spec).getUnit()); + TPolygon polygonizedCircleFilter = polygonizeCircle((TPoint) verifyProjection(geomOfFilterProperty), radiusInMeters); + addFilter(createShapeFilter(spec.property().toString(), polygonizedCircleFilter, ShapeRelation.INTERSECTS), filterBuilder); + } + } else { + + addFilter(createShapeFilter(spec.property().toString(), geomOfFilterProperty, ShapeRelation.INTERSECTS), filterBuilder); } } + + public PredicateFinderSupport.PredicateSpecification support(Module module, ElasticSearchSupport support) { + this.module = module; + this.support = support; + + return this; + } + }
