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