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