001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wfs/operation/GetFeatureWithLock.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 53115 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 ---------------------------------------------------------------------------*/
044 package org.deegree.ogcwebservices.wfs.operation;
045
046 import java.util.Map;
047
048 import org.deegree.datatypes.QualifiedName;
049 import org.deegree.framework.log.ILogger;
050 import org.deegree.framework.log.LoggerFactory;
051 import org.deegree.framework.util.KVP2Map;
052 import org.deegree.i18n.Messages;
053 import org.deegree.model.filterencoding.Filter;
054 import org.deegree.ogcbase.PropertyPath;
055 import org.deegree.ogcbase.SortProperty;
056 import org.deegree.ogcwebservices.InconsistentRequestException;
057 import org.deegree.ogcwebservices.InvalidParameterValueException;
058 import org.deegree.ogcwebservices.OGCWebServiceException;
059 import org.deegree.ogcwebservices.wfs.operation.LockFeature.ALL_SOME_TYPE;
060 import org.w3c.dom.Element;
061
062 /**
063 * Represents a <code>GetFeatureWithLock</code> request to a web feature service.
064 * <p>
065 * This is identical to a {@link GetFeature} request, except that the features matching the request
066 * will also be locked.
067 *
068 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
069 * @author last edited by: $Author: apoth $
070 *
071 * @version $Revision: 9345 $
072 */
073 public class GetFeatureWithLock extends GetFeature {
074
075 private static final ILogger LOG = LoggerFactory.getLogger( GetFeatureWithLock.class );
076
077 private static final long serialVersionUID = 8885456550385437651L;
078
079 /** Duration until timeout (in milliseconds). */
080 private long expiry;
081
082 private ALL_SOME_TYPE lockAction;
083
084 /**
085 * Creates a new <code>GetFeatureWithLock</code> instance.
086 *
087 * @param version
088 * request version
089 * @param id
090 * id of the request
091 * @param handle
092 * @param resultType
093 * desired result type (results | hits)
094 * @param outputFormat
095 * requested result format
096 * @param maxFeatures
097 * @param startPosition
098 * deegree specific parameter defining where to start considering features
099 * @param traverseXLinkDepth
100 * @param traverseXLinkExpiry
101 * @param queries
102 * @param vendorSpecificParam
103 * @param expiry
104 * the limit on how long the web feature service keeps the lock (in milliseconds)
105 * @param lockAction
106 * method for lock acquisition
107 */
108 GetFeatureWithLock( String version, String id, String handle, RESULT_TYPE resultType, String outputFormat,
109 int maxFeatures, int startPosition, int traverseXLinkDepth, int traverseXLinkExpiry,
110 Query[] queries, Map<String, String> vendorSpecificParam, long expiry, ALL_SOME_TYPE lockAction ) {
111 super( version, id, handle, resultType, outputFormat, maxFeatures, startPosition, traverseXLinkDepth,
112 traverseXLinkExpiry, queries, vendorSpecificParam );
113 this.expiry = expiry;
114 this.lockAction = lockAction;
115 }
116
117 /**
118 * Creates a new <code>GetFeatureWithLock</code> instance from the given parameters.
119 *
120 * @param version
121 * request version
122 * @param id
123 * id of the request
124 * @param handle
125 * @param resultType
126 * desired result type (results | hits)
127 * @param outputFormat
128 * requested result format
129 * @param maxFeatures
130 * @param startPosition
131 * deegree specific parameter defining where to start considering features
132 * @param traverseXLinkDepth
133 * @param traverseXLinkExpiry
134 * @param queries
135 * @param vendorSpecificParam
136 * @param expiry
137 * the limit on how long the web feature service keeps the lock (in milliseconds)
138 * @param lockAction
139 * method for lock acquisition
140 * @return new <code>GetFeatureWithLock</code> request
141 */
142 public static GetFeatureWithLock create( String version, String id, String handle, RESULT_TYPE resultType,
143 String outputFormat, int maxFeatures, int startPosition,
144 int traverseXLinkDepth, int traverseXLinkExpiry, Query[] queries,
145 Map<String, String> vendorSpecificParam, long expiry,
146 ALL_SOME_TYPE lockAction ) {
147 return new GetFeatureWithLock( version, id, handle, resultType, outputFormat, maxFeatures, startPosition,
148 traverseXLinkDepth, traverseXLinkExpiry, queries, vendorSpecificParam, expiry,
149 lockAction );
150 }
151
152 /**
153 * Creates a new <code>GetFeatureWithLock</code> instance from a document that contains the
154 * DOM representation of the request.
155 *
156 * @param id
157 * of the request
158 * @param root
159 * element that contains the DOM representation of the request
160 * @return new <code>GetFeatureWithLock</code> request
161 * @throws OGCWebServiceException
162 */
163 public static GetFeatureWithLock create( String id, Element root )
164 throws OGCWebServiceException {
165 GetFeatureWithLockDocument doc = new GetFeatureWithLockDocument();
166 doc.setRootElement( root );
167 GetFeatureWithLock request;
168 try {
169 request = doc.parse( id );
170 } catch ( Exception e ) {
171 LOG.logError( e.getMessage(), e );
172 throw new OGCWebServiceException( "GetFeatureWithLock", e.getMessage() );
173 }
174 return request;
175 }
176
177 /**
178 * Creates a new <code>GetFeatureWithLock</code> instance from the given key-value pair
179 * encoded request.
180 *
181 * @param id
182 * request identifier
183 * @param request
184 * @return new <code>GetFeatureWithLock</code> request
185 * @throws InvalidParameterValueException
186 * @throws InconsistentRequestException
187 */
188 public static GetFeatureWithLock create( String id, String request )
189 throws InconsistentRequestException, InvalidParameterValueException {
190 Map<String, String> map = KVP2Map.toMap( request );
191 map.put( "ID", id );
192 return create( map );
193 }
194
195 /**
196 * Creates a new <code>GetFeatureWithLock</code> request from the given map.
197 *
198 * @param kvp
199 * key-value pairs, keys have to be uppercase
200 * @return new <code>GetFeatureWithLock</code> request
201 * @throws InconsistentRequestException
202 * @throws InvalidParameterValueException
203 */
204 public static GetFeatureWithLock create( Map<String, String> kvp )
205 throws InconsistentRequestException, InvalidParameterValueException {
206
207 // SERVICE
208 checkServiceParameter( kvp );
209
210 // ID (deegree specific)
211 String id = kvp.get( "ID" );
212
213 // VERSION
214 String version = checkVersionParameter( kvp );
215
216 // OUTPUTFORMAT
217 String outputFormat = getParam( "OUTPUTFORMAT", kvp, FORMAT_GML3 );
218
219 // RESULTTYPE
220 RESULT_TYPE resultType = RESULT_TYPE.RESULTS;
221 String resultTypeString = kvp.get( "RESULTTYPE" );
222 if ( "hits".equals( resultTypeString ) ) {
223 resultType = RESULT_TYPE.HITS;
224 }
225
226 // FEATUREVERSION
227 String featureVersion = kvp.get( "FEATUREVERSION" );
228
229 // MAXFEATURES
230 String maxFeaturesString = kvp.get( "MAXFEATURES" );
231 // -1: fetch all features
232 int maxFeatures = -1;
233 if ( maxFeaturesString != null ) {
234 try {
235 maxFeatures = Integer.parseInt( maxFeaturesString );
236 if ( maxFeatures < 1 ) {
237 throw new NumberFormatException();
238 }
239 } catch ( NumberFormatException e ) {
240 LOG.logError( e.getMessage(), e );
241 String msg = Messages.getMessage( "WFS_PARAMETER_INVALID_INT", maxFeaturesString, "MAXFEATURES" );
242 throw new InvalidParameterValueException( msg );
243 }
244 }
245
246 // STARTPOSITION (deegree specific)
247 String startPosString = getParam( "STARTPOSITION", kvp, "1" );
248 int startPosition = 1;
249 try {
250 startPosition = Integer.parseInt( startPosString );
251 if ( startPosition < 1 ) {
252 throw new NumberFormatException();
253 }
254 } catch ( NumberFormatException e ) {
255 LOG.logError( e.getMessage(), e );
256 String msg = Messages.getMessage( "WFS_PARAMETER_INVALID_INT", startPosString, "STARTPOSITION" );
257 throw new InvalidParameterValueException( msg );
258 }
259
260 // SRSNAME
261 String srsName = kvp.get( "SRSNAME" );
262
263 // TYPENAME
264 QualifiedName[] typeNames = extractTypeNames( kvp );
265 if ( typeNames == null ) {
266 // no TYPENAME parameter -> FEATUREID must be present
267 String featureId = kvp.get( "FEATUREID" );
268 if ( featureId != null ) {
269 String msg = Messages.getMessage( "WFS_FEATUREID_PARAM_UNSUPPORTED" );
270 throw new InvalidParameterValueException( msg );
271 }
272 String msg = Messages.getMessage( "WFS_TYPENAME+FID_PARAMS_MISSING" );
273 throw new InvalidParameterValueException( msg );
274 }
275
276 // BBOX
277 Filter bboxFilter = extractBBOXFilter( kvp );
278
279 // FILTER (prequisite: TYPENAME)
280 Map<QualifiedName, Filter> filterMap = extractFilters( kvp, typeNames );
281 if ( bboxFilter != null && filterMap.size() > 0 ) {
282 String msg = Messages.getMessage( "WFS_BBOX_FILTER_INVALID" );
283 throw new InvalidParameterValueException( msg );
284 }
285
286 // PROPERTYNAME
287 Map<QualifiedName, PropertyPath[]> propertyNameMap = extractPropNames( kvp, typeNames );
288
289 // SORTBY
290 SortProperty[] sortProperties = null;
291
292 // TRAVERSEXLINKDEPTH
293 int traverseXLinkDepth = -1;
294
295 // TRAVERSEXLINKEXPIRY
296 int traverseXLinkExpiry = -1;
297
298 // build a Query instance for each requested feature type (later also for each featureid...)
299 Query[] queries = new Query[typeNames.length];
300 for ( int i = 0; i < queries.length; i++ ) {
301 QualifiedName ftName = typeNames[i];
302 PropertyPath[] properties = propertyNameMap.get( ftName );
303 Filter filter;
304 if ( bboxFilter != null ) {
305 filter = bboxFilter;
306 } else {
307 filter = filterMap.get( ftName );
308 }
309 QualifiedName[] ftNames = new QualifiedName[] { ftName };
310 queries[i] = new Query( properties, null, sortProperties, null, featureVersion, ftNames, null, srsName,
311 filter, resultType, maxFeatures, startPosition );
312 }
313
314 // EXPIRY
315 String expiryString = getParam( "EXPIRY", kvp, LockFeature.DEFAULT_EXPIRY );
316 int expiry = 0;
317 try {
318 expiry = Integer.parseInt( expiryString );
319 if ( expiry < 1 ) {
320 throw new NumberFormatException();
321 }
322 } catch ( NumberFormatException e ) {
323 String msg = Messages.getMessage( "WFS_PARAMETER_INVALID_INT", expiryString, "EXPIRY" );
324 throw new InvalidParameterValueException( msg );
325 }
326
327 // LOCKACTION
328 String lockActionString = getParam( "LOCKACTION", kvp, "ALL" );
329 ALL_SOME_TYPE lockAction = LockFeature.validateLockAction( lockActionString );
330
331 // build a GetFeatureLock request that contains all queries
332 GetFeatureWithLock request = new GetFeatureWithLock( version, id, null, resultType, outputFormat, maxFeatures,
333 startPosition, traverseXLinkDepth, traverseXLinkExpiry,
334 queries, kvp, expiry, lockAction );
335 return request;
336 }
337
338 /**
339 * Returns the limit on how long the web feature service holds the lock in the event that a
340 * transaction is never issued that would release the lock. The expiry limit is specified in
341 * milliseconds.
342 *
343 * @return the limit on how long the web feature service holds the lock (in milliseconds)
344 */
345 public long getExpiry() {
346 return this.expiry;
347 }
348
349 /**
350 * Returns the mode for lock acquisition.
351 *
352 * @see ALL_SOME_TYPE
353 *
354 * @return the mode for lock acquisition
355 */
356 public ALL_SOME_TYPE getLockAction() {
357 return this.lockAction;
358 }
359 }