001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcwebservices/wpvs/configuration/WPVSConfigurationDocument.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.configuration;
038
039 import java.awt.Color;
040 import java.net.MalformedURLException;
041 import java.net.URL;
042 import java.util.ArrayList;
043 import java.util.HashMap;
044 import java.util.List;
045 import java.util.Map;
046
047 import org.deegree.datatypes.QualifiedName;
048 import org.deegree.framework.log.ILogger;
049 import org.deegree.framework.log.LoggerFactory;
050 import org.deegree.framework.util.IDGenerator;
051 import org.deegree.framework.util.KVP2Map;
052 import org.deegree.framework.util.StringTools;
053 import org.deegree.framework.xml.InvalidConfigurationException;
054 import org.deegree.framework.xml.XMLParsingException;
055 import org.deegree.framework.xml.XMLTools;
056 import org.deegree.i18n.Messages;
057 import org.deegree.model.crs.CoordinateSystem;
058 import org.deegree.model.filterencoding.AbstractFilter;
059 import org.deegree.model.filterencoding.Filter;
060 import org.deegree.model.metadata.iso19115.Keywords;
061 import org.deegree.model.metadata.iso19115.OnlineResource;
062 import org.deegree.model.spatialschema.Envelope;
063 import org.deegree.model.spatialschema.GMLGeometryAdapter;
064 import org.deegree.model.spatialschema.Geometry;
065 import org.deegree.model.spatialschema.GeometryException;
066 import org.deegree.model.spatialschema.GeometryFactory;
067 import org.deegree.model.spatialschema.Surface;
068 import org.deegree.ogcbase.CommonNamespaces;
069 import org.deegree.ogcbase.PropertyPath;
070 import org.deegree.ogcwebservices.InvalidParameterValueException;
071 import org.deegree.ogcwebservices.MissingParameterValueException;
072 import org.deegree.ogcwebservices.OGCWebServiceException;
073 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
074 import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
075 import org.deegree.ogcwebservices.wms.operation.GetMap;
076 import org.deegree.ogcwebservices.wpvs.capabilities.DataProvider;
077 import org.deegree.ogcwebservices.wpvs.capabilities.Dataset;
078 import org.deegree.ogcwebservices.wpvs.capabilities.DatasetReference;
079 import org.deegree.ogcwebservices.wpvs.capabilities.Dimension;
080 import org.deegree.ogcwebservices.wpvs.capabilities.ElevationModel;
081 import org.deegree.ogcwebservices.wpvs.capabilities.FeatureListReference;
082 import org.deegree.ogcwebservices.wpvs.capabilities.Identifier;
083 import org.deegree.ogcwebservices.wpvs.capabilities.MetaData;
084 import org.deegree.ogcwebservices.wpvs.capabilities.OWSCapabilities;
085 import org.deegree.ogcwebservices.wpvs.capabilities.Style;
086 import org.deegree.ogcwebservices.wpvs.capabilities.WPVSCapabilitiesDocument;
087 import org.w3c.dom.Element;
088 import org.w3c.dom.Node;
089 import org.w3c.dom.Text;
090
091 /**
092 * Parser for WPVS configuration documents.
093 *
094 * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
095 * @author last edited by: $Author: rbezema $
096 *
097 * @version $Revision: 19665 $, $Date: 2009-09-16 10:11:29 +0200 (Mi, 16. Sep 2009) $
098 */
099 public class WPVSConfigurationDocument extends WPVSCapabilitiesDocument {
100
101 private static final long serialVersionUID = 1511898601495679163L;
102
103 private static final ILogger LOG = LoggerFactory.getLogger( WPVSConfigurationDocument.class );
104
105 private static String PRE_DWPVS = CommonNamespaces.DEEGREEWPVS_PREFIX + ":";
106
107 private static String PRE_OWS = CommonNamespaces.OWS_PREFIX + ":";
108
109 // The smallestMinimalScaleDenomiator is needed to calculate the smallest resolutionstripe
110 // possible
111 private double smallestMinimalScaleDenominator = Double.MAX_VALUE;
112
113 /**
114 * Creates a class representation of the <code>WPVSConfiguration</code> document.
115 *
116 * @return Returns a WPVSConfiguration object.
117 * @throws InvalidConfigurationException
118 */
119 public WPVSConfiguration parseConfiguration()
120 throws InvalidConfigurationException {
121 WPVSConfiguration wpvsConfiguration = null;
122 try {
123
124 // TODO 'contents' field not verified, therefore null! Check spec.
125 Element requestedNode = (Element) XMLTools.getRequiredNode( getRootElement(), PRE_DWPVS + "deegreeParams",
126 nsContext );
127 WPVSDeegreeParams wpvsDeegreeParams = parseDeegreeParams( requestedNode );
128
129 requestedNode = (Element) XMLTools.getRequiredNode( getRootElement(), PRE_DWPVS + "Dataset", nsContext );
130 Dataset rootDataset = parseDataset( requestedNode, null, null, 0, 9E9,
131 wpvsDeegreeParams.getMinimalWCS_DGMResolution() );
132
133 wpvsConfiguration = new WPVSConfiguration(
134 parseVersion(),
135 parseUpdateSequence(),
136 getServiceIdentification(),
137 getServiceProvider(),
138 parseOperationsMetadata( wpvsDeegreeParams.getDefaultOnlineResource() ),
139 null,
140 rootDataset,
141 wpvsDeegreeParams,
142 ( Double.isInfinite( smallestMinimalScaleDenominator ) ? 1.0
143 : smallestMinimalScaleDenominator ) );
144
145 } catch ( XMLParsingException e ) {
146 throw new InvalidConfigurationException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
147
148 } catch ( MissingParameterValueException e ) {
149 throw new InvalidConfigurationException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
150
151 } catch ( InvalidParameterValueException e ) {
152 throw new InvalidConfigurationException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
153
154 } catch ( OGCWebServiceException e ) {
155 throw new InvalidConfigurationException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
156
157 } catch ( InvalidConfigurationException e ) {
158 throw new InvalidConfigurationException( e.getMessage() + "\n" + StringTools.stackTraceToString( e ) );
159
160 }
161 return wpvsConfiguration;
162 }
163
164 /**
165 * Creates and returns a new <code>WPVSDeegreeParams</code> object from the given <code>Node</code>.
166 *
167 * @param deegreeNode
168 * @return Returns a new WPVSDeegreeParams object.
169 * @throws XMLParsingException
170 * @throws InvalidConfigurationException
171 */
172 private WPVSDeegreeParams parseDeegreeParams( Node deegreeNode )
173 throws XMLParsingException, InvalidConfigurationException {
174
175 Element deegreeElement = (Element) XMLTools.getRequiredNode( deegreeNode, PRE_DWPVS + "DefaultOnlineResource",
176 nsContext );
177 OnlineResource defaultOnlineResource = parseOnLineResource( deegreeElement );
178
179 int cacheSize = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "CacheSize", nsContext, 100 );
180
181 int maxLifeTime = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "MaxLifeTime", nsContext, 3600 );
182
183 int reqTimeLimit = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "RequestTimeLimit", nsContext, 60 );
184 reqTimeLimit *= 1000;
185
186 int maxTextureDimension = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "MaxTextureDimension", nsContext,
187 Integer.MAX_VALUE );
188
189 int quadMergeCount = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "QuadMergeCount", nsContext, 10 );
190
191 float viewQuality = (float) XMLTools.getNodeAsDouble( deegreeNode, PRE_DWPVS + "ViewQuality", nsContext, 0.95f );
192
193 int maxMapWidth = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "MaxViewWidth", nsContext, 1000 );
194
195 int maxMapHeight = XMLTools.getNodeAsInt( deegreeNode, PRE_DWPVS + "MaxViewHeight", nsContext, 1000 );
196
197 String charSet = XMLTools.getNodeAsString( deegreeNode, PRE_DWPVS + "CharacterSet", nsContext, "UTF-8" );
198
199 Node copyrightNode = XMLTools.getNode( deegreeNode, PRE_DWPVS + "Copyright", nsContext );
200 String copyright = null;
201 boolean isWatermarked = false;
202 if ( copyrightNode != null ) {
203
204 Node copyTextNode = XMLTools.getNode( copyrightNode, PRE_DWPVS + "Text", nsContext );
205 Node copyURLNode = XMLTools.getNode( copyrightNode, PRE_DWPVS + "ImageURL/@xlink:href", nsContext );
206
207 if ( copyTextNode != null ) {
208 copyright = XMLTools.getRequiredNodeAsString( copyrightNode, PRE_DWPVS + "Text/text()", nsContext );
209 } else if ( copyURLNode != null ) {
210 copyright = XMLTools.getRequiredNodeAsString( copyrightNode, PRE_DWPVS + "ImageURL/@xlink:href",
211 nsContext );
212
213 isWatermarked = XMLTools.getNodeAsBoolean( copyrightNode, PRE_DWPVS + "ImageURL/@watermark", nsContext,
214 isWatermarked );
215
216 try {
217 copyright = resolve( copyright ).toString();
218 } catch ( MalformedURLException e ) {
219 throw new InvalidConfigurationException( "Copyright/ImageURL '" + copyright
220 + "' doesn't seem to be a valid URL!" );
221 }
222
223 } else {
224 throw new InvalidConfigurationException( "Copyright must contain either "
225 + "a Text-Element or an ImageURL-Element!" );
226 }
227 }
228
229 Map<String, URL> backgroundMap = new HashMap<String, URL>( 10 );
230 Element backgrounds = (Element) XMLTools.getNode( deegreeNode, PRE_DWPVS + "BackgroundList", nsContext );
231 if ( backgrounds != null ) {
232 List<Element> backgroundList = XMLTools.getElements( backgrounds, PRE_DWPVS + "Background", nsContext );
233 for ( Element background : backgroundList ) {
234
235 String bgName = background.getAttribute( "name" );
236 String bgHref = background.getAttribute( "href" );
237
238 if ( bgName == null || bgName.length() == 0 || bgHref == null || bgHref.length() == 0 )
239 throw new InvalidConfigurationException(
240 "Background must contain a 'name' and a "
241 + " 'href' attribute, both if which must contain non-empty strings." );
242
243 try {
244
245 backgroundMap.put( bgName, resolve( bgHref ) );
246 } catch ( MalformedURLException e ) {
247 throw new InvalidConfigurationException( "Background", e.getMessage() );
248 }
249 }
250
251 }
252
253 boolean quality = XMLTools.getNodeAsBoolean( deegreeNode, PRE_DWPVS + "RequestQualityPreferred", nsContext,
254 true );
255 double maximumFarClippingPlane = XMLTools.getNodeAsDouble( deegreeNode, PRE_DWPVS
256 + "RequestsMaximumFarClippingPlane",
257 nsContext, 15000 );
258
259 double nearClippingPlane = XMLTools.getNodeAsDouble( deegreeNode, PRE_DWPVS + "NearClippingPlane", nsContext, 2 );
260
261 String defaultSplitter = XMLTools.getNodeAsString( deegreeNode, PRE_DWPVS + "DefaultSplitter", nsContext,
262 "QUAD" ).toUpperCase();
263
264 double minimalTerrainHeight = XMLTools.getNodeAsDouble( deegreeNode, PRE_DWPVS + "MinimalTerrainHeight",
265 nsContext, 0 );
266
267 double minimalWCS_DGMResolution = XMLTools.getNodeAsDouble( deegreeNode,
268 PRE_DWPVS + "MinimalWCSElevationModelResolution",
269 nsContext, 0 );
270
271 double extendRequestPercentage = XMLTools.getNodeAsDouble( deegreeNode, PRE_DWPVS + "ExtendRequestPercentage",
272 nsContext, 0 );
273 if ( extendRequestPercentage > 100 ) {
274 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_EXTEND_REQUEST_PERCENTAGE",
275 Double.valueOf( extendRequestPercentage ), Double.valueOf( 100 ) ) );
276 extendRequestPercentage = 100d;
277 } else if ( extendRequestPercentage < -0.00000001 ) {
278 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_EXTEND_REQUEST_PERCENTAGE",
279 Double.valueOf( extendRequestPercentage ), Double.valueOf( 0 ) ) );
280 extendRequestPercentage = 0d;
281 }
282
283 boolean antialiased = XMLTools.getNodeAsBoolean( deegreeNode, PRE_DWPVS + "RenderAntialiased", nsContext, true );
284 WPVSDeegreeParams wpvsDeegreeParams = new WPVSDeegreeParams( defaultOnlineResource, cacheSize, reqTimeLimit,
285 charSet, copyright, isWatermarked, maxLifeTime,
286 viewQuality, backgroundMap, maxMapWidth,
287 maxMapHeight, quality, maximumFarClippingPlane,
288 nearClippingPlane, defaultSplitter,
289 minimalTerrainHeight, minimalWCS_DGMResolution,
290 extendRequestPercentage * 0.01,
291 maxTextureDimension, quadMergeCount, antialiased );
292
293 return wpvsDeegreeParams;
294 }
295
296 /**
297 * Creates and returns a new <code>Dataset</code> object from the given <code>Element</code> and the parent
298 * <code>Dataset</code> object.
299 *
300 * @param datasetElement
301 * @param parent
302 * may be null if root Dataset
303 * @return Returns a new Dataset object.
304 * @throws XMLParsingException
305 * @throws MissingParameterValueException
306 * @throws InvalidParameterValueException
307 * @throws OGCWebServiceException
308 * @throws InvalidConfigurationException
309 */
310 private Dataset parseDataset( Element datasetElement, Dataset parent, CoordinateSystem defaultCoordinateSystem,
311 double defaultMinScaleDonominator, double defaultMaxScaleDenominator,
312 double minimalWCS_DGMResolution )
313 throws XMLParsingException, MissingParameterValueException, InvalidParameterValueException,
314 OGCWebServiceException, InvalidConfigurationException {
315 // attributes
316 boolean queryable = XMLTools.getNodeAsBoolean( datasetElement, "@queryable", nsContext, false );
317 boolean opaque = XMLTools.getNodeAsBoolean( datasetElement, "@opaque", nsContext, false );
318 boolean noSubsets = XMLTools.getNodeAsBoolean( datasetElement, "@noSubsets", nsContext, false );
319 int fixedWidth = XMLTools.getNodeAsInt( datasetElement, "@fixedWidth", nsContext, 0 );
320 int fixedHeight = XMLTools.getNodeAsInt( datasetElement, "@fixedHeight", nsContext, 0 );
321
322 // elements
323 String name = XMLTools.getNodeAsString( datasetElement, PRE_DWPVS + "Name/text()", nsContext, null );
324 String title = XMLTools.getRequiredNodeAsString( datasetElement, PRE_DWPVS + "Title/text()", nsContext );
325 String abstract_ = XMLTools.getNodeAsString( datasetElement, PRE_DWPVS + "Abstract/text()", nsContext, null );
326 Keywords[] keywords = getKeywords( XMLTools.getNodes( datasetElement, PRE_OWS + "Keywords", nsContext ) );
327 String[] crsStrings = XMLTools.getNodesAsStrings( datasetElement, PRE_DWPVS + "CRS/text()", nsContext );
328 List<CoordinateSystem> crsList = parseCoordinateSystems( crsStrings );
329
330 if ( parent == null ) { // root dataset
331 if ( crsList.size() == 0 || crsList.get( 0 ) == null ) {
332 throw new InvalidCapabilitiesException( Messages.getMessage( "WPVS_NO_TOPLEVEL_DATASET_CRS", title ) );
333 }
334 defaultCoordinateSystem = crsList.get( 0 );
335 }
336
337 String[] format = XMLTools.getRequiredNodesAsStrings( datasetElement, PRE_DWPVS + "Format/text()", nsContext );
338 // wgs84 == mandatory
339 Element boundingBoxElement = (Element) XMLTools.getRequiredNode( datasetElement, PRE_OWS + "WGS84BoundingBox",
340 nsContext );
341 Envelope wgs84BoundingBox = getWGS84BoundingBoxType( boundingBoxElement );
342
343 Envelope[] boundingBoxes = getBoundingBoxes( datasetElement, defaultCoordinateSystem );
344 Dimension[] dimensions = parseDimensions( datasetElement );
345 DataProvider dataProvider = parseDataProvider( datasetElement );
346 Identifier identifier = parseDatasetIdentifier( datasetElement, PRE_DWPVS + "Identifier" );
347 MetaData[] metaData = parseMetaData( datasetElement );
348 DatasetReference[] datasetRefs = parseDatasetReferences( datasetElement );
349 FeatureListReference[] featureListRefs = parseFeatureListReferences( datasetElement );
350 Style[] style = parseStyles( datasetElement );
351 double minScaleDenom = XMLTools.getNodeAsDouble( datasetElement, PRE_DWPVS + "MinimumScaleDenominator/text()",
352 nsContext, defaultMinScaleDonominator );
353
354 // update the smallestMinimalScaleDenomiator
355 if ( minScaleDenom < smallestMinimalScaleDenominator ) {
356 smallestMinimalScaleDenominator = minScaleDenom;
357 }
358
359 double maxScaleDenom = XMLTools.getNodeAsDouble( datasetElement, PRE_DWPVS + "MaximumScaleDenominator/text()",
360 nsContext, defaultMaxScaleDenominator );
361
362 if ( parent == null ) {// toplevel dataset sets the default minScaleDenominator
363 defaultMinScaleDonominator = minScaleDenom;
364 defaultMaxScaleDenominator = maxScaleDenom;
365 }
366
367 if ( minScaleDenom >= maxScaleDenom ) {
368 throw new InvalidCapabilitiesException( "MinimumScaleDenominator must be "
369 + "less than MaximumScaleDenominator!" );
370 }
371 CoordinateSystem currentCRS = defaultCoordinateSystem;
372 if ( crsList.size() > 0 && crsList.get( 0 ) != null ) {
373 currentCRS = crsList.get( 0 );
374 }
375 ElevationModel elevationModel = parseElevationModel( datasetElement, name, minimalWCS_DGMResolution,
376 currentCRS, defaultMinScaleDonominator,
377 defaultMaxScaleDenominator );
378 AbstractDataSource[] dataSources = parseAbstractDatasources( datasetElement, name, defaultMinScaleDonominator,
379 defaultMaxScaleDenominator, currentCRS );
380
381 // create new root dataset
382 Dataset dataset = new Dataset( queryable, opaque, noSubsets, fixedWidth, fixedHeight, name, title, abstract_,
383 keywords, crsList, format, wgs84BoundingBox, boundingBoxes, dimensions,
384 dataProvider, identifier, metaData, datasetRefs, featureListRefs, style,
385 minScaleDenom, maxScaleDenom, null, elevationModel, dataSources, parent );
386
387 // get child datasets
388 List<Element> nl = XMLTools.getElements( datasetElement, PRE_DWPVS + "Dataset", nsContext );
389 Dataset[] childDatasets = new Dataset[nl.size()];
390 for ( int i = 0; i < childDatasets.length; i++ ) {
391 childDatasets[i] = parseDataset( nl.get( i ), dataset, defaultCoordinateSystem, defaultMinScaleDonominator,
392 defaultMaxScaleDenominator, minimalWCS_DGMResolution );
393
394 }
395
396 // set child datasets
397 dataset.setDatasets( childDatasets );
398
399 return dataset;
400 }
401
402 /**
403 * Creates and returns a new <code>ElevationModel</code> object from the given <code>Element</code> and the parent
404 * <code>Dataset</code>.
405 *
406 * The OGC ElevationModel contains only a String. The Deegree ElevationModel additionally contains a complex
407 * dataSource.
408 *
409 * @param datasetElement
410 * @param parentName
411 * @return Returns the ElevationModel object.
412 * @throws XMLParsingException
413 * @throws OGCWebServiceException
414 * @throws InvalidParameterValueException
415 * @throws MissingParameterValueException
416 * @throws InvalidConfigurationException
417 */
418 private ElevationModel parseElevationModel( Element datasetElement, String parentName,
419 double minimalWCS_DGMResolution, CoordinateSystem defaultCRS,
420 double defaultMinScaleDenominator, double defaultMaxScaleDenominator )
421 throws XMLParsingException, MissingParameterValueException, InvalidParameterValueException,
422 OGCWebServiceException, InvalidConfigurationException {
423
424 Element elevationElement = null;
425 String name = null;
426 ElevationModel elevationModel = null;
427
428 elevationElement = (Element) XMLTools.getNode( datasetElement, PRE_DWPVS + "ElevationModel", nsContext );
429
430 AbstractDataSource[] dataSources = null;
431 if ( elevationElement != null ) {
432
433 name = XMLTools.getRequiredNodeAsString( elevationElement, PRE_DWPVS + "Name/text()", nsContext );
434
435 dataSources = parseAbstractDatasources( elevationElement, parentName, defaultMinScaleDenominator,
436 defaultMaxScaleDenominator, defaultCRS );
437 if ( dataSources.length < 1 ) {
438 throw new InvalidCapabilitiesException( "Each '" + elevationElement.getNodeName()
439 + "' must contain at least one data source!" );
440 }
441 if ( !Double.isNaN( minimalWCS_DGMResolution ) ) {
442 // little trick to know which dgm datasources have a configured minimal resolution,
443 // if the minimalWCS_DGMResolution is not set (e.g Double.nan) nothing has to be
444 // done (a value of 0d is presumed)
445 for ( AbstractDataSource source : dataSources ) {
446 if ( source.getServiceType() == AbstractDataSource.LOCAL_WCS
447 || source.getServiceType() == AbstractDataSource.REMOTE_WCS ) {
448 ( (LocalWCSDataSource) source ).setConfiguredMinimalDGMResolution( minimalWCS_DGMResolution );
449 }
450 }
451 }
452 }
453
454 elevationModel = new ElevationModel( name, dataSources );
455
456 return elevationModel;
457 }
458
459 /**
460 * Creates and returns a new array of <code>AbstractDataSource</code> objects from the given <code>Element</code>.
461 *
462 * If the objects are used within an ElevationModel object, they may be of the following types: LocalWCSDataSource,
463 * RemoteWCSDataSource, LocalWFSDataSource, RemoteWFSDataSource. If the objects are used within a Dataset object,
464 * they may additionaly be of the types: LocalWMSDataSource, RemoteWMSDataSource.
465 *
466 * @param element
467 * @return Returns a new array of AbstractDataSource objects.
468 * @throws XMLParsingException
469 * @throws OGCWebServiceException
470 * @throws InvalidConfigurationException
471 */
472 private AbstractDataSource[] parseAbstractDatasources( Element element, String parentName,
473 double defaultMinScaleDenominator,
474 double defaultMaxScaleDenominator,
475 CoordinateSystem defaultCRS )
476 throws XMLParsingException, OGCWebServiceException, InvalidConfigurationException {
477
478 List<Element> abstractDataSources = XMLTools.getElements( element, "*", nsContext );
479 List<AbstractDataSource> tempDataSources = new ArrayList<AbstractDataSource>( abstractDataSources.size() );
480
481 for ( Element dataSourceElement : abstractDataSources ) {
482
483 // String nodeName = dataSourceElement.getNodeName();
484 String nodeName = dataSourceElement.getLocalName();
485
486 if ( nodeName != null && nodeName.endsWith( "DataSource" ) ) {
487 QualifiedName pn = null;
488 if ( parentName != null ) {
489 pn = new QualifiedName( PRE_DWPVS, parentName, nsContext.getURI( PRE_DWPVS ) );
490 }
491 QualifiedName name = XMLTools.getNodeAsQualifiedName( dataSourceElement, PRE_DWPVS + "Name/text()",
492 nsContext, pn );
493
494 OWSCapabilities owsCapabilities = parseOWSCapabilities( dataSourceElement );
495
496 double minScaleDenom = XMLTools.getNodeAsDouble( dataSourceElement, PRE_DWPVS
497 + "MinimumScaleDenominator/text()",
498 nsContext, defaultMinScaleDenominator );
499
500 // update the smallestMinimalScaleDenomiator
501 if ( minScaleDenom < smallestMinimalScaleDenominator )
502 smallestMinimalScaleDenominator = minScaleDenom;
503
504 double maxScaleDenom = XMLTools.getNodeAsDouble( dataSourceElement, PRE_DWPVS
505 + "MaximumScaleDenominator/text()",
506 nsContext, defaultMaxScaleDenominator );
507
508 Surface validArea = parseValidArea( dataSourceElement, defaultCRS );
509 AbstractDataSource dataSource = null;
510
511 if ( nodeName.equals( "LocalWCSDataSource" ) || "RemoteWCSDataSource".equals( nodeName ) ) {
512 Element filterElement = (Element) XMLTools.getRequiredNode( dataSourceElement, PRE_DWPVS
513 + "FilterCondition",
514 nsContext );
515 GetCoverage getCoverage = parseWCSFilterCondition( filterElement );
516 Color[] transparentColors = parseTransparentColors( dataSourceElement );
517
518 if ( "RemoteWCSDataSource".equals( nodeName ) ) {
519 dataSource = new RemoteWCSDataSource( name, owsCapabilities, validArea, minScaleDenom,
520 maxScaleDenom, getCoverage, transparentColors );
521 LOG.logDebug( "created remote wcs with name: " + name );
522 } else {
523 dataSource = new LocalWCSDataSource( name, owsCapabilities, validArea, minScaleDenom,
524 maxScaleDenom, getCoverage, transparentColors );
525 LOG.logDebug( "created local wcs with name: " + name );
526 }
527 } else if ( "RemoteWFSDataSource".equals( nodeName ) || "LocalWFSDataSource".equals( nodeName ) ) {
528 Text geoPropNode = (Text) XMLTools.getRequiredNode( dataSourceElement, PRE_DWPVS
529 + "GeometryProperty/text()",
530 nsContext );
531 PropertyPath geometryProperty = parsePropertyPath( geoPropNode );
532
533 Element filterElement = (Element) XMLTools.getNode( dataSourceElement,
534 PRE_DWPVS + "FilterCondition/ogc:Filter",
535 nsContext );
536
537 int maxFeatures = XMLTools.getNodeAsInt( dataSourceElement, PRE_DWPVS + "MaxFeatures", nsContext,
538 -1 );
539
540 Filter filterCondition = null;
541 if ( filterElement != null ) {
542 filterCondition = AbstractFilter.buildFromDOM( filterElement, false );
543 }
544
545 // FeatureCollectionAdapter adapter = createFCAdapterFromAdapterClassName(
546 // dataSourceElement );
547
548 if ( "LocalWFSDataSource".equals( nodeName ) ) {
549 dataSource = new LocalWFSDataSource( name, owsCapabilities, validArea, minScaleDenom,
550 maxScaleDenom, geometryProperty, filterCondition,
551 maxFeatures );
552 LOG.logDebug( "created local wfs with name: " + name );
553 } else {
554 dataSource = new RemoteWFSDataSource( name, owsCapabilities, validArea, minScaleDenom,
555 maxScaleDenom, geometryProperty, filterCondition,
556 maxFeatures );
557 LOG.logDebug( "created remote wfs with name: " + name );
558 }
559 } else if ( nodeName.equals( "LocalWMSDataSource" ) ) {
560 if ( element.getNodeName().endsWith( "ElevationModel" ) ) {
561 throw new InvalidConfigurationException( "An ElevationModel cannot "
562 + "contain a LocalWMSDataSource!" );
563 }
564 Element filterElement = (Element) XMLTools.getRequiredNode( dataSourceElement, PRE_DWPVS
565 + "FilterCondition",
566 nsContext );
567 GetMap getMap = parseWMSFilterCondition( filterElement );
568
569 Color[] transparentColors = parseTransparentColors( dataSourceElement );
570
571 dataSource = new LocalWMSDataSource( name, owsCapabilities, validArea, minScaleDenom,
572 maxScaleDenom, getMap, transparentColors );
573 LOG.logDebug( "created local wms with name: " + name );
574
575 } else if ( nodeName.equals( "RemoteWMSDataSource" ) ) {
576 if ( element.getNodeName().endsWith( "ElevationModel" ) ) {
577 throw new InvalidConfigurationException( "An ElevationModel cannot "
578 + "contain a LocalWMSDataSource!" );
579 }
580 Element filterElement = (Element) XMLTools.getRequiredNode( dataSourceElement, PRE_DWPVS
581 + "FilterCondition",
582 nsContext );
583 GetMap getMap = parseWMSFilterCondition( filterElement );
584
585 Color[] transparentColors = parseTransparentColors( dataSourceElement );
586
587 dataSource = new RemoteWMSDataSource( name, owsCapabilities, validArea, minScaleDenom,
588 maxScaleDenom, getMap, transparentColors );
589 LOG.logDebug( "created remote wms with name: " + name );
590 } else {
591 throw new InvalidCapabilitiesException( "Unknown data source: '" + nodeName + "'" );
592 }
593
594 tempDataSources.add( dataSource );
595 }
596 }
597
598 AbstractDataSource[] dataSources = tempDataSources.toArray( new AbstractDataSource[tempDataSources.size()] );
599
600 return dataSources;
601 }
602
603 /**
604 * FIXME check content of StringBuffer and Map! This is an adapted copy from:
605 * org.deegree.ogcwebservices.wms.configuration#parseWMSFilterCondition(Node)
606 *
607 * Creates and returns a new <code>GetMap</code> object from the given <code>Element</code>.
608 *
609 * @param filterElement
610 * @return a partial wms GetMap request instance
611 * @throws XMLParsingException
612 */
613 private GetMap parseWMSFilterCondition( Element filterElement )
614 throws XMLParsingException {
615
616 GetMap getMap = null;
617
618 String wmsRequest = XMLTools.getRequiredNodeAsString( filterElement, PRE_DWPVS + "WMSRequest/text()", nsContext );
619
620 StringBuffer sd = new StringBuffer( 1000 );
621 sd.append( "REQUEST=GetMap&LAYERS=%default%&STYLES=&SRS=EPSG:4326&" );
622 sd.append( "BBOX=0,0,1,1&WIDTH=1&HEIGHT=1&FORMAT=%default%" );
623
624 Map<String, String> map1 = KVP2Map.toMap( sd.toString() );
625
626 Map<String, String> map2 = KVP2Map.toMap( wmsRequest );
627 if ( map2.get( "VERSION" ) == null && map2.get( "WMTVER" ) == null ) {
628 map2.put( "VERSION", "1.1.1" );
629 }
630 // if no service is set use WMS as default
631 if ( map2.get( "SERVICE" ) == null ) {
632 map2.put( "SERVICE", "WMS" );
633 }
634
635 map1.putAll( map2 );
636
637 String id = Long.toString( IDGenerator.getInstance().generateUniqueID() );
638 map1.put( "ID", id );
639 try {
640 getMap = GetMap.create( map1 );
641 } catch ( Exception e ) {
642 throw new XMLParsingException( "could not create GetMap from WMS FilterCondition", e );
643 }
644
645 return getMap;
646 }
647
648 /**
649 * FIXME check content of StringBuffer ! This is an adapted copy from:
650 * org.deegree.ogcwebservices.wms.configuration#parseWCSFilterCondition(Node)
651 *
652 * Creates and returns a new <code>GetCoverage</code> object from the given <code>Element</code>.
653 *
654 * @param filterElement
655 * @return a partial GetCoverage request
656 * @throws XMLParsingException
657 */
658 private GetCoverage parseWCSFilterCondition( Element filterElement )
659 throws XMLParsingException {
660
661 GetCoverage coverage = null;
662
663 String wcsRequest = XMLTools.getRequiredNodeAsString( filterElement, PRE_DWPVS + "WCSRequest/text()", nsContext );
664
665 StringBuffer sd = new StringBuffer( 1000 );
666 sd.append( "version=1.0.0&Coverage=%default%&CRS=EPSG:4326&BBOX=0,0,1,1" );
667 sd.append( "&Width=1&Height=1&Format=%default%&" );
668 sd.append( wcsRequest );
669
670 String id = "" + IDGenerator.getInstance().generateUniqueID();
671
672 try {
673 coverage = GetCoverage.create( id, sd.toString() );
674 } catch ( Exception e ) {
675 throw new XMLParsingException( "Could not create GetCoverage " + "from WPVS FilterCondition", e );
676 }
677
678 return coverage;
679 }
680
681 /**
682 * Creates and returns a new <code>OWSCapabilities</code> object from the given <code>Element</code>.
683 *
684 * @param element
685 * @return Returns a new OWSCapabilities object.
686 * @throws XMLParsingException
687 * @throws InvalidCapabilitiesException
688 */
689 private OWSCapabilities parseOWSCapabilities( Element element )
690 throws XMLParsingException, InvalidCapabilitiesException {
691
692 Element owsCapabilitiesElement = (Element) XMLTools.getRequiredNode( element, PRE_DWPVS + "OWSCapabilities",
693 nsContext );
694
695 String format = null;
696
697 // FIXME
698 // schema has onlineResourceType as not optional, so it should be mandatory.
699 // but in other examples onlineResource is never created with this onlineResourceType.
700 // therefore it gets omitted here, too.
701
702 // String onlineResourceType = XMLTools.getRequiredNodeAsString(
703 // owsCapabilitiesElement, PRE_DWPVS+"OnlineResource/@xlink:type", nsContext );
704
705 String onlineResourceURI = XMLTools.getRequiredNodeAsString( owsCapabilitiesElement,
706 PRE_DWPVS + "OnlineResource/@xlink:href",
707 nsContext );
708
709 URL onlineResource;
710 try {
711 onlineResource = resolve( onlineResourceURI );
712 } catch ( MalformedURLException e ) {
713 throw new InvalidCapabilitiesException( onlineResourceURI + " does not represent a valid URL: "
714 + e.getMessage() );
715 }
716 LOG.logDebug( "found following onlineResource: " + onlineResource );
717 return new OWSCapabilities( format, onlineResource );
718
719 // FIXME
720 // if onlineResourceType is going to be used, the returned new OnlineResource should be
721 // created with different constructor:
722 // return new OWSCapabilities( format, onlineResourceType, onlineResource );
723 }
724
725 /**
726 * Creates and returns a new <code>Geometry</code> object from the given Element.
727 *
728 * @param dataSource
729 * @return Returns a new Geometry object.
730 * @throws XMLParsingException
731 * @throws InvalidConfigurationException
732 */
733 private Surface parseValidArea( Element dataSource, CoordinateSystem defaultCRS )
734 throws XMLParsingException, InvalidConfigurationException {
735 List<Element> nl = XMLTools.getElements( dataSource, PRE_DWPVS + "ValidArea/*", nsContext );
736 if ( nl.size() == 0 ) {
737 return null;
738 }
739
740 if ( nl.size() > 1 ) {
741 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_NUMBER_OF_VALID_AREAS", GMLNS.toASCIIString(),
742 dataSource.getLocalName() ) );
743 return null;
744 }
745 Surface validArea = null;
746 Element firsElement = nl.get( 0 );
747 if ( firsElement.getNamespaceURI().equals( GMLNS.toASCIIString() ) ) {
748 try {
749 String srsName = XMLTools.getNodeAsString( firsElement, "@srsName", nsContext, null );
750 if ( srsName == null ) {
751 srsName = defaultCRS.getFormattedString();
752 }
753
754 Geometry geom = GMLGeometryAdapter.wrap( firsElement, srsName );
755 if ( !( geom instanceof Surface ) ) {
756 throw new InvalidConfigurationException( Messages.getMessage( "WPVS_WRONG_GEOMTERY_VALID_AREA",
757 dataSource.getLocalName() ) );
758 }
759 validArea = (Surface) geom;
760 } catch ( GeometryException e ) {
761 throw new InvalidConfigurationException( Messages.getMessage( "WPVS_WRONG_GEOMTERY_VALID_AREA",
762 dataSource.getLocalName() )
763 + "\n" + e.getMessage(),
764
765 e );
766 }
767
768 } else if ( firsElement.getNamespaceURI().equals( CommonNamespaces.OWSNS ) ) {
769 try {
770 if ( !"BoundingBox".equals( firsElement.getLocalName() ) ) {
771 throw new InvalidConfigurationException( Messages.getMessage( "WPVS_WRONG_GEOMTERY_VALID_AREA",
772 dataSource.getLocalName() ) );
773 }
774 Envelope env = parseBoundingBox( firsElement, null );
775 validArea = GeometryFactory.createSurface( env, env.getCoordinateSystem() );
776 } catch ( GeometryException e ) {
777 throw new InvalidConfigurationException( Messages.getMessage( "WPVS_WRONG_GEOMTERY_VALID_AREA",
778 dataSource.getLocalName() )
779 + "\n" + e.getMessage(), e );
780 } catch ( InvalidParameterValueException e ) {
781 throw new InvalidConfigurationException( Messages.getMessage( "WPVS_WRONG_GEOMTERY_VALID_AREA",
782 dataSource.getLocalName() )
783 + "\n" + e.getMessage(), e );
784 }
785 } else {
786 LOG.logWarning( Messages.getMessage( "WPVS_WRONG_GEOMTERY_VALID_AREA", dataSource.getLocalName() ) );
787 return null;
788 }
789 return validArea;
790 }
791
792 /**
793 * Creates and returns a new array of <code>Color</code> objects from the given Element.
794 *
795 * @param dataSourceElement
796 * @return Returns a new array of Color objects.
797 * @throws XMLParsingException
798 */
799 private Color[] parseTransparentColors( Element dataSourceElement )
800 throws XMLParsingException {
801
802 List<Element> colorList = XMLTools.getElements( dataSourceElement, PRE_DWPVS + "TransparentColors/" + PRE_DWPVS
803 + "Color", nsContext );
804
805 Color[] transparentColors = null;
806 if ( colorList != null ) {
807 transparentColors = new Color[colorList.size()];
808
809 for ( int i = 0; i < transparentColors.length; i++ ) {
810
811 Element colorElement = colorList.get( i );
812 String color = XMLTools.getRequiredNodeAsString( colorElement, "text()", nsContext );
813
814 transparentColors[i] = Color.decode( color );
815 }
816 }
817
818 return transparentColors;
819 }
820
821 }