001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wfs/operation/Query.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     Aennchenstraße 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.operation;
044    
045    import org.deegree.datatypes.QualifiedName;
046    import org.deegree.framework.xml.XMLParsingException;
047    import org.deegree.model.filterencoding.Filter;
048    import org.deegree.model.filterencoding.Function;
049    import org.deegree.ogcbase.PropertyPath;
050    import org.deegree.ogcbase.SortProperty;
051    import org.deegree.ogcwebservices.wfs.operation.GetFeature.RESULT_TYPE;
052    import org.w3c.dom.Element;
053    
054    /**
055     * Represents a <code>Query</code> operation as a part of a {@link GetFeature} request.
056     * 
057     * Each individual query packaged in a {@link GetFeature} request is defined using the query value.
058     * The query value defines which feature type to query, what properties to retrieve and what
059     * constraints (spatial and non-spatial) to apply to those properties.
060     * <p>
061     * The mandatory <code>typeName</code> attribute is used to indicate the name of one or more
062     * feature type instances or class instances to be queried. Its value is a list of
063     * namespace-qualified names (XML Schema type QName, e.g. myns:School) whose value must match one of
064     * the feature types advertised in the Capabilities document of the WFS. Specifying more than one
065     * typename indicates that a join operation is being performed. All the names in the typeName list
066     * must be valid types that belong to this query's feature content as defined by the GML Application
067     * Schema. Optionally, individual feature type names in the typeName list may be aliased using the
068     * format QName=Alias. The following is an example typeName value that indicates that a join
069     * operation is to be performed and includes aliases: <BR>
070     * <code>typeName="ns1:InwaterA_1m=A,ns1:InwaterA_1m=B,ns2:CoastL_1M=C"</code><BR>
071     * This example encodes a join between three feature types aliased as A, B and C. The join between
072     * feature type A and B is a self-join.
073     * </p>
074     * 
075     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
076     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a>
077     * @author last edited by: $Author: apoth $
078     * 
079     * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $
080     */
081    public class Query {
082    
083        private String handle;
084    
085        private QualifiedName[] typeNames;
086    
087        private String[] aliases;
088    
089        private String featureVersion;
090    
091        private String srsName;
092    
093        private PropertyPath[] propertyNames;
094    
095        private Function[] functions;
096    
097        private Filter filter;
098    
099        private SortProperty[] sortProperties;
100    
101        // deegree specific extension ("inherited" from GetFeature container)
102        private RESULT_TYPE resultType;
103    
104        // deegree specific extension ("inherited" from GetFeature container)
105        private int maxFeatures = -1;
106    
107        // deegree specific extension ("inherited" from GetFeature container)
108        private int startPosition = 1;
109    
110        /**
111         * Creates a new <code>Query</code> instance.
112         * 
113         * @param propertyNames
114         *            names of the requested properties, may be null or empty
115         * @param functions
116         *            names of the requested functions, may be null or empty
117         * @param sortProperties
118         *            sort criteria, may be null or empty
119         * @param handle
120         *            client-generated identifier for the query, may be null
121         * @param featureVersion
122         *            version of the feature instances to fetched, may be null
123         * @param typeNames
124         *            list of requested feature types
125         * @param aliases
126         *            list of aliases for the feature types, must either be null or have the same length
127         *            as the typeNames array
128         * @param srsName
129         *            name of the spatial reference system
130         * @param filter
131         *            spatial and none-spatial constraints
132         * @param resultType
133         *            deegree specific extension ("inherited" from GetFeature container)
134         * @param maxFeatures
135         *            deegree specific extension ("inherited" from GetFeature container)
136         * @param startPosition
137         *            deegree specific extension ("inherited" from GetFeature container)
138         */
139        Query( PropertyPath[] propertyNames, Function[] functions, SortProperty[] sortProperties, String handle,
140               String featureVersion, QualifiedName[] typeNames, String[] aliases, String srsName, Filter filter,
141               RESULT_TYPE resultType, int maxFeatures, int startPosition ) {
142            if ( propertyNames == null ) {
143                this.propertyNames = new PropertyPath[0];
144                // this.propertyNames[0] = new PropertyPath( typeNames[0] );
145            } else {
146                this.propertyNames = propertyNames;
147            }
148            this.functions = functions;
149            this.sortProperties = sortProperties;
150            this.handle = handle;
151            this.featureVersion = featureVersion;
152            this.typeNames = typeNames;
153            this.aliases = aliases;
154            assert aliases == null || aliases.length == typeNames.length;
155            this.srsName = srsName;
156            this.filter = filter;
157            this.resultType = resultType;
158            this.maxFeatures = maxFeatures;
159            this.startPosition = startPosition;
160        }
161    
162        /**
163         * Creates a new <code>Query</code> instance.
164         * 
165         * @param propertyNames
166         *            names of the requested properties, may be null or empty
167         * @param functions
168         *            names of the requested functions, may be null or empty
169         * @param sortProperties
170         *            sort criteria, may be null or empty
171         * @param handle
172         *            client-generated identifier for the query, may be null
173         * @param featureVersion
174         *            version of the feature instances to fetched, may be null
175         * @param typeNames
176         *            list of requested feature types. if more than one feature types is set a JOIN will
177         *            be created (not yet supported)
178         * @param srsName
179         *            name of the spatial reference system
180         * @param filter
181         *            spatial and none-spatial constraints
182         * @param resultType
183         *            deegree specific extension ("inherited" from GetFeature container)
184         * @param maxFeatures
185         *            deegree specific extension ("inherited" from GetFeature container)
186         * @param startPosition
187         *            deegree specific extension ("inherited" from GetFeature container)
188         * @return new <code>Query</code> instance
189         * @deprecated use
190         *             {@link #create(PropertyPath[], Function[], SortProperty[], String, String, QualifiedName[], String, Filter, int, int, RESULT_TYPE)}
191         *             instead
192         */
193        @Deprecated
194        public static Query create( PropertyPath[] propertyNames, Function[] functions, SortProperty[] sortProperties,
195                                    String handle, String featureVersion, QualifiedName[] typeNames, String srsName,
196                                    Filter filter, int maxFeatures, int startPosition, RESULT_TYPE resultType ) {
197            return new Query( propertyNames, functions, sortProperties, handle, featureVersion, typeNames, null, srsName,
198                              filter, resultType, maxFeatures, startPosition );
199        }
200    
201        /**
202         * Creates a new <code>Query</code> instance.
203         * 
204         * @param propertyNames
205         *            names of the requested properties, may be null or empty
206         * @param functions
207         *            names of the requested functions, may be null or empty
208         * @param sortProperties
209         *            sort criteria, may be null or empty
210         * @param handle
211         *            client-generated identifier for the query, may be null
212         * @param featureVersion
213         *            version of the feature instances to fetched, may be null
214         * @param typeNames
215         *            list of requested feature types. if more than one feature types is set a JOIN will
216         *            be created (not yet supported)
217         * @param aliases
218         *            list of aliases for the feature types, must either be null or have the same length
219         *            as the typeNames array
220         * @param srsName
221         *            name of the spatial reference system
222         * @param filter
223         *            spatial and none-spatial constraints
224         * @param resultType
225         *            deegree specific extension ("inherited" from GetFeature container)
226         * @param maxFeatures
227         *            deegree specific extension ("inherited" from GetFeature container)
228         * @param startPosition
229         *            deegree specific extension ("inherited" from GetFeature container)
230         * @return new <code>Query</code> instance
231         */
232        public static Query create( PropertyPath[] propertyNames, Function[] functions, SortProperty[] sortProperties,
233                                    String handle, String featureVersion, QualifiedName[] typeNames, String[] aliases,
234                                    String srsName, Filter filter, int maxFeatures, int startPosition,
235                                    RESULT_TYPE resultType ) {
236            return new Query( propertyNames, functions, sortProperties, handle, featureVersion, typeNames, aliases,
237                              srsName, filter, resultType, maxFeatures, startPosition );
238        }
239    
240        /**
241         * Creates a new simple <code>Query</code> instance that selects the whole feature type.
242         * 
243         * @param typeName
244         *            name of the feature to be queried
245         * @return new <code>Query</code> instance
246         */
247        public static Query create( QualifiedName typeName ) {
248            return new Query( null, null, null, null, null, new QualifiedName[] { typeName }, null, null, null,
249                              RESULT_TYPE.RESULTS, -1, 0 );
250        }
251    
252        /**
253         * Creates a new simple <code>Query</code> instance that selects the whole feature type.
254         * 
255         * @param typeName
256         *            name of the feature to be queried
257         * @param filter
258         *            spatial and none-spatial constraints
259         * @return new <code>Query</code> instance
260         */
261        public static Query create( QualifiedName typeName, Filter filter ) {
262            return new Query( null, null, null, null, null, new QualifiedName[] { typeName }, null, null, filter,
263                              RESULT_TYPE.RESULTS, -1, 0 );
264        }
265        
266        /**
267         * Creates a <code>Query</code> instance from a document that contains the DOM representation
268         * of the request, using the 1.1.0 filter encoding.
269         * <p>
270         * Note that the following attributes from the surrounding element are also considered (if it
271         * present):
272         * <ul>
273         * <li>resultType</li>
274         * <li>maxFeatures</li>
275         * <li>startPosition</li>
276         * </ul>
277         * 
278         * @param element
279         * @return corresponding <code>Query</code> instance
280         * @throws XMLParsingException
281         */
282        public static Query create( Element element )
283                                throws XMLParsingException {
284            return create( element, false);
285        }
286    
287        /**
288         * Creates a <code>Query</code> instance from a document that contains the DOM representation
289         * of the request.
290         * <p>
291         * Note that the following attributes from the surrounding element are also considered (if it
292         * present):
293         * <ul>
294         * <li>resultType</li>
295         * <li>maxFeatures</li>
296         * <li>startPosition</li>
297         * </ul>
298         * 
299         * @param element
300         * @param useVersion_1_0_0 if the filterencoding 1.0.0 rules should be applied.
301         * @return corresponding <code>Query</code> instance
302         * @throws XMLParsingException
303         */
304        public static Query create( Element element, boolean useVersion_1_0_0 )
305                                throws XMLParsingException {
306    
307            GetFeatureDocument doc = new GetFeatureDocument();
308            Query query = doc.parseQuery( element, useVersion_1_0_0 );
309            return query;
310        }
311        
312    
313        /**
314         * Returns the handle attribute.
315         * <p>
316         * The handle attribute is included to allow a client to associate a mnemonic name to the query.
317         * The purpose of the handle attribute is to provide an error handling mechanism for locating a
318         * statement that might fail.
319         * 
320         * @return the handle attribute
321         */
322        public String getHandle() {
323            return this.handle;
324        }
325    
326        /**
327         * Returns the names of the requested feature types.
328         * 
329         * @return the names of the requested feature types
330         */
331        public QualifiedName[] getTypeNames() {
332            return this.typeNames;
333        }
334    
335        /**
336         * Returns the aliases for the requested feature types.
337         * <p>
338         * The returned array is either null or has the same length as the array returned by
339         * {@link #getTypeNames()}.
340         * 
341         * @see #getTypeNames()
342         * @return the aliases for the requested feature types, or null if no aliases are used
343         */
344        public String[] getAliases() {
345            return this.aliases;
346        }
347    
348        /**
349         * Returns the srsName attribute.
350         * 
351         * @return the srsName attribute
352         */
353        public String getSrsName() {
354            return this.srsName;
355        }
356    
357        /**
358         * Sets the srsName attribute to given value.
359         * 
360         * @param srsName
361         *            name of the requested SRS
362         */
363        public void setSrsName( String srsName ) {
364            this.srsName = srsName;
365        }
366    
367        /**
368         * Returns the featureVersion attribute.
369         * 
370         * The version attribute is included in order to accommodate systems that support feature
371         * versioning. A value of ALL indicates that all versions of a feature should be fetched.
372         * Otherwise an integer can be specified to return the n th version of a feature. The version
373         * numbers start at '1' which is the oldest version. If a version value larger than the largest
374         * version is specified then the latest version is return. The default action shall be for the
375         * query to return the latest version. Systems that do not support versioning can ignore the
376         * parameter and return the only version that they have.
377         * 
378         * @return the featureVersion attribute
379         */
380        public String getFeatureVersion() {
381            return this.featureVersion;
382        }
383    
384        /**
385         * Returns all requested properties.
386         * 
387         * @return all requested properties
388         * 
389         * @see #getFunctions()
390         */
391        public PropertyPath[] getPropertyNames() {
392            return this.propertyNames;
393        }
394    
395        /**
396         * Beside property names a query may contains 0 to n functions modifying the values of one or
397         * more original properties. E.g. instead of area and population the density of a country can be
398         * requested by using a function instead:
399         * 
400         * <pre>
401         *  &lt;ogc:Div&gt;
402         *   &lt;ogc:PropertyName&gt;population&lt;/ogc:PropertyName&gt;
403         *   &lt;ogc:PropertyName&gt;area&lt;/ogc:PropertyName&gt;
404         *  &lt;/ogc:Div&gt;
405         * </pre>
406         * 
407         * <p>
408         * If no functions and no property names are specified all properties should be fetched.
409         * </p>
410         * 
411         * @return requested functions
412         * 
413         * @see #getPropertyNames()
414         */
415        public Function[] getFunctions() {
416            return this.functions;
417        }
418    
419        /**
420         * Returns the filter that limits the query.
421         * 
422         * @return the filter that limits the query
423         */
424        public Filter getFilter() {
425            return this.filter;
426        }
427    
428        /**
429         * Returns the sort criteria for the result.
430         * 
431         * @return the sort criteria for the result
432         */
433        public SortProperty[] getSortProperties() {
434            return this.sortProperties;
435        }
436    
437        /**
438         * Returns the value of the resultType attribute ("inherited" from the GetFeature container).
439         * 
440         * @return the value of the resultType attribute
441         */
442        public RESULT_TYPE getResultType() {
443            return this.resultType;
444        }
445    
446        /**
447         * Returns the value of the maxFeatures attribute ("inherited" from the GetFeature container).
448         * 
449         * The optional maxFeatures attribute can be used to limit the number of features that a
450         * GetFeature request retrieves. Once the maxFeatures limit is reached, the result set is
451         * truncated at that point. If not limit is set -1 will be returned
452         * 
453         * @return the value of the maxFeatures attribute
454         */
455        public int getMaxFeatures() {
456            return this.maxFeatures;
457        }
458    
459        /**
460         * @param maxFeatures
461         */
462        public void setMaxFeatures( int maxFeatures ) {
463            this.maxFeatures = maxFeatures;
464        }
465    
466        /**
467         * Returns the value of the startPosition attribute ("inherited" from the GetFeature container).
468         * <p>
469         * The startPosition parameter identifies the first result set entry to be returned. If no
470         * startPosition is set explicitly, 1 will be returned.
471         * 
472         * @return the value of the startPosition attribute, 1 if undefined
473         */
474        public int getStartPosition() {
475            return this.startPosition;
476        }
477        
478        /**
479         * @see #getStartPosition()
480         * @param startPosition
481         */
482        public void setStartPosition(int startPosition) {
483            this.startPosition = startPosition;
484        }
485    
486        /**
487         * Returns a string representation of the object.
488         * 
489         * @return a string representation of the object
490         */
491        @Override
492        public String toString() {
493            String ret = null;
494            ret = "propertyNames = " + propertyNames + "\n";
495            ret += ( "handle = " + handle + "\n" );
496            ret += ( "version = " + featureVersion + "\n" );
497            ret += ( "typeName = " + typeNames + "\n" );
498            ret += ( "filter = " + filter + "\n" );
499            return ret;
500        }
501    }