001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/ogcwebservices/wms/capabilities/WMSCapabilitiesDocument.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.wms.capabilities; 037 038 import java.io.IOException; 039 import java.net.MalformedURLException; 040 import java.net.URI; 041 import java.net.URISyntaxException; 042 import java.net.URL; 043 import java.util.ArrayList; 044 import java.util.Arrays; 045 import java.util.Date; 046 import java.util.List; 047 048 import org.deegree.datatypes.Code; 049 import org.deegree.datatypes.QualifiedName; 050 import org.deegree.datatypes.values.TypedLiteral; 051 import org.deegree.framework.log.ILogger; 052 import org.deegree.framework.log.LoggerFactory; 053 import org.deegree.framework.util.StringTools; 054 import org.deegree.framework.xml.XMLParsingException; 055 import org.deegree.framework.xml.XMLTools; 056 import org.deegree.i18n.Messages; 057 import org.deegree.model.crs.CRSFactory; 058 import org.deegree.model.crs.CoordinateSystem; 059 import org.deegree.model.crs.UnknownCRSException; 060 import org.deegree.model.metadata.iso19115.Address; 061 import org.deegree.model.metadata.iso19115.CitedResponsibleParty; 062 import org.deegree.model.metadata.iso19115.Constraints; 063 import org.deegree.model.metadata.iso19115.ContactInfo; 064 import org.deegree.model.metadata.iso19115.Keywords; 065 import org.deegree.model.metadata.iso19115.Linkage; 066 import org.deegree.model.metadata.iso19115.OnlineResource; 067 import org.deegree.model.metadata.iso19115.Phone; 068 import org.deegree.model.spatialschema.Envelope; 069 import org.deegree.model.spatialschema.GeometryFactory; 070 import org.deegree.model.spatialschema.Position; 071 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException; 072 import org.deegree.ogcwebservices.getcapabilities.MetadataURL; 073 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities; 074 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilitiesDocument; 075 import org.deegree.owscommon_new.DCP; 076 import org.deegree.owscommon_new.DomainType; 077 import org.deegree.owscommon_new.HTTP; 078 import org.deegree.owscommon_new.Operation; 079 import org.deegree.owscommon_new.OperationsMetadata; 080 import org.deegree.owscommon_new.Parameter; 081 import org.deegree.owscommon_new.ServiceIdentification; 082 import org.deegree.owscommon_new.ServiceProvider; 083 import org.w3c.dom.Element; 084 import org.w3c.dom.Node; 085 import org.xml.sax.SAXException; 086 087 /** 088 * <code>WMSCapabilitiesDocument</code> is the parser class for WMS capabilities documents that uses the new OWS common 089 * classes to encapsulate the data. 090 * 091 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 092 * @author last edited by: $Author: apoth $ 093 * 094 * @version 2.0, $Revision: 29867 $, $Date: 2011-03-04 11:40:16 +0100 (Fri, 04 Mar 2011) $ 095 * 096 * @since 2.0 097 */ 098 099 public class WMSCapabilitiesDocument extends OGCCapabilitiesDocument { 100 101 private static final long serialVersionUID = -4165017479515126226L; 102 103 private static final String XML_TEMPLATE = "WMSCapabilitiesTemplate.xml"; 104 105 private static final ILogger LOG = LoggerFactory.getLogger( WMSCapabilitiesDocument.class ); 106 107 /** 108 * Creates a skeleton capabilities document that contains the mandatory elements only. 109 * 110 * @throws IOException 111 * @throws SAXException 112 */ 113 public void createEmptyDocument() 114 throws IOException, SAXException { 115 116 URL url = WMSCapabilitiesDocument.class.getResource( XML_TEMPLATE ); 117 if ( url == null ) { 118 throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." ); 119 } 120 load( url ); 121 } 122 123 protected List<String> parseExceptionFormats( Element elem ) 124 throws XMLParsingException { 125 String[] formats = XMLTools.getRequiredNodesAsStrings( elem, "Format", nsContext ); 126 return Arrays.asList( formats ); 127 } 128 129 /** 130 * Creates a class representation of the document. 131 * 132 * @return class representation of the configuration document 133 * @throws InvalidCapabilitiesException 134 */ 135 @Override 136 public OGCCapabilities parseCapabilities() 137 throws InvalidCapabilitiesException { 138 ServiceIdentification serviceIdentification = null; 139 ServiceProvider serviceProvider = null; 140 OperationsMetadata metadata = null; 141 Layer layer = null; 142 UserDefinedSymbolization uds = null; 143 String version = parseVersion(); 144 List<String> exceptions; 145 146 String updateSeq = parseUpdateSequence(); 147 try { 148 serviceIdentification = parseServiceIdentification(); 149 serviceProvider = parseServiceProvider(); 150 metadata = parseOperationsMetadata(); 151 152 Element exceptionElement = XMLTools.getRequiredElement( getRootElement(), "Capability/Exception", nsContext ); 153 exceptions = parseExceptionFormats( exceptionElement ); 154 155 uds = parseUserDefinedSymbolization(); 156 Element layerElem = XMLTools.getRequiredElement( getRootElement(), "./Capability/Layer", nsContext ); 157 layer = parseLayers( layerElem, null, null ); 158 } catch ( XMLParsingException e ) { 159 e.printStackTrace(); 160 throw new InvalidCapabilitiesException( e.getMessage() + StringTools.stackTraceToString( e ) ); 161 } catch ( UnknownCRSException e ) { 162 e.printStackTrace(); 163 throw new InvalidCapabilitiesException( e.getMessage() + StringTools.stackTraceToString( e ) ); 164 } 165 166 WMSCapabilities wmsCapabilities = new WMSCapabilities( version, updateSeq, serviceIdentification, 167 serviceProvider, uds, metadata, layer, exceptions ); 168 169 return wmsCapabilities; 170 } 171 172 /** 173 * @return the services indentification read from the WMS capabilities service section 174 * 175 * @throws XMLParsingException 176 */ 177 protected ServiceIdentification parseServiceIdentification() 178 throws XMLParsingException { 179 String name = XMLTools.getNodeAsString( getRootElement(), "./Service/Name", nsContext, null ); 180 String title = XMLTools.getNodeAsString( getRootElement(), "./Service/Title", nsContext, name ); 181 String serviceAbstract = XMLTools.getNodeAsString( getRootElement(), "./Service/Abstract", nsContext, null ); 182 183 String[] kw = XMLTools.getNodesAsStrings( getRootElement(), "./Service/KeywordList/Keyword", nsContext ); 184 185 Keywords[] keywordArray = new Keywords[] { new Keywords( kw ) }; 186 List<Keywords> keywords = Arrays.asList( keywordArray ); 187 188 String fees = XMLTools.getNodeAsString( getRootElement(), "./Service/Fees", nsContext, null ); 189 190 List<Constraints> accessConstraints = new ArrayList<Constraints>(); 191 192 String[] constraints = XMLTools.getNodesAsStrings( getRootElement(), "./Service/AccessConstraints", nsContext ); 193 194 for ( String constraint : constraints ) { 195 List<String> limits = new ArrayList<String>(); 196 limits.add( constraint ); 197 accessConstraints.add( new Constraints( fees, null, null, null, limits, null, null, null ) ); 198 } 199 200 List<String> versions = new ArrayList<String>(); 201 versions.add( "1.0.0" ); 202 versions.add( "1.1.0" ); 203 versions.add( "1.1.1" ); 204 versions.add( "1.2.0" ); 205 versions.add( "1.3.0" ); 206 207 ServiceIdentification serviceIdentification = new ServiceIdentification( 208 new Code( "OGC:WMS" ), 209 versions, 210 title, 211 null, 212 new Date( System.currentTimeMillis() ), 213 title, serviceAbstract, keywords, 214 accessConstraints ); 215 216 return serviceIdentification; 217 } 218 219 /** 220 * returns WMS contact informaion encapsulated within a <code>ServiceProvider</code> object 221 * 222 * @return the service provider data 223 * @throws XMLParsingException 224 */ 225 protected ServiceProvider parseServiceProvider() 226 throws XMLParsingException { 227 Node ci = XMLTools.getNode( getRootElement(), "./Service/ContactInformation", nsContext ); 228 // according to WMS 1.1.1 specification this element is mandatory 229 // but there are several services online which does not contain 230 // this element in its capabilities :-( 231 String s = XMLTools.getNodeAsString( getRootElement(), "./Service/OnlineResource/@xlink:href", nsContext, null ); 232 233 OnlineResource providerSite = null; 234 235 if ( s != null ) { 236 try { 237 providerSite = new OnlineResource( new Linkage( new URL( s ) ) ); 238 } catch ( MalformedURLException e ) { 239 LOG.logError( 240 "could not parse service online resource; use default URL: http://www.opengeospatial.org instead", 241 e ); 242 try { 243 providerSite = new OnlineResource( new Linkage( new URL( "http://www.opengeospatial.org" ) ) ); 244 } catch ( MalformedURLException neverHappens ) { 245 // useless exception 246 } 247 } 248 } else { 249 // use default if no online resource is contained in the 250 // capabilities (see comment above) 251 try { 252 providerSite = new OnlineResource( new Linkage( new URL( "http://www.opengeospatial.org/" ) ) ); 253 } catch ( MalformedURLException neverHappens ) { 254 // useless exception 255 } 256 } 257 258 String person = null; 259 String orga = null; 260 String position = null; 261 if ( ci != null ) { 262 person = XMLTools.getNodeAsString( ci, "./ContactPersonPrimary/ContactPerson", nsContext, null ); 263 orga = XMLTools.getNodeAsString( ci, "./ContactPersonPrimary/ContactOrganization", nsContext, null ); 264 position = XMLTools.getNodeAsString( ci, "./ContactPosition", nsContext, null ); 265 } 266 ContactInfo contact = parseContactInfo(); 267 // ServiceProvider sp = new ServiceProvider( orga, sLink, person, position, contact, null ); 268 CitedResponsibleParty party = new CitedResponsibleParty( 269 contact == null ? new ContactInfo[] {} 270 : new ContactInfo[] { contact }, 271 person == null ? new String[] {} 272 : new String[] { person }, 273 orga == null ? new String[] {} : new String[] { orga }, 274 position == null ? new String[] {} 275 : new String[] { position }, null ); 276 ServiceProvider sp = new ServiceProvider( person, providerSite, party ); 277 278 return sp; 279 } 280 281 /** 282 * 283 * @return the contact information 284 * @throws XMLParsingException 285 */ 286 protected ContactInfo parseContactInfo() 287 throws XMLParsingException { 288 Node ci = XMLTools.getNode( getRootElement(), "./Service/ContactInformation", nsContext ); 289 ContactInfo cont = null; 290 if ( ci != null ) { 291 String[] addr = XMLTools.getNodesAsStrings( ci, "./ContactAddress/Address", nsContext ); 292 // String addrType = 293 // XMLTools.getNodeAsString( ci, "./ContactAddress/AddressType", nsContext, null ); 294 String city = XMLTools.getNodeAsString( ci, "./ContactAddress/City", nsContext, null ); 295 String state = XMLTools.getNodeAsString( ci, "./ContactAddress/StateOrProvince", nsContext, null ); 296 String pc = XMLTools.getNodeAsString( ci, "./ContactAddress/PostCode", nsContext, null ); 297 String country = XMLTools.getNodeAsString( ci, "./ContactAddress/Country", nsContext, null ); 298 String[] mail = XMLTools.getNodesAsStrings( ci, "./ContactElectronicMailAddress", nsContext ); 299 Address address = new Address( state, city, country, addr, mail, pc ); 300 301 String[] phone = XMLTools.getNodesAsStrings( ci, "./ContactVoiceTelephone", nsContext ); 302 String[] fax = XMLTools.getNodesAsStrings( ci, "./ContactFacsimileTelephone", nsContext ); 303 304 Phone ph = new Phone( fax, phone ); 305 306 cont = new ContactInfo( address, null, null, null, ph ); 307 } 308 309 return cont; 310 } 311 312 /** 313 * returns the services capabilitiy read from the WMS capabilities file 314 * 315 * @return the operations metadata 316 * @throws XMLParsingException 317 */ 318 protected OperationsMetadata parseOperationsMetadata() 319 throws XMLParsingException { 320 321 Node opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetCapabilities", nsContext ); 322 323 if ( opNode == null ) { 324 // may it is a WMS 1.0.0 capabilities document 325 opNode = XMLTools.getRequiredNode( getRootElement(), "./Capability/Request/Capabilities", nsContext ); 326 } 327 Operation getCapa = parseOperation( opNode ); 328 329 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetMap", nsContext ); 330 if ( opNode == null ) { 331 // may it is a WMS 1.0.0 capabilities document 332 opNode = XMLTools.getRequiredNode( getRootElement(), "./Capability/Request/Map", nsContext ); 333 } 334 Operation getMap = parseOperation( opNode ); 335 336 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetFeatureInfo", nsContext ); 337 Operation getFI = null; 338 if ( opNode != null ) { 339 getFI = parseOperation( opNode ); 340 } else { 341 // maybe its WMS 1.0.0 342 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/FeatureInfo", nsContext ); 343 if ( opNode != null ) { 344 getFI = parseOperation( opNode ); 345 } 346 } 347 348 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetLegendGraphic", nsContext ); 349 Operation getLG = null; 350 if ( opNode != null ) { 351 getLG = parseOperation( opNode ); 352 } 353 354 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/DescribeLayer", nsContext ); 355 Operation descL = null; 356 if ( opNode != null ) { 357 descL = parseOperation( opNode ); 358 } 359 360 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetStyles", nsContext ); 361 Operation getStyles = null; 362 if ( opNode != null ) { 363 getStyles = parseOperation( opNode ); 364 } 365 366 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/PutStyles", nsContext ); 367 Operation putStyles = null; 368 if ( opNode != null ) { 369 putStyles = parseOperation( opNode ); 370 } 371 372 List<Operation> operations = new ArrayList<Operation>(); 373 if ( getCapa != null ) 374 operations.add( getCapa ); 375 if ( getMap != null ) 376 operations.add( getMap ); 377 if ( getFI != null ) 378 operations.add( getFI ); 379 if ( getLG != null ) 380 operations.add( getLG ); 381 if ( descL != null ) 382 operations.add( descL ); 383 if ( getStyles != null ) 384 operations.add( getStyles ); 385 if ( putStyles != null ) 386 operations.add( putStyles ); 387 388 OperationsMetadata metadata = new OperationsMetadata( null, null, operations, null ); 389 390 return metadata; 391 } 392 393 /** 394 * Creates an <tt>Operation</tt>-instance according to the contents of the DOM-subtree starting at the given 395 * <tt>Node</tt>. 396 * <p> 397 * Notice: operation to be parsed must be operations in sense of WMS 1.0.0 - 1.3.0 and not as defined in OWSCommons. 398 * But the method will return an OWSCommon Operation which encapsulates parsed WMS operation 399 * <p> 400 * 401 * @param node 402 * the <tt>Element</tt> that describes an <tt>Operation</tt> 403 * @throws XMLParsingException 404 * if a syntactic or semantic error in the DOM-subtree is encountered 405 * @return the constructed <tt>Operation</tt>-instance 406 */ 407 protected Operation parseOperation( Node node ) 408 throws XMLParsingException { 409 // use node name as name of the Operation to be defined 410 String name = node.getNodeName(); 411 if ( name.equals( "Capabilities" ) ) { 412 name = "GetCapabilities"; 413 } else if ( name.equals( "Map" ) ) { 414 name = "GetMap"; 415 } else if ( name.equals( "FeatureInfo" ) ) { 416 name = "GetFeatureInfo"; 417 } 418 419 String[] tmp = XMLTools.getRequiredNodesAsStrings( node, "./Format", nsContext ); 420 List<TypedLiteral> values = new ArrayList<TypedLiteral>(); 421 422 URI stringURI = null; 423 try { 424 stringURI = new URI( null, "String", null ); 425 } catch ( URISyntaxException e ) { 426 // cannot happen, why do I have to catch this? 427 } 428 429 for ( String str : tmp ) 430 values.add( new TypedLiteral( str, stringURI ) ); 431 432 DomainType owsDomainType = new DomainType( false, true, null, 0, new QualifiedName( "Format" ), values, null, 433 null, false, null, false, null, null, null, null ); 434 List<Parameter> parameters = new ArrayList<Parameter>(); 435 parameters.add( owsDomainType ); 436 437 List<Element> nl = XMLTools.getRequiredElements( node, "./DCPType", nsContext ); 438 List<DCP> dcps = new ArrayList<DCP>(); 439 440 for ( Element element : nl ) { 441 dcps.add( parseDCP( element ) ); 442 } 443 444 return new Operation( new QualifiedName( name ), dcps, parameters, null, null, null ); 445 } 446 447 /** 448 * Parses a DCPType element. Does not override the method defined in the base class any more. 449 * 450 * @param element 451 * @return created <code>DCPType</code> 452 * @throws XMLParsingException 453 * @see org.deegree.ogcwebservices.getcapabilities.OGCStandardCapabilities 454 */ 455 protected DCP parseDCP( Element element ) 456 throws XMLParsingException { 457 458 List<HTTP.Type> types = new ArrayList<HTTP.Type>(); 459 List<OnlineResource> links = new ArrayList<OnlineResource>(); 460 461 Element elem = XMLTools.getRequiredElement( element, "HTTP", nsContext ); 462 String s = null; 463 try { 464 List<Node> nl = XMLTools.getNodes( elem, "Get", nsContext ); 465 466 for ( int i = 0; i < nl.size(); i++ ) { 467 s = XMLTools.getNodeAsString( nl.get( i ), "./@xlink:href", nsContext, null ); 468 if ( s == null ) { 469 s = XMLTools.getRequiredNodeAsString( nl.get( i ), "./OnlineResource/@xlink:href", nsContext ); 470 } 471 types.add( HTTP.Type.Get ); 472 links.add( new OnlineResource( new Linkage( new URL( s ) ) ) ); 473 } 474 } catch ( Exception e ) { 475 LOG.logError( e.getMessage(), e ); 476 throw new XMLParsingException( Messages.getMessage( "WMS_DCPGET", s ) ); 477 } 478 try { 479 List<Node> nl = XMLTools.getNodes( elem, "Post", nsContext ); 480 481 for ( int i = 0; i < nl.size(); i++ ) { 482 s = XMLTools.getNodeAsString( nl.get( i ), "./@xlink:href", nsContext, null ); 483 if ( s == null ) { 484 s = XMLTools.getRequiredNodeAsString( nl.get( i ), "./OnlineResource/@xlink:href", nsContext ); 485 } 486 types.add( HTTP.Type.Post ); 487 links.add( new OnlineResource( new Linkage( new URL( s ) ) ) ); 488 } 489 490 } catch ( MalformedURLException e ) { 491 throw new XMLParsingException( Messages.getMessage( "WMS_DCPPOST", s ) ); 492 } 493 HTTP http = new HTTP( links, null, types ); 494 495 return http; 496 } 497 498 /** 499 * 500 * @return the parsed data 501 * @throws XMLParsingException 502 */ 503 protected UserDefinedSymbolization parseUserDefinedSymbolization() 504 throws XMLParsingException { 505 506 boolean supportSLD = XMLTools.getNodeAsBoolean( getRootElement(), 507 "./Capability/UserDefinedSymbolization/@SupportSLD", nsContext, 508 false ); 509 510 boolean userLayer = XMLTools.getNodeAsBoolean( getRootElement(), 511 "./Capability/UserDefinedSymbolization/@UserLayer", nsContext, 512 false ); 513 514 boolean userStyle = XMLTools.getNodeAsBoolean( getRootElement(), 515 "./Capability/UserDefinedSymbolization/@UserStyle", nsContext, 516 false ); 517 518 boolean remoteWFS = XMLTools.getNodeAsBoolean( getRootElement(), 519 "./Capability/UserDefinedSymbolization/@RemoteWFS", nsContext, 520 false ); 521 522 UserDefinedSymbolization uds = new UserDefinedSymbolization( supportSLD, userLayer, remoteWFS, userStyle ); 523 524 return uds; 525 } 526 527 /** 528 * @param layerElem 529 * @param parent 530 * @param scaleHint 531 * 532 * @return the layer created from the given element 533 * @throws XMLParsingException 534 * @throws UnknownCRSException 535 */ 536 protected Layer parseLayers( Element layerElem, Layer parent, ScaleHint scaleHint ) 537 throws XMLParsingException, UnknownCRSException { 538 539 boolean queryable = XMLTools.getNodeAsBoolean( layerElem, "./@queryable", nsContext, false ); 540 541 int cascaded = XMLTools.getNodeAsInt( layerElem, "./@cascaded", nsContext, 0 ); 542 boolean opaque = XMLTools.getNodeAsBoolean( layerElem, "./@opaque", nsContext, false ); 543 boolean noSubsets = XMLTools.getNodeAsBoolean( layerElem, "./@noSubsets", nsContext, false ); 544 int fixedWidth = XMLTools.getNodeAsInt( layerElem, "./@fixedWidth", nsContext, 0 ); 545 int fixedHeight = XMLTools.getNodeAsInt( layerElem, "./@fixedHeight", nsContext, 0 ); 546 String name = XMLTools.getNodeAsString( layerElem, "./Name", nsContext, null ); 547 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Title", nsContext ); 548 String layerAbstract = XMLTools.getNodeAsString( layerElem, "./Abstract", nsContext, null ); 549 String[] keywords = XMLTools.getNodesAsStrings( layerElem, "./KeywordList/Keyword", nsContext ); 550 String[] srs = XMLTools.getNodesAsStrings( layerElem, "./SRS", nsContext ); 551 552 List<Element> nl = XMLTools.getElements( layerElem, "./BoundingBox", nsContext ); 553 // TODO 554 // substitue with Envelope 555 LayerBoundingBox[] bboxes = null; 556 if ( nl.size() == 0 && parent != null ) { 557 // inherit BoundingBoxes from parent layer 558 bboxes = parent.getBoundingBoxes(); 559 } else { 560 bboxes = parseLayerBoundingBoxes( nl ); 561 } 562 563 Element llBox = XMLTools.getElement( layerElem, "./LatLonBoundingBox", nsContext ); 564 Envelope llBoundingBox = null; 565 566 if ( llBox == null && parent != null ) { 567 // inherit LatLonBoundingBox parent layer 568 llBoundingBox = parent.getLatLonBoundingBox(); 569 } else if ( llBox != null ) { 570 llBoundingBox = parseLatLonBoundingBox( llBox ); 571 } else { 572 llBoundingBox = GeometryFactory.createEnvelope( -180, -90, 180, 90, CRSFactory.create( "EPSG:4326" ) ); 573 } 574 575 Dimension[] dimensions = parseDimensions( layerElem ); 576 Extent[] extents = parseExtents( layerElem ); 577 578 Attribution attribution = parseAttribution( layerElem ); 579 580 AuthorityURL[] authorityURLs = parseAuthorityURLs( layerElem ); 581 582 MetadataURL[] metadataURLs = parseMetadataURLs( layerElem ); 583 584 DataURL[] dataURLs = parseDataURL( layerElem ); 585 586 Identifier[] identifiers = parseIdentifiers( layerElem ); 587 588 FeatureListURL[] featureListURLs = parseFeatureListURL( layerElem ); 589 590 Style[] styles = parseStyles( layerElem ); 591 592 scaleHint = parseScaleHint( layerElem, scaleHint ); 593 594 Layer layer = new Layer( queryable, cascaded, opaque, noSubsets, fixedWidth, fixedHeight, name, title, 595 layerAbstract, llBoundingBox, attribution, scaleHint, keywords, srs, bboxes, 596 dimensions, extents, authorityURLs, identifiers, metadataURLs, dataURLs, 597 featureListURLs, styles, null, null, parent ); 598 599 // get Child layers 600 nl = XMLTools.getElements( layerElem, "./Layer", nsContext ); 601 Layer[] layers = new Layer[nl.size()]; 602 for ( int i = 0; i < layers.length; i++ ) { 603 layers[i] = parseLayers( nl.get( i ), layer, scaleHint ); 604 } 605 606 // set child layers 607 layer.setLayer( layers ); 608 609 return layer; 610 } 611 612 /** 613 * 614 * @param layerElem 615 * @return the dimensions 616 * @throws XMLParsingException 617 */ 618 protected Dimension[] parseDimensions( Element layerElem ) 619 throws XMLParsingException { 620 621 List<Node> nl = XMLTools.getNodes( layerElem, "./Dimension", nsContext ); 622 Dimension[] dimensions = new Dimension[nl.size()]; 623 for ( int i = 0; i < dimensions.length; i++ ) { 624 String name = XMLTools.getNodeAsString( nl.get( i ), "./@name", nsContext, null ); 625 String units = XMLTools.getNodeAsString( nl.get( i ), "./@units", nsContext, null ); 626 String unitSymbol = XMLTools.getNodeAsString( nl.get( i ), "./@unitSymbol", nsContext, null ); 627 dimensions[i] = new Dimension( name, units, unitSymbol ); 628 } 629 630 return dimensions; 631 } 632 633 /** 634 * 635 * @param layerElem 636 * @return the extent 637 * @throws XMLParsingException 638 */ 639 protected Extent[] parseExtents( Element layerElem ) 640 throws XMLParsingException { 641 642 List<Node> nl = XMLTools.getNodes( layerElem, "./Extent", nsContext ); 643 Extent[] extents = new Extent[nl.size()]; 644 for ( int i = 0; i < extents.length; i++ ) { 645 String name = XMLTools.getNodeAsString( nl.get( i ), "./@name", nsContext, null ); 646 String deflt = XMLTools.getNodeAsString( nl.get( i ), "./@default", nsContext, null ); 647 boolean nearestValue = XMLTools.getNodeAsBoolean( nl.get( i ), "./@nearestValue", nsContext, false ); 648 String value = XMLTools.getNodeAsString( nl.get( i ), ".", nsContext, "" ); 649 extents[i] = new Extent( name, deflt, nearestValue, value ); 650 } 651 652 return extents; 653 } 654 655 /** 656 * 657 * @param layerElem 658 * @return the attribution 659 * @throws XMLParsingException 660 */ 661 protected Attribution parseAttribution( Element layerElem ) 662 throws XMLParsingException { 663 664 Attribution attribution = null; 665 Node node = XMLTools.getNode( layerElem, "./Attribution", nsContext ); 666 if ( node != null ) { 667 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Attribution/Title", nsContext ); 668 OnlineResource onLineResource = parseOnLineResource( XMLTools.getRequiredElement( node, "./OnlineResource", 669 nsContext ) ); 670 node = XMLTools.getNode( node, "./LogoURL", nsContext ); 671 LogoURL logoURL = null; 672 if ( node != null ) { 673 int width = XMLTools.getRequiredNodeAsInt( node, "./@width", nsContext ); 674 int height = XMLTools.getRequiredNodeAsInt( node, "./@height", nsContext ); 675 String format = XMLTools.getRequiredNodeAsString( node, "./Format", nsContext ); 676 OnlineResource logoOR = parseOnLineResource( XMLTools.getRequiredElement( node, "./OnlineResource", 677 nsContext ) ); 678 logoURL = new LogoURL( width, height, format, logoOR.getLinkage().getHref() ); 679 } 680 attribution = new Attribution( title, onLineResource.getLinkage().getHref(), logoURL ); 681 } 682 683 return attribution; 684 } 685 686 /** 687 * 688 * @param layerElem 689 * @return the URLs 690 * @throws XMLParsingException 691 */ 692 protected AuthorityURL[] parseAuthorityURLs( Element layerElem ) 693 throws XMLParsingException { 694 695 List<Node> nl = XMLTools.getNodes( layerElem, "./AuthorityURL", nsContext ); 696 AuthorityURL[] authorityURLs = new AuthorityURL[nl.size()]; 697 for ( int i = 0; i < authorityURLs.length; i++ ) { 698 String name = XMLTools.getRequiredNodeAsString( nl.get( i ), "./@name", nsContext ); 699 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 700 OnlineResource olr = parseOnLineResource( tmp ); 701 authorityURLs[i] = new AuthorityURL( name, olr.getLinkage().getHref() ); 702 } 703 704 return authorityURLs; 705 } 706 707 /** 708 * 709 * @param layerElem 710 * @return the URLs 711 * @throws XMLParsingException 712 */ 713 protected MetadataURL[] parseMetadataURLs( Element layerElem ) 714 throws XMLParsingException { 715 716 List<Node> nl = XMLTools.getNodes( layerElem, "./MetadataURL", nsContext ); 717 MetadataURL[] metadataURL = new MetadataURL[nl.size()]; 718 for ( int i = 0; i < metadataURL.length; i++ ) { 719 String type = XMLTools.getRequiredNodeAsString( nl.get( i ), "./@type", nsContext ); 720 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 721 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 722 OnlineResource olr = parseOnLineResource( tmp ); 723 metadataURL[i] = new MetadataURL( type, format, olr.getLinkage().getHref() ); 724 725 } 726 727 return metadataURL; 728 } 729 730 /** 731 * 732 * @param layerElem 733 * @return the URLs 734 * @throws XMLParsingException 735 */ 736 protected DataURL[] parseDataURL( Element layerElem ) 737 throws XMLParsingException { 738 739 List<Node> nl = XMLTools.getNodes( layerElem, "./DataURL", nsContext ); 740 DataURL[] dataURL = new DataURL[nl.size()]; 741 for ( int i = 0; i < dataURL.length; i++ ) { 742 743 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 744 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 745 OnlineResource olr = parseOnLineResource( tmp ); 746 dataURL[i] = new DataURL( format, olr.getLinkage().getHref() ); 747 748 } 749 750 return dataURL; 751 } 752 753 /** 754 * 755 * @param layerElem 756 * @return the URLs 757 * @throws XMLParsingException 758 */ 759 protected FeatureListURL[] parseFeatureListURL( Element layerElem ) 760 throws XMLParsingException { 761 762 List<Node> nl = XMLTools.getNodes( layerElem, "./FeatureListURL", nsContext ); 763 FeatureListURL[] flURL = new FeatureListURL[nl.size()]; 764 for ( int i = 0; i < flURL.length; i++ ) { 765 766 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 767 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 768 OnlineResource olr = parseOnLineResource( tmp ); 769 flURL[i] = new FeatureListURL( format, olr.getLinkage().getHref() ); 770 771 } 772 773 return flURL; 774 } 775 776 /** 777 * 778 * @param layerElem 779 * @return the styles 780 * @throws XMLParsingException 781 */ 782 protected Style[] parseStyles( Element layerElem ) 783 throws XMLParsingException { 784 785 List<Node> nl = XMLTools.getNodes( layerElem, "./Style", nsContext ); 786 Style[] styles = new Style[nl.size()]; 787 for ( int i = 0; i < styles.length; i++ ) { 788 String name = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Name", nsContext ); 789 790 if ( name == null ) { 791 throw new XMLParsingException( Messages.getMessage( "WMS_STYLENAME" ) ); 792 } 793 String title = XMLTools.getNodeAsString( nl.get( i ), "./Title", nsContext, null ); 794 if ( title == null ) { 795 throw new XMLParsingException( Messages.getMessage( "WMS_STYLETITLE" ) ); 796 } 797 String styleAbstract = XMLTools.getNodeAsString( nl.get( i ), "./Abstract", nsContext, null ); 798 LegendURL[] legendURLs = parseLegendURL( nl.get( i ) ); 799 StyleURL styleURL = parseStyleURL( nl.get( i ) ); 800 StyleSheetURL styleSheetURL = parseStyleSheetURL( nl.get( i ) ); 801 802 styles[i] = new Style( name, title, styleAbstract, legendURLs, styleSheetURL, styleURL, null ); 803 } 804 805 return styles; 806 } 807 808 /** 809 * 810 * @param node 811 * @return the URLs 812 * @throws XMLParsingException 813 */ 814 protected LegendURL[] parseLegendURL( Node node ) 815 throws XMLParsingException { 816 817 List<Node> nl = XMLTools.getNodes( node, "./LegendURL", nsContext ); 818 LegendURL[] lURL = new LegendURL[nl.size()]; 819 for ( int i = 0; i < lURL.length; i++ ) { 820 int width = XMLTools.getRequiredNodeAsInt( nl.get( i ), "./@width", nsContext ); 821 int height = XMLTools.getRequiredNodeAsInt( nl.get( i ), "./@height", nsContext ); 822 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 823 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 824 OnlineResource olr = parseOnLineResource( tmp ); 825 lURL[i] = new LegendURL( width, height, format, olr.getLinkage().getHref() ); 826 827 } 828 829 return lURL; 830 } 831 832 /** 833 * 834 * @param node 835 * @return the URL 836 * @throws XMLParsingException 837 */ 838 protected StyleURL parseStyleURL( Node node ) 839 throws XMLParsingException { 840 841 StyleURL styleURL = null; 842 Node styleNode = XMLTools.getNode( node, "./StyleURL", nsContext ); 843 844 if ( styleNode != null ) { 845 String format = XMLTools.getRequiredNodeAsString( styleNode, "./Format", nsContext ); 846 Element tmp = XMLTools.getRequiredElement( styleNode, "./OnlineResource", nsContext ); 847 OnlineResource olr = parseOnLineResource( tmp ); 848 styleURL = new StyleURL( format, olr.getLinkage().getHref() ); 849 850 } 851 852 return styleURL; 853 } 854 855 /** 856 * 857 * @param node 858 * @return the URL 859 * @throws XMLParsingException 860 */ 861 protected StyleSheetURL parseStyleSheetURL( Node node ) 862 throws XMLParsingException { 863 864 StyleSheetURL styleSheetURL = null; 865 Node styleNode = XMLTools.getNode( node, "./StyleSheetURL", nsContext ); 866 867 if ( styleNode != null ) { 868 String format = XMLTools.getRequiredNodeAsString( styleNode, "./Format", nsContext ); 869 Element tmp = XMLTools.getRequiredElement( styleNode, "./OnlineResource", nsContext ); 870 OnlineResource olr = parseOnLineResource( tmp ); 871 styleSheetURL = new StyleSheetURL( format, olr.getLinkage().getHref() ); 872 873 } 874 875 return styleSheetURL; 876 } 877 878 /** 879 * 880 * @param layerElem 881 * @param scaleHint 882 * the default scale hint 883 * @return the scale hint 884 * @throws XMLParsingException 885 */ 886 protected ScaleHint parseScaleHint( Element layerElem, ScaleHint scaleHint ) 887 throws XMLParsingException { 888 889 Node scNode = XMLTools.getNode( layerElem, "./ScaleHint", nsContext ); 890 if ( scNode != null ) { 891 double mn = XMLTools.getNodeAsDouble( scNode, "./@min", nsContext, 0 ); 892 double mx = XMLTools.getNodeAsDouble( scNode, "./@max", nsContext, Double.MAX_VALUE ); 893 scaleHint = new ScaleHint( mn, mx ); 894 } 895 896 if ( scaleHint == null ) { 897 // set default value to avoid NullPointerException 898 // when accessing a layers scalehint 899 scaleHint = new ScaleHint( 0, Double.MAX_VALUE ); 900 } 901 902 return scaleHint; 903 } 904 905 /** 906 * 907 * @param layerElem 908 * @return the identifiers 909 * @throws XMLParsingException 910 */ 911 protected Identifier[] parseIdentifiers( Element layerElem ) 912 throws XMLParsingException { 913 914 List<Node> nl = XMLTools.getNodes( layerElem, "./Identifier", nsContext ); 915 Identifier[] identifiers = new Identifier[nl.size()]; 916 for ( int i = 0; i < identifiers.length; i++ ) { 917 String value = XMLTools.getStringValue( nl.get( i ) ); 918 String authority = XMLTools.getNodeAsString( layerElem, "./@authority", nsContext, null ); 919 identifiers[i] = new Identifier( value, authority ); 920 } 921 922 return identifiers; 923 } 924 925 /** 926 * 927 * @param nl 928 * @return the bboxes 929 * @throws XMLParsingException 930 */ 931 protected LayerBoundingBox[] parseLayerBoundingBoxes( List<Element> nl ) 932 throws XMLParsingException { 933 934 LayerBoundingBox[] llBoxes = new LayerBoundingBox[nl.size()]; 935 for ( int i = 0; i < llBoxes.length; i++ ) { 936 double minx = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@minx", nsContext ); 937 double maxx = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@maxx", nsContext ); 938 double miny = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@miny", nsContext ); 939 double maxy = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@maxy", nsContext ); 940 double resx = XMLTools.getNodeAsDouble( nl.get( i ), "./@resx", nsContext, -1 ); 941 double resy = XMLTools.getNodeAsDouble( nl.get( i ), "./@resx", nsContext, -1 ); 942 String srs = XMLTools.getRequiredNodeAsString( nl.get( i ), "./@SRS", nsContext ); 943 Position min = GeometryFactory.createPosition( minx, miny ); 944 Position max = GeometryFactory.createPosition( maxx, maxy ); 945 llBoxes[i] = new LayerBoundingBox( min, max, srs, resx, resy ); 946 } 947 948 return llBoxes; 949 } 950 951 /** 952 * 953 * @param llBox 954 * @return the envelope 955 * @throws XMLParsingException 956 * @throws UnknownCRSException 957 */ 958 protected Envelope parseLatLonBoundingBox( Element llBox ) 959 throws XMLParsingException, UnknownCRSException { 960 961 double minx = XMLTools.getRequiredNodeAsDouble( llBox, "./@minx", nsContext ); 962 double maxx = XMLTools.getRequiredNodeAsDouble( llBox, "./@maxx", nsContext ); 963 double miny = XMLTools.getRequiredNodeAsDouble( llBox, "./@miny", nsContext ); 964 double maxy = XMLTools.getRequiredNodeAsDouble( llBox, "./@maxy", nsContext ); 965 CoordinateSystem crs = CRSFactory.create( "EPSG:4326" ); 966 967 Envelope env = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, crs ); 968 969 return env; 970 } 971 972 }