001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.wfs;
017:
018: import java.io.IOException;
019: import java.util.ArrayList;
020: import java.util.Arrays;
021: import java.util.HashMap;
022: import java.util.HashSet;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.NoSuchElementException;
026: import java.util.Set;
027:
028: import org.geotools.data.DataUtilities;
029: import org.geotools.data.FeatureReader;
030: import org.geotools.data.FeatureStore;
031: import org.geotools.data.Transaction;
032:
033: import org.geotools.data.wfs.Action.DeleteAction;
034: import org.geotools.data.wfs.Action.InsertAction;
035: import org.geotools.data.wfs.Action.UpdateAction;
036: import org.geotools.feature.AttributeType;
037: import org.geotools.feature.DefaultFeature;
038: import org.geotools.feature.DefaultFeatureType;
039: import org.geotools.feature.Feature;
040: import org.geotools.feature.FeatureCollection;
041: import org.geotools.feature.FeatureIterator;
042: import org.geotools.feature.GeometryAttributeType;
043: import org.geotools.feature.IllegalAttributeException;
044: import org.opengis.filter.Filter;
045: import org.opengis.referencing.crs.CoordinateReferenceSystem;
046:
047: import com.vividsolutions.jts.geom.Envelope;
048: import com.vividsolutions.jts.geom.Geometry;
049:
050: /**
051: * DOCUMENT ME!
052: *
053: * @author dzwiers
054: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/plugin/wfs/src/main/java/org/geotools/data/wfs/WFSFeatureStore.java $
055: */
056: public class WFSFeatureStore extends WFSFeatureSource implements
057: FeatureStore {
058: protected Transaction trans = Transaction.AUTO_COMMIT;
059:
060: /**
061: *
062: * @param ds
063: * @param typeName
064: */
065: public WFSFeatureStore(WFSDataStore ds, String typeName) {
066: super (ds, typeName);
067: }
068:
069: /**
070: *
071: * @see org.geotools.data.AbstractFeatureSource#getTransaction()
072: */
073: public Transaction getTransaction() {
074: return trans;
075: }
076:
077: public Set addFeatures(final FeatureReader reader)
078: throws IOException {
079: List features = new ArrayList();
080: while (reader.hasNext()) {
081: try {
082: Feature next = reader.next();
083: features.add(next);
084: } catch (Exception e) {
085: throw (IOException) new IOException().initCause(e);
086: }
087: }
088: return addFeatures(DataUtilities
089: .collection((Feature[]) features
090: .toArray(new Feature[0])));
091: }
092:
093: public Set addFeatures(FeatureCollection collection)
094: throws IOException {
095: WFSTransactionState ts = null;
096:
097: if (trans == Transaction.AUTO_COMMIT) {
098: ts = new WFSTransactionState(ds);
099: } else {
100: ts = (WFSTransactionState) trans.getState(ds);
101: }
102:
103: HashSet r = new HashSet();
104:
105: AttributeType[] atrs = getSchema().getAttributeTypes();
106: FeatureIterator iter = collection.features();
107: try {
108: Envelope bounds = null;
109: while (iter.hasNext()) {
110: try {
111: Feature newFeature;
112: try {
113: Feature f = iter.next();
114: newFeature = getSchema().create(
115: f.getAttributes(new Object[getSchema()
116: .getAttributeCount()]),
117: ts.nextFid(getSchema().getTypeName()));
118: r.add(newFeature.getID());
119: } catch (IllegalAttributeException e) {
120: throw (IOException) new IOException(e
121: .getLocalizedMessage());
122: }
123:
124: for (int i = 0; i < atrs.length; i++) {
125: if (atrs[i] instanceof GeometryAttributeType) {
126: Geometry g = (Geometry) newFeature
127: .getAttribute(i);
128: CoordinateReferenceSystem cs = ((GeometryAttributeType) atrs[i])
129: .getCoordinateSystem();
130: if (g == null)
131: continue;
132: if (cs != null
133: && !cs.getIdentifiers().isEmpty())
134: g.setUserData(cs.getIdentifiers()
135: .iterator().next().toString());
136: if (bounds == null) {
137: bounds = new Envelope(g
138: .getEnvelopeInternal());
139: } else {
140: bounds.expandToInclude(g
141: .getEnvelopeInternal());
142: }
143: }
144: }
145:
146: ts.addAction(getSchema().getTypeName(),
147: new InsertAction(newFeature));
148:
149: } catch (NoSuchElementException e) {
150: WFSDataStoreFactory.logger.warning(e.toString());
151: throw new IOException(e.toString());
152: }
153: }
154:
155: // Fire a notification.
156: // JE
157: if (bounds == null) {
158: // if bounds are null then send an envelope to say that features were added but
159: // at an unknown location.
160: ((WFSDataStore) getDataStore()).listenerManager
161: .fireFeaturesRemoved(getSchema().getTypeName(),
162: getTransaction(), new Envelope(), false);
163: } else {
164: ((WFSDataStore) getDataStore()).listenerManager
165: .fireFeaturesRemoved(getSchema().getTypeName(),
166: getTransaction(), bounds, false);
167: }
168:
169: } finally {
170: iter.close();
171: }
172: if (trans == Transaction.AUTO_COMMIT) {
173: ts.commit();
174:
175: String[] fids = ts.getFids(getSchema().getTypeName());
176: r = new HashSet(Arrays.asList(fids));
177:
178: return r;
179: }
180:
181: return r;
182: }
183:
184: /**
185: *
186: * @see org.geotools.data.FeatureStore#removeFeatures(org.geotools.filter.Filter)
187: */
188: public void removeFeatures(Filter filter2) throws IOException {
189: Filter filter = ds.processFilter(filter2);
190: WFSTransactionState ts = null;
191:
192: if (trans == Transaction.AUTO_COMMIT) {
193: ts = new WFSTransactionState(ds);
194: } else {
195: ts = (WFSTransactionState) trans.getState(ds);
196: }
197:
198: ts.addAction(getSchema().getTypeName(), new DeleteAction(
199: getSchema().getTypeName(), filter));
200:
201: // Fire a notification. I don't know a way of quickly getting the bounds of
202: // an arbitrary filter so I'm sending a NULL envelope to say "some features were removed but I don't
203: // know what." Can't be null because the convention states that null is sent on commits only.
204: // JE
205: ((WFSDataStore) getDataStore()).listenerManager
206: .fireFeaturesRemoved(getSchema().getTypeName(),
207: getTransaction(), new Envelope(), false);
208:
209: if (trans == Transaction.AUTO_COMMIT) {
210: ts.commit();
211: }
212: }
213:
214: /**
215: *
216: * @see org.geotools.data.FeatureStore#modifyFeatures(org.geotools.feature.AttributeType[], java.lang.Object[], org.geotools.filter.Filter)
217: */
218: public void modifyFeatures(AttributeType[] type, Object[] value,
219: Filter filter2) throws IOException {
220: Filter filter = ds.processFilter(filter2);
221: WFSTransactionState ts = null;
222:
223: if (trans == Transaction.AUTO_COMMIT) {
224: ts = new WFSTransactionState(ds);
225: } else {
226: ts = (WFSTransactionState) trans.getState(ds);
227: }
228:
229: Map props = new HashMap();
230:
231: Envelope bounds = null;
232: for (int i = 0; i < type.length; i++) {
233: if (type[i] instanceof GeometryAttributeType) {
234: Geometry g = (Geometry) value[i];
235: CoordinateReferenceSystem cs = ((GeometryAttributeType) type[i])
236: .getCoordinateSystem();
237:
238: if (cs != null && !cs.getIdentifiers().isEmpty())
239: g.setUserData(cs.getIdentifiers().iterator().next()
240: .toString());
241: g.setUserData(cs.getIdentifiers().iterator().next()
242: .toString());
243: if (cs != null && !cs.getIdentifiers().isEmpty())
244: g.setUserData(cs.getIdentifiers().iterator().next()
245: .toString());
246: // set/expand the bounds that are being changed.
247: if (g == null)
248: continue;
249: if (bounds == null) {
250: bounds = new Envelope(g.getEnvelopeInternal());
251: } else {
252: bounds.expandToInclude(g.getEnvelopeInternal());
253: }
254: }
255: props.put(type[i].getName(), value[i]);
256: }
257:
258: ts.addAction(getSchema().getTypeName(), new UpdateAction(
259: getSchema().getTypeName(), filter, props));
260:
261: // Fire a notification.
262: // JE
263: if (bounds == null) {
264: // if bounds are null then send an envelope to say that features were modified but
265: // at an unknown location.
266: ((WFSDataStore) getDataStore()).listenerManager
267: .fireFeaturesRemoved(getSchema().getTypeName(),
268: getTransaction(), new Envelope(), false);
269: } else {
270: ((WFSDataStore) getDataStore()).listenerManager
271: .fireFeaturesRemoved(getSchema().getTypeName(),
272: getTransaction(), bounds, false);
273: }
274:
275: if (trans == Transaction.AUTO_COMMIT) {
276: ts.commit();
277: }
278: }
279:
280: /**
281: *
282: * @see org.geotools.data.FeatureStore#modifyFeatures(org.geotools.feature.AttributeType, java.lang.Object, org.geotools.filter.Filter)
283: */
284: public void modifyFeatures(AttributeType type, Object value,
285: Filter filter) throws IOException {
286: modifyFeatures(new AttributeType[] { type, },
287: new Object[] { value, }, filter);
288: }
289:
290: /**
291: *
292: * @see org.geotools.data.FeatureStore#setFeatures(org.geotools.data.FeatureReader)
293: */
294: public void setFeatures(FeatureReader reader) throws IOException {
295: WFSTransactionState ts = null;
296:
297: if (trans == Transaction.AUTO_COMMIT) {
298: ts = new WFSTransactionState(ds);
299: } else {
300: ts = (WFSTransactionState) trans.getState(ds);
301: }
302:
303: ts.addAction(getSchema().getTypeName(), new DeleteAction(
304: getSchema().getTypeName(), Filter.INCLUDE));
305:
306: Envelope bounds = null;
307: while (reader.hasNext()) {
308:
309: try {
310: Feature f = reader.next();
311: AttributeType[] atrs = f.getFeatureType()
312: .getAttributeTypes();
313: for (int i = 0; i < atrs.length; i++) {
314: if (atrs[i] instanceof GeometryAttributeType) {
315: Geometry g = (Geometry) f.getAttribute(i);
316: CoordinateReferenceSystem cs = ((GeometryAttributeType) atrs[i])
317: .getCoordinateSystem();
318: if (cs != null
319: && !cs.getIdentifiers().isEmpty())
320: g.setUserData(cs.getIdentifiers()
321: .iterator().next().toString());
322: if (g == null)
323: continue;
324: if (bounds == null) {
325: bounds = new Envelope(g
326: .getEnvelopeInternal());
327: } else {
328: bounds.expandToInclude(g
329: .getEnvelopeInternal());
330: }
331: }
332: }
333: ts.addAction(getSchema().getTypeName(),
334: new InsertAction(f));
335: } catch (NoSuchElementException e) {
336: WFSDataStoreFactory.logger.warning(e.toString());
337: } catch (IllegalAttributeException e) {
338: WFSDataStoreFactory.logger.warning(e.toString());
339: }
340: }
341:
342: // Fire a notification.
343: // JE
344: if (bounds == null) {
345: // if bounds are null then send an envelope to say that features were added but
346: // at an unknown location.
347: ((WFSDataStore) getDataStore()).listenerManager
348: .fireFeaturesRemoved(getSchema().getTypeName(),
349: getTransaction(), new Envelope(), false);
350: } else {
351: ((WFSDataStore) getDataStore()).listenerManager
352: .fireFeaturesRemoved(getSchema().getTypeName(),
353: getTransaction(), bounds, false);
354: }
355: if (trans == Transaction.AUTO_COMMIT) {
356: ts.commit();
357: }
358: }
359:
360: /**
361: *
362: * @see org.geotools.data.FeatureStore#setTransaction(org.geotools.data.Transaction)
363: */
364: public void setTransaction(Transaction transaction) {
365: if (transaction == null)
366: throw new NullPointerException(
367: "Should this not be Transaction.AutoCommit?");
368: trans = transaction;
369: if (trans != Transaction.AUTO_COMMIT) {
370: WFSTransactionState ts = (WFSTransactionState) trans
371: .getState(ds);
372: if (ts == null) {
373: trans.putState(ds, new WFSTransactionState(ds));
374: }
375: }
376: }
377: }
|