001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wpvs/configuration/WPVSConfigurationDocument.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2006 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 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.configuration;
045
046 import java.awt.Color;
047 import java.net.MalformedURLException;
048 import java.net.URL;
049 import java.util.ArrayList;
050 import java.util.HashMap;
051 import java.util.Iterator;
052 import java.util.List;
053 import java.util.Map;
054
055 import org.deegree.datatypes.QualifiedName;
056 import org.deegree.framework.log.ILogger;
057 import org.deegree.framework.log.LoggerFactory;
058 import org.deegree.framework.util.IDGenerator;
059 import org.deegree.framework.util.KVP2Map;
060 import org.deegree.framework.util.StringTools;
061 import org.deegree.framework.xml.InvalidConfigurationException;
062 import org.deegree.framework.xml.XMLParsingException;
063 import org.deegree.framework.xml.XMLTools;
064 import org.deegree.i18n.Messages;
065 import org.deegree.model.crs.CoordinateSystem;
066 import org.deegree.model.filterencoding.AbstractFilter;
067 import org.deegree.model.filterencoding.Filter;
068 import org.deegree.model.metadata.iso19115.Keywords;
069 import org.deegree.model.metadata.iso19115.OnlineResource;
070 import org.deegree.model.spatialschema.Envelope;
071 import org.deegree.model.spatialschema.GMLGeometryAdapter;
072 import org.deegree.model.spatialschema.Geometry;
073 import org.deegree.model.spatialschema.GeometryException;
074 import org.deegree.model.spatialschema.GeometryFactory;
075 import org.deegree.model.spatialschema.Surface;
076 import org.deegree.ogcbase.CommonNamespaces;
077 import org.deegree.ogcbase.PropertyPath;
078 import org.deegree.ogcwebservices.InvalidParameterValueException;
079 import org.deegree.ogcwebservices.MissingParameterValueException;
080 import org.deegree.ogcwebservices.OGCWebServiceException;
081 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
082 import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
083 import org.deegree.ogcwebservices.wms.operation.GetMap;
084 import org.deegree.ogcwebservices.wpvs.capabilities.DataProvider;
085 import org.deegree.ogcwebservices.wpvs.capabilities.Dataset;
086 import org.deegree.ogcwebservices.wpvs.capabilities.DatasetReference;
087 import org.deegree.ogcwebservices.wpvs.capabilities.Dimension;
088 import org.deegree.ogcwebservices.wpvs.capabilities.ElevationModel;
089 import org.deegree.ogcwebservices.wpvs.capabilities.FeatureListReference;
090 import org.deegree.ogcwebservices.wpvs.capabilities.Identifier;
091 import org.deegree.ogcwebservices.wpvs.capabilities.MetaData;
092 import org.deegree.ogcwebservices.wpvs.capabilities.OWSCapabilities;
093 import org.deegree.ogcwebservices.wpvs.capabilities.Style;
094 import org.deegree.ogcwebservices.wpvs.capabilities.WPVSCapabilitiesDocument;
095 import org.w3c.dom.Element;
096 import org.w3c.dom.Node;
097 import org.w3c.dom.Text;
098
099 /**
100 * Parser for WPVS configuration documents.
101 *
102 * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
103 * @author last edited by: $Author: rbezema $
104 *
105 * @version $Revision: 7952 $, $Date: 2007-08-09 11:57:34 +0200 (Do, 09 Aug 2007) $
106 */
107 public class WPVSConfigurationDocument extends WPVSCapabilitiesDocument {
108
109 private static final long serialVersionUID = 1511898601495679163L;
110
111 private static final ILogger LOG = LoggerFactory.getLogger( WPVSConfigurationDocument.class );
112
113 private static String PRE_DWPVS = CommonNamespaces.DEEGREEWPVS_PREFIX + ":";
114
115 private static String PRE_OWS = CommonNamespaces.OWS_PREFIX + ":";
116
117 // The smallestMinimalScaleDenomiator is needed to calculate the smallest resolutionstripe
118 // possible
119 private double smallestMinimalScaleDenominator = Double.MAX_VALUE;
120
121 /**
122 * Creates a class representation of the <code>WPVSConfiguration</code> document.
123 *
124 * @return Returns a WPVSConfiguration object.
125 * @throws InvalidConfigurationException
126 */
127 public WPVSConfiguration parseConfiguration()
128 throws InvalidConfigurationException {
129 WPVSConfiguration wpvsConfiguration = null;
130 try {
131
132 // TODO 'contents' field not verified, therefore null! Check spec.
133 Element requestedNode = (Element) XMLTools.getRequiredNode(
134 getRootElement(),
135 PRE_DWPVS + "deegreeParams",
136 nsContext );
137 WPVSDeegreeParams wpvsDeegreeParams = parseDeegreeParams( requestedNode );
138
139 requestedNode = (Element) XMLTools.getRequiredNode( getRootElement(), PRE_DWPVS
140 + "Dataset",
141 nsContext );
142 Dataset rootDataset = parseDataset( requestedNode, null, null,
143 wpvsDeegreeParams.getMinimalWCS_DGMResolution() );
144
145 wpvsConfiguration = new WPVSConfiguration(
146 parseVersion(),
147 parseUpdateSequence(),
148 getServiceIdentification(),
149 getServiceProvider(),
150 parseOperationsMetadata(),
151 null,
152 rootDataset,
153 wpvsDeegreeParams,
154 ( Double.isInfinite( smallestMinimalScaleDenominator ) ? 1.0
155 : smallestMinimalScaleDenominator ) );
156
157 } catch ( XMLParsingException e ) {
158 throw new InvalidConfigurationException( e.getMessage() + "\n"
159 + StringTools.stackTraceToString( e ) );
160
161 } catch ( MissingParameterValueException e ) {
162 throw new InvalidConfigurationException( e.getMessage() + "\n"
163 + StringTools.stackTraceToString( e ) );
164
165 } catch ( InvalidParameterValueException e ) {
166 throw new InvalidConfigurationException( e.getMessage() + "\n"
167 + StringTools.stackTraceToString( e ) );
168
169 } catch ( OGCWebServiceException e ) {
170 throw new InvalidConfigurationException( e.getMessage() + "\n"
171 + StringTools.stackTraceToString( e ) );
172
173 } catch ( InvalidConfigurationException e ) {
174 throw new InvalidConfigurationException( e.getMessage() + "\n"
175 + StringTools.stackTraceToString( e ) );
176
177 }
178 return wpvsConfiguration;
179 }
180
181 /**
182 * Creates and returns a new <code>WPVSDeegreeParams</code> object from the given
183 * <code>Node</code>.
184 *
185 * @param deegreeNode
186 * @return Returns a new WPVSDeegreeParams object.
187 * @throws XMLParsingException
188 * @throws InvalidConfigurationException
189 */
190 private WPVSDeegreeParams parseDeegreeParams( Node deegreeNode )
191 throws XMLParsingException, InvalidConfigurationException {
192
193 Element deegreeElement = (Element) XMLTools.getRequiredNode(
194 deegreeNode,
195 PRE_DWPVS
196 + "DefaultOnlineResource",
197 nsContext );
198 OnlineResource online = parseOnLineResource( deegreeElement );
199
200 int cacheSize = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "CacheSize", nsContext, 100 );
201
202 int maxLifeTime = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "MaxLifeTime", nsContext,
203 3600 );
204
205 int reqTimeLimit = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "RequestTimeLimit",
206 nsContext, 60 );
207 reqTimeLimit *= 1000;
208
209 float viewQuality = (float) XMLTools.getNodeAsDouble( deegreeNode, PRE_DWPVS
210 + "ViewQuality",
211 nsContext, 0.95f );
212
213 int maxMapWidth = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "MaxViewWidth",
214 nsContext, 1000 );
215
216 int maxMapHeight = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "MaxViewHeight",
217 nsContext, 1000 );
218
219 String charSet = XMLTools.getNodeAsString( deegreeNode, PRE_DWPVS + "CharacterSet",
220 nsContext, "UTF-8" );
221
222 Node copyrightNode = XMLTools.getNode( deegreeNode, PRE_DWPVS + "Copyright", nsContext );
223
224 Node copyTextNode = XMLTools.getNode( copyrightNode, PRE_DWPVS + "Text", nsContext );
225 Node copyURLNode = XMLTools.getNode( copyrightNode, PRE_DWPVS + "ImageURL/@xlink:href",
226 nsContext );
227
228 boolean isWatermarked = false;
229
230 String copyright;
231 if ( copyTextNode != null ) {
232 copyright = XMLTools.getRequiredNodeAsString( copyrightNode, PRE_DWPVS + "Text/text()",
233 nsContext );
234 } else if ( copyURLNode != null ) {
235 copyright = XMLTools.getRequiredNodeAsString( copyrightNode, PRE_DWPVS
236 + "ImageURL/@xlink:href",
237 nsContext );
238
239 isWatermarked = XMLTools.getNodeAsBoolean( copyrightNode, PRE_DWPVS
240 + "ImageURL/@watermark",
241 nsContext, isWatermarked );
242
243 try {
244 copyright = resolve( copyright ).toString();
245 } catch ( MalformedURLException e ) {
246 throw new InvalidConfigurationException( "Copyright/ImageURL '" + copyright
247 + "' doesn't seem to be a valid URL!" );
248 }
249
250 } else {
251 throw new InvalidConfigurationException( "Copyright must contain either "
252 + "a Text-Element or an ImageURL-Element!" );
253 }
254
255 Map<String, URL> backgroundMap = new HashMap<String, URL>( 10 );
256 Element backgrounds = (Element) XMLTools.getNode( deegreeNode,
257 PRE_DWPVS + "BackgroundList", nsContext );
258 if ( backgrounds != null ) {
259 List backgroundList = XMLTools.getNodes( backgrounds, PRE_DWPVS + "Background",
260 nsContext );
261 for ( Iterator iter = backgroundList.iterator(); iter.hasNext(); ) {
262 Element background = (Element) iter.next();
263
264 String bgName = background.getAttribute( "name" );
265 String bgHref = background.getAttribute( "href" );
266
267 if ( bgName == null || bgName.length() == 0 || bgHref == null
268 || bgHref.length() == 0 )
269 throw new InvalidConfigurationException(
270 "Background must contain a 'name' and a "
271 + " 'href' attribute, both if which must contain non-empty strings." );
272
273 try {
274
275 backgroundMap.put( bgName, resolve( bgHref ) );
276 } catch ( MalformedURLException e ) {
277 throw new InvalidConfigurationException( "Background", e.getMessage() );
278 }
279 }
280
281 }
282
283 boolean quality = XMLTools.getNodeAsBoolean( deegreeNode, PRE_DWPVS
284 + "RequestQualityPreferred",
285 nsContext, true );
286 double maximumFarClippingPlane = XMLTools.getNodeAsDouble(
287 deegreeNode,
288 PRE_DWPVS
289 + "RequestsMaximumFarClippingPlane",
290 nsContext, 15000 );
291
292 double nearClippingPlane = XMLTools.getNodeAsDouble(
293 deegreeNode,
294 PRE_DWPVS
295 + "NearClippingPlane",
296 nsContext, 2 );
297
298 String defaultSplitter = XMLTools.getNodeAsString( deegreeNode,
299 PRE_DWPVS + "DefaultSplitter",
300 nsContext, "QUAD" ).toUpperCase();
301
302 double minimalTerrainHeight = XMLTools.getNodeAsDouble( deegreeNode,
303 PRE_DWPVS + "MinimalTerrainHeight",
304 nsContext, 0 );
305
306 double minimalWCS_DGMResolution = XMLTools.getNodeAsDouble(
307 deegreeNode,
308 PRE_DWPVS
309 + "MinimalWCSElevationModelResolution",
310 nsContext, 0 );
311
312 double extendRequestPercentage = XMLTools.getNodeAsDouble(
313 deegreeNode,
314 PRE_DWPVS
315 + "ExtendRequestPercentage",
316 nsContext, 0 );
317 if ( extendRequestPercentage > 100 ) {
318 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_EXTEND_REQUEST_PERCENTAGE",
319 Double.valueOf( extendRequestPercentage ),
320 Double.valueOf( 100 ) ) );
321 extendRequestPercentage = 100d;
322 } else if ( extendRequestPercentage < -0.00000001 ) {
323 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_EXTEND_REQUEST_PERCENTAGE",
324 Double.valueOf( extendRequestPercentage ),
325 Double.valueOf( 0 ) ) );
326 extendRequestPercentage = 0d;
327 }
328 WPVSDeegreeParams wpvsDeegreeParams = new WPVSDeegreeParams( online,
329 cacheSize,
330 reqTimeLimit,
331 charSet,
332 copyright,
333 isWatermarked,
334 maxLifeTime,
335 viewQuality,
336 backgroundMap,
337 maxMapWidth,
338 maxMapHeight,
339 quality,
340 maximumFarClippingPlane,
341 nearClippingPlane,
342 defaultSplitter,
343 minimalTerrainHeight,
344 minimalWCS_DGMResolution,
345 extendRequestPercentage * 0.01 );
346
347 return wpvsDeegreeParams;
348 }
349
350 // /**
351 // * Gets the <code>Dataset</code> object from the <code>WPVSConfiguration</code> element.
352 // *
353 // * @return Returns the Dataset object form root element.
354 // * @throws XMLParsingException
355 // * @throws OGCWebServiceException
356 // * @throws InvalidParameterValueException
357 // * @throws MissingParameterValueException
358 // * @throws InvalidConfigurationException
359 // */
360 // private Dataset getDataset( Deegree)
361 // throws XMLParsingException, MissingParameterValueException,
362 // InvalidParameterValueException, OGCWebServiceException,
363 // InvalidConfigurationException {
364 //
365 // Element datasetElement = (Element) XMLTools.getRequiredNode( getRootElement(), PRE_DWPVS
366 // + "Dataset",
367 // nsContext );
368 // Dataset dataset = parseDataset( datasetElement, null, null );
369 //
370 // return dataset;
371 // }
372
373 /**
374 * Creates and returns a new <code>Dataset</code> object from the given <code>Element</code>
375 * and the parent <code>Dataset</code> object.
376 *
377 * @param datasetElement
378 * @param parent
379 * may be null if root Dataset
380 * @return Returns a new Dataset object.
381 * @throws XMLParsingException
382 * @throws MissingParameterValueException
383 * @throws InvalidParameterValueException
384 * @throws OGCWebServiceException
385 * @throws InvalidConfigurationException
386 */
387 private Dataset parseDataset( Element datasetElement, Dataset parent,
388 CoordinateSystem defaultCoordinateSystem,
389 double minimalWCS_DGMResolution )
390 throws XMLParsingException, MissingParameterValueException,
391 InvalidParameterValueException, OGCWebServiceException,
392 InvalidConfigurationException {
393 // attributes
394 boolean queryable = XMLTools.getNodeAsBoolean( datasetElement, "@queryable", nsContext,
395 false );
396 boolean opaque = XMLTools.getNodeAsBoolean( datasetElement, "@opaque", nsContext, false );
397 boolean noSubsets = XMLTools.getNodeAsBoolean( datasetElement, "@noSubsets", nsContext,
398 false );
399 int fixedWidth = XMLTools.getNodeAsInt( datasetElement, "@fixedWidth", nsContext, 0 );
400 int fixedHeight = XMLTools.getNodeAsInt( datasetElement, "@fixedHeight", nsContext, 0 );
401
402 // elements
403 String name = XMLTools.getNodeAsString( datasetElement, PRE_DWPVS + "Name/text()",
404 nsContext, null );
405 String title = XMLTools.getRequiredNodeAsString( datasetElement,
406 PRE_DWPVS + "Title/text()", nsContext );
407 String abstract_ = XMLTools.getNodeAsString( datasetElement, PRE_DWPVS + "Abstract/text()",
408 nsContext, null );
409 Keywords[] keywords = getKeywords( XMLTools.getNodes( datasetElement, PRE_OWS + "Keywords",
410 nsContext ) );
411 String[] crsStrings = XMLTools.getNodesAsStrings( datasetElement, PRE_DWPVS + "CRS/text()",
412 nsContext );
413 List<CoordinateSystem> crsList = parseCoordinateSystems( crsStrings );
414
415 if ( parent == null ) { // root dataset
416 if ( crsList.size() == 0 || crsList.get( 0 ) == null ) {
417 throw new InvalidCapabilitiesException(
418 Messages.getMessage(
419 "WPVS_NO_TOPLEVEL_DATASET_CRS",
420 title ) );
421 }
422 defaultCoordinateSystem = crsList.get( 0 );
423 }
424
425 String[] format = XMLTools.getRequiredNodesAsStrings( datasetElement, PRE_DWPVS
426 + "Format/text()",
427 nsContext );
428 // wgs84 == mandatory
429 Element boundingBoxElement = (Element) XMLTools.getRequiredNode(
430 datasetElement,
431 PRE_OWS
432 + "WGS84BoundingBox",
433 nsContext );
434 Envelope wgs84BoundingBox = getWGS84BoundingBoxType( boundingBoxElement );
435
436 Envelope[] boundingBoxes = getBoundingBoxes( datasetElement, defaultCoordinateSystem );
437 Dimension[] dimensions = parseDimensions( datasetElement );
438 DataProvider dataProvider = parseDataProvider( datasetElement );
439 Identifier identifier = parseDatasetIdentifier( datasetElement, PRE_DWPVS + "Identifier" );
440 MetaData[] metaData = parseMetaData( datasetElement );
441 DatasetReference[] datasetRefs = parseDatasetReferences( datasetElement );
442 FeatureListReference[] featureListRefs = parseFeatureListReferences( datasetElement );
443 Style[] style = parseStyles( datasetElement );
444 double minScaleDenom = XMLTools.getNodeAsDouble(
445 datasetElement,
446 PRE_DWPVS
447 + "MinimumScaleDenominator/text()",
448 nsContext, 0 );
449
450 // update the smallestMinimalScaleDenomiator
451 if ( minScaleDenom < smallestMinimalScaleDenominator )
452 smallestMinimalScaleDenominator = minScaleDenom;
453
454 double maxScaleDenom = XMLTools.getNodeAsDouble(
455 datasetElement,
456 PRE_DWPVS
457 + "MaximumScaleDenominator/text()",
458 nsContext, 9E9 );
459
460 if ( minScaleDenom >= maxScaleDenom ) {
461 throw new InvalidCapabilitiesException( "MinimumScaleDenominator must be "
462 + "less than MaximumScaleDenominator!" );
463 }
464 CoordinateSystem currentCRS = defaultCoordinateSystem;
465 if ( crsList.size() > 0 && crsList.get( 0 ) != null ) {
466 currentCRS = crsList.get( 0 );
467 }
468 ElevationModel elevationModel = parseElevationModel( datasetElement, name,
469 minimalWCS_DGMResolution, currentCRS );
470 AbstractDataSource[] dataSources = parseAbstractDatasources( datasetElement, name,
471 currentCRS );
472
473 // create new root dataset
474 Dataset dataset = new Dataset( queryable, opaque, noSubsets, fixedWidth, fixedHeight, name,
475 title, abstract_, keywords, crsList, format,
476 wgs84BoundingBox, boundingBoxes, dimensions, dataProvider,
477 identifier, metaData, datasetRefs, featureListRefs, style,
478 minScaleDenom, maxScaleDenom, null, elevationModel,
479 dataSources, parent );
480
481 // get child datasets
482 List nl = XMLTools.getNodes( datasetElement, PRE_DWPVS + "Dataset", nsContext );
483 Dataset[] childDatasets = new Dataset[nl.size()];
484 for ( int i = 0; i < childDatasets.length; i++ ) {
485 childDatasets[i] = parseDataset( (Element) nl.get( i ), dataset,
486 defaultCoordinateSystem, minimalWCS_DGMResolution );
487
488 }
489
490 // set child datasets
491 dataset.setDatasets( childDatasets );
492
493 return dataset;
494 }
495
496 /**
497 * Creates and returns a new <code>ElevationModel</code> object from the given
498 * <code>Element</code> and the parent <code>Dataset</code>.
499 *
500 * The OGC ElevationModel contains only a String. The Deegree ElevationModel additionaly
501 * contains a complex dataSource.
502 *
503 * @param datasetElement
504 * @param parent
505 * @return Returns the ElevationModel object.
506 * @throws XMLParsingException
507 * @throws OGCWebServiceException
508 * @throws InvalidParameterValueException
509 * @throws MissingParameterValueException
510 * @throws InvalidConfigurationException
511 */
512 private ElevationModel parseElevationModel( Element datasetElement, String parentName,
513 double minimalWCS_DGMResolution,
514 CoordinateSystem defaultCRS )
515 throws XMLParsingException, MissingParameterValueException,
516 InvalidParameterValueException, OGCWebServiceException,
517 InvalidConfigurationException {
518
519 Element elevationElement = null;
520 String name = null;
521 ElevationModel elevationModel = null;
522
523 elevationElement = (Element) XMLTools.getNode( datasetElement,
524 PRE_DWPVS + "ElevationModel", nsContext );
525
526 AbstractDataSource[] dataSources = null;
527 if ( elevationElement != null ) {
528
529 name = XMLTools.getRequiredNodeAsString( elevationElement, PRE_DWPVS + "Name/text()",
530 nsContext );
531
532 dataSources = parseAbstractDatasources( elevationElement, parentName, defaultCRS );
533 if ( dataSources.length < 1 ) {
534 throw new InvalidCapabilitiesException(
535 "Each '"
536 + elevationElement.getNodeName()
537 + "' must contain at least one data source!" );
538 }
539 if ( !Double.isNaN( minimalWCS_DGMResolution ) ) {
540 // little trick to know which dgm datasources have a configured minimal resolution,
541 // if the minimalWCS_DGMResolution is not set (e.g Double.nan) nothing has to be
542 // done (a value of 0d is presumed)
543 for ( AbstractDataSource source : dataSources ) {
544 if ( source.getServiceType() == AbstractDataSource.LOCAL_WCS
545 || source.getServiceType() == AbstractDataSource.REMOTE_WCS ) {
546 ( (LocalWCSDataSource) source ).setConfiguredMinimalDGMResolution( minimalWCS_DGMResolution );
547 }
548 }
549 }
550 }
551
552 elevationModel = new ElevationModel( name, dataSources );
553
554 return elevationModel;
555 }
556
557 /**
558 * Creates and returns a new array of <code>AbstractDataSource</code> objects from the given
559 * <code>Element</code>.
560 *
561 * If the objects are used within an ElevationModel object, they may be of the following types:
562 * LocalWCSDataSource, RemoteWCSDataSource, LocalWFSDataSource, RemoteWFSDataSource. If the
563 * objects are used within a Dataset object, they may additionaly be of the types:
564 * LocalWMSDataSource, RemoteWMSDataSource.
565 *
566 * @param element
567 * @return Returns a new array of AbstractDataSource objects.
568 * @throws XMLParsingException
569 * @throws OGCWebServiceException
570 * @throws InvalidConfigurationException
571 */
572 private AbstractDataSource[] parseAbstractDatasources( Element element, String parentName,
573 CoordinateSystem defaultCRS )
574 throws XMLParsingException, OGCWebServiceException,
575 InvalidConfigurationException {
576
577 List abstractDataSources = XMLTools.getNodes( element, "*", nsContext );
578 List<AbstractDataSource> tempDataSources = new ArrayList<AbstractDataSource>(
579 abstractDataSources.size() );
580
581 for ( int i = 0; i < abstractDataSources.size(); i++ ) {
582
583 Element dataSourceElement = (Element) abstractDataSources.get( i );
584
585 // String nodeName = dataSourceElement.getNodeName();
586 String nodeName = dataSourceElement.getLocalName();
587
588 if ( nodeName.endsWith( "DataSource" ) ) {
589 QualifiedName pn = null;
590 if ( parentName != null ) {
591 pn = new QualifiedName( PRE_DWPVS, parentName, nsContext.getURI( PRE_DWPVS ) );
592 }
593 QualifiedName name = XMLTools.getNodeAsQualifiedName( dataSourceElement,
594 PRE_DWPVS + "Name/text()",
595 nsContext, pn );
596
597 OWSCapabilities owsCapabilities = parseOWSCapabilities( dataSourceElement );
598
599 double minScaleDenom = XMLTools.getNodeAsDouble(
600 dataSourceElement,
601 PRE_DWPVS
602 + "MinimumScaleDenominator/text()",
603 nsContext, 0 );
604
605 // update the smallestMinimalScaleDenomiator
606 if ( minScaleDenom < smallestMinimalScaleDenominator )
607 smallestMinimalScaleDenominator = minScaleDenom;
608
609 double maxScaleDenom = XMLTools.getNodeAsDouble(
610 dataSourceElement,
611 PRE_DWPVS
612 + "MaximumScaleDenominator/text()",
613 nsContext, 9E9 );
614
615 Surface validArea = parseValidArea( dataSourceElement, defaultCRS );
616 AbstractDataSource dataSource = null;
617
618 if ( nodeName.equals( "LocalWCSDataSource" ) ) {
619 Element filterElement = (Element) XMLTools.getRequiredNode(
620 dataSourceElement,
621 PRE_DWPVS
622 + "FilterCondition",
623 nsContext );
624 GetCoverage getCoverage = parseWCSFilterCondition( filterElement );
625 Color[] transparentColors = parseTransparentColors( dataSourceElement );
626
627 dataSource = new LocalWCSDataSource( name, owsCapabilities, validArea,
628 minScaleDenom, maxScaleDenom, getCoverage,
629 transparentColors );
630 LOG.logDebug( "created local wcs with name: " + name );
631
632 } else if ( nodeName.equals( "RemoteWCSDataSource" ) ) {
633 Element filterElement = (Element) XMLTools.getRequiredNode(
634 dataSourceElement,
635 PRE_DWPVS
636 + "FilterCondition",
637 nsContext );
638 GetCoverage getCoverage = parseWCSFilterCondition( filterElement );
639 Color[] transparentColors = parseTransparentColors( dataSourceElement );
640
641 dataSource = new RemoteWCSDataSource( name, owsCapabilities, validArea,
642 minScaleDenom, maxScaleDenom,
643 getCoverage, transparentColors );
644 LOG.logDebug( "created remote wcs with name: " + name );
645
646 } else if ( nodeName.equals( "LocalWFSDataSource" ) ) {
647 Text geoPropNode = (Text) XMLTools.getRequiredNode(
648 dataSourceElement,
649 PRE_DWPVS
650 + "GeometryProperty/text()",
651 nsContext );
652 PropertyPath geometryProperty = parsePropertyPath( geoPropNode );
653
654 Element filterElement = (Element) XMLTools.getNode(
655 dataSourceElement,
656 PRE_DWPVS
657 + "FilterCondition/ogc:Filter",
658 nsContext );
659
660 Filter filterCondition = null;
661 if ( filterElement != null ) {
662 filterCondition = AbstractFilter.buildFromDOM( filterElement, false );
663 }
664
665 // FeatureCollectionAdapter adapter = createFCAdapterFromAdapterClassName(
666 // dataSourceElement );
667
668 dataSource = new LocalWFSDataSource( name, owsCapabilities, validArea,
669 minScaleDenom, maxScaleDenom,
670 geometryProperty, filterCondition/*
671 * ,
672 * adapter
673 */);
674 LOG.logDebug( "created local wfs with name: " + name );
675
676 } else if ( nodeName.equals( "RemoteWFSDataSource" ) ) {
677 Text geoPropNode = (Text) XMLTools.getRequiredNode(
678 dataSourceElement,
679 PRE_DWPVS
680 + "GeometryProperty/text()",
681 nsContext );
682 PropertyPath geometryProperty = parsePropertyPath( geoPropNode );
683
684 Element filterElement = (Element) XMLTools.getNode(
685 dataSourceElement,
686 PRE_DWPVS
687 + "FilterCondition/ogc:Filter",
688 nsContext );
689
690 Filter filterCondition = null;
691 if ( filterElement != null ) {
692 filterCondition = AbstractFilter.buildFromDOM( filterElement, false );
693 }
694
695 // FeatureCollectionAdapter adapter = createFCAdapterFromAdapterClassName(
696 // dataSourceElement );
697
698 dataSource = new RemoteWFSDataSource( name, owsCapabilities, validArea,
699 minScaleDenom, maxScaleDenom,
700 geometryProperty, filterCondition
701 /* ,adapter */);
702 LOG.logDebug( "created remote wfs with name: " + name );
703
704 } else if ( nodeName.equals( "LocalWMSDataSource" ) ) {
705 if ( element.getNodeName().endsWith( "ElevationModel" ) ) {
706 throw new InvalidConfigurationException( "An ElevationModel cannot "
707 + "contain a LocalWMSDataSource!" );
708 }
709 Element filterElement = (Element) XMLTools.getRequiredNode(
710 dataSourceElement,
711 PRE_DWPVS
712 + "FilterCondition",
713 nsContext );
714 GetMap getMap = parseWMSFilterCondition( filterElement );
715
716 Color[] transparentColors = parseTransparentColors( dataSourceElement );
717
718 dataSource = new LocalWMSDataSource( name, owsCapabilities, validArea,
719 minScaleDenom, maxScaleDenom, getMap,
720 transparentColors );
721 LOG.logDebug( "created local wms with name: " + name );
722
723 } else if ( nodeName.equals( "RemoteWMSDataSource" ) ) {
724 if ( element.getNodeName().endsWith( "ElevationModel" ) ) {
725 throw new InvalidConfigurationException( "An ElevationModel cannot "
726 + "contain a LocalWMSDataSource!" );
727 }
728 Element filterElement = (Element) XMLTools.getRequiredNode(
729 dataSourceElement,
730 PRE_DWPVS
731 + "FilterCondition",
732 nsContext );
733 GetMap getMap = parseWMSFilterCondition( filterElement );
734
735 Color[] transparentColors = parseTransparentColors( dataSourceElement );
736
737 dataSource = new RemoteWMSDataSource( name, owsCapabilities, validArea,
738 minScaleDenom, maxScaleDenom, getMap,
739 transparentColors );
740 LOG.logDebug( "created remote wms with name: " + name );
741 } else {
742 throw new InvalidCapabilitiesException( "Unknown data source: '" + nodeName
743 + "'" );
744 }
745
746 tempDataSources.add( dataSource );
747 }
748 }
749
750 AbstractDataSource[] dataSources = tempDataSources.toArray( new AbstractDataSource[tempDataSources.size()] );
751
752 return dataSources;
753 }
754
755 /**
756 * FIXME check content of StringBuffer and Map! This is an adapted copy from:
757 * org.deegree.ogcwebservices.wms.configuration#parseWMSFilterCondition(Node)
758 *
759 * Creates and returns a new <code>GetMap</code> object from the given <code>Element</code>.
760 *
761 * @param filterElement
762 * @return a partial wms GetMap request instance
763 * @throws XMLParsingException
764 */
765 private GetMap parseWMSFilterCondition( Element filterElement )
766 throws XMLParsingException {
767
768 GetMap getMap = null;
769
770 String wmsRequest = XMLTools.getRequiredNodeAsString( filterElement, PRE_DWPVS
771 + "WMSRequest/text()",
772 nsContext );
773
774 StringBuffer sd = new StringBuffer( 1000 );
775 sd.append( "REQUEST=GetMap&LAYERS=%default%&STYLES=&SRS=EPSG:4326&" );
776 sd.append( "BBOX=0,0,1,1&WIDTH=1&HEIGHT=1&FORMAT=%default%" );
777
778 Map<String, String> map1 = KVP2Map.toMap( sd.toString() );
779
780 Map<String, String> map2 = KVP2Map.toMap( wmsRequest );
781 if ( map2.get( "VERSION" ) == null && map2.get( "WMTVER" ) == null ) {
782 map2.put( "VERSION", "1.1.1" );
783 }
784 // if no service is set use WMS as default
785 if ( map2.get( "SERVICE" ) == null ) {
786 map2.put( "SERVICE", "WMS" );
787 }
788
789 map1.putAll( map2 );
790
791 String id = Long.toString( IDGenerator.getInstance().generateUniqueID() );
792 map1.put( "ID", id );
793 try {
794 getMap = GetMap.create( map1 );
795 } catch ( Exception e ) {
796 throw new XMLParsingException( "could not create GetMap from WMS FilterCondition", e );
797 }
798
799 return getMap;
800 }
801
802 /**
803 * FIXME check content of StringBuffer ! This is an adapted copy from:
804 * org.deegree.ogcwebservices.wms.configuration#parseWCSFilterCondition(Node)
805 *
806 * Creates and returns a new <code>GetCoverage</code> object from the given
807 * <code>Element</code>.
808 *
809 * @param filterElement
810 * @return a partial GetCoverage request
811 * @throws XMLParsingException
812 */
813 private GetCoverage parseWCSFilterCondition( Element filterElement )
814 throws XMLParsingException {
815
816 GetCoverage coverage = null;
817
818 String wcsRequest = XMLTools.getRequiredNodeAsString( filterElement, PRE_DWPVS
819 + "WCSRequest/text()",
820 nsContext );
821
822 StringBuffer sd = new StringBuffer( 1000 );
823 sd.append( "version=1.0.0&Coverage=%default%&CRS=EPSG:4326&BBOX=0,0,1,1" );
824 sd.append( "&Width=1&Height=1&Format=%default%&" );
825 sd.append( wcsRequest );
826
827 String id = "" + IDGenerator.getInstance().generateUniqueID();
828
829 try {
830 coverage = GetCoverage.create( id, sd.toString() );
831 } catch ( Exception e ) {
832 throw new XMLParsingException( "Could not create GetCoverage "
833 + "from WPVS FilterCondition", e );
834 }
835
836 return coverage;
837 }
838
839 /**
840 * Creates and returns a new <code>OWSCapabilities</code> object from the given
841 * <code>Element</code>.
842 *
843 * @param element
844 * @return Returns a new OWSCapabilities object.
845 * @throws XMLParsingException
846 * @throws InvalidCapabilitiesException
847 */
848 private OWSCapabilities parseOWSCapabilities( Element element )
849 throws XMLParsingException, InvalidCapabilitiesException {
850
851 Element owsCapabilitiesElement = (Element) XMLTools.getRequiredNode(
852 element,
853 PRE_DWPVS
854 + "OWSCapabilities",
855 nsContext );
856
857 String format = null;
858
859 // FIXME
860 // schema has onlineResourceType as not optional, so it should be mandatory.
861 // but in other examples onlineResource is never created with this onlineResourceType.
862 // therefore it gets omitted here, too.
863
864 // String onlineResourceType = XMLTools.getRequiredNodeAsString(
865 // owsCapabilitiesElement, PRE_DWPVS+"OnlineResource/@xlink:type", nsContext );
866
867 String onlineResourceURI = XMLTools.getRequiredNodeAsString(
868 owsCapabilitiesElement,
869 PRE_DWPVS
870 + "OnlineResource/@xlink:href",
871 nsContext );
872
873 URL onlineResource;
874 try {
875 onlineResource = resolve( onlineResourceURI );
876 } catch ( MalformedURLException e ) {
877 throw new InvalidCapabilitiesException( onlineResourceURI
878 + " does not represent a valid URL: "
879 + e.getMessage() );
880 }
881 LOG.logDebug( "found following onlineResource: " + onlineResource );
882 return new OWSCapabilities( format, onlineResource );
883
884 // FIXME
885 // if onlineResourceType is going to be used, the returned new OnlineResource should be
886 // created with different constructor:
887 // return new OWSCapabilities( format, onlineResourceType, onlineResource );
888 }
889
890 /**
891 * Creates and returns a new <code>Geometry</code> object from the given Element.
892 *
893 * @param dataSource
894 * @return Returns a new Geometry object.
895 * @throws XMLParsingException
896 * @throws InvalidConfigurationException
897 */
898 private Surface parseValidArea( Element dataSource, CoordinateSystem defaultCRS )
899 throws XMLParsingException, InvalidConfigurationException {
900 List nl = XMLTools.getNodes( dataSource, PRE_DWPVS + "ValidArea/*", nsContext );
901 if ( nl.size() == 0 ) {
902 return null;
903 }
904
905 if ( nl.size() > 1 ) {
906 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_NUMBER_OF_VALID_AREAS",
907 GMLNS.toASCIIString(), dataSource.getLocalName() ) );
908 return null;
909 }
910 Surface validArea = null;
911 if ( ( (Node) nl.get( 0 ) ).getNamespaceURI().equals( GMLNS.toASCIIString() ) ) {
912 try {
913 String srsName = XMLTools.getNodeAsString( (Node) nl.get( 0 ), "@srsName",
914 nsContext, null );
915 if ( srsName == null ) {
916 srsName = defaultCRS.getFormattedString();
917 }
918
919 Geometry geom = GMLGeometryAdapter.wrap( (Element) nl.get( 0 ), srsName );
920 if ( !( geom instanceof Surface ) ) {
921 throw new InvalidConfigurationException(
922 Messages.getMessage(
923 "WPVS_WRONG_GEOMTERY_VALID_AREA",
924 dataSource.getLocalName() ) );
925 }
926 validArea = (Surface) geom;
927 } catch ( GeometryException e ) {
928 throw new InvalidConfigurationException(
929 Messages.getMessage(
930 "WPVS_WRONG_GEOMTERY_VALID_AREA",
931 dataSource.getLocalName() )
932 + "\n"
933 + e.getMessage(),
934
935 e );
936 }
937
938 } else if ( ( (Node) nl.get( 0 ) ).getNamespaceURI().equals( CommonNamespaces.OWSNS ) ) {
939 try {
940 Element bbox = (Element) nl.get( 0 );
941 if ( !"BoundingBox".equals( bbox.getLocalName() ) ) {
942 throw new InvalidConfigurationException(
943 Messages.getMessage(
944 "WPVS_WRONG_GEOMTERY_VALID_AREA",
945 dataSource.getLocalName() ) );
946 }
947 Envelope env = parseBoundingBox( (Element) nl.get( 0 ), null );
948 validArea = GeometryFactory.createSurface( env, env.getCoordinateSystem() );
949 } catch ( GeometryException e ) {
950 throw new InvalidConfigurationException(
951 Messages.getMessage(
952 "WPVS_WRONG_GEOMTERY_VALID_AREA",
953 dataSource.getLocalName() )
954 + "\n"
955 + e.getMessage(),
956 e );
957 } catch ( InvalidParameterValueException e ) {
958 throw new InvalidConfigurationException(
959 Messages.getMessage(
960 "WPVS_WRONG_GEOMTERY_VALID_AREA",
961 dataSource.getLocalName() )
962 + "\n"
963 + e.getMessage(),
964 e );
965 }
966 } else {
967 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_GEOMTERY_VALID_AREA",
968 dataSource.getLocalName() ) );
969 return null;
970 }
971 return validArea;
972 }
973
974 /**
975 * Creates and returns a new array of <code>Color</code> objects from the given Element.
976 *
977 * @param dataSourceElement
978 * @return Returns a new array of Color objects.
979 * @throws XMLParsingException
980 * @throws InvalidCapabilitiesException
981 */
982 private Color[] parseTransparentColors( Element dataSourceElement )
983 throws XMLParsingException {
984
985 List colorList = XMLTools.getNodes( dataSourceElement, PRE_DWPVS + "TransparentColors/"
986 + PRE_DWPVS + "Color", nsContext );
987
988 Color[] transparentColors = null;
989 if ( colorList != null ) {
990 transparentColors = new Color[colorList.size()];
991
992 for ( int i = 0; i < transparentColors.length; i++ ) {
993
994 Element colorElement = (Element) colorList.get( i );
995 String color = XMLTools.getRequiredNodeAsString( colorElement, "text()", nsContext );
996
997 transparentColors[i] = Color.decode( color );
998 }
999 }
1000
1001 return transparentColors;
1002 }
1003
1004 }
1005
1006 /***************************************************************************************************
1007 * <code>
1008 * Changes to this class. What the people have been up to:
1009 *
1010 * $Log$
1011 * Revision 1.51 2007/03/08 10:16:42 bezema
1012 * added support for the extendRequestPercentage parameter and some small docu/code changes
1013 *
1014 * Revision 1.50 2007/03/06 14:56:55 poth
1015 * bug fix wpvs accessing a dataservices caps
1016 *
1017 * Revision 1.49 2007/03/05 10:19:46 bezema
1018 * removed the usage of an deprectated api
1019 *
1020 * Revision 1.48 2007/01/29 16:44:10 bezema
1021 * removing use of the deprecated api
1022 *
1023 * Revision 1.47 2007/01/29 09:05:16 bezema
1024 * removing use of the deprecated api
1025 *
1026 * Revision 1.46 2007/01/15 17:02:14 bezema
1027 * Updated the capabilities /configuration parsing, and the construction of their beans
1028 *
1029 * Revision 1.45 2006/12/22 13:37:35 poth
1030 * code formatting
1031 *
1032 * Revision 1.44 2006/12/21 11:22:04 bezema
1033 * removed the gabs in a pointbased dgm by interpolation of the nearest boundingbox points and Made the minimalterrainheight configurable.
1034 *
1035 * Revision 1.43 2006/12/20 14:31:50 bezema
1036 * removed syso
1037 *
1038 * Revision 1.42 2006/12/06 12:00:46 poth
1039 * bug fix - reading relative pathes
1040 *
1041 * Revision 1.41 2006/12/06 11:24:33 bezema
1042 * can use the wcs as a localdatasource for textures and dgm, also added support for the wfs features in gml. Still trying to figure out how the eyepoint is set by java3d
1043 *
1044 * Revision 1.40 2006/11/28 18:09:28 mschneider
1045 * Fixed header.
1046 *
1047 * Revision 1.39 2006/11/28 18:08:55 mschneider
1048 * Fixed parsing of GeometryProperty name. Namespace binding was not correctly extracted (null).
1049 *
1050 * Revision 1.38 2006/11/28 16:52:19 bezema Added support for a default splitter
1051 *
1052 * Revision 1.37 2006/11/27 15:41:13 bezema Updated the coordinatesystem handling and the featurecollection adapter
1053 *
1054 * Revision 1.36 2006/11/27 11:44:14 bezema Added a minimalScaleDenomitator check
1055
1056 * Revision 1.34 2006/11/23 11:46:40 bezema The initial version of the new wpvs
1057 *
1058 * Revision 1.33 2006/11/07 16:33:49 poth bug fixes and code formatting
1059 *
1060 * Revision 1.32 2006/08/07 12:14:57 poth never read variable removed
1061 *
1062 * Revision 1.31 2006/07/20 08:13:05 taddei use of QualiName for geometry property
1063 *
1064 * Revision 1.30 2006/07/12 16:59:32 poth required adaptions according to renaming of OnLineResource to OnlineResource
1065 *
1066 * Revision 1.29 2006/07/05 15:58:23 poth bug fix - changed Query to Filter for WFS datasources
1067 *
1068 * Revision 1.28 2006/06/29 19:06:54 poth ** empty log message ***
1069 *
1070 * Revision 1.27 2006/06/29 18:50:16 poth bug fix reading optional element TransparentColors
1071 *
1072 * Revision 1.26 2006/06/20 07:45:21 taddei datasources use quali names now
1073 *
1074 * Revision 1.25 2006/05/05 12:41:36 taddei fixed bug in max tex size
1075 *
1076 * Revision 1.24 2006/04/26 12:13:07 taddei max size and tex config parameters
1077 *
1078 * Revision 1.23 2006/04/06 20:25:24 poth ** empty log message ***
1079 *
1080 * Revision 1.22 2006/04/05 08:56:21 taddei refactoring: fc adapter
1081 *
1082 * Revision 1.20 2006/03/07 08:46:26 taddei added pts list factory
1083 *
1084 * Revision 1.19 2006/02/14 15:14:43 taddei added possibility to choose splitter
1085 *
1086 * Revision 1.18 2006/02/10 16:05:41 taddei capabilities use now resolve()
1087 *
1088 * Revision 1.17 2006/01/30 14:56:10 taddei implementation of copyright info
1089 *
1090 * Revision 1.16 2006/01/26 13:54:59 taddei added code for parsing ElevationModel/Name
1091 *
1092 * Revision 1.15 2006/01/18 08:47:54 taddei bug fixes
1093 *
1094 * Revision 1.14 2005/12/23 11:16:50 mays add comments
1095 *
1096 * Revision 1.13 2005/12/23 10:39:19 mays add imports that where accidentally lost
1097 *
1098 * Revision 1.12 2005/12/23 10:34:56 mays correction of color and filterConditions
1099 *
1100 * Revision 1.10 2005/12/13 13:31:49 mays changes in parseElevationModel because of necessary changes in namespace
1101 *
1102 * Revision 1.9 2005/12/12 13:51:38 mays revision of parseElevationModel, parseDataset, parseDeegreeParams and parseOWSCapabilities.
1103 *
1104 * Revision 1.8 2005/12/09 14:11:22 mays code clean up
1105 *
1106 * Revision 1.7 2005/12/08 16:53:10 mays organized imports
1107 *
1108 * Revision 1.6 2005/12/08 16:49:08 mays move configuration specific stuff from WPVSCapabilitiesDocument to here
1109 *
1110 * Revision 1.5 2005/12/01 10:30:14 mays add standard footer to all java classes in wpvs package
1111 * </code>
1112 **************************************************************************************************/