/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-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.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.geotools.data.DataUtilities; import org.geotools.data.DefaultQuery; import org.geotools.data.FeatureEvent; import org.geotools.data.FeatureListener; import org.geotools.data.FeatureReader; import org.geotools.data.Query; import org.geotools.feature.CollectionEvent; import org.geotools.feature.CollectionListener; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.feature.visitor.FeatureVisitor; import org.geotools.filter.SortBy; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.util.NullProgressListener; import org.geotools.util.ProgressListener; import org.opengis.feature.GeometryAttribute; 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.Name; import org.opengis.filter.Filter; import org.opengis.filter.identity.FeatureId; /** * A FeatureCollection that completly delegates to a backing FetaureSource. * * @author Jody Garnett (Refractions Research, Inc.) * * @source $URL$ */ public class ContentFeatureCollection implements FeatureCollection<SimpleFeatureType, SimpleFeature> { /** * feature store the collection originated from. */ protected ContentFeatureSource featureSource; protected Query query; /** * feature (possibly retyped from feautre source original) type */ protected SimpleFeatureType featureType; /** * state of the feature source */ protected ContentState state; /** Internal listener storage list */ protected List listeners = new ArrayList(2); /** Set of open resource iterators */ protected final Set open = new HashSet(); /** * feature listener which listens to the feautre source and * forwards events to its listeners. */ FeatureListener listener = new FeatureListener(){ public void changed(FeatureEvent featureEvent) { if( listeners.isEmpty() ) return; FeatureCollection<SimpleFeatureType, SimpleFeature> collection; collection = (FeatureCollection<SimpleFeatureType, SimpleFeature>) ContentFeatureCollection.this; CollectionEvent event = new CollectionEvent( collection, featureEvent ); CollectionListener[] notify = (CollectionListener[]) listeners.toArray( new CollectionListener[ listeners.size() ]); for( int i=0; i<notify.length; i++ ){ CollectionListener listener = notify[i]; try { listener.collectionChanged( event ); } catch (Throwable t ){ //TODO: log this //ContentDataStore.LOGGER.log( Level.WARNING, "Problem encountered during notification of "+event, t ); } } } }; protected ContentFeatureCollection( ContentFeatureSource featureSource, Query query ) { this.featureSource = featureSource; this.query = query; //retype feature type if necessary if ( query.getPropertyNames() != Query.ALL_NAMES ) { this.featureType = SimpleFeatureTypeBuilder.retype(featureSource.getSchema(), query.getPropertyNames() ); } else { this.featureType = featureSource.getSchema(); } } public SimpleFeatureType getSchema() { return featureType; } //Visitors /** * Accepts a visitor, which then visits each feature in the collection. * @throws IOException */ public void accepts(FeatureVisitor visitor, ProgressListener progress ) throws IOException { accepts( (org.opengis.feature.FeatureVisitor) visitor, (org.opengis.util.ProgressListener) progress ); } public void accepts(org.opengis.feature.FeatureVisitor visitor, org.opengis.util.ProgressListener progress) throws IOException { featureSource.accepts( query, visitor, progress); } //Listeners /** * Adds a listener for collection events. * * @param listener The listener to add */ public void addListener(CollectionListener listener) { // create the bridge only if we have collection listeners around synchronized (listeners) { if(listeners.size() == 0) { featureSource.addFeatureListener(this.listener); } listeners.add(listener); } } /** * Removes a listener for collection events. * * @param listener The listener to remove */ public void removeListener(CollectionListener listener) { // as soon as the listeners are out we clean up synchronized (listeners) { listeners.remove(listener); if(listeners.size() == 0) featureSource.removeFeatureListener(this.listener); } } // Iterators public static class WrappingFeatureIterator implements FeatureIterator<SimpleFeature> { FeatureReader<SimpleFeatureType, SimpleFeature> delegate; public WrappingFeatureIterator( FeatureReader<SimpleFeatureType, SimpleFeature> delegate ) { this.delegate = delegate; } public boolean hasNext() { try { return delegate.hasNext(); } catch( IOException e ) { throw new RuntimeException( e ); } } public SimpleFeature next() throws java.util.NoSuchElementException { try { return delegate.next(); } catch( IOException e ) { throw new RuntimeException( e ); } } public void close() { try { delegate.close(); } catch( IOException e ) { throw new RuntimeException( e ); } } } public FeatureIterator<SimpleFeature> features(){ try { return new WrappingFeatureIterator( featureSource.getReader(query) ); } catch( IOException e ) { throw new RuntimeException( e ); } } public void close( FeatureIterator<SimpleFeature> iterator ) { iterator.close(); } public static class WrappingIterator implements Iterator { FeatureReader<SimpleFeatureType, SimpleFeature> delegate; public WrappingIterator( FeatureReader<SimpleFeatureType, SimpleFeature> delegate ) { this.delegate = delegate; } public boolean hasNext() { try { return delegate.hasNext(); } catch( IOException e ) { throw new RuntimeException( e ); } } public Object next() { try { return delegate.next(); } catch( IOException e ) { throw new RuntimeException( e ); } } public void remove() { throw new UnsupportedOperationException(); } } public Iterator iterator() { try { return new WrappingIterator( featureSource.getReader(query) ); } catch( IOException e ) { throw new RuntimeException( e ); } } public void close(Iterator close) { try { ((WrappingIterator)close).delegate.close(); } catch( IOException e ) { throw new RuntimeException( e ); } } public ReferencedEnvelope getBounds() { try { return featureSource.getBounds(query); } catch( IOException e ) { throw new RuntimeException( e ); } } public int size() { try { return featureSource.getCount(query); } catch (IOException e) { throw new RuntimeException(e); } } public boolean isEmpty() { return size() == 0; } public boolean add(SimpleFeature o) { return addAll(Collections.singletonList(o)); } ContentFeatureStore ensureFeatureStore() { if ( featureSource instanceof ContentFeatureStore ) { return (ContentFeatureStore) featureSource; } throw new UnsupportedOperationException( "read only" ); } public boolean addAll(Collection c) { ContentFeatureStore featureStore = ensureFeatureStore(); try { List<FeatureId> ids = featureStore.addFeatures(c); return ids.size() == c.size(); } catch (IOException e) { throw new RuntimeException(e); } } public boolean addAll(FeatureCollection c) { ContentFeatureStore featureStore = ensureFeatureStore(); try { List<FeatureId> ids; ids = featureStore.addFeatures( c ); return ids.size() == c.size(); } catch (IOException e) { throw new RuntimeException(e); } } public void clear() { ContentFeatureStore featureStore = ensureFeatureStore(); try { featureStore.removeFeatures(query.getFilter()); } catch (IOException e) { throw new RuntimeException(e); } } public void purge() { //do nothing } public FeatureCollection<SimpleFeatureType, SimpleFeature> sort(SortBy order) { return sort( (org.opengis.filter.sort.SortBy) order ); } public FeatureCollection<SimpleFeatureType, SimpleFeature> sort(org.opengis.filter.sort.SortBy sort) { Query query = new DefaultQuery(); ((DefaultQuery)query).setSortBy( new org.opengis.filter.sort.SortBy[]{sort}); query = DataUtilities.mixQueries( this.query, query, null ); return new ContentFeatureCollection( featureSource, query ); } public FeatureCollection<SimpleFeatureType, SimpleFeature> subCollection(Filter filter) { Query query = new DefaultQuery(); ((DefaultQuery)query).setFilter( filter ); query = DataUtilities.mixQueries(this.query, query, null); return new ContentFeatureCollection( featureSource, query ); } //Unsupported public boolean contains(Object o) { throw new UnsupportedOperationException(); } public boolean containsAll(Collection collection) { throw new UnsupportedOperationException(); } public boolean remove(Object o) { throw new UnsupportedOperationException(); } public boolean removeAll(Collection collection) { throw new UnsupportedOperationException(); } public boolean retainAll(Collection collection) { throw new UnsupportedOperationException(); } public Object[] toArray() { throw new UnsupportedOperationException(); } public Object[] toArray(Object[] array) { throw new UnsupportedOperationException(); } public Object getAttribute(String name) { throw new UnsupportedOperationException(); } public Object getAttribute(Name name) { throw new UnsupportedOperationException(); } public Object getAttribute(int indedx) throws IndexOutOfBoundsException { throw new UnsupportedOperationException(); } public int getAttributeCount() { throw new UnsupportedOperationException(); } public List<Object> getAttributes() { throw new UnsupportedOperationException(); } public Object getDefaultGeometry() { throw new UnsupportedOperationException(); } public SimpleFeatureType getFeatureType() { throw new UnsupportedOperationException(); } public SimpleFeatureType getType() { throw new UnsupportedOperationException(); } public void setAttribute(String name, Object value) { throw new UnsupportedOperationException(); } public void setAttribute(Name name, Object value) { throw new UnsupportedOperationException(); } public void setAttribute(int index, Object value) throws IndexOutOfBoundsException { throw new UnsupportedOperationException(); } public void setAttributes(List<Object> attributes) { throw new UnsupportedOperationException(); } public void setAttributes(Object[] attributes) { throw new UnsupportedOperationException(); } public void setDefaultGeometry(Object defaultGeometry) { throw new UnsupportedOperationException(); } public GeometryAttribute getDefaultGeometryProperty() { throw new UnsupportedOperationException(); } public FeatureId getIdentifier() { throw new UnsupportedOperationException(); } public String getID() { throw new UnsupportedOperationException(); } public void setDefaultGeometryProperty(GeometryAttribute defaultGeometryProperty) { throw new UnsupportedOperationException(); } public Collection<Property> getProperties() { throw new UnsupportedOperationException(); } public Collection<Property> getProperties(Name name) { throw new UnsupportedOperationException(); } public Collection<Property> getProperties(String name) { throw new UnsupportedOperationException(); } public Property getProperty(Name name) { throw new UnsupportedOperationException(); } public Property getProperty(String name) { throw new UnsupportedOperationException(); } public Collection<? extends Property> getValue() { throw new UnsupportedOperationException(); } public void setValue(Collection<Property> value) { throw new UnsupportedOperationException(); } public AttributeDescriptor getDescriptor() { throw new UnsupportedOperationException(); } public Name getName() { throw new UnsupportedOperationException(); } public Map<Object, Object> getUserData() { throw new UnsupportedOperationException(); } public boolean isNillable() { throw new UnsupportedOperationException(); } public void setValue(Object value) { throw new UnsupportedOperationException(); } public void validate() { } }