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