From: <svn...@os...> - 2012-05-01 10:03:07
|
Author: ang05a Date: 2012-05-01 03:03:00 -0700 (Tue, 01 May 2012) New Revision: 38697 Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java Log: App-schema isList experimental/temporary solution to subsetting timeseries via filters. Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -61,6 +61,7 @@ import org.opengis.feature.type.AttributeType; import org.opengis.feature.type.FeatureType; import org.opengis.feature.type.Name; +import org.opengis.filter.Filter; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.PropertyName; import org.opengis.filter.identity.FeatureId; @@ -118,7 +119,13 @@ private boolean isFiltered = false; private ArrayList<String> filteredFeatures; + /** + * Temporary/experimental changes for enabling subsetting for isList only. + */ + private Filter listFilter; + private List<StepList> listFilterProperties; + public DataAccessMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, boolean isFiltered) throws IOException { this(store, mapping, query, null); @@ -821,14 +828,28 @@ Attribute instance = setAttributeValue(target, null, sources.get(0), attMapping, null, null, selectedProperties.get(attMapping)); if (sources.size() > 1 && instance != null) { - Object[] values = new Object[sources.size()]; + List<Object> values = new ArrayList<Object>(); Expression sourceExpr = attMapping.getSourceExpression(); - int i = 0; - for (Feature source : sources) { - values[i] = getValue(sourceExpr, source); - i++; + if (listFilter != null + && listFilterProperties.contains(attMapping.getTargetXPath())) { + for (Feature source : sources) { + // HACK HACK HACK + // evaluate filter that applies to this list as we want a subset + // instead of full result + // this is a temporary solution for Bureau of Meteorology + // requirement for timePositionList + if (listFilter.evaluate(source)) { + // only add to subset if filter matches value + values.add(getValue(sourceExpr, source)); + } + } + } else { + // no filter concerning the list + for (Feature source : sources) { + values.add(getValue(sourceExpr, source)); + } } - String valueString = StringUtils.join(values, " "); + String valueString = StringUtils.join(values.iterator(), " "); StepList fullPath = attMapping.getTargetXPath(); StepList leafPath = fullPath.subList(fullPath.size() - 1, fullPath.size()); if (instance instanceof ComplexAttributeImpl) { @@ -954,6 +975,8 @@ sourceFeatureIterator = null; sourceFeatures = null; filteredFeatures = null; + listFilterProperties = null; + listFilter = null; //NC - joining nested atts for (AttributeMapping attMapping : selectedMapping) { @@ -1085,4 +1108,12 @@ public boolean isReprojectionCrsEqual(CoordinateReferenceSystem source,CoordinateReferenceSystem target) { return CRS.equalsIgnoreMetadata(source,target); } + + public void setListFilter(Filter filter) { + listFilter = filter; + } + + public void setListFilterProperties(List<StepList> properties) { + listFilterProperties = properties; + } } Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java 2012-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -223,11 +223,24 @@ public Name getMappingName() { return mappingName; } - - - - + /** + * Return list of attribute mappings that are configured as list (isList = true). + * @return attribute mappings with isList enabled. + */ + public List<AttributeMapping> getIsListMappings() { + List<AttributeMapping> mappings = new ArrayList<AttributeMapping>(); + AttributeMapping attMapping; + for (Iterator<AttributeMapping> it = attributeMappings.iterator(); it.hasNext();) { + attMapping = (AttributeMapping) it.next(); + if (attMapping.isList()) { + mappings.add(attMapping); + } + } + return mappings; + } + + /** * Looks up for attribute mappings matching the xpath expression <code>propertyName</code>. * <p> * If any step in <code>propertyName</code> has index greater than 1, any mapping for the same Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java 2012-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -18,23 +18,28 @@ package org.geotools.data.complex; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Logger; import org.geotools.data.FeatureSource; import org.geotools.data.Query; import org.geotools.data.complex.config.AppSchemaDataAccessConfigurator; import org.geotools.data.complex.filter.ComplexFilterSplitter; +import org.geotools.data.complex.filter.XPath; +import org.geotools.data.complex.filter.XPath.StepList; import org.geotools.data.joining.JoiningQuery; import org.geotools.feature.Types; import org.geotools.filter.FidFilterImpl; import org.geotools.filter.FilterCapabilities; -import org.geotools.filter.NestedAttributeExpression; import org.geotools.filter.visitor.DefaultFilterVisitor; import org.geotools.jdbc.JDBCFeatureSource; import org.geotools.jdbc.JDBCFeatureStore; +import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.expression.PropertyName; import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.xml.sax.helpers.NamespaceSupport; /** * @author Russell Petty (GeoScience Victoria) @@ -49,13 +54,76 @@ public class MappingFeatureIteratorFactory { protected static final Logger LOGGER = org.geotools.util.logging.Logging .getLogger("org.geotools.data.complex"); + + /** + * Temporary filter visitor to determine whether the filter concerns any attribute mapping that + * has isList enabled. This is because Bureau of Meteorology requires a subset of the property + * value to be returned, instead of the full value. This should be a temporary solution. This + * won't work with feature chaining at the moment. + * + * @author Rini Angreani (CSIRO Earth Science and Resource Engineering) + * + */ + static class IsListFilterVisitor extends DefaultFilterVisitor { + // Attribute mappings that have isList enabled + private List<AttributeMapping> listMappings; + + // Filter properties that are configured as isList + private List<StepList> listFilterProperties; + + private FeatureTypeMapping mappings; + + public IsListFilterVisitor(List<AttributeMapping> listMappings, FeatureTypeMapping mappings) { + this.listMappings = listMappings; + this.mappings = mappings; + listFilterProperties = new ArrayList<StepList>(); + } + + @Override + public Object visit(PropertyName expression, Object extraData) { + AttributeDescriptor root = mappings.getTargetFeature(); + String attPath = expression.getPropertyName(); + NamespaceSupport namespaces = mappings.getNamespaces(); + StepList simplifiedSteps = XPath.steps(root, attPath, namespaces); + StepList targetXpath; + for (AttributeMapping mapping : listMappings) { + targetXpath = mapping.getTargetXPath(); + if (targetXpath.equals(simplifiedSteps)) { + // TODO: support feature chaining too? + listFilterProperties.add(targetXpath); + } + } + return extraData; + } + + public List<StepList> getListFilterProperties() { + return listFilterProperties; + } + } + public static IMappingFeatureIterator getInstance(AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, Filter unrolledFilter) throws IOException { if (mapping instanceof XmlFeatureTypeMapping) { return new XmlMappingFeatureIterator(store, mapping, query); } + + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + List<AttributeMapping> listMappings = mapping.getIsListMappings(); + Filter isListFilter = null; + List<StepList> listFilterProperties = null; + if (!listMappings.isEmpty()) { + IsListFilterVisitor listChecker = new IsListFilterVisitor(listMappings, mapping); + Filter complexFilter = query.getFilter(); + complexFilter.accept(listChecker, null); + listFilterProperties = listChecker.getListFilterProperties(); + if (!listFilterProperties.isEmpty()) { + isListFilter = AppSchemaDataAccess.unrollFilter(complexFilter, mapping); + } + } + // END OF HACK boolean isJoining = AppSchemaDataAccessConfigurator.isJoining(); @@ -99,6 +167,14 @@ // to find denormalised rows that match the id (but doesn't match pre filter) boolean isFiltered = !isJoining && preFilter != null && preFilter != Filter.INCLUDE; iterator = new DataAccessMappingFeatureIterator(store, mapping, query, isFiltered); + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + if (isListFilter != null) { + ((DataAccessMappingFeatureIterator) iterator).setListFilter(isListFilter); + ((DataAccessMappingFeatureIterator) iterator) + .setListFilterProperties(listFilterProperties); + } + // END OF HACK if (filter != null && filter != Filter.INCLUDE) { iterator = new PostFilteringMappingFeatureIterator(iterator, filter, maxFeatures); @@ -137,6 +213,15 @@ } } } + + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + if (isListFilter != null && iterator instanceof DataAccessMappingFeatureIterator) { + ((DataAccessMappingFeatureIterator) iterator).setListFilter(isListFilter); + ((DataAccessMappingFeatureIterator) iterator) + .setListFilterProperties(listFilterProperties); + } + // END OF HACK return iterator; } Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java 2012-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -54,8 +54,14 @@ protected Feature getFilteredNext() { while (delegate.hasNext() && count < maxFeatures) { Feature feature = delegate.next(); - if (filter.evaluate(feature)) { - return feature; + try { + if (filter.evaluate(feature)) { + return feature; + } + } catch (NullPointerException e) { + // ignore this exception + // this is to cater the case if the attribute has no value and + // has been skipped in the delegate DataAccessMappingFeatureIterator } } return null; |