|
From: <svn...@os...> - 2012-01-12 07:30:59
|
Author: ang05a
Date: 2012-01-11 23:30:49 -0800 (Wed, 11 Jan 2012)
New Revision: 38479
Added:
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java
Removed:
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java
Modified:
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AbstractMappingFeatureIterator.java
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java
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/MappingAttributeIterator.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/XmlMappingFeatureIterator.java
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/filter/ComplexFilterSplitter.java
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/filter/XPath.java
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningNestedAttributeMapping.java
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/feature/xpath/XmlAttributeNodePointer.java
trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/jdbc/JoiningJDBCFeatureSource.java
trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/FeatureChainingTest.java
trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/PolymorphicChainingTest.java
trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/TimeSeriesTest.java
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/CGITermValue.properties
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/CGITermValue.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/CompositionPart.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/ControlledConcept.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/FirstParentFeature.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/GeologicUnit.properties
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/GeologicUnit.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/MappedFeatureAsOccurrence.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/MappedFeatureMissingNamespaceXlink.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/PointFeatureGeomPropertyfile.properties
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/PointFeaturePropertyfile.properties
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/SecondParentFeature.xml
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/SimpleContent.properties
trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/exposureColor.properties
Log:
Enable geoserver app-schema-test to run online.
Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AbstractMappingFeatureIterator.java
===================================================================
--- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AbstractMappingFeatureIterator.java 2012-01-12 04:24:42 UTC (rev 38478)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AbstractMappingFeatureIterator.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -20,7 +20,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
@@ -30,6 +29,7 @@
import org.geotools.data.complex.filter.XPath.StepList;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.AppSchemaFeatureFactoryImpl;
+import org.geotools.feature.FeatureIterator;
import org.geotools.feature.Types;
import org.geotools.filter.FilterFactoryImplNamespaceAware;
import org.geotools.xlink.XLINK;
@@ -40,7 +40,6 @@
import org.opengis.feature.type.PropertyDescriptor;
import org.opengis.feature.GeometryAttribute;
import org.opengis.feature.Property;
-import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.type.Name;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.FilterFactory2;
@@ -155,7 +154,7 @@
}
xpathAttributeBuilder = new XPath();
xpathAttributeBuilder.setFeatureFactory(attf);
- initialiseSourceFeatures(mapping, unrolledQuery);
+ initialiseSourceFeatures(mapping, unrolledQuery, query.getCoordinateSystemReproject());
xpathAttributeBuilder.setFilterFactory(namespaceAwareFilterFactory);
}
@@ -268,75 +267,24 @@
* @see java.util.Iterator#next()
*/
public Feature next() {
- if (!isHasNextCalled()) {
- LOGGER.warning("hasNext not called before calling next() in the iterator!");
- if (!hasNext()) {
- return null;
- }
+ if (!hasNext()) {
+ throw new IllegalStateException("there are no more features in this iterator");
}
+
Feature next;
try {
next = computeNext();
- this.cleanEmptyElements(next);
} catch (IOException e) {
close();
throw new RuntimeException(e);
}
- ++featureCounter;
+ ++featureCounter;
+
+ setHasNextCalled(false);
return next;
}
- private void cleanEmptyElements(Feature target) throws DataSourceException {
- try {
- ArrayList values = new ArrayList<Property>();
- for (Iterator i = target.getValue().iterator(); i.hasNext();) {
- Property p = (Property) i.next();
-
- if (hasChild(p) || p.getDescriptor().getMinOccurs() > 0) {
- values.add(p);
- }
- }
- target.setValue(values);
- } catch (DataSourceException e) {
- throw new DataSourceException("Unable to clean empty element", e);
- }
- }
-
- private boolean hasChild(Property p) throws DataSourceException {
- boolean result = false;
- if (p.getValue() instanceof Collection) {
-
- Collection c = (Collection) p.getValue();
-
- if (this.getClientProperties(p).containsKey(XLINK_HREF_NAME)) {
- return true;
- }
-
- ArrayList values = new ArrayList();
- for (Object o : c) {
- if (o instanceof Property) {
- if (hasChild((Property) o)) {
- values.add(o);
- result = true;
- } else if (((Property) o).getDescriptor().getMinOccurs() > 0) {
- if (((Property) o).getDescriptor().isNillable()) {
- // add nil mandatory property
- values.add(o);
- }
- }
- }
- }
- p.setValue(values);
- } else if (p.getName().equals(ComplexFeatureConstants.FEATURE_CHAINING_LINK_NAME)) {
- // ignore fake attribute FEATURE_LINK
- result = false;
- } else if (p.getValue() != null && p.getValue().toString().length() > 0) {
- result = true;
- }
- return result;
- }
-
protected Map getClientProperties(Property attribute) throws DataSourceException {
Map<Object, Object> userData = attribute.getUserData();
@@ -439,10 +387,10 @@
protected abstract void closeSourceFeatures();
- protected abstract Iterator<SimpleFeature> getSourceFeatureIterator();
+ protected abstract FeatureIterator<? extends Feature> getSourceFeatureIterator();
- protected abstract void initialiseSourceFeatures(FeatureTypeMapping mapping, Query query)
- throws IOException;
+ protected abstract void initialiseSourceFeatures(FeatureTypeMapping mapping, Query query,
+ CoordinateReferenceSystem crs) throws IOException;
protected abstract boolean unprocessedFeatureExists();
Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java
===================================================================
--- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java 2012-01-12 04:24:42 UTC (rev 38478)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -306,7 +306,7 @@
@SuppressWarnings("unchecked")
public Query unrollQuery(Query query, FeatureTypeMapping mapping) {
Query unrolledQuery = Query.ALL;
- FeatureSource<FeatureType, Feature> source = mapping.getSource();
+ FeatureSource source = mapping.getSource();
if (!Query.ALL.equals(query)) {
Filter complexFilter = query.getFilter();
@@ -339,8 +339,7 @@
JoiningQuery jQuery = new JoiningQuery(newQuery);
jQuery.setQueryJoins(((JoiningQuery)query).getQueryJoins());
unrolledQuery = jQuery;
- }
- else {
+ } else {
unrolledQuery = newQuery;
}
}
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-01-12 04:24:42 UTC (rev 38478)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -31,6 +31,7 @@
import javax.xml.namespace.QName;
import org.geotools.data.DataAccess;
+import org.geotools.data.DataSourceException;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.data.complex.filter.XPath;
@@ -38,7 +39,6 @@
import org.geotools.data.complex.filter.XPath.StepList;
import org.geotools.data.joining.JoiningNestedAttributeMapping;
import org.geotools.data.joining.JoiningQuery;
-import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.AttributeBuilder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureImpl;
@@ -46,7 +46,6 @@
import org.geotools.feature.Types;
import org.geotools.filter.AttributeExpressionImpl;
import org.geotools.filter.FilterAttributeExtractor;
-import org.geotools.filter.FilterFactoryImpl;
import org.geotools.gml2.bindings.GML2EncodingUtils;
import org.geotools.jdbc.JDBCFeatureSource;
import org.geotools.jdbc.JDBCFeatureStore;
@@ -56,13 +55,10 @@
import org.opengis.feature.ComplexAttribute;
import org.opengis.feature.Feature;
import org.opengis.feature.Property;
-import org.opengis.feature.simple.SimpleFeature;
-import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.AttributeType;
import org.opengis.feature.type.FeatureType;
import org.opengis.feature.type.Name;
-import org.opengis.feature.type.PropertyType;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.identity.FeatureId;
@@ -94,7 +90,7 @@
/**
* Hold on to iterator to allow features to be streamed.
*/
- private Iterator<SimpleFeature> sourceFeatureIterator;
+ private FeatureIterator<? extends Feature> sourceFeatureIterator;
/**
* Reprojected CRS from the source simple features, or null
@@ -106,22 +102,34 @@
*/
protected Feature curSrcFeature;
- protected FeatureSource<SimpleFeatureType, SimpleFeature> mappedSource;
+ protected FeatureSource<? extends FeatureType, ? extends Feature> mappedSource;
- protected FeatureCollection<SimpleFeatureType, SimpleFeature> sourceFeatures;
+ protected FeatureCollection<? extends FeatureType, ? extends Feature> sourceFeatures;
protected List<Expression> foreignIds = null;
- private boolean isNextFeatureSet;
-
- private boolean isFiltered;
-
+ /**
+ * True if joining is turned off and pre filter exists. There's a need to run extra query to get
+ * features by id because they might come from denormalised view. The rows might not match the
+ * filter therefore doesn't exist in the mapped source but match the id of other rows.
+ */
+ private boolean isFiltered = false;
+
private ArrayList<String> filteredFeatures;
public DataAccessMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping,
Query query, boolean isFiltered) throws IOException {
- this(store, mapping, query, isFiltered, null);
+ this(store, mapping, query, null);
+ this.isFiltered = isFiltered;
+ if (isFiltered) {
+ filteredFeatures = new ArrayList<String>();
+ }
}
+
+ public DataAccessMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping,
+ Query query) throws IOException {
+ this(store, mapping, query, null);
+ }
/**
*
@@ -135,48 +143,37 @@
* @throws IOException
*/
public DataAccessMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping,
- Query query, boolean isFiltered, Query unrolledQuery) throws IOException {
+ Query query, Query unrolledQuery) throws IOException {
super(store, mapping, query, unrolledQuery);
- this.isFiltered = isFiltered;
- if (isFiltered) {
- filteredFeatures = new ArrayList<String>();
- }
}
@Override
public boolean hasNext() {
- if (isHasNextCalled()) {
- return !isNextSourceFeatureNull();
- }
+ boolean exists = !isNextSourceFeatureNull();
- setHasNextCalled(true);
-
- boolean exists = false;
-
- if (featureCounter < maxFeatures) {
- if (isNextFeatureSet()) {
- flagNextFeature(false);
- return curSrcFeature != null;
- }
-
- if (getSourceFeatureIterator() != null && getSourceFeatureIterator().hasNext()) {
- this.curSrcFeature = getSourceFeatureIterator().next();
- exists = true;
- }
- if (exists && filteredFeatures != null) {
- // get the next one if this row has already been added to the target
- // feature from setNextFilteredFeature
- while (exists && filteredFeatures.contains(extractIdForFeature(this.curSrcFeature))) {
- if (getSourceFeatureIterator() != null && getSourceFeatureIterator().hasNext()) {
- this.curSrcFeature = getSourceFeatureIterator().next();
- exists = true;
- } else {
- exists = false;
+ if (!isHasNextCalled()) {
+ if (featureCounter < maxFeatures) {
+ if (!exists && getSourceFeatureIterator() != null
+ && getSourceFeatureIterator().hasNext()) {
+ this.curSrcFeature = getSourceFeatureIterator().next();
+ exists = true;
+ }
+ if (exists && filteredFeatures != null) {
+ // get the next one if this row has already been added to the target
+ // feature from setNextFilteredFeature
+ while (exists
+ && filteredFeatures.contains(extractIdForFeature(this.curSrcFeature))) {
+ if (getSourceFeatureIterator() != null
+ && getSourceFeatureIterator().hasNext()) {
+ this.curSrcFeature = getSourceFeatureIterator().next();
+ exists = true;
+ } else {
+ exists = false;
+ }
}
}
- if (!exists) {
- curSrcFeature = null;
- }
+ } else {
+ exists = false;
}
}
@@ -186,12 +183,12 @@
curSrcFeature = null;
}
- flagNextFeature(false);
+ setHasNextCalled(true);
return exists;
}
- protected Iterator<SimpleFeature> getSourceFeatureIterator() {
+ protected FeatureIterator<? extends Feature> getSourceFeatureIterator() {
return sourceFeatureIterator;
}
@@ -258,7 +255,7 @@
FilterAttributeExtractor extractor = new FilterAttributeExtractor();
mapping.getFeatureIdExpression().accept(extractor, null);
for (String att : extractor.getAttributeNameSet()) {
- ids.add(peekValue(source, CommonFactoryFinder.getFilterFactory2(null).property( att)));
+ ids.add(peekValue(source, namespaceAwareFilterFactory.property( att)));
}
if (foreignIds != null) {
@@ -275,8 +272,8 @@
return checkForeignIdValues(foreignIdValues, curSrcFeature);
}
- protected void initialiseSourceFeatures(FeatureTypeMapping mapping, Query query)
- throws IOException {
+ protected void initialiseSourceFeatures(FeatureTypeMapping mapping, Query query,
+ CoordinateReferenceSystem targetCRS) throws IOException {
mappedSource = mapping.getSource();
//NC - joining query
@@ -292,7 +289,7 @@
}
String version=(String)this.mapping.getTargetFeature().getType().getUserData().get("targetVersion");
//might be because top level feature has no geometry
- if (query.getCoordinateSystemReproject() == null && version!=null) {
+ if (targetCRS == null && version!=null) {
// figure out the crs the data is in
CoordinateReferenceSystem crs=null;
try{
@@ -317,7 +314,7 @@
this.reprojection = target;
} else {
- this.reprojection = query.getCoordinateSystemReproject();
+ this.reprojection = targetCRS;
}
// we need to disable the max number of features retrieved so we can
@@ -334,7 +331,7 @@
}
}
if (!(this instanceof XmlMappingFeatureIterator)) {
- this.sourceFeatureIterator = sourceFeatures.iterator();
+ this.sourceFeatureIterator = sourceFeatures.features();
}
// NC - joining nested atts
@@ -586,10 +583,9 @@
if (uri != null) {
Attribute instance = xpathAttributeBuilder.set(target, xpath, null, "", targetNodeType,
true, null);
- FilterFactoryImpl ff = new FilterFactoryImpl();
Map<Name, Expression> newClientProps = new HashMap<Name, Expression>();
newClientProps.putAll(clientPropsMappings);
- newClientProps.put(XLINK_HREF_NAME, ff.literal(uri));
+ newClientProps.put(XLINK_HREF_NAME, namespaceAwareFilterFactory.literal(uri));
setClientProperties(instance, null, newClientProps);
}
}
@@ -665,45 +661,46 @@
*/
protected void setXlinkReference(Attribute target, Map<Name, Expression> clientPropsMappings,
Object value, StepList xpath, AttributeType targetNodeType) {
- // Make sure the same value isn't already set
- // in case it comes from a denormalized view for many-to-many relationship.
- // (1) Get the first existing value
- Property existingAttribute = getProperty(target, xpath);
+ Expression linkExpression = clientPropsMappings.get(XLINK_HREF_NAME);
+
+ for (Object singleVal : (Collection) value) {
+ // Make sure the same value isn't already set
+ // in case it comes from a denormalized view for many-to-many relationship.
+ // (1) Get the first existing value
+ Collection<Property> existingAttributes = getProperties((ComplexAttribute) target, xpath);
+ boolean exists = false;
- if (existingAttribute != null) {
- Object existingValue = existingAttribute.getUserData().get(Attributes.class);
- if (existingValue != null) {
- assert existingValue instanceof HashMap;
- existingValue = ((Map) existingValue).get(XLINK_HREF_NAME);
- }
- if (existingValue != null) {
- Expression linkExpression = clientPropsMappings.get(XLINK_HREF_NAME);
- for (Object singleVal : (Collection) value) {
- assert singleVal instanceof Feature;
- assert linkExpression != null;
- Object hrefValue = linkExpression.evaluate(singleVal);
- if (hrefValue != null && hrefValue.equals(existingValue)) {
- // (2) if one of the new values matches the first existing value,
- // that means this comes from a denormalized view,
- // and this set has already been set
- return;
+ if (existingAttributes != null) {
+ for (Property existingAttribute : existingAttributes) {
+ Object existingValue = existingAttribute.getUserData().get(Attributes.class);
+ if (existingValue != null) {
+ assert existingValue instanceof HashMap;
+ existingValue = ((Map) existingValue).get(XLINK_HREF_NAME);
}
+ if (existingValue != null) {
+ Object hrefValue = linkExpression.evaluate(singleVal);
+ if (hrefValue != null && hrefValue.equals(existingValue)) {
+ // (2) if one of the new values matches the first existing value,
+ // that means this comes from a denormalized view,
+ // and this set has already been set
+ exists = true;
+ // stop looking once found
+ break;
+ }
+ }
}
}
+ if (!exists) {
+ Attribute instance = xpathAttributeBuilder.set(target, xpath, null, null,
+ targetNodeType, true, null);
+ setClientProperties(instance, singleVal, clientPropsMappings);
+ }
}
-
- for (Object singleVal : (Collection) value) {
- assert singleVal instanceof Feature;
- Attribute instance = xpathAttributeBuilder.set(target, xpath, null, null,
- targetNodeType, true, null);
- setClientProperties(instance, singleVal, clientPropsMappings);
- }
}
- protected void setNextFeature(String fId, List<Object> foreignIdValues, ArrayList<Feature> features) throws IOException {
- if (features.isEmpty()) {
- features.add(curSrcFeature);
- }
+ protected List<Feature> setNextFeature(String fId, List<Object> foreignIdValues) throws IOException {
+ List<Feature> features = new ArrayList<Feature>();
+ features.add(curSrcFeature);
curSrcFeature = null;
while (getSourceFeatureIterator().hasNext()) {
@@ -712,19 +709,26 @@
features.add(next);
} else {
curSrcFeature = next;
- flagNextFeature(true);
break;
}
}
+ return features;
}
-
- private void setNextFilteredFeature(String fId, ArrayList<Feature> features) throws IOException {
- FeatureCollection<SimpleFeatureType, SimpleFeature> matchingFeatures;
- FeatureId featureId = namespaceAwareFilterFactory.featureId(fId);
+
+ /**
+ * Only used when joining is not used and pre-filter exists because the sources will match
+ * the prefilter but there might be denormalised rows with same id that don't.
+ * @param fId
+ * @param features
+ * @throws IOException
+ */
+ private List<Feature> setNextFilteredFeature(String fId) throws IOException {
+ FeatureCollection<? extends FeatureType, ? extends Feature> matchingFeatures;
Query query = new Query();
if (reprojection != null) {
- if (sourceFeatures.getSchema().getGeometryDescriptor() != null && !this.isReprojectionCrsEqual(this.mappedSource.getSchema()
- .getCoordinateReferenceSystem(),this.reprojection)) {
+ if (sourceFeatures.getSchema().getGeometryDescriptor() != null
+ && !this.isReprojectionCrsEqual(this.mappedSource.getSchema()
+ .getCoordinateReferenceSystem(), this.reprojection)) {
query.setCoordinateSystemReproject(reprojection);
}
}
@@ -733,6 +737,7 @@
// no real feature id mapping,
// so let's find by database row id
Set<FeatureId> ids = new HashSet<FeatureId>();
+ FeatureId featureId = namespaceAwareFilterFactory.featureId(fId);
ids.add(featureId);
query.setFilter(namespaceAwareFilterFactory.id(ids));
matchingFeatures = this.mappedSource.getFeatures(query);
@@ -744,8 +749,9 @@
matchingFeatures = this.mappedSource.getFeatures(query);
}
- FeatureIterator<SimpleFeature> iterator = matchingFeatures.features();
+ FeatureIterator<? extends Feature> iterator = matchingFeatures.features();
+ List<Feature> features = new ArrayList<Feature>();
while (iterator.hasNext()) {
features.add(iterator.next());
}
@@ -757,23 +763,12 @@
filteredFeatures.add(fId);
iterator.close();
-
+
curSrcFeature = null;
+
+ return features;
}
- protected List<Feature> getSources() throws IOException {
- String id = extractIdForFeature(curSrcFeature);
-
- ArrayList<Feature> sources = new ArrayList<Feature>();
- if (isFiltered) {
- setNextFilteredFeature(id, sources);
- } else {
- setNextFeature(id, getForeignIdValues(curSrcFeature), sources);
- }
-
- return sources;
- }
-
public void skipNestedMapping(AttributeMapping attMapping, List<Feature> sources) throws IOException {
if (attMapping instanceof JoiningNestedAttributeMapping) {
@@ -795,7 +790,7 @@
public List<Feature> skip() throws IOException {
setHasNextCalled(false);
- List<Feature> sources = getSources();
+ List<Feature> sources = getSources(extractIdForFeature(curSrcFeature));
for (AttributeMapping attMapping : selectedMapping) {
skipNestedMapping(attMapping, sources);
}
@@ -803,16 +798,10 @@
}
protected Feature computeNext() throws IOException {
- if (curSrcFeature == null) {
- throw new UnsupportedOperationException("No features found in next()."
- + "This wouldn't have happenned if hasNext() was called beforehand.");
- }
- setHasNextCalled(false);
+ String id = getNextFeatureId();
+ List<Feature> sources = getSources(id);
- String id = extractIdForFeature(curSrcFeature);
- List<Feature> sources = getSources();
-
final AttributeDescriptor targetNode = mapping.getTargetFeature();
final Name targetNodeName = targetNode.getName();
@@ -852,9 +841,81 @@
+ attMapping.getTargetXPath(), e);
}
}
+ cleanEmptyElements(target);
+
return target;
}
+ /**
+ * Get all source features of the provided id. This assumes the source features are grouped by
+ * id.
+ *
+ * @param id
+ * The feature id
+ * @return list of source features
+ * @throws IOException
+ */
+ protected List<Feature> getSources(String id) throws IOException {
+ if (isFiltered) {
+ return setNextFilteredFeature(id);
+ } else {
+ return setNextFeature(id, getForeignIdValues(curSrcFeature));
+ }
+ }
+
+ protected String getNextFeatureId() {
+ return extractIdForFeature(curSrcFeature);
+ }
+
+ protected void cleanEmptyElements(Feature target) throws DataSourceException {
+ try {
+ ArrayList values = new ArrayList<Property>();
+ for (Iterator i = target.getValue().iterator(); i.hasNext();) {
+ Property p = (Property) i.next();
+ if (hasChild(p) || p.getDescriptor().getMinOccurs() > 0) {
+ values.add(p);
+ }
+ }
+ target.setValue(values);
+ } catch (DataSourceException e) {
+ throw new DataSourceException("Unable to clean empty element", e);
+ }
+ }
+
+ private boolean hasChild(Property p) throws DataSourceException {
+ boolean result = false;
+ if (p.getValue() instanceof Collection) {
+
+ Collection c = (Collection) p.getValue();
+
+ if (this.getClientProperties(p).containsKey(XLINK_HREF_NAME)) {
+ return true;
+ }
+
+ ArrayList values = new ArrayList();
+ for (Object o : c) {
+ if (o instanceof Property) {
+ if (hasChild((Property) o)) {
+ values.add(o);
+ result = true;
+ } else if (((Property) o).getDescriptor().getMinOccurs() > 0) {
+ if (((Property) o).getDescriptor().isNillable()) {
+ // add nil mandatory property
+ values.add(o);
+ }
+ }
+ }
+ }
+ p.setValue(values);
+ } else if (p.getName().equals(ComplexFeatureConstants.FEATURE_CHAINING_LINK_NAME)) {
+ // ignore fake attribute FEATURE_LINK
+ result = false;
+ } else if (p.getValue() != null && p.getValue().toString().length() > 0) {
+ result = true;
+ }
+ return result;
+ }
+
protected boolean skipTopElement(Name topElement, StepList xpath, AttributeType type) {
// don't skip simple content e.g. when feature chaining gml:name
return Types.equals(topElement, xpath) && !Types.isSimpleContentType(type);
@@ -866,7 +927,7 @@
protected void closeSourceFeatures() {
if (sourceFeatures != null && getSourceFeatureIterator() != null) {
- sourceFeatures.close(sourceFeatureIterator);
+ sourceFeatureIterator.close();
sourceFeatureIterator = null;
sourceFeatures = null;
filteredFeatures = null;
@@ -971,14 +1032,6 @@
return isNested ? (clientPropsMappings.isEmpty() ? false : (clientPropsMappings
.get(XLINK_HREF_NAME) == null) ? false : true) : false;
}
-
- public void flagNextFeature(boolean isSet) {
- this.isNextFeatureSet = isSet;
- }
-
- public boolean isNextFeatureSet() {
- return isNextFeatureSet;
- }
/**
* Returns the declared CRS given the native CRS and the request WFS version
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-01-12 04:24:42 UTC (rev 38478)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -30,6 +30,7 @@
import org.geotools.data.complex.filter.XPath;
import org.geotools.data.complex.filter.XPath.Step;
import org.geotools.data.complex.filter.XPath.StepList;
+import org.geotools.data.joining.JoiningNestedAttributeMapping;
import org.geotools.feature.Types;
import org.geotools.filter.NestedAttributeExpression;
import org.geotools.gml3.GML;
@@ -284,23 +285,30 @@
Expression propertyExpression;
for (Iterator it = attributeMappings.iterator(); it.hasNext();) {
attMapping = (AttributeMapping) it.next();
- clientProperties = attMapping.getClientProperties();
- // NC -added
- if (clientPropertyName.equals(GML.id)) {
- clientPropertyExpressions.add(attMapping.getIdentifierExpression());
- } else if (clientProperties.containsKey(clientPropertyName)) {
- // end NC - added
- propertyExpression = (Expression) clientProperties.get(clientPropertyName);
- clientPropertyExpressions.add(propertyExpression);
- } else if (attMapping.isNestedAttribute() && Types.isSimpleContent(parentPath, getTargetFeature().getType())) {
- // create the full xpath from the parent's attribute
- // only bother if this is a simple content
- // otherwise, it would be handled in NestedAttributeExpression since it'd
- // already have the full path then
- StepList fullXpath = parentPath.clone();
- fullXpath.add(new Step(Types.toQName(clientPropertyName, namespaces), 1, true, false));
- clientPropertyExpressions.add(new NestedAttributeExpression(
- fullXpath, this));
+ if (attMapping instanceof JoiningNestedAttributeMapping) {
+ // if it's joining for simple content feature chaining it has to be empty
+ // so it will be added to the post filter
+ clientPropertyExpressions.add(null);
+ } else {
+ clientProperties = attMapping.getClientProperties();
+ // NC -added
+ if (clientPropertyName.equals(GML.id)) {
+ clientPropertyExpressions.add(attMapping.getIdentifierExpression());
+ } else if (clientProperties.containsKey(clientPropertyName)) {
+ // end NC - added
+ propertyExpression = (Expression) clientProperties.get(clientPropertyName);
+ clientPropertyExpressions.add(propertyExpression);
+ } else if (attMapping.isNestedAttribute()
+ && Types.isSimpleContent(parentPath, getTargetFeature().getType())) {
+ // create the full xpath from the parent's attribute
+ // only bother if this is a simple content
+ // otherwise, it would be handled in NestedAttributeExpression since it'd
+ // already have the full path then
+ StepList fullXpath = parentPath.clone();
+ fullXpath.add(new Step(Types.toQName(clientPropertyName, namespaces), 1, true,
+ false));
+ clientPropertyExpressions.add(new NestedAttributeExpression(fullXpath, this));
+ }
}
}
@@ -318,10 +326,13 @@
Expression sourceExpression;
for (Iterator it = attributeMappings.iterator(); it.hasNext();) {
mapping = (AttributeMapping) it.next();
- if (mapping instanceof NestedAttributeMapping) {
+ if (mapping instanceof JoiningNestedAttributeMapping) {
+ // if it's joining for simple content feature chaining it has to be null
+ // so it will be added to the post filter
+ sourceExpression = null;
+ } else if (mapping instanceof NestedAttributeMapping) {
// nested attribute with simple content is possible now
- sourceExpression = new NestedAttributeExpression(
- mapping.getTargetXPath(), this);
+ sourceExpression = new NestedAttributeExpression(mapping.getTargetXPath(), this);
} else {
sourceExpression = mapping.getSourceExpression();
}
Deleted: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java
===================================================================
--- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java 2012-01-12 04:24:42 UTC (rev 38478)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -1,108 +0,0 @@
-/*
- * GeoTools - The Open Source Java GIS Toolkit
- * http://geotools.org
- *
- * (C) 2010-2011, Open Source Geospatial Foundation (OSGeo)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- */
-
-package org.geotools.data.complex;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-import org.apache.commons.collections.IteratorUtils;
-import org.geotools.data.Query;
-import org.opengis.feature.Feature;
-import org.opengis.feature.simple.SimpleFeature;
-import org.opengis.filter.Filter;
-
-/**
- * An extension to {@linkplain org.geotools.data.complex.DataAccessMappingFeatureIterator} where
- * filter is present. Since join query between 2 or more tables isn't supported, the only way we can
- * query nested features is by applying the filter per simple feature (database row). This is done
- * in hasNext().
- *
- * @author Rini Angreani (CSIRO Earth Science and Resource Engineering)
- *
- *
- *
- * @source $URL$
- */
-public class FilteringMappingFeatureIterator extends DataAccessMappingFeatureIterator {
-
- protected ListIterator<SimpleFeature> listFeatureIterator;
-
- private Filter filter;
-
- public FilteringMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping,
- Query query, Query unrolledQuery, Filter filter) throws IOException {
- super(store, mapping, query, false, unrolledQuery);
- this.filter = filter;
- }
-
- @Override
- protected void initialiseSourceFeatures(FeatureTypeMapping mapping, Query query)
- throws IOException {
- super.initialiseSourceFeatures(mapping, query);
- listFeatureIterator = IteratorUtils.toListIterator(super.getSourceFeatureIterator());
- }
-
- @Override
- protected void closeSourceFeatures() {
- super.closeSourceFeatures();
- listFeatureIterator = null;
- }
-
- @Override
- protected ListIterator<SimpleFeature> getSourceFeatureIterator() {
- return listFeatureIterator;
- }
-
- @Override
- public boolean hasNext() {
- // check that the feature exists
- while (super.hasNext()) {
- // apply filter
- if (filter.evaluate(curSrcFeature)) {
- return true;
- }
-
- setHasNextCalled(false);
- }
- return false;
- }
-
- @Override
- protected void setNextFeature(String fId, List<Object> foreignIds, ArrayList<Feature> features) throws IOException {
- int prevCount = 0;
- while (listFeatureIterator.hasPrevious()) {
- Feature prev = listFeatureIterator.previous();
- prevCount++;
- // include other rows that don't match the filter, but matches the id of the
- // matching feature.. for denormalised view
- if (extractIdForFeature(prev).equals(fId)) {
- features.add(prev);
- } else {
- break;
- }
- }
- // get back to the original position
- for (int i = 0; i < prevCount; i++) {
- listFeatureIterator.next();
- }
- // then add next features to same id
- super.setNextFeature(fId, foreignIds, features);
- }
-}
Added: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java
===================================================================
--- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java (rev 0)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FilteringMappingFeatureIterator.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -0,0 +1,171 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2010-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+package org.geotools.data.complex;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.geotools.data.Query;
+import org.geotools.data.store.ReprojectingIterator;
+import org.geotools.factory.FactoryRegistryException;
+import org.geotools.geometry.jts.GeometryCoordinateSequenceTransformer;
+import org.opengis.feature.Feature;
+import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.filter.Filter;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.OperationNotFoundException;
+
+/**
+ * An extension to {@linkplain org.geotools.data.complex.DataAccessMappingFeatureIterator} where
+ * filter is present. Since join query between 2 or more tables isn't supported, the only way we can
+ * query nested features is by applying the filter per simple feature (database row). This is done
+ * in hasNext().
+ *
+ * @author Rini Angreani (CSIRO Earth Science and Resource Engineering)
+ *
+ *
+ *
+ * @source $URL$
+ */
+public class FilteringMappingFeatureIterator extends DataAccessMappingFeatureIterator {
+
+ private Filter filter;
+
+ private List<Feature> sources;
+
+ private String currentFeatureId;
+
+ private CoordinateReferenceSystem targetCrs;
+
+ public FilteringMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping,
+ Query query, Query unrolledQuery, Filter filter) throws IOException {
+ super(store, mapping, query, unrolledQuery);
+ this.filter = filter;
+ // don't reproject if there's no geometry, therefore no source CRS (will cause exception)
+ this.targetCrs = (sourceFeatures.getSchema().getGeometryDescriptor() != null) ? super.reprojection
+ : null;
+ }
+
+ public FilteringMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping,
+ Query query, Query unrolledQuery, Filter filter, CoordinateReferenceSystem crs)
+ throws IOException {
+ super(store, mapping, query, unrolledQuery);
+ this.filter = filter;
+ this.targetCrs = crs;
+ }
+
+ @Override
+ protected void initialiseSourceFeatures(FeatureTypeMapping mapping, Query query,
+ CoordinateReferenceSystem crs) throws IOException {
+ super.initialiseSourceFeatures(mapping, query, crs);
+ }
+
+ @Override
+ protected void closeSourceFeatures() {
+ super.closeSourceFeatures();
+ this.sources = null;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (sources != null) {
+ // this is called in the beginning of next()
+ // we don't want to actually check the source iterator again
+ return true;
+ }
+ List<Feature> groupedFeatures;
+ // check that the feature exists
+ boolean matches = false;
+ while (!matches && super.hasNext()) {
+ sources = null;
+ // get all rows with same id from denormalised views
+ // and evaluate each row
+ currentFeatureId = extractIdForFeature(curSrcFeature);
+ try {
+ groupedFeatures = super.getSources(currentFeatureId);
+ Iterator<Feature> srcFeatures = groupedFeatures.iterator();
+ while (!matches && srcFeatures.hasNext()) {
+ // apply filter
+ if (filter == null || filter.evaluate(srcFeatures.next())) {
+ sources = reprojectFeatures(groupedFeatures);
+ matches = true;
+ }
+ }
+ } catch (IOException e) {
+ close();
+ throw new RuntimeException(e);
+ }
+ // reset so next time we call hasNext, it will get the next row
+ setHasNextCalled(false);
+ }
+ return matches;
+ }
+
+ /**
+ * Reproject source features if reprojection is set in the query. This has to be done after filtering, so
+ * it's consistent with JDBCFeatureSource way of filtering and reprojection.
+ * @param srcFeatures
+ * @return
+ * @throws OperationNotFoundException
+ * @throws FactoryRegistryException
+ * @throws FactoryException
+ */
+ @SuppressWarnings("unchecked")
+ private List<Feature> reprojectFeatures(List<Feature> srcFeatures) {
+ if (targetCrs != null) {
+ List<Feature> features = new ArrayList<Feature>();
+ GeometryCoordinateSequenceTransformer transformer = new GeometryCoordinateSequenceTransformer();
+ Iterator<Feature> reprojectedFeatures;
+ try {
+ reprojectedFeatures = new ReprojectingIterator(srcFeatures.iterator(), mappedSource
+ .getSchema().getCoordinateReferenceSystem(), targetCrs,
+ (SimpleFeatureType) this.mappedSource.getSchema(), transformer);
+ while (reprojectedFeatures.hasNext()) {
+ features.add(reprojectedFeatures.next());
+ }
+ } catch (Exception e) {
+ close();
+ throw new RuntimeException ("Failed to reproject features in app-schema!", e);
+ }
+ return features;
+ }
+ return srcFeatures;
+ }
+
+ @Override
+ protected String getNextFeatureId() {
+ return currentFeatureId;
+ }
+
+ @Override
+ protected List<Feature> getSources(String id) throws IOException {
+ // return grouped source features
+ List<Feature> features;
+ if (sources != null) {
+ features = sources;
+ // reset for the next hasNext call
+ sources = null;
+ } else {
+ features = super.getSources(id);
+ }
+ return features;
+ }
+}
Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingAttributeIterator.java
===================================================================
--- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingAttributeIterator.java 2012-01-12 04:24:42 UTC (rev 38478)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingAttributeIterator.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -48,8 +48,8 @@
private Name elementName;
public MappingAttributeIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping,
- Query query, boolean isFiltered, Query unrolledQuery) throws IOException {
- super(store, mapping, query, isFiltered, unrolledQuery);
+ Query query, Query unrolledQuery) throws IOException {
+ super(store, mapping, query, unrolledQuery);
elementName = mapping.getTargetFeature().getName();
checkAttributeMappings();
}
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-01-12 04:24:42 UTC (rev 38478)
+++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java 2012-01-12 07:30:49 UTC (rev 38479)
@@ -34,34 +34,22 @@
import org.geotools.jdbc.JDBCFeatureStore;
import org.opengis.filter.Filter;
import org.opengis.filter.expression.PropertyName;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
/**
* @author Russell Petty (GeoScience Victoria)
- *
- *
- *
- *
- * @source $URL$
+ * @author Rini Angreani (CSIRO Earth Science and Resource Engineering)
+ *
+ * @source $URL:
+ * http://svn.osgeo.org/geotools/trunk/modules/extension/app-schema/app-schema/src/main
+ * /java/org/geotools/data/complex/MappingFeatureIteratorFactory.java $
* http://svn.osgeo.org/geotools/trunk/modules/unsupported/app-schema/app-schema/src/main
* /java/org/geotools/data/complex/MappingFeatureIteratorFactory.java $
*/
public class MappingFeatureIteratorFactory {
protected static final Logger LOGGER = org.geotools.util.logging.Logging
- .getLogger("org.geotools.data.complex");
+ .getLogger("org.geotools.data.complex");
-
- protected static class CheckIfNestedFilterVisitor extends DefaultFilterVisitor {
-
- public boolean hasNestedAttributes = false;
-
- public Object visit( PropertyName expression, Object data ) {
- if (expression instanceof NestedAttributeExpression) {
- hasNestedAttributes = true;
- }
- return data;
- }
- }
-
public static IMappingFeatureIterator getInstance(AppSchemaDataAccess store,
FeatureTypeMapping mapping, Query query, Filter unrolledFilter) throws IOException {
@@ -69,97 +57,107 @@
return new XmlMappingFeatureIterator(store, mapping, query);
}
- if (AppSchemaDataAccessConfigurator.isJoining()) {
+ boolean isJoining = AppSchemaDataAccessConfigurator.isJoining();
+
+ if (isJoining) {
if (!(query instanceof JoiningQuery)) {
query = new JoiningQuery(query);
}
- FeatureSource mappedSource = mapping.getSource();
- FilterCapabilities capabilities = getFilterCapabilities(mappedSource);
-
-
- IMappingFeatureIterator iterator;
- if (unrolledFilter != null) {
- query.setFilter(Filter.INCLUDE);
- Query unrolledQuery = store.unrollQuery(query, mapping);
- unrolledQuery.setFilter(unrolledFilter);
- if (isSimpleType(mapping)) {
- iterator = new MappingAttributeIterator(store, mapping, query, false, unrolledQuery);
- } else {
- iterator = new DataAccessMappingFeatureIterator(store, mapping, query, false, unrolledQuery);
- }
-
+ }
+ IMappingFeatureIterator iterator;
+ if (unrolledFilter != null) {
+ // unrolledFilter is set in JoiningNestedAttributeMapping
+ // so this is for nested features with joining
+ query.setFilter(Filter.INCLUDE);
+ Query unrolledQuery = store.unrollQuery(query, mapping);
+ unrolledQuery.setFilter(unrolledFilter);
+ if (isSimpleType(mapping)) {
+ iterator = new MappingAttributeIterator(store, mapping, query, unrolledQuery);
} else {
+ iterator = new DataAccessMappingFeatureIterator(store, mapping, query,
+ unrolledQuery);
+ }
+ } else {
+ FeatureSource mappedSource = mapping.getSource();
+ if (isJoining || mappedSource instanceof JDBCFeatureSource
+ || mappedSource instanceof JDBCFeatureStore) {
+ // has database as data source, we can use the data source filter capabilities
+ FilterCapabilities capabilities = getFilterCapabilities(mappedSource);
+ ComplexFilterSplitter splitter = new ComplexFilterSplitter(capabilities, mapping);
Filter filter = query.getFilter();
- ComplexFilterSplitter splitter = new ComplexFilterSplitter( capabilities , mapping );
filter.accept(splitter, null);
-
- query.setFilter(splitter.getFilterPre());
+ Filter preFilter = splitter.getFilterPre();
+ query.setFilter(preFilter);
filter = splitter.getFilterPost();
+
int maxFeatures = Query.DEFAULT_MAX;
if (filter != null && filter != Filter.INCLUDE) {
maxFeatures = query.getMaxFeatures();
query.setMaxFeatures(Query.DEFAULT_MAX);
}
- iterator = new DataAccessMappingFeatureIterator(store, mapping, query, false);
+ // need to flag if this is non joining and has pre filter because it needs
+ // 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);
if (filter != null && filter != Filter.INCLUDE) {
- iterator = new PostFilteringMappingFeatureIterator(iterator, filter, maxFeatures);
+ iterator = new PostFilteringMappingFeatureIterator(iterator, filter,
+ maxFeatures);
}
- }
- return iterator;
- } else {
- if (query.getFilter() != null) {
+ } else if (mappedSource instanceof MappingFeatureSource) {
+ // web service data access wrapper
+ iterator = new DataAccessMappingFeatureIterator(store, mapping, query);
+ } else {
+ // non database sources e.g. property data store
Query unrolledQuery = store.unrollQuery(query, mapping);
Filter filter = unrolledQuery.getFilter();
- CheckIfNestedFilterVisitor visitor = new CheckIfNestedFilterVisitor();
- filter.accept(visitor, null);
- if (visitor.hasNestedAttributes) {
- FeatureSource mappedSource = mapping.getSource();
- if (mappedSource instanceof JDBCFeatureSource
- || mappedSource instanceof JDBCFeatureStore) {
- FilterCapabilities capabilities = getFilterCapabilities(mappedSource);
- ComplexFilterSplitter splitter = new ComplexFilterSplitter(capabilities,
- mapping);
- filter.accept(splitter, null);
- query.setFilter(splitter.getFilterPre());
- unrolledQuery.setFilter(splitter.getFilterPre());
- filter = splitter.getFilterPost();
- } else {
- // VT:no Filtering capbilities cause source may not be of jdbc type
- // therefore we continue;
- // has nested attribute in the filter expression
- unrolledQuery.setFilter(Filter.INCLUDE);
- }
- return new FilteringMappingFeatureIterator(store, mapping, query,
- unrolledQuery, filter);
- } else if (!filter.equals(Filter.INCLUDE) && !filter.equals(Filter.EXCLUDE)
+
+ if (!filter.equals(Filter.INCLUDE) && !filter.equals(Filter.EXCLUDE)
&& !(filter instanceof FidFilterImpl)) {
- // normal filters
- if (isSimpleType(mapping)) {
- return new MappingAttributeIterator(store, mapping, query, true, unrolledQuery);
- } else {
- return new DataAccessMappingFeatureIterator(store, mapping, query, true, unrolledQuery);
+ // non joining with filters
+ // the filter can't be passed to the data source as is and has to be
+ // performed
+ // per simple feature
+ // also in case the data is denormalised and the 2nd row matches the filter, it
+ // will still find the first row
+ // since this iterator would group the sources by id before evaluating the
+ // filter
+ unrolledQuery.setFilter(Filter.INCLUDE);
+
+ CoordinateReferenceSystem crs = query.getCoordinateSystemReproject();
+ if (crs != null) {
+ // remove reprojection too, as it should be done after filter is applied
+ // to be consistent with app-schema with JDBC sources
+ unrolledQuery.setCoordinateSystemReproject(null);
}
+ iterator = new FilteringMappingFeatureIterator(store, mapping, query,
+ unrolledQuery, filter);
+ } else {
+ // non database sources with no filters
+ iterator = new DataAccessMappingFeatureIterator(store, mapping, query);
}
}
-
- return new DataAccessMappingFeatureIterator(store, mapping, query, false);
}
+
+ return iterator;
}
-
+
private static boolean isSimpleType(FeatureTypeMapping mapping) {
- return Types.isSimpleContentType(mapping.getTargetFeature().getType());
+ return Types.isSimpleContentType(mapping.getTargetFeature().getType());
}
-
- private static FilterCapabilities getFilterCapabilities(FeatureSource mappedSource)throws IllegalArgumentException{
- FilterCapabilities capabilities=null;
+
+ private static FilterCapabilities getFilterCapabilities(FeatureSource mappedSource)
+ throws IllegalArgumentException {
+ FilterCapabilities capabilities = null;
if (mappedSource instanceof JDBCFeatureSource) {
- capabilities = ((JDBCFeatureSource) mappedSource).getDataStore().getFilterCapabilities();
- } else if (mappedSource instanceof JDBCFeatureStore){
+ capabilities = ((JDBCFeature...
[truncated message content] |