001    // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wcs/XMLFactory.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.ogcwebservices.wcs;
045    
046    import java.io.IOException;
047    import java.net.URI;
048    import java.net.URL;
049    
050    import org.deegree.datatypes.CodeList;
051    import org.deegree.datatypes.values.Interval;
052    import org.deegree.datatypes.values.TypedLiteral;
053    import org.deegree.datatypes.values.ValueEnum;
054    import org.deegree.framework.log.ILogger;
055    import org.deegree.framework.log.LoggerFactory;
056    import org.deegree.framework.util.StringTools;
057    import org.deegree.framework.xml.XMLFragment;
058    import org.deegree.framework.xml.XMLParsingException;
059    import org.deegree.framework.xml.XMLTools;
060    import org.deegree.model.metadata.iso19115.Address;
061    import org.deegree.model.metadata.iso19115.CitedResponsibleParty;
062    import org.deegree.model.metadata.iso19115.ContactInfo;
063    import org.deegree.model.metadata.iso19115.Linkage;
064    import org.deegree.model.metadata.iso19115.OnlineResource;
065    import org.deegree.model.metadata.iso19115.Phone;
066    import org.deegree.model.spatialschema.Envelope;
067    import org.deegree.ogcbase.CommonNamespaces;
068    import org.deegree.ogcwebservices.ExceptionFormat;
069    import org.deegree.ogcwebservices.MetadataLink;
070    import org.deegree.ogcwebservices.SupportedFormats;
071    import org.deegree.ogcwebservices.SupportedSRSs;
072    import org.deegree.ogcwebservices.getcapabilities.Capability;
073    import org.deegree.ogcwebservices.getcapabilities.HTTP;
074    import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
075    import org.deegree.ogcwebservices.getcapabilities.Operation;
076    import org.deegree.ogcwebservices.getcapabilities.Service;
077    import org.deegree.ogcwebservices.wcs.configuration.InvalidConfigurationException;
078    import org.deegree.ogcwebservices.wcs.configuration.WCSConfiguration;
079    import org.deegree.ogcwebservices.wcs.configuration.WCSConfigurationDocument;
080    import org.deegree.ogcwebservices.wcs.configuration.WCSDeegreeParams;
081    import org.deegree.ogcwebservices.wcs.describecoverage.AxisDescription;
082    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescription;
083    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescriptionDocument;
084    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
085    import org.deegree.ogcwebservices.wcs.describecoverage.DomainSet;
086    import org.deegree.ogcwebservices.wcs.describecoverage.InvalidCoverageDescriptionExcpetion;
087    import org.deegree.ogcwebservices.wcs.describecoverage.RangeSet;
088    import org.deegree.ogcwebservices.wcs.describecoverage.SpatialDomain;
089    import org.deegree.ogcwebservices.wcs.getcapabilities.ContentMetadata;
090    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities;
091    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilitiesDocument;
092    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilityOperations;
093    import org.w3c.dom.Document;
094    import org.w3c.dom.Element;
095    import org.xml.sax.SAXException;
096    
097    /**
098     * 
099     * 
100     * @version $Revision: 9345 $
101     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
102     * @author last edited by: $Author: apoth $
103     * 
104     * @version 1.0. $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $
105     * 
106     * @since 1.1
107     */
108    public class XMLFactory extends org.deegree.ogcbase.XMLFactory {
109    
110        private static final ILogger LOG = LoggerFactory.getLogger( XMLFactory.class );
111    
112        protected static final URI WCSNS = CommonNamespaces.WCSNS;
113    
114        protected static final URI DGRNS = CommonNamespaces.DEEGREEWCS;
115    
116        /**
117         * ... notice:
118         * </p>
119         * at the moment just HTTP is supported as DCPType. It is assumed that just one HTTP element is
120         * assigned within an operation
121         * </p>
122         * vendor specific capabilities are not supported yet and won't be appended to the document if
123         * present.
124         * 
125         * @param capabilities
126         * @return
127         * @throws InvalidCapabilitiesException
128         */
129        public static WCSCapabilitiesDocument export( WCSCapabilities capabilities )
130                                throws InvalidCapabilitiesException, IOException {
131            WCSCapabilitiesDocument wcsCapaDoc = new WCSCapabilitiesDocument();
132            try {
133                wcsCapaDoc.createEmptyDocument();
134                Element root = wcsCapaDoc.getRootElement();
135    
136                Service service = capabilities.getService();
137                appendService( root, service );
138                Capability capability = capabilities.getCapabilitiy();
139                appendCapability( root, capability );
140                ContentMetadata contentMetadata = capabilities.getContentMetadata();
141                appendContentMetadata( root, contentMetadata );
142            } catch ( XMLParsingException e ) {
143                LOG.logError( "could not parse the WCSCapabilitiesTemplate.xml", e );
144                String s = "could not parse the WCSCapabilitiesTemplate.xml" + "\n" + e.getMessage();
145                throw new InvalidCapabilitiesException( s );
146            } catch ( SAXException e ) {
147                LOG.logError( "couldn't create XML Document for CoverageDescription ", e );
148                throw new IOException( "couldn't create XML Document for CoverageDescription" + e.getMessage() );
149            }
150            return wcsCapaDoc;
151        }
152    
153        public static XMLFragment export( WCSConfiguration configuration )
154                                throws InvalidConfigurationException, IOException {
155            WCSConfigurationDocument wcsConfigDoc = new WCSConfigurationDocument();
156            try {
157                wcsConfigDoc.createEmptyDocument();
158                Element root = wcsConfigDoc.getRootElement();
159                WCSDeegreeParams deegreeParams = configuration.getDeegreeParams();
160                appendDeegreeParams( root, deegreeParams );
161                Service service = configuration.getService();
162                appendService( root, service );
163                Capability capability = configuration.getCapabilitiy();
164                appendCapability( root, capability );
165                ContentMetadata contentMetadata = configuration.getContentMetadata();
166                appendContentMetadata( root, contentMetadata );
167            } catch ( XMLParsingException e ) {
168                String s = "could not parse the WCSCapabilitiesTemplate.xml" + "\n" + e.getMessage() + "\n"
169                           + StringTools.stackTraceToString( e );
170                throw new InvalidConfigurationException( s );
171            } catch ( SAXException e ) {
172                throw new IOException( "couldn't create XML Document for CoverageDescription " + e.getMessage() + "\n"
173                                       + StringTools.stackTraceToString( e ) );
174            }
175            return wcsConfigDoc;
176        }
177    
178        /**
179         * exprots a WCS <tt>CoverageDescription</tt> object to its XML represetation encapsulated
180         * within a <tt>XmlDocument</tt>
181         * 
182         * @param coverageDescription
183         * @return
184         * @throws InvalidCoverageDescriptionExcpetion
185         * @throws IOException
186         */
187        public static XMLFragment export( CoverageDescription coverageDescription )
188                                throws IOException {
189            CoverageDescriptionDocument covDescDoc = new CoverageDescriptionDocument();
190            try {
191                covDescDoc.createEmptyDocument();
192                Element root = covDescDoc.getRootElement();
193                root.setAttribute( "version", coverageDescription.getVersion() );
194                CoverageOffering[] cos = coverageDescription.getCoverageOfferings();
195                for ( int i = 0; i < cos.length; i++ ) {
196                    appendCoverageOffering( root, cos[i] );
197                }
198            } catch ( SAXException e ) {
199                throw new IOException( "couldn't create XML Document for CoverageDescription " + e.getMessage() + "\n"
200                                       + StringTools.stackTraceToString( e ) );
201            }
202            return covDescDoc;
203        }
204    
205        /**
206         * appends the XML representation of the deegreeParams section to the passed <tt>Element</tt>
207         * 
208         * @param root
209         * @param deegreeParam
210         * @throws XMLParsingException
211         */
212        protected static void appendDeegreeParams( Element root, WCSDeegreeParams deegreeParam )
213                                throws XMLParsingException {
214    
215            Element element = XMLTools.getRequiredChildElement( "deegreeParam", DGRNS, root );
216            Element node = XMLTools.appendElement( element, DGRNS, "deegree:DefaultOnlineResource" );
217            node.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
218            node.setAttribute( "xlink:type", "simple" );
219            node.setAttribute( "xlink:href", deegreeParam.getDefaultOnlineResource().toString() );
220            XMLTools.appendElement( element, DGRNS, "deegree:CacheSize", "" + deegreeParam.getCacheSize() );
221            XMLTools.appendElement( element, DGRNS, "deegree:RequestTimeLimit", "" + deegreeParam.getRequestTimeLimit() );
222            appendDirectoryList( element, deegreeParam.getDirectoryList() );
223    
224        }
225    
226        /**
227         * appends the XML representation of a list of data directory names to the passed
228         * <tt>XmlNode</tt>
229         * 
230         * @param dgrParam
231         * @param directoryList
232         */
233        protected static void appendDirectoryList( Element dgrParam, String[] directoryList ) {
234            if ( directoryList == null || directoryList.length == 0 )
235                return;
236            Element node = XMLTools.appendElement( dgrParam, DGRNS, "deegree:DataDirectoryList", null );
237            for ( int i = 0; i < directoryList.length; i++ ) {
238                XMLTools.appendElement( node, DGRNS, "deegree:DataDirectory", directoryList[i] );
239            }
240        }
241    
242        protected static void appendCoverageOffering( Element parent, CoverageOffering coverageOffering ) {
243    
244            // Document doc = XMLTools.create();
245            Document doc = parent.getOwnerDocument();
246            Element xmlNode = doc.createElementNS( WCSNS.toString(), "CoverageOffering" );
247            /*
248             * Element node = doc.createElementNS(WCSNS, "CoverageDescription" ); doc.appendChild(node);
249             * Element xmlNode = doc.getDocumentElement();
250             */
251    
252            appendMetadataLink( xmlNode, coverageOffering.getMetadataLink() );
253            if ( coverageOffering.getDescription() != null ) {
254                XMLTools.appendElement( xmlNode, WCSNS, "description", coverageOffering.getName() );
255            }
256            XMLTools.appendElement( xmlNode, WCSNS, "name", coverageOffering.getName() );
257            XMLTools.appendElement( xmlNode, WCSNS, "label", coverageOffering.getLabel() );
258            org.deegree.ogcbase.XMLFactory.appendLonLatEnvelope( xmlNode, coverageOffering.getLonLatEnvelope(), WCSNS );
259            appendKeywords( xmlNode, coverageOffering.getKeywords(), WCSNS );
260            appendDomainSet( xmlNode, coverageOffering.getDomainSet() );
261            appendRangeSet( xmlNode, coverageOffering.getRangeSet() );
262            appendSupportedCRSs( xmlNode, coverageOffering.getSupportedCRSs() );
263            appendSupportedFormats( xmlNode, coverageOffering.getSupportedFormats() );
264            appendSupportedInterpolations( xmlNode, coverageOffering.getSupportedInterpolations() );
265            // TODO appendExtension
266            // XmlNode coveDesc = new XmlNode( parent );
267            // coveDesc.appendDomElement( WCSNS, "CoverageOffering", xmlNode);
268            parent.appendChild( xmlNode );
269        }
270    
271        /**
272         * appends the XML representation of the passed <tt>MetadataLink</tt> to the passed
273         * <tt>XmlNode</tt> including all attributes
274         * 
275         * @param xmlNode
276         * @param mLink
277         */
278        protected static void appendMetadataLink( Element xmlNode, MetadataLink mLink ) {
279            if ( mLink != null ) {
280                Element element = XMLTools.appendElement( xmlNode, WCSNS, "metadataLink" );
281                element.setAttribute( "xlink:type", "simple" );
282                element.setAttribute( "xlink:href", mLink.getReference().toString() );
283                element.setAttribute( "about", mLink.getAbout().toString() );
284                element.setAttribute( "metadataType", mLink.getMetadataType().value );
285                element.setAttribute( "xlink:title", mLink.getTitle() );
286            }
287        }
288    
289        /**
290         * appends a XML representation of the passed <tt>DomainSet</tt> to the passed
291         * <tt>XmlNode</tt>
292         * 
293         * @param xmlNode
294         * @param domainSet
295         */
296        protected static void appendDomainSet( Element xmlNode, DomainSet domainSet ) {
297            Element node = XMLTools.appendElement( xmlNode, WCSNS, "domainSet" );
298            appendSpatialDomain( node, domainSet.getSpatialDomain() );
299            appendTemporalDomain( node, domainSet.getTimeSequence(), WCSNS );
300        }
301    
302        /**
303         * append the XML representation of a <tt>SpatialDomain</tt> object to the passed
304         * <tt>XmlNode</tt>. At the moment deegree just considers enclosed gml:Envelope elements
305         * gml:Grid and gml:Polygon are not supported yet
306         * 
307         * @param xmlNode
308         * @param spatialDomain
309         */
310        protected static void appendSpatialDomain( Element xmlNode, SpatialDomain spatialDomain ) {
311            Element node = XMLTools.appendElement( xmlNode, WCSNS, "spatialDomain" );
312            Envelope[] envelops = spatialDomain.getEnvelops();
313            for ( int i = 0; i < envelops.length; i++ ) {
314                appendEnvelope( node, envelops[i] );
315            }
316        }
317    
318        /**
319         * appends a XML representation of the passed <tt>RangeSet</tt> to the passed <tt>XmlNode</tt>
320         * 
321         * @param xmlNode
322         * @param rangeSet
323         */
324        protected static void appendRangeSet( Element xmlNode, RangeSet rangeSet ) {
325            Element node = XMLTools.appendElement( xmlNode, WCSNS, "rangeSet" );
326            Element tmp = node;
327            node = XMLTools.appendElement( tmp, WCSNS, "RangeSet", null );
328            Element rs = node;
329            appendMetadataLink( rs, rangeSet.getMetadataLink() );
330            if ( rangeSet.getDescription() != null ) {
331                XMLTools.appendElement( rs, WCSNS, "description", rangeSet.getDescription() );
332            }
333            XMLTools.appendElement( rs, WCSNS, "name", rangeSet.getName() );
334            XMLTools.appendElement( rs, WCSNS, "label", rangeSet.getLabel() );
335            AxisDescription[] axisDesc = rangeSet.getAxisDescription();
336            if ( axisDesc != null ) {
337                for ( int i = 0; i < axisDesc.length; i++ ) {
338                    appendAxisDescription( rs, axisDesc[i] );
339                }
340            }
341            appendNullValues( rs, rangeSet.getNullValues() );
342        }
343    
344        /**
345         * appends a XML representation of the passed <tt>AxisDescription</tt> to the passed
346         * <tt>XmlNode</tt>
347         * 
348         * @param xmlNode
349         * @param axisDesc
350         */
351        protected static void appendAxisDescription( Element xmlNode, AxisDescription axisDesc ) {
352            Element node = XMLTools.appendElement( xmlNode, WCSNS, "axisDescription", null );
353            Element ad = node;
354            node = XMLTools.appendElement( ad, WCSNS, "AxisDescription", null );
355            Element aD = node;
356            appendMetadataLink( aD, axisDesc.getMetadataLink() );
357            if ( axisDesc.getDescription() != null ) {
358                XMLTools.appendElement( aD, WCSNS, "description", axisDesc.getDescription() );
359            }
360            XMLTools.appendElement( aD, WCSNS, "name", axisDesc.getName() );
361            XMLTools.appendElement( aD, WCSNS, "label", axisDesc.getLabel() );
362            appendValues( aD, axisDesc.getValues(), WCSNS );
363    
364        }
365    
366        /**
367         * appends a XML representation of the passed <tt>ValueEnum</tt> to the passed
368         * <tt>XmlNode</tt>
369         * 
370         * @param xmlNode
371         * @param values
372         */
373        protected static void appendNullValues( Element xmlNode, ValueEnum values ) {
374            Element node = XMLTools.appendElement( xmlNode, WCSNS, "nullValues" );
375            Element val = node;
376            if ( values.getType() != null ) {
377                node.setAttribute( "xmlns:wcs", WCSNS.toString() );
378                node.setAttributeNS( WCSNS.toString(), "wcs:type", values.getType().toString() );
379            }
380            if ( values.getSemantic() != null ) {
381                node.setAttribute( "xmlns:wcs", WCSNS.toString() );
382                node.setAttributeNS( WCSNS.toString(), "wcs:semantic", values.getSemantic().toString() );
383            }
384            Interval[] intervals = values.getInterval();
385            if ( intervals != null ) {
386                for ( int i = 0; i < intervals.length; i++ ) {
387                    appendInterval( val, intervals[i], WCSNS );
388                }
389            }
390            TypedLiteral[] sVal = values.getSingleValue();
391            if ( sVal != null ) {
392                for ( int i = 0; i < sVal.length; i++ ) {
393                    appendTypedLiteral( val, sVal[i], "singleValue", WCSNS );
394                }
395            }
396        }
397    
398        /**
399         * appends a XML representation of the passed <tt>SupportedSRSs</tt> to the passed
400         * <tt>XmlNode</tt>
401         * 
402         * @param xmlNode
403         * @param supportedCRSs
404         */
405        protected static void appendSupportedCRSs( Element xmlNode, SupportedSRSs supportedCRSs ) {
406            Element node = XMLTools.appendElement( xmlNode, WCSNS, "supportedCRSs" );
407            Element supCRS = node;
408            CodeList[] rrCRS = supportedCRSs.getRequestResponseSRSs();
409            for ( int i = 0; i < rrCRS.length; i++ ) {
410                appendCodeList( supCRS, rrCRS[i], WCSNS );
411            }
412            CodeList[] reqCRS = supportedCRSs.getRequestSRSs();
413            for ( int i = 0; i < reqCRS.length; i++ ) {
414                appendCodeList( supCRS, reqCRS[i], WCSNS );
415            }
416            CodeList[] resCRS = supportedCRSs.getResponseSRSs();
417            for ( int i = 0; i < resCRS.length; i++ ) {
418                appendCodeList( supCRS, resCRS[i], WCSNS );
419            }
420            CodeList[] natCRS = supportedCRSs.getNativeSRSs();
421            for ( int i = 0; i < natCRS.length; i++ ) {
422                appendCodeList( supCRS, natCRS[i], WCSNS );
423            }
424        }
425    
426        /**
427         * appends a XML representation of the passed <tt>SupportedFormats</tt> to the passed
428         * <tt>XmlNode</tt>
429         * 
430         * @param xmlNode
431         * @param supportedFormats
432         */
433        protected static void appendSupportedFormats( Element xmlNode, SupportedFormats supportedFormats ) {
434            Element node = XMLTools.appendElement( xmlNode, WCSNS, "supportedFormats" );
435            CodeList[] formats = supportedFormats.getFormats();
436            for ( int i = 0; i < formats.length; i++ ) {
437                appendCodeList( node, formats[i], WCSNS );
438            }
439        }
440    
441        /**
442         * appends a XML representation of the passed <tt>SupportedInterpolations</tt> to the passed
443         * <tt>XmlNode</tt>
444         * 
445         * @param xmlNode
446         * @param supportedInterpolations
447         */
448        protected static void appendSupportedInterpolations( Element xmlNode,
449                                                             SupportedInterpolations supportedInterpolations ) {
450            Element node = XMLTools.appendElement( xmlNode, WCSNS, "supportedInterpolations" );
451            if ( supportedInterpolations.getDefault() != null ) {
452                String s = supportedInterpolations.getDefault().value;
453                node.setAttribute( "default", s );
454            }
455            Element supInter = node;
456            InterpolationMethod[] ims = supportedInterpolations.getInterpolationMethod();
457            for ( int i = 0; i < ims.length; i++ ) {
458                XMLTools.appendElement( supInter, WCSNS, "interpolationMethod", ims[i].value );
459            }
460        }
461    
462        /**
463         * appends a XML representation of the passed <tt>CapabilitiesService</tt> to the passed
464         * <tt>XmlNode</tt>
465         * 
466         * @param element
467         * @param service
468         */
469        protected static void appendService( Element element, Service service ) {
470            Element elem = XMLTools.getChildElement( "Service", WCSNS, element );
471            elem.setAttribute( "version", service.getVersion() );
472            elem.setAttribute( "updateSequence", service.getUpdateSequence() );
473            Element servNode = elem;
474            appendMetadataLink( servNode, service.getMetadataLink() );
475            if ( service.getDescription() != null ) {
476                XMLTools.appendElement( servNode, WCSNS, "description", service.getDescription() );
477            }
478            XMLTools.appendElement( servNode, WCSNS, "name", service.getName() );
479            XMLTools.appendElement( servNode, WCSNS, "label", service.getLabel() );
480    
481            appendResponsibleParty( servNode, service.getCitedResponsibleParty() );
482            appendCodeList( servNode, service.getFees(), WCSNS );
483            CodeList[] ac = service.getAccessConstraints();
484            if ( ac != null ) {
485                for ( int i = 0; i < ac.length; i++ ) {
486                    appendCodeList( servNode, ac[i], WCSNS );
487                }
488            }
489        }
490    
491        /**
492         * appends a XML representation of the passed <tt>CitedResponsibleParty</tt> to the passed
493         * <tt>XmlNode</tt>
494         * 
495         * @param servNode
496         * @param responsibleParty
497         */
498        protected static void appendResponsibleParty( Element servNode, CitedResponsibleParty responsibleParty ) {
499    
500            Element element = XMLTools.appendElement( servNode, WCSNS, "responsibleParty" );
501            Element respNode = element;
502            String[] in = responsibleParty.getIndividualName();
503            if ( in != null ) {
504                for ( int i = 0; i < in.length; i++ ) {
505                    XMLTools.appendElement( respNode, WCSNS, "individualName", in[i] );
506                }
507            }
508            String[] on = responsibleParty.getOrganisationName();
509            if ( on != null ) {
510                for ( int i = 0; i < on.length; i++ ) {
511                    XMLTools.appendElement( respNode, WCSNS, "organisationName", on[i] );
512                }
513            }
514            String[] pn = responsibleParty.getPositionName();
515            if ( pn != null ) {
516                for ( int i = 0; i < pn.length; i++ ) {
517                    XMLTools.appendElement( respNode, WCSNS, "positionName", pn[i] );
518                }
519            }
520            appendContactInfo( element, responsibleParty.getContactInfo()[0] );
521        }
522    
523        /**
524         * appends a XML representation of the passed <tt>ContactInfo</tt> to the passed
525         * <tt>XmlNode</tt>
526         * 
527         * @param contactNode
528         * @param contactInfo
529         */
530        protected static void appendContactInfo( Element contactNode, ContactInfo contactInfo ) {
531            Element element = XMLTools.appendElement( contactNode, WCSNS, "contactInfo" );
532            Element ciNode = element;
533            Phone phone = contactInfo.getPhone();
534            if ( phone != null ) {
535                appendPhone( ciNode, phone );
536            }
537            Address address = contactInfo.getAddress();
538            if ( address != null ) {
539                appendAddress( ciNode, address );
540            }
541            OnlineResource olr = contactInfo.getOnLineResource();
542            appendOnlineResource( ciNode, olr );
543        }
544    
545        /**
546         * appends a XML representation of the passed <tt>Phone</tt> to the passed <tt>XmlNode</tt>
547         * 
548         * @param ciNode
549         * @param phone
550         */
551        protected static void appendPhone( Element ciNode, Phone phone ) {
552            Element node = XMLTools.appendElement( ciNode, WCSNS, "phone" );
553            Element pnNode = node;
554            String[] voice = phone.getVoice();
555            if ( voice != null ) {
556                for ( int i = 0; i < voice.length; i++ ) {
557                    XMLTools.appendElement( pnNode, WCSNS, "voice", voice[i] );
558                }
559            }
560            String[] facsimile = phone.getFacsimile();
561            if ( facsimile != null ) {
562                for ( int i = 0; i < facsimile.length; i++ ) {
563                    XMLTools.appendElement( pnNode, WCSNS, "facsimile", facsimile[i] );
564                }
565            }
566        }
567    
568        /**
569         * appends a XML representation of the passed <tt>Phone</tt> to the passed <tt>XmlNode</tt>
570         * 
571         * @param ciNode
572         * @param address
573         */
574        protected static void appendAddress( Element ciNode, Address address ) {
575            Element node = XMLTools.appendElement( ciNode, WCSNS, "address" );
576            Element adNode = node;
577            String[] delPoint = address.getDeliveryPoint();
578            if ( delPoint != null ) {
579                for ( int i = 0; i < delPoint.length; i++ ) {
580                    XMLTools.appendElement( adNode, WCSNS, "deliveryPoint", delPoint[i] );
581                }
582            }
583            XMLTools.appendElement( adNode, WCSNS, "city", address.getCity() );
584            XMLTools.appendElement( adNode, WCSNS, "administrativeArea", address.getAdministrativeArea() );
585            XMLTools.appendElement( adNode, WCSNS, "postalCode", address.getPostalCode() );
586            XMLTools.appendElement( adNode, WCSNS, "country", address.getCountry() );
587            String[] eMail = address.getElectronicMailAddress();
588            if ( eMail != null ) {
589                for ( int i = 0; i < eMail.length; i++ ) {
590                    XMLTools.appendElement( adNode, WCSNS, "electronicMailAddress", eMail[i] );
591                }
592            }
593        }
594    
595        /**
596         * appends a XML representation of the passed <tt>OnLineResource</tt> to the passed
597         * <tt>XmlNode</tt>
598         * 
599         * @param ciNode
600         * @param olr
601         */
602        protected static void appendOnlineResource( Element ciNode, OnlineResource olr ) {
603            Element node = XMLTools.appendElement( ciNode, WCSNS, "onlineResource" );
604            node.setAttribute( "xlink:type", "simple" );
605            Linkage linkage = olr.getLinkage();
606            node.setAttribute( "xlink:href", linkage.getHref().toString() );
607        }
608    
609        /**
610         * appends a XML representation of the passed <tt>OnLineResource</tt> to the passed
611         * <tt>Element</tt>. Notice: vendor specific capabilities are not supported yet and, if
612         * present, won't be appended to the root element
613         * 
614         * @param root
615         * @param capability
616         * @throws XMLParsingException
617         */
618        protected static void appendCapability( Element root, Capability capability )
619                                throws XMLParsingException {
620    
621            Element capab = XMLTools.getRequiredChildElement( "Capability", WCSNS, root );
622            capab.setAttribute( "version", capability.getVersion() );
623            capab.setAttribute( "updateSequence", capability.getUpdateSequence() );
624            Element request = XMLTools.getRequiredChildElement( "Request", WCSNS, capab );
625            WCSCapabilityOperations req = (WCSCapabilityOperations) capability.getOperations();
626            Operation operation = req.getGetCapabilitiesOperation();
627            appendOperation( "GetCapabilities", request, operation );
628            operation = req.getDescribeCoverageOperation();
629            appendOperation( "DescribeCoverage", request, operation );
630            operation = req.getGetCoverageOperation();
631            appendOperation( "GetCoverage", request, operation );
632    
633            ExceptionFormat excepForm = capability.getException();
634            appendExceptionFormat( capab, excepForm );
635    
636        }
637    
638        /**
639         * appends a XML representation of the passed <tt>OnLineResource</tt> to the passed
640         * <tt>Element</tt>. at the moment just the first DCPType is considered because other types
641         * than HTTP are not supported yet.
642         * 
643         * @param name
644         * @param root
645         * @param operation
646         * @throws XMLParsingException
647         */
648        protected static void appendOperation( String name, Element root, Operation operation )
649                                throws XMLParsingException {
650            Element getCapa = XMLTools.getRequiredChildElement( name, WCSNS, root );
651            Element dcp = XMLTools.getRequiredChildElement( "DCPType", WCSNS, getCapa );
652            Element http = XMLTools.getRequiredChildElement( "HTTP", WCSNS, dcp );
653            Element get = XMLTools.getRequiredChildElement( "Get", WCSNS, http );
654            Element getNode = get;
655            URL[] urls = ( (HTTP) operation.getDCPs()[0].getProtocol() ).getGetOnlineResources();
656            for ( int i = 0; i < urls.length; i++ ) {
657                Element node = XMLTools.appendElement( getNode, WCSNS, "OnlineResource" );
658                node.setAttribute( "xlink:type", "simple" );
659                node.setAttribute( "xlink:href", urls[i].toString() );
660            }
661            urls = ( (HTTP) operation.getDCPs()[0].getProtocol() ).getPostOnlineResources();
662            if ( urls != null && urls.length > 0 ) {
663                Element httpNode = http;
664                Element node = XMLTools.appendElement( httpNode, WCSNS, "Post" );
665                Element postNode = node;
666                for ( int i = 0; i < urls.length; i++ ) {
667                    node = XMLTools.appendElement( postNode, WCSNS, "OnlineResource" );
668                    node.setAttribute( "xlink:type", "simple" );
669                    node.setAttribute( "xlink:href", urls[i].toString() );
670                }
671            }
672    
673        }
674    
675        /**
676         * appends a XML representation of the passed <tt>OnLineResource</tt> to the passed
677         * <tt>Element</tt>.
678         * 
679         * @param root
680         * @param excepForm
681         */
682        protected static void appendExceptionFormat( Element root, ExceptionFormat excepForm ) {
683            Element node = XMLTools.appendElement( root, WCSNS, "Exception" );
684            String[] formats = excepForm.getFormat();
685            for ( int i = 0; i < formats.length; i++ ) {
686                XMLTools.appendElement( node, WCSNS, "Format", formats[i] );
687            }
688        }
689    
690        /**
691         * appends a XML representation of the passed <tt>ContentMetadata</tt> to the passed
692         * <tt>Element</tt>
693         * 
694         * @param root
695         * @param contentMetadata
696         * @throws XMLParsingException
697         */
698        protected static void appendContentMetadata( Element root, ContentMetadata contentMetadata )
699                                throws XMLParsingException {
700            Element content = XMLTools.getRequiredChildElement( "ContentMetadata", WCSNS, root );
701            content.setAttribute( "version", contentMetadata.getVersion() );
702            content.setAttribute( "updateSequence", contentMetadata.getUpdateSequence() );
703            Element contentNode = content;
704            CoverageOfferingBrief[] cob = contentMetadata.getCoverageOfferingBrief();
705            for ( int i = 0; i < cob.length; i++ ) {
706                appendCoverageOfferingBrief( contentNode, cob[i] );
707            }
708        }
709    
710        /**
711         * appends a XML representation of the passed <tt>CoverageOfferingBrief</tt> to the passed
712         * <tt>XmlNode</tt>
713         * 
714         * @param contentNode
715         * @param cob
716         */
717        protected static void appendCoverageOfferingBrief( Element contentNode, CoverageOfferingBrief cob ) {
718            Element node = XMLTools.appendElement( contentNode, WCSNS, "CoverageOfferingBrief" );
719            Element xmlNode = node;
720            appendMetadataLink( xmlNode, cob.getMetadataLink() );
721            if ( cob.getDescription() != null ) {
722                XMLTools.appendElement( xmlNode, WCSNS, "description", cob.getDescription() );
723            }
724            XMLTools.appendElement( xmlNode, WCSNS, "name", cob.getName() );
725            XMLTools.appendElement( xmlNode, WCSNS, "label", cob.getLabel() );
726            org.deegree.ogcbase.XMLFactory.appendLonLatEnvelope( xmlNode, cob.getLonLatEnvelope(), WCSNS );
727            appendKeywords( xmlNode, cob.getKeywords(), WCSNS );
728        }
729    }