001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wfs/operation/GetFeatureWithLock.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.ogcwebservices.wfs.operation; 037 038 import java.util.Map; 039 040 import org.deegree.datatypes.QualifiedName; 041 import org.deegree.framework.log.ILogger; 042 import org.deegree.framework.log.LoggerFactory; 043 import org.deegree.framework.util.KVP2Map; 044 import org.deegree.i18n.Messages; 045 import org.deegree.model.filterencoding.Filter; 046 import org.deegree.ogcbase.PropertyPath; 047 import org.deegree.ogcbase.SortProperty; 048 import org.deegree.ogcwebservices.InconsistentRequestException; 049 import org.deegree.ogcwebservices.InvalidParameterValueException; 050 import org.deegree.ogcwebservices.MissingParameterValueException; 051 import org.deegree.ogcwebservices.OGCWebServiceException; 052 import org.deegree.ogcwebservices.wfs.operation.LockFeature.ALL_SOME_TYPE; 053 import org.w3c.dom.Element; 054 055 /** 056 * Represents a <code>GetFeatureWithLock</code> request to a web feature service. 057 * <p> 058 * This is identical to a {@link GetFeature} request, except that the features matching the request will also be locked. 059 * 060 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a> 061 * @author last edited by: $Author: mschneider $ 062 * 063 * @version $Revision: 18195 $ 064 */ 065 public class GetFeatureWithLock extends GetFeature { 066 067 private static final ILogger LOG = LoggerFactory.getLogger( GetFeatureWithLock.class ); 068 069 private static final long serialVersionUID = 8885456550385437651L; 070 071 /** Duration until timeout (in milliseconds). */ 072 private long expiry; 073 074 private ALL_SOME_TYPE lockAction; 075 076 /** 077 * Creates a new <code>GetFeatureWithLock</code> instance. 078 * 079 * @param version 080 * request version 081 * @param id 082 * id of the request 083 * @param handle 084 * @param resultType 085 * desired result type (results | hits) 086 * @param outputFormat 087 * requested result format 088 * @param maxFeatures 089 * @param startPosition 090 * deegree specific parameter defining where to start considering features 091 * @param traverseXLinkDepth 092 * @param traverseXLinkExpiry 093 * @param queries 094 * @param vendorSpecificParam 095 * @param expiry 096 * the limit on how long the web feature service keeps the lock (in milliseconds) 097 * @param lockAction 098 * method for lock acquisition 099 */ 100 GetFeatureWithLock( String version, String id, String handle, RESULT_TYPE resultType, String outputFormat, 101 int maxFeatures, int startPosition, int traverseXLinkDepth, int traverseXLinkExpiry, 102 Query[] queries, Map<String, String> vendorSpecificParam, long expiry, ALL_SOME_TYPE lockAction ) { 103 super( version, id, handle, resultType, outputFormat, maxFeatures, startPosition, traverseXLinkDepth, 104 traverseXLinkExpiry, queries, vendorSpecificParam ); 105 this.expiry = expiry; 106 this.lockAction = lockAction; 107 } 108 109 /** 110 * Creates a new <code>GetFeatureWithLock</code> instance from the given parameters. 111 * 112 * @param version 113 * request version 114 * @param id 115 * id of the request 116 * @param handle 117 * @param resultType 118 * desired result type (results | hits) 119 * @param outputFormat 120 * requested result format 121 * @param maxFeatures 122 * @param startPosition 123 * deegree specific parameter defining where to start considering features 124 * @param traverseXLinkDepth 125 * @param traverseXLinkExpiry 126 * @param queries 127 * @param vendorSpecificParam 128 * @param expiry 129 * the limit on how long the web feature service keeps the lock (in milliseconds) 130 * @param lockAction 131 * method for lock acquisition 132 * @return new <code>GetFeatureWithLock</code> request 133 */ 134 public static GetFeatureWithLock create( String version, String id, String handle, RESULT_TYPE resultType, 135 String outputFormat, int maxFeatures, int startPosition, 136 int traverseXLinkDepth, int traverseXLinkExpiry, Query[] queries, 137 Map<String, String> vendorSpecificParam, long expiry, 138 ALL_SOME_TYPE lockAction ) { 139 return new GetFeatureWithLock( version, id, handle, resultType, outputFormat, maxFeatures, startPosition, 140 traverseXLinkDepth, traverseXLinkExpiry, queries, vendorSpecificParam, expiry, 141 lockAction ); 142 } 143 144 /** 145 * Creates a new <code>GetFeatureWithLock</code> instance from a document that contains the DOM representation of 146 * the request. 147 * 148 * @param id 149 * of the request 150 * @param root 151 * element that contains the DOM representation of the request 152 * @return new <code>GetFeatureWithLock</code> request 153 * @throws OGCWebServiceException 154 */ 155 public static GetFeatureWithLock create( String id, Element root ) 156 throws OGCWebServiceException { 157 GetFeatureWithLockDocument doc = new GetFeatureWithLockDocument(); 158 doc.setRootElement( root ); 159 GetFeatureWithLock request; 160 try { 161 request = doc.parse( id ); 162 } catch ( Exception e ) { 163 LOG.logError( e.getMessage(), e ); 164 throw new OGCWebServiceException( "GetFeatureWithLock", e.getMessage() ); 165 } 166 return request; 167 } 168 169 /** 170 * Creates a new <code>GetFeatureWithLock</code> instance from the given key-value pair encoded request. 171 * 172 * @param id 173 * request identifier 174 * @param request 175 * @return new <code>GetFeatureWithLock</code> request 176 * @throws InvalidParameterValueException 177 * @throws InconsistentRequestException 178 * @throws MissingParameterValueException 179 */ 180 public static GetFeatureWithLock create( String id, String request ) 181 throws InconsistentRequestException, InvalidParameterValueException, 182 MissingParameterValueException { 183 Map<String, String> map = KVP2Map.toMap( request ); 184 map.put( "ID", id ); 185 return create( map ); 186 } 187 188 /** 189 * Creates a new <code>GetFeatureWithLock</code> request from the given map. 190 * 191 * @param kvp 192 * key-value pairs, keys have to be uppercase 193 * @return new <code>GetFeatureWithLock</code> request 194 * @throws InconsistentRequestException 195 * @throws InvalidParameterValueException 196 * @throws MissingParameterValueException 197 */ 198 public static GetFeatureWithLock create( Map<String, String> kvp ) 199 throws InconsistentRequestException, InvalidParameterValueException, 200 MissingParameterValueException { 201 202 // SERVICE 203 checkServiceParameter( kvp ); 204 205 // ID (deegree specific) 206 String id = kvp.get( "ID" ); 207 208 // VERSION 209 String version = checkVersionParameter( kvp ); 210 211 // OUTPUTFORMAT 212 String outputFormat = getParam( "OUTPUTFORMAT", kvp, version.equals( "1.0.0" ) ? FORMAT_GML2_WFS100 213 : FORMAT_GML3 ); 214 215 // RESULTTYPE 216 RESULT_TYPE resultType = RESULT_TYPE.RESULTS; 217 String resultTypeString = kvp.get( "RESULTTYPE" ); 218 if ( "hits".equals( resultTypeString ) ) { 219 resultType = RESULT_TYPE.HITS; 220 } 221 222 // FEATUREVERSION 223 String featureVersion = kvp.get( "FEATUREVERSION" ); 224 225 // MAXFEATURES 226 String maxFeaturesString = kvp.get( "MAXFEATURES" ); 227 // -1: fetch all features 228 int maxFeatures = -1; 229 if ( maxFeaturesString != null ) { 230 try { 231 maxFeatures = Integer.parseInt( maxFeaturesString ); 232 if ( maxFeatures < 1 ) { 233 throw new NumberFormatException(); 234 } 235 } catch ( NumberFormatException e ) { 236 LOG.logError( e.getMessage(), e ); 237 String msg = Messages.getMessage( "WFS_PARAMETER_INVALID_INT", maxFeaturesString, "MAXFEATURES" ); 238 throw new InvalidParameterValueException( msg ); 239 } 240 } 241 242 // STARTPOSITION (deegree specific) 243 String startPosString = getParam( "STARTPOSITION", kvp, "1" ); 244 int startPosition = 1; 245 try { 246 startPosition = Integer.parseInt( startPosString ); 247 if ( startPosition < 1 ) { 248 throw new NumberFormatException(); 249 } 250 } catch ( NumberFormatException e ) { 251 LOG.logError( e.getMessage(), e ); 252 String msg = Messages.getMessage( "WFS_PARAMETER_INVALID_INT", startPosString, "STARTPOSITION" ); 253 throw new InvalidParameterValueException( msg ); 254 } 255 256 // SRSNAME 257 String srsName = kvp.get( "SRSNAME" ); 258 259 // TYPENAME 260 QualifiedName[] typeNames = extractTypeNames( kvp ); 261 if ( typeNames == null ) { 262 // no TYPENAME parameter -> FEATUREID must be present 263 String featureId = kvp.get( "FEATUREID" ); 264 if ( featureId != null ) { 265 String msg = Messages.getMessage( "WFS_FEATUREID_PARAM_UNSUPPORTED" ); 266 throw new InvalidParameterValueException( msg ); 267 } 268 String msg = Messages.getMessage( "WFS_TYPENAME+FID_PARAMS_MISSING" ); 269 throw new InvalidParameterValueException( msg ); 270 } 271 272 // BBOX 273 Filter bboxFilter = extractBBOXFilter( kvp ); 274 275 // FILTER (prequisite: TYPENAME) 276 Map<QualifiedName, Filter> filterMap = extractFilters( kvp, typeNames ); 277 if ( bboxFilter != null && filterMap.size() > 0 ) { 278 String msg = Messages.getMessage( "WFS_BBOX_FILTER_INVALID" ); 279 throw new InvalidParameterValueException( msg ); 280 } 281 282 // PROPERTYNAME 283 Map<QualifiedName, PropertyPath[]> propertyNameMap = extractPropNames( kvp, typeNames ); 284 285 // SORTBY 286 SortProperty[] sortProperties = null; 287 288 // TRAVERSEXLINKDEPTH 289 int traverseXLinkDepth = -1; 290 291 // TRAVERSEXLINKEXPIRY 292 int traverseXLinkExpiry = -1; 293 294 // build a Query instance for each requested feature type (later also for each featureid...) 295 Query[] queries = new Query[typeNames.length]; 296 for ( int i = 0; i < queries.length; i++ ) { 297 QualifiedName ftName = typeNames[i]; 298 PropertyPath[] properties = propertyNameMap.get( ftName ); 299 Filter filter; 300 if ( bboxFilter != null ) { 301 filter = bboxFilter; 302 } else { 303 filter = filterMap.get( ftName ); 304 } 305 QualifiedName[] ftNames = new QualifiedName[] { ftName }; 306 queries[i] = new Query( properties, null, sortProperties, null, featureVersion, ftNames, null, srsName, 307 filter, resultType, maxFeatures, startPosition ); 308 } 309 310 // EXPIRY 311 String expiryString = getParam( "EXPIRY", kvp, LockFeature.DEFAULT_EXPIRY ); 312 int expiry = 0; 313 try { 314 expiry = Integer.parseInt( expiryString ); 315 if ( expiry < 1 ) { 316 throw new NumberFormatException(); 317 } 318 } catch ( NumberFormatException e ) { 319 String msg = Messages.getMessage( "WFS_PARAMETER_INVALID_INT", expiryString, "EXPIRY" ); 320 throw new InvalidParameterValueException( msg ); 321 } 322 323 // LOCKACTION 324 String lockActionString = getParam( "LOCKACTION", kvp, "ALL" ); 325 ALL_SOME_TYPE lockAction = LockFeature.validateLockAction( lockActionString ); 326 327 // build a GetFeatureLock request that contains all queries 328 GetFeatureWithLock request = new GetFeatureWithLock( version, id, null, resultType, outputFormat, maxFeatures, 329 startPosition, traverseXLinkDepth, traverseXLinkExpiry, 330 queries, kvp, expiry, lockAction ); 331 return request; 332 } 333 334 /** 335 * Returns the limit on how long the web feature service holds the lock in the event that a transaction is never 336 * issued that would release the lock. The expiry limit is specified in milliseconds. 337 * 338 * @return the limit on how long the web feature service holds the lock (in milliseconds) 339 */ 340 public long getExpiry() { 341 return this.expiry; 342 } 343 344 /** 345 * Returns the mode for lock acquisition. 346 * 347 * @see ALL_SOME_TYPE 348 * 349 * @return the mode for lock acquisition 350 */ 351 public ALL_SOME_TYPE getLockAction() { 352 return this.lockAction; 353 } 354 }