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