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