001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wms/configuration/WMSConfigurationDocument.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstraße 19
030 53177 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Prof. Dr. Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: greve@giub.uni-bonn.de
041
042 ---------------------------------------------------------------------------*/
043 package org.deegree.ogcwebservices.wms.configuration;
044
045 import java.awt.Color;
046 import java.io.IOException;
047 import java.net.MalformedURLException;
048 import java.net.URI;
049 import java.net.URL;
050 import java.util.ArrayList;
051 import java.util.Arrays;
052 import java.util.HashMap;
053 import java.util.List;
054 import java.util.Map;
055
056 import javax.xml.transform.TransformerException;
057
058 import org.deegree.datatypes.QualifiedName;
059 import org.deegree.enterprise.Proxy;
060 import org.deegree.framework.log.ILogger;
061 import org.deegree.framework.log.LoggerFactory;
062 import org.deegree.framework.util.BootLogger;
063 import org.deegree.framework.util.IDGenerator;
064 import org.deegree.framework.util.KVP2Map;
065 import org.deegree.framework.util.StringTools;
066 import org.deegree.framework.xml.InvalidConfigurationException;
067 import org.deegree.framework.xml.XMLFragment;
068 import org.deegree.framework.xml.XMLParsingException;
069 import org.deegree.framework.xml.XMLTools;
070 import org.deegree.framework.xml.XSLTDocument;
071 import org.deegree.i18n.Messages;
072 import org.deegree.model.crs.UnknownCRSException;
073 import org.deegree.model.metadata.iso19115.OnlineResource;
074 import org.deegree.model.spatialschema.Envelope;
075 import org.deegree.model.spatialschema.GMLGeometryAdapter;
076 import org.deegree.model.spatialschema.Geometry;
077 import org.deegree.model.spatialschema.GeometryException;
078 import org.deegree.ogcbase.CommonNamespaces;
079 import org.deegree.ogcwebservices.OGCWebService;
080 import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
081 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
082 import org.deegree.ogcwebservices.wcs.WCService;
083 import org.deegree.ogcwebservices.wcs.configuration.WCSConfiguration;
084 import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
085 import org.deegree.ogcwebservices.wfs.RemoteWFService;
086 import org.deegree.ogcwebservices.wfs.WFServiceFactory;
087 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
088 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
089 import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration;
090 import org.deegree.ogcwebservices.wfs.configuration.WFSConfigurationDocument;
091 import org.deegree.ogcwebservices.wfs.operation.Query;
092 import org.deegree.ogcwebservices.wms.RemoteWMService;
093 import org.deegree.ogcwebservices.wms.capabilities.Attribution;
094 import org.deegree.ogcwebservices.wms.capabilities.AuthorityURL;
095 import org.deegree.ogcwebservices.wms.capabilities.DataURL;
096 import org.deegree.ogcwebservices.wms.capabilities.Dimension;
097 import org.deegree.ogcwebservices.wms.capabilities.Extent;
098 import org.deegree.ogcwebservices.wms.capabilities.FeatureListURL;
099 import org.deegree.ogcwebservices.wms.capabilities.Identifier;
100 import org.deegree.ogcwebservices.wms.capabilities.Layer;
101 import org.deegree.ogcwebservices.wms.capabilities.LayerBoundingBox;
102 import org.deegree.ogcwebservices.wms.capabilities.LegendURL;
103 import org.deegree.ogcwebservices.wms.capabilities.ScaleHint;
104 import org.deegree.ogcwebservices.wms.capabilities.Style;
105 import org.deegree.ogcwebservices.wms.capabilities.StyleSheetURL;
106 import org.deegree.ogcwebservices.wms.capabilities.StyleURL;
107 import org.deegree.ogcwebservices.wms.capabilities.UserDefinedSymbolization;
108 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
109 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
110 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory;
111 import org.deegree.ogcwebservices.wms.operation.GetMap;
112 import org.deegree.owscommon_new.OperationsMetadata;
113 import org.deegree.owscommon_new.ServiceIdentification;
114 import org.deegree.owscommon_new.ServiceProvider;
115 import org.w3c.dom.Element;
116 import org.w3c.dom.Node;
117 import org.xml.sax.SAXException;
118
119 /**
120 * <code>WMSConfigurationDocument</code> is the parser class for a standard 1.1.1 WMS
121 * configuration document, ie, a capabilities document enriched by deegree parameters.
122 *
123 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
124 * @author last edited by: $Author: apoth $
125 *
126 * @version 2.0, $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $
127 *
128 * @since 2.0
129 */
130 public class WMSConfigurationDocument extends WMSCapabilitiesDocument {
131
132 private static final long serialVersionUID = 2320990982989322325L;
133
134 protected static final URI DEEGREEWMSNS = CommonNamespaces.DEEGREEWMS;
135
136 private static final String XML_TEMPLATE = "WMSConfigurationTemplate.xml";
137
138 private static final String XSLT_TEMPLATE_NAME = "WMSConfigurationTransform.xsl";
139
140 private static XSLTDocument XSLT_TEMPLATE;
141
142 private static Map<URL, OGCCapabilities> capaCache = new HashMap<URL, OGCCapabilities>();
143
144 private static final ILogger LOG = LoggerFactory.getLogger( WMSConfigurationDocument.class );
145
146 private static final QualifiedName DEFAULT_GEO_PROP = new QualifiedName(
147 "app",
148 "GEOM",
149 CommonNamespaces.buildNSURI( "http://www.deegree.org/app" ) );
150
151 static {
152 XSLT_TEMPLATE = new XSLTDocument();
153 try {
154 XSLT_TEMPLATE.load( WMSConfigurationDocument.class.getResource( XSLT_TEMPLATE_NAME ) );
155 } catch ( Exception e ) {
156 BootLogger.logError( "Error loading XSLT sheet in WMSConfigurationDocument.", e );
157 }
158 }
159
160 /**
161 *
162 */
163 public static void resetCapabilitiesCache() {
164 capaCache.clear();
165 }
166
167 /**
168 * Creates a skeleton capabilities document that contains the mandatory elements only.
169 *
170 * @throws IOException
171 * @throws SAXException
172 */
173 @Override
174 public void createEmptyDocument()
175 throws IOException, SAXException {
176 URL url = WMSConfigurationDocument.class.getResource( XML_TEMPLATE );
177 if ( url == null ) {
178 throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." );
179 }
180 load( url );
181 }
182
183 /**
184 * Creates a class representation of the document.
185 *
186 * @return class representation of the configuration document
187 * @throws InvalidConfigurationException
188 */
189 public WMSConfiguration parseConfiguration()
190 throws InvalidConfigurationException {
191
192 try {
193 // transform document to fill missing elements and attributes with
194 // default values
195 XMLFragment frag = XSLT_TEMPLATE.transform( this );
196 this.setRootElement( frag.getRootElement() );
197 } catch ( TransformerException e ) {
198 String msg = Messages.getMessage( "WMS_CONFIGURATION_TRANSFORM" );
199 LOG.logError( msg, e );
200 throw new InvalidConfigurationException( msg, e );
201 }
202
203 ServiceIdentification serviceIdentification = null;
204 ServiceProvider serviceProvider = null;
205 OperationsMetadata metadata = null;
206 Layer layer = null;
207 UserDefinedSymbolization uds = null;
208 WMSDeegreeParams params = null;
209 Element root = getRootElement();
210 String version = root.getAttribute( "version" );
211 String updateSeq = root.getAttribute( "updateSequence" );
212 List<String> exceptions;
213
214 try {
215 Node node = XMLTools.getRequiredNode( getRootElement(), "./deegreewms:DeegreeParam", nsContext );
216 params = parseDeegreeParams( node );
217
218 serviceIdentification = parseServiceIdentification();
219 serviceProvider = parseServiceProvider();
220 metadata = parseOperationsMetadata();
221
222 Element exceptionElement = XMLTools.getRequiredElement( getRootElement(), "Capability/Exception", nsContext );
223 exceptions = parseExceptionFormats( exceptionElement );
224
225 uds = parseUserDefinedSymbolization();
226 Element layerElem = (Element) XMLTools.getRequiredNode( getRootElement(), "./Capability/Layer", nsContext );
227 layer = parseLayers( layerElem, null, null );
228
229 } catch ( XMLParsingException e ) {
230 e.printStackTrace();
231 throw new InvalidConfigurationException( e.getMessage() + StringTools.stackTraceToString( e ) );
232 } catch ( MalformedURLException e ) {
233 throw new InvalidConfigurationException( e.getMessage() + " - " + StringTools.stackTraceToString( e ) );
234 } catch ( UnknownCRSException e ) {
235 throw new InvalidConfigurationException( e.getMessage() + " - " + StringTools.stackTraceToString( e ) );
236 }
237
238 WMSConfiguration wmsConfiguration = new WMSConfiguration( version, updateSeq, serviceIdentification,
239 serviceProvider, uds, metadata, layer, params,
240 getSystemId(), exceptions );
241
242 return wmsConfiguration;
243 }
244
245 /**
246 * Creates a class representation of the <code>deegreeParams</code>- section.
247 *
248 * @param root
249 *
250 * @return the deegree params
251 * @throws XMLParsingException
252 * @throws MalformedURLException
253 */
254 public WMSDeegreeParams parseDeegreeParams( Node root )
255 throws XMLParsingException, MalformedURLException {
256
257 Element elem = (Element) XMLTools.getRequiredNode( root, "./deegreewms:DefaultOnlineResource", nsContext );
258 OnlineResource ol = parseOnLineResource( elem );
259 int cache = XMLTools.getNodeAsInt( root, "./deegreewms:CacheSize", nsContext, 100 );
260 int maxLifeTime = XMLTools.getNodeAsInt( root, "./deegreewms:MaxLifeTime", nsContext, 3600 );
261 int reqTimeLimit = XMLTools.getNodeAsInt( root, "./deegreewms:RequestTimeLimit", nsContext, 15 );
262 reqTimeLimit *= 1000;
263 double mapQuality = XMLTools.getNodeAsDouble( root, "./deegreewms:MapQuality", nsContext, 0.95 );
264 int maxMapWidth = XMLTools.getNodeAsInt( root, "./deegreewms:MaxMapWidth", nsContext, 1000 );
265 int maxMapHeight = XMLTools.getNodeAsInt( root, "./deegreewms:MaxMapHeight", nsContext, 1000 );
266 int featureInfoRadius = XMLTools.getNodeAsInt( root, "./deegreewms:FeatureInfoRadius", nsContext, 5 );
267 String copyright = XMLTools.getNodeAsString( root, "./deegreewms:Copyright", nsContext, "" );
268
269 URL dtdLocation = null;
270 if ( XMLTools.getNode( root, "deegreewms:DTDLocation", nsContext ) != null ) {
271 elem = (Element) XMLTools.getRequiredNode( root, "./deegreewms:DTDLocation/deegreewms:OnlineResource",
272 nsContext );
273 OnlineResource olr = parseOnLineResource( elem );
274 dtdLocation = olr.getLinkage().getHref();
275 } else {
276 dtdLocation = new URL( "http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd" );
277 }
278
279 URL featureSchemaLocation = null;
280 String featureSchemaNamespace = null;
281 if ( XMLTools.getNode( root, "deegreewms:FeatureInfoSchema", nsContext ) != null ) {
282 featureSchemaNamespace = XMLTools.getRequiredNodeAsString(
283 root,
284 "deegreewms:FeatureInfoSchema/deegreewms:Namespace",
285 nsContext );
286 elem = (Element) XMLTools.getRequiredNode( root, "deegreewms:FeatureInfoSchema/deegreewms:OnlineResource",
287 nsContext );
288 OnlineResource link = parseOnLineResource( elem );
289 featureSchemaLocation = link.getLinkage().getHref();
290 }
291
292 boolean antiAliased = XMLTools.getNodeAsBoolean( root, "./deegreewms:AntiAliased", nsContext, true );
293
294 Proxy proxy = parseProxy( root );
295
296 List<String> supportedVersions = parseSupportedVersions( root );
297
298 WMSDeegreeParams deegreeParams = new WMSDeegreeParams( cache, maxLifeTime, reqTimeLimit, (float) mapQuality,
299 ol, maxMapWidth, maxMapHeight, antiAliased,
300 featureInfoRadius, copyright, null, dtdLocation, proxy,
301 supportedVersions, featureSchemaLocation,
302 featureSchemaNamespace );
303
304 return deegreeParams;
305 }
306
307 // returns the list of supported versions
308 private List<String> parseSupportedVersions( Node root )
309 throws XMLParsingException {
310
311 String[] versions = XMLTools.getNodesAsStrings( root, "./deegreewms:SupportedVersion", nsContext );
312
313 if ( versions != null )
314 return Arrays.asList( versions );
315
316 return new ArrayList<String>();
317
318 }
319
320 /**
321 * @param root
322 * @return the proxy
323 * @throws XMLParsingException
324 */
325 private Proxy parseProxy( Node root )
326 throws XMLParsingException {
327
328 Proxy proxy = null;
329 Node pro = XMLTools.getNode( root, "./deegreewms:Proxy", nsContext );
330 if ( pro != null ) {
331 String proxyHost = XMLTools.getRequiredNodeAsString( pro, "./@proxyHost", nsContext );
332 String proxyPort = XMLTools.getRequiredNodeAsString( pro, "./@proxyPort", nsContext );
333 proxy = new Proxy( proxyHost, proxyPort );
334 }
335
336 return proxy;
337 }
338
339 /**
340 * returns the layers offered by the WMS
341 *
342 * @throws XMLParsingException
343 * @throws UnknownCRSException
344 */
345 @Override
346 protected Layer parseLayers( Element layerElem, Layer parent, ScaleHint scaleHint )
347 throws XMLParsingException, UnknownCRSException {
348
349 boolean queryable = XMLTools.getNodeAsBoolean( layerElem, "./@queryable", nsContext, false );
350 int cascaded = XMLTools.getNodeAsInt( layerElem, "./@cascaded", nsContext, 0 );
351 boolean opaque = XMLTools.getNodeAsBoolean( layerElem, "./@opaque", nsContext, false );
352 boolean noSubsets = XMLTools.getNodeAsBoolean( layerElem, "./@noSubsets", nsContext, false );
353 int fixedWidth = XMLTools.getNodeAsInt( layerElem, "./@fixedWidth", nsContext, 0 );
354 int fixedHeight = XMLTools.getNodeAsInt( layerElem, "./@fixedHeight", nsContext, 0 );
355 String name = XMLTools.getNodeAsString( layerElem, "./Name", nsContext, null );
356 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Title", nsContext );
357 String layerAbstract = XMLTools.getNodeAsString( layerElem, "./Abstract", nsContext, null );
358 String[] keywords = XMLTools.getNodesAsStrings( layerElem, "./KeywordList/Keyword", nsContext );
359 String[] srs = XMLTools.getNodesAsStrings( layerElem, "./SRS", nsContext );
360
361 List<Element> nl = XMLTools.getElements( layerElem, "./BoundingBox", nsContext );
362 // TODO
363 // substitue with Envelope
364 LayerBoundingBox[] bboxes = null;
365 if ( nl.size() == 0 && parent != null ) {
366 // inherit BoundingBoxes from parent layer
367 bboxes = parent.getBoundingBoxes();
368 } else {
369 bboxes = parseLayerBoundingBoxes( nl );
370 }
371
372 Element llBox = (Element) XMLTools.getNode( layerElem, "./LatLonBoundingBox", nsContext );
373 Envelope llBoundingBox = null;
374 if ( llBox == null && parent != null ) {
375 // inherit LatLonBoundingBox parent layer
376 llBoundingBox = parent.getLatLonBoundingBox();
377 } else {
378 llBoundingBox = parseLatLonBoundingBox( llBox );
379 }
380
381 Dimension[] dimensions = parseDimensions( layerElem );
382 Extent[] extents = parseExtents( layerElem );
383
384 Attribution attribution = parseAttribution( layerElem );
385
386 AuthorityURL[] authorityURLs = parseAuthorityURLs( layerElem );
387
388 MetadataURL[] metadataURLs = parseMetadataURLs( layerElem );
389
390 DataURL[] dataURLs = parseDataURL( layerElem );
391
392 Identifier[] identifiers = parseIdentifiers( layerElem );
393
394 FeatureListURL[] featureListURLs = parseFeatureListURL( layerElem );
395
396 Style[] styles = parseStyles( layerElem );
397
398 scaleHint = parseScaleHint( layerElem, scaleHint );
399
400 AbstractDataSource[] ds = parseDataSources( layerElem, name, scaleHint );
401
402 Layer layer = new Layer( queryable, cascaded, opaque, noSubsets, fixedWidth, fixedHeight, name, title,
403 layerAbstract, llBoundingBox, attribution, scaleHint, keywords, srs, bboxes,
404 dimensions, extents, authorityURLs, identifiers, metadataURLs, dataURLs,
405 featureListURLs, styles, null, ds, parent );
406
407 // get Child layers
408 nl = XMLTools.getElements( layerElem, "./Layer", nsContext );
409 Layer[] layers = new Layer[nl.size()];
410 for ( int i = 0; i < layers.length; i++ ) {
411 layers[i] = parseLayers( nl.get( i ), layer, scaleHint );
412 }
413
414 // set child layers
415 layer.setLayer( layers );
416
417 return layer;
418 }
419
420 /**
421 *
422 * @param layerElem
423 * @return the data sources
424 * @throws XMLParsingException
425 */
426 protected AbstractDataSource[] parseDataSources( Element layerElem, String layerName, ScaleHint scaleHint )
427 throws XMLParsingException {
428
429 List<Node> nl = XMLTools.getNodes( layerElem, "./deegreewms:DataSource", nsContext );
430
431 AbstractDataSource[] ds = new AbstractDataSource[nl.size()];
432 for ( int i = 0; i < ds.length; i++ ) {
433 boolean failOnEx = XMLTools.getNodeAsBoolean( nl.get( i ), "./@failOnException", nsContext, true );
434 boolean queryable = XMLTools.getNodeAsBoolean( nl.get( i ), "./@queryable", nsContext, false );
435 QualifiedName name = XMLTools.getNodeAsQualifiedName( nl.get( i ), "./deegreewms:Name/text()", nsContext,
436 new QualifiedName( layerName ) );
437 String stype = XMLTools.getRequiredNodeAsString( nl.get( i ), "./deegreewms:Type", nsContext );
438
439 int reqTimeLimit = XMLTools.getNodeAsInt( nl.get( i ), "./deegreewms:RequestTimeLimit/text()", nsContext,
440 30 );
441
442 scaleHint = parseDSScaleHint( (Element) nl.get( i ), scaleHint );
443
444 String s = "./deegreewms:OWSCapabilities/deegreewms:OnlineResource";
445 Node node = XMLTools.getRequiredNode( nl.get( i ), s, nsContext );
446
447 URL url = parseOnLineResource( (Element) node ).getLinkage().getHref();
448
449 Geometry validArea = parseValidArea( nl.get( i ) );
450
451 try {
452 if ( "LOCALWFS".equals( stype ) ) {
453 ds[i] = createLocalWFSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint,
454 validArea, reqTimeLimit );
455 } else if ( "LOCALWCS".equals( stype ) ) {
456 ds[i] = createLocalWCSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint,
457 validArea, reqTimeLimit );
458 } else if ( "REMOTEWFS".equals( stype ) ) {
459 ds[i] = createRemoteWFSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint,
460 validArea, reqTimeLimit );
461 } else if ( "REMOTEWCS".equals( stype ) ) {
462 // int type = AbstractDataSource.REMOTEWCS;
463 // GetCoverage getCoverage =
464 parseWCSFilterCondition( nl.get( i ) );
465 // Color[] colors =
466 parseTransparentColors( nl.get( i ) );
467 // TODO
468 throw new XMLParsingException( "REMOTEWCS is not supported yet!" );
469 } else if ( "REMOTEWMS".equals( stype ) ) {
470 ds[i] = createRemoteWMSDataSource( nl.get( i ), failOnEx, queryable, name, url, scaleHint,
471 validArea, reqTimeLimit );
472 } else {
473 throw new XMLParsingException( "invalid DataSource type: " + stype + " defined "
474 + "in deegree WMS configuration for DataSource: " + name );
475 }
476 } catch ( Exception e ) {
477 LOG.logError( e.getMessage(), e );
478 throw new XMLParsingException( "could not create service instance for WMS " + "datasource: " + name, e );
479 }
480 }
481
482 return ds;
483 }
484
485 /**
486 * parses the ScaleHint for a Datasource
487 *
488 * @param layerElem
489 * @param scaleHint
490 * @return the scale hint for the datasource
491 * @throws XMLParsingException
492 */
493 protected ScaleHint parseDSScaleHint( Element layerElem, ScaleHint scaleHint )
494 throws XMLParsingException {
495
496 Node scNode = XMLTools.getNode( layerElem, "./deegreewms:ScaleHint", nsContext );
497 if ( scNode != null ) {
498 double mn = XMLTools.getNodeAsDouble( scNode, "./@min", nsContext, 0 );
499 double mx = XMLTools.getNodeAsDouble( scNode, "./@max", nsContext, Double.MAX_VALUE );
500 scaleHint = new ScaleHint( mn, mx );
501 }
502
503 if ( scaleHint == null ) {
504 // set default value to avoid NullPointerException
505 // when accessing a layers scalehint
506 scaleHint = new ScaleHint( 0, Double.MAX_VALUE );
507 }
508
509 return scaleHint;
510 }
511
512 /**
513 * returns the area a data source is valid. If the optional element <ValidArea>is not defined in
514 * the configuration <code>null</code>.
515 *
516 * @param node
517 * @return the geometry
518 * @throws Exception
519 */
520 private Geometry parseValidArea( Node node )
521 throws XMLParsingException {
522
523 Geometry geom = null;
524
525 List<Node> nl = XMLTools.getNodes( node, "./deegreewms:ValidArea/*", nsContext );
526 if ( node != null ) {
527
528 try {
529 for ( int i = 0; i < nl.size(); i++ ) {
530
531 if ( nl.get( 0 ).getNamespaceURI().equals( GMLNS.toString() ) ) {
532
533 geom = GMLGeometryAdapter.wrap( (Element) nl.get( 0 ), null );
534 break;
535 }
536 }
537 } catch ( GeometryException e ) {
538 e.printStackTrace();
539 throw new XMLParsingException( "couldn't parse/create valid aera of a datasource", e );
540 }
541 }
542
543 return geom;
544 }
545
546 /**
547 * @param vendor
548 * @return the parsed list
549 * @throws XMLParsingException
550 */
551 static List<String> parsePassedParameters( Node vendor )
552 throws XMLParsingException {
553 List<String> passedParameters = new ArrayList<String>( 10 );
554
555 if ( vendor == null ) {
556 return passedParameters;
557 }
558
559 List<Node> nl = XMLTools.getNodes( vendor, "deegreewms:PassedVendorspecificParameter/deegreewms:Name",
560 nsContext );
561
562 for ( Object obj : nl ) {
563 passedParameters.add( ( (Node) obj ).getTextContent().toUpperCase() );
564 }
565
566 return passedParameters;
567 }
568
569 /**
570 * @param vendor
571 * @return the parsed map
572 * @throws XMLParsingException
573 */
574 static Map<String, String> parseAddedParameters( Node vendor )
575 throws XMLParsingException {
576 Map<String, String> addedParameters = new HashMap<String, String>( 10 );
577
578 if ( vendor == null ) {
579 return addedParameters;
580 }
581
582 List<Node> nl = XMLTools.getNodes(
583 vendor,
584 "deegreewms:AddedVendorspecificParameter/deegreewms:VendorspecificParameter",
585 nsContext );
586
587 for ( Object obj : nl ) {
588 String pName = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewms:Name", nsContext );
589 String pValue = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewms:Value", nsContext );
590
591 addedParameters.put( pName, pValue );
592 }
593 return addedParameters;
594 }
595
596 /**
597 * @param node
598 * @param failOnEx
599 * @param queryable
600 * @param name
601 * @param geoProp
602 * @param url
603 * @param scaleHint
604 * @throws Exception
605 */
606 private RemoteWMSDataSource createRemoteWMSDataSource( Node node, boolean failOnEx, boolean queryable,
607 QualifiedName name, URL url, ScaleHint scaleHint,
608 Geometry validArea, int reqTimeLimit )
609 throws Exception {
610 int type = AbstractDataSource.REMOTEWMS;
611
612 String s = "./deegreewms:FeatureInfoTransformation/deegreewms:OnlineResource";
613 Node fitNode = XMLTools.getNode( node, s, nsContext );
614 URL fitURL = null;
615 if ( fitNode != null ) {
616 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref();
617 }
618
619 GetMap getMap = parseWMSFilterCondition( node );
620 Color[] colors = parseTransparentColors( node );
621 WMSCapabilities wCapa = null;
622 if ( capaCache.get( url ) != null ) {
623 wCapa = (WMSCapabilities) capaCache.get( url );
624 } else {
625 WMSCapabilitiesDocument doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( url );
626 LOG.logDebug( "Fetching remote WMS capabilities from URL " + url + " succeeded." );
627 wCapa = (WMSCapabilities) doc.parseCapabilities();
628 capaCache.put( url, wCapa );
629 }
630 OGCWebService ows = new RemoteWMService( wCapa );
631
632 // parse added/passed parameter map/list
633 Node vendor = XMLTools.getNode( node,
634 "deegreewms:FilterCondition/deegreewms:VendorspecificParameterDefinition",
635 nsContext );
636
637 List<String> passedParameters = parsePassedParameters( vendor );
638 Map<String, String> addedParameters = parseAddedParameters( vendor );
639
640 return new RemoteWMSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getMap,
641 colors, fitURL, reqTimeLimit, passedParameters, addedParameters );
642 }
643
644 /**
645 * @param node
646 * @param failOnEx
647 * @param queryable
648 * @param name
649 * @param geoProp
650 * @param url
651 * @param scaleHint
652 * @throws Exception
653 */
654 private RemoteWFSDataSource createRemoteWFSDataSource( Node node, boolean failOnEx, boolean queryable,
655 QualifiedName name, URL url, ScaleHint scaleHint,
656 Geometry validArea, int reqTimeLimit )
657 throws Exception {
658 int type = AbstractDataSource.REMOTEWFS;
659 String s = "./deegreewms:FeatureInfoTransformation/deegreewms:OnlineResource";
660 Node fitNode = XMLTools.getNode( node, s, nsContext );
661 URL fitURL = null;
662 if ( fitNode != null ) {
663 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref();
664 }
665 Query query = parseWFSFilterCondition( node );
666
667 WFSCapabilities wfsCapa = null;
668 if ( capaCache.get( url ) != null ) {
669 wfsCapa = (WFSCapabilities) capaCache.get( url );
670 } else {
671 WFSCapabilitiesDocument wfsDoc = new WFSCapabilitiesDocument();
672 wfsDoc.load( url );
673 wfsCapa = (WFSCapabilities) wfsDoc.parseCapabilities();
674 capaCache.put( url, wfsCapa );
675 }
676 OGCWebService ows = new RemoteWFService( wfsCapa );
677 // OGCWebService ows = null;
678
679 Node geoPropNode = XMLTools.getNode( node, "deegreewms:GeometryProperty/text()", nsContext );
680 QualifiedName geoProp = DEFAULT_GEO_PROP;
681 if ( geoPropNode != null ) {
682 geoProp = parseQualifiedName( geoPropNode );
683 }
684
685 return new RemoteWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea,
686 query, fitURL, reqTimeLimit );
687
688 }
689
690 /**
691 * @param node
692 * @param failOnEx
693 * @param queryable
694 * @param name
695 * @param geoProp
696 * @param url
697 * @param scaleHint
698 * @throws Exception
699 */
700 private LocalWCSDataSource createLocalWCSDataSource( Node node, boolean failOnEx, boolean queryable,
701 QualifiedName name, URL url, ScaleHint scaleHint,
702 Geometry validArea, int reqTimeLimit )
703 throws Exception {
704 int type = AbstractDataSource.LOCALWCS;
705 GetCoverage getCoverage = parseWCSFilterCondition( node );
706 Color[] colors = parseTransparentColors( node );
707 WCSConfiguration configuration = null;
708 if ( capaCache.get( url ) != null ) {
709 configuration = (WCSConfiguration) capaCache.get( url );
710 } else {
711 configuration = WCSConfiguration.create( url );
712 capaCache.put( url, configuration );
713 }
714
715 OGCWebService ows = new WCService( configuration );
716
717 return new LocalWCSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getCoverage,
718 colors, reqTimeLimit );
719 }
720
721 /**
722 * @param node
723 * @param failOnEx
724 * @param queryable
725 * @param name
726 * @param geoProp
727 * @param url
728 * @param scaleHint
729 * @throws Exception
730 */
731 private LocalWFSDataSource createLocalWFSDataSource( Node node, boolean failOnEx, boolean queryable,
732 QualifiedName name, URL url, ScaleHint scaleHint,
733 Geometry validArea, int reqTimeLimit )
734 throws Exception {
735 int type = AbstractDataSource.LOCALWFS;
736 String s = "./deegreewms:FeatureInfoTransformation/deegreewms:OnlineResource";
737 Node fitNode = XMLTools.getNode( node, s, nsContext );
738 URL fitURL = null;
739 if ( fitNode != null ) {
740 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref();
741 }
742 Query query = parseWFSFilterCondition( node );
743 WFSConfiguration wfsCapa = null;
744 if ( capaCache.get( url ) != null ) {
745 wfsCapa = (WFSConfiguration) capaCache.get( url );
746 } else {
747 WFSConfigurationDocument wfsDoc = new WFSConfigurationDocument();
748 wfsDoc.load( url );
749 wfsCapa = wfsDoc.getConfiguration();
750 // wfsCapa = new WFSCapabilitiesDocument( url ).createCapabilities();
751 capaCache.put( url, wfsCapa );
752 }
753 // OGCWebService ows = WFServiceFactory.getUncachedService( wfsCapa );
754 OGCWebService ows = WFServiceFactory.createInstance( wfsCapa );
755
756 Node geoPropNode = XMLTools.getNode( node, "deegreewms:GeometryProperty/text()", nsContext );
757 QualifiedName geoProp = DEFAULT_GEO_PROP;
758 if ( geoPropNode != null ) {
759 geoProp = parseQualifiedName( geoPropNode );
760 }
761
762 LOG.logDebug( "geometry property", geoProp );
763
764 return new LocalWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea, query,
765 fitURL, reqTimeLimit );
766 }
767
768 /**
769 * @param nl
770 * @param type
771 * @throws XMLParsingException
772 */
773 private Color[] parseTransparentColors( Node node )
774 throws XMLParsingException {
775
776 String s = "./deegreewms:TransparentColors/deegreewms:Color";
777 List<Node> clnl = XMLTools.getNodes( node, s, nsContext );
778 Color[] colors = new Color[clnl.size()];
779 for ( int j = 0; j < colors.length; j++ ) {
780 colors[j] = Color.decode( XMLTools.getStringValue( clnl.get( j ) ) );
781 }
782
783 return colors;
784 }
785
786 /**
787 *
788 * @param node
789 * @return the query
790 * @throws XMLParsingException
791 */
792 private Query parseWFSFilterCondition( Node node )
793 throws XMLParsingException {
794
795 Query o = null;
796
797 Node queryNode = XMLTools.getNode( node, "./deegreewms:FilterCondition/wfs:Query", nsContext );
798 if ( queryNode != null ) {
799 try {
800 o = Query.create( (Element) queryNode );
801 } catch ( Exception e ) {
802 throw new XMLParsingException( StringTools.stackTraceToString( e ) );
803 }
804 }
805
806 return o;
807 }
808
809 /**
810 *
811 * @param node
812 * @return the request
813 * @throws XMLParsingException
814 */
815 private GetCoverage parseWCSFilterCondition( Node node )
816 throws XMLParsingException {
817
818 GetCoverage o = null;
819
820 String id = "" + IDGenerator.getInstance().generateUniqueID();
821
822 StringBuffer sd = new StringBuffer( 1000 );
823 sd.append( "version=1.0.0&Coverage=%default%&" );
824 sd.append( "CRS=EPSG:4326&BBOX=0,0,1,1&Width=1" );
825 sd.append( "&Height=1&Format=%default%&" );
826 String s = XMLTools.getNodeAsString( node, "./deegreewms:FilterCondition/deegreewms:WCSRequest", nsContext, "" );
827 sd.append( s );
828 try {
829 o = GetCoverage.create( id, sd.toString() );
830 } catch ( Exception e ) {
831 throw new XMLParsingException( "could not create GetCoverage from layer FilterCondition", e );
832 }
833
834 return o;
835 }
836
837 /**
838 *
839 * @param node
840 * @return the request
841 * @throws XMLParsingException
842 */
843 private GetMap parseWMSFilterCondition( Node node )
844 throws XMLParsingException {
845
846 GetMap o = null;
847
848 String id = "" + IDGenerator.getInstance().generateUniqueID();
849
850 StringBuffer sd = new StringBuffer( 1000 );
851 sd.append( "REQUEST=GetMap&LAYERS=%default%&" );
852 sd.append( "STYLES=&SRS=EPSG:4326&BBOX=0,0,1,1&WIDTH=1&" );
853 sd.append( "HEIGHT=1&FORMAT=%default%" );
854 Map<String, String> map1 = KVP2Map.toMap( sd.toString() );
855 String s = XMLTools.getRequiredNodeAsString( node, "./deegreewms:FilterCondition/deegreewms:WMSRequest",
856 nsContext );
857 Map<String, String> map2 = KVP2Map.toMap( s );
858 if ( map2.get( "VERSION" ) == null && map2.get( "WMTVER" ) == null ) {
859 map2.put( "VERSION", "1.1.1" );
860 }
861 // if no service is set use WMS as default
862 if ( map2.get( "SERVICE" ) == null ) {
863 map2.put( "SERVICE", "WMS" );
864 }
865 map1.putAll( map2 );
866 try {
867 map1.put( "ID", id );
868 o = GetMap.create( map1 );
869 } catch ( Exception e ) {
870 throw new XMLParsingException( "could not create GetMap from layer FilterCondition", e );
871 }
872
873 return o;
874 }
875
876 /**
877 *
878 * @param layerElem
879 * @throws XMLParsingException
880 */
881 @Override
882 protected Style[] parseStyles( Element layerElem )
883 throws XMLParsingException {
884
885 List<Node> nl = XMLTools.getNodes( layerElem, "./Style", nsContext );
886 Style[] styles = new Style[nl.size()];
887 for ( int i = 0; i < styles.length; i++ ) {
888 String name = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Name", nsContext );
889 String title = XMLTools.getNodeAsString( nl.get( i ), "./Title", nsContext, null );
890 String styleAbstract = XMLTools.getNodeAsString( nl.get( i ), "./Abstract", nsContext, null );
891 LegendURL[] legendURLs = parseLegendURL( nl.get( i ) );
892 StyleURL styleURL = parseStyleURL( nl.get( i ) );
893 StyleSheetURL styleSheetURL = parseStyleSheetURL( nl.get( i ) );
894 String styleResource = XMLTools.getNodeAsString( nl.get( i ), "deegreewms:StyleResource", nsContext,
895 "styles.xml" );
896 URL sr = null;
897 try {
898 sr = resolve( styleResource );
899 } catch ( MalformedURLException e ) {
900 throw new XMLParsingException( "could not parse style resource of style: " + name, e );
901 }
902
903 String layerName = XMLTools.getRequiredNodeAsString( layerElem, "Name", nsContext );
904 if ( name == null || name.length() == 0 ) {
905 name = "default:" + layerName;
906 }
907 if ( name.equals( "default" ) ) {
908 name += ":" + layerName;
909 }
910 if ( name.equals( "default:" ) ) {
911 name += layerName;
912 }
913
914 styles[i] = new Style( name, title, styleAbstract, legendURLs, styleSheetURL, styleURL, sr );
915 }
916
917 return styles;
918 }
919
920 }