001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/ogcwebservices/wfs/LockFeatureHandler.java $
002: /*---------------- FILE HEADER ------------------------------------------
003:
004: This file is part of deegree.
005: Copyright (C) 2001-2008 by:
006: EXSE, Department of Geography, University of Bonn
007: http://www.giub.uni-bonn.de/deegree/
008: lat/lon GmbH
009: http://www.lat-lon.de
010:
011: This library is free software; you can redistribute it and/or
012: modify it under the terms of the GNU Lesser General Public
013: License as published by the Free Software Foundation; either
014: version 2.1 of the License, or (at your option) any later version.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: Contact:
026:
027: Andreas Poth
028: lat/lon GmbH
029: Aennchenstr. 19
030: 53177 Bonn
031: Germany
032: E-Mail: poth@lat-lon.de
033:
034: Prof. Dr. Klaus Greve
035: Department of Geography
036: University of Bonn
037: Meckenheimer Allee 166
038: 53115 Bonn
039: Germany
040: E-Mail: greve@giub.uni-bonn.de
041:
042: ---------------------------------------------------------------------------*/
043: package org.deegree.ogcwebservices.wfs;
044:
045: import java.util.ArrayList;
046: import java.util.HashMap;
047: import java.util.List;
048: import java.util.Map;
049: import java.util.Set;
050:
051: import org.deegree.datatypes.QualifiedName;
052: import org.deegree.framework.log.ILogger;
053: import org.deegree.framework.log.LoggerFactory;
054: import org.deegree.i18n.Messages;
055: import org.deegree.io.datastore.Datastore;
056: import org.deegree.io.datastore.DatastoreException;
057: import org.deegree.io.datastore.FeatureId;
058: import org.deegree.io.datastore.LockManager;
059: import org.deegree.io.datastore.schema.MappedFeatureType;
060: import org.deegree.model.feature.Feature;
061: import org.deegree.model.feature.FeatureCollection;
062: import org.deegree.model.feature.schema.FeatureType;
063: import org.deegree.ogcwebservices.OGCWebServiceException;
064: import org.deegree.ogcwebservices.wfs.operation.FeatureResult;
065: import org.deegree.ogcwebservices.wfs.operation.GetFeature;
066: import org.deegree.ogcwebservices.wfs.operation.GetFeatureWithLock;
067: import org.deegree.ogcwebservices.wfs.operation.Lock;
068: import org.deegree.ogcwebservices.wfs.operation.LockFeature;
069: import org.deegree.ogcwebservices.wfs.operation.LockFeatureResponse;
070: import org.deegree.ogcwebservices.wfs.operation.Query;
071:
072: /**
073: * Handles {@link LockFeature} requests to the {@link WFService}.
074: *
075: * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
076: * @author last edited by: $Author: apoth $
077: *
078: * @version $Revision: 9345 $, $Date: 2007-12-27 08:22:25 -0800 (Thu, 27 Dec 2007) $
079: */
080: class LockFeatureHandler {
081:
082: private static final ILogger LOG = LoggerFactory
083: .getLogger(LockFeatureHandler.class);
084:
085: // shared instance to handle GetFeature requests (for GetFeatureWithLock)
086: private GetFeatureHandler getFeatureHandler;
087:
088: private WFService wfs;
089:
090: /**
091: * Creates a new instance of <code>LockFeatureHandler</code>. Only called by the associated
092: * {@link WFService} (once).
093: *
094: * @param wfs
095: * associated WFService
096: */
097: LockFeatureHandler(WFService wfs) {
098: this .wfs = wfs;
099: this .getFeatureHandler = new GetFeatureHandler(wfs);
100: }
101:
102: /**
103: * Handles a {@link LockFeature} request.
104: *
105: * @param request
106: * <code>LockFeature</code> request to perform
107: * @return response to the request
108: * @throws OGCWebServiceException
109: */
110: LockFeatureResponse handleRequest(LockFeature request)
111: throws OGCWebServiceException {
112:
113: LockFeatureResponse response = null;
114:
115: try {
116: List<FeatureId> fidsToLock = new ArrayList<FeatureId>();
117: Map<Datastore, List<Lock>> dsToLocksMap = buildDsToLocksMap(request);
118: for (Datastore ds : dsToLocksMap.keySet()) {
119: fidsToLock.addAll(ds.determineFidsToLock(dsToLocksMap
120: .get(ds)));
121: }
122: org.deegree.io.datastore.Lock lock = LockManager
123: .getInstance().acquireLock(request, fidsToLock);
124: Set<String> lockedFeatures = lock.getLockedFids();
125: String[] lockedFids = new String[lockedFeatures.size()];
126: String[] notLockedFids = new String[fidsToLock.size()
127: - lockedFeatures.size()];
128: int lockedIdx = 0, notLockedIdx = 0;
129: for (FeatureId fid : fidsToLock) {
130: String fidAsString = fid.getAsString();
131: if (lockedFeatures.contains(fidAsString)) {
132: lockedFids[lockedIdx++] = fidAsString;
133: } else {
134: notLockedFids[notLockedIdx++] = fidAsString;
135: }
136: }
137: response = new LockFeatureResponse(request, lock.getId(),
138: lockedFids, notLockedFids);
139: } catch (DatastoreException e) {
140: LOG.logDebug(e.getMessage(), e);
141: throw new OGCWebServiceException(this .getClass().getName(),
142: e.getMessage());
143: }
144:
145: return response;
146: }
147:
148: /**
149: * Handles a {@link GetFeatureWithLock} request.
150: * <p>
151: * This is performed using the following strategy:
152: * <ul>
153: * <li>Perform the request as a standard {@link GetFeature} request.</li>
154: * <li>Create a corresponding {@link LockFeature} request from the {@link GetFeatureWithLock}
155: * request.</li>
156: * <li>Set the "lockId" attribute in the result feature collection.</li>
157: * <li>Remove all features from the feature collection that could not be locked.</li>
158: * </ul>
159: *
160: * @param request
161: * <code>GetFeatureWithLock</code> request to perform
162: * @return response to the request
163: * @throws OGCWebServiceException
164: */
165: FeatureResult handleRequest(GetFeatureWithLock request)
166: throws OGCWebServiceException {
167:
168: FeatureResult response = this .getFeatureHandler
169: .handleRequest(request);
170:
171: List<Lock> locks = new ArrayList<Lock>(
172: request.getQuery().length);
173: for (Query query : request.getQuery()) {
174: Lock lock = new Lock(null, query.getTypeNames()[0], query
175: .getFilter());
176: locks.add(lock);
177: }
178: LockFeature lockRequest = LockFeature.create(WFService.VERSION,
179: null, null, request.getExpiry(), request
180: .getLockAction(), locks);
181: LockFeatureResponse lockResponse = handleRequest(lockRequest);
182:
183: // set "lockId" parameter in result feature collection
184: FeatureCollection fc = (FeatureCollection) response
185: .getResponse();
186: fc.setAttribute("lockId", lockResponse.getLockId());
187:
188: // remove all features from the result feature collection that could not be locked (and
189: // count removed features)
190: int removed = 0;
191: for (String notLockedFid : lockResponse.getFeaturesNotLocked()) {
192: Feature feature = fc.getFeature(notLockedFid);
193: if (feature != null) {
194: fc.remove(feature);
195: removed++;
196: }
197: }
198:
199: // correct "numberOfFeatures" attribute (and make it work even for resultType=HITS)
200: int before = Integer.parseInt(fc
201: .getAttribute("numberOfFeatures"));
202: fc.setAttribute("numberOfFeatures", "" + (before - removed));
203:
204: return response;
205: }
206:
207: /**
208: * Groups all {@link Lock}s contained in the given {@link LockFeature} request by the
209: * responsible {@link Datastore}, i.e. that serves the {@link FeatureType} to be locked.
210: *
211: * @param request
212: * @return keys: responsible <code>Datastore</code>, values: List of <code>Lock</code>s
213: * @throws OGCWebServiceException
214: */
215: private Map<Datastore, List<Lock>> buildDsToLocksMap(
216: LockFeature request) throws OGCWebServiceException {
217:
218: Map<Datastore, List<Lock>> dsToLocksMap = new HashMap<Datastore, List<Lock>>();
219: List<Lock> locks = request.getLocks();
220:
221: for (Lock lock : locks) {
222: QualifiedName ftName = lock.getTypeName();
223: MappedFeatureType ft = this .wfs
224: .getMappedFeatureType(ftName);
225:
226: if (ft == null) {
227: String msg = Messages.getMessage(
228: "WFS_FEATURE_TYPE_UNKNOWN", ftName);
229: throw new OGCWebServiceException(this .getClass()
230: .getName(), msg);
231: }
232: if (ft.isAbstract()) {
233: String msg = Messages.getMessage(
234: "WFS_FEATURE_TYPE_ABSTRACT", ftName);
235: throw new OGCWebServiceException(this .getClass()
236: .getName(), msg);
237: }
238: if (!ft.isVisible()) {
239: String msg = Messages.getMessage(
240: "WFS_FEATURE_TYPE_INVISIBLE", ftName);
241: throw new OGCWebServiceException(this .getClass()
242: .getName(), msg);
243: }
244:
245: Datastore ds = ft.getGMLSchema().getDatastore();
246: List<Lock> dsLocks = dsToLocksMap.get(ds);
247: if (dsLocks == null) {
248: dsLocks = new ArrayList<Lock>();
249: dsToLocksMap.put(ds, dsLocks);
250: }
251: dsLocks.add(lock);
252: }
253: return dsToLocksMap;
254: }
255: }
|