001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.geoserver.wfs;
006:
007: import com.vividsolutions.jts.geom.Envelope;
008: import net.opengis.wfs.AllSomeType;
009: import net.opengis.wfs.DeleteElementType;
010: import net.opengis.wfs.TransactionResponseType;
011: import net.opengis.wfs.TransactionType;
012: import org.eclipse.emf.ecore.EObject;
013: import org.geotools.data.DataStore;
014: import org.geotools.data.DefaultQuery;
015: import org.geotools.data.FeatureLocking;
016: import org.geotools.data.FeatureStore;
017: import org.geotools.data.FeatureWriter;
018: import org.geotools.factory.CommonFactoryFinder;
019: import org.geotools.factory.GeoTools;
020: import org.geotools.xml.EMFUtils;
021: import org.opengis.filter.Filter;
022: import org.opengis.filter.FilterFactory;
023: import org.opengis.filter.FilterFactory2;
024: import org.opengis.referencing.crs.CoordinateReferenceSystem;
025:
026: import java.io.IOException;
027: import java.math.BigInteger;
028: import java.util.HashSet;
029: import java.util.Map;
030: import java.util.Set;
031: import java.util.logging.Logger;
032: import javax.xml.namespace.QName;
033:
034: /**
035: * Processes standard Delete elements
036: *
037: * @author Andrea Aime - TOPP
038: *
039: */
040: public class DeleteElementHandler implements TransactionElementHandler {
041: /**
042: * logger
043: */
044: static Logger LOGGER = org.geotools.util.logging.Logging
045: .getLogger("org.geoserver.wfs");
046: private WFS wfs;
047:
048: public DeleteElementHandler(WFS wfs) {
049: this .wfs = wfs;
050: }
051:
052: public Class getElementClass() {
053: return DeleteElementType.class;
054: }
055:
056: public QName[] getTypeNames(EObject element)
057: throws WFSTransactionException {
058: return new QName[] { ((DeleteElementType) element)
059: .getTypeName() };
060: }
061:
062: public void checkValidity(EObject element, Map featureTypeInfos)
063: throws WFSTransactionException {
064: if ((wfs.getServiceLevel() & WFS.SERVICE_DELETE) == 0) {
065: throw new WFSException(
066: "Transaction Delete support is not enabled");
067: }
068:
069: // check that a filter was specified
070: DeleteElementType delete = (DeleteElementType) element;
071:
072: if ((delete.getFilter() == null)
073: || Filter.INCLUDE.equals(delete.getFilter())) {
074: throw new WFSTransactionException(
075: "Must specify filter for delete",
076: "MissingParameterValue");
077: }
078: }
079:
080: public void execute(EObject element, TransactionType request,
081: Map featureStores, TransactionResponseType response,
082: TransactionListener listener)
083: throws WFSTransactionException {
084: DeleteElementType delete = (DeleteElementType) element;
085: QName elementName = delete.getTypeName();
086: String handle = delete.getHandle();
087: long deleted = response.getTransactionSummary()
088: .getTotalDeleted().longValue();
089:
090: FeatureStore store = (FeatureStore) featureStores
091: .get(elementName);
092:
093: if (store == null) {
094: throw new WFSException(
095: "Could not locate FeatureStore for '" + elementName
096: + "'");
097: }
098:
099: String typeName = store.getSchema().getTypeName();
100: LOGGER.finer("Transaction Delete:" + element);
101:
102: try {
103: Filter filter = (Filter) delete.getFilter();
104:
105: // make sure all geometric elements in the filter have a crs, and that the filter
106: // is reprojected to store's native crs as well
107: CoordinateReferenceSystem declaredCRS = WFSReprojectionUtil
108: .getDeclaredCrs(store.getSchema(), request
109: .getVersion());
110: filter = WFSReprojectionUtil.normalizeFilterCRS(filter,
111: store.getSchema(), declaredCRS);
112:
113: // notify listeners
114: listener.dataStoreChange(new TransactionEvent(
115: TransactionEventType.PRE_DELETE, elementName, store
116: .getFeatures(filter)));
117:
118: // compute damaged area
119: Envelope damaged = store.getBounds(new DefaultQuery(delete
120: .getTypeName().getLocalPart(), filter));
121:
122: if (damaged == null) {
123: damaged = store.getFeatures(filter).getBounds();
124: }
125:
126: if ((request.getLockId() != null)
127: && store instanceof FeatureLocking
128: && (request.getReleaseAction() == AllSomeType.SOME_LITERAL)) {
129: FeatureLocking locking = (FeatureLocking) store;
130:
131: // TODO: Revisit Lock/Delete interaction in gt2
132: if (false) {
133: // REVISIT: This is bad - by releasing locks before
134: // we remove features we open ourselves up to the
135: // danger of someone else locking the features we
136: // are about to remove.
137: //
138: // We cannot do it the other way round, as the
139: // Features will not exist
140: //
141: // We cannot grab the fids offline using AUTO_COMMIT
142: // because we may have removed some of them earlier
143: // in the transaction
144: //
145: locking.unLockFeatures(filter);
146: store.removeFeatures(filter);
147: } else {
148: // This a bit better and what should be done, we
149: // will need to rework the gt2 locking api to work
150: // with fids or something
151: //
152: // The only other thing that would work
153: // would be to specify that FeatureLocking is
154: // required to remove locks when removing Features.
155: //
156: // While that sounds like a good idea, it
157: // would be extra work when doing release mode ALL.
158: //
159: DataStore data = store.getDataStore();
160: FilterFactory factory = CommonFactoryFinder
161: .getFilterFactory(null);
162: FeatureWriter writer;
163: writer = data.getFeatureWriter(typeName, filter,
164: store.getTransaction());
165:
166: try {
167: while (writer.hasNext()) {
168: String fid = writer.next().getID();
169: Set featureIds = new HashSet();
170: featureIds.add(factory.featureId(fid));
171: locking.unLockFeatures(factory
172: .id(featureIds));
173: writer.remove();
174: deleted++;
175: }
176: } finally {
177: writer.close();
178: }
179:
180: store.removeFeatures(filter);
181: }
182: } else {
183: // We don't have to worry about locking right now
184: deleted += store.getFeatures(filter).size();
185: // if(count >= 0) {
186: // deleted += store.getCount(new DefaultQuery(null, filter));
187: store.removeFeatures(filter);
188: // } else {
189: // store.getFeatures(filter).size();
190: // try {
191: // while (writer.hasNext()) {
192: // writer.next();
193: // writer.remove();
194: // deleted++;
195: // }
196: // } finally {
197: // writer.close();
198: // }
199: // }
200: }
201: } catch (IOException e) {
202: String msg = e.getMessage();
203: String eHandle = (String) EMFUtils.get(element, "handle");
204: throw new WFSTransactionException(msg, (String) null,
205: eHandle, handle);
206: }
207:
208: // update deletion count
209: response.getTransactionSummary().setTotalDeleted(
210: BigInteger.valueOf(deleted));
211: }
212: }
|