001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wmps/configuration/WMPSConfigurationDocument.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2007 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.wmps.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.HashMap;
052 import java.util.List;
053 import java.util.Map;
054
055 import javax.xml.transform.TransformerException;
056
057 import org.deegree.datatypes.QualifiedName;
058 import org.deegree.enterprise.Proxy;
059 import org.deegree.framework.log.ILogger;
060 import org.deegree.framework.log.LoggerFactory;
061 import org.deegree.framework.util.BootLogger;
062 import org.deegree.framework.util.IDGenerator;
063 import org.deegree.framework.util.KVP2Map;
064 import org.deegree.framework.util.StringTools;
065 import org.deegree.framework.xml.InvalidConfigurationException;
066 import org.deegree.framework.xml.XMLFragment;
067 import org.deegree.framework.xml.XMLParsingException;
068 import org.deegree.framework.xml.XMLTools;
069 import org.deegree.framework.xml.XSLTDocument;
070 import org.deegree.model.crs.UnknownCRSException;
071 import org.deegree.model.metadata.iso19115.OnlineResource;
072 import org.deegree.model.spatialschema.Envelope;
073 import org.deegree.model.spatialschema.GMLGeometryAdapter;
074 import org.deegree.model.spatialschema.Geometry;
075 import org.deegree.model.spatialschema.GeometryException;
076 import org.deegree.ogcbase.CommonNamespaces;
077 import org.deegree.ogcwebservices.OGCWebService;
078 import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
079 import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
080 import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification;
081 import org.deegree.ogcwebservices.getcapabilities.ServiceProvider;
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.WFServiceFactory;
086 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
087 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
088 import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration;
089 import org.deegree.ogcwebservices.wfs.configuration.WFSConfigurationDocument;
090 import org.deegree.ogcwebservices.wfs.operation.Query;
091 import org.deegree.ogcwebservices.wmps.capabilities.WMPSCapabilitiesDocument;
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.GazetteerParam;
100 import org.deegree.ogcwebservices.wms.capabilities.Identifier;
101 import org.deegree.ogcwebservices.wms.capabilities.Layer;
102 import org.deegree.ogcwebservices.wms.capabilities.LayerBoundingBox;
103 import org.deegree.ogcwebservices.wms.capabilities.LegendURL;
104 import org.deegree.ogcwebservices.wms.capabilities.ScaleHint;
105 import org.deegree.ogcwebservices.wms.capabilities.Style;
106 import org.deegree.ogcwebservices.wms.capabilities.StyleSheetURL;
107 import org.deegree.ogcwebservices.wms.capabilities.StyleURL;
108 import org.deegree.ogcwebservices.wms.capabilities.UserDefinedSymbolization;
109 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
110 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
111 import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
112 import org.deegree.ogcwebservices.wms.configuration.LocalWCSDataSource;
113 import org.deegree.ogcwebservices.wms.configuration.LocalWFSDataSource;
114 import org.deegree.ogcwebservices.wms.configuration.RemoteWFSDataSource;
115 import org.deegree.ogcwebservices.wms.configuration.RemoteWMSDataSource;
116 import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationDocument;
117 import org.deegree.ogcwebservices.wms.operation.GetMap;
118 import org.w3c.dom.Element;
119 import org.w3c.dom.Node;
120 import org.xml.sax.SAXException;
121
122 /**
123 * Represents an XML configuration document for a deegree WMPS 1.0 instance, i.e. it consists of all
124 * sections common to an OGC WMS 1.1.1 capabilities document plus a deegree specific section named
125 * <code>deegreeParams</code> and... TODO
126 *
127 * @author <a href="mailto:deshmukh@lat-lon.de">Anup Deshmukh</a>
128 * @author last edited by: $Author: jmays $
129 *
130 * @version 2.0, $Revision: 7860 $, $Date: 2007-07-26 17:08:10 +0200 (Do, 26 Jul 2007) $
131 */
132 public class WMPSConfigurationDocument extends WMPSCapabilitiesDocument {
133
134 private static final long serialVersionUID = -7940857863171829848L;
135
136 private static final ILogger LOG = LoggerFactory.getLogger( WMPSConfigurationDocument.class );
137
138 protected static final URI DEEGREEWPSNS = CommonNamespaces.DEEGREEWMPS;
139
140 private static final String XML_TEMPLATE = "WMPSConfigurationTemplate.xml";
141
142 private static final String XSLT_TEMPLATE_NAME = "WMPSConfigurationTransform.xsl";
143
144 private static XSLTDocument XSLT_TEMPLATE;
145
146 private static Map<URL, Object> capaCache = new HashMap<URL, Object>();
147
148 static {
149 XSLT_TEMPLATE = new XSLTDocument();
150 try {
151 XSLT_TEMPLATE.load( WMPSConfigurationDocument.class.getResource( XSLT_TEMPLATE_NAME ) );
152 } catch ( Exception e ) {
153 BootLogger.logError( "Error loading XSLT sheet in WMPSConfigurationDocument.", e );
154 }
155 }
156
157 /**
158 * Creates a skeleton capabilities document that contains the mandatory elements only.
159 *
160 * @throws IOException
161 * @throws SAXException
162 */
163 @Override
164 public void createEmptyDocument()
165 throws IOException, SAXException {
166 URL url = WMPSConfigurationDocument.class.getResource( XML_TEMPLATE );
167 if ( url == null ) {
168 throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." );
169 }
170 load( url );
171 }
172
173 /**
174 * Creates a class representation of the document.
175 *
176 * @return class representation of the configuration document
177 * @throws InvalidConfigurationException
178 */
179 public WMPSConfiguration parseConfiguration()
180 throws InvalidConfigurationException {
181
182 try {
183 // transform document to fill missing elements and attributes with default values
184 XMLFragment frag = XSLT_TEMPLATE.transform( this );
185 this.setRootElement( frag.getRootElement() );
186 } catch ( TransformerException e ) {
187 String msg = "Error transforming WMPS configuration document (in order to fill " + "in default value). "
188 + e.getMessage();
189 LOG.logError( msg, e );
190 throw new InvalidConfigurationException( msg, e );
191 }
192
193 ServiceIdentification serviceIdentification = null;
194 ServiceProvider serviceProvider = null;
195 UserDefinedSymbolization uds = null;
196 OperationsMetadata metadata = null;
197 Layer layer = null;
198 WMPSDeegreeParams params = null;
199 String version = parseVersion();
200 try {
201 Node node = XMLTools.getRequiredNode( getRootElement(), "deegreewmps:DeegreeParam", nsContext );
202 params = parseDeegreeParams( node );
203 serviceIdentification = parseServiceIdentification();
204 serviceProvider = parseServiceProvider();
205 uds = parseUserDefinedSymbolization();
206 metadata = parseOperationsMetadata();
207 Element layerElem = (Element) XMLTools.getRequiredNode( getRootElement(), "./Capability/Layer", nsContext );
208 layer = parseLayers( layerElem, null );
209 } catch ( XMLParsingException e ) {
210 e.printStackTrace();
211 throw new InvalidConfigurationException( e.getMessage() + StringTools.stackTraceToString( e ) );
212 } catch ( MalformedURLException e ) {
213 throw new InvalidConfigurationException( e.getMessage() + " - " + StringTools.stackTraceToString( e ) );
214 } catch ( UnknownCRSException e ) {
215 throw new InvalidConfigurationException( getClass().getName(), e.getMessage() );
216 }
217 WMPSConfiguration wmpsConfiguration = new WMPSConfiguration( version, serviceIdentification, serviceProvider,
218 uds, metadata, layer, params, getSystemId() );
219
220 return wmpsConfiguration;
221 }
222
223 /**
224 * Creates a class representation of the <code>deegreeParams</code>- section.
225 *
226 * @param root
227 * @return WMPSDeegreeParams
228 * @throws XMLParsingException
229 * @throws MalformedURLException
230 */
231 public WMPSDeegreeParams parseDeegreeParams( Node root )
232 throws XMLParsingException, MalformedURLException {
233
234 String xPath = "./deegreewmps:DefaultOnlineResource";
235 Element elem = (Element) XMLTools.getRequiredNode( root, xPath, nsContext );
236
237 OnlineResource ol = parseOnLineResource( elem );
238 xPath = "./deegreewmps:CacheSize";
239 int cache = XMLTools.getNodeAsInt( root, xPath, nsContext, 100 );
240 xPath = "./deegreewmps:MaxLifeTime";
241 int maxLifeTime = XMLTools.getNodeAsInt( root, xPath, nsContext, 3600 );
242 xPath = "./deegreewmps:RequestTimeLimit";
243 int reqTimeLimit = XMLTools.getNodeAsInt( root, xPath, nsContext, 15 );
244 reqTimeLimit *= 1000;
245 xPath = "./deegreewmps:MapQuality";
246 double mapQuality = XMLTools.getNodeAsDouble( root, xPath, nsContext, 0.95 );
247 xPath = "./deegreewmps:MaxMapWidth";
248 int maxMapWidth = XMLTools.getNodeAsInt( root, xPath, nsContext, 1000 );
249 xPath = "./deegreewmps:MaxMapHeight";
250 int maxMapHeight = XMLTools.getNodeAsInt( root, xPath, nsContext, 1000 );
251 xPath = "./deegreewmps:FeatureInfoRadius";
252 int featureInfoRadius = XMLTools.getNodeAsInt( root, xPath, nsContext, 5 );
253 xPath = "./deegreewmps:Copyright";
254 String copyright = XMLTools.getNodeAsString( root, xPath, nsContext, "" );
255 URL dtdLocation = null;
256 xPath = "deegreewmps:DTDLocation";
257 if ( XMLTools.getNode( root, xPath, nsContext ) != null ) {
258 xPath = "./deegreewmps:DTDLocation/deegreewmps:OnlineResource";
259 elem = (Element) XMLTools.getRequiredNode( root, xPath, nsContext );
260 OnlineResource olr = parseOnLineResource( elem );
261 dtdLocation = olr.getLinkage().getHref();
262 } else {
263 dtdLocation = new URL( "http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd" );
264 }
265 xPath = "./deegreewmps:AntiAliased";
266 boolean antiAliased = XMLTools.getNodeAsBoolean( root, xPath, nsContext, true );
267 xPath = "./deegreewmps:GazetteerParameter";
268 elem = (Element) XMLTools.getNode( root, xPath, nsContext );
269 GazetteerParam gazetteer = null;
270 if ( elem != null ) {
271 gazetteer = parseGazetteerParameter( elem );
272 }
273
274 Proxy proxy = parseProxy( root );
275
276 List<String> synchList = parseSynchTemplates( root );
277
278 CacheDatabase cacheDatabase = parseCacheDatabase( root );
279
280 PrintMapParam printMapParam = parsePrintMapParam( root );
281
282 WMPSDeegreeParams deegreeParams = new WMPSDeegreeParams( cache, maxLifeTime, reqTimeLimit, (float) mapQuality,
283 ol, maxMapWidth, maxMapHeight, antiAliased,
284 featureInfoRadius, copyright, gazetteer, null,
285 dtdLocation, proxy, synchList, cacheDatabase,
286 printMapParam );
287
288 return deegreeParams;
289 }
290
291 /**
292 * Parse the cache database parameters used by the wmps to store the asynchronous requests.
293 *
294 * @param root
295 * @return CacheDatabase
296 * @throws XMLParsingException
297 */
298 private CacheDatabase parseCacheDatabase( Node root )
299 throws XMLParsingException {
300
301 CacheDatabase cacheDatabase = null;
302 String xPath = "./deegreewmps:CacheDatabase";
303 Node cacheDb = XMLTools.getNode( root, xPath, nsContext );
304 if ( cacheDb != null ) {
305 xPath = "./deegreewmps:JDBCConnection";
306 Node jdbcConnection = XMLTools.getRequiredNode( cacheDb, xPath, nsContext );
307 String driver = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:Driver", nsContext );
308 String url = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:Url", nsContext );
309 String user = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:User", nsContext );
310 String password = XMLTools.getRequiredNodeAsString( jdbcConnection, "./deegreewmps:Password", nsContext );
311 cacheDatabase = new CacheDatabase( driver, url, user, password );
312 LOG.logDebug( "Successfully parsed the deegree wmps cache database parameters." );
313 }
314
315 return cacheDatabase;
316 }
317
318 /**
319 * Parse the PrintMapParam node and retrieve the (jasper reports)template directory, the default
320 * template name if none is specified in the request. Also parse the output directory location
321 * and the location of the printed image output directory.
322 *
323 * @param root
324 * @return PrintMapParam
325 * @throws XMLParsingException
326 * @throws MalformedURLException
327 */
328 private PrintMapParam parsePrintMapParam( Node root )
329 throws XMLParsingException, MalformedURLException {
330
331 Node printParam = XMLTools.getRequiredNode( root, "./deegreewmps:PrintMapParam", nsContext );
332 // set default as pdf
333 String format = XMLTools.getNodeAsString( printParam, "./deegreewmps:Format", nsContext, "pdf" );
334 Node templ = XMLTools.getRequiredNode( printParam, "./deegreewmps:Template", nsContext );
335 String templateDirectory = XMLTools.getRequiredNodeAsString( templ, "./deegreewmps:Directory", nsContext );
336
337 templateDirectory = this.resolve( templateDirectory ).toExternalForm();
338 if ( !templateDirectory.endsWith( "/" ) ) {
339 templateDirectory = templateDirectory + '/';
340 }
341 String plotDirectory = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:PlotDirectory", nsContext );
342 plotDirectory = this.resolve( plotDirectory ).toExternalForm();
343 String onlineResource = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:OnlineResource", nsContext );
344 String plotImgDir = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:PlotImageDirectory", nsContext );
345 plotImgDir = this.resolve( plotImgDir ).toExternalForm();
346 String adminMail = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:AdministratorEMailAddress",
347 nsContext );
348 String mailHost = XMLTools.getRequiredNodeAsString( printParam, "./deegreewmps:MailHost", nsContext );
349
350 String mailTextTemplate = XMLTools.getNodeAsString( printParam, "./deegreewmps:MailTextTemplate", nsContext,
351 "You can access the printMap result at {1}" );
352
353 int targetRes = XMLTools.getNodeAsInt( printParam, "./deegreewmps:TargetResolution", nsContext, 300 );
354
355 PrintMapParam printMapParam = new PrintMapParam( format, templateDirectory, onlineResource, plotDirectory,
356 plotImgDir, adminMail, mailHost, mailTextTemplate, targetRes );
357
358 return printMapParam;
359 }
360
361 /**
362 * parses the list of templates that shall be handled synchronously
363 *
364 * @param root
365 * @return List
366 * @throws XMLParsingException
367 */
368 private List<String> parseSynchTemplates( Node root )
369 throws XMLParsingException {
370
371 String xPath = "./deegreewmps:SynchronousTemplates/deegreewmps:Template";
372 String[] nodes = XMLTools.getNodesAsStrings( root, xPath, nsContext );
373 List<String> list = new ArrayList<String>( nodes.length );
374 for ( int i = 0; i < nodes.length; i++ ) {
375 list.add( nodes[i] );
376 }
377
378 return list;
379 }
380
381 /**
382 * @param root
383 * @return Proxy
384 * @throws XMLParsingException
385 */
386 private Proxy parseProxy( Node root )
387 throws XMLParsingException {
388
389 Proxy proxy = null;
390 Node pro = XMLTools.getNode( root, "./deegreewmps:Proxy", nsContext );
391 if ( pro != null ) {
392 String proxyHost = XMLTools.getRequiredNodeAsString( pro, "./@proxyHost", nsContext );
393 String proxyPort = XMLTools.getRequiredNodeAsString( pro, "./@proxyPort", nsContext );
394 proxy = new Proxy( proxyHost, proxyPort );
395 }
396
397 return proxy;
398 }
399
400 /**
401 * creates an object that describes the access to a gazetteer if one have been defined at the
402 * <DeegreeParam>section of the capabilities/configuration
403 *
404 * @param element
405 * @return GazetteerParam
406 * @throws XMLParsingException
407 */
408 private GazetteerParam parseGazetteerParameter( Element element )
409 throws XMLParsingException {
410
411 GazetteerParam gazetteer = null;
412
413 if ( element != null ) {
414 String xPath = "./deegreewmps:OnlineResource";
415 Element elem = (Element) XMLTools.getRequiredNode( element, xPath, nsContext );
416 OnlineResource olr = parseOnLineResource( elem );
417 URL onlineResource = olr.getLinkage().getHref();
418 // optional: <LocationRadius>, default: 10
419 double radius = XMLTools.getNodeAsDouble( element, "LocationRadius", nsContext, 10 );
420 gazetteer = new GazetteerParam( onlineResource, radius );
421 }
422
423 return gazetteer;
424 }
425
426 /**
427 * returns the layers offered by the WMS
428 *
429 * @param layerElem
430 * @param parent
431 * @return Layer
432 * @throws XMLParsingException
433 * @throws UnknownCRSException
434 */
435 @Override
436 protected Layer parseLayers( Element layerElem, Layer parent )
437 throws XMLParsingException, UnknownCRSException {
438
439 boolean queryable = XMLTools.getNodeAsBoolean( layerElem, "./@queryable", nsContext, false );
440 int cascaded = XMLTools.getNodeAsInt( layerElem, "./@cascaded", nsContext, 0 );
441 boolean opaque = XMLTools.getNodeAsBoolean( layerElem, "./@opaque", nsContext, false );
442 boolean noSubsets = XMLTools.getNodeAsBoolean( layerElem, "./@noSubsets", nsContext, false );
443 int fixedWidth = XMLTools.getNodeAsInt( layerElem, "./@fixedWidth", nsContext, 0 );
444 int fixedHeight = XMLTools.getNodeAsInt( layerElem, "./@fixedHeight", nsContext, 0 );
445 String name = XMLTools.getNodeAsString( layerElem, "./Name", nsContext, null );
446 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Title", nsContext );
447 String layerAbstract = XMLTools.getNodeAsString( layerElem, "./Abstract", nsContext, null );
448 String[] keywords = XMLTools.getNodesAsStrings( layerElem, "./KeywordList/Keyword", nsContext );
449 String[] srs = XMLTools.getNodesAsStrings( layerElem, "./SRS", nsContext );
450 List nl = XMLTools.getNodes( layerElem, "./BoundingBox", nsContext );
451 // substitue with Envelope
452 LayerBoundingBox[] bboxes = null;
453 if ( nl.size() == 0 && parent != null ) {
454 // inherit BoundingBoxes from parent layer
455 bboxes = parent.getBoundingBoxes();
456 } else {
457 bboxes = parseLayerBoundingBoxes( nl );
458 }
459
460 Element llBox = (Element) XMLTools.getNode( layerElem, "./LatLonBoundingBox", nsContext );
461 Envelope llBoundingBox = null;
462 if ( llBox == null && parent != null ) {
463 // inherit LatLonBoundingBox parent layer
464 llBoundingBox = parent.getLatLonBoundingBox();
465 } else {
466 llBoundingBox = parseLatLonBoundingBox( llBox );
467 }
468
469 Dimension[] dimensions = parseDimensions( layerElem );
470 Extent[] extents = parseExtents( layerElem );
471 Attribution attribution = parseAttribution( layerElem );
472 AuthorityURL[] authorityURLs = parseAuthorityURLs( layerElem );
473 MetadataURL[] metadataURLs = parseMetadataURLs( layerElem );
474 DataURL[] dataURLs = parseDataURL( layerElem );
475 Identifier[] identifiers = parseIdentifiers( layerElem );
476 FeatureListURL[] featureListURLs = parseFeatureListURL( layerElem );
477 Style[] styles = parseStyles( layerElem );
478 ScaleHint scaleHint = parseScaleHint( layerElem );
479 AbstractDataSource[] ds = parseDataSources( layerElem, name );
480
481 Layer layer = new Layer( queryable, cascaded, opaque, noSubsets, fixedWidth, fixedHeight, name, title,
482 layerAbstract, llBoundingBox, attribution, scaleHint, keywords, srs, bboxes,
483 dimensions, extents, authorityURLs, identifiers, metadataURLs, dataURLs,
484 featureListURLs, styles, null, ds, parent );
485
486 // get Child layers
487 nl = XMLTools.getNodes( layerElem, "./Layer", nsContext );
488 Layer[] layers = new Layer[nl.size()];
489 for ( int i = 0; i < layers.length; i++ ) {
490 layers[i] = parseLayers( (Element) nl.get( i ), layer );
491 }
492 // set child layers
493 layer.setLayer( layers );
494
495 return layer;
496 }
497
498 /**
499 * Parse the Datasources element
500 *
501 * @param layerElem
502 * @param layerName
503 * @return AbstractDataSource[]
504 * @throws XMLParsingException
505 */
506 private AbstractDataSource[] parseDataSources( Element layerElem, String layerName )
507 throws XMLParsingException {
508
509 List nl = XMLTools.getNodes( layerElem, "./deegreewmps:DataSource", nsContext );
510
511 AbstractDataSource[] ds = new AbstractDataSource[nl.size()];
512 for ( int i = 0; i < ds.length; i++ ) {
513
514 boolean failOnEx = XMLTools.getNodeAsBoolean( (Node) nl.get( i ), "./@failOnException", nsContext, true );
515
516 boolean queryable = XMLTools.getNodeAsBoolean( (Node) nl.get( i ), "./@queryable", nsContext, false );
517
518 QualifiedName name = XMLTools.getNodeAsQualifiedName( (Node) nl.get( i ), "./deegreewmps:Name/text()",
519 nsContext, new QualifiedName( layerName ) );
520
521 String stype = XMLTools.getRequiredNodeAsString( (Node) nl.get( i ), "./deegreewmps:Type", nsContext );
522
523 String xPath = "./deegreewmps:OWSCapabilities/deegreewmps:OnlineResource";
524 Node node = XMLTools.getRequiredNode( (Node) nl.get( i ), xPath, nsContext );
525
526 URL url = parseOnLineResource( (Element) node ).getLinkage().getHref();
527 ScaleHint scaleHint = parseScaleHint( (Node) nl.get( i ) );
528 Geometry validArea = parseValidArea( (Node) nl.get( i ) );
529
530 try {
531 if ( "LOCALWFS".equals( stype ) ) {
532 ds[i] = createLocalWFSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint,
533 validArea, 60 );
534 } else if ( "LOCALWCS".equals( stype ) ) {
535 ds[i] = createLocalWCSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint,
536 validArea, 60 );
537 } else if ( "REMOTEWFS".equals( stype ) ) {
538 ds[i] = createRemoteWFSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint,
539 validArea, 60 );
540 } else if ( "REMOTEWCS".equals( stype ) ) {
541 // TODO
542 // int type = AbstractDataSource.REMOTEWCS;
543 // GetCoverage getCoverage = parseWCSFilterCondition( (Node) nl.get( i ) );
544 // Color[] colors = parseTransparentColors( (Node) nl.get( i ) );
545 throw new UnsupportedOperationException( "REMOTEWCS is not supported as yet!" );
546 } else if ( "REMOTEWMS".equals( stype ) ) {
547 ds[i] = createRemoteWMSDataSource( (Node) nl.get( i ), failOnEx, queryable, name, url, scaleHint,
548 validArea, 60 );
549 } else {
550 throw new XMLParsingException( "invalid DataSource type: " + stype + " defined in deegree WMS "
551 + "configuration for DataSource: " + name );
552 }
553 } catch ( Exception e ) {
554 throw new XMLParsingException( "could not create service instance for " + "WMPS datasource: " + name, e );
555 }
556 }
557
558 return ds;
559 }
560
561 /**
562 * returns the area a data source is valid. If the optional element <ValidArea>is not defined in
563 * the configuration returns <code>null</code>.
564 *
565 * @param node
566 * @return Geometry
567 * @throws XMLParsingException
568 */
569 private Geometry parseValidArea( Node node )
570 throws XMLParsingException {
571
572 Geometry geom = null;
573 List nl = XMLTools.getNodes( node, "./deegreewmps:ValidArea/*", nsContext );
574 if ( node != null ) {
575 try {
576 for ( int i = 0; i < nl.size(); i++ ) {
577 if ( ( (Node) nl.get( 0 ) ).getNamespaceURI().equals( GMLNS ) ) {
578 geom = GMLGeometryAdapter.wrap( (Element) nl.get( 0 ), null );
579 break;
580 }
581 }
582 } catch ( GeometryException e ) {
583 throw new XMLParsingException( "couldn't parse/create valid area of a " + "datasource", e );
584 }
585 }
586
587 return geom;
588 }
589
590 /**
591 * Create a RemoteWMS datasource.
592 *
593 * @param node
594 * @param failOnEx
595 * @param queryable
596 * @param name
597 * @param url
598 * @param scaleHint
599 * @param validArea
600 * @param reqTimeLimit
601 * @return XMLParsingException
602 * @throws Exception
603 */
604 private RemoteWMSDataSource createRemoteWMSDataSource( Node node, boolean failOnEx, boolean queryable,
605 QualifiedName name, URL url, ScaleHint scaleHint,
606 Geometry validArea, int reqTimeLimit )
607 throws Exception {
608
609 int type = AbstractDataSource.REMOTEWMS;
610 String xPath = "./deegreewmps:FeatureInfoTransformation/deegreewmps:OnlineResource";
611 Node fitNode = XMLTools.getNode( node, xPath, nsContext );
612 URL fitURL = null;
613 if ( fitNode != null ) {
614 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref();
615 }
616
617 GetMap getMap = parseWMSFilterCondition( node );
618 Color[] colors = parseTransparentColors( node );
619 WMSCapabilities wCapa = null;
620 try {
621 if ( capaCache.get( url ) != null ) {
622 wCapa = (WMSCapabilities) capaCache.get( url );
623 } else {
624 WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument();
625 doc.load( url );
626 wCapa = (WMSCapabilities) doc.parseCapabilities();
627 capaCache.put( url, wCapa );
628 }
629 } catch ( Exception e ) {
630 LOG.logError( "could not connet: " + url, e );
631 }
632 OGCWebService ows = new RemoteWMService( wCapa );
633
634 // parse added/passed parameter map/list
635 Node vendor = XMLTools.getNode( node,
636 "deegreewmps:FilterCondition/deegreewmps:VendorspecificParameterDefinition",
637 nsContext );
638
639 List<String> passedParameters = parsePassedParameters( vendor );
640 Map<String, String> addedParameters = parseAddedParameters( vendor );
641
642 return new RemoteWMSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getMap,
643 colors, fitURL, reqTimeLimit, passedParameters, addedParameters );
644 }
645
646 /**
647 * @param vendor
648 * @return the parsed list
649 * @throws XMLParsingException
650 */
651 private static List<String> parsePassedParameters( Node vendor )
652 throws XMLParsingException {
653 List<String> passedParameters = new ArrayList<String>( 10 );
654
655 if ( vendor == null ) {
656 return passedParameters;
657 }
658
659 List<Node> nl = XMLTools.getNodes( vendor, "deegreewmps:PassedVendorspecificParameter/deegreewmps:Name",
660 nsContext );
661
662 for ( Object obj : nl ) {
663 passedParameters.add( ( (Node) obj ).getTextContent().toUpperCase() );
664 }
665
666 return passedParameters;
667 }
668
669 /**
670 * @param vendor
671 * @return the parsed map
672 * @throws XMLParsingException
673 */
674 private static Map<String, String> parseAddedParameters( Node vendor )
675 throws XMLParsingException {
676 Map<String, String> addedParameters = new HashMap<String, String>( 10 );
677
678 if ( vendor == null ) {
679 return addedParameters;
680 }
681
682 List<Node> nl = XMLTools.getNodes( vendor,
683 "deegreewmps:AddedVendorspecificParameter/deegreewmps:VendorspecificParameter",
684 nsContext );
685
686 for ( Object obj : nl ) {
687 String pName = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewmps:Name", nsContext );
688 String pValue = XMLTools.getRequiredNodeAsString( (Node) obj, "deegreewmps:Value", nsContext );
689
690 addedParameters.put( pName, pValue );
691 }
692 return addedParameters;
693 }
694
695
696 /**
697 * Create a Remote WFS datasource.
698 *
699 * @param node
700 * @param failOnEx
701 * @param queryable
702 * @param name
703 * @param url
704 * @param scaleHint
705 * @param validArea
706 * @param reqTimeLimit
707 * @return RemoteWFSDataSource
708 * @throws Exception
709 */
710 private RemoteWFSDataSource createRemoteWFSDataSource( Node node, boolean failOnEx, boolean queryable,
711 QualifiedName name, URL url, ScaleHint scaleHint,
712 Geometry validArea, int reqTimeLimit )
713 throws Exception {
714
715 int type = AbstractDataSource.REMOTEWFS;
716 String xPath = "./deegreewmps:FeatureInfoTransformation/deegreewmps:OnlineResource";
717 Node fitNode = XMLTools.getNode( node, xPath, nsContext );
718 URL fitURL = null;
719 if ( fitNode != null ) {
720 fitURL = parseOnLineResource( (Element) fitNode ).getLinkage().getHref();
721 }
722 Query query = parseWFSFilterCondition( node );
723
724 WFSCapabilities wfsCapa = null;
725 if ( capaCache.get( url ) != null ) {
726 wfsCapa = (WFSCapabilities) capaCache.get( url );
727 } else {
728 WFSCapabilitiesDocument wfsDoc = new WFSCapabilitiesDocument();
729 wfsDoc.load( url );
730 wfsCapa = (WFSCapabilities) wfsDoc.parseCapabilities();
731 capaCache.put( url, wfsCapa );
732 }
733 // OGCWebService ows = new RemoteWFService( wfsCapa );
734 OGCWebService ows = null;
735 xPath = "./deegreewmps:GeometryProperty/text()";
736 QualifiedName geom = new QualifiedName( "app", "GEOM", new URI( "http://www.deegree.org/app" ) );
737 QualifiedName geoProp = XMLTools.getNodeAsQualifiedName( node, xPath, nsContext, geom );
738
739 return new RemoteWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea,
740 query, fitURL, reqTimeLimit );
741
742 }
743
744 /**
745 * Create a Local WCS Datasource
746 *
747 * @param node
748 * @param failOnEx
749 * @param queryable
750 * @param name
751 * @param url
752 * @param scaleHint
753 * @param validArea
754 * @param reqTimeLimit
755 * @return RemoteWFSDataSource
756 * @throws Exception
757 */
758 private LocalWCSDataSource createLocalWCSDataSource( Node node, boolean failOnEx, boolean queryable,
759 QualifiedName name, URL url, ScaleHint scaleHint,
760 Geometry validArea, int reqTimeLimit )
761 throws Exception {
762
763 int type = AbstractDataSource.LOCALWCS;
764 GetCoverage getCoverage = parseWCSFilterCondition( node );
765 Color[] colors = parseTransparentColors( node );
766 WCSConfiguration configuration = null;
767 if ( capaCache.get( url ) != null ) {
768 configuration = (WCSConfiguration) capaCache.get( url );
769 } else {
770 configuration = WCSConfiguration.create( url );
771 capaCache.put( url, configuration );
772 }
773
774 OGCWebService ows = new WCService( configuration );
775
776 return new LocalWCSDataSource( queryable, failOnEx, name, type, ows, url, scaleHint, validArea, getCoverage,
777 colors, reqTimeLimit );
778 }
779
780 /**
781 * Create a Local WFS Datasource
782 *
783 * @param node
784 * @param failOnEx
785 * @param queryable
786 * @param name
787 * @param url
788 * @param scaleHint
789 * @param validArea
790 * @param reqTimeLimit
791 * @return LocalWFSDataSource
792 * @throws Exception
793 */
794 private LocalWFSDataSource createLocalWFSDataSource( Node node, boolean failOnEx, boolean queryable,
795 QualifiedName name, URL url, ScaleHint scaleHint,
796 Geometry validArea, int reqTimeLimit )
797 throws Exception {
798
799 int type = AbstractDataSource.LOCALWFS;
800 String xPath = null;
801 Query query = parseWFSFilterCondition( node );
802 WFSConfiguration wfsCapa = null;
803 if ( capaCache.get( url ) != null ) {
804 wfsCapa = (WFSConfiguration) capaCache.get( url );
805 } else {
806 WFSConfigurationDocument wfsDoc = new WFSConfigurationDocument();
807 wfsDoc.load( url );
808 wfsCapa = wfsDoc.getConfiguration();
809 capaCache.put( url, wfsCapa );
810 }
811 // OGCWebService ows = WFServiceFactory.getUncachedService( wfsCapa );
812 OGCWebService ows = WFServiceFactory.createInstance( wfsCapa );
813
814 QualifiedName geom = new QualifiedName( "app", "GEOM", new URI( "http://www.deegree.org/app" ) );
815 xPath = "./deegreewmps:GeometryProperty/text()";
816 QualifiedName geoProp = XMLTools.getNodeAsQualifiedName( node, xPath, nsContext, geom );
817
818 return new LocalWFSDataSource( queryable, failOnEx, name, type, geoProp, ows, url, scaleHint, validArea, query,
819 null, reqTimeLimit );
820 }
821
822 /**
823 * Parse trasparent colors.
824 *
825 * @param node
826 * @return Color[]
827 * @throws XMLParsingException
828 */
829 private Color[] parseTransparentColors( Node node )
830 throws XMLParsingException {
831
832 String xPath = "./deegreewmps:TransparentColors/deegreewmps:Color";
833 List clnl = XMLTools.getNodes( node, xPath, nsContext );
834 Color[] colors = new Color[clnl.size()];
835 for ( int i = 0; i < colors.length; i++ ) {
836 colors[i] = Color.decode( XMLTools.getStringValue( (Node) clnl.get( i ) ) );
837 }
838
839 return colors;
840 }
841
842 /**
843 * Parse Scale hint
844 *
845 * @param node
846 * @return ScaleHint
847 * @throws XMLParsingException
848 */
849 private ScaleHint parseScaleHint( Node node )
850 throws XMLParsingException {
851
852 String xPath = "./deegreewmps:ScaleHint/@min";
853 double minScale = XMLTools.getNodeAsDouble( node, xPath, nsContext, 0 );
854 xPath = "./deegreewmps:ScaleHint/@max";
855 double maxScale = XMLTools.getNodeAsDouble( node, xPath, nsContext, Double.MAX_VALUE );
856
857 return new ScaleHint( minScale, maxScale );
858 }
859
860 /**
861 * Parse WFS Filter condition
862 *
863 * @param node
864 * @return Query
865 * @throws XMLParsingException
866 */
867 private Query parseWFSFilterCondition( Node node )
868 throws XMLParsingException {
869
870 Query query = null;
871 String xPath = "./deegreewmps:FilterCondition/wfs:Query";
872 Node queryNode = XMLTools.getNode( node, xPath, nsContext );
873 if ( queryNode != null ) {
874 try {
875 query = Query.create( (Element) queryNode );
876 } catch ( Exception e ) {
877 throw new XMLParsingException( StringTools.stackTraceToString( e ) );
878 }
879 }
880
881 return query;
882 }
883
884 /**
885 * Parse WCS Filter Condition
886 *
887 * @param node
888 * @return GetCoverage
889 * @throws XMLParsingException
890 */
891 private GetCoverage parseWCSFilterCondition( Node node )
892 throws XMLParsingException {
893
894 GetCoverage getCoverage = null;
895
896 String id = "" + IDGenerator.getInstance().generateUniqueID();
897
898 StringBuffer sd = new StringBuffer( 1000 );
899 sd.append( "version=1.0.0&Coverage=%default%&" );
900 sd.append( "CRS=EPSG:4326&BBOX=0,0,1,1&Width=1" );
901 sd.append( "&Height=1&Format=%default%&" );
902 String xPath = "./deegreewmps:FilterCondition/deegreewmps:WCSRequest";
903 String s = XMLTools.getNodeAsString( node, xPath, nsContext, "" );
904 sd.append( s );
905 try {
906 getCoverage = GetCoverage.create( id, sd.toString() );
907 } catch ( Exception e ) {
908 throw new XMLParsingException( "could not create GetCoverage from WMS " + "FilterCondition", e );
909 }
910
911 return getCoverage;
912 }
913
914 /**
915 * Returns a GetMap instance , parsing the WMS Filter condition
916 *
917 * @param node
918 * @return GetMap
919 * @throws XMLParsingException
920 */
921 private GetMap parseWMSFilterCondition( Node node )
922 throws XMLParsingException {
923
924 GetMap getMap = null;
925
926 String id = "" + IDGenerator.getInstance().generateUniqueID();
927
928 StringBuffer sd = new StringBuffer( 1000 );
929 sd.append( "REQUEST=GetMap&LAYERS=%default%&" );
930 sd.append( "STYLES=&SRS=EPSG:4326&BBOX=0,0,1,1&WIDTH=1&" );
931 sd.append( "HEIGHT=1&FORMAT=%default%" );
932 Map<String, String> map1 = KVP2Map.toMap( sd.toString() );
933 String xPath = "./deegreewmps:FilterCondition/deegreewmps:WMSRequest";
934 String s = XMLTools.getRequiredNodeAsString( node, xPath, nsContext );
935 Map<String, String> map2 = KVP2Map.toMap( s );
936 if ( map2.get( "VERSION" ) == null && map2.get( "WMTVER" ) == null ) {
937 map2.put( "VERSION", "1.1.1" );
938 }
939 // if no service is set use WMS as default
940 if ( map2.get( "SERVICE" ) == null ) {
941 map2.put( "SERVICE", "WMS" );
942 }
943 map1.putAll( map2 );
944 try {
945 map1.put( "ID", id );
946 getMap = GetMap.create( map1 );
947 } catch ( Exception e ) {
948 throw new XMLParsingException( "could not create GetCoverage from WMS " + "FilterCondition", e );
949 }
950
951 return getMap;
952 }
953
954 /**
955 * Returns a list of Style elements, parsing the style element
956 *
957 * @param layerElem
958 * @return Style[]
959 * @throws XMLParsingException
960 */
961 @Override
962 protected Style[] parseStyles( Element layerElem )
963 throws XMLParsingException {
964
965 List nl = XMLTools.getNodes( layerElem, "./Style", nsContext );
966 Style[] styles = new Style[nl.size()];
967 for ( int i = 0; i < styles.length; i++ ) {
968 String name = XMLTools.getRequiredNodeAsString( (Node) nl.get( i ), "./Name", nsContext );
969 String title = XMLTools.getNodeAsString( (Node) nl.get( i ), "./Title", nsContext, null );
970 String styleAbstract = XMLTools.getNodeAsString( (Node) nl.get( i ), "./Abstract", nsContext, null );
971 LegendURL[] legendURLs = parseLegendURL( (Node) nl.get( i ) );
972 StyleURL styleURL = parseStyleURL( (Node) nl.get( i ) );
973 StyleSheetURL styleSheetURL = parseStyleSheetURL( (Node) nl.get( i ) );
974 String xPath = "deegreewmps:StyleResource";
975 String styleResource = XMLTools.getNodeAsString( (Node) nl.get( i ), xPath, nsContext, "styles.xml" );
976 URL sr = null;
977 try {
978 sr = resolve( styleResource );
979 } catch ( MalformedURLException e ) {
980 throw new XMLParsingException( "could not parse style resource of " + "style: " + name, e );
981 }
982 styles[i] = new Style( name, title, styleAbstract, legendURLs, styleSheetURL, styleURL, sr );
983 }
984
985 return styles;
986 }
987
988 }