001    // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wfs/capabilities/WFSCapabilitiesDocument.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2006 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    package org.deegree.ogcwebservices.wfs.capabilities;
044    
045    import java.io.IOException;
046    import java.net.MalformedURLException;
047    import java.net.URI;
048    import java.net.URISyntaxException;
049    import java.net.URL;
050    import java.security.InvalidParameterException;
051    import java.util.ArrayList;
052    import java.util.HashMap;
053    import java.util.List;
054    import java.util.Map;
055    
056    import org.deegree.datatypes.Code;
057    import org.deegree.datatypes.QualifiedName;
058    import org.deegree.framework.log.ILogger;
059    import org.deegree.framework.log.LoggerFactory;
060    import org.deegree.framework.util.StringTools;
061    import org.deegree.framework.xml.XMLParsingException;
062    import org.deegree.framework.xml.XMLTools;
063    import org.deegree.model.filterencoding.capabilities.FilterCapabilities;
064    import org.deegree.model.filterencoding.capabilities.FilterCapabilities110Fragment;
065    import org.deegree.model.metadata.iso19115.Keywords;
066    import org.deegree.model.spatialschema.Envelope;
067    import org.deegree.ogcbase.CommonNamespaces;
068    import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
069    import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
070    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
071    import org.deegree.ogcwebservices.getcapabilities.Operation;
072    import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
073    import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification;
074    import org.deegree.owscommon.OWSCommonCapabilitiesDocument;
075    import org.deegree.owscommon.OWSDomainType;
076    import org.w3c.dom.Document;
077    import org.w3c.dom.Element;
078    import org.w3c.dom.Node;
079    import org.xml.sax.SAXException;
080    
081    /**
082     * Represents a capabilities document for an OGC WFS 1.1.0 compliant web service.
083     * 
084     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
085     * @author last edited by: $Author: rbezema $
086     * 
087     * @version $Revision: 7928 $, $Date: 2007-08-07 10:39:27 +0200 (Di, 07 Aug 2007) $
088     */
089    public class WFSCapabilitiesDocument extends OWSCommonCapabilitiesDocument {
090    
091        private static final long serialVersionUID = 6664839532969382269L;
092        private static ILogger LOG = LoggerFactory.getLogger( WFSCapabilitiesDocument.class );
093    
094        /**
095         * The "FeatureTypeList" string.
096         */
097        public final static String FEATURE_TYPE_LIST_NAME = "FeatureTypeList";
098    
099        /**
100         * The "ServesGMLObjectTypeList" string.
101         */
102        public final static String SERVES_GML_OBJECT_TYPE_LIST_NAME = "ServesGMLObjectTypeList";
103    
104        /**
105         * The "SupportsGMLObjectTypeList" string.
106         */
107        public final static String SUPPORTS_GML_OBJECT_TYPE_LIST_NAME = "SupportsGMLObjectTypeList";
108    
109        /**
110         * The "FilterCapabilities" string.
111         */
112        public final static String FILTER_CAPABILITIES_NAME = "FilterCapabilities";
113    
114        protected static final URI WFSNS = CommonNamespaces.WFSNS;
115        private static final String PRE_WFS = CommonNamespaces.WFS_PREFIX +":";
116        
117        private static final String PRE_OWS = CommonNamespaces.OWS_PREFIX +":";
118    
119        protected static final URI OGCNS = CommonNamespaces.OGCNS;
120    
121        protected static final URI DEEGREEWFSNS = CommonNamespaces.DEEGREEWFS;
122    
123        private static final String XML_TEMPLATE = "WFSCapabilitiesTemplate.xml";
124    
125        private static final String[] VALID_TYPES = { "TDC211", "FGDC", "19115", "19139" };
126    
127        private static final String[] VALID_FORMATS = { "text/xml", "text/html", "text/sgml",
128                                                       "text/plain" };
129    
130    
131        /**
132         * Creates a skeleton capabilities document that contains the mandatory elements only.
133         * 
134         * @throws IOException
135         * @throws SAXException
136         */
137        public void createEmptyDocument() throws IOException,
138                                         SAXException {
139            URL url = WFSCapabilitiesDocument.class.getResource( XML_TEMPLATE );
140            if ( url == null ) {
141                throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." );
142            }
143            load( url );
144        }
145        
146        /**
147         * Creates an emptyDocument with given version, and an updateSequence of "0" without reading the skeleton document.
148         * @param version if 
149         * 
150         */
151        public void createEmptyDocument(String version) {
152            //      set up the root document.
153            Document doc = XMLTools.create();
154            Element root = doc.createElementNS( "http://www.opengis.net/wfs", PRE_WFS + "WFS_Capabilities" );
155            doc.importNode( root, false );
156    
157            setRootElement( root );
158            root.setAttribute( "version", version );
159            root.setAttribute( "updateSequence", "0" );
160        }
161    
162        /**
163         * Creates a class representation of the document.
164         * 
165         * @return class representation of the configuration document
166         */
167        @Override
168        public OGCCapabilities parseCapabilities() throws InvalidCapabilitiesException {
169    
170            WFSCapabilities wfsCapabilities = null;
171            try {
172    
173                wfsCapabilities = new WFSCapabilities( parseVersion(), parseUpdateSequence(),
174                                                       getServiceIdentification(),
175                                                       getServiceProvider(), getOperationsMetadata(),
176                                                       getFeatureTypeList(),
177                                                       getServesGMLObjectTypeList(),
178                                                       getSupportsGMLObjectTypeList(), null,
179                                                       getFilterCapabilities() );
180            } catch ( XMLParsingException e ) {
181                throw new InvalidCapabilitiesException( e.getMessage() + "\n"
182                                                        + StringTools.stackTraceToString( e ) );
183            }
184    
185            return wfsCapabilities;
186        }
187    
188        /**
189         * Returns the class representation for the <code>ServiceIdentification</code> section of the
190         * document. <p> NOTE: this method is overridden, because the WFS 1.1.0 requires the OWS 1.0.0
191         * version of the element
192         * 
193         * @return class representation for the <code>ServiceIdentification</code> section
194         * @throws XMLParsingException
195         */
196        @Override
197        public ServiceIdentification getServiceIdentification() throws XMLParsingException {
198    
199    //        Element element = XMLTools.getRequiredChildElement( "ServiceIdentification", OWSNS,
200    //                                                            getRootElement() );
201          Element element = XMLTools.getRequiredElement( getRootElement(),  PRE_OWS+"ServiceIdentification", nsContext );
202    
203            // 'ServiceType' element (mandatory)
204    //        Element serviceTypeElement = XMLTools.getRequiredChildElement( "ServiceType", OWSNS,
205    //                                                                       element );
206            Element serviceTypeElement = XMLTools.getRequiredElement( element, PRE_OWS+"ServiceType", nsContext);
207            Code serviceType = null;
208            try {
209                String codeSpace = XMLTools.getAttrValue( serviceTypeElement, OWSNS, "codeSpace", null );
210                URI uri = codeSpace != null ? new URI( codeSpace ) : null;
211                serviceType = new Code( XMLTools.getStringValue( serviceTypeElement ), uri );
212            } catch ( URISyntaxException e ) {
213                throw new XMLParsingException( "Given value '"
214                                               + XMLTools.getAttrValue( serviceTypeElement, OWSNS,
215                                                                        "codeSpace", null )
216                                               + "' in attribute 'codeSpace' of element 'ServiceType' "
217                                               + "(namespace: '" + OWSNS + "') is not a valid URI." );
218            }
219    
220            // 'ServiceTypeVersion' elements (mandatory)
221            String[] serviceTypeVersions = XMLTools.getRequiredNodeAsStrings( element,
222                                                                              "ows:ServiceTypeVersion",
223                                                                              nsContext, ",;" );
224            if ( serviceTypeVersions.length == 0 ) {
225                String msg = "No version specified in 'ows:ServiceTypeVersion' element.";
226                throw new XMLParsingException( msg );
227            }
228    
229            // 'Fees' element (optional)
230            String fees = XMLTools.getStringValue( "Fees", OWSNS, element, null );
231    
232            // 'AccessConstraints' elements (optional)
233            String accessConstraints[] = XMLTools.getNodesAsStrings( element, "ows:AccessConstraints",
234                                                                     nsContext );
235    
236            ServiceIdentification serviceIdentification = new ServiceIdentification(
237                                                                                     serviceType,
238                                                                                     serviceTypeVersions,
239                                                                                     null, null, null,
240                                                                                     fees,
241                                                                                     accessConstraints );
242            return serviceIdentification;
243        }
244    
245        /**
246         * Creates an object representation of the <code>ows:OperationsMetadata</code> section.
247         * 
248         * @return object representation of the <code>ows:OperationsMetadata</code> section
249         * @throws XMLParsingException
250         */
251        public OperationsMetadata getOperationsMetadata() throws XMLParsingException {
252    
253            List<Node> operationElementList = XMLTools.getNodes( getRootElement(),
254                                                              "ows:OperationsMetadata/ows:Operation",
255                                                              nsContext );
256    
257            // build HashMap of 'ows:Operation'-elements for easier access
258            Map<String, Node> operations = new HashMap<String, Node>();
259            for ( int i = 0; i < operationElementList.size(); i++ ) {
260                operations.put( XMLTools.getRequiredNodeAsString(  operationElementList.get( i ),
261                                                                  "@name", nsContext ),
262                                operationElementList.get( i ) );
263            }
264    
265            Operation getCapabilities = getOperation( OperationsMetadata.GET_CAPABILITIES_NAME, true,
266                                                      operations );
267            Operation describeFeatureType = getOperation(
268                                                          WFSOperationsMetadata.DESCRIBE_FEATURETYPE_NAME,
269                                                          true, operations );
270            Operation getFeature = getOperation( WFSOperationsMetadata.GET_FEATURE_NAME, false,
271                                                 operations );
272            Operation getFeatureWithLock = getOperation(
273                                                         WFSOperationsMetadata.GET_FEATURE_WITH_LOCK_NAME,
274                                                         false, operations );
275            Operation getGMLObject = getOperation( WFSOperationsMetadata.GET_GML_OBJECT_NAME, false,
276                                                   operations );
277            Operation lockFeature = getOperation( WFSOperationsMetadata.LOCK_FEATURE_NAME, false,
278                                                  operations );
279            Operation transaction = getOperation( WFSOperationsMetadata.TRANSACTION_NAME, false,
280                                                  operations );
281    
282            List parameterElementList = XMLTools.getNodes( getRootElement(),
283                                                           "ows:OperationsMetadata/ows:Parameter",
284                                                           nsContext );
285            OWSDomainType[] parameters = new OWSDomainType[parameterElementList.size()];
286            for ( int i = 0; i < parameters.length; i++ ) {
287                parameters[i] = getOWSDomainType( null, (Element) parameterElementList.get( i ) );
288            }
289    
290            List constraintElementList = XMLTools.getNodes( getRootElement(),
291                                                            "ows:OperationsMetadata/ows:Constraint",
292                                                            nsContext );
293            OWSDomainType[] constraints = new OWSDomainType[constraintElementList.size()];
294            for ( int i = 0; i < constraints.length; i++ ) {
295                constraints[i] = getOWSDomainType( null, (Element) constraintElementList.get( i ) );
296            }
297            WFSOperationsMetadata metadata = new WFSOperationsMetadata( getCapabilities,
298                                                                        describeFeatureType,
299                                                                        getFeature, getFeatureWithLock,
300                                                                        getGMLObject, lockFeature,
301                                                                        transaction, parameters,
302                                                                        constraints );
303    
304            return metadata;
305        }
306    
307        /**
308         * Returns the object representation for the <code>wfs:FeatureTypeList</code>- section.
309         * 
310         * @return object representation of the <code>wfs:FeatureTypeList</code> section, may be empty
311         *         (if missing)
312         * @throws XMLParsingException
313         */
314        public FeatureTypeList getFeatureTypeList() throws XMLParsingException {
315    
316            List<WFSFeatureType> wfsFeatureTypes = new ArrayList<WFSFeatureType>();
317    
318            FeatureTypeList featureTypeList = new FeatureTypeList(
319                                                                   new org.deegree.ogcwebservices.wfs.capabilities.Operation[0],
320                                                                   wfsFeatureTypes );
321    
322            Element element = (Element) XMLTools.getNode( getRootElement(), "wfs:FeatureTypeList",
323                                                          nsContext );
324            if ( element != null ) {
325                org.deegree.ogcwebservices.wfs.capabilities.Operation[] globalOperations = null;
326                Element operationsTypeElement = (Element) XMLTools.getNode( element, "wfs:Operations",
327                                                                            nsContext );
328                if ( operationsTypeElement != null ) {
329                    globalOperations = getOperationsType( operationsTypeElement );
330                }
331                List featureTypeElementList = XMLTools.getNodes( element, "wfs:FeatureType", nsContext );
332                // TODO Check this.
333                // if ( featureTypeElementList.getLength() < 1 ) {
334                // throw new XMLParsingException(
335                // "A wfs:FeatureTypeListType must contain at least one wfs:FeatureType-element." );
336                // }
337                for ( int i = 0; i < featureTypeElementList.size(); i++ ) {
338                    WFSFeatureType wfsFT = getFeatureTypeType( (Element) featureTypeElementList.get( i ) );
339                    wfsFeatureTypes.add( wfsFT );
340                }
341    
342                featureTypeList = new FeatureTypeList( globalOperations, wfsFeatureTypes );
343            }
344    
345            return featureTypeList;
346        }
347    
348        /**
349         * Returns the object representation for the <code>wfs:ServesGMLObjectTypeList</code>-
350         * section.
351         * 
352         * @return object representation of the <code>wfs:ServesGMLObjectTypeList</code> section, null
353         *         if the section does not exist
354         * @throws XMLParsingException
355         */
356        public GMLObject[] getServesGMLObjectTypeList() throws XMLParsingException {
357    
358            GMLObject[] gmlObjectTypes = null;
359            Element element = (Element) XMLTools.getNode( getRootElement(),
360                                                          "wfs:ServesGMLObjectTypeList", nsContext );
361            if ( element != null ) {
362                List nodeList = XMLTools.getRequiredNodes( element, "wfs:GMLObjectType", nsContext );
363                gmlObjectTypes = new GMLObject[nodeList.size()];
364                for ( int i = 0; i < gmlObjectTypes.length; i++ ) {
365                    gmlObjectTypes[i] = getGMLObjectType( (Element) nodeList.get( i ) );
366                }
367            }
368    
369            return gmlObjectTypes;
370        }
371    
372        /**
373         * Returns the object representation for the <code>wfs:SupportsGMLObjectTypeList</code>-
374         * section.
375         * 
376         * @return object representation of the <code>wfs:SupportsGMLObjectTypeList</code> section,
377         *         null if the section does not exist
378         * @throws XMLParsingException
379         */
380        public GMLObject[] getSupportsGMLObjectTypeList() throws XMLParsingException {
381    
382            GMLObject[] gmlObjectTypes = null;
383            Element element = (Element) XMLTools.getNode( getRootElement(),
384                                                          "wfs:SupportsGMLObjectTypeList", nsContext );
385            if ( element != null ) {
386                List nodeList = XMLTools.getRequiredNodes( element, "wfs:GMLObjectType", nsContext );
387                gmlObjectTypes = new GMLObject[nodeList.size()];
388                for ( int i = 0; i < gmlObjectTypes.length; i++ ) {
389                    gmlObjectTypes[i] = getGMLObjectType( (Element) nodeList.get( i ) );
390                }
391            }
392    
393            return gmlObjectTypes;
394        }
395    
396        /**
397         * Returns the object representation for an element of type <code>wfs:GMLObjectType</code>.
398         * 
399         * @param element
400         * @return object representation of the element of type <code>wfs:GMLObjectType</code>
401         * @throws XMLParsingException
402         */
403        public GMLObject getGMLObjectType( Element element ) throws XMLParsingException {
404            QualifiedName name = parseQualifiedName( XMLTools.getRequiredNode( element,
405                                                                               "wfs:Name/text()",
406                                                                               nsContext ) );
407            String title = XMLTools.getNodeAsString( element, "wfs:Title/text()", nsContext, null );
408            String abstract_ = XMLTools.getNodeAsString( element, "wfs:Abstract/text()", nsContext,
409                                                         null );
410            Keywords[] keywords = getKeywords( XMLTools.getNodes( element, "ows:Keywords", nsContext ) );
411            List formatElementList = XMLTools.getNodes( element, "wfs:OutputFormats/wfs:Format",
412                                                        nsContext );
413            FormatType[] outputFormats = new FormatType[formatElementList.size()];
414            for ( int i = 0; i < outputFormats.length; i++ ) {
415                outputFormats[i] = getFormatType( (Element) formatElementList.get( i ) );
416            }
417            return new GMLObject( name, title, abstract_, keywords, outputFormats );
418        }
419    
420        /**
421         * Returns the object representation for an element of type <code>wfs:FeatureTypeType</code>.
422         * 
423         * @param element
424         * @return object representation for the element of type <code>wfs:OperationsType</code>
425         * @throws XMLParsingException
426         */
427        public WFSFeatureType getFeatureTypeType( Element element ) throws XMLParsingException {
428    
429            QualifiedName name = parseQualifiedName( XMLTools.getRequiredNode( element,
430                                                                               "wfs:Name/text()",
431                                                                               nsContext ) );
432            String title = XMLTools.getRequiredNodeAsString( element, "wfs:Title/text()", nsContext );
433            String abstract_ = XMLTools.getNodeAsString( element, "wfs:Abstract/text()", nsContext,
434                                                         null );
435            Keywords[] keywords = getKeywords( XMLTools.getNodes( element, "ows:Keywords", nsContext ) );
436    
437            URI defaultSrs = null;
438            URI[] otherSrs = null;
439            Node noSrsElement = XMLTools.getNode( element, "wfs:NoSRS", nsContext );
440            if ( noSrsElement == null ) {
441                defaultSrs = XMLTools.getNodeAsURI( element, "wfs:DefaultSRS/text()", nsContext, null );
442                if ( defaultSrs == null ) {
443                    String msg = "A 'wfs:FeatureType' element must always contain a 'wfs:NoSRS' "
444                                 + "element  or a 'wfs:DefaultSRS' element";
445                    throw new XMLParsingException( msg );
446                }
447                otherSrs = XMLTools.getNodesAsURIs( element, "wfs:OtherSRS/text()", nsContext );
448            }
449    
450            org.deegree.ogcwebservices.wfs.capabilities.Operation[] operations = null;
451            Element operationsTypeElement = (Element) XMLTools.getNode( element, "wfs:Operations",
452                                                                        nsContext );
453            if ( operationsTypeElement != null ) {
454                operations = getOperationsType( operationsTypeElement );
455            }
456            List formatElementList = XMLTools.getNodes( element, "wfs:OutputFormats/wfs:Format",
457                                                        nsContext );
458            FormatType[] formats = new FormatType[formatElementList.size()];
459            for ( int i = 0; i < formats.length; i++ ) {
460                formats[i] = getFormatType( (Element) formatElementList.get( i ) );
461            }
462            List wgs84BoundingBoxElements = XMLTools.getNodes( element, "ows:WGS84BoundingBox",
463                                                               nsContext );
464            if ( wgs84BoundingBoxElements.size() < 1 ) {
465                throw new XMLParsingException( "A 'wfs:FeatureTypeType' must contain at least one "
466                                               + "'ows:WGS84BoundingBox'-element." );
467            }
468            Envelope[] wgs84BoundingBoxes = new Envelope[wgs84BoundingBoxElements.size()];
469            for ( int i = 0; i < wgs84BoundingBoxes.length; i++ ) {
470                wgs84BoundingBoxes[i] = getWGS84BoundingBoxType( (Element) wgs84BoundingBoxElements.get( i ) );
471            }
472            List metadataURLElementList = XMLTools.getNodes( element, "wfs:MetadataURL", nsContext );
473            MetadataURL[] metadataUrls = new MetadataURL[metadataURLElementList.size()];
474            for ( int i = 0; i < metadataUrls.length; i++ ) {
475                metadataUrls[i] = getMetadataURL( (Element) metadataURLElementList.get( i ) );
476            }
477            WFSFeatureType featureType = new WFSFeatureType( name, title, abstract_, keywords,
478                                                             defaultSrs, otherSrs, operations, formats,
479                                                             wgs84BoundingBoxes, metadataUrls );
480    
481            return featureType;
482        }
483    
484        /**
485         * Returns the object representation for an <code>wfs:OutputFormat</code> -element.
486         * 
487         * @param element
488         * @return object representation for the element
489         * @throws XMLParsingException
490         */
491        public FormatType getFormatType( Element element ) throws XMLParsingException {
492    
493            String[] tmp = new String[3];
494            URI[] uris = new URI[3];
495            tmp[0] = XMLTools.getNodeAsString( element, "@deegreewfs:inFilter", nsContext,
496                                                        null );
497            tmp[1] = XMLTools.getNodeAsString( element, "@deegreewfs:outFilter", nsContext,
498                                               null );
499            tmp[2] = XMLTools.getNodeAsString( element, "@deegreewfs:schemaLocation",
500                                               nsContext, null );
501            for ( int i = 0; i < tmp.length; i++ ) {
502               try {
503                   if ( tmp[i] != null && !"".equals( tmp[i].trim() )) {
504                       if (  !( tmp[i].toLowerCase().startsWith( "file:/" ) ) ) {
505                           tmp[i] = this.resolve( tmp[i] ).toExternalForm();
506                           LOG.logDebug( "Found format "+ (( i == 0)?"inFilter":((i==1)?"outFilter":"schemaLocation")) +" at location: " + tmp[i] );
507                       }
508                       uris[i] = new URI( tmp[i] );
509                   }               
510                } catch ( MalformedURLException e ) {
511                    throw new XMLParsingException( "Could not resolve relative path:" + tmp[i] );
512                } catch ( URISyntaxException e ) {
513                    throw new XMLParsingException( "Not a valid URI:" + tmp[i] );
514                }
515            }
516            
517            String value = XMLTools.getRequiredNodeAsString( element, "text()", nsContext );
518            
519            return new FormatType( uris[0], uris[1], uris[2], value );
520        }
521    
522        /**
523         * Returns the object representation for an element node of type
524         * <code>wfs:MetadataURLType</code>.
525         * 
526         * TODO: Schema says base type is String, not URL!
527         * 
528         * @param element
529         * @return object representation for the element of type <code>wfs:MetadataURLType</code>
530         * @throws XMLParsingException
531         */
532        public MetadataURL getMetadataURL( Element element ) throws XMLParsingException {
533    
534            String type = XMLTools.getRequiredNodeAsString( element, "@type", nsContext, VALID_TYPES );
535            String format = XMLTools.getRequiredNodeAsString( element, "@format", nsContext,
536                                                              VALID_FORMATS );
537            String url = XMLTools.getRequiredNodeAsString( element, "text()", nsContext );
538            URL onlineResource;
539            try {
540                onlineResource = new URL( url );
541            } catch ( MalformedURLException e ) {
542                throw new XMLParsingException( "A wfs:MetadataURLType must contain a valid URL: "
543                                               + e.getMessage() );
544            }
545    
546            return new MetadataURL( type, format, onlineResource );
547        }
548    
549        /**
550         * Returns the object representation for an element node of type <code>wfs:OperationsType</code>.
551         * 
552         * @param element
553         * @return object representation for the element of type <code>wfs:OperationsType</code>
554         * @throws XMLParsingException
555         */
556        public org.deegree.ogcwebservices.wfs.capabilities.Operation[] getOperationsType(
557                                                                                         Element element ) throws XMLParsingException {
558    
559            String[] operationCodes = XMLTools.getNodesAsStrings( element, "wfs:Operation/text()",
560                                                                  nsContext );
561            org.deegree.ogcwebservices.wfs.capabilities.Operation[] operations = new org.deegree.ogcwebservices.wfs.capabilities.Operation[operationCodes.length];
562            for ( int i = 0; i < operations.length; i++ ) {
563                try {
564                    operations[i] = new org.deegree.ogcwebservices.wfs.capabilities.Operation(
565                                                                                               operationCodes[i] );
566                } catch ( InvalidParameterException e ) {
567                    throw new XMLParsingException( e.getMessage() );
568                }
569            }
570    
571            return operations;
572        }
573    
574        /**
575         * Returns the object representation for the <code>Filter_Capabilities</code> section of the
576         * document.
577         * 
578         * @return class representation for the <code>Filter_Capabilities</code> section
579         * @throws XMLParsingException
580         */
581        public FilterCapabilities getFilterCapabilities() throws XMLParsingException {
582    
583            FilterCapabilities filterCapabilities = null;
584            Element filterCapabilitiesElement = (Element) XMLTools.getNode( getRootElement(),
585                                                                            "ogc:Filter_Capabilities",
586                                                                            nsContext );
587            if ( filterCapabilitiesElement != null ) {
588                filterCapabilities = new FilterCapabilities110Fragment( filterCapabilitiesElement,
589                                                                        getSystemId() ).parseFilterCapabilities();
590            }
591            return filterCapabilities;
592        }
593    }