001: package org.geotools.data.jdbc.collection;
002:
003: import java.io.IOException;
004: import java.sql.ResultSet;
005: import java.sql.SQLException;
006: import java.sql.Statement;
007: import java.util.ArrayList;
008: import java.util.Collection;
009: import java.util.HashSet;
010: import java.util.Iterator;
011: import java.util.List;
012: import java.util.Set;
013: import java.util.logging.Level;
014:
015: import org.geotools.data.FeatureEvent;
016: import org.geotools.data.FeatureListener;
017: import org.geotools.data.jdbc.JDBCDataStore;
018: import org.geotools.data.jdbc.JDBCFeatureSource;
019: import org.geotools.data.jdbc.JDBCRunnable;
020: import org.geotools.data.jdbc.JDBCState;
021: import org.geotools.data.jdbc.JDBCUtils;
022: import org.geotools.data.jdbc.SQLBuilder;
023: import org.geotools.data.store.FeatureIteratorIterator;
024: import org.geotools.feature.CollectionEvent;
025: import org.geotools.feature.CollectionListener;
026: import org.geotools.feature.Feature;
027: import org.geotools.feature.FeatureCollection;
028: import org.geotools.feature.FeatureIterator;
029: import org.geotools.feature.FeatureList;
030: import org.geotools.feature.FeatureType;
031: import org.geotools.feature.IllegalAttributeException;
032: import org.geotools.feature.visitor.FeatureVisitor;
033: import org.geotools.geometry.jts.ReferencedEnvelope;
034: import org.geotools.util.ProgressListener;
035: import org.opengis.filter.Filter;
036: import org.opengis.filter.sort.SortBy;
037:
038: import com.vividsolutions.jts.geom.Envelope;
039: import com.vividsolutions.jts.geom.Geometry;
040:
041: /**
042: * Contains some common state needed for all JDBCFeatureCollections.
043: * <p>
044: * Please note the result does *not* implement FeatureCollection itself (
045: * as you may want to choose between FeatureList and FeatureCollection).
046: *
047: * @author Jody
048: */
049: public class JDBCFeatureCollection implements FeatureCollection {
050:
051: /**
052: * feature sourfce the collection originated from.
053: */
054: JDBCFeatureSource source;
055: /**
056: * state of the feature source
057: */
058: JDBCState state;
059: /**
060: * filter used to filter content.
061: */
062: Filter filter;
063:
064: /**
065: * feature listener which listens to the feautre source and
066: * forwards events to its listeners.
067: */
068: FeatureListener listener = new FeatureListener() {
069: public void changed(FeatureEvent featureEvent) {
070: if (listeners.isEmpty())
071: return;
072:
073: FeatureCollection collection = (FeatureCollection) JDBCFeatureCollection.this ;
074: CollectionEvent event = new CollectionEvent(collection,
075: featureEvent);
076:
077: CollectionListener[] notify = (CollectionListener[]) listeners
078: .toArray(new CollectionListener[listeners.size()]);
079: for (int i = 0; i < notify.length; i++) {
080: CollectionListener listener = notify[i];
081: try {
082: listener.collectionChanged(event);
083: } catch (Throwable t) {
084: source.getLogger().log(
085: Level.WARNING,
086: "Problem encountered during notification of "
087: + event, t);
088: }
089: }
090: }
091: };
092:
093: /** Internal listener storage list */
094: private List listeners = new ArrayList(2);
095:
096: /** Set of open resource iterators */
097: protected final Set open = new HashSet();
098:
099: public JDBCFeatureCollection(JDBCFeatureSource source,
100: JDBCState state) {
101: this (source, state, null);
102: }
103:
104: public JDBCFeatureCollection(JDBCFeatureSource source,
105: JDBCState state, Filter filter) {
106: this .source = source;
107: this .state = state;
108: this .filter = filter;
109:
110: //add the feautre source listener
111: source.addFeatureListener(listener);
112:
113: //ensure the state has a connection
114: if (state.getConnection() == null) {
115: state.setConnection(((JDBCDataStore) source.getDataStore())
116: .connection());
117: }
118: }
119:
120: /**
121: * @return The feautre source the collection originates from.
122: */
123: public JDBCFeatureSource getFeatureSource() {
124: return source;
125: }
126:
127: /**
128: * Sets a filter used to "filter" the content of the collection.
129: */
130: public void setFilter(Filter filter) {
131: this .filter = filter;
132: }
133:
134: /**
135: * @return The filter being used to "filter" the collection.
136: */
137: public Filter getFilter() {
138: return filter;
139: }
140:
141: /**
142: * Adds a listener for collection events.
143: *
144: * @param listener The listener to add
145: */
146: public void addListener(CollectionListener listener) {
147: listeners.add(listener);
148: }
149:
150: /**
151: * Removes a listener for collection events.
152: *
153: * @param listener The listener to remove
154: */
155: public void removeListener(CollectionListener listener) {
156: listeners.remove(listener);
157: }
158:
159: // Iterators
160: public FeatureIterator features() {
161: FeatureIterator iterator;
162: try {
163: iterator = createFeatureIterator();
164: } catch (Exception e) {
165: throw new RuntimeException(e);
166: }
167:
168: // keep track of the iterator
169: open.add(iterator);
170:
171: return iterator;
172: }
173:
174: public void close(FeatureIterator close) {
175: close.close();
176: open.remove(close);
177: }
178:
179: public Iterator iterator() {
180: FeatureIterator iterator = features();
181: return new FeatureIteratorIterator(iterator);
182: }
183:
184: public void close(Iterator close) {
185: if (close instanceof FeatureIteratorIterator) {
186: FeatureIteratorIterator iterator = (FeatureIteratorIterator) close;
187: close(iterator.getDelegate());
188: }
189: }
190:
191: protected FeatureIterator createFeatureIterator() throws Exception {
192: SQLBuilder sql = new SQLBuilder((JDBCDataStore) source
193: .getDataStore());
194:
195: Statement st = state.getConnection().createStatement();
196: st.execute(sql.select(source.getSchema(), filter));
197:
198: return new JDBCFeatureIterator(st, this );
199: }
200:
201: public void purge() {
202: for (Iterator i = open.iterator(); i.hasNext();) {
203: Object resource = i.next();
204: if (resource instanceof FeatureIterator) {
205: FeatureIterator resourceIterator = (FeatureIterator) resource;
206: try {
207: close(resourceIterator);
208: } catch (Throwable e) {
209: String msg = "Error occured closing iterator";
210: source.getLogger().log(Level.WARNING, msg, e);
211: } finally {
212: i.remove();
213: }
214: }
215: }
216: }
217:
218: /**
219: * Accepts a visitor, which then visits each feature in the collection.
220: * @throws IOException
221: */
222: public void accepts(FeatureVisitor visitor,
223: ProgressListener progress) throws IOException {
224: Iterator iterator = null;
225: // if( progress == null ) progress = new NullProgressListener();
226: try {
227: float size = size();
228: float position = 0;
229: progress.started();
230: for (iterator = iterator(); !progress.isCanceled()
231: && iterator.hasNext();) {
232: if (size > 0)
233: progress.progress(position++ / size);
234: try {
235: Feature feature = (Feature) iterator.next();
236: visitor.visit(feature);
237: } catch (Exception erp) {
238: progress.exceptionOccurred(erp);
239: }
240: }
241: } finally {
242: progress.complete();
243: close(iterator);
244: }
245: }
246:
247: public FeatureType getSchema() {
248: return source.getSchema();
249: }
250:
251: public ReferencedEnvelope getBounds() {
252:
253: JDBCRunnable runnable = new JDBCRunnable() {
254:
255: public Object run(Statement statement) throws IOException,
256: SQLException {
257:
258: Envelope bounds = new Envelope();
259:
260: SQLBuilder sql = new SQLBuilder((JDBCDataStore) source
261: .getDataStore());
262: ResultSet rs = statement.executeQuery(sql.bounds(source
263: .getSchema(), filter));
264:
265: if (rs.next()) {
266: bounds.init((Envelope) rs.getObject(1));
267: while (rs.next()) {
268: bounds.expandToInclude((Envelope) rs
269: .getObject(1));
270: }
271: } else {
272: bounds.setToNull();
273: }
274:
275: rs.close();
276:
277: return ReferencedEnvelope.reference(bounds);
278: }
279:
280: };
281:
282: try {
283: return (ReferencedEnvelope) JDBCUtils.statement(state
284: .getConnection(), runnable);
285: } catch (IOException e) {
286: throw new RuntimeException(e);
287: }
288: }
289:
290: public int size() {
291: JDBCRunnable runnable = new JDBCRunnable() {
292:
293: public Object run(Statement statement) throws IOException,
294: SQLException {
295: SQLBuilder sql = new SQLBuilder((JDBCDataStore) source
296: .getDataStore());
297:
298: ResultSet rs = statement.executeQuery(sql.count(source
299: .getSchema(), filter));
300: rs.next();
301:
302: Integer count = new Integer(rs.getInt(1));
303: rs.close();
304:
305: return count;
306: }
307:
308: };
309:
310: try {
311: return ((Integer) JDBCUtils.statement(
312: state.getConnection(), runnable)).intValue();
313: } catch (IOException e) {
314: throw new RuntimeException(e);
315: }
316: }
317:
318: public boolean isEmpty() {
319: return size() == 0;
320: }
321:
322: public boolean add(Object o) {
323: throw new UnsupportedOperationException();
324: }
325:
326: public boolean addAll(Collection arg0) {
327: throw new UnsupportedOperationException();
328: }
329:
330: public void clear() {
331: throw new UnsupportedOperationException();
332: }
333:
334: public boolean contains(Object o) {
335: throw new UnsupportedOperationException();
336: }
337:
338: public boolean containsAll(Collection arg0) {
339: throw new UnsupportedOperationException();
340: }
341:
342: public boolean remove(Object o) {
343: throw new UnsupportedOperationException();
344: }
345:
346: public boolean removeAll(Collection arg0) {
347: throw new UnsupportedOperationException();
348: }
349:
350: public boolean retainAll(Collection arg0) {
351: throw new UnsupportedOperationException();
352: }
353:
354: public Object[] toArray() {
355: throw new UnsupportedOperationException();
356: }
357:
358: public Object[] toArray(Object[] arg0) {
359: throw new UnsupportedOperationException();
360: }
361:
362: public FeatureList sort(SortBy order) {
363: // TODO Auto-generated method stub
364: return null;
365: }
366:
367: public FeatureCollection subCollection(Filter filter) {
368: // TODO Auto-generated method stub
369: return null;
370: }
371:
372: //Feature API
373: public FeatureType getFeatureType() {
374: return null;
375: }
376:
377: public Object getAttribute(String xPath) {
378: return null;
379: }
380:
381: public Object getAttribute(int index) {
382: return null;
383: }
384:
385: public Object[] getAttributes(Object[] attributes) {
386: // TODO Auto-generated method stub
387: return null;
388: }
389:
390: public Geometry getDefaultGeometry() {
391: return null;
392: }
393:
394: public String getID() {
395: // TODO Auto-generated method stub
396: return null;
397: }
398:
399: public int getNumberOfAttributes() {
400: // TODO Auto-generated method stub
401: return 0;
402: }
403:
404: public void setAttribute(int position, Object val)
405: throws IllegalAttributeException,
406: ArrayIndexOutOfBoundsException {
407: // TODO Auto-generated method stub
408:
409: }
410:
411: public void setAttribute(String xPath, Object attribute)
412: throws IllegalAttributeException {
413: // TODO Auto-generated method stub
414:
415: }
416:
417: public final void setDefaultGeometry(Geometry geometry)
418: throws IllegalAttributeException {
419:
420: }
421: }
|