001: package com.vividsolutions.jump.workbench.model.cache;
002:
003: import java.util.Collection;
004: import java.util.Collections;
005: import java.util.Iterator;
006: import java.util.List;
007: import java.util.NoSuchElementException;
008:
009: import javax.swing.SwingUtilities;
010:
011: import com.vividsolutions.jts.geom.Envelope;
012: import com.vividsolutions.jts.geom.GeometryFactory;
013: import com.vividsolutions.jts.util.Assert;
014: import com.vividsolutions.jump.datastore.*;
015: import com.vividsolutions.jump.feature.Feature;
016: import com.vividsolutions.jump.feature.FeatureCollection;
017: import com.vividsolutions.jump.feature.FeatureSchema;
018: import com.vividsolutions.jump.io.FeatureInputStream;
019: import com.vividsolutions.jump.util.ListWrapper;
020: import com.vividsolutions.jump.workbench.datastore.ConnectionDescriptor;
021: import com.vividsolutions.jump.workbench.datastore.ConnectionManager;
022: import com.vividsolutions.jump.workbench.ui.plugin.AddNewLayerPlugIn;
023:
024: public class DynamicFeatureCollection implements FeatureCollection {
025: private Integer featureLimit = null;
026:
027: private FilterQuery spatialQuery;
028:
029: private ConnectionManager connectionManager;
030: private ConnectionDescriptor connectionDescriptor;
031:
032: public DynamicFeatureCollection(
033: ConnectionDescriptor connectionDescriptor,
034: ConnectionManager connectionManager,
035: FilterQuery spatialQuery) {
036: this .connectionManager = connectionManager;
037: this .connectionDescriptor = connectionDescriptor;
038: this .spatialQuery = spatialQuery;
039: }
040:
041: public void setFeatureLimit(Integer featureLimit) {
042: this .featureLimit = featureLimit;
043: }
044:
045: private volatile Object currentQueryContext;
046:
047: private FeatureSchema schema = AddNewLayerPlugIn
048: .createBlankFeatureCollection().getFeatureSchema();
049:
050: public FeatureSchema getFeatureSchema() {
051: return schema;
052: }
053:
054: public List query(Envelope envelope) {
055: final Object myQueryContext = new Object();
056: currentQueryContext = myQueryContext;
057:
058: Envelope layerExtents = getEnvelope();
059: if (layerExtents == null || layerExtents.isNull()
060: || layerExtents.contains(envelope)) {
061: spatialQuery.setFilterGeometry(new GeometryFactory()
062: .toGeometry(envelope));
063: } else {
064: // we are asking for too much data ...
065: spatialQuery.setFilterGeometry(new GeometryFactory()
066: .toGeometry(layerExtents.intersection(envelope)));
067: }
068:
069: // Q: When do we close the stream? A: When a new stream is
070: // requested. Implication: You cannot have two streams active from
071: // the same DynamicFeatureCollection. But JUMP does not need this
072: // capability. [Jon Aquino 2005-03-02]
073: final FeatureInputStream myFeatureInputStream;
074: try {
075: myFeatureInputStream = connectionManager.getOpenConnection(
076: connectionDescriptor).execute(spatialQuery);
077: } catch (Exception e) {
078: throw new RuntimeException(e);
079: }
080: // Sometimes #execute takes a long time (e.g. SDE), and other calls to
081: // #query may have occurred. [Jon Aquino 2005-03-15]
082: if (myQueryContext != currentQueryContext) {
083: return Collections.EMPTY_LIST;
084: }
085: schema = myFeatureInputStream.getFeatureSchema();
086: return new ListWrapper() {
087: public Collection getCollection() {
088: // Implement #iterator only [Jon Aquino 2005-03-03]
089: throw new UnsupportedOperationException();
090: }
091:
092: public Iterator iterator() {
093: return new Iterator() {
094: private int featuresReturned = 0;
095:
096: private boolean featureInputStreamOpen = true;
097:
098: public void remove() {
099: throw new UnsupportedOperationException();
100: }
101:
102: public boolean hasNext() {
103: try {
104: if (featureLimit != null
105: && featuresReturned >= featureLimit
106: .intValue()) {
107: closeFeatureInputStream();
108: return false;
109: }
110: if (myQueryContext != currentQueryContext) {
111: closeFeatureInputStream();
112: return false;
113: }
114: // Explicitly check if the stream is closed;
115: // otherwise #hasNext will throw a
116: // NullPointerException.
117: // [Jon Aquino 2005-03-03]
118: if (!featureInputStreamOpen) {
119: return false;
120: }
121: if (!myFeatureInputStream.hasNext()) {
122: closeFeatureInputStream();
123: return false;
124: }
125: return true;
126: } catch (Exception e) {
127: e.printStackTrace();
128: throw new RuntimeException(e);
129: }
130: }
131:
132: private void closeFeatureInputStream()
133: throws Exception {
134: myFeatureInputStream.close();
135: featureInputStreamOpen = false;
136: }
137:
138: public Object next() {
139: assertNotInGUIThread();
140: if (!hasNext()) {
141: throw new NoSuchElementException();
142: }
143: try {
144: featuresReturned++;
145: return myFeatureInputStream.next();
146: } catch (Exception e) {
147: throw new RuntimeException(e);
148: }
149: }
150: };
151: }
152: };
153: }
154:
155: public void add(Feature feature) {
156: throw new UnsupportedOperationException();
157: }
158:
159: public void addAll(Collection features) {
160: throw new UnsupportedOperationException();
161: }
162:
163: public void removeAll(Collection features) {
164: throw new UnsupportedOperationException();
165: }
166:
167: public void remove(Feature feature) {
168: throw new UnsupportedOperationException();
169: }
170:
171: public void clear() {
172: throw new UnsupportedOperationException();
173: }
174:
175: public Collection remove(Envelope env) {
176: throw new UnsupportedOperationException();
177: }
178:
179: /**
180: * @see com.vividsolutions.jump.feature.FeatureCollection#getEnvelope()
181: */
182: public Envelope getEnvelope() {
183: DataStoreConnection dsc = null;
184: try {
185: dsc = connectionManager
186: .getOpenConnection(connectionDescriptor);
187: } catch (Exception e1) {
188: // ignore
189: return new Envelope();
190: }
191: Envelope e = null;
192: if (dsc != null) {
193: DataStoreMetadata dsm = dsc.getMetadata();
194: if (dsm != null && spatialQuery != null)
195: e = dsm.getExtents(spatialQuery.getDatasetName(),
196: spatialQuery.getGeometryAttributeName());
197: }
198: return e;
199: }
200:
201: public int size() {
202: throw new UnsupportedOperationException();
203: }
204:
205: public boolean isEmpty() {
206: throw new UnsupportedOperationException();
207: }
208:
209: public List getFeatures() {
210: throw new UnsupportedOperationException();
211: }
212:
213: public Iterator iterator() {
214: throw new UnsupportedOperationException();
215: }
216:
217: private void assertNotInGUIThread() {
218: Assert
219: .isTrue(!SwingUtilities.isEventDispatchThread(),
220: "This operation should be done outside of the GUI thread");
221: }
222: }
|