001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wms/XMLFactory.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2006 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: aschmitz $
097     * 
098     * @version $Revision: 6860 $, $Date: 2007-05-07 16:41:06 +0200 (Mo, 07 Mai 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            } catch ( SAXException e ) {
141                LOG.logError( e.getMessage(), e );
142            } catch ( XMLParsingException e ) {
143                LOG.logError( e.getMessage(), e );
144            }
145    
146            return capabilitiesDocument;
147        }
148    
149        /**
150         * This method exports a 1.3.0 capabilities document as 1.1.1, providing backward compatibility.
151         * 
152         * @param capabilities
153         * @return the 1.1.1 document
154         * @throws IOException
155         */
156        public static WMSCapabilitiesDocument exportAs_1_1_1( WMSCapabilities_1_3_0 capabilities )
157                                throws IOException {
158            WMSCapabilitiesDocument doc = new WMSCapabilitiesDocument();
159    
160            try {
161                doc.createEmptyDocument();
162    
163                Element root = doc.getRootElement();
164    
165                root.setAttribute( "version", "1.1.1" );
166                root.setAttribute( "updateSequence", capabilities.getUpdateSequence() );
167    
168                appendService( root, capabilities.getServiceIdentification(), capabilities.getServiceProvider() );
169    
170                appendCapabilityRequests( root, capabilities.getOperationMetadata() );
171    
172                Element cap = (Element) XMLTools.getNode( root, "Capability", nsContext );
173                // we don't have that one in 1.3.0 data, so just make it up since it is generally
174                // enabled in deegree WMS
175                UserDefinedSymbolization uds = new UserDefinedSymbolization( true, true, false, true );
176                appendUserDefinedSymbolization( cap, uds );
177    
178                appendCapabilityLayer( cap, capabilities.getLayer() );
179    
180            } catch ( XMLParsingException e ) {
181                LOG.logError( e.getMessage(), e );
182            } catch ( SAXException e ) {
183                LOG.logError( e.getMessage(), e );
184            }
185    
186            return doc;
187        }
188    
189        /**
190         * 
191         * @param root
192         * @param uds
193         */
194        protected static void appendUserDefinedSymbolization( Element root, UserDefinedSymbolization uds ) {
195    
196            Element elem = XMLTools.appendElement( root, null, "UserDefinedSymbolization" );
197            elem.setAttribute( "SupportSLD", boolean2Number( uds.isSldSupported() ) );
198            elem.setAttribute( "UserLayer", boolean2Number( uds.isUserLayerSupported() ) );
199            elem.setAttribute( "UserStyle", boolean2Number( uds.isUserStyleSupported() ) );
200            elem.setAttribute( "RemoteWFS", boolean2Number( uds.isRemoteWFSSupported() ) );
201    
202        }
203    
204        private static String boolean2Number( boolean bool ) {
205            if ( bool ) {
206                return "1";
207            }
208            return "0";
209        }
210    
211        /**
212         * 
213         * @param root
214         * @param identification
215         * @param provider
216         * @throws XMLParsingException
217         */
218        protected static void appendService( Element root, ServiceIdentification identification, ServiceProvider provider )
219                                throws XMLParsingException {
220    
221            root = (Element) XMLTools.getRequiredNode( root, "./Service", nsContext );
222    
223            Element node = (Element) XMLTools.getRequiredNode( root, "./Name", nsContext );
224            // is this actually desired?
225            node.setTextContent( "OGC:WMS" );
226    
227            node = (Element) XMLTools.getRequiredNode( root, "./Title", nsContext );
228            node.setTextContent( identification.getTitle() );
229    
230            String serviceAbstract = identification.getAbstractString();
231            if ( serviceAbstract != null ) {
232                XMLTools.appendElement( root, null, "Abstract", serviceAbstract );
233            }
234    
235            List<Keywords> keywords = identification.getKeywords();
236            if ( keywords.size() > 0 ) {
237                String[] kw = keywords.get( 0 ).getKeywords();
238                Element kwl = XMLTools.appendElement( root, null, "KeywordList" );
239                for ( int i = 0; i < kw.length; i++ ) {
240                    XMLTools.appendElement( kwl, null, "Keyword", kw[i] );
241                }
242            }
243    
244            node = root.getOwnerDocument().createElement( "OnlineResource" );
245    
246            OnlineResource sLink = provider.getProviderSite();
247            org.deegree.model.metadata.iso19115.XMLFactory.appendOnlineResource( node, sLink );
248    
249            root.appendChild( node );
250    
251            appendContactInformation( root, provider );
252    
253            String fee = null;
254            if ( identification.getAccessConstraints().size() > 0 )
255                fee = identification.getAccessConstraints().get( 0 ).getFees();
256            if ( fee != null ) {
257                XMLTools.appendElement( root, null, "Fees", fee );
258            } else {
259                XMLTools.appendElement( root, null, "Fees", "none" );
260            }
261    
262            if ( identification.getAccessConstraints().size() > 0 ) {
263                XMLTools.appendElement( root, null, "AccessConstraints",
264                                        identification.getAccessConstraints().get( 0 ).getUseLimitations().get( 0 ) );
265            } else {
266                XMLTools.appendElement( root, null, "AccessConstraints", "none" );
267            }
268    
269        }
270    
271        /**
272         * 
273         * @param root
274         * @param provider
275         */
276        protected static void appendContactInformation( Element root, ServiceProvider provider ) {
277    
278            Element ciNode = XMLTools.appendElement( root, null, "ContactInformation" );
279            Element cppNode = XMLTools.appendElement( ciNode, null, "ContactPersonPrimary" );
280            if ( provider.getServiceContact().getIndividualName().length > 0 ) {
281                XMLTools.appendElement( cppNode, null, "ContactPerson", provider.getServiceContact().getIndividualName()[0] );
282            }
283            if ( provider.getServiceContact().getOrganisationName().length > 0 ) {
284                XMLTools.appendElement( cppNode, null, "ContactOrganization",
285                                        provider.getServiceContact().getOrganisationName()[0] );
286            }
287            if ( provider.getServiceContact().getPositionName().length > 0 ) {
288                XMLTools.appendElement( ciNode, null, "ContactPosition", provider.getServiceContact().getPositionName()[0] );
289            }
290            Element caNode = XMLTools.appendElement( ciNode, null, "ContactAddress" );
291    
292            XMLTools.appendElement( caNode, null, "AddressType", "postal" );
293    
294            if ( provider.getServiceContact().getContactInfo().length > 0 ) {
295                Address addr = provider.getServiceContact().getContactInfo()[0].getAddress();
296                String[] dp = addr.getDeliveryPoint();
297                if ( dp.length > 0 ) {
298                    XMLTools.appendElement( caNode, null, "Address", dp[0] );
299                }
300                if ( addr.getCity() != null ) {
301                    XMLTools.appendElement( caNode, null, "City", addr.getCity() );
302                }
303                if ( addr.getAdministrativeArea() != null ) {
304                    XMLTools.appendElement( caNode, null, "StateOrProvince", addr.getAdministrativeArea() );
305                }
306                if ( addr.getPostalCode() != null ) {
307                    XMLTools.appendElement( caNode, null, "PostCode", addr.getPostalCode() );
308                }
309                if ( addr.getCountry() != null ) {
310                    XMLTools.appendElement( caNode, null, "Country", addr.getCountry() );
311                }
312    
313                Phone phone = provider.getServiceContact().getContactInfo()[0].getPhone();
314                if ( phone.getVoice().length > 0 ) {
315                    XMLTools.appendElement( ciNode, null, "ContactVoiceTelephone", phone.getVoice()[0] );
316                }
317                if ( phone.getFacsimile().length > 0 ) {
318                    XMLTools.appendElement( ciNode, null, "ContactFacsimileTelephone", phone.getFacsimile()[0] );
319                }
320                if ( addr.getElectronicMailAddress().length > 0 ) {
321                    XMLTools.appendElement( ciNode, null, "ContactElectronicMailAddress",
322                                            addr.getElectronicMailAddress()[0] );
323                }
324            }
325    
326        }
327    
328        /**
329         * 
330         * @param root
331         * @param operationsMetadata
332         * @throws XMLParsingException
333         */
334        protected static void appendCapabilityRequests( Element root, OperationsMetadata operationsMetadata )
335                                throws XMLParsingException {
336    
337            root = (Element) XMLTools.getRequiredNode( root, "./Capability/Request", nsContext );
338    
339            operationsMetadata.getOperations();
340    
341            // just append all operations
342            for ( Operation operation : operationsMetadata.getOperations() ) {
343                appendOperation( root, operation );
344            }
345    
346        }
347    
348        /**
349         * 
350         * @param root
351         * @param operation
352         */
353        protected static void appendOperation( Element root, Operation operation ) {
354    
355            String name = operation.getName().getLocalName();
356    
357            root = XMLTools.appendElement( root, null, name );
358    
359            DomainType odt = (DomainType) operation.getParameter( new QualifiedName( "Format" ) );
360    
361            List<TypedLiteral> values = odt.getValues();
362            for ( TypedLiteral value : values )
363                XMLTools.appendElement( root, null, "Format", value.getValue() );
364    
365            List<DCP> dcps = operation.getDCP();
366            for ( DCP dcp : dcps ) {
367                Element http = XMLTools.appendElement( root, null, "DCPType" );
368                http = XMLTools.appendElement( http, null, "HTTP" );
369                HTTP ht = (HTTP) dcp;
370                List<HTTP.Type> types = ht.getTypes();
371                List<OnlineResource> links = ht.getLinks();
372                for ( int i = 0; i < types.size(); ++i ) {
373                    Element elem = null;
374                    if ( types.get( i ) == HTTP.Type.Get )
375                        elem = XMLTools.appendElement( http, null, "Get" );
376                    if ( types.get( i ) == HTTP.Type.Post )
377                        elem = XMLTools.appendElement( http, null, "Post" );
378                    if ( elem != null ) {
379                        elem = XMLTools.appendElement( elem, null, "OnlineResource" );
380                        org.deegree.model.metadata.iso19115.XMLFactory.appendOnlineResource( elem, links.get( i ) );
381                    }
382                }
383            }
384    
385        }
386    
387        /**
388         * 
389         * @param root
390         * @param layer
391         * @throws XMLParsingException
392         */
393        protected static void appendCapabilityLayer( Element root, Layer layer )
394                                throws XMLParsingException {
395    
396            root = XMLTools.appendElement( root, null, "Layer" );
397            root.setAttribute( "queryable", boolean2Number( layer.isQueryable() ) );
398            root.setAttribute( "cascaded", Integer.toString( layer.getCascaded() ) );
399            root.setAttribute( "opaque", boolean2Number( layer.isOpaque() ) );
400            root.setAttribute( "noSubsets", boolean2Number( layer.hasNoSubsets() ) );
401            if ( layer.getFixedWidth() > 0 ) {
402                root.setAttribute( "fixedWidth", Integer.toString( layer.getFixedWidth() ) );
403            }
404            if ( layer.getFixedHeight() > 0 ) {
405                root.setAttribute( "fixedHeight", Integer.toString( layer.getFixedHeight() ) );
406            }
407    
408            if ( layer.getName() != null ) {
409                XMLTools.appendElement( root, null, "Name", layer.getName() );
410            }
411            XMLTools.appendElement( root, null, "Title", layer.getTitle() );
412    
413            if ( layer.getAbstract() != null ) {
414                XMLTools.appendElement( root, null, "Abstract", layer.getAbstract() );
415            }
416    
417            String[] keywords = layer.getKeywordList();
418            if ( keywords.length > 0 ) {
419                Element elem = XMLTools.appendElement( root, null, "KeywordList" );
420                for ( int i = 0; i < keywords.length; i++ ) {
421                    XMLTools.appendElement( elem, null, "Keyword", keywords[i] );
422                }
423            }
424    
425            String[] srs = layer.getSrs();
426            for ( int i = 0; i < srs.length; i++ ) {
427                XMLTools.appendElement( root, null, "SRS", srs[i] );
428            }
429    
430            Envelope llBox = layer.getLatLonBoundingBox();
431            appendLatLonBoundingBox( root, llBox );
432    
433            LayerBoundingBox[] lBoxes = layer.getBoundingBoxes();
434            for ( int i = 0; i < lBoxes.length; i++ ) {
435                appendLayerBoundingBox( root, lBoxes[i] );
436            }
437    
438            Dimension[] dims = layer.getDimension();
439            for ( int i = 0; i < dims.length; i++ ) {
440                appendDimension( root, dims[i] );
441            }
442    
443            Extent[] extents = layer.getExtent();
444            for ( int i = 0; i < extents.length; i++ ) {
445                appendExtent( root, extents[i] );
446            }
447    
448            Attribution attr = layer.getAttribution();
449            if ( attr != null ) {
450                appendAttribution( root, attr );
451            }
452    
453            AuthorityURL[] authorityURLs = layer.getAuthorityURL();
454            for ( int i = 0; i < authorityURLs.length; i++ ) {
455                appendAuthorityURL( root, authorityURLs[i] );
456            }
457    
458            Identifier[] identifiers = layer.getIdentifier();
459            for ( int i = 0; i < identifiers.length; i++ ) {
460                appendIdentifier( root, identifiers[i] );
461            }
462    
463            MetadataURL[] metadataURLs = layer.getMetadataURL();
464            for ( int i = 0; i < metadataURLs.length; i++ ) {
465                appendMetadataURL( root, metadataURLs[i] );
466            }
467    
468            DataURL[] dataURLs = layer.getDataURL();
469            for ( int i = 0; i < dataURLs.length; i++ ) {
470                appendDataURL( root, dataURLs[i] );
471            }
472    
473            FeatureListURL[] featureListURLs = layer.getFeatureListURL();
474            for ( int i = 0; i < featureListURLs.length; i++ ) {
475                appendFeatureListURL( root, featureListURLs[i] );
476            }
477    
478            if ( layer.getName() != null && layer.getName().length() > 0 ) {
479                Style[] styles = layer.getStyles();
480                for ( int i = 0; i < styles.length; i++ ) {
481                    appendStyle( root, styles[i] );
482                }
483            }
484    
485            ScaleHint scaleHint = layer.getScaleHint();
486            Element elem = XMLTools.appendElement( root, null, "ScaleHint" );
487            elem.setAttribute( "min", "" + scaleHint.getMin() );
488            elem.setAttribute( "max", "" + scaleHint.getMax() );
489    
490            Layer[] layers = layer.getLayer();
491            for ( int i = 0; i < layers.length; i++ ) {
492                appendCapabilityLayer( root, layers[i] );
493            }
494    
495        }
496    
497        /**
498         * 
499         * @param root
500         * @param style
501         */
502        protected static void appendStyle( Element root, Style style ) {
503    
504            String nm = style.getName();
505            String tlt = style.getTitle();
506            if ( nm.startsWith( "default:" ) ) {
507                nm = "default";
508                if ( tlt != null ) {
509                    tlt = StringTools.replace( tlt, "default:", "", false ) + " (default)";
510                }
511            }
512    
513            root = XMLTools.appendElement( root, null, "Style" );
514            XMLTools.appendElement( root, null, "Name", nm );
515            if ( style.getTitle() != null ) {
516                XMLTools.appendElement( root, null, "Title", tlt );
517            }
518            if ( style.getAbstract() != null ) {
519                XMLTools.appendElement( root, null, "Abstract", style.getAbstract() );
520            }
521            LegendURL[] legendURLs = style.getLegendURL();
522            for ( int i = 0; i < legendURLs.length; i++ ) {
523                appendLegendURL( root, legendURLs[i] );
524            }
525    
526            StyleSheetURL styleSheetURL = style.getStyleSheetURL();
527            if ( styleSheetURL != null ) {
528                appendStyleSheetURL( root, styleSheetURL );
529            }
530    
531            StyleURL styleURL = style.getStyleURL();
532            if ( styleURL != null ) {
533                appendStyleURL( root, styleURL );
534            }
535    
536        }
537    
538        /**
539         * @param root
540         * @param styleURL
541         */
542        protected static void appendStyleURL( Element root, StyleURL styleURL ) {
543            Element elem = XMLTools.appendElement( root, null, "StyleURL" );
544            XMLTools.appendElement( elem, null, "Format", styleURL.getFormat() );
545            appendOnlineResource( elem, styleURL.getOnlineResource(), false );
546        }
547    
548        /**
549         * @param root
550         * @param styleSheetURL
551         */
552        protected static void appendStyleSheetURL( Element root, StyleSheetURL styleSheetURL ) {
553            Element elem = XMLTools.appendElement( root, null, "StyleSheetURL" );
554            XMLTools.appendElement( elem, null, "Format", styleSheetURL.getFormat() );
555            appendOnlineResource( elem, styleSheetURL.getOnlineResource(), false );
556        }
557    
558        /**
559         * @param root
560         * @param legendURL
561         */
562        protected static void appendLegendURL( Element root, LegendURL legendURL ) {
563            Element elem = XMLTools.appendElement( root, null, "LegendURL" );
564            elem.setAttribute( "width", "" + legendURL.getWidth() );
565            elem.setAttribute( "height", "" + legendURL.getWidth() );
566            XMLTools.appendElement( elem, null, "Format", legendURL.getFormat() );
567    
568            appendOnlineResource( elem, legendURL.getOnlineResource(), false );
569        }
570    
571        /**
572         * @param root
573         * @param featureListURL
574         */
575        protected static void appendFeatureListURL( Element root, FeatureListURL featureListURL ) {
576            Element elem = XMLTools.appendElement( root, null, "FeatureListURL" );
577            XMLTools.appendElement( elem, null, "Format", featureListURL.getFormat() );
578            appendOnlineResource( elem, featureListURL.getOnlineResource(), false );
579        }
580    
581        /**
582         * @param root
583         * @param dataURL
584         */
585        protected static void appendDataURL( Element root, DataURL dataURL ) {
586            Element elem = XMLTools.appendElement( root, null, "DataURL" );
587            XMLTools.appendElement( elem, null, "Format", dataURL.getFormat() );
588            appendOnlineResource( elem, dataURL.getOnlineResource(), false );
589        }
590    
591        /**
592         * @param root
593         * @param metadataURL
594         */
595        protected static void appendMetadataURL( Element root, MetadataURL metadataURL ) {
596            Element elem = XMLTools.appendElement( root, null, "MetadataURL" );
597            elem.setAttribute( "type", metadataURL.getType() );
598            XMLTools.appendElement( elem, null, "Format", metadataURL.getFormat() );
599            appendOnlineResource( elem, metadataURL.getOnlineResource(), false );
600        }
601    
602        /**
603         * @param root
604         * @param identifier
605         */
606        protected static void appendIdentifier( Element root, Identifier identifier ) {
607            Element elem = XMLTools.appendElement( root, null, "Identifier" );
608            elem.setAttribute( "authority", identifier.getAuthority() );
609            elem.setTextContent( identifier.getValue() );
610        }
611    
612        /**
613         * @param root
614         * @param authorityURL
615         */
616        protected static void appendAuthorityURL( Element root, AuthorityURL authorityURL ) {
617            Element elem = XMLTools.appendElement( root, null, "AuthorityURL" );
618            elem.setAttribute( "name", authorityURL.getName() );
619            appendOnlineResource( elem, authorityURL.getOnlineResource(), false );
620        }
621    
622        /**
623         * @param root
624         * @param attr
625         */
626        protected static void appendAttribution( Element root, Attribution attr ) {
627            Element elem = XMLTools.appendElement( root, null, "Attribution" );
628            XMLTools.appendElement( elem, null, "Title", attr.getTitle() );
629            appendOnlineResource( elem, attr.getOnlineResource(), false );
630            LogoURL logoURL = attr.getLogoURL();
631            if ( logoURL != null ) {
632                elem = XMLTools.appendElement( elem, null, "LogoURL" );
633                elem.setAttribute( "width", "" + logoURL.getWidth() );
634                elem.setAttribute( "height", "" + logoURL.getHeight() );
635                XMLTools.appendElement( elem, null, "Format", logoURL.getFormat() );
636                appendOnlineResource( elem, logoURL.getOnlineResource(), false );
637            }
638        }
639    
640        /**
641         * @param root
642         * @param url
643         * @param appendFineChar
644         */
645        protected static void appendOnlineResource( Element root, URL url, boolean appendFineChar ) {
646    
647            Element olr = XMLTools.appendElement( root, null, "OnlineResource" );
648            olr.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:type", "simple" );
649            if ( appendFineChar ) {
650                // according to OGC WMS 1.1.1 & 1.3 Testsuite a URL to a service operation
651                // via HTTPGet must end with '?' or '&'
652                String href = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() );
653                olr.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:href", href );
654            } else {
655                olr.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:href", url.toExternalForm() );
656            }
657        }
658    
659        /**
660         * @param root
661         * @param extent
662         */
663        protected static void appendExtent( Element root, Extent extent ) {
664            Element exNode = XMLTools.appendElement( root, null, "Extent" );
665            exNode.setAttribute( "name", extent.getName() );
666            exNode.setAttribute( "default", extent.getDefault() );
667            exNode.setAttribute( "nearestValue", boolean2Number( extent.useNearestValue() ) );
668            exNode.setTextContent( extent.getValue() );
669        }
670    
671        /**
672         * @param root
673         * @param dim
674         */
675        protected static void appendDimension( Element root, Dimension dim ) {
676            Element dimNode = XMLTools.appendElement( root, null, "Dimension" );
677            dimNode.setAttribute( "name", dim.getName() );
678            dimNode.setAttribute( "units", dim.getUnits() );
679            dimNode.setAttribute( "unitSymbol", dim.getUnitSymbol() );
680        }
681    
682        /**
683         * @param root
684         * @param lBox
685         */
686        protected static void appendLayerBoundingBox( Element root, LayerBoundingBox lBox ) {
687            Element bbNode = XMLTools.appendElement( root, null, "BoundingBox" );
688            bbNode.setAttribute( "minx", "" + lBox.getMin().getX() );
689            bbNode.setAttribute( "miny", "" + lBox.getMin().getY() );
690            bbNode.setAttribute( "maxx", "" + lBox.getMax().getX() );
691            bbNode.setAttribute( "maxy", "" + lBox.getMax().getY() );
692            bbNode.setAttribute( "resx", "" + lBox.getResx() );
693            bbNode.setAttribute( "resy", "" + lBox.getResy() );
694            bbNode.setAttribute( "SRS", "" + lBox.getSRS() );
695        }
696    
697        /**
698         * @param root
699         * @param llBox
700         */
701        protected static void appendLatLonBoundingBox( Element root, Envelope llBox ) {
702            Element bbNode = XMLTools.appendElement( root, null, "LatLonBoundingBox" );
703            bbNode.setAttribute( "minx", "" + llBox.getMin().getX() );
704            bbNode.setAttribute( "miny", "" + llBox.getMin().getY() );
705            bbNode.setAttribute( "maxx", "" + llBox.getMax().getX() );
706            bbNode.setAttribute( "maxy", "" + llBox.getMax().getY() );
707        }
708    
709    }