001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/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: mschneider $ 093 * 094 * @version 2.0, $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 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 throw new XMLParsingException( "could not parse service online resource", e ); 240 } 241 } else { 242 // use default if no online resource is contained in the 243 // capabilities (see comment above) 244 try { 245 providerSite = new OnlineResource( new Linkage( new URL( "http://www.opengeospatial.org/" ) ) ); 246 } catch ( MalformedURLException neverHappens ) { 247 // useless exception 248 } 249 } 250 251 String person = null; 252 String orga = null; 253 String position = null; 254 if ( ci != null ) { 255 person = XMLTools.getNodeAsString( ci, "./ContactPersonPrimary/ContactPerson", nsContext, null ); 256 orga = XMLTools.getNodeAsString( ci, "./ContactPersonPrimary/ContactOrganization", nsContext, null ); 257 position = XMLTools.getNodeAsString( ci, "./ContactPosition", nsContext, null ); 258 } 259 ContactInfo contact = parseContactInfo(); 260 // ServiceProvider sp = new ServiceProvider( orga, sLink, person, position, contact, null ); 261 CitedResponsibleParty party = new CitedResponsibleParty( 262 contact == null ? new ContactInfo[] {} 263 : new ContactInfo[] { contact }, 264 person == null ? new String[] {} 265 : new String[] { person }, 266 orga == null ? new String[] {} : new String[] { orga }, 267 position == null ? new String[] {} 268 : new String[] { position }, null ); 269 ServiceProvider sp = new ServiceProvider( person, providerSite, party ); 270 271 return sp; 272 } 273 274 /** 275 * 276 * @return the contact information 277 * @throws XMLParsingException 278 */ 279 protected ContactInfo parseContactInfo() 280 throws XMLParsingException { 281 Node ci = XMLTools.getNode( getRootElement(), "./Service/ContactInformation", nsContext ); 282 ContactInfo cont = null; 283 if ( ci != null ) { 284 String[] addr = XMLTools.getNodesAsStrings( ci, "./ContactAddress/Address", nsContext ); 285 // String addrType = 286 // XMLTools.getNodeAsString( ci, "./ContactAddress/AddressType", nsContext, null ); 287 String city = XMLTools.getNodeAsString( ci, "./ContactAddress/City", nsContext, null ); 288 String state = XMLTools.getNodeAsString( ci, "./ContactAddress/StateOrProvince", nsContext, null ); 289 String pc = XMLTools.getNodeAsString( ci, "./ContactAddress/PostCode", nsContext, null ); 290 String country = XMLTools.getNodeAsString( ci, "./ContactAddress/Country", nsContext, null ); 291 String[] mail = XMLTools.getNodesAsStrings( ci, "./ContactElectronicMailAddress", nsContext ); 292 Address address = new Address( state, city, country, addr, mail, pc ); 293 294 String[] phone = XMLTools.getNodesAsStrings( ci, "./ContactVoiceTelephone", nsContext ); 295 String[] fax = XMLTools.getNodesAsStrings( ci, "./ContactFacsimileTelephone", nsContext ); 296 297 Phone ph = new Phone( fax, phone ); 298 299 cont = new ContactInfo( address, null, null, null, ph ); 300 } 301 302 return cont; 303 } 304 305 /** 306 * returns the services capabilitiy read from the WMS capabilities file 307 * 308 * @return the operations metadata 309 * @throws XMLParsingException 310 */ 311 protected OperationsMetadata parseOperationsMetadata() 312 throws XMLParsingException { 313 314 Node opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetCapabilities", nsContext ); 315 316 if ( opNode == null ) { 317 // may it is a WMS 1.0.0 capabilities document 318 opNode = XMLTools.getRequiredNode( getRootElement(), "./Capability/Request/Capabilities", nsContext ); 319 } 320 Operation getCapa = parseOperation( opNode ); 321 322 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetMap", nsContext ); 323 if ( opNode == null ) { 324 // may it is a WMS 1.0.0 capabilities document 325 opNode = XMLTools.getRequiredNode( getRootElement(), "./Capability/Request/Map", nsContext ); 326 } 327 Operation getMap = parseOperation( opNode ); 328 329 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetFeatureInfo", nsContext ); 330 Operation getFI = null; 331 if ( opNode != null ) { 332 getFI = parseOperation( opNode ); 333 } else { 334 // maybe its WMS 1.0.0 335 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/FeatureInfo", nsContext ); 336 if ( opNode != null ) { 337 getFI = parseOperation( opNode ); 338 } 339 } 340 341 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetLegendGraphic", nsContext ); 342 Operation getLG = null; 343 if ( opNode != null ) { 344 getLG = parseOperation( opNode ); 345 } 346 347 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/DescribeLayer", nsContext ); 348 Operation descL = null; 349 if ( opNode != null ) { 350 descL = parseOperation( opNode ); 351 } 352 353 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/GetStyles", nsContext ); 354 Operation getStyles = null; 355 if ( opNode != null ) { 356 getStyles = parseOperation( opNode ); 357 } 358 359 opNode = XMLTools.getNode( getRootElement(), "./Capability/Request/PutStyles", nsContext ); 360 Operation putStyles = null; 361 if ( opNode != null ) { 362 putStyles = parseOperation( opNode ); 363 } 364 365 List<Operation> operations = new ArrayList<Operation>(); 366 if ( getCapa != null ) 367 operations.add( getCapa ); 368 if ( getMap != null ) 369 operations.add( getMap ); 370 if ( getFI != null ) 371 operations.add( getFI ); 372 if ( getLG != null ) 373 operations.add( getLG ); 374 if ( descL != null ) 375 operations.add( descL ); 376 if ( getStyles != null ) 377 operations.add( getStyles ); 378 if ( putStyles != null ) 379 operations.add( putStyles ); 380 381 OperationsMetadata metadata = new OperationsMetadata( null, null, operations, null ); 382 383 return metadata; 384 } 385 386 /** 387 * Creates an <tt>Operation</tt>-instance according to the contents of the DOM-subtree starting at the given 388 * <tt>Node</tt>. 389 * <p> 390 * Notice: operation to be parsed must be operations in sense of WMS 1.0.0 - 1.3.0 and not as defined in OWSCommons. 391 * But the method will return an OWSCommon Operation which encapsulates parsed WMS operation 392 * <p> 393 * 394 * @param node 395 * the <tt>Element</tt> that describes an <tt>Operation</tt> 396 * @throws XMLParsingException 397 * if a syntactic or semantic error in the DOM-subtree is encountered 398 * @return the constructed <tt>Operation</tt>-instance 399 */ 400 protected Operation parseOperation( Node node ) 401 throws XMLParsingException { 402 // use node name as name of the Operation to be defined 403 String name = node.getNodeName(); 404 if ( name.equals( "Capabilities" ) ) { 405 name = "GetCapabilities"; 406 } else if ( name.equals( "Map" ) ) { 407 name = "GetMap"; 408 } else if ( name.equals( "FeatureInfo" ) ) { 409 name = "GetFeatureInfo"; 410 } 411 412 String[] tmp = XMLTools.getRequiredNodesAsStrings( node, "./Format", nsContext ); 413 List<TypedLiteral> values = new ArrayList<TypedLiteral>(); 414 415 URI stringURI = null; 416 try { 417 stringURI = new URI( null, "String", null ); 418 } catch ( URISyntaxException e ) { 419 // cannot happen, why do I have to catch this? 420 } 421 422 for ( String str : tmp ) 423 values.add( new TypedLiteral( str, stringURI ) ); 424 425 DomainType owsDomainType = new DomainType( false, true, null, 0, new QualifiedName( "Format" ), values, null, 426 null, false, null, false, null, null, null, null ); 427 List<Parameter> parameters = new ArrayList<Parameter>(); 428 parameters.add( owsDomainType ); 429 430 List<Element> nl = XMLTools.getRequiredElements( node, "./DCPType", nsContext ); 431 List<DCP> dcps = new ArrayList<DCP>(); 432 433 for ( Element element : nl ) { 434 dcps.add( parseDCP( element ) ); 435 } 436 437 return new Operation( new QualifiedName( name ), dcps, parameters, null, null, null ); 438 } 439 440 /** 441 * Parses a DCPType element. Does not override the method defined in the base class any more. 442 * 443 * @param element 444 * @return created <code>DCPType</code> 445 * @throws XMLParsingException 446 * @see org.deegree.ogcwebservices.getcapabilities.OGCStandardCapabilities 447 */ 448 protected DCP parseDCP( Element element ) 449 throws XMLParsingException { 450 451 List<HTTP.Type> types = new ArrayList<HTTP.Type>(); 452 List<OnlineResource> links = new ArrayList<OnlineResource>(); 453 454 Element elem = XMLTools.getRequiredElement( element, "HTTP", nsContext ); 455 String s = null; 456 try { 457 List<Node> nl = XMLTools.getNodes( elem, "Get", nsContext ); 458 459 for ( int i = 0; i < nl.size(); i++ ) { 460 s = XMLTools.getNodeAsString( nl.get( i ), "./@xlink:href", nsContext, null ); 461 if ( s == null ) { 462 s = XMLTools.getRequiredNodeAsString( nl.get( i ), "./OnlineResource/@xlink:href", nsContext ); 463 } 464 types.add( HTTP.Type.Get ); 465 links.add( new OnlineResource( new Linkage( new URL( s ) ) ) ); 466 } 467 } catch ( Exception e ) { 468 LOG.logError( e.getMessage(), e ); 469 throw new XMLParsingException( Messages.getMessage( "WMS_DCPGET", s ) ); 470 } 471 try { 472 List<Node> nl = XMLTools.getNodes( elem, "Post", nsContext ); 473 474 for ( int i = 0; i < nl.size(); i++ ) { 475 s = XMLTools.getNodeAsString( nl.get( i ), "./@xlink:href", nsContext, null ); 476 if ( s == null ) { 477 s = XMLTools.getRequiredNodeAsString( nl.get( i ), "./OnlineResource/@xlink:href", nsContext ); 478 } 479 types.add( HTTP.Type.Post ); 480 links.add( new OnlineResource( new Linkage( new URL( s ) ) ) ); 481 } 482 483 } catch ( MalformedURLException e ) { 484 throw new XMLParsingException( Messages.getMessage( "WMS_DCPPOST", s ) ); 485 } 486 HTTP http = new HTTP( links, null, types ); 487 488 return http; 489 } 490 491 /** 492 * 493 * @return the parsed data 494 * @throws XMLParsingException 495 */ 496 protected UserDefinedSymbolization parseUserDefinedSymbolization() 497 throws XMLParsingException { 498 499 boolean supportSLD = XMLTools.getNodeAsBoolean( getRootElement(), 500 "./Capability/UserDefinedSymbolization/@SupportSLD", nsContext, 501 false ); 502 503 boolean userLayer = XMLTools.getNodeAsBoolean( getRootElement(), 504 "./Capability/UserDefinedSymbolization/@UserLayer", nsContext, 505 false ); 506 507 boolean userStyle = XMLTools.getNodeAsBoolean( getRootElement(), 508 "./Capability/UserDefinedSymbolization/@UserStyle", nsContext, 509 false ); 510 511 boolean remoteWFS = XMLTools.getNodeAsBoolean( getRootElement(), 512 "./Capability/UserDefinedSymbolization/@RemoteWFS", nsContext, 513 false ); 514 515 UserDefinedSymbolization uds = new UserDefinedSymbolization( supportSLD, userLayer, remoteWFS, userStyle ); 516 517 return uds; 518 } 519 520 /** 521 * @param layerElem 522 * @param parent 523 * @param scaleHint 524 * 525 * @return the layer created from the given element 526 * @throws XMLParsingException 527 * @throws UnknownCRSException 528 */ 529 protected Layer parseLayers( Element layerElem, Layer parent, ScaleHint scaleHint ) 530 throws XMLParsingException, UnknownCRSException { 531 532 boolean queryable = XMLTools.getNodeAsBoolean( layerElem, "./@queryable", nsContext, false ); 533 534 int cascaded = XMLTools.getNodeAsInt( layerElem, "./@cascaded", nsContext, 0 ); 535 boolean opaque = XMLTools.getNodeAsBoolean( layerElem, "./@opaque", nsContext, false ); 536 boolean noSubsets = XMLTools.getNodeAsBoolean( layerElem, "./@noSubsets", nsContext, false ); 537 int fixedWidth = XMLTools.getNodeAsInt( layerElem, "./@fixedWidth", nsContext, 0 ); 538 int fixedHeight = XMLTools.getNodeAsInt( layerElem, "./@fixedHeight", nsContext, 0 ); 539 String name = XMLTools.getNodeAsString( layerElem, "./Name", nsContext, null ); 540 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Title", nsContext ); 541 String layerAbstract = XMLTools.getNodeAsString( layerElem, "./Abstract", nsContext, null ); 542 String[] keywords = XMLTools.getNodesAsStrings( layerElem, "./KeywordList/Keyword", nsContext ); 543 String[] srs = XMLTools.getNodesAsStrings( layerElem, "./SRS", nsContext ); 544 545 List<Element> nl = XMLTools.getElements( layerElem, "./BoundingBox", nsContext ); 546 // TODO 547 // substitue with Envelope 548 LayerBoundingBox[] bboxes = null; 549 if ( nl.size() == 0 && parent != null ) { 550 // inherit BoundingBoxes from parent layer 551 bboxes = parent.getBoundingBoxes(); 552 } else { 553 bboxes = parseLayerBoundingBoxes( nl ); 554 } 555 556 Element llBox = XMLTools.getElement( layerElem, "./LatLonBoundingBox", nsContext ); 557 Envelope llBoundingBox = null; 558 559 if ( llBox == null && parent != null ) { 560 // inherit LatLonBoundingBox parent layer 561 llBoundingBox = parent.getLatLonBoundingBox(); 562 } else if ( llBox != null ) { 563 llBoundingBox = parseLatLonBoundingBox( llBox ); 564 } else { 565 llBoundingBox = GeometryFactory.createEnvelope( -180, -90, 180, 90, CRSFactory.create( "EPSG:4326" ) ); 566 } 567 568 Dimension[] dimensions = parseDimensions( layerElem ); 569 Extent[] extents = parseExtents( layerElem ); 570 571 Attribution attribution = parseAttribution( layerElem ); 572 573 AuthorityURL[] authorityURLs = parseAuthorityURLs( layerElem ); 574 575 MetadataURL[] metadataURLs = parseMetadataURLs( layerElem ); 576 577 DataURL[] dataURLs = parseDataURL( layerElem ); 578 579 Identifier[] identifiers = parseIdentifiers( layerElem ); 580 581 FeatureListURL[] featureListURLs = parseFeatureListURL( layerElem ); 582 583 Style[] styles = parseStyles( layerElem ); 584 585 scaleHint = parseScaleHint( layerElem, scaleHint ); 586 587 Layer layer = new Layer( queryable, cascaded, opaque, noSubsets, fixedWidth, fixedHeight, name, title, 588 layerAbstract, llBoundingBox, attribution, scaleHint, keywords, srs, bboxes, 589 dimensions, extents, authorityURLs, identifiers, metadataURLs, dataURLs, 590 featureListURLs, styles, null, null, parent ); 591 592 // get Child layers 593 nl = XMLTools.getElements( layerElem, "./Layer", nsContext ); 594 Layer[] layers = new Layer[nl.size()]; 595 for ( int i = 0; i < layers.length; i++ ) { 596 layers[i] = parseLayers( nl.get( i ), layer, scaleHint ); 597 } 598 599 // set child layers 600 layer.setLayer( layers ); 601 602 return layer; 603 } 604 605 /** 606 * 607 * @param layerElem 608 * @return the dimensions 609 * @throws XMLParsingException 610 */ 611 protected Dimension[] parseDimensions( Element layerElem ) 612 throws XMLParsingException { 613 614 List<Node> nl = XMLTools.getNodes( layerElem, "./Dimension", nsContext ); 615 Dimension[] dimensions = new Dimension[nl.size()]; 616 for ( int i = 0; i < dimensions.length; i++ ) { 617 String name = XMLTools.getNodeAsString( nl.get( i ), "./@name", nsContext, null ); 618 String units = XMLTools.getNodeAsString( nl.get( i ), "./@units", nsContext, null ); 619 String unitSymbol = XMLTools.getNodeAsString( nl.get( i ), "./@unitSymbol", nsContext, null ); 620 dimensions[i] = new Dimension( name, units, unitSymbol ); 621 } 622 623 return dimensions; 624 } 625 626 /** 627 * 628 * @param layerElem 629 * @return the extent 630 * @throws XMLParsingException 631 */ 632 protected Extent[] parseExtents( Element layerElem ) 633 throws XMLParsingException { 634 635 List<Node> nl = XMLTools.getNodes( layerElem, "./Extent", nsContext ); 636 Extent[] extents = new Extent[nl.size()]; 637 for ( int i = 0; i < extents.length; i++ ) { 638 String name = XMLTools.getNodeAsString( nl.get( i ), "./@name", nsContext, null ); 639 String deflt = XMLTools.getNodeAsString( nl.get( i ), "./@default", nsContext, null ); 640 boolean nearestValue = XMLTools.getNodeAsBoolean( nl.get( i ), "./@nearestValue", nsContext, false ); 641 String value = XMLTools.getNodeAsString( nl.get( i ), ".", nsContext, "" ); 642 extents[i] = new Extent( name, deflt, nearestValue, value ); 643 } 644 645 return extents; 646 } 647 648 /** 649 * 650 * @param layerElem 651 * @return the attribution 652 * @throws XMLParsingException 653 */ 654 protected Attribution parseAttribution( Element layerElem ) 655 throws XMLParsingException { 656 657 Attribution attribution = null; 658 Node node = XMLTools.getNode( layerElem, "./Attribution", nsContext ); 659 if ( node != null ) { 660 String title = XMLTools.getRequiredNodeAsString( layerElem, "./Attribution/Title", nsContext ); 661 OnlineResource onLineResource = parseOnLineResource( XMLTools.getRequiredElement( node, "./OnlineResource", 662 nsContext ) ); 663 node = XMLTools.getNode( node, "./LogoURL", nsContext ); 664 LogoURL logoURL = null; 665 if ( node != null ) { 666 int width = XMLTools.getRequiredNodeAsInt( node, "./@width", nsContext ); 667 int height = XMLTools.getRequiredNodeAsInt( node, "./@height", nsContext ); 668 String format = XMLTools.getRequiredNodeAsString( node, "./Format", nsContext ); 669 OnlineResource logoOR = parseOnLineResource( XMLTools.getRequiredElement( node, "./OnlineResource", 670 nsContext ) ); 671 logoURL = new LogoURL( width, height, format, logoOR.getLinkage().getHref() ); 672 } 673 attribution = new Attribution( title, onLineResource.getLinkage().getHref(), logoURL ); 674 } 675 676 return attribution; 677 } 678 679 /** 680 * 681 * @param layerElem 682 * @return the URLs 683 * @throws XMLParsingException 684 */ 685 protected AuthorityURL[] parseAuthorityURLs( Element layerElem ) 686 throws XMLParsingException { 687 688 List<Node> nl = XMLTools.getNodes( layerElem, "./AuthorityURL", nsContext ); 689 AuthorityURL[] authorityURLs = new AuthorityURL[nl.size()]; 690 for ( int i = 0; i < authorityURLs.length; i++ ) { 691 String name = XMLTools.getRequiredNodeAsString( nl.get( i ), "./@name", nsContext ); 692 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 693 OnlineResource olr = parseOnLineResource( tmp ); 694 authorityURLs[i] = new AuthorityURL( name, olr.getLinkage().getHref() ); 695 } 696 697 return authorityURLs; 698 } 699 700 /** 701 * 702 * @param layerElem 703 * @return the URLs 704 * @throws XMLParsingException 705 */ 706 protected MetadataURL[] parseMetadataURLs( Element layerElem ) 707 throws XMLParsingException { 708 709 List<Node> nl = XMLTools.getNodes( layerElem, "./MetadataURL", nsContext ); 710 MetadataURL[] metadataURL = new MetadataURL[nl.size()]; 711 for ( int i = 0; i < metadataURL.length; i++ ) { 712 String type = XMLTools.getRequiredNodeAsString( nl.get( i ), "./@type", nsContext ); 713 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 714 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 715 OnlineResource olr = parseOnLineResource( tmp ); 716 metadataURL[i] = new MetadataURL( type, format, olr.getLinkage().getHref() ); 717 718 } 719 720 return metadataURL; 721 } 722 723 /** 724 * 725 * @param layerElem 726 * @return the URLs 727 * @throws XMLParsingException 728 */ 729 protected DataURL[] parseDataURL( Element layerElem ) 730 throws XMLParsingException { 731 732 List<Node> nl = XMLTools.getNodes( layerElem, "./DataURL", nsContext ); 733 DataURL[] dataURL = new DataURL[nl.size()]; 734 for ( int i = 0; i < dataURL.length; i++ ) { 735 736 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 737 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 738 OnlineResource olr = parseOnLineResource( tmp ); 739 dataURL[i] = new DataURL( format, olr.getLinkage().getHref() ); 740 741 } 742 743 return dataURL; 744 } 745 746 /** 747 * 748 * @param layerElem 749 * @return the URLs 750 * @throws XMLParsingException 751 */ 752 protected FeatureListURL[] parseFeatureListURL( Element layerElem ) 753 throws XMLParsingException { 754 755 List<Node> nl = XMLTools.getNodes( layerElem, "./FeatureListURL", nsContext ); 756 FeatureListURL[] flURL = new FeatureListURL[nl.size()]; 757 for ( int i = 0; i < flURL.length; i++ ) { 758 759 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 760 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 761 OnlineResource olr = parseOnLineResource( tmp ); 762 flURL[i] = new FeatureListURL( format, olr.getLinkage().getHref() ); 763 764 } 765 766 return flURL; 767 } 768 769 /** 770 * 771 * @param layerElem 772 * @return the styles 773 * @throws XMLParsingException 774 */ 775 protected Style[] parseStyles( Element layerElem ) 776 throws XMLParsingException { 777 778 List<Node> nl = XMLTools.getNodes( layerElem, "./Style", nsContext ); 779 Style[] styles = new Style[nl.size()]; 780 for ( int i = 0; i < styles.length; i++ ) { 781 String name = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Name", nsContext ); 782 783 if ( name == null ) { 784 throw new XMLParsingException( Messages.getMessage( "WMS_STYLENAME" ) ); 785 } 786 String title = XMLTools.getNodeAsString( nl.get( i ), "./Title", nsContext, null ); 787 if ( title == null ) { 788 throw new XMLParsingException( Messages.getMessage( "WMS_STYLETITLE" ) ); 789 } 790 String styleAbstract = XMLTools.getNodeAsString( nl.get( i ), "./Abstract", nsContext, null ); 791 LegendURL[] legendURLs = parseLegendURL( nl.get( i ) ); 792 StyleURL styleURL = parseStyleURL( nl.get( i ) ); 793 StyleSheetURL styleSheetURL = parseStyleSheetURL( nl.get( i ) ); 794 795 styles[i] = new Style( name, title, styleAbstract, legendURLs, styleSheetURL, styleURL, null ); 796 } 797 798 return styles; 799 } 800 801 /** 802 * 803 * @param node 804 * @return the URLs 805 * @throws XMLParsingException 806 */ 807 protected LegendURL[] parseLegendURL( Node node ) 808 throws XMLParsingException { 809 810 List<Node> nl = XMLTools.getNodes( node, "./LegendURL", nsContext ); 811 LegendURL[] lURL = new LegendURL[nl.size()]; 812 for ( int i = 0; i < lURL.length; i++ ) { 813 int width = XMLTools.getRequiredNodeAsInt( nl.get( i ), "./@width", nsContext ); 814 int height = XMLTools.getRequiredNodeAsInt( nl.get( i ), "./@height", nsContext ); 815 String format = XMLTools.getRequiredNodeAsString( nl.get( i ), "./Format", nsContext ); 816 Element tmp = XMLTools.getRequiredElement( nl.get( i ), "./OnlineResource", nsContext ); 817 OnlineResource olr = parseOnLineResource( tmp ); 818 lURL[i] = new LegendURL( width, height, format, olr.getLinkage().getHref() ); 819 820 } 821 822 return lURL; 823 } 824 825 /** 826 * 827 * @param node 828 * @return the URL 829 * @throws XMLParsingException 830 */ 831 protected StyleURL parseStyleURL( Node node ) 832 throws XMLParsingException { 833 834 StyleURL styleURL = null; 835 Node styleNode = XMLTools.getNode( node, "./StyleURL", nsContext ); 836 837 if ( styleNode != null ) { 838 String format = XMLTools.getRequiredNodeAsString( styleNode, "./Format", nsContext ); 839 Element tmp = XMLTools.getRequiredElement( styleNode, "./OnlineResource", nsContext ); 840 OnlineResource olr = parseOnLineResource( tmp ); 841 styleURL = new StyleURL( format, olr.getLinkage().getHref() ); 842 843 } 844 845 return styleURL; 846 } 847 848 /** 849 * 850 * @param node 851 * @return the URL 852 * @throws XMLParsingException 853 */ 854 protected StyleSheetURL parseStyleSheetURL( Node node ) 855 throws XMLParsingException { 856 857 StyleSheetURL styleSheetURL = null; 858 Node styleNode = XMLTools.getNode( node, "./StyleSheetURL", nsContext ); 859 860 if ( styleNode != null ) { 861 String format = XMLTools.getRequiredNodeAsString( styleNode, "./Format", nsContext ); 862 Element tmp = XMLTools.getRequiredElement( styleNode, "./OnlineResource", nsContext ); 863 OnlineResource olr = parseOnLineResource( tmp ); 864 styleSheetURL = new StyleSheetURL( format, olr.getLinkage().getHref() ); 865 866 } 867 868 return styleSheetURL; 869 } 870 871 /** 872 * 873 * @param layerElem 874 * @param scaleHint 875 * the default scale hint 876 * @return the scale hint 877 * @throws XMLParsingException 878 */ 879 protected ScaleHint parseScaleHint( Element layerElem, ScaleHint scaleHint ) 880 throws XMLParsingException { 881 882 Node scNode = XMLTools.getNode( layerElem, "./ScaleHint", nsContext ); 883 if ( scNode != null ) { 884 double mn = XMLTools.getNodeAsDouble( scNode, "./@min", nsContext, 0 ); 885 double mx = XMLTools.getNodeAsDouble( scNode, "./@max", nsContext, Double.MAX_VALUE ); 886 scaleHint = new ScaleHint( mn, mx ); 887 } 888 889 if ( scaleHint == null ) { 890 // set default value to avoid NullPointerException 891 // when accessing a layers scalehint 892 scaleHint = new ScaleHint( 0, Double.MAX_VALUE ); 893 } 894 895 return scaleHint; 896 } 897 898 /** 899 * 900 * @param layerElem 901 * @return the identifiers 902 * @throws XMLParsingException 903 */ 904 protected Identifier[] parseIdentifiers( Element layerElem ) 905 throws XMLParsingException { 906 907 List<Node> nl = XMLTools.getNodes( layerElem, "./Identifier", nsContext ); 908 Identifier[] identifiers = new Identifier[nl.size()]; 909 for ( int i = 0; i < identifiers.length; i++ ) { 910 String value = XMLTools.getStringValue( nl.get( i ) ); 911 String authority = XMLTools.getNodeAsString( layerElem, "./@authority", nsContext, null ); 912 identifiers[i] = new Identifier( value, authority ); 913 } 914 915 return identifiers; 916 } 917 918 /** 919 * 920 * @param nl 921 * @return the bboxes 922 * @throws XMLParsingException 923 */ 924 protected LayerBoundingBox[] parseLayerBoundingBoxes( List<Element> nl ) 925 throws XMLParsingException { 926 927 LayerBoundingBox[] llBoxes = new LayerBoundingBox[nl.size()]; 928 for ( int i = 0; i < llBoxes.length; i++ ) { 929 double minx = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@minx", nsContext ); 930 double maxx = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@maxx", nsContext ); 931 double miny = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@miny", nsContext ); 932 double maxy = XMLTools.getRequiredNodeAsDouble( nl.get( i ), "./@maxy", nsContext ); 933 double resx = XMLTools.getNodeAsDouble( nl.get( i ), "./@resx", nsContext, -1 ); 934 double resy = XMLTools.getNodeAsDouble( nl.get( i ), "./@resx", nsContext, -1 ); 935 String srs = XMLTools.getRequiredNodeAsString( nl.get( i ), "./@SRS", nsContext ); 936 Position min = GeometryFactory.createPosition( minx, miny ); 937 Position max = GeometryFactory.createPosition( maxx, maxy ); 938 llBoxes[i] = new LayerBoundingBox( min, max, srs, resx, resy ); 939 } 940 941 return llBoxes; 942 } 943 944 /** 945 * 946 * @param llBox 947 * @return the envelope 948 * @throws XMLParsingException 949 * @throws UnknownCRSException 950 */ 951 protected Envelope parseLatLonBoundingBox( Element llBox ) 952 throws XMLParsingException, UnknownCRSException { 953 954 double minx = XMLTools.getRequiredNodeAsDouble( llBox, "./@minx", nsContext ); 955 double maxx = XMLTools.getRequiredNodeAsDouble( llBox, "./@maxx", nsContext ); 956 double miny = XMLTools.getRequiredNodeAsDouble( llBox, "./@miny", nsContext ); 957 double maxy = XMLTools.getRequiredNodeAsDouble( llBox, "./@maxy", nsContext ); 958 CoordinateSystem crs = CRSFactory.create( "EPSG:4326" ); 959 960 Envelope env = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, crs ); 961 962 return env; 963 } 964 965 }