/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-2008, 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.store; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.data.FeatureReader; import org.geotools.data.FeatureWriter; import org.geotools.data.collection.DelegateFeatureReader; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.feature.CollectionEvent; import org.geotools.feature.CollectionListener; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.feature.FeatureReaderIterator; import org.geotools.feature.collection.DelegateSimpleFeatureIterator; import org.geotools.feature.collection.SubFeatureCollection; import org.geotools.filter.SortBy2; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.util.NullProgressListener; import org.opengis.feature.Feature; import org.opengis.feature.IllegalAttributeException; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.filter.sort.SortBy; /** * A starting point for implementing FeatureCollection's backed onto a FeatureReader. *
* This implementation requires you to implement the following: *
* This class will implement the 'extra' methods required by FeatureCollection * for you (in simple terms based on the FeatureResults API). Anything that is * often customised is available to you as a constructor parameters. *
* Enjoy. *
* @author jgarnett * @since 2.1.RC0 * * * @source $URL$ */ public abstract class DataFeatureCollection implements SimpleFeatureCollection { /** logger */ static Logger LOGGER = org.geotools.util.logging.Logging.getLogger( "org.geotools.data" ); static private int unique = 0; /** * Collection based on a generic collection */ protected DataFeatureCollection(){ this( "features"+(unique++) ); } /** * Collection based on a generic collection */ protected DataFeatureCollection( String id ){ this(id,null); } /** Subclass must think about what consitructors it needs. */ protected DataFeatureCollection( String id, SimpleFeatureType memberType ){ this.id = id == null ? "featureCollection" : id; this.schema = memberType; } /** * To let listeners know that something has changed. */ protected void fireChange(SimpleFeature[] features, int type) { CollectionEvent cEvent = new CollectionEvent(this, features, type); for (int i = 0, ii = listeners.size(); i < ii; i++) { ((CollectionListener) listeners.get(i)).collectionChanged(cEvent); } } protected void fireChange(SimpleFeature feature, int type) { fireChange(new SimpleFeature[] {feature}, type); } protected void fireChange(Collection coll, int type) { SimpleFeature[] features = new SimpleFeature[coll.size()]; features = (SimpleFeature[]) coll.toArray(features); fireChange(features, type); } public FeatureReader* All operations that attempt to modify the "data" will * use this method, allowing them to throw an "UnsupportedOperationException" * in the same manner as Collections.unmodifiableCollection(Collection c), or just * return null. *
* @throws UnsupportedOperationException To indicate that write support is not avaiable * @return the writer, or null if write support is not available */ protected FeatureWriter
* So when we implement FeatureCollection.iterator() this will work
* out of the box.
*/
public SimpleFeatureIterator features() {
SimpleFeatureIterator iterator = new DelegateSimpleFeatureIterator( this, iterator() );
open.add( iterator );
return iterator;
}
/**
* Iterator may (or may) not support modification.
*/
final public Iterator
* If you have a way to tell that you are readonly please subclass with
* a less hardcore check - this implementations catches a
* UnsupportedOpperationsException from wrtier()!
*
* @return Iterator, should be closed closeIterator
*/
protected Iterator
* For once the Collections API does not give us an escape route, we *have* to check the data.
*
* This method is constructed by either:
*
* The subCollection is constructed by using an AND Filter.
* For the converse of this opperation please see
* collection.addAll( Collection ), it has been optimized
* to be aware of these filter based SubCollections.
*
* This method is intended in a manner similar to subList,
* example use:
*
* Sorts may be combined togther in a stable fashion, in congruence
* with the Filter 1.1 specification.
*
* Advanced in this case really means making use of a generic
* Expression, rather then being limited to PropertyName.
*
*
*
*/
public boolean addAll(Collection collection) {
if( collection instanceof FeatureCollection ){
return addAll( (FeatureCollection,?>) collection );
}
try {
FeatureWriter writer = writer();
if(writer == null) {
return false;
}
try {
// skip to end
while( writer.hasNext() ){
Feature feature = writer.next();
}
for( Object obj : collection ){
if( obj instanceof SimpleFeature){
SimpleFeature copy = (SimpleFeature) obj;
SimpleFeature feature = (SimpleFeature) writer.next();
feature.setAttributes( copy.getAttributes() );
writer.write();
}
}
}
finally {
if( writer != null ) writer.close();
}
return true;
}
catch( IOException ignore ){
return false;
}
}
public boolean addAll(FeatureCollection resource) {
return false;
}
public boolean removeAll( Collection arg0 ) {
return false;
}
public boolean retainAll( Collection arg0 ) {
return false;
}
public void clear() {
}
public void accepts(org.opengis.feature.FeatureVisitor visitor, org.opengis.util.ProgressListener progress) {
Iterator iterator = null;
if (progress == null) progress = new NullProgressListener();
try{
float size = size();
float position = 0;
progress.started();
for( iterator = iterator(); !progress.isCanceled() && iterator.hasNext(); progress.progress( 100.0f * position++ / size )){
try {
SimpleFeature feature = (SimpleFeature) iterator.next();
visitor.visit(feature);
}
catch( Exception erp ){
progress.exceptionOccurred( erp );
}
}
}
finally {
progress.complete();
close( iterator );
}
}
/**
* Will return an optimized subCollection based on access
* to the origional FeatureSource.
*
* collection.subCollection( myFilter ).clear()
*
*