/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2009-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.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.joining.JoiningQuery;
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.filter.Filter;
import org.opengis.filter.expression.PropertyName;
/**
* @author Russell Petty (GeoScience Victoria)
*
*
*
* @source $URL$
* 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");
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 {
if (mapping instanceof XmlFeatureTypeMapping) {
return new XmlMappingFeatureIterator(store, mapping, query);
}
if (AppSchemaDataAccessConfigurator.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);
iterator = new DataAccessMappingFeatureIterator(store, mapping, query, false, unrolledQuery);
} else {
Filter filter = query.getFilter();
ComplexFilterSplitter splitter = new ComplexFilterSplitter( capabilities , mapping );
filter.accept(splitter, null);
query.setFilter(splitter.getFilterPre());
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);
if (filter != null && filter != Filter.INCLUDE) {
iterator = new PostFilteringMappingFeatureIterator(iterator, filter, maxFeatures);
}
}
return iterator;
} else {
if (query.getFilter() != null) {
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)
&& !(filter instanceof FidFilterImpl)) {
// normal filters
return new DataAccessMappingFeatureIterator(store, mapping, query, true,
unrolledQuery);
}
}
return new DataAccessMappingFeatureIterator(store, mapping, query, false);
}
}
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 = ((JDBCFeatureStore) mappedSource).getDataStore().getFilterCapabilities();
} else {
throw new IllegalArgumentException("Joining queries are only supported on JDBC data stores");
}
return capabilities;
}
}