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