/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2011, Open Source Geospatial Foundation (OSGeo) * (C) 2008-2011 TOPP - www.openplans.org. * * 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.process.feature.gs; import java.util.Iterator; import java.util.NoSuchElementException; import org.geotools.process.factory.DescribeParameter; import org.geotools.process.factory.DescribeProcess; import org.geotools.process.factory.DescribeResult; import org.geotools.process.gs.GSProcess; import org.geotools.process.gs.WrappingIterator; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.collection.DecoratingSimpleFeatureCollection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory2; import com.vividsolutions.jts.geom.Geometry; /** * A process providing a feature collection containing the features of the first input collection * which are included in the second feature collection * * @author Gianni Barrotta - Sinergis * @author Andrea Di Nora - Sinergis * @author Pietro Arena - Sinergis */ @DescribeProcess(title = "inclusion", description = "Provide a feature collection containing the features of " + "the first input collection included in at least one feature of the the second feature collection") public class InclusionFeatureCollection implements GSProcess { @DescribeResult(description = "feature collection containg the features of the first collection included in the second collection") public SimpleFeatureCollection execute( @DescribeParameter(name = "first feature collection", description = "First feature collection") SimpleFeatureCollection firstFeatures, @DescribeParameter(name = "second feature collection", description = "Second feature collection") SimpleFeatureCollection secondFeatures) { return new IncludedFeatureCollection(firstFeatures, secondFeatures); } /** * Wrapper that will trigger the "included" computation as features are requested */ static class IncludedFeatureCollection extends DecoratingSimpleFeatureCollection { SimpleFeatureCollection features; public IncludedFeatureCollection(SimpleFeatureCollection delegate, SimpleFeatureCollection features) { super(delegate); this.features = features; } @Override public SimpleFeatureIterator features() { return new IncludedFeatureIterator(delegate.features(), delegate, features, getSchema()); } @Override public Iterator<SimpleFeature> iterator() { return new WrappingIterator(features()); } @Override public void close(Iterator<SimpleFeature> close) { if (close instanceof WrappingIterator) { ((WrappingIterator) close).close(); } } } /** * Computes the inclusion property as we stream */ static class IncludedFeatureIterator implements SimpleFeatureIterator { SimpleFeatureIterator delegate; SimpleFeatureCollection firstFeatures; SimpleFeatureCollection secondFeatures; SimpleFeatureBuilder fb; SimpleFeature next; String dataGeomName; FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null); public IncludedFeatureIterator(SimpleFeatureIterator delegate, SimpleFeatureCollection firstFeatures, SimpleFeatureCollection secondFeatures, SimpleFeatureType schema) { this.delegate = delegate; this.firstFeatures = firstFeatures; this.secondFeatures = secondFeatures; this.fb = new SimpleFeatureBuilder(schema); this.dataGeomName = this.firstFeatures.getSchema().getGeometryDescriptor() .getLocalName(); } public void close() { delegate.close(); } public boolean hasNext() { while (next == null && delegate.hasNext()) { SimpleFeature f = delegate.next(); for (Object attribute : f.getAttributes()) { if (attribute instanceof Geometry) { Geometry geom = (Geometry) attribute; Filter overFilter = ff .contains(ff.property(dataGeomName), ff.literal(geom)); SimpleFeatureCollection subFeatureCollectionInclusion = this.secondFeatures .subCollection(overFilter); if (subFeatureCollectionInclusion.size() > 0) { next = f; } } } } return next != null; } public SimpleFeature next() throws NoSuchElementException { if (!hasNext()) { throw new NoSuchElementException("hasNext() returned false!"); } SimpleFeature result = next; next = null; return result; } } }