From e3cb97c6bd7de3cf1c2cb5c7afcb951ce27503f9 Mon Sep 17 00:00:00 2001 From: Lyn Elisa Goltz Date: Thu, 18 Jul 2024 11:20:44 +0200 Subject: [PATCH] #9885 (#32) - consider all geometry properties if propName is missing --- .../filter/AbstractWhereBuilder.java | 68 ++++++++++++++----- .../sqldialect/filter/PropertyNameMapper.java | 6 +- .../sqldialect/mssql/MSSQLWhereBuilder.java | 19 ++---- .../mssql/MSSQLWhereBuilderTest.java | 12 ++-- .../sqldialect/oracle/OracleWhereBuilder.java | 8 +-- .../postgis/PostGISWhereBuilder.java | 28 +++----- .../persistence/shape/H2WhereBuilder.java | 4 +- .../persistence/sql/SQLFeatureStore.java | 10 +-- .../sql/SQLPropertyNameMapper.java | 48 ++++++++----- .../persistence/sql/xpath/MappedXPath.java | 38 ++++------- .../sql/SQLPropertyNameMapperTest.java | 24 +++++-- .../eo/mapping/EOPropertyNameMapper.java | 4 +- .../persistence/ISOPropertyNameMapper.java | 7 +- 13 files changed, 155 insertions(+), 121 deletions(-) diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java index c417a2d948..c63352baf8 100644 --- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java +++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/AbstractWhereBuilder.java @@ -678,8 +678,24 @@ protected SQLOperation toProtoSQL(LogicalOperator op) throws UnmappableException * @throws FilterEvaluationException if the filter contains invalid * {@link ValueReference}s */ - protected abstract SQLOperation toProtoSQL(SpatialOperator op) - throws UnmappableException, FilterEvaluationException; + protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException, FilterEvaluationException { + List propNameExprs = toProtoSQLSpatial(op.getPropName()); + checkIfExpressionsAreSpatial(propNameExprs, op.getPropName()); + + SQLOperationBuilder builder = new SQLOperationBuilder(BOOLEAN); + boolean isFirst = true; + for (SQLExpression propNameExpr : propNameExprs) { + if (!isFirst) { + builder.add(" OR "); + } + toProtoSql(op, propNameExpr, builder); + isFirst = false; + } + return builder.toOperation(); + } + + protected abstract void toProtoSql(SpatialOperator op, SQLExpression propNameExpr, SQLOperationBuilder builder) + throws FilterEvaluationException, UnmappableException; /** * Translates the given {@link TemporalOperator} into an {@link SQLOperation}. @@ -916,22 +932,25 @@ protected SQLExpression toProtoSQL(ValueReference propName) throws UnmappableExc * @throws FilterEvaluationException if the filter contains invalid * {@link ValueReference}s */ - protected SQLExpression toProtoSQLSpatial(ValueReference propName) + protected List toProtoSQLSpatial(ValueReference propName) throws FilterEvaluationException, UnmappableException { - SQLExpression sql = null; - PropertyNameMapping propMapping = mapper.getSpatialMapping(propName, aliasManager); - if (propMapping != null) { - propNameMappingList.add(propMapping); - if (propMapping instanceof ConstantPropertyNameMapping) { - // TODO get rid of ConstantPropertyNameMapping - PrimitiveType pt = new PrimitiveType(STRING); - PrimitiveValue value = new PrimitiveValue("" + ((ConstantPropertyNameMapping) propMapping).getValue(), - pt); - PrimitiveParticleConverter converter = new DefaultPrimitiveConverter(pt, null, false); - sql = new SQLArgument(value, converter); - } - else { - sql = new SQLColumn(propMapping.getTableAlias(), propMapping.getColumn(), propMapping.getConverter()); + List sql = new ArrayList<>(); + List propMappings = mapper.getSpatialMappings(propName, aliasManager); + if (!propMappings.isEmpty()) { + for (PropertyNameMapping propMapping : propMappings) { + propNameMappingList.add(propMapping); + if (propMapping instanceof ConstantPropertyNameMapping) { + // TODO get rid of ConstantPropertyNameMapping + PrimitiveType pt = new PrimitiveType(STRING); + PrimitiveValue value = new PrimitiveValue( + "" + ((ConstantPropertyNameMapping) propMapping).getValue(), pt); + PrimitiveParticleConverter converter = new DefaultPrimitiveConverter(pt, null, false); + sql.add(new SQLArgument(value, converter)); + } + else { + sql.add(new SQLColumn(propMapping.getTableAlias(), propMapping.getColumn(), + propMapping.getConverter())); + } } } else { @@ -1015,4 +1034,19 @@ protected String getStringValueFromFunction(Expression pattern) return ((PrimitiveValue) value).getAsText(); } + private void checkIfExpressionsAreSpatial(List sqlExpressions, ValueReference propName) + throws FilterEvaluationException { + for (SQLExpression sqlExpression : sqlExpressions) + checkIfExpressionIsSpatial(sqlExpression, propName); + } + + protected void checkIfExpressionIsSpatial(SQLExpression sqlExpression, ValueReference propName) + throws FilterEvaluationException { + if (!sqlExpression.isSpatial()) { + String msg = "Cannot evaluate spatial operator on database. Targeted property name '" + propName + + "' does not denote a spatial column."; + throw new FilterEvaluationException(msg); + } + } + } \ No newline at end of file diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/PropertyNameMapper.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/PropertyNameMapper.java index e173ab3d81..69ae4ff50d 100644 --- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/PropertyNameMapper.java +++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-commons/src/main/java/org/deegree/sqldialect/filter/PropertyNameMapper.java @@ -37,6 +37,8 @@ import org.deegree.filter.FilterEvaluationException; import org.deegree.filter.expression.ValueReference; +import java.util.List; + /** * Implementations provide {@link ValueReference} to table/column mappings for * {@link AbstractWhereBuilder} implementations. @@ -56,10 +58,10 @@ public interface PropertyNameMapper { * invalid * @throws UnmappableException */ - public PropertyNameMapping getMapping(ValueReference propName, TableAliasManager aliasManager) + PropertyNameMapping getMapping(ValueReference propName, TableAliasManager aliasManager) throws FilterEvaluationException, UnmappableException; - public PropertyNameMapping getSpatialMapping(ValueReference propName, TableAliasManager aliasManager) + List getSpatialMappings(ValueReference propName, TableAliasManager aliasManager) throws FilterEvaluationException, UnmappableException; } diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/main/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilder.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/main/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilder.java index 39bc05d6e6..51929709ee 100644 --- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/main/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilder.java +++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/main/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilder.java @@ -34,9 +34,6 @@ ----------------------------------------------------------------------------*/ package org.deegree.sqldialect.mssql; -import static java.sql.Types.BOOLEAN; -import static org.deegree.commons.tom.primitive.BaseType.DECIMAL; - import org.deegree.commons.tom.primitive.PrimitiveType; import org.deegree.commons.tom.primitive.PrimitiveValue; import org.deegree.commons.tom.sql.DefaultPrimitiveConverter; @@ -74,6 +71,9 @@ import java.util.List; +import static java.sql.Types.BOOLEAN; +import static org.deegree.commons.tom.primitive.BaseType.DECIMAL; + /** * {@link AbstractWhereBuilder} implementation for Microsoft SQL Server databases. * @@ -162,17 +162,7 @@ private String replaceAdditionalMsSqlServerSpecialChars(String sqlEncoded) { } @Override - protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException, FilterEvaluationException { - - SQLOperationBuilder builder = new SQLOperationBuilder(BOOLEAN); - - SQLExpression propNameExpr = toProtoSQLSpatial(op.getPropName()); - if (!propNameExpr.isSpatial()) { - String msg = "Cannot evaluate spatial operator on database. Targeted property name '" + op.getPropName() - + "' does not denote a spatial column."; - throw new FilterEvaluationException(msg); - } - + protected void toProtoSql(SpatialOperator op, SQLExpression propNameExpr, SQLOperationBuilder builder) { ICRS storageCRS = propNameExpr.getCRS(); int srid = propNameExpr.getSRID() != null ? Integer.parseInt(propNameExpr.getSRID()) : 0; @@ -269,7 +259,6 @@ protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException break; } } - return builder.toOperation(); } private SQLExpression toProtoSQL(Geometry geom, ICRS targetCRS, int srid) { diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/test/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilderTest.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/test/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilderTest.java index ea470a0fb6..051e45170e 100644 --- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/test/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilderTest.java +++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-mssql/src/test/java/org/deegree/sqldialect/mssql/MSSQLWhereBuilderTest.java @@ -54,6 +54,9 @@ import org.junit.Before; import org.junit.Test; +import java.util.Collections; +import java.util.List; + /** * Tests for {@link MSSQLWhereBuilder}. * @@ -70,14 +73,13 @@ public void setup() throws FilterEvaluationException, UnmappableException { PropertyNameMapper mapper = new PropertyNameMapper() { @Override - public PropertyNameMapping getSpatialMapping(ValueReference propName, TableAliasManager aliasManager) - throws FilterEvaluationException, UnmappableException { - return new PropertyNameMapping(null, null, propName.getAsText(), "table"); + public List getSpatialMappings(ValueReference propName, + TableAliasManager aliasManager) { + return Collections.singletonList(new PropertyNameMapping(null, null, propName.getAsText(), "table")); } @Override - public PropertyNameMapping getMapping(ValueReference propName, TableAliasManager aliasManager) - throws FilterEvaluationException, UnmappableException { + public PropertyNameMapping getMapping(ValueReference propName, TableAliasManager aliasManager) { return new PropertyNameMapping(null, null, propName.getAsText(), "table"); } }; diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-oracle/src/main/java/org/deegree/sqldialect/oracle/OracleWhereBuilder.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-oracle/src/main/java/org/deegree/sqldialect/oracle/OracleWhereBuilder.java index e368068b0a..4ccda26b94 100644 --- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-oracle/src/main/java/org/deegree/sqldialect/oracle/OracleWhereBuilder.java +++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-oracle/src/main/java/org/deegree/sqldialect/oracle/OracleWhereBuilder.java @@ -129,11 +129,7 @@ class OracleWhereBuilder extends AbstractWhereBuilder { } @Override - protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException, FilterEvaluationException { - - SQLOperationBuilder builder = new SQLOperationBuilder(BOOLEAN); - SQLExpression propNameExpr = toProtoSQLSpatial(op.getPropName()); - + protected void toProtoSql(SpatialOperator op, SQLExpression propNameExpr, SQLOperationBuilder builder) { switch (op.getSubType()) { case BBOX: BBOX bbox = (BBOX) op; @@ -178,8 +174,6 @@ protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException appendDWithinOperation(builder, propNameExpr, ((Beyond) op).getGeometry(), ((Beyond) op).getDistance()); break; } - - return builder.toOperation(); } /** diff --git a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java index 5caaf35b4a..93dd51104b 100644 --- a/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java +++ b/deegree-core/deegree-core-sqldialect/deegree-sqldialect-postgis/src/main/java/org/deegree/sqldialect/postgis/PostGISWhereBuilder.java @@ -82,6 +82,8 @@ import org.deegree.time.position.TimePosition; import org.deegree.time.primitive.GenericTimeInstant; import org.deegree.time.primitive.GenericTimePeriod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * {@link AbstractWhereBuilder} implementation for PostGIS databases. @@ -90,6 +92,8 @@ */ public class PostGISWhereBuilder extends AbstractWhereBuilder { + private static final Logger LOG = LoggerFactory.getLogger(PostGISWhereBuilder.class); + private final boolean useLegacyPredicates; /** @@ -187,13 +191,8 @@ private SQLOperation getOperationFromBuilder(PropertyIsLike op, SQLExpression pr } @Override - protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException, FilterEvaluationException { - - SQLOperationBuilder builder = new SQLOperationBuilder(BOOLEAN); - - SQLExpression propNameExpr = toProtoSQLSpatial(op.getPropName()); - checkIfExpressionIsSpatial(propNameExpr, op.getPropName()); - + protected void toProtoSql(SpatialOperator op, SQLExpression propNameExpr, SQLOperationBuilder builder) + throws FilterEvaluationException, UnmappableException { ICRS storageCRS = propNameExpr.getCRS(); int srid = propNameExpr.getSRID() != null ? Integer.parseInt(propNameExpr.getSRID()) : -1; @@ -376,7 +375,6 @@ protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException break; } } - return builder.toOperation(); } protected SQLOperation toProtoSQL(TemporalOperator op) throws UnmappableException, FilterEvaluationException { @@ -495,7 +493,10 @@ private SQLExpression toProtoSQL(Geometry geom, ICRS targetCRS, int srid) throws private SQLExpression toProtoSqlSecondParameter(SpatialOperator spatialOperator, ICRS storageCRS, int srid) throws FilterEvaluationException, UnmappableException { if (spatialOperator.getValueReference() != null) { - SQLExpression sqlExpression = toProtoSQLSpatial(spatialOperator.getValueReference()); + List sqlExpressions = toProtoSQLSpatial(spatialOperator.getValueReference()); + if (sqlExpressions.size() > 1) + LOG.warn("Multiple spatial geometry mappings as second parameter are currently not supported."); + SQLExpression sqlExpression = sqlExpressions.get(0); checkIfExpressionIsSpatial(sqlExpression, spatialOperator.getValueReference()); return sqlExpression; } @@ -575,13 +576,4 @@ private boolean isTimeInstant(Expression parameter2) { return parameter2 instanceof Literal && ((Literal) parameter2).getValue() instanceof GenericTimeInstant; } - private void checkIfExpressionIsSpatial(SQLExpression sqlExpression, ValueReference propName) - throws FilterEvaluationException { - if (!sqlExpression.isSpatial()) { - String msg = "Cannot evaluate spatial operator on database. Targeted property name '" + propName - + "' does not denote a spatial column."; - throw new FilterEvaluationException(msg); - } - } - } \ No newline at end of file diff --git a/deegree-datastores/deegree-featurestores/deegree-featurestore-shape/src/main/java/org/deegree/feature/persistence/shape/H2WhereBuilder.java b/deegree-datastores/deegree-featurestores/deegree-featurestore-shape/src/main/java/org/deegree/feature/persistence/shape/H2WhereBuilder.java index 4a84dd9e63..c04d1c7d6a 100644 --- a/deegree-datastores/deegree-featurestores/deegree-featurestore-shape/src/main/java/org/deegree/feature/persistence/shape/H2WhereBuilder.java +++ b/deegree-datastores/deegree-featurestores/deegree-featurestore-shape/src/main/java/org/deegree/feature/persistence/shape/H2WhereBuilder.java @@ -55,6 +55,7 @@ import org.deegree.sqldialect.filter.expression.SQLColumn; import org.deegree.sqldialect.filter.expression.SQLExpression; import org.deegree.sqldialect.filter.expression.SQLOperation; +import org.deegree.sqldialect.filter.expression.SQLOperationBuilder; /** * @author Andreas Schmitz @@ -80,7 +81,8 @@ public H2WhereBuilder(SQLDialect dialect, OperatorFilter filter, SortProperty[] } @Override - protected SQLOperation toProtoSQL(SpatialOperator op) throws UnmappableException, FilterEvaluationException { + protected void toProtoSql(SpatialOperator op, SQLExpression propNameExpr, SQLOperationBuilder builder) + throws UnmappableException { throw new UnmappableException("Spatial operators are currently not mappable in h2."); } diff --git a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLFeatureStore.java b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLFeatureStore.java index d9934d05cf..b46dfd0a2c 100644 --- a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLFeatureStore.java +++ b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLFeatureStore.java @@ -48,6 +48,7 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -1669,8 +1670,7 @@ private AbstractWhereBuilder getWhereBuilderBlob(OperatorFilter filter, Connecti final String srid = detectConfiguredSrid(); PropertyNameMapper mapper = new PropertyNameMapper() { @Override - public PropertyNameMapping getMapping(ValueReference propName, TableAliasManager aliasManager) - throws FilterEvaluationException, UnmappableException { + public PropertyNameMapping getMapping(ValueReference propName, TableAliasManager aliasManager) { GeometryStorageParams geometryParams = new GeometryStorageParams(blobMapping.getCRS(), srid, CoordinateDimension.DIM_2); GeometryMapping bboxMapping = new GeometryMapping(null, false, new DBField(blobMapping.getBBoxColumn()), @@ -1680,9 +1680,9 @@ public PropertyNameMapping getMapping(ValueReference propName, TableAliasManager } @Override - public PropertyNameMapping getSpatialMapping(ValueReference propName, TableAliasManager aliasManager) - throws FilterEvaluationException, UnmappableException { - return getMapping(propName, aliasManager); + public List getSpatialMappings(ValueReference propName, + TableAliasManager aliasManager) { + return Collections.singletonList(getMapping(propName, aliasManager)); } }; return dialect.getWhereBuilder(mapper, filter, null, null, allowInMemoryFiltering); diff --git a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapper.java b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapper.java index 2d7cd5bba2..0642d3da26 100644 --- a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapper.java +++ b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapper.java @@ -34,12 +34,6 @@ ----------------------------------------------------------------------------*/ package org.deegree.feature.persistence.sql; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.xml.namespace.QName; - import org.deegree.commons.utils.QNameUtils; import org.deegree.feature.persistence.sql.xpath.MappableNameStep; import org.deegree.feature.persistence.sql.xpath.MappableStep; @@ -50,6 +44,13 @@ import org.deegree.sqldialect.filter.PropertyNameMapping; import org.deegree.sqldialect.filter.TableAliasManager; import org.deegree.sqldialect.filter.UnmappableException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * {@link PropertyNameMapper} for the {@link SQLFeatureStore}. @@ -58,6 +59,8 @@ */ public class SQLPropertyNameMapper implements PropertyNameMapper { + private static final Logger LOG = LoggerFactory.getLogger(SQLPropertyNameMapper.class); + private final SQLFeatureStore fs; private final FeatureTypeMapping ftMapping; @@ -103,23 +106,36 @@ else if (ftMapping == null && (ftMappings != null && ftMappings.size() > 1)) { @Override public PropertyNameMapping getMapping(ValueReference propName, TableAliasManager aliasManager) throws FilterEvaluationException, UnmappableException { - if (ftMapping != null || propName == null || propName.getAsText().isEmpty()) - return new MappedXPath(fs, ftMapping, propName, aliasManager, false, handleStrict).getPropertyNameMapping(); + if (ftMapping != null || propName == null || propName.getAsText().isEmpty()) { + List propertyNameMappings = new MappedXPath(fs, ftMapping, propName, aliasManager, + false, handleStrict) + .getPropertyNameMappings(); + if (propertyNameMappings.isEmpty()) + return null; + else if (propertyNameMappings.size() > 1) + LOG.warn("Multiple non-spatial mappings are currently not supported!"); + return propertyNameMappings.get(0); + } FeatureTypeMapping correspondingFtMapping = findCorrespondingMapping(propName); - return new MappedXPath(fs, correspondingFtMapping, propName, aliasManager, false, handleStrict) - .getPropertyNameMapping(); + List propertyNameMappings = new MappedXPath(fs, correspondingFtMapping, propName, + aliasManager, false, handleStrict) + .getPropertyNameMappings(); + if (propertyNameMappings.isEmpty()) + return null; + else if (propertyNameMappings.size() > 1) + LOG.warn("Multiple non-spatial mappings are currently not supported!"); + return propertyNameMappings.get(0); } @Override - public PropertyNameMapping getSpatialMapping(ValueReference propName, TableAliasManager aliasManager) - throws FilterEvaluationException, UnmappableException { - + public List getSpatialMappings(ValueReference propName, TableAliasManager aliasManager) + throws UnmappableException { if (ftMapping != null || propName == null || propName.getAsText().isEmpty()) - return new MappedXPath(fs, ftMapping, propName, aliasManager, true, handleStrict).getPropertyNameMapping(); - FeatureTypeMapping correspondingFtMapping = findCorrespondingMapping(propName); + return new MappedXPath(fs, ftMapping, propName, aliasManager, true, handleStrict).getPropertyNameMappings(); + FeatureTypeMapping correspondingFtMapping = ftMapping != null ? ftMapping : findCorrespondingMapping(propName); return new MappedXPath(fs, correspondingFtMapping, propName, aliasManager, true, handleStrict) - .getPropertyNameMapping(); + .getPropertyNameMappings(); } private FeatureTypeMapping findCorrespondingMapping(ValueReference propName) throws UnmappableException { diff --git a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/xpath/MappedXPath.java b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/xpath/MappedXPath.java index c6b96bb672..4e9c66af9c 100644 --- a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/xpath/MappedXPath.java +++ b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/xpath/MappedXPath.java @@ -94,7 +94,7 @@ public class MappedXPath { private String currentTableAlias; - private PropertyNameMapping propMapping; + private List propMappings = new ArrayList<>(); /** * @param fs @@ -141,8 +141,8 @@ public MappedXPath(SQLFeatureStore fs, FeatureTypeMapping ftMapping, ValueRefere map(ftMapping.getMappings(), steps); } - public PropertyNameMapping getPropertyNameMapping() { - return propMapping; + public List getPropertyNameMappings() { + return propMappings; } private void map(Collection mappedParticles, List steps) throws UnmappableException { @@ -202,13 +202,14 @@ else if (mapping instanceof FeatureMapping) { throw new InvalidParameterValueException(msg); } // determine path to nearest geometry mapping - List additionalSteps = new ArrayList(); - if (determineNearestGeometryMapping(mappedParticles, additionalSteps)) { + List additionalSteps = new ArrayList<>(); + determineNearestGeometryMappings(mappedParticles, additionalSteps); + if (!additionalSteps.isEmpty()) { matchFound = true; - for (int i = 0; i < additionalSteps.size() - 1; i++) { - followJoins(additionalSteps.get(i).getJoinedTable()); + for (GeometryMapping geomStep : additionalSteps) { + followJoins(geomStep.getJoinedTable()); + map(geomStep, steps); } - map((GeometryMapping) additionalSteps.get(additionalSteps.size() - 1), steps); } } @@ -224,24 +225,15 @@ else if (mapping instanceof FeatureMapping) { } } - private boolean determineNearestGeometryMapping(Collection mappedParticles, List steps) { - boolean found = false; + private void determineNearestGeometryMappings(Collection mappedParticles, List steps) { for (Mapping mapping : mappedParticles) { if (mapping instanceof GeometryMapping) { - steps.add(mapping); - found = true; - break; + steps.add((GeometryMapping) mapping); } else if (mapping instanceof CompoundMapping) { - steps.add(mapping); - found = determineNearestGeometryMapping(((CompoundMapping) mapping).getParticles(), steps); - if (found) { - break; - } - steps.remove(steps.size() - 1); + determineNearestGeometryMappings(((CompoundMapping) mapping).getParticles(), steps); } } - return found; } private void map(PrimitiveMapping mapping, List remaining) throws UnmappableException { @@ -253,10 +245,10 @@ private void map(PrimitiveMapping mapping, List remaining) throws } if (!(me instanceof DBField)) { final String qualifiedExpr = me.toString().replace("$0", currentTableAlias); - propMapping = new PropertyNameMapping(converter, joins, qualifiedExpr, null); + propMappings.add(new PropertyNameMapping(converter, joins, qualifiedExpr, null)); return; } - propMapping = new PropertyNameMapping(converter, joins, ((DBField) me).getColumn(), currentTableAlias); + propMappings.add(new PropertyNameMapping(converter, joins, ((DBField) me).getColumn(), currentTableAlias)); } private void map(GeometryMapping mapping, List remaining) throws UnmappableException { @@ -270,7 +262,7 @@ private void map(GeometryMapping mapping, List remaining) throws U if (fs != null) { converter = fs.getConverter(geomMapping); } - propMapping = new PropertyNameMapping(converter, joins, ((DBField) me).getColumn(), currentTableAlias); + propMappings.add(new PropertyNameMapping(converter, joins, ((DBField) me).getColumn(), currentTableAlias)); } private void map(FeatureMapping mapping, List remaining) throws UnmappableException { diff --git a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/test/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapperTest.java b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/test/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapperTest.java index 86df5c487c..9e3e27569b 100644 --- a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/test/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapperTest.java +++ b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/test/java/org/deegree/feature/persistence/sql/SQLPropertyNameMapperTest.java @@ -34,7 +34,7 @@ ----------------------------------------------------------------------------*/ package org.deegree.feature.persistence.sql; -import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -85,9 +85,9 @@ public void testGetSpatialMapping() throws Exception { ValueReference propName = new ValueReference("app:ftType2/app:geometry", nsContext()); List ftMapping = createFeatureTypeMappings(propName); SQLPropertyNameMapper mapper = new SQLPropertyNameMapper(mockFeatureStore(), ftMapping, false); - PropertyNameMapping spatialMapping = mapper.getSpatialMapping(propName, mockAliasManager()); + List spatialMappings = mapper.getSpatialMappings(propName, mockAliasManager()); - assertThat(spatialMapping, notNullValue()); + assertThat(spatialMappings.size(), is(1)); } @Test @@ -96,9 +96,9 @@ public void testGetSpatialMapping_withMissingNamespaceBinding() throws Exception CommonNamespaces.getNamespaceContext()); List ftMapping = createFeatureTypeMappings(propName); SQLPropertyNameMapper mapper = new SQLPropertyNameMapper(mockFeatureStore(), ftMapping, false); - PropertyNameMapping spatialMapping = mapper.getSpatialMapping(propName, mockAliasManager()); + List spatialMappings = mapper.getSpatialMappings(propName, mockAliasManager()); - assertThat(spatialMapping, notNullValue()); + assertThat(spatialMappings.size(), is(1)); } @Test @@ -106,9 +106,19 @@ public void testGetSpatialMapping_withMissingNamespaceBindingAndPrefix() throws ValueReference propName = new ValueReference("ftType2/geometry", CommonNamespaces.getNamespaceContext()); List ftMapping = createFeatureTypeMappings(propName); SQLPropertyNameMapper mapper = new SQLPropertyNameMapper(mockFeatureStore(), ftMapping, false); - PropertyNameMapping spatialMapping = mapper.getSpatialMapping(propName, mockAliasManager()); + List spatialMappings = mapper.getSpatialMappings(propName, mockAliasManager()); - assertThat(spatialMapping, notNullValue()); + assertThat(spatialMappings.size(), is(1)); + } + + @Test + public void testGetSpatialMapping_withNullPropName() throws Exception { + ValueReference propName = new ValueReference("app:ftType2/app:geometry", nsContext()); + FeatureTypeMapping ftMapping = mockFeatureTypeMapping("ftType1", "http://www.deegree.org/app", propName); + SQLPropertyNameMapper mapper = new SQLPropertyNameMapper(mockFeatureStore(), ftMapping, false); + List spatialMappings = mapper.getSpatialMappings(null, mockAliasManager()); + + assertThat(spatialMappings.size(), is(1)); } private List createFeatureTypeMappings(ValueReference valueReference) { diff --git a/deegree-datastores/deegree-mdstores/deegree-mdstore-ebrim-eo/src/main/java/org/deegree/metadata/persistence/ebrim/eo/mapping/EOPropertyNameMapper.java b/deegree-datastores/deegree-mdstores/deegree-mdstore-ebrim-eo/src/main/java/org/deegree/metadata/persistence/ebrim/eo/mapping/EOPropertyNameMapper.java index fa95233046..824dda6b25 100644 --- a/deegree-datastores/deegree-mdstores/deegree-mdstore-ebrim-eo/src/main/java/org/deegree/metadata/persistence/ebrim/eo/mapping/EOPropertyNameMapper.java +++ b/deegree-datastores/deegree-mdstores/deegree-mdstore-ebrim-eo/src/main/java/org/deegree/metadata/persistence/ebrim/eo/mapping/EOPropertyNameMapper.java @@ -593,9 +593,9 @@ private boolean isElementStep(NameStep step, QName elName) { } @Override - public PropertyNameMapping getSpatialMapping(ValueReference propName, TableAliasManager aliasManager) + public List getSpatialMappings(ValueReference propName, TableAliasManager aliasManager) throws FilterEvaluationException, UnmappableException { - return getMapping(propName, aliasManager); + return Collections.singletonList(getMapping(propName, aliasManager)); } } diff --git a/deegree-datastores/deegree-mdstores/deegree-mdstore-iso/src/main/java/org/deegree/metadata/iso/persistence/ISOPropertyNameMapper.java b/deegree-datastores/deegree-mdstores/deegree-mdstore-iso/src/main/java/org/deegree/metadata/iso/persistence/ISOPropertyNameMapper.java index 43c804b10e..ad09ea5f7a 100644 --- a/deegree-datastores/deegree-mdstores/deegree-mdstore-iso/src/main/java/org/deegree/metadata/iso/persistence/ISOPropertyNameMapper.java +++ b/deegree-datastores/deegree-mdstores/deegree-mdstore-iso/src/main/java/org/deegree/metadata/iso/persistence/ISOPropertyNameMapper.java @@ -48,6 +48,7 @@ import static org.slf4j.LoggerFactory.getLogger; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -396,9 +397,9 @@ public Map, Boolean, BaseType>> getPropToTabl } @Override - public PropertyNameMapping getSpatialMapping(ValueReference propName, TableAliasManager aliasManager) - throws FilterEvaluationException, UnmappableException { - return getMapping(propName, aliasManager); + public List getSpatialMappings(ValueReference propName, TableAliasManager aliasManager) + throws FilterEvaluationException { + return Collections.singletonList(getMapping(propName, aliasManager)); } }