    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/ogcwebservices/wpvs/capabilities/WPVSCapabilitiesDocument.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
    037    package org.deegree.ogcwebservices.wpvs.capabilities;
    038
    039    import java.io.IOException;
    040    import java.net.MalformedURLException;
    041    import java.net.URI;
    042    import java.net.URL;
    043    import java.util.ArrayList;
    044    import java.util.Arrays;
    045    import java.util.HashMap;
    046    import java.util.List;
    047    import java.util.Map;
    048    import java.util.Queue;
    049    import java.util.concurrent.LinkedBlockingQueue;
    050
    051    import org.deegree.datatypes.values.TypedLiteral;
    052    import org.deegree.datatypes.values.ValueRange;
    053    import org.deegree.datatypes.xlink.SimpleLink;
    054    import org.deegree.framework.log.ILogger;
    055    import org.deegree.framework.log.LoggerFactory;
    056    import org.deegree.framework.util.StringTools;
    057    import org.deegree.framework.xml.NamespaceContext;
    058    import org.deegree.framework.xml.XMLParsingException;
    059    import org.deegree.framework.xml.XMLTools;
    060    import org.deegree.i18n.Messages;
    061    import org.deegree.model.crs.CRSFactory;
    062    import org.deegree.model.crs.CoordinateSystem;
    063    import org.deegree.model.crs.UnknownCRSException;
    064    import org.deegree.model.metadata.iso19115.Keywords;
    065    import org.deegree.model.metadata.iso19115.OnlineResource;
    066    import org.deegree.model.spatialschema.Envelope;
    067    import org.deegree.model.spatialschema.GeometryFactory;
    068    import org.deegree.ogcbase.CommonNamespaces;
    069    import org.deegree.ogcwebservices.InvalidParameterValueException;
    070    import org.deegree.ogcwebservices.MissingParameterValueException;
    071    import org.deegree.ogcwebservices.OGCWebServiceException;
    072    import org.deegree.ogcwebservices.getcapabilities.DCPType;
    073    import org.deegree.ogcwebservices.getcapabilities.HTTP;
    074    import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
    075    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
    076    import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
    077    import org.deegree.ogcwebservices.getcapabilities.Protocol;
    078    import org.deegree.owscommon.OWSCommonCapabilitiesDocument;
    079    import org.deegree.owscommon.OWSMetadata;
    080    import org.deegree.owscommon.com110.HTTP110;
    081    import org.deegree.owscommon.com110.OWSAllowedValues;
    082    import org.deegree.owscommon.com110.OWSDomainType110;
    083    import org.deegree.owscommon.com110.OWSRequestMethod;
    084    import org.deegree.owscommon.com110.Operation110;
    085    import org.w3c.dom.Element;
    086    import org.w3c.dom.Node;
    087    import org.xml.sax.SAXException;
    088
    089    /**
    090     * This class represents a <code>WPVSCapabilitiesDocument</code> object.
    091     *
    092     * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
    093     * @author last edited by: $Author: mschneider $
    094     *
    095     * $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    096     *
    097     */
    098    public class WPVSCapabilitiesDocument extends OWSCommonCapabilitiesDocument {
    099
    100        private ArrayList<String> datasetIdentifiers = new ArrayList<String>();
    101
    102        private ArrayList<String> styleIdentifiers = new ArrayList<String>();
    103
    104        /**
    105         *
    106         */
    107        private static final long serialVersionUID = 2633513531080190745L;
    108
    109        private static final ILogger LOG = LoggerFactory.getLogger( WPVSCapabilitiesDocument.class );
    110
    111        private static final String XML_TEMPLATE = "WPVSCapabilitiesTemplate.xml";
    112
    113        private static String PRE_WPVS = CommonNamespaces.WPVS_PREFIX + ":";
    114
    115        private static String PRE_OWS = CommonNamespaces.OWS_PREFIX + ":";
    116
    117        /**
    118         * Creates a skeleton capabilities document that contains the mandatory elements only.
    119         *
    120         * @throws IOException
    121         * @throws SAXException
    122         */
    123        public void createEmptyDocument()
    124                                         throws IOException, SAXException {
    125            URL url = WPVSCapabilitiesDocument.class.getResource( XML_TEMPLATE );
    126            if ( url == null ) {
    127                throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." );
    128            }
    129            load( url );
    130        }
    131
    132        /**
    133         * @see org.deegree.ogcwebservices.getcapabilities.OGCCapabilitiesDocument#parseCapabilities()
    134         */
    135        @Override
    136        public OGCCapabilities parseCapabilities()
    137                                                  throws InvalidCapabilitiesException {
    138            WPVSCapabilities wpvsCapabilities = null;
    139
    140            try {
    141                wpvsCapabilities = new WPVSCapabilities( parseVersion(),
    142                                                         parseUpdateSequence(),
    143                                                         getServiceIdentification(),
    144                                                         getServiceProvider(),
    145                                                         parseOperationsMetadata( null ),
    146                                                         null,
    147                                                         getDataset() );
    148
    149            } catch ( XMLParsingException e ) {
    150                throw new InvalidCapabilitiesException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
    151
    152            } catch ( MissingParameterValueException e ) {
    153                throw new InvalidCapabilitiesException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
    154
    155            } catch ( InvalidParameterValueException e ) {
    156                throw new InvalidCapabilitiesException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
    157
    158            } catch ( OGCWebServiceException e ) {
    159                throw new InvalidCapabilitiesException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
    160            }
    161
    162            return wpvsCapabilities;
    163        }
    164
    165        /**
    166         * Gets the <code>Dataset</code> object from the root element of the WPVSCapabilities element.
    167         *
    168         *
    169         * @return Returns the Dataset object form root element.
    170         * @throws XMLParsingException
    171         * @throws OGCWebServiceException
    172         * @throws InvalidParameterValueException
    173         * @throws MissingParameterValueException
    174         */
    175        private Dataset getDataset()
    176                                    throws XMLParsingException, MissingParameterValueException,
    177                                    InvalidParameterValueException, OGCWebServiceException {
    178
    179            Element datasetElement = (Element) XMLTools.getRequiredNode( getRootElement(), PRE_WPVS + "Dataset", nsContext );
    180            Dataset dataset = parseDataset( datasetElement, null, null, null );
    181
    182            return dataset;
    183        }
    184
    185        /**
    186         * Creates and returns a new <code>Dataset</code> object from the given <code>Element</code> and the parent
    187         * <code>Dataset</code> object.
    188         *
    189         * @param datasetElement
    190         * @param parent
    191         *            may be null if root node
    192         * @param defaultCoordinateSystem
    193         * @param defaultElevationModel
    194         * @return Returns a new Dataset object.
    195         * @throws XMLParsingException
    196         * @throws OGCWebServiceException
    197         * @throws InvalidParameterValueException
    198         */
    199        private Dataset parseDataset( Element datasetElement, Dataset parent, CoordinateSystem defaultCoordinateSystem,
    200                                      ElevationModel defaultElevationModel )
    201                                                                            throws XMLParsingException,
    202                                                                            InvalidParameterValueException,
    203                                                                            OGCWebServiceException {
    204
    205            // attributes are all optional
    206            boolean queryable = XMLTools.getNodeAsBoolean( datasetElement, "@queryable", nsContext, false );
    207            boolean opaque = XMLTools.getNodeAsBoolean( datasetElement, "@opaque", nsContext, false );
    208            boolean noSubsets = XMLTools.getNodeAsBoolean( datasetElement, "@noSubsets", nsContext, false );
    209            int fixedWidth = XMLTools.getNodeAsInt( datasetElement, "@fixedWidth", nsContext, 0 );
    210            int fixedHeight = XMLTools.getNodeAsInt( datasetElement, "@fixedHeight", nsContext, 0 );
    211
    212            // elements
    213            String name = XMLTools.getNodeAsString( datasetElement, PRE_WPVS + "Name/text()", nsContext, null );
    214            String title = XMLTools.getRequiredNodeAsString( datasetElement, PRE_WPVS + "Title/text()", nsContext );
    215            String abstract_ = XMLTools.getNodeAsString( datasetElement, PRE_WPVS + "Abstract/text()", nsContext, null );
    216            // keywords == optional
    217            Keywords[] keywords = getKeywords( XMLTools.getNodes( datasetElement, PRE_OWS + "Keywords", nsContext ) );
    218            // crsstrings == optional
    219            String[] crsStrings = XMLTools.getNodesAsStrings( datasetElement, PRE_WPVS + "CRS/text()", nsContext );
    220            List<CoordinateSystem> crsList = parseCoordinateSystems( crsStrings );
    221            ElevationModel elevationModel = parseElevationModel( datasetElement, defaultElevationModel );
    222            // create a default ElevationModel if not exists allready, a little HACK to circumvent the
    223            // optional deegree:dataset:ElevationModel mapping onto the mandatory
    224            // ogc:dataset:ElevationModel
    225            if ( defaultElevationModel == null && elevationModel != null ) {
    226                defaultElevationModel = elevationModel;
    227                // found an ElevationModel setting it to default
    228                // and update the parents of this dataset, until we have the root,
    229
    230                if ( parent != null ) {
    231                    // first find root parent
    232                    Dataset tmpParent = parent;
    233                    while ( tmpParent.getParent() != null ) {
    234                        tmpParent = tmpParent.getParent();
    235                    }
    236                    // now iterate over all so far created children to set an default elevationmodel
    237                    tmpParent.setElevationModel( defaultElevationModel );
    238                    Queue<Dataset> children = new LinkedBlockingQueue<Dataset>( Arrays.asList( tmpParent.getDatasets() ) );
    239                    while ( !children.isEmpty() ) {
    240                        Dataset child = children.poll();
    241                        if ( child != null ) {
    242                            child.setElevationModel( defaultElevationModel );
    243                            for ( Dataset dataset : child.getDatasets() ) {
    244                                children.offer( dataset );
    245                            }
    246                        }
    247                    }
    248                }
    249            }
    250            // now find a defaultcoordinatesystem to use if no crs is given in a child dataset
    251            if ( parent == null ) { // root dataset
    252                if ( crsList.size() == 0 || crsList.get( 0 ) == null ) {
    253                    throw new InvalidCapabilitiesException( Messages.getMessage( "WPVS_NO_TOPLEVEL_DATASET_CRS", title ) );
    254                }
    255                defaultCoordinateSystem = crsList.get( 0 );
    256            }
    257
    258            String[] format = XMLTools.getRequiredNodesAsStrings( datasetElement, PRE_WPVS + "Format/text()", nsContext );
    259            // wgs84 == mandatory
    260            Element boundingBoxElement = (Element) XMLTools.getRequiredNode( datasetElement,
    261                                                                             PRE_OWS + "WGS84BoundingBox",
    262                                                                             nsContext );
    263            Envelope wgs84BoundingBox = getWGS84BoundingBoxType( boundingBoxElement );
    264
    265            // boundingboxes can be used to make a more precise specification of the useable area of
    266            // this dataset in it's native crs's, the wgs84 bbox can be inaccurate
    267            Envelope[] boundingBoxes = getBoundingBoxes( datasetElement, defaultCoordinateSystem );
    268
    269            // optional
    270            Dimension[] dimensions = parseDimensions( datasetElement );
    271
    272            // optional
    273            DataProvider dataProvider = parseDataProvider( datasetElement );
    274
    275            // mandatory
    276            Identifier identifier = parseDatasetIdentifier( datasetElement, PRE_WPVS + "Identifier" );
    277
    278            // optional
    279            MetaData[] metaData = parseMetaData( datasetElement );
    280
    281            // optional
    282            DatasetReference[] datasetRefs = parseDatasetReferences( datasetElement );
    283
    284            // optional
    285            FeatureListReference[] featureListRefs = parseFeatureListReferences( datasetElement );
    286
    287            // optional
    288            Style[] style = parseStyles( datasetElement );
    289
    290            // mandatory
    291            double minScaleDenom = XMLTools.getRequiredNodeAsDouble( datasetElement,
    292                                                                     PRE_WPVS + "MinimumScaleDenominator/text()",
    293                                                                     nsContext );
    294            // mandatory
    295            double maxScaleDenom = XMLTools.getRequiredNodeAsDouble( datasetElement,
    296                                                                     PRE_WPVS + "MaximumScaleDenominator/text()",
    297                                                                     nsContext );
    298
    299            if ( minScaleDenom > maxScaleDenom ) {
    300                throw new InvalidCapabilitiesException( Messages.getMessage( "WPVS_WRONG_SCALE_DENOMINATORS" ) );
    301            }
    302
    303            // create new root dataset
    304            Dataset dataset = new Dataset( queryable,
    305                                           opaque,
    306                                           noSubsets,
    307                                           fixedWidth,
    308                                           fixedHeight,
    309                                           name,
    310                                           title,
    311                                           abstract_,
    312                                           keywords,
    313                                           crsList,
    314                                           format,
    315                                           wgs84BoundingBox,
    316                                           boundingBoxes,
    317                                           dimensions,
    318                                           dataProvider,
    319                                           identifier,
    320                                           metaData,
    321                                           datasetRefs,
    322                                           featureListRefs,
    323                                           style,
    324                                           minScaleDenom,
    325                                           maxScaleDenom,
    326                                           null,
    327                                           elevationModel,
    328                                           null,
    329                                           parent );
    330
    331            // get child datasets
    332            List<Node> nl = XMLTools.getNodes( datasetElement, PRE_WPVS + "Dataset", nsContext );
    333            Dataset[] childDatasets = new Dataset[nl.size()];
    334            for ( int i = 0; i < childDatasets.length; i++ ) {
    335                childDatasets[i] = parseDataset( (Element) nl.get( i ),
    336                                                 dataset,
    337                                                 defaultCoordinateSystem,
    338                                                 defaultElevationModel );
    339            }
    340
    341            // set child datasets
    342            dataset.setDatasets( childDatasets );
    343
    344            return dataset;
    345        }
    346
    347        /**
    348         * @param coordinateStrings
    349         *            the Strings to create the coordinates from
    350         * @return a List of coordinatesystems, if no coordinateString were given (null || length==0 ) an emtpy list is
    351         *         returned.
    352         */
    353        protected List<CoordinateSystem> parseCoordinateSystems( String[] coordinateStrings ) {
    354            if ( coordinateStrings == null )
    355                return new ArrayList<CoordinateSystem>();
    356            ArrayList<CoordinateSystem> crsList = new ArrayList<CoordinateSystem>( coordinateStrings.length );
    357            for ( String tmpCRS : coordinateStrings ) {
    358                try {
    359                    CoordinateSystem crs = CRSFactory.create( tmpCRS );
    360                    crsList.add( crs );
    361                } catch ( UnknownCRSException e ) {
    362                    // fail configuration notify the user
    363                    LOG.logError( e.getLocalizedMessage(), e );
    364                }
    365            }
    366            return crsList;
    367        }
    368
    369        /**
    370         * Creates and returns a new <code>ElevationModel</code> object from the given <code>Element</code>.
    371         *
    372         * This OGC ElevationModel contains only a String. ATTENTION ogc elevation model is mandatory, we IGNORE this and
    373         * say it's mandatory.
    374         *
    375         * @param datasetElement
    376         * @param defaultElevationModel
    377         *            the defaultElevationModel will be used if no elevationmodel was defined in this dataset(for example
    378         *            the topdatasets dgm-name)
    379         * @return Returns the ElevationModel object or <code>null</code> if none defined (optional)
    380         * @throws XMLParsingException
    381         */
    382        private ElevationModel parseElevationModel( Element datasetElement, ElevationModel defaultElevationModel )
    383                                                                                                                  throws XMLParsingException {
    384            // ATTENTION ogc elevation model is mandatory, we IGNORE it for the capabilities.
    385            String name = XMLTools.getNodeAsString( datasetElement, PRE_WPVS + "ElevationModel/text()", nsContext, null );
    386            if ( name == null ) {
    387                if ( defaultElevationModel == null ) {
    388                    return null;
    389                }
    390                return defaultElevationModel;
    391            }
    392            ElevationModel elevationModel = new ElevationModel( name );
    393
    394            return elevationModel;
    395        }
    396
    397        /**
    398         * Creates and returns a new array of <code>Style</code> objects from the given <code>Element</code>.
    399         *
    400         * @param datasetElement
    401         * @return Returns a new array of Style objects or <code>null</code> if none were defined
    402         * @throws XMLParsingException
    403         * @throws InvalidCapabilitiesException
    404         */
    405        protected Style[] parseStyles( Element datasetElement )
    406                                                               throws XMLParsingException, InvalidCapabilitiesException {
    407
    408            List<Node> styleList = XMLTools.getNodes( datasetElement, PRE_WPVS + "Style", nsContext );
    409            // optional therefore return null if not present
    410            if ( styleList.size() == 0 ) {
    411                return null;
    412            }
    413
    414            Style[] styles = new Style[styleList.size()];
    415
    416            for ( int i = 0; i < styles.length; i++ ) {
    417
    418                Element styleElement = (Element) styleList.get( i );
    419
    420                String name = XMLTools.getRequiredNodeAsString( styleElement, PRE_WPVS + "Name/text()", nsContext );
    421                String title = XMLTools.getRequiredNodeAsString( styleElement, PRE_WPVS + "Title/text()", nsContext );
    422                String abstract_ = XMLTools.getRequiredNodeAsString( styleElement, PRE_WPVS + "Abstract/text()", nsContext );
    423                // optional
    424                Keywords[] keywords = getKeywords( XMLTools.getNodes( styleElement, PRE_OWS + "Keywords", nsContext ) );
    425                // mandatory
    426                Identifier identifier = parseStyleIdentifier( styleElement, PRE_WPVS + "Identifier" );
    427
    428                // optional
    429                LegendURL[] legendURLs = parseLegendURLs( styleElement );
    430
    431                // optional
    432                StyleSheetURL styleSheetURL = parseStyleSheetURL( styleElement );
    433                StyleURL styleURL = parseStyleURL( styleElement );
    434
    435                styles[i] = new Style( name, title, abstract_, keywords, identifier, legendURLs, styleSheetURL, styleURL );
    436            }
    437
    438            return styles;
    439        }
    440
    441        /**
    442         * Creates and returns a new <code>StyleURL</code> object from the given <code>Element</code>.
    443         *
    444         * @param styleElement
    445         * @return Returns a new StyleURL object or <code>null</code> if not defined (optional)
    446         * @throws XMLParsingException
    447         * @throws InvalidCapabilitiesException
    448         */
    449        private StyleURL parseStyleURL( Element styleElement )
    450                                                              throws XMLParsingException, InvalidCapabilitiesException {
    451
    452            Element styleURLElement = (Element) XMLTools.getNode( styleElement, PRE_WPVS + "StyleURL", nsContext );
    453            if ( styleURLElement == null ) {
    454                return null;
    455            }
    456            String format = XMLTools.getRequiredNodeAsString( styleURLElement, PRE_WPVS + "Format/text()", nsContext );
    457
    458            // optional
    459            URI onlineResourceURI = XMLTools.getNodeAsURI( styleURLElement,
    460                                                           PRE_WPVS + "OnlineResource/@xlink:href",
    461                                                           nsContext,
    462                                                           null );
    463            URL onlineResource = null;
    464            if ( onlineResourceURI != null ) {
    465                try {
    466                    onlineResource = onlineResourceURI.toURL();
    467                } catch ( MalformedURLException e ) {
    468                    throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
    469                                                            + e.getMessage() );
    470                }
    471            }
    472            return new StyleURL( format, onlineResource );
    473        }
    474
    475        /**
    476         * Creates and returns a new <code>StyleSheetURL</code> object from the given <code>Element</code>.
    477         *
    478         * @param styleElement
    479         * @return Returns a new StyleSheetURL object or <code>null</code> if no stylSheetURL was given (optional)
    480         * @throws XMLParsingException
    481         * @throws InvalidCapabilitiesException
    482         */
    483        private StyleSheetURL parseStyleSheetURL( Element styleElement )
    484                                                                        throws XMLParsingException,
    485                                                                        InvalidCapabilitiesException {
    486
    487            Element styleSheetURLElement = (Element) XMLTools.getNode( styleElement, PRE_WPVS + "StyleSheetURL", nsContext );
    488            if ( styleSheetURLElement == null ) {
    489                return null;
    490            }
    491            String format = XMLTools.getRequiredNodeAsString( styleSheetURLElement, PRE_WPVS + "Format/text()", nsContext );
    492
    493            // optional onlineResource
    494            URI onlineResourceURI = XMLTools.getNodeAsURI( styleSheetURLElement,
    495                                                           PRE_WPVS + "OnlineResource/@xlink:href",
    496                                                           nsContext,
    497                                                           null );
    498            URL onlineResource = null;
    499            if ( onlineResourceURI != null ) {
    500                try {
    501                    onlineResource = onlineResourceURI.toURL();
    502                } catch ( MalformedURLException e ) {
    503                    throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
    504                                                            + e.getMessage() );
    505                }
    506            }
    507
    508            return new StyleSheetURL( format, onlineResource );
    509        }
    510
    511        /**
    512         * Creates and returns a new array of <code>LegendURL</code> objects from the given <code>Element</code>.
    513         *
    514         * @param styleElement
    515         * @return Returns a new array of LegendURL objects or <code>null</code> if none were defined (optional).
    516         * @throws XMLParsingException
    517         * @throws InvalidCapabilitiesException
    518         */
    519        private LegendURL[] parseLegendURLs( Element styleElement )
    520                                                                   throws XMLParsingException, InvalidCapabilitiesException {
    521
    522            List<Node> legendList = XMLTools.getNodes( styleElement, PRE_WPVS + "LegendURL", nsContext );
    523            if ( legendList.size() == 0 ) {
    524                return null;
    525            }
    526
    527            LegendURL[] legendURLs = new LegendURL[legendList.size()];
    528
    529            for ( int i = 0; i < legendURLs.length; i++ ) {
    530
    531                Element legendURLElement = (Element) legendList.get( i );
    532
    533                int width = XMLTools.getRequiredNodeAsInt( legendURLElement, "@width", nsContext );
    534                int height = XMLTools.getRequiredNodeAsInt( legendURLElement, "@height", nsContext );
    535                if ( width < 0 || height < 0 ) {
    536                    throw new InvalidCapabilitiesException( "The attributes width and height of '" + legendURLElement.getNodeName()
    537                                                            + "' must be positive!" );
    538                }
    539
    540                String format = XMLTools.getRequiredNodeAsString( legendURLElement, PRE_WPVS + "Format/text()", nsContext );
    541                // optional
    542                URI onlineResourceURI = XMLTools.getNodeAsURI( legendURLElement,
    543                                                               PRE_WPVS + "OnlineResource/@xlink:href",
    544                                                               nsContext,
    545                                                               null );
    546
    547                URL onlineResource = null;
    548                if ( onlineResourceURI != null ) {
    549                    try {
    550                        onlineResource = onlineResourceURI.toURL();
    551                    } catch ( MalformedURLException e ) {
    552                        throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
    553                                                                + e.getMessage() );
    554                    }
    555                }
    556
    557                legendURLs[i] = new LegendURL( width, height, format, onlineResource );
    558            }
    559            return legendURLs;
    560        }
    561
    562        /**
    563         * Creates and returns a new array of <code>FeatureListReference</code> objects from the given
    564         * <code>Element</code>.
    565         *
    566         * @param datasetElement
    567         * @return Returns an array of FeatureListReference instances or <code>null</code> if none were defined
    568         *         (optional).
    569         * @throws XMLParsingException
    570         * @throws InvalidCapabilitiesException
    571         */
    572        protected FeatureListReference[] parseFeatureListReferences( Element datasetElement )
    573                                                                                             throws XMLParsingException,
    574                                                                                             InvalidCapabilitiesException {
    575
    576            List<Node> featureList = XMLTools.getNodes( datasetElement, PRE_WPVS + "FeatureListReference", nsContext );
    577            if ( featureList.size() == 0 ) {
    578                return null;
    579            }
    580            FeatureListReference[] featureRefs = new FeatureListReference[featureList.size()];
    581            for ( int i = 0; i < featureRefs.length; i++ ) {
    582
    583                Element featureRefElement = (Element) featureList.get( i );
    584
    585                String format = XMLTools.getRequiredNodeAsString( featureRefElement, PRE_WPVS + "Format/text()", nsContext );
    586
    587                URI onlineResourceURI = XMLTools.getNodeAsURI( featureRefElement,
    588                                                               PRE_WPVS + "OnlineResource/@xlink:href",
    589                                                               nsContext,
    590                                                               null );
    591                URL onlineResource = null;
    592                if ( onlineResourceURI != null ) {
    593                    try {
    594                        onlineResource = onlineResourceURI.toURL();
    595                    } catch ( MalformedURLException e ) {
    596                        throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
    597                                                                + e.getMessage() );
    598                    }
    599                }
    600                featureRefs[i] = new FeatureListReference( format, onlineResource );
    601            }
    602            return featureRefs;
    603        }
    604
    605        /**
    606         * Creates and returns a new array of <code>DatasetReference</code> objects from the given <code>Element</code>.
    607         *
    608         * @param datasetElement
    609         * @return Returns a new array of DatasetReference objects or <code>null</code> if no DatasetReferences are
    610         *         specified in this dataset (optional)
    611         * @throws XMLParsingException
    612         * @throws InvalidCapabilitiesException
    613         */
    614        protected DatasetReference[] parseDatasetReferences( Element datasetElement )
    615                                                                                     throws XMLParsingException,
    616                                                                                     InvalidCapabilitiesException {
    617
    618            List<Node> datasetRefList = XMLTools.getNodes( datasetElement, PRE_WPVS + "DatasetReference", nsContext );
    619            if ( datasetRefList == null ) {
    620                return null;
    621            }
    622            DatasetReference[] datasetRefs = new DatasetReference[datasetRefList.size()];
    623
    624            for ( int i = 0; i < datasetRefs.length; i++ ) {
    625
    626                Element datasetRefElement = (Element) datasetRefList.get( i );
    627
    628                String format = XMLTools.getRequiredNodeAsString( datasetRefElement, PRE_WPVS + "Format/text()", nsContext );
    629
    630                URI onlineResourceURI = XMLTools.getNodeAsURI( datasetRefElement,
    631                                                               PRE_WPVS + "OnlineResource/@xlink:href",
    632                                                               nsContext,
    633                                                               null );
    634                URL onlineResource = null;
    635                if ( onlineResourceURI != null ) {
    636                    try {
    637                        onlineResource = onlineResourceURI.toURL();
    638                    } catch ( MalformedURLException e ) {
    639                        throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
    640                                                                + e.getMessage() );
    641                    }
    642                }
    643                datasetRefs[i] = new DatasetReference( format, onlineResource );
    644            }
    645
    646            return datasetRefs;
    647        }
    648
    649        /**
    650         * Creates and returns a new <code>MetaData</code> object from the given <code>Element</code>.
    651         *
    652         * @param datasetElement
    653         * @return Returns an array of MetaData objects, or <code>null</code> if no metadata was specified in the dataset
    654         *         (optional).
    655         * @throws XMLParsingException
    656         * @throws InvalidCapabilitiesException
    657         */
    658        protected MetaData[] parseMetaData( Element datasetElement )
    659                                                                    throws XMLParsingException,
    660                                                                    InvalidCapabilitiesException {
    661
    662            List<Node> metaDataList = XMLTools.getNodes( datasetElement, PRE_WPVS + "MetaData", nsContext );
    663            if ( metaDataList.size() == 0 ) {
    664                return null;
    665            }
    666            MetaData[] metaData = new MetaData[metaDataList.size()];
    667
    668            for ( int i = 0; i < metaData.length; i++ ) {
    669
    670                Element metaDataElement = (Element) metaDataList.get( i );
    671
    672                String type = XMLTools.getRequiredNodeAsString( metaDataElement, "@type", nsContext );
    673
    674                String format = XMLTools.getRequiredNodeAsString( metaDataElement, PRE_WPVS + "Format/text()", nsContext );
    675                URI onlineResourceURI = XMLTools.getNodeAsURI( metaDataElement,
    676                                                               PRE_WPVS + "OnlineResource/@xlink:href",
    677                                                               nsContext,
    678                                                               null );
    679                URL onlineResource = null;
    680                if ( onlineResourceURI != null ) {
    681                    try {
    682                        onlineResource = onlineResourceURI.toURL();
    683                    } catch ( MalformedURLException e ) {
    684                        throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
    685                                                                + e.getMessage() );
    686                    }
    687                }
    688
    689                metaData[i] = new MetaData( type, format, onlineResource );
    690            }
    691
    692            return metaData;
    693        }
    694
    695        /**
    696         * Creates and returns a new <code>Identifier</code> object from the given <code>Element</code> and the given
    697         * <cod>xPathQuery</code>.
    698         *
    699         * @param element
    700         * @param xPathQuery
    701         * @return Returns a new Identifier object.
    702         * @throws XMLParsingException
    703         * @throws InvalidCapabilitiesException
    704         *             if no (valid) identifier is found
    705         */
    706        protected Identifier parseStyleIdentifier( Element element, String xPathQuery )
    707                                                                                       throws XMLParsingException,
    708                                                                                       InvalidCapabilitiesException {
    709
    710            Element identifierElement = (Element) XMLTools.getRequiredNode( element, xPathQuery, nsContext );
    711
    712            String value = XMLTools.getStringValue( identifierElement ).trim();
    713            if ( "".equals( value ) ) {
    714                throw new InvalidCapabilitiesException( Messages.getMessage( "WPVS_NO_VALID_IDENTIFIER", "style" ) );
    715            }
    716            URI codeSpace = XMLTools.getNodeAsURI( identifierElement, "@codeSpace", nsContext, null );
    717
    718            Identifier id = new Identifier( value, codeSpace );
    719            if ( styleIdentifiers.contains( id.toString() ) ) {
    720                throw new InvalidCapabilitiesException( Messages.getMessage( "WPVS_NO_UNIQUE_IDENTIFIER",
    721                                                                             "styles",
    722                                                                             id.toString() ) );
    723
    724            }
    725            styleIdentifiers.add( id.toString() );
    726            return id;
    727        }
    728
    729        /**
    730         * Creates and returns a new <code>Identifier</code> object from the given <code>Element</code> and the given
    731         * <cod>xPathQuery</code>.
    732         *
    733         * @param element
    734         * @param xPathQuery
    735         * @return Returns a new Identifier object.
    736         * @throws XMLParsingException
    737         * @throws InvalidCapabilitiesException
    738         *             if no (valid) identifier is found
    739         */
    740        protected Identifier parseDatasetIdentifier( Element element, String xPathQuery )
    741                                                                                         throws XMLParsingException,
    742                                                                                         InvalidCapabilitiesException {
    743
    744            Element identifierElement = (Element) XMLTools.getRequiredNode( element, xPathQuery, nsContext );
    745
    746            String value = XMLTools.getStringValue( identifierElement ).trim();
    747            if ( "".equals( value ) ) {
    748                throw new InvalidCapabilitiesException( Messages.getMessage( "WPVS_NO_VALID_IDENTIFIER", "dataset" ) );
    749            }
    750            URI codeSpace = XMLTools.getNodeAsURI( identifierElement, "@codeSpace", nsContext, null );
    751            Identifier id = new Identifier( value, codeSpace );
    752            if ( datasetIdentifiers.contains( id.toString() ) ) {
    753                throw new InvalidCapabilitiesException( Messages.getMessage( "WPVS_NO_UNIQUE_IDENTIFIER",
    754                                                                             "datasets",
    755                                                                             id.toString() ) );
    756
    757            }
    758            datasetIdentifiers.add( id.toString() );
    759
    760            return id;
    761        }
    762
    763        /**
    764         * Creates and returns a new <code>DataProvider</code> object from the given <code>Element</code>.
    765         *
    766         * @param datasetElement
    767         * @return Returns a new DataProvider object or <code>null</code>if no provider was defined.
    768         * @throws XMLParsingException
    769         * @throws InvalidCapabilitiesException
    770         */
    771        protected DataProvider parseDataProvider( Element datasetElement )
    772                                                                          throws XMLParsingException,
    773                                                                          InvalidCapabilitiesException {
    774
    775            String providerName = null;
    776            URL providerSite = null;
    777            LogoURL logoURL = null;
    778
    779            Element dataProviderElement = (Element) XMLTools.getNode( datasetElement, PRE_WPVS + "DataProvider", nsContext );
    780            if ( dataProviderElement == null )
    781                return null;
    782
    783            providerName = XMLTools.getNodeAsString( dataProviderElement, PRE_WPVS + "ProviderName/text()", nsContext, null );
    784            URI providerSiteURI = XMLTools.getNodeAsURI( dataProviderElement,
    785                                                         PRE_WPVS + "ProviderSite/@xlink:href",
    786                                                         nsContext,
    787                                                         null );
    788            if ( providerSiteURI != null ) {
    789                try {
    790                    providerSite = providerSiteURI.toURL();
    791                } catch ( MalformedURLException e ) {
    792                    throw new InvalidCapabilitiesException( providerSiteURI + " does not represent a valid URL: "
    793                                                            + e.getMessage() );
    794                }
    795            }
    796
    797            Node logoURLElement = XMLTools.getNode( dataProviderElement, PRE_WPVS + "LogoURL", nsContext );
    798            if ( logoURLElement != null ) {
    799
    800                int width = XMLTools.getRequiredNodeAsInt( logoURLElement, "@width", nsContext );
    801                int height = XMLTools.getRequiredNodeAsInt( logoURLElement, "@height", nsContext );
    802                if ( width < 0 || height < 0 ) {
    803                    throw new InvalidCapabilitiesException( "width and height of '" + logoURLElement
    804                                                            + "' must be positive!" );
    805                }
    806
    807                String format = XMLTools.getRequiredNodeAsString( logoURLElement, PRE_WPVS + "Format/text()", nsContext );
    808
    809                URI onlineResourceURI = XMLTools.getNodeAsURI( logoURLElement,
    810                                                               PRE_WPVS + "OnlineResource/@xlink:href",
    811                                                               nsContext,
    812                                                               null );
    813                URL onlineResource = null;
    814                if ( onlineResourceURI != null ) {
    815                    try {
    816                        onlineResource = onlineResourceURI.toURL();
    817                    } catch ( MalformedURLException e ) {
    818                        throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
    819                                                                + e.getMessage() );
    820                    }
    821                }
    822
    823                logoURL = new LogoURL( width, height, format, onlineResource );
    824            }
    825            return new DataProvider( providerName, providerSite, logoURL );
    826        }
    827
    828        /**
    829         *
    830         * @param element
    831         * @return the Dimensions of a given element or <code>null</code> if no dimension is found (optional).
    832         * @throws XMLParsingException
    833         */
    834        protected Dimension[] parseDimensions( Element element )
    835                                                                throws XMLParsingException {
    836
    837            List<Node> nl = XMLTools.getNodes( element, PRE_WPVS + "Dimension", nsContext );
    838            if ( nl.size() == 0 ) {
    839                return null;
    840            }
    841            Dimension[] dimensions = new Dimension[nl.size()];
    842
    843            for ( int i = 0; i < dimensions.length; i++ ) {
    844                Node dimNode = nl.get( i );
    845                String name = XMLTools.getRequiredNodeAsString( dimNode, "@name", nsContext );
    846                String units = XMLTools.getRequiredNodeAsString( dimNode, "@units", nsContext );
    847                String unitSymbol = XMLTools.getNodeAsString( dimNode, "@unitSymbol", nsContext, null );
    848                String default_ = XMLTools.getNodeAsString( dimNode, "@default", nsContext, null );
    849                Boolean multipleValues = Boolean.valueOf( XMLTools.getNodeAsBoolean( dimNode,
    850                                                                                     "@multipleValues",
    851                                                                                     nsContext,
    852                                                                                     true ) );
    853                Boolean nearestValues = Boolean.valueOf( XMLTools.getNodeAsBoolean( dimNode,
    854                                                                                    "@nearestValues",
    855                                                                                    nsContext,
    856                                                                                    true ) );
    857                Boolean current = Boolean.valueOf( XMLTools.getNodeAsBoolean( dimNode,
    858                                                                              "@current",
    859                                                                              nsContext,
    860                                                                              true ) );
    861                String value = XMLTools.getNodeAsString( dimNode, ".", nsContext, null );
    862
    863                dimensions[i] = new Dimension( name,
    864                                               units,
    865                                               unitSymbol,
    866                                               default_,
    867                                               multipleValues,
    868                                               nearestValues,
    869                                               current,
    870                                               value );
    871            }
    872
    873            return dimensions;
    874        }
    875
    876        /**
    877         * Gets an array of <code>boundingBoxes</code> from the given <code>Element</code>. This method returns all
    878         * boundingBoxes together in one array.
    879         *
    880         * @param element
    881         * @param defaultCoordinateSystem
    882         *            to be used for not defined coordinate system attribute in the bbox element
    883         * @return Returns an array of boundingBoxes.
    884         * @throws XMLParsingException
    885         * @throws InvalidParameterValueException
    886         */
    887        protected Envelope[] getBoundingBoxes( Element element, CoordinateSystem defaultCoordinateSystem )
    888                                                                                                          throws XMLParsingException,
    889                                                                                                          InvalidParameterValueException {
    890
    891            List<Node> boundingBoxList = XMLTools.getNodes( element, PRE_OWS + "BoundingBox", nsContext );
    892
    893            List<Envelope> bboxesList = new ArrayList<Envelope>( boundingBoxList.size() );
    894
    895            for ( int i = 0; i < boundingBoxList.size(); i++ ) {
    896                bboxesList.add( parseBoundingBox( (Element) boundingBoxList.get( i ), defaultCoordinateSystem ) );
    897            }
    898
    899            // The ogc_wpvs schema says: wgs84 is mandatory therefore-> not checking parents to use it's
    900            // bboxes.
    901
    902            // if ( parent != null ) {
    903            // Envelope[] boundingBoxes = parent.getBoundingBoxes();
    904            // for ( int i = 0; i < boundingBoxes.length; i++ ) {
    905            // bboxesList.add( boundingBoxes[i] );
    906            // }
    907            // }
    908
    909            Envelope[] boxes = bboxesList.toArray( new Envelope[bboxesList.size()] );
    910            return boxes;
    911        }
    912
    913        /**
    914         * Usable with any BoundingBox. Changed crs from null to given attribute value of crs. Added check for min values to
    915         * be smaler than max values.
    916         *
    917         * Creates an <code>Envelope</code> object from the given element of type <code>ows:WGS84BoundingBox</code> or
    918         * <code>ows:BoundingBox</code>.
    919         *
    920         * @param element
    921         * @param defaultCoordinateSystem
    922         *            if the crs-attribute of the bbox element is not defined
    923         * @return a boundingbox of a dataset
    924         * @throws XMLParsingException
    925         * @throws InvalidParameterValueException
    926         */
    927        protected Envelope parseBoundingBox( Element element, CoordinateSystem defaultCoordinateSystem )
    928                                                                                                        throws XMLParsingException,
    929                                                                                                        InvalidParameterValueException {
    930
    931            // Envelope env = getWGS84BoundingBoxType( element );
    932
    933            String crsAtt = element.getAttribute( "crs" );
    934            CoordinateSystem crs = null;
    935            if ( crsAtt == null ) {
    936                crs = defaultCoordinateSystem;
    937            } else {
    938                try {
    939                    crs = CRSFactory.create( crsAtt );
    940                } catch ( UnknownCRSException e ) {
    941                    throw new InvalidParameterValueException( e.getMessage() );
    942                }
    943            }
    944
    945            double[] lowerCorner = XMLTools.getRequiredNodeAsDoubles( element,
    946                                                                      PRE_OWS + "LowerCorner/text()",
    947                                                                      nsContext,
    948                                                                      " " );
    949            if ( lowerCorner.length < 2 ) {
    950                throw new XMLParsingException( Messages.getMessage( "WPVS_NO_VALID_BBOX_POINT", PRE_OWS + "LowerCorner" ) );
    951            }
    952            double[] upperCorner = XMLTools.getRequiredNodeAsDoubles( element,
    953                                                                      PRE_OWS + "UpperCorner/text()",
    954                                                                      nsContext,
    955                                                                      " " );
    956            if ( upperCorner.length < 2 ) {
    957                throw new XMLParsingException( Messages.getMessage( "WPVS_NO_VALID_BBOX_POINT", PRE_OWS + "UpperCorner" ) );
    958            }
    959            if ( upperCorner.length != lowerCorner.length ) {
    960                throw new XMLParsingException( Messages.getMessage( "WPVS_DIFFERENT_BBOX_DIMENSIONS",
    961                                                                    PRE_OWS + "LowerCorner",
    962                                                                    PRE_OWS + "UpperCorner" ) );
    963            }
    964
    965            for ( int i = 0; i < upperCorner.length; ++i ) {
    966                if ( lowerCorner[i] >= upperCorner[i] ) {
    967                    throw new InvalidParameterValueException( Messages.getMessage( "WPVS_WRONG_BBOX_POINT_POSITIONS",
    968                                                                                   new Integer( i ),
    969                                                                                   new Double( lowerCorner[i] ),
    970                                                                                   PRE_OWS + "LowerCorner",
    971                                                                                   new Double( upperCorner[i] ),
    972                                                                                   PRE_OWS + "UpperCorner" ) );
    973
    974                }
    975            }
    976
    977            return GeometryFactory.createEnvelope( lowerCorner[0], lowerCorner[1], upperCorner[0], upperCorner[1], crs );
    978
    979        }
    980
    981        /**
    982         * Creates and returns a new <code>OperationsMetadata</code> object.
    983         *
    984         * @param defaultOnlineResource
    985         *            to fill in the left out dcp's or <code>null</code> if no default URL was given.
    986         *
    987         * @return Returns a new OperationsMetadata object.
    988         * @throws XMLParsingException
    989         * @throws InvalidCapabilitiesException
    990         */
    991        protected OperationsMetadata parseOperationsMetadata( OnlineResource defaultOnlineResource )
    992                                                                                                    throws XMLParsingException,
    993                                                                                                    InvalidCapabilitiesException {
    994
    995            Node operationMetadata = XMLTools.getRequiredNode( getRootElement(), PRE_OWS + "OperationsMetadata", nsContext );
    996            List<Node> operationElementList = XMLTools.getNodes( operationMetadata, PRE_OWS + "Operation", nsContext );
    997
    998            Map<String, Element> operations = new HashMap<String, Element>();
    999            for ( int i = 0; i < operationElementList.size(); i++ ) {
    1000                operations.put( XMLTools.getRequiredNodeAsString( operationElementList.get( i ), "@name", nsContext ),
    1001                                (Element) operationElementList.get( i ) );
    1002            }
    1003
    1004            Operation110 getCapabilities = getOperation110( OperationsMetadata.GET_CAPABILITIES_NAME,
    1005                                                            true,
    1006                                                            operations,
    1007                                                            defaultOnlineResource );
    1008            Operation110 getView = getOperation110( WPVSOperationsMetadata.GET_VIEW_NAME,
    1009                                                    true,
    1010                                                    operations,
    1011                                                    defaultOnlineResource );
    1012            Operation110 getDescription = getOperation110( WPVSOperationsMetadata.GET_DESCRIPTION_NAME,
    1013                                                           false,
    1014                                                           operations,
    1015                                                           defaultOnlineResource );
    1016
    1017            Operation110 get3DFeatureInfo = getOperation110( WPVSOperationsMetadata.GET_3D_FEATURE_INFO,
    1018                                                             false,
    1019                                                             operations,
    1020                                                             defaultOnlineResource );
    1021
    1022            Operation110 getLegendGraphics = getOperation110( WPVSOperationsMetadata.GET_LEGEND_GRAPHIC_NAME,
    1023                                                              false,
    1024                                                              operations,
    1025                                                              defaultOnlineResource );
    1026
    1027            List<Node> parameterElementList = XMLTools.getNodes( operationMetadata, PRE_OWS + "Parameter", nsContext );
    1028            OWSDomainType110[] parameters = new OWSDomainType110[parameterElementList.size()];
    1029            for ( int i = 0; i < parameters.length; i++ ) {
    1030                parameters[i] = getOWSDomainType110( (Element) parameterElementList.get( i ) );
    1031            }
    1032
    1033            List<Node> constraintElementList = XMLTools.getNodes( operationMetadata, PRE_OWS + "Constraint", nsContext );
    1034            OWSDomainType110[] constraints = new OWSDomainType110[constraintElementList.size()];
    1035            for ( int i = 0; i < constraints.length; i++ ) {
    1036                constraints[i] = getOWSDomainType110( (Element) constraintElementList.get( i ) );
    1037            }
    1038
    1039            List<Node> extendedCapsList = XMLTools.getNodes( operationMetadata, PRE_OWS + "ExtendedCapabilities", nsContext );
    1040            Object[] extendedCapabilities = new Object[extendedCapsList.size()];
    1041            for ( int i = 0; i < extendedCapabilities.length; i++ ) {
    1042                extendedCapabilities[i] = extendedCapsList.get( i );
    1043            }
    1044
    1045            WPVSOperationsMetadata metadata = new WPVSOperationsMetadata( getCapabilities,
    1046                                                                          getView,
    1047                                                                          getDescription,
    1048                                                                          getLegendGraphics,
    1049                                                                          parameters,
    1050                                                                          constraints,
    1051                                                                          extendedCapabilities,
    1052                                                                          get3DFeatureInfo );
    1053
    1054            return metadata;
    1055        }
    1056
    1057        /**
    1058         * FIXME needs to be handled, when OWSDomainType110 ceases to exist.
    1059         *
    1060         * @see org.deegree.owscommon.OWSCommonCapabilitiesDocument#getOperation(String, boolean, Map)
    1061         *
    1062         * @param name
    1063         * @param isMandatory
    1064         * @param operations
    1065         * @return the Operation110 with the given name from the map
    1066         * @throws XMLParsingException
    1067         * @throws InvalidCapabilitiesException
    1068         */
    1069        private Operation110 getOperation110( String name, boolean isMandatory, Map<String, Element> operations,
    1070                                              OnlineResource defaultOnlineResource )
    1071                                                                                    throws XMLParsingException,
    1072                                                                                    InvalidCapabilitiesException {
    1073
    1074            Operation110 operation = null;
    1075            Element operationElement = operations.get( name );
    1076            if ( operationElement == null ) {
    1077                if ( isMandatory ) {
    1078                    throw new XMLParsingException( "Mandatory operation '" + name
    1079                                                   + "' not defined in "
    1080                                                   + "'OperationsMetadata'-section." );
    1081                }
    1082            } else {
    1083                // 'ows:DCP' - elements
    1084                DCPType[] dcps = getDCPs( XMLTools.getRequiredElements( operationElement, PRE_OWS + "DCP", nsContext ) );
    1085                //fill in the default online resource if one is missing.
    1086                if ( defaultOnlineResource != null ) {
    1087                    for ( DCPType dcp : dcps ) {
    1088                        Protocol pr = dcp.getProtocol();
    1089                        if ( pr != null ) {
    1090                            if ( pr instanceof HTTP ) {
    1091                                if ( ( (HTTP) pr ).getGetOnlineResources() == null || ( (HTTP) pr ).getGetOnlineResources().length == 0 ) {
    1092                                    ( (HTTP) pr ).setGetOnlineResources( new URL[] { defaultOnlineResource.getLinkage()
    1093                                                                                                          .getHref() } );
    1094                                }
    1095                                if ( ( (HTTP) pr ).getPostOnlineResources() == null || ( (HTTP) pr ).getPostOnlineResources().length == 0 ) {
    1096                                    ( (HTTP) pr ).setPostOnlineResources( new URL[] { defaultOnlineResource.getLinkage()
    1097                                                                                                           .getHref() } );
    1098                                }
    1099                            }
    1100                        }
    1101                    }
    1102                }
    1103
    1104                // 'Parameter' - elements
    1105                List<Node> parameterList = XMLTools.getNodes( operationElement, PRE_OWS + "Parameter", nsContext );
    1106                OWSDomainType110[] parameters = new OWSDomainType110[parameterList.size()];
    1107                for ( int i = 0; i < parameters.length; i++ ) {
    1108                    parameters[i] = getOWSDomainType110( (Element) parameterList.get( i ) );
    1109                }
    1110                // 'Constraint' - elements
    1111                List<Node> constraintList = XMLTools.getNodes( operationElement, PRE_OWS + "Constraint", nsContext );
    1112                OWSDomainType110[] constraints = new OWSDomainType110[constraintList.size()];
    1113                for ( int i = 0; i < constraintList.size(); i++ ) {
    1114                    constraints[i] = getOWSDomainType110( (Element) constraintList.get( i ) );
    1115                }
    1116                // 'ows:Metadata' - element
    1117                List<Node> metadataList = XMLTools.getNodes( operationElement, PRE_OWS + "Metadata", nsContext );
    1118                OWSMetadata[] metadata = new OWSMetadata[metadataList.size()];
    1119                for ( int i = 0; i < metadata.length; i++ ) {
    1120                    metadata[i] = getOWSMetadata( operationElement, PRE_OWS + "Metadata", nsContext );
    1121                }
    1122
    1123                // return new Operation110 object
    1124                operation = new Operation110( name, dcps, parameters, constraints, metadata );
    1125            }
    1126
    1127            return operation;
    1128        }
    1129
    1130        /**
    1131         * FIXME there is a similar method in org.deegree.owscommon.OWSCommonCapabilitiesDocument#getDCP. overrides that
    1132         * method!
    1133         *
    1134         * Creates a <code>DCPType</code> object from the passed <code>DCP</code> element.
    1135         *
    1136         * @param element
    1137         * @return created <code>DCPType</code>
    1138         * @throws XMLParsingException
    1139         * @see org.deegree.ogcwebservices.getcapabilities.OGCStandardCapabilities
    1140         */
    1141        @Override
    1142        protected DCPType getDCP( Element element )
    1143                                                   throws XMLParsingException {
    1144            DCPType dcpType = null;
    1145            Element httpElement = (Element) XMLTools.getRequiredNode( element, PRE_OWS + "HTTP", nsContext );
    1146
    1147            try {
    1148                List<Node> requestList = XMLTools.getNodes( httpElement, PRE_OWS + "Get", nsContext );
    1149                OWSRequestMethod[] getRequests = new OWSRequestMethod[requestList.size()];
    1150                for ( int i = 0; i < getRequests.length; i++ ) {
    1151
    1152                    List<Node> constraintList = XMLTools.getNodes( requestList.get( i ), PRE_OWS + "Constraint", nsContext );
    1153                    OWSDomainType110[] constraint = new OWSDomainType110[constraintList.size()];
    1154                    for ( int j = 0; j < constraint.length; j++ ) {
    1155                        constraint[j] = getOWSDomainType110( (Element) constraintList.get( i ) );
    1156                    }
    1157
    1158                    SimpleLink link = parseSimpleLink( (Element) requestList.get( i ) );
    1159
    1160                    getRequests[i] = new OWSRequestMethod( link, constraint );
    1161                }
    1162
    1163                requestList = XMLTools.getNodes( httpElement, PRE_OWS + "Post", nsContext );
    1164                OWSRequestMethod[] postRequests = new OWSRequestMethod[requestList.size()];
    1165                for ( int i = 0; i < postRequests.length; i++ ) {
    1166
    1167                    List<Node> constraintList = XMLTools.getNodes( requestList.get( i ), PRE_OWS + "Constraint", nsContext );
    1168                    OWSDomainType110[] constraint = new OWSDomainType110[constraintList.size()];
    1169                    for ( int j = 0; j < constraint.length; j++ ) {
    1170                        constraint[j] = getOWSDomainType110( (Element) constraintList.get( i ) );
    1171                    }
    1172
    1173                    SimpleLink link = parseSimpleLink( (Element) requestList.get( i ) );
    1174
    1175                    postRequests[i] = new OWSRequestMethod( link, constraint );
    1176                }
    1177
    1178                Protocol protocol = new HTTP110( getRequests, postRequests );
    1179                dcpType = new DCPType( protocol );
    1180
    1181            } catch ( InvalidCapabilitiesException e ) {
    1182                throw new XMLParsingException( "Couldn't parse the OWSDomainType110 within DCPType: " + StringTools.stackTraceToString( e ) );
    1183            }
    1184
    1185            return dcpType;
    1186        }
    1187
    1188        /**
    1189         * FIXME needs to be handled, when OWSDomainType110 ceases to exist.
    1190         *
    1191         * @see org.deegree.owscommon.OWSCommonCapabilitiesDocument#getOWSDomainType(String, Element)
    1192         *
    1193         * @param element
    1194         * @return Returns owsDomainType110 object.
    1195         * @throws InvalidCapabilitiesException
    1196         */
    1197        private OWSDomainType110 getOWSDomainType110( Element element )
    1198                                                                       throws XMLParsingException,
    1199                                                                       InvalidCapabilitiesException {
    1200
    1201            // 'name' - attribute
    1202            String name = XMLTools.getRequiredNodeAsString( element, "@name", nsContext );
    1203
    1204            // 'ows:AllowedValues' - element
    1205            Element allowedElement = (Element) XMLTools.getNode( element, PRE_OWS + "AllowedValues", nsContext );
    1206            OWSAllowedValues allowedValues = null;
    1207            if ( allowedElement != null ) {
    1208
    1209                // 'ows:Value' - elements
    1210                String[] values = XMLTools.getNodesAsStrings( allowedElement, PRE_OWS + "Value/text()", nsContext );
    1211                TypedLiteral[] literals = null;
    1212                if ( values != null ) {
    1213                    literals = new TypedLiteral[values.length];
    1214                    for ( int i = 0; i < literals.length; i++ ) {
    1215                        literals[i] = new TypedLiteral( values[i], null );
    1216                    }
    1217                }
    1218
    1219                // 'ows:Range' - elements
    1220                List<Node> rangeList = XMLTools.getNodes( allowedElement, PRE_OWS + "Range", nsContext );
    1221                ValueRange[] ranges = new ValueRange[rangeList.size()];
    1222                for ( int i = 0; i < ranges.length; i++ ) {
    1223                    String minimum = XMLTools.getNodeAsString( rangeList.get( i ),
    1224                                                               PRE_OWS + "MinimumValue",
    1225                                                               nsContext,
    1226                                                               null );
    1227                    String maximum = XMLTools.getNodeAsString( rangeList.get( i ),
    1228                                                               PRE_OWS + "MaximumValue",
    1229                                                               nsContext,
    1230                                                               null );
    1231                    String spacing = XMLTools.getNodeAsString( rangeList.get( i ),
    1232                                                               PRE_OWS + "Spacing",
    1233                                                               nsContext,
    1234                                                               null );
    1235                    TypedLiteral min = new TypedLiteral( minimum, null );
    1236                    TypedLiteral max = new TypedLiteral( maximum, null );
    1237                    TypedLiteral space = new TypedLiteral( spacing, null );
    1238
    1239                    ranges[i] = new ValueRange( min, max, space );
    1240                }
    1241
    1242                if ( values.length < 1 && ranges.length < 1 ) {
    1243                    throw new XMLParsingException( "At least one 'ows:Value'-element or one 'ows:Range'-element must be defined " + "in each element of type 'ows:AllowedValues'." );
    1244                }
    1245
    1246                allowedValues = new OWSAllowedValues( literals, ranges );
    1247            }
    1248
    1249            // FIXME manage elements: ows:AnyValue, ows:NoValues.
    1250            boolean anyValue = false;
    1251            boolean noValues = false;
    1252
    1253            // 'ows:ValuesListReference' - element
    1254            OWSMetadata valuesListReference = getOWSMetadata( element, PRE_OWS + "ValuesListReference", nsContext );
    1255
    1256            // 'ows:DefaulValue' - element
    1257            String defaultValue = XMLTools.getNodeAsString( element, PRE_OWS + "DefaultValue/text()", nsContext, null );
    1258
    1259            // 'ows:Meaning' - element
    1260            OWSMetadata meaning = getOWSMetadata( element, PRE_OWS + "Meaning", nsContext );
    1261
    1262            // 'ows:DataType - element
    1263            OWSMetadata dataType = getOWSMetadata( element, PRE_OWS + "DataType", nsContext );
    1264
    1265            // choose up to one measurement element
    1266            String measurementType = null;
    1267            // 'ows:ReferenceSystem' - element
    1268            Element referenceElement = (Element) XMLTools.getNode( element, PRE_OWS + "ReferenceSystem", nsContext );
    1269            // 'ows:UOM' - element
    1270            Element uomElement = (Element) XMLTools.getNode( element, PRE_OWS + "UOM", nsContext );
    1271            OWSMetadata measurement = null;
    1272
    1273            if ( referenceElement != null && uomElement != null ) {
    1274                throw new InvalidCapabilitiesException( "Within an 'ows:DomainType'-Element only one " + "of the following elements is allowed: "
    1275                                                        + "'ows:ReferenceSystem' OR 'ows:UOM'." );
    1276            } else if ( referenceElement != null ) {
    1277                measurementType = OWSDomainType110.REFERENCE_SYSTEM;
    1278                measurement = getOWSMetadata( element, PRE_OWS + "ReferenceSystem", nsContext );
    1279            } else if ( uomElement != null ) {
    1280                measurementType = OWSDomainType110.UOM;
    1281                measurement = getOWSMetadata( element, PRE_OWS + "UOM", nsContext );
    1282            }
    1283
    1284            // 'ows:Metadata' - elements
    1285            List<Node> metaList = XMLTools.getNodes( element, PRE_OWS + "Metadata", nsContext );
    1286            OWSMetadata[] metadata = new OWSMetadata[metaList.size()];
    1287            for ( int i = 0; i < metadata.length; i++ ) {
    1288                metadata[i] = getOWSMetadata( (Element) metaList.get( i ), PRE_OWS + "Metadata", nsContext );
    1289            }
    1290
    1291            // return new OWSDomainType110
    1292            OWSDomainType110 domainType110 = null;
    1293            if ( allowedValues != null && !anyValue && !noValues && valuesListReference == null ) {
    1294                domainType110 = new OWSDomainType110( allowedValues,
    1295                                                      defaultValue,
    1296                                                      meaning,
    1297                                                      dataType,
    1298                                                      measurementType,
    1299                                                      measurement,
    1300                                                      metadata,
    1301                                                      name );
    1302            } else if ( ( anyValue || noValues ) && allowedValues == null && valuesListReference == null ) {
    1303                domainType110 = new OWSDomainType110( anyValue,
    1304                                                      noValues,
    1305                                                      defaultValue,
    1306                                                      meaning,
    1307                                                      dataType,
    1308                                                      measurementType,
    1309                                                      measurement,
    1310                                                      metadata,
    1311                                                      name );
    1312            } else if ( valuesListReference != null && allowedValues == null && !anyValue && !noValues ) {
    1313                domainType110 = new OWSDomainType110( valuesListReference,
    1314                                                      defaultValue,
    1315                                                      meaning,
    1316                                                      dataType,
    1317                                                      measurementType,
    1318                                                      measurement,
    1319                                                      metadata,
    1320                                                      name );
    1321            } else {
    1322                throw new InvalidCapabilitiesException( "Only one of the following elements may be " + "contained within an 'ows:DomainType': 'ows:AllowedValues', 'ows:AnyValue', "
    1323                                                        + "'ows:NoValues' or 'ows:ValuesListReference'." );
    1324            }
    1325
    1326            return domainType110;
    1327        }
    1328
    1329        /**
    1330         * FIXME check, wether the URIs go to the correct address within OWSMetadata. So far, no example was given to check
    1331         * this with.
    1332         *
    1333         * Creates and returns a new <code>OWSMetadata</code> object (or null) from the given <code>Element</code> at
    1334         * the given <code>XPath</code>.
    1335         *
    1336         * @param element
    1337         * @param xPath
    1338         * @param nsContext
    1339         * @return Returns a new OWSMetadata object (may be null).
    1340         * @throws XMLParsingException
    1341         */
    1342        private OWSMetadata getOWSMetadata( Element element, String xPath, NamespaceContext nsContext )
    1343                                                                                                       throws XMLParsingException {
    1344
    1345            Element child = (Element) XMLTools.getNode( element, xPath, nsContext );
    1346
    1347            if ( child == null ) {
    1348                return null;
    1349            }
    1350
    1351            // attrib about
    1352            URI about = XMLTools.getNodeAsURI( child, "@about", nsContext, null );
    1353
    1354            // attribs for SimpleLink
    1355            URI href = XMLTools.getNodeAsURI( child, "@xlink:href", nsContext, null );
    1356            URI role = XMLTools.getNodeAsURI( child, "@xlink:role", nsContext, null );
    1357            URI arcrole = XMLTools.getNodeAsURI( child, "@xlink:arcrole", nsContext, null );
    1358            String title = XMLTools.getNodeAsString( child, "@xlink:title", nsContext, null );
    1359            String show = XMLTools.getNodeAsString( child, "@xlink:show", nsContext, null );
    1360            String actuate = XMLTools.getNodeAsString( child, "@xlink:actuate", nsContext, null );
    1361
    1362            // ows:name (ows:AbstractMetaData)
    1363            String name = XMLTools.getNodeAsString( child, "text()", nsContext, null );
    1364
    1365            SimpleLink link = new SimpleLink( href, role, arcrole, title, show, actuate );
    1366
    1367            return new OWSMetadata( about, link, name );
    1368        }
    1369
    1370    }