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