001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcwebservices/wpvs/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    
037    package org.deegree.ogcwebservices.wpvs;
038    
039    import java.io.IOException;
040    import java.net.URI;
041    import java.net.URL;
042    
043    import org.deegree.datatypes.values.TypedLiteral;
044    import org.deegree.datatypes.values.ValueRange;
045    import org.deegree.framework.xml.XMLTools;
046    import org.deegree.model.crs.CoordinateSystem;
047    import org.deegree.model.spatialschema.Envelope;
048    import org.deegree.ogcbase.BaseURL;
049    import org.deegree.ogcbase.CommonNamespaces;
050    import org.deegree.ogcbase.ImageURL;
051    import org.deegree.ogcwebservices.getcapabilities.DCPType;
052    import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
053    import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification;
054    import org.deegree.ogcwebservices.getcapabilities.ServiceProvider;
055    import org.deegree.ogcwebservices.wpvs.capabilities.DataProvider;
056    import org.deegree.ogcwebservices.wpvs.capabilities.Dataset;
057    import org.deegree.ogcwebservices.wpvs.capabilities.Dimension;
058    import org.deegree.ogcwebservices.wpvs.capabilities.Identifier;
059    import org.deegree.ogcwebservices.wpvs.capabilities.MetaData;
060    import org.deegree.ogcwebservices.wpvs.capabilities.Style;
061    import org.deegree.ogcwebservices.wpvs.capabilities.WPVSCapabilities;
062    import org.deegree.ogcwebservices.wpvs.capabilities.WPVSCapabilitiesDocument;
063    import org.deegree.ogcwebservices.wpvs.capabilities.WPVSOperationsMetadata;
064    import org.deegree.owscommon.OWSMetadata;
065    import org.deegree.owscommon.com110.HTTP110;
066    import org.deegree.owscommon.com110.OWSAllowedValues;
067    import org.deegree.owscommon.com110.OWSDomainType110;
068    import org.deegree.owscommon.com110.OWSRequestMethod;
069    import org.deegree.owscommon.com110.Operation110;
070    import org.w3c.dom.Element;
071    import org.w3c.dom.Text;
072    import org.xml.sax.SAXException;
073    
074    /**
075     * TODO class description
076     *
077     * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
078     * @author last edited by: $Author: mschneider $
079     *
080     * $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
081     */
082    public class XMLFactory extends org.deegree.owscommon.XMLFactory {
083    
084        private static final URI WPVSNS = CommonNamespaces.WPVSNS;
085    
086        private static final String PRE_OWS = CommonNamespaces.OWS_PREFIX + ':';
087    
088        private static final String PRE_WPVS = CommonNamespaces.WPVS_PREFIX + ':';
089    
090        private XMLFactory() {
091            // not instantiable.
092        }
093    
094        /**
095         * This method exporst a wpvs capabilitiesDocument with following information taken from the
096         * given WPVSCapabilities
097         * <ul>
098         * <li>ServiceIdentification</li>
099         * <li>ServiceProvide</li>
100         * <li>operationMetadata</li>
101         * <li>the root dataset</li>
102         * </ul>
103         *
104         * @param wpvsCapabilities
105         * @return the WPVSCapabilitiesDocument of this wpvs
106         * @throws IOException
107         *             if wpvsCapabilitiesDocument cannot be instantiated
108         */
109        public static WPVSCapabilitiesDocument export( WPVSCapabilities wpvsCapabilities )
110                                throws IOException {
111            XMLFactory factory = new XMLFactory();
112            return factory.createCapabilitiesDocument( wpvsCapabilities );
113        }
114    
115        private WPVSCapabilitiesDocument createCapabilitiesDocument( WPVSCapabilities wpvsCapabilities )
116                                throws IOException {
117            WPVSCapabilitiesDocument wpvsCapabilitiesDocument = new WPVSCapabilitiesDocument();
118            try {
119                wpvsCapabilitiesDocument.createEmptyDocument();
120                Element root = wpvsCapabilitiesDocument.getRootElement();
121    
122                ServiceIdentification serviceIdentification = wpvsCapabilities.getServiceIdentification();
123                if ( serviceIdentification != null ) {
124                    appendServiceIdentification( root, serviceIdentification );
125                }
126    
127                ServiceProvider serviceProvider = wpvsCapabilities.getServiceProvider();
128                if ( serviceProvider != null ) {
129                    appendServiceProvider( root, serviceProvider );
130                }
131    
132                OperationsMetadata operationMetadata = wpvsCapabilities.getOperationsMetadata();
133                if ( operationMetadata != null && operationMetadata instanceof WPVSOperationsMetadata ) {
134                    appendWPVSOperationsMetadata( root, (WPVSOperationsMetadata) operationMetadata );
135                }
136    
137                Dataset dataset = wpvsCapabilities.getDataset();
138                if ( dataset != null ) {
139                    appendDataset( root, dataset );
140                }
141    
142            } catch ( SAXException e ) {
143                e.printStackTrace();
144                LOG.logError( e.getMessage(), e );
145            }
146    
147            return wpvsCapabilitiesDocument;
148        }
149    
150        /**
151         * Appends the DOM representation of an <code>WPVSOperationsMetadata</code> to the passed
152         * <code>Element</code>.
153         *
154         * @param root
155         * @param operationsMetadata
156         */
157        private void appendWPVSOperationsMetadata( Element root, WPVSOperationsMetadata operationsMetadata ) {
158            // 'ows:OperationsMetadata'-element
159            Element operationsMetadataNode = XMLTools.appendElement( root, OWSNS, PRE_OWS + "OperationsMetadata" );
160    
161            // append all Operations
162            Operation110[] operations = (Operation110[]) operationsMetadata.getAllOperations();
163            for ( int i = 0; i < operations.length; i++ ) {
164                Operation110 operation = operations[i];
165    
166                // 'ows:Operation' - element
167                Element operationElement = XMLTools.appendElement( operationsMetadataNode, OWSNS, PRE_OWS + "Operation" );
168                operationElement.setAttribute( "name", operation.getName() );
169    
170                // 'ows:DCP' - elements
171                DCPType[] dcps = operation.getDCPs();
172                for ( int j = 0; j < dcps.length; j++ ) {
173                    appendDCPValue( operationElement, dcps[j] );
174                }
175    
176                // 'ows:Parameter' - elements
177                OWSDomainType110[] parameters = operation.getParameters110();
178                for ( int j = 0; j < parameters.length; j++ ) {
179                    appendDomainType( operationElement, parameters[j], PRE_OWS + "Parameter" );
180                }
181    
182                // 'ows:Constraint' - elements
183                OWSDomainType110[] constraints = operation.getConstraints110();
184                for ( int j = 0; j < constraints.length; j++ ) {
185                    appendDomainType( operationElement, constraints[j], PRE_OWS + "Constraint" );
186                }
187    
188                // 'ows:Metadata' - elements
189                OWSMetadata[] metadata = operation.getMetadata110();
190                for ( int j = 0; j < metadata.length; j++ ) {
191                    appendOWSMetadata( operationElement, metadata[j], PRE_OWS + "Metadata" );
192                }
193            }
194    
195            // append general parameters
196            OWSDomainType110[] parameters = operationsMetadata.getParameters110();
197            for ( int i = 0; i < parameters.length; i++ ) {
198                appendDomainType( operationsMetadataNode, parameters[i], PRE_OWS + "Parameter" );
199            }
200    
201            // append general constraints
202            OWSDomainType110[] constraints = operationsMetadata.getConstraints110();
203            for ( int i = 0; i < constraints.length; i++ ) {
204                appendDomainType( operationsMetadataNode, constraints[i], PRE_OWS + "Constraint" );
205            }
206    
207            // append 'ows:ExtendedCapabilities'
208            // TODO when needed.
209    
210        }
211    
212        /**
213         * Appends the DOM representation of an <code>OWSMetadata</code> to the passed
214         * <code>Element</code>. The given <code>String</code> is used to distinguish between the
215         * different Metadata types.
216         *
217         * @param element
218         * @param metadata
219         * @param tagName
220         */
221        private void appendOWSMetadata( Element element, OWSMetadata metadata, String tagName ) {
222    
223            if ( metadata != null ) {
224    
225                Element metadataElement = XMLTools.appendElement( element, OWSNS, tagName );
226    
227                appendSimpleLinkAttributes( metadataElement, metadata.getLink() );
228    
229                Element nameElement = XMLTools.appendElement( metadataElement, OWSNS, CommonNamespaces.OWS_PREFIX + ":Name" );
230                metadataElement.appendChild( nameElement );
231                nameElement.setNodeValue( metadata.getName() );
232            }
233    
234        }
235    
236        /**
237         * Appends the DOM representation of an <code>OWSDomainType</code> to the passed
238         * <code>Element</code>. The given <code>String</code> is used to distinguish between
239         * <code>Parameter</code> and <code>Constraint</code>.
240         *
241         * @param element
242         * @param domainType
243         * @param tagName
244         */
245        private void appendDomainType( Element element, OWSDomainType110 domainType, String tagName ) {
246    
247            Element domainElement = XMLTools.appendElement( element, OWSNS, tagName );
248    
249            // attribute
250            domainElement.setAttribute( "name", domainType.getName() );
251    
252            // elements
253            OWSAllowedValues allowedValues = domainType.getAllowedValues();
254            OWSMetadata valuesListReference = domainType.getValuesListReference();
255            if ( allowedValues != null ) {
256                appendAllowedValues( domainElement, allowedValues );
257            }
258            // else if ( domainType.isAnyValue() ) {
259            // Element anyElement = XMLTools.appendElement( domainElement, OWSNS,
260            // CommonNamespaces.OWS_PREFIX+":AnyValue" );
261            // // TODO content of this tag!
262            // } else if ( domainType.hasNoValues() ) {
263            // Element noValuesElement = XMLTools.appendElement( domainElement, OWSNS,
264            // CommonNamespaces.OWS_PREFIX+":NoValues" );
265            // // TODO content of this tag!
266            // }
267            else if ( valuesListReference != null ) {
268                appendOWSMetadata( domainElement, valuesListReference, CommonNamespaces.OWS_PREFIX + ":ValuesListReference" );
269            } else {
270                // TODO "domainType object is invalid!"
271            }
272    
273            appendTypedLiteral( domainElement, domainType.getDefaultValue(), PRE_OWS + "DefaultValue", OWSNS );
274    
275            appendOWSMetadata( domainElement, domainType.getMeaning(), PRE_OWS + "Meaning" );
276    
277            appendOWSMetadata( domainElement, domainType.getOwsDataType(), PRE_OWS + "DataType" );
278    
279            String measurement = domainType.getMeasurementType();
280            if ( OWSDomainType110.REFERENCE_SYSTEM.equals( measurement ) ) {
281                appendOWSMetadata( domainElement, domainType.getMeasurement(), PRE_OWS + "ReferenceSystem" );
282            } else if ( OWSDomainType110.UOM.equals( measurement ) ) {
283                appendOWSMetadata( domainElement, domainType.getMeasurement(), PRE_OWS + "UOM" );
284            }
285    
286            OWSMetadata[] metadata = domainType.getMetadata();
287            for ( int i = 0; i < metadata.length; i++ ) {
288                appendOWSMetadata( domainElement, metadata[i], PRE_OWS + "Metadata" );
289            }
290    
291        }
292    
293        /**
294         * Appends the DOM representation of an <code>OWSAllowedValues</code> object to the passed
295         * <code>Element</code>.
296         *
297         * @param element
298         * @param allowedValues
299         */
300        private void appendAllowedValues( Element element, OWSAllowedValues allowedValues ) {
301    
302            Element allowedElement = XMLTools.appendElement( element, OWSNS, PRE_OWS + "AllowedValues" );
303    
304            TypedLiteral[] literals = allowedValues.getOwsValues();
305            for ( int i = 0; i < literals.length; i++ ) {
306                appendTypedLiteral( allowedElement, literals[i], PRE_OWS + "Value", OWSNS );
307            }
308    
309            ValueRange[] range = allowedValues.getValueRanges();
310            for ( int i = 0; i < range.length; i++ ) {
311                Element rangeElement = XMLTools.appendElement( allowedElement, OWSNS, PRE_OWS + "Range" );
312    
313                appendTypedLiteral( rangeElement, range[i].getMin(), PRE_OWS + "MinimumValue", OWSNS );
314                appendTypedLiteral( rangeElement, range[i].getMax(), PRE_OWS + "MaximumValue", OWSNS );
315                appendTypedLiteral( rangeElement, range[i].getSpacing(), PRE_OWS + "Spacing", OWSNS );
316            }
317    
318        }
319    
320        /*
321         * (non-Javadoc)
322         *
323         * @see org.deegree.owscommon.XMLFactory#appendDCP(org.w3c.dom.Element,
324         *      org.deegree.ogcwebservices.getcapabilities.DCPType)
325         */
326        private void appendDCPValue( Element operationElement, DCPType dcp ) {
327    
328            // 'ows:DCP'-element
329            Element dcpNode = XMLTools.appendElement( operationElement, OWSNS, PRE_OWS + "DCP" );
330    
331            // currently, the only supported DCP are HTTP and HTTP110!
332            if ( dcp.getProtocol() instanceof HTTP110 ) {
333                HTTP110 http = (HTTP110) dcp.getProtocol();
334    
335                // 'ows:HTTP'-element
336                Element httpNode = XMLTools.appendElement( dcpNode, OWSNS, PRE_OWS + "HTTP" );
337    
338                // 'ows:Get'-elements
339                OWSRequestMethod[] getRequest = http.getGetRequests();
340                for ( int i = 0; i < getRequest.length; i++ ) {
341                    appendRequest( httpNode, PRE_OWS + "Get", getRequest[i] );
342                }
343    
344                // 'ows:Post'-elements
345                OWSRequestMethod[] postRequest = http.getPostRequests();
346                for ( int i = 0; i < postRequest.length; i++ ) {
347                    appendRequest( httpNode, PRE_OWS + "Post", postRequest[i] );
348                }
349            }
350    
351        }
352    
353        /**
354         * Appends the DOM representation of an <code>OWSRequestMethod</code> to the passed
355         * <code>Element</code>. The given <code>String</code> is used to distinguish between
356         * <code>ows:Get</code> and <code>ows:Post</code> requests.
357         *
358         * @param httpNode
359         * @param type
360         * @param request
361         */
362        private void appendRequest( Element httpNode, String type, OWSRequestMethod request ) {
363    
364            Element owsElement = XMLTools.appendElement( httpNode, OWSNS, type );
365    
366            appendSimpleLinkAttributes( owsElement, request.getLink() );
367    
368            OWSDomainType110[] constraint = request.getConstraints();
369            for ( int i = 0; i < constraint.length; i++ ) {
370                appendDomainType( owsElement, constraint[i], PRE_OWS + "Constraint" );
371            }
372    
373        }
374    
375        /**
376         * Appends the DOM representation of a <code>Dataset</code> to the passed <code>Element</code>.
377         *
378         * @param root
379         * @param dataset
380         */
381        private void appendDataset( Element root, Dataset dataset ) {
382    
383            // 'wpvs:Dataset'-element (parent)
384            Element datasetNode = XMLTools.appendElement( root, WPVSNS, PRE_WPVS + "Dataset" );
385    
386            // attributes
387            datasetNode.setAttribute( "queryable", ( ( dataset.getQueryable() ) ? "1" : "0" ) );
388            datasetNode.setAttribute( "opaque", ( ( dataset.getOpaque() ) ? "1" : "0" ) );
389            datasetNode.setAttribute( "noSubsets", ( ( dataset.getNoSubset() ) ? "1" : "0" ) );
390            datasetNode.setAttribute( "fixedWidth", String.valueOf( dataset.getFixedWidth() ) );
391            datasetNode.setAttribute( "fixedHeight", String.valueOf( dataset.getFixedHeight() ) );
392    
393            // optional 'wpvs:Name'-element
394            appendName( datasetNode, dataset );
395    
396            // mandatory 'wpvs:Title'-element
397            appendTitle( datasetNode, dataset );
398    
399            // optional 'wpvs:Abstract'-element
400            appendAbstract( datasetNode, dataset );
401    
402            // optional 'ows:Keywords'-elements
403            appendOWSKeywords( datasetNode, dataset.getKeywords() );
404    
405            // optional 'wpvs:CRS'-elements
406            appendCRSNodes( datasetNode, dataset.getCrs() );
407    
408            // optional 'wpvs:Format'-elements
409            appendFormats( datasetNode, dataset.getMimeTypeFormat() );
410    
411            // mandatory 'ows:WGS84BoundingBox
412            appendBoundingBox( datasetNode, dataset.getWgs84BoundingBox(), PRE_OWS + "WGS84BoundingBox",
413                               "urn:ogc:def:crs:OGC:2:84", "2" );
414    
415            // optional 'ows:BoundingBox'-elements
416            Envelope[] boundingBoxes = dataset.getBoundingBoxes();
417    
418            for ( int i = 0; i < boundingBoxes.length; i++ ) {
419    
420                if ( boundingBoxes[i] != null ) {
421                    String crsName = boundingBoxes[i].getCoordinateSystem().getIdentifier();
422    
423                    appendBoundingBox( datasetNode, boundingBoxes[i], PRE_OWS + "BoundingBox", crsName, "2" );
424                }
425            }
426    
427            // optional 'wpvs:Dimension'-elements
428            appendDimensions( datasetNode, dataset.getDimensions() );
429    
430            // optional 'wpvs:DataProvider'-element
431            appendDataProvider( datasetNode, dataset.getDataProvider() );
432    
433            // mandatory 'wpvs:Identifier'-element
434            appendIdentifier( datasetNode, dataset.getIdentifier() );
435    
436            // 'wpvs:MetaData'-elements
437            appendURLs( datasetNode, dataset.getMetadata(), WPVSNS, PRE_WPVS + "MetaData" );
438    
439            // 'wpvs:DatasetReference'-elements
440            appendURLs( datasetNode, dataset.getDatasetReferences(), WPVSNS, PRE_WPVS + "DatasetReference" );
441    
442            // 'wpvs:FeatureListReference'-elements
443            appendURLs( datasetNode, dataset.getFeatureListReferences(), WPVSNS, PRE_WPVS + "FeatureListReference" );
444    
445            // 'wpvs:Style'-elements
446            appendStyles( datasetNode, dataset.getStyles() );
447    
448            // 'wpvs:MinimumScaleDenominator'-element
449            appendScaleDenominator( datasetNode, dataset.getMinimumScaleDenominator(), "MIN" );
450    
451            // 'wpvs:MaximumScaleDenominator'-element
452            appendScaleDenominator( datasetNode, dataset.getMaximumScaleDenominator(), "MAX" );
453    
454            // 'wpvs:Dataset'-elements (children)
455            Dataset[] datasets = dataset.getDatasets();
456            for ( int i = 0; i < datasets.length; i++ ) {
457                appendDataset( datasetNode, datasets[i] );
458            }
459    
460            // 'ElevationModel'-element (the simple ogc-ElevationModel)
461            String emName = dataset.getElevationModel().getName();
462            if ( emName != null ) {
463                appendElevationModel( datasetNode, emName );
464            }
465        }
466    
467        /**
468         * Appends the DOM representation of an OGC <code>ElevationModel</code> to the passed
469         * <code>Element</code>.
470         *
471         * @param datasetNode
472         * @param elevationModelName
473         */
474        private void appendElevationModel( Element datasetNode, String elevationModelName ) {
475    
476            Element elevation = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "ElevationModel" );
477            Text elevationText = elevation.getOwnerDocument().createTextNode( elevationModelName );
478            elevation.appendChild( elevationText );
479    
480            elevation.appendChild( elevationText );
481    
482        }
483    
484        /**
485         * Appends the DOM representations of the given <code>ScaleDenominator</code> to the passed
486         * <code>Element</code>. The given <code>String</code> is used to distinguish between
487         * MinimumsScaleDenominator and MaximumScaleDenominator.
488         *
489         * @param datasetNode
490         * @param scaleDenominator
491         * @param extremum
492         *            must be either 'MIN' or 'MAX'.
493         */
494        private void appendScaleDenominator( Element datasetNode, double scaleDenominator, String extremum ) {
495            Element scaleElement = null;
496    
497            if ( "MIN".equalsIgnoreCase( extremum ) ) {
498                scaleElement = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "MinimumScaleDenominator" );
499            } else if ( "MAX".equalsIgnoreCase( extremum ) ) {
500                scaleElement = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "MaximumScaleDenominator" );
501            } else {
502                throw new IllegalArgumentException( "The extremum must be either 'MIN' or 'MAX'." );
503            }
504    
505            String value = String.valueOf( scaleDenominator );
506            Text scaleText = scaleElement.getOwnerDocument().createTextNode( value );
507            scaleElement.appendChild( scaleText );
508    
509        }
510    
511        /**
512         * Appends the DOM representations of the <code>Abstract</code> Element from the given
513         * <code>Object</code> to the passed <code>Element</code>.
514         *
515         * @param root
516         * @param obj
517         *            may be of the following types: Style, Dataset.
518         */
519        private void appendAbstract( Element root, Object obj ) {
520    
521            String abstractString = null;
522            if ( obj instanceof Style ) {
523                abstractString = ( (Style) obj ).getAbstract();
524            } else if ( obj instanceof Dataset ) {
525                abstractString = ( (Dataset) obj ).getAbstract();
526            }
527            if ( abstractString != null ) {
528                Element abstractElement = XMLTools.appendElement( root, WPVSNS, PRE_WPVS + "Abstract" );
529                Text abstractText = abstractElement.getOwnerDocument().createTextNode( abstractString );
530                abstractElement.appendChild( abstractText );
531            }
532    
533        }
534    
535        /**
536         * Appends the DOM representations of the <code>Title</code> Element from the given
537         * <code>Object</code> to the passed <code>Element</code>.
538         *
539         * @param root
540         * @param obj
541         *            may be of the following types: Style, Dataset.
542         */
543        private void appendTitle( Element root, Object obj ) {
544    
545            String title = null;
546            if ( obj instanceof Style ) {
547                title = ( (Style) obj ).getTitle();
548            } else if ( obj instanceof Dataset ) {
549                title = ( (Dataset) obj ).getTitle();
550            }
551            Element titleElement = XMLTools.appendElement( root, WPVSNS, PRE_WPVS + "Title" );
552            Text titleText = titleElement.getOwnerDocument().createTextNode( title );
553            titleElement.appendChild( titleText );
554        }
555    
556        /**
557         * Appends the DOM representations of the <code>Name</code> Element from the given
558         * <code>Object</code> to the passed <code>Element</code>.
559         *
560         * @param root
561         * @param obj
562         *            may be of the following types: Style, Dataset.
563         */
564        private void appendName( Element root, Object obj ) {
565    
566            String name = null;
567            if ( obj instanceof Style ) {
568                name = ( (Style) obj ).getName();
569            } else if ( obj instanceof Dataset ) {
570                name = ( (Dataset) obj ).getName();
571            }
572    
573            if ( name != null ) {
574                Element nameElement = XMLTools.appendElement( root, WPVSNS, PRE_WPVS + "Name" );
575                Text nameText = nameElement.getOwnerDocument().createTextNode( name );
576                nameElement.appendChild( nameText );
577            }
578    
579        }
580    
581        /**
582         * Appends the DOM representations of the given array of <code>Style</code> to the passed
583         * <code>Element</code>.
584         *
585         * @param datasetNode
586         * @param styles
587         */
588        private void appendStyles( Element datasetNode, Style[] styles ) {
589    
590            if ( styles != null ) {
591                for ( int i = 0; i < styles.length; i++ ) {
592    
593                    Element styleElement = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "Style" );
594    
595                    appendName( styleElement, styles[i] );
596                    appendTitle( styleElement, styles[i] );
597                    appendAbstract( styleElement, styles[i] );
598    
599                    appendOWSKeywords( styleElement, styles[i].getKeywords() );
600    
601                    if ( styles[i].getIdentifier() != null ) {
602                        appendIdentifier( styleElement, styles[i].getIdentifier() );
603                    }
604    
605                    appendURLs( styleElement, styles[i].getLegendURLs(), WPVSNS, PRE_WPVS + "LegendURL" );
606    
607                    Element styleSheetURLElement = XMLTools.appendElement( styleElement, WPVSNS, PRE_WPVS + "StyleSheetURL" );
608                    appendURL( styleSheetURLElement, styles[i].getStyleSheetURL(), WPVSNS );
609    
610                    Element styleURLElement = XMLTools.appendElement( styleElement, WPVSNS, PRE_WPVS + "StyleURL" );
611                    appendURL( styleURLElement, styles[i].getStyleURL(), WPVSNS );
612    
613                }
614            }
615        }
616    
617        /**
618         * Appends the DOM representations of the given array of <code>BaseURL</code> under the given
619         * name to the passed <code>Element</code>.
620         *
621         * @param root
622         * @param baseURL
623         * @param uri
624         * @param newNode
625         */
626        private void appendURLs( Element root, BaseURL[] baseURL, URI uri, String newNode ) {
627            if ( baseURL != null ) {
628                for ( int i = 0; i < baseURL.length; i++ ) {
629                    Element urlElement = XMLTools.appendElement( root, uri, newNode );
630                    appendURL( urlElement, baseURL[i], uri );
631                }
632            }
633        }
634    
635        /**
636         * Appends the contents of the given <code>BaseURL</code> within the given <code>URI</code>
637         * as DOM representation to the passed URL <code>Element</code>.
638         *
639         * @param urlElement
640         *            example: logoURLElement
641         * @param baseURL
642         *            example: dataProvider.getLogoURL()
643         * @param uri
644         *            example: "WPVSNS"
645         */
646        private void appendURL( Element urlElement, BaseURL baseURL, URI uri ) {
647    
648            // child elements of urlElement
649            Element formatElement = XMLTools.appendElement( urlElement, uri, PRE_WPVS + "Format" );
650            String format = baseURL != null ? baseURL.getFormat() : "";
651            Text formatText = formatElement.getOwnerDocument().createTextNode( format );
652            formatElement.appendChild( formatText );
653    
654            Element onlineElement = XMLTools.appendElement( urlElement, uri, PRE_WPVS + "OnlineResource" );
655            String url = ( baseURL != null && baseURL.getOnlineResource() != null ) ? baseURL.getOnlineResource().toString()
656                                                                                   : "";
657            onlineElement.setAttribute( "xlink:href", url );
658    
659            // attributes of urlElement
660            if ( baseURL instanceof ImageURL ) {
661                String width = String.valueOf( ( (ImageURL) baseURL ).getWidth() );
662                String height = String.valueOf( ( (ImageURL) baseURL ).getHeight() );
663                urlElement.setAttribute( "width", width );
664                urlElement.setAttribute( "height", height );
665    
666            } else if ( baseURL instanceof MetaData ) {
667    
668                urlElement.setAttribute( "type", ( (MetaData) baseURL ).getType() );
669            }
670    
671        }
672    
673        /**
674         * Appends the DOM representation of the given <code>Identifier</code> to the passed
675         * <code>Element</code>.
676         *
677         * @param root
678         * @param identifier
679         */
680        private void appendIdentifier( Element root, Identifier identifier ) {
681    
682            Element idElement = XMLTools.appendElement( root, WPVSNS, PRE_WPVS + "Identifier" );
683    
684            if ( identifier.getCodeSpace() != null ) {
685                idElement.setAttribute( "codeSpace", identifier.getCodeSpace().toASCIIString() );
686            }
687    
688            Text idText = idElement.getOwnerDocument().createTextNode( identifier.getValue() );
689            idElement.appendChild( idText );
690    
691        }
692    
693        /**
694         * Appends the DOM representation of the given <code>DataProvider</code> to the passed
695         * <code>Element</code>.
696         *
697         * @param datasetNode
698         * @param dataProvider
699         */
700        private void appendDataProvider( Element datasetNode, DataProvider dataProvider ) {
701            if ( dataProvider != null ) {
702                Element provider = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "DataProvider" );
703    
704                String provName = dataProvider.getProviderName();
705                if ( provName != null ) {
706                    Element providerName = XMLTools.appendElement( provider, WPVSNS, PRE_WPVS + "ProviderName" );
707                    Text providerNameText = providerName.getOwnerDocument().createTextNode( provName );
708                    providerName.appendChild( providerNameText );
709    
710                }
711    
712                Element providerSite = XMLTools.appendElement( provider, WPVSNS, PRE_WPVS + "ProviderSite" );
713                URL siteURL = dataProvider.getProviderSite();
714                String site = "";
715                if ( siteURL != null ) {
716                    site = siteURL.toString();
717                }
718                providerSite.setAttribute( "xlink:href", site );
719    
720                Element logoURLElement = XMLTools.appendElement( provider, WPVSNS, PRE_WPVS + "LogoURL" );
721                appendURL( logoURLElement, dataProvider.getLogoURL(), WPVSNS );
722            }
723        }
724    
725        /**
726         * Appends the DOM representations of the given array of <code>Dimension</code> to the passed
727         * <code>Element</code>.
728         *
729         * @param datasetNode
730         * @param dimensions
731         */
732        private void appendDimensions( Element datasetNode, Dimension[] dimensions ) {
733            if ( dimensions != null ) {
734                for ( Dimension dimension : dimensions ) {
735                    if ( dimension != null ) {
736                        Element dimensionElement = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "Dimension" );
737                        dimensionElement.setAttribute( "name", dimension.getName() );
738                        dimensionElement.setAttribute( "units", dimension.getUnits() );
739                        dimensionElement.setAttribute( "unitSymbol", dimension.getUnitSymbol() );
740                        dimensionElement.setAttribute( "default", dimension.getDefault() );
741                        dimensionElement.setAttribute( "multipleValues",
742                                                       ( ( dimension.getMultipleValues().booleanValue() ) ? "1" : "0" ) );
743                        dimensionElement.setAttribute( "nearestValue",
744                                                       ( ( dimension.getNearestValue().booleanValue() ) ? "1" : "0" ) );
745                        dimensionElement.setAttribute( "current", ( ( dimension.getCurrent().booleanValue() ) ? "1" : "0" ) );
746    
747                        Text dimensionText = dimensionElement.getOwnerDocument().createTextNode( dimension.getValue() );
748                        dimensionElement.appendChild( dimensionText );
749                    }
750                }
751            }
752        }
753    
754        /**
755         * Appends the DOM representations of the given array of <code>Format</code> to the passed
756         * <code>Element</code>.
757         *
758         * @param datasetNode
759         * @param mimeTypeFormat
760         */
761        private void appendFormats( Element datasetNode, String[] mimeTypeFormat ) {
762    
763            if ( mimeTypeFormat != null ) {
764    
765                for ( int i = 0; i < mimeTypeFormat.length; i++ ) {
766                    Element format = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "Format" );
767                    Text formatText = format.getOwnerDocument().createTextNode( mimeTypeFormat[i] );
768                    format.appendChild( formatText );
769                }
770            }
771        }
772    
773        /**
774         * Appends the DOM representations of the given array of <code>CRS</code> to the passed
775         * <code>Element</code>.
776         *
777         * @param datasetNode
778         * @param coordinateSystems
779         */
780        private void appendCRSNodes( Element datasetNode, CoordinateSystem[] coordinateSystems ) {
781    
782            if ( coordinateSystems != null ) {
783                for ( CoordinateSystem crs : coordinateSystems ) {
784                    Element crsElement = XMLTools.appendElement( datasetNode, WPVSNS, PRE_WPVS + "CRS" );
785                    Text crsText = crsElement.getOwnerDocument().createTextNode( crs.getFormattedString() );
786                    crsElement.appendChild( crsText );
787                }
788            }
789        }
790    
791        /**
792         * Appends the DOM representation of the given parameters <code>Envelope, elementName, crsName,
793         * dimension</code>
794         * to the passed <code>Element</code>.
795         *
796         * elementName should be of the kind ows:WGS84BoundingBox" or "ows:BoundingBox". crsName should
797         * be of the kind "urn:ogc:def:crs:OGC:2:84" or "...TODO...". dimension should be "2".
798         *
799         * @param root
800         * @param envelope
801         * @param elementName
802         * @param crsName
803         * @param dimension
804         */
805        private void appendBoundingBox( Element root, Envelope envelope, String elementName, String crsName,
806                                        String dimension ) {
807    
808            Element boundingBoxElement = XMLTools.appendElement( root, OWSNS, elementName );
809            boundingBoxElement.setAttribute( "crs", crsName );
810            boundingBoxElement.setAttribute( "dimensions", dimension );
811    
812            Element lowerCornerElement = XMLTools.appendElement( boundingBoxElement, OWSNS, PRE_OWS + "LowerCorner" );
813            Text lowerCornerText = lowerCornerElement.getOwnerDocument().createTextNode(
814                                                                                         envelope.getMin().getX()
815                                                                                                                 + " "
816                                                                                                                 + envelope.getMin().getY() );
817            lowerCornerElement.appendChild( lowerCornerText );
818    
819            Element upperCornerElement = XMLTools.appendElement( boundingBoxElement, OWSNS, PRE_OWS + "UpperCorner" );
820            Text upperCornerText = upperCornerElement.getOwnerDocument().createTextNode(
821                                                                                         envelope.getMax().getX()
822                                                                                                                 + " "
823                                                                                                                 + envelope.getMax().getY() );
824            upperCornerElement.appendChild( upperCornerText );
825    
826        }
827    
828    }