001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }