001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wms/XMLFactory.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041     
042     ---------------------------------------------------------------------------*/
043    package org.deegree.ogcwebservices.wms;
044    
045    import java.io.IOException;
046    import java.net.URL;
047    import java.util.List;
048    
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.NamespaceContext;
055    import org.deegree.framework.xml.XMLParsingException;
056    import org.deegree.framework.xml.XMLTools;
057    import org.deegree.model.metadata.iso19115.Address;
058    import org.deegree.model.metadata.iso19115.Keywords;
059    import org.deegree.model.metadata.iso19115.OnlineResource;
060    import org.deegree.model.metadata.iso19115.Phone;
061    import org.deegree.model.spatialschema.Envelope;
062    import org.deegree.ogcbase.CommonNamespaces;
063    import org.deegree.ogcwebservices.OWSUtils;
064    import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
065    import org.deegree.ogcwebservices.wms.capabilities.Attribution;
066    import org.deegree.ogcwebservices.wms.capabilities.AuthorityURL;
067    import org.deegree.ogcwebservices.wms.capabilities.DataURL;
068    import org.deegree.ogcwebservices.wms.capabilities.Dimension;
069    import org.deegree.ogcwebservices.wms.capabilities.Extent;
070    import org.deegree.ogcwebservices.wms.capabilities.FeatureListURL;
071    import org.deegree.ogcwebservices.wms.capabilities.Identifier;
072    import org.deegree.ogcwebservices.wms.capabilities.Layer;
073    import org.deegree.ogcwebservices.wms.capabilities.LayerBoundingBox;
074    import org.deegree.ogcwebservices.wms.capabilities.LegendURL;
075    import org.deegree.ogcwebservices.wms.capabilities.LogoURL;
076    import org.deegree.ogcwebservices.wms.capabilities.ScaleHint;
077    import org.deegree.ogcwebservices.wms.capabilities.Style;
078    import org.deegree.ogcwebservices.wms.capabilities.StyleSheetURL;
079    import org.deegree.ogcwebservices.wms.capabilities.StyleURL;
080    import org.deegree.ogcwebservices.wms.capabilities.UserDefinedSymbolization;
081    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
082    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
083    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities_1_3_0;
084    import org.deegree.owscommon_new.DCP;
085    import org.deegree.owscommon_new.DomainType;
086    import org.deegree.owscommon_new.HTTP;
087    import org.deegree.owscommon_new.Operation;
088    import org.deegree.owscommon_new.OperationsMetadata;
089    import org.deegree.owscommon_new.ServiceIdentification;
090    import org.deegree.owscommon_new.ServiceProvider;
091    import org.w3c.dom.Element;
092    import org.xml.sax.SAXException;
093    
094    /**
095     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
096     * @author last edited by: $Author: apoth $
097     * 
098     * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $
099     */
100    public class XMLFactory extends org.deegree.owscommon.XMLFactory {
101    
102        private static final ILogger LOG = LoggerFactory.getLogger( XMLFactory.class );
103    
104        private static NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
105    
106        /**
107         * Exports a <code>WMSCapabilities</code> instance to a <code>WMSCapabilitiesDocument</code>.
108         * 
109         * @param capabilities
110         * @return DOM representation of the <code>WMSCapabilities</code>
111         * @throws IOException
112         *             if XML template could not be loaded
113         */
114        public static WMSCapabilitiesDocument export( WMSCapabilities capabilities )
115                                throws IOException {
116    
117            // in case of a 1.3.0 capabilities, switch the method
118            if ( capabilities instanceof WMSCapabilities_1_3_0 ) {
119                return XMLFactory_1_3_0.export( (WMSCapabilities_1_3_0) capabilities );
120            }
121    
122            WMSCapabilitiesDocument capabilitiesDocument = new WMSCapabilitiesDocument();
123            try {
124                capabilitiesDocument.createEmptyDocument();
125                Element root = capabilitiesDocument.getRootElement();
126    
127                root.setAttribute( "version", "1.1.1" );
128                root.setAttribute( "updateSequence", capabilities.getUpdateSequence() );
129    
130                appendService( root, capabilities.getServiceIdentification(), capabilities.getServiceProvider() );
131    
132                appendCapabilityRequests( root, capabilities.getOperationMetadata() );
133    
134                appendUserDefinedSymbolization( (Element) XMLTools.getNode( root, "./Capability", nsContext ),
135                                                capabilities.getUserDefinedSymbolization() );
136    
137                appendCapabilityLayer( (Element) XMLTools.getNode( root, "./Capability", nsContext ),
138                                       capabilities.getLayer() );
139    
140                Element exc = XMLTools.getRequiredElement( root, "Capability/Exception", nsContext );
141                for ( String f : capabilities.getExceptions() ) {
142                    XMLTools.appendElement( exc, null, "Format", f );
143                }
144    
145            } catch ( SAXException e ) {
146                LOG.logError( e.getMessage(), e );
147            } catch ( XMLParsingException e ) {
148                LOG.logError( e.getMessage(), e );
149            }
150    
151            return capabilitiesDocument;
152        }
153    
154        /**
155         * This method exports a 1.3.0 capabilities document as 1.1.1, providing backward compatibility.
156         * 
157         * @param capabilities
158         * @return the 1.1.1 document
159         * @throws IOException
160         */
161        public static WMSCapabilitiesDocument exportAs_1_1_1( WMSCapabilities_1_3_0 capabilities )
162                                throws IOException {
163            WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument();
164    
165            try {
166                doc.createEmptyDocument();
167    
168                Element root = doc.getRootElement();
169    
170                root.setAttribute( "version", "1.1.1" );
171                root.setAttribute( "updateSequence", capabilities.getUpdateSequence() );
172    
173                appendService( root, capabilities.getServiceIdentification(), capabilities.getServiceProvider() );
174    
175                appendCapabilityRequests( root, capabilities.getOperationMetadata() );
176    
177                Element cap = (Element) XMLTools.getNode( root, "Capability", nsContext );
178                // we don't have that one in 1.3.0 data, so just make it up since it is generally
179                // enabled in deegree WMS
180                UserDefinedSymbolization uds = new UserDefinedSymbolization( true, true, false, true );
181                appendUserDefinedSymbolization( cap, uds );
182    
183                appendCapabilityLayer( cap, capabilities.getLayer() );
184    
185                Element exc = XMLTools.getRequiredElement( root, "Capability/Exception", nsContext );
186                for ( String f : capabilities.getExceptions() ) {
187                    if ( f.equalsIgnoreCase( "XML" ) ) {
188                        f = "application/vnd.ogc.se_xml";
189                    }
190                    if ( f.equalsIgnoreCase( "INIMAGE" ) ) {
191                        f = "application/vnd.ogc.se_inimage";
192                    }
193                    if ( f.equalsIgnoreCase( "BLANK" ) ) {
194                        f = "application/vnd.ogc.se_blank";
195                    }
196                    XMLTools.appendElement( exc, null, "Format", f );
197                }
198    
199            } catch ( XMLParsingException e ) {
200                LOG.logError( e.getMessage(), e );
201            } catch ( SAXException e ) {
202                LOG.logError( e.getMessage(), e );
203            }
204    
205            return doc;
206        }
207    
208        /**
209         * 
210         * @param root
211         * @param uds
212         */
213        protected static void appendUserDefinedSymbolization( Element root, UserDefinedSymbolization uds ) {
214    
215            Element elem = XMLTools.appendElement( root, null, "UserDefinedSymbolization" );
216            elem.setAttribute( "SupportSLD", boolean2Number( uds.isSldSupported() ) );
217            elem.setAttribute( "UserLayer", boolean2Number( uds.isUserLayerSupported() ) );
218            elem.setAttribute( "UserStyle", boolean2Number( uds.isUserStyleSupported() ) );
219            elem.setAttribute( "RemoteWFS", boolean2Number( uds.isRemoteWFSSupported() ) );
220    
221        }
222    
223        private static String boolean2Number( boolean bool ) {
224            if ( bool ) {
225                return "1";
226            }
227            return "0";
228        }
229    
230        /**
231         * 
232         * @param root
233         * @param identification
234         * @param provider
235         * @throws XMLParsingException
236         */
237        protected static void appendService( Element root, ServiceIdentification identification, ServiceProvider provider )
238                                throws XMLParsingException {
239    
240            root = (Element) XMLTools.getRequiredNode( root, "./Service", nsContext );
241    
242            Element node = (Element) XMLTools.getRequiredNode( root, "./Name", nsContext );
243            // is this actually desired?
244            node.setTextContent( "OGC:WMS" );
245    
246            node = (Element) XMLTools.getRequiredNode( root, "./Title", nsContext );
247            node.setTextContent( identification.getTitle() );
248    
249            String serviceAbstract = identification.getAbstractString();
250            if ( serviceAbstract != null ) {
251                XMLTools.appendElement( root, null, "Abstract", serviceAbstract );
252            }
253    
254            List<Keywords> keywords = identification.getKeywords();
255            if ( keywords.size() > 0 ) {
256                String[] kw = keywords.get( 0 ).getKeywords();
257                Element kwl = XMLTools.appendElement( root, null, "KeywordList" );
258                for ( int i = 0; i < kw.length; i++ ) {
259                    XMLTools.appendElement( kwl, null, "Keyword", kw[i] );
260                }
261            }
262    
263            node = root.getOwnerDocument().createElement( "OnlineResource" );
264    
265            OnlineResource sLink = provider.getProviderSite();
266            org.deegree.model.metadata.iso19115.XMLFactory.appendOnlineResource( node, sLink );
267    
268            root.appendChild( node );
269    
270            appendContactInformation( root, provider );
271    
272            String fee = null;
273            if ( identification.getAccessConstraints().size() > 0 )
274                fee = identification.getAccessConstraints().get( 0 ).getFees();
275            if ( fee != null ) {
276                XMLTools.appendElement( root, null, "Fees", fee );
277            } else {
278                XMLTools.appendElement( root, null, "Fees", "none" );
279            }
280    
281            if ( identification.getAccessConstraints().size() > 0 ) {
282                XMLTools.appendElement( root, null, "AccessConstraints",
283                                        identification.getAccessConstraints().get( 0 ).getUseLimitations().get( 0 ) );
284            } else {
285                XMLTools.appendElement( root, null, "AccessConstraints", "none" );
286            }
287    
288        }
289    
290        /**
291         * 
292         * @param root
293         * @param provider
294         */
295        protected static void appendContactInformation( Element root, ServiceProvider provider ) {
296    
297            Element ciNode = XMLTools.appendElement( root, null, "ContactInformation" );
298            Element cppNode = XMLTools.appendElement( ciNode, null, "ContactPersonPrimary" );
299            if ( provider.getServiceContact().getIndividualName().length > 0 ) {
300                XMLTools.appendElement( cppNode, null, "ContactPerson", provider.getServiceContact().getIndividualName()[0] );
301            }
302            if ( provider.getServiceContact().getOrganisationName().length > 0 ) {
303                XMLTools.appendElement( cppNode, null, "ContactOrganization",
304                                        provider.getServiceContact().getOrganisationName()[0] );
305            }
306            if ( provider.getServiceContact().getPositionName().length > 0 ) {
307                XMLTools.appendElement( ciNode, null, "ContactPosition", provider.getServiceContact().getPositionName()[0] );
308            }
309            Element caNode = XMLTools.appendElement( ciNode, null, "ContactAddress" );
310    
311            XMLTools.appendElement( caNode, null, "AddressType", "postal" );
312    
313            if ( provider.getServiceContact().getContactInfo().length > 0 ) {
314                Address addr = provider.getServiceContact().getContactInfo()[0].getAddress();
315                String[] dp = addr.getDeliveryPoint();
316                if ( dp.length > 0 ) {
317                    XMLTools.appendElement( caNode, null, "Address", dp[0] );
318                }
319                if ( addr.getCity() != null ) {
320                    XMLTools.appendElement( caNode, null, "City", addr.getCity() );
321                }
322                if ( addr.getAdministrativeArea() != null ) {
323                    XMLTools.appendElement( caNode, null, "StateOrProvince", addr.getAdministrativeArea() );
324                }
325                if ( addr.getPostalCode() != null ) {
326                    XMLTools.appendElement( caNode, null, "PostCode", addr.getPostalCode() );
327                }
328                if ( addr.getCountry() != null ) {
329                    XMLTools.appendElement( caNode, null, "Country", addr.getCountry() );
330                }
331    
332                Phone phone = provider.getServiceContact().getContactInfo()[0].getPhone();
333                if ( phone.getVoice().length > 0 ) {
334                    XMLTools.appendElement( ciNode, null, "ContactVoiceTelephone", phone.getVoice()[0] );
335                }
336                if ( phone.getFacsimile().length > 0 ) {
337                    XMLTools.appendElement( ciNode, null, "ContactFacsimileTelephone", phone.getFacsimile()[0] );
338                }
339                if ( addr.getElectronicMailAddress().length > 0 ) {
340                    XMLTools.appendElement( ciNode, null, "ContactElectronicMailAddress",
341                                            addr.getElectronicMailAddress()[0] );
342                }
343            }
344    
345        }
346    
347        /**
348         * 
349         * @param root
350         * @param operationsMetadata
351         * @throws XMLParsingException
352         */
353        protected static void appendCapabilityRequests( Element root, OperationsMetadata operationsMetadata )
354                                throws XMLParsingException {
355    
356            root = (Element) XMLTools.getRequiredNode( root, "./Capability/Request", nsContext );
357    
358            operationsMetadata.getOperations();
359    
360            // just append all operations
361            for ( Operation operation : operationsMetadata.getOperations() ) {
362                appendOperation( root, operation );
363            }
364    
365        }
366    
367        /**
368         * 
369         * @param root
370         * @param operation
371         */
372        protected static void appendOperation( Element root, Operation operation ) {
373    
374            String name = operation.getName().getLocalName();
375    
376            root = XMLTools.appendElement( root, null, name );
377    
378            DomainType odt = (DomainType) operation.getParameter( new QualifiedName( "Format" ) );
379    
380            List<TypedLiteral> values = odt.getValues();
381            for ( TypedLiteral value : values )
382                XMLTools.appendElement( root, null, "Format", value.getValue() );
383    
384            List<DCP> dcps = operation.getDCP();
385            for ( DCP dcp : dcps ) {
386                Element http = XMLTools.appendElement( root, null, "DCPType" );
387                http = XMLTools.appendElement( http, null, "HTTP" );
388                HTTP ht = (HTTP) dcp;
389                List<HTTP.Type> types = ht.getTypes();
390                List<OnlineResource> links = ht.getLinks();
391                for ( int i = 0; i < types.size(); ++i ) {
392                    Element elem = null;
393                    if ( types.get( i ) == HTTP.Type.Get )
394                        elem = XMLTools.appendElement( http, null, "Get" );
395                    if ( types.get( i ) == HTTP.Type.Post )
396                        elem = XMLTools.appendElement( http, null, "Post" );
397                    if ( elem != null ) {
398                        elem = XMLTools.appendElement( elem, null, "OnlineResource" );
399                        org.deegree.model.metadata.iso19115.XMLFactory.appendOnlineResource( elem, links.get( i ) );
400                    }
401                }
402            }
403    
404        }
405    
406        /**
407         * 
408         * @param root
409         * @param layer
410         * @throws XMLParsingException
411         */
412        protected static void appendCapabilityLayer( Element root, Layer layer )
413                                throws XMLParsingException {
414    
415            root = XMLTools.appendElement( root, null, "Layer" );
416            root.setAttribute( "queryable", boolean2Number( layer.isQueryable() ) );
417            root.setAttribute( "cascaded", Integer.toString( layer.getCascaded() ) );
418            root.setAttribute( "opaque", boolean2Number( layer.isOpaque() ) );
419            root.setAttribute( "noSubsets", boolean2Number( layer.hasNoSubsets() ) );
420            if ( layer.getFixedWidth() > 0 ) {
421                root.setAttribute( "fixedWidth", Integer.toString( layer.getFixedWidth() ) );
422            }
423            if ( layer.getFixedHeight() > 0 ) {
424                root.setAttribute( "fixedHeight", Integer.toString( layer.getFixedHeight() ) );
425            }
426    
427            if ( layer.getName() != null ) {
428                XMLTools.appendElement( root, null, "Name", layer.getName() );
429            }
430            XMLTools.appendElement( root, null, "Title", layer.getTitle() );
431    
432            if ( layer.getAbstract() != null ) {
433                XMLTools.appendElement( root, null, "Abstract", layer.getAbstract() );
434            }
435    
436            String[] keywords = layer.getKeywordList();
437            if ( keywords.length > 0 ) {
438                Element elem = XMLTools.appendElement( root, null, "KeywordList" );
439                for ( int i = 0; i < keywords.length; i++ ) {
440                    XMLTools.appendElement( elem, null, "Keyword", keywords[i] );
441                }
442            }
443    
444            String[] srs = layer.getSrs();
445            for ( int i = 0; i < srs.length; i++ ) {
446                XMLTools.appendElement( root, null, "SRS", srs[i] );
447            }
448    
449            Envelope llBox = layer.getLatLonBoundingBox();
450            appendLatLonBoundingBox( root, llBox );
451    
452            LayerBoundingBox[] lBoxes = layer.getBoundingBoxes();
453            for ( int i = 0; i < lBoxes.length; i++ ) {
454                appendLayerBoundingBox( root, lBoxes[i] );
455            }
456    
457            Dimension[] dims = layer.getDimension();
458            for ( int i = 0; i < dims.length; i++ ) {
459                appendDimension( root, dims[i] );
460            }
461    
462            Extent[] extents = layer.getExtent();
463            for ( int i = 0; i < extents.length; i++ ) {
464                appendExtent( root, extents[i] );
465            }
466    
467            Attribution attr = layer.getAttribution();
468            if ( attr != null ) {
469                appendAttribution( root, attr );
470            }
471    
472            AuthorityURL[] authorityURLs = layer.getAuthorityURL();
473            for ( int i = 0; i < authorityURLs.length; i++ ) {
474                appendAuthorityURL( root, authorityURLs[i] );
475            }
476    
477            Identifier[] identifiers = layer.getIdentifier();
478            for ( int i = 0; i < identifiers.length; i++ ) {
479                appendIdentifier( root, identifiers[i] );
480            }
481    
482            MetadataURL[] metadataURLs = layer.getMetadataURL();
483            for ( int i = 0; i < metadataURLs.length; i++ ) {
484                appendMetadataURL( root, metadataURLs[i] );
485            }
486    
487            DataURL[] dataURLs = layer.getDataURL();
488            for ( int i = 0; i < dataURLs.length; i++ ) {
489                appendDataURL( root, dataURLs[i] );
490            }
491    
492            FeatureListURL[] featureListURLs = layer.getFeatureListURL();
493            for ( int i = 0; i < featureListURLs.length; i++ ) {
494                appendFeatureListURL( root, featureListURLs[i] );
495            }
496    
497            if ( layer.getName() != null && layer.getName().length() > 0 ) {
498                Style[] styles = layer.getStyles();
499                for ( int i = 0; i < styles.length; i++ ) {
500                    appendStyle( root, styles[i] );
501                }
502            }
503    
504            ScaleHint scaleHint = layer.getScaleHint();
505            Element elem = XMLTools.appendElement( root, null, "ScaleHint" );
506            elem.setAttribute( "min", "" + scaleHint.getMin() );
507            elem.setAttribute( "max", "" + scaleHint.getMax() );
508    
509            Layer[] layers = layer.getLayer();
510            for ( int i = 0; i < layers.length; i++ ) {
511                appendCapabilityLayer( root, layers[i] );
512            }
513    
514        }
515    
516        /**
517         * 
518         * @param root
519         * @param style
520         */
521        protected static void appendStyle( Element root, Style style ) {
522    
523            String nm = style.getName();
524            String tlt = style.getTitle();
525            if ( nm.startsWith( "default:" ) ) {
526                nm = "default";
527                if ( tlt != null ) {
528                    tlt = StringTools.replace( tlt, "default:", "", false ) + " (default)";
529                }
530            }
531    
532            root = XMLTools.appendElement( root, null, "Style" );
533            XMLTools.appendElement( root, null, "Name", nm );
534            if ( style.getTitle() != null ) {
535                XMLTools.appendElement( root, null, "Title", tlt );
536            }
537            if ( style.getAbstract() != null ) {
538                XMLTools.appendElement( root, null, "Abstract", style.getAbstract() );
539            }
540            LegendURL[] legendURLs = style.getLegendURL();
541            for ( int i = 0; i < legendURLs.length; i++ ) {
542                appendLegendURL( root, legendURLs[i] );
543            }
544    
545            StyleSheetURL styleSheetURL = style.getStyleSheetURL();
546            if ( styleSheetURL != null ) {
547                appendStyleSheetURL( root, styleSheetURL );
548            }
549    
550            StyleURL styleURL = style.getStyleURL();
551            if ( styleURL != null ) {
552                appendStyleURL( root, styleURL );
553            }
554    
555        }
556    
557        /**
558         * @param root
559         * @param styleURL
560         */
561        protected static void appendStyleURL( Element root, StyleURL styleURL ) {
562            Element elem = XMLTools.appendElement( root, null, "StyleURL" );
563            XMLTools.appendElement( elem, null, "Format", styleURL.getFormat() );
564            appendOnlineResource( elem, styleURL.getOnlineResource(), false );
565        }
566    
567        /**
568         * @param root
569         * @param styleSheetURL
570         */
571        protected static void appendStyleSheetURL( Element root, StyleSheetURL styleSheetURL ) {
572            Element elem = XMLTools.appendElement( root, null, "StyleSheetURL" );
573            XMLTools.appendElement( elem, null, "Format", styleSheetURL.getFormat() );
574            appendOnlineResource( elem, styleSheetURL.getOnlineResource(), false );
575        }
576    
577        /**
578         * @param root
579         * @param legendURL
580         */
581        protected static void appendLegendURL( Element root, LegendURL legendURL ) {
582            Element elem = XMLTools.appendElement( root, null, "LegendURL" );
583            elem.setAttribute( "width", "" + legendURL.getWidth() );
584            elem.setAttribute( "height", "" + legendURL.getWidth() );
585            XMLTools.appendElement( elem, null, "Format", legendURL.getFormat() );
586    
587            appendOnlineResource( elem, legendURL.getOnlineResource(), false );
588        }
589    
590        /**
591         * @param root
592         * @param featureListURL
593         */
594        protected static void appendFeatureListURL( Element root, FeatureListURL featureListURL ) {
595            Element elem = XMLTools.appendElement( root, null, "FeatureListURL" );
596            XMLTools.appendElement( elem, null, "Format", featureListURL.getFormat() );
597            appendOnlineResource( elem, featureListURL.getOnlineResource(), false );
598        }
599    
600        /**
601         * @param root
602         * @param dataURL
603         */
604        protected static void appendDataURL( Element root, DataURL dataURL ) {
605            Element elem = XMLTools.appendElement( root, null, "DataURL" );
606            XMLTools.appendElement( elem, null, "Format", dataURL.getFormat() );
607            appendOnlineResource( elem, dataURL.getOnlineResource(), false );
608        }
609    
610        /**
611         * @param root
612         * @param metadataURL
613         */
614        protected static void appendMetadataURL( Element root, MetadataURL metadataURL ) {
615            Element elem = XMLTools.appendElement( root, null, "MetadataURL" );
616            elem.setAttribute( "type", metadataURL.getType() );
617            XMLTools.appendElement( elem, null, "Format", metadataURL.getFormat() );
618            appendOnlineResource( elem, metadataURL.getOnlineResource(), false );
619        }
620    
621        /**
622         * @param root
623         * @param identifier
624         */
625        protected static void appendIdentifier( Element root, Identifier identifier ) {
626            Element elem = XMLTools.appendElement( root, null, "Identifier" );
627            elem.setAttribute( "authority", identifier.getAuthority() );
628            elem.setTextContent( identifier.getValue() );
629        }
630    
631        /**
632         * @param root
633         * @param authorityURL
634         */
635        protected static void appendAuthorityURL( Element root, AuthorityURL authorityURL ) {
636            Element elem = XMLTools.appendElement( root, null, "AuthorityURL" );
637            elem.setAttribute( "name", authorityURL.getName() );
638            appendOnlineResource( elem, authorityURL.getOnlineResource(), false );
639        }
640    
641        /**
642         * @param root
643         * @param attr
644         */
645        protected static void appendAttribution( Element root, Attribution attr ) {
646            Element elem = XMLTools.appendElement( root, null, "Attribution" );
647            XMLTools.appendElement( elem, null, "Title", attr.getTitle() );
648            appendOnlineResource( elem, attr.getOnlineResource(), false );
649            LogoURL logoURL = attr.getLogoURL();
650            if ( logoURL != null ) {
651                elem = XMLTools.appendElement( elem, null, "LogoURL" );
652                elem.setAttribute( "width", "" + logoURL.getWidth() );
653                elem.setAttribute( "height", "" + logoURL.getHeight() );
654                XMLTools.appendElement( elem, null, "Format", logoURL.getFormat() );
655                appendOnlineResource( elem, logoURL.getOnlineResource(), false );
656            }
657        }
658    
659        /**
660         * @param root
661         * @param url
662         * @param appendFineChar
663         */
664        protected static void appendOnlineResource( Element root, URL url, boolean appendFineChar ) {
665    
666            Element olr = XMLTools.appendElement( root, null, "OnlineResource" );
667            olr.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:type", "simple" );
668            if ( appendFineChar ) {
669                // according to OGC WMS 1.1.1 & 1.3 Testsuite a URL to a service operation
670                // via HTTPGet must end with '?' or '&'
671                String href = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() );
672                olr.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:href", href );
673            } else {
674                olr.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:href", url.toExternalForm() );
675            }
676        }
677    
678        /**
679         * @param root
680         * @param extent
681         */
682        protected static void appendExtent( Element root, Extent extent ) {
683            Element exNode = XMLTools.appendElement( root, null, "Extent" );
684            exNode.setAttribute( "name", extent.getName() );
685            exNode.setAttribute( "default", extent.getDefault() );
686            exNode.setAttribute( "nearestValue", boolean2Number( extent.useNearestValue() ) );
687            exNode.setTextContent( extent.getValue() );
688        }
689    
690        /**
691         * @param root
692         * @param dim
693         */
694        protected static void appendDimension( Element root, Dimension dim ) {
695            Element dimNode = XMLTools.appendElement( root, null, "Dimension" );
696            dimNode.setAttribute( "name", dim.getName() );
697            dimNode.setAttribute( "units", dim.getUnits() );
698            dimNode.setAttribute( "unitSymbol", dim.getUnitSymbol() );
699        }
700    
701        /**
702         * @param root
703         * @param lBox
704         */
705        protected static void appendLayerBoundingBox( Element root, LayerBoundingBox lBox ) {
706            Element bbNode = XMLTools.appendElement( root, null, "BoundingBox" );
707            bbNode.setAttribute( "minx", "" + lBox.getMin().getX() );
708            bbNode.setAttribute( "miny", "" + lBox.getMin().getY() );
709            bbNode.setAttribute( "maxx", "" + lBox.getMax().getX() );
710            bbNode.setAttribute( "maxy", "" + lBox.getMax().getY() );
711            bbNode.setAttribute( "resx", "" + lBox.getResx() );
712            bbNode.setAttribute( "resy", "" + lBox.getResy() );
713            bbNode.setAttribute( "SRS", "" + lBox.getSRS() );
714        }
715    
716        /**
717         * @param root
718         * @param llBox
719         */
720        protected static void appendLatLonBoundingBox( Element root, Envelope llBox ) {
721            Element bbNode = XMLTools.appendElement( root, null, "LatLonBoundingBox" );
722            bbNode.setAttribute( "minx", "" + llBox.getMin().getX() );
723            bbNode.setAttribute( "miny", "" + llBox.getMin().getY() );
724            bbNode.setAttribute( "maxx", "" + llBox.getMax().getX() );
725            bbNode.setAttribute( "maxy", "" + llBox.getMax().getY() );
726        }
727    
728    }