/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2003-2012, 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.feature.collection; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import org.geotools.data.DataUtilities; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.feature.FeatureIterator; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.filter.sort.SortBy; /** * Implement a feature collection just based on provision of an {@link Iterator}. * <p> * This implementation asks you to implement: * <ul> * <li>{@link #openIterator()}</li> * <li>{@link #size()}</li> * <li> * User interaction is provided by the public API for FeatureCollection: * <ul> * <li>{@link #features()}: makes use of {@link DelegateSimpleFeatureIterator} (if needed) to wrap your iterator up as a SimpleFeatureIterator for * public use.</li> * </ul> * This is the origional implementation of FeatureCollection and is recommended * when presenting {@link Collection} classes as a FeatureCollection. * * @author Jody Garnett (LISAsoft) * * @source $URL$ */ public abstract class AbstractFeatureCollection implements SimpleFeatureCollection { /** * id used when serialized to gml */ protected String id; protected SimpleFeatureType schema; protected AbstractFeatureCollection(SimpleFeatureType memberType) { this.id = id == null ? "featureCollection" : id; this.schema = memberType; } // // SimpleFeatureCollection - Feature Access // public SimpleFeatureIterator features() { Iterator<SimpleFeature> iterator = openIterator(); if (iterator instanceof SimpleFeatureIterator) { return (SimpleFeatureIterator) iterator; } else { SimpleFeatureIterator iter = new DelegateSimpleFeatureIterator(this, iterator); return iter; } } /** * Factory method used to open an iterator over collection contents * for use by {@link #iterator()} and {@link #features()}. * <p> * If you return an instance of FeatureIterator some effort * is taken to call the {@link FeatureIterator#close()} internally, however * we cannot offer any assurance that client code using {@link #iterator()} * will perform the same check. * * @return Iterator over collection contents */ abstract protected Iterator<SimpleFeature> openIterator(); /** * Returns the number of elements in this collection. * * @return Number of items, or Interger.MAX_VALUE */ public abstract int size(); /** * Returns <tt>true</tt> if this collection contains the specified * element. * <tt></tt>.<p> * * This implementation iterates over the elements in the collection, * checking each element in turn for equality with the specified element. * * @param o object to be checked for containment in this collection. * @return <tt>true</tt> if this collection contains the specified element. */ public boolean contains(Object o) { Iterator<SimpleFeature> e = null; e = iterator(); try { if (o == null) { while (e.hasNext()) if (e.next() == null) return true; } else { while (e.hasNext()) if (o.equals(e.next())) return true; } return false; } finally { if( e instanceof FeatureIterator ){ ((FeatureIterator<?>)e).close(); } } } /** * Returns <tt>true</tt> if this collection contains all of the elements * in the specified collection. <p> * * @param c collection to be checked for containment in this collection. * @return <tt>true</tt> if this collection contains all of the elements * in the specified collection. * @throws NullPointerException if the specified collection is null. * * @see #contains(Object) */ public boolean containsAll(Collection<?> c) { Iterator<?> e = c.iterator(); while (e.hasNext()){ if(!contains(e.next())){ return false; } } return true; } // // Contents // // /** * Provides acess to {@link #openIterator()} used to traverse collection contents. * <p> * You are asked to perform the following check when finished with the iterator:<pre> if( e instanceof FeatureIterator ){ * (FeatureIterator<?>)iterator).close(); * }</pre> * @return Iterator traversing collection contents */ final public Iterator<SimpleFeature> iterator(){ Iterator<SimpleFeature> iterator = openIterator(); return iterator; } /** * @return <tt>true</tt> if this collection contains no elements. */ public boolean isEmpty() { Iterator<SimpleFeature> iterator = iterator(); try { return !iterator.hasNext(); } finally { if( iterator instanceof FeatureIterator){ ((FeatureIterator<?>)iterator).close(); } } } /** * Array of all the elements. * * @return an array containing all of the elements in this collection. */ public Object[] toArray() { Object[] result = new Object[size()]; Iterator<SimpleFeature> e = null; try { e = iterator(); for (int i=0; e.hasNext(); i++) result[i] = e.next(); return result; } finally { if( e instanceof FeatureIterator){ ((FeatureIterator<?>)e).close(); } } } @SuppressWarnings("unchecked") public <O> O[] toArray(O[] a) { int size = size(); if (a.length < size){ a = (O[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); } Iterator<SimpleFeature> it = iterator(); try { Object[] result = a; for (int i=0; i<size; i++) result[i] = it.next(); if (a.length > size) a[size] = null; return a; } finally { if( it instanceof FeatureIterator){ ((FeatureIterator<?>)it).close(); } } } public void accepts(org.opengis.feature.FeatureVisitor visitor, org.opengis.util.ProgressListener progress) throws IOException { DataUtilities.visit(this, visitor, progress); } // // Feature Collections API // public SimpleFeatureCollection subCollection( Filter filter ) { if( filter == Filter.INCLUDE ){ return this; } return new SubFeatureCollection( this, filter ); } public SimpleFeatureCollection sort( SortBy order ) { return new SubFeatureList(this, order ); } public String getID() { return id; } public SimpleFeatureType getSchema() { return schema; } /** * Subclasses need to override this. */ public abstract ReferencedEnvelope getBounds(); }