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