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