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