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