    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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    }