001    // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/owscommon/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     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.owscommon;
045    
046    import java.io.UnsupportedEncodingException;
047    import java.net.URI;
048    import java.net.URL;
049    import java.net.URLEncoder;
050    
051    import org.deegree.framework.util.CharsetUtils;
052    import org.deegree.framework.xml.XMLFragment;
053    import org.deegree.framework.xml.XMLParsingException;
054    import org.deegree.framework.xml.XMLTools;
055    import org.deegree.model.metadata.iso19115.Address;
056    import org.deegree.model.metadata.iso19115.ContactInfo;
057    import org.deegree.model.metadata.iso19115.Keywords;
058    import org.deegree.model.metadata.iso19115.Linkage;
059    import org.deegree.model.metadata.iso19115.OnlineResource;
060    import org.deegree.model.metadata.iso19115.Phone;
061    import org.deegree.model.metadata.iso19115.TypeCode;
062    import org.deegree.ogcbase.CommonNamespaces;
063    import org.deegree.ogcwebservices.ExceptionDocument;
064    import org.deegree.ogcwebservices.ExceptionReport;
065    import org.deegree.ogcwebservices.OGCWebServiceException;
066    import org.deegree.ogcwebservices.getcapabilities.DCPType;
067    import org.deegree.ogcwebservices.getcapabilities.HTTP;
068    import org.deegree.ogcwebservices.getcapabilities.Operation;
069    import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
070    import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification;
071    import org.deegree.ogcwebservices.getcapabilities.ServiceProvider;
072    import org.w3c.dom.Element;
073    
074    /**
075     * Factory to create XML representations of components that are defined in the
076     * <code>OWS Common Implementation Capabilities Specification 0.3</code>.
077     * 
078     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
079     * @author last edited by: $Author: aschmitz $
080     * 
081     * @version $Revision: 7975 $, $Date: 2007-08-10 09:38:27 +0200 (Fr, 10 Aug 2007) $
082     */
083    public class XMLFactory extends org.deegree.ogcbase.XMLFactory {
084    
085        protected static final URI OWSNS = CommonNamespaces.OWSNS;
086        
087        private static final String POGC = CommonNamespaces.OGC_PREFIX + ':';
088    
089        protected static final URI DEEGREECSWNS = CommonNamespaces.DEEGREECSW;
090    
091        /**
092         * Exports an <tt>ExceptionReport</tt> to an XML Document as defined in the
093         * <code>OGC common implementation specification 0.2.0</code>.
094         * 
095         * @param exr
096         * @return a new ServiceException document
097         */
098        public static XMLFragment export( ExceptionReport exr ) {
099    
100            ExceptionDocument eDoc = new ExceptionDocument();
101            eDoc.createEmptyDocument();
102            Element node = eDoc.getRootElement();
103    
104            for ( int i = 0; i < exr.getExceptions().length; i++ ) {
105                appendException( node, exr.getExceptions()[i], false );
106            }
107    
108            return eDoc;
109        }
110    
111        /**
112         * @param exr
113         * @return a new ServiceException document
114         */
115        public static XMLFragment exportNS( ExceptionReport exr ) {
116    
117            ExceptionDocument eDoc = new ExceptionDocument();
118            eDoc.createEmptyDocumentNS();
119            Element node = eDoc.getRootElement();
120    
121            for ( int i = 0; i < exr.getExceptions().length; i++ ) {
122                appendException( node, exr.getExceptions()[i], true );
123            }
124    
125            return eDoc;
126    
127        }
128    
129        /**
130         * appends a xml representation of an <tt>OGCWebServiceException</tt> to the passed
131         * <tt>Element</tt>
132         * 
133         * @param node
134         * @param ex
135         * @param namespace if true, the ogc prefix (bound to the ogc namespace) will be appended
136         */
137        protected static void appendException( Element node, OGCWebServiceException ex,
138                                              boolean namespace ) {
139    
140            if ( namespace ) {
141                node = XMLTools.appendElement( node, OGCNS, POGC + "ServiceException", ex.getMessage() );
142            } else {
143                node = XMLTools.appendElement( node, null, "ServiceException", ex.getMessage() );
144            }
145    
146            if ( ex.getCode() != null ) {
147                node.setAttribute( "code", ex.getCode().value );
148            }
149            String locator = ex.getLocator();
150            try {
151                if ( locator != null ) {
152                    locator = URLEncoder.encode( locator, CharsetUtils.getSystemCharset() );
153                } else {
154                    locator = "unknown";
155                }
156            } catch ( UnsupportedEncodingException e ) {
157                //if catched why not do something -> setting locator to "unknown"
158                locator = "unknown";            
159            }
160            node.setAttribute( "locator", locator );
161        }
162    
163        /**
164         * Appends the DOM representation of the <code>ServiceIdentification</code>- section to the
165         * passed <code>Element</code>.
166         * 
167         * @param root
168         * @param serviceIdentification
169         * @throws XMLParsingException
170         */
171        protected static void appendServiceIdentification( Element root,
172                                                          ServiceIdentification serviceIdentification ) {
173    
174            // 'ServiceIdentification'-element
175            Element serviceIdentificationNode = XMLTools.appendElement( root, OWSNS,
176                                                                        "ows:ServiceIdentification" );
177    
178            // 'ServiceType'-element
179            XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceType",
180                                    serviceIdentification.getServiceType().getCode() );
181    
182            // 'ServiceTypeVersion'-elements
183            String[] versions = serviceIdentification.getServiceTypeVersions();
184            for ( int i = 0; i < versions.length; i++ ) {
185                XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceTypeVersion",
186                                        versions[i] );
187            }
188    
189            // 'Title'-element
190            XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Title",
191                                    serviceIdentification.getTitle() );
192    
193            // 'Abstract'-element
194            if ( serviceIdentification.getAbstract() != null ) {
195                XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Abstract",
196                                        serviceIdentification.getAbstract() );
197            }
198    
199            // 'Keywords'-element
200            appendOWSKeywords( serviceIdentificationNode, serviceIdentification.getKeywords() );
201    
202            // 'Fees'-element
203            XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Fees",
204                                    serviceIdentification.getFees() );
205    
206            // 'AccessConstraints'-element
207            String[] constraints = serviceIdentification.getAccessConstraints();
208            if ( constraints != null ) {
209                for ( int i = 0; i < constraints.length; i++ ) {
210                    XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:AccessConstraints",
211                                            constraints[i] );
212                }
213            }
214        }
215    
216        /**
217         * Appends a <code>ows:Keywords</code> -element for each <code>Keywords</code> object of the
218         * passed array to the passed <code>Element</code>.
219         * 
220         * @param xmlNode
221         * @param keywords
222         */
223        protected static void appendOWSKeywords( Element xmlNode, Keywords[] keywords ) {
224            if ( keywords != null ) {
225                for ( int i = 0; i < keywords.length; i++ ) {
226                    Element node = XMLTools.appendElement( xmlNode, OWSNS, "ows:Keywords" );
227                    appendOWSKeywords( node, keywords[i] );
228                }
229            }
230        }
231    
232        /**
233         * Appends a <code>ows:Keywords</code> -element to the passed <code>Element</code> and fills
234         * it with the available keywords.
235         * 
236         * @param xmlNode
237         * @param keywords
238         */
239        protected static void appendOWSKeywords( Element xmlNode, Keywords keywords ) {
240            if ( keywords != null ) {
241                String[] kw = keywords.getKeywords();
242                for ( int i = 0; i < kw.length; i++ ) {
243                    XMLTools.appendElement( xmlNode, OWSNS, "ows:Keyword", kw[i] );
244                }
245                TypeCode typeCode = keywords.getTypeCode();
246                if ( typeCode != null ) {
247                    Element node = XMLTools.appendElement( xmlNode, OWSNS, "ows:Type",
248                                                           typeCode.getCode() );
249                    if ( typeCode.getCodeSpace() != null ) {
250                        node.setAttribute( "codeSpace", typeCode.getCodeSpace().toString() );
251                    }
252                }
253            }
254        }
255    
256        /**
257         * Appends the DOM representation of the <code>ServiceProvider</code>- section to the passed
258         * <code>Element</code>.
259         * 
260         * @param root
261         * @param serviceProvider
262         * @throws XMLParsingException
263         */
264        protected static void appendServiceProvider( Element root, ServiceProvider serviceProvider ) {
265    
266            // 'ServiceProvider'-element
267            Element serviceProviderNode = XMLTools.appendElement( root, OWSNS, "ows:ServiceProvider" );
268    
269            // 'ProviderName'-element
270            XMLTools.appendElement( serviceProviderNode, OWSNS, "ows:ProviderName",
271                                    serviceProvider.getProviderName() );
272    
273            // 'ProviderSite'-element
274            if ( serviceProvider.getProviderSite() != null ) {
275                Element providerSiteNode = XMLTools.appendElement( serviceProviderNode, OWSNS,
276                                                                   "ows:ProviderSite" );
277                appendSimpleLinkAttributes( providerSiteNode, serviceProvider.getProviderSite() );
278            }
279    
280            // 'ServiceContact'-element
281            Element serviceContactNode = XMLTools.appendElement( serviceProviderNode, OWSNS,
282                                                                 "ows:ServiceContact" );
283    
284            // 'IndividualName'-element
285            XMLTools.appendElement( serviceContactNode, OWSNS, "ows:IndividualName",
286                                    serviceProvider.getIndividualName() );
287    
288            // 'PositionName'-element
289            if ( serviceProvider.getPositionName() != null ) {
290                XMLTools.appendElement( serviceContactNode, OWSNS, "ows:PositionName",
291                                        serviceProvider.getPositionName() );
292            }
293    
294            // 'ContactInfo'-element
295            ContactInfo contactInfo = serviceProvider.getContactInfo();
296            if ( contactInfo != null ) {
297                Element contactInfoNode = XMLTools.appendElement( serviceContactNode, OWSNS,
298                                                                  "ows:ContactInfo" );
299                Phone phone = contactInfo.getPhone();
300                if ( phone != null ) {
301                    appendPhone( contactInfoNode, phone );
302                }
303                Address address = contactInfo.getAddress();
304                if ( address != null ) {
305                    appendAddress( contactInfoNode, address );
306                }
307                OnlineResource onlineResource = contactInfo.getOnLineResource();
308                if ( onlineResource != null ) {
309                    appendOnlineResource( contactInfoNode, "ows:OnlineResource", onlineResource, OWSNS );
310                }
311                String hoursOfService = contactInfo.getHoursOfService();
312                if ( hoursOfService != null ) {
313                    XMLTools.appendElement( contactInfoNode, OWSNS, "ows:HoursOfService",
314                                            hoursOfService );
315                }
316                String contactInstructions = contactInfo.getContactInstructions();
317                if ( contactInstructions != null ) {
318                    XMLTools.appendElement( contactInfoNode, OWSNS, "ows:ContactInstructions",
319                                            contactInstructions );
320                }
321            }
322            TypeCode role = serviceProvider.getRole();
323            if ( role != null ) {
324                Element roleElement = XMLTools.appendElement( serviceContactNode, OWSNS, "ows:Role",
325                                                              role.getCode() );
326                if ( role.getCodeSpace() != null ) {
327                    roleElement.setAttribute( "codeSpace", role.getCodeSpace().toString() );
328                }
329            }
330        }
331    
332        /**
333         * Appends the DOM representation of the <code>Phone</code> -section to the passed
334         * <code>Element</code>.
335         * 
336         * @param root
337         * @param phone
338         */
339        protected static void appendPhone( Element root, Phone phone ) {
340    
341            // 'Phone'-element
342            Element phoneNode = XMLTools.appendElement( root, OWSNS, "ows:Phone" );
343    
344            // 'Voice'-elements
345            String[] voiceNumbers = phone.getVoice();
346            for ( int i = 0; i < voiceNumbers.length; i++ ) {
347                XMLTools.appendElement( phoneNode, OWSNS, "ows:Voice", voiceNumbers[i] );
348            }
349    
350            // 'Facsimile'-elements
351            String[] facsimileNumbers = phone.getFacsimile();
352            for ( int i = 0; i < facsimileNumbers.length; i++ ) {
353                XMLTools.appendElement( phoneNode, OWSNS, "ows:Facsimile", facsimileNumbers[i] );
354            }
355        }
356    
357        /**
358         * Appends the DOM representation of the <code>Address</code> -section to the passed
359         * <code>Element</code>.
360         * 
361         * @param root
362         * @param address
363         */
364        protected static void appendAddress( Element root, Address address ) {
365    
366            // 'Address'-element
367            Element addressNode = XMLTools.appendElement( root, OWSNS, "ows:Address" );
368    
369            // 'DeliveryPoint'-elements
370            String[] deliveryPoints = address.getDeliveryPoint();
371            for ( int i = 0; i < deliveryPoints.length; i++ ) {
372                XMLTools.appendElement( addressNode, OWSNS, "ows:DeliveryPoint", deliveryPoints[i] );
373            }
374    
375            // 'City'-element
376            if ( address.getCity() != null ) {
377                XMLTools.appendElement( addressNode, OWSNS, "ows:City", address.getCity() );
378            }
379    
380            // 'AdministrativeArea'-element
381            if ( address.getAdministrativeArea() != null ) {
382                XMLTools.appendElement( addressNode, OWSNS, "ows:AdministrativeArea",
383                                        address.getAdministrativeArea() );
384            }
385    
386            // 'PostalCode'-element
387            if ( address.getPostalCode() != null ) {
388                XMLTools.appendElement( addressNode, OWSNS, "ows:PostalCode", address.getPostalCode() );
389            }
390    
391            // 'Country'-element
392            if ( address.getCountry() != null ) {
393                XMLTools.appendElement( addressNode, OWSNS, "ows:Country", address.getCountry() );
394            }
395    
396            // 'ElectronicMailAddress'-elements
397            String[] electronicMailAddresses = address.getElectronicMailAddress();
398            if ( address.getElectronicMailAddress() != null ) {
399                for ( int i = 0; i < electronicMailAddresses.length; i++ ) {
400                    XMLTools.appendElement( addressNode, OWSNS, "ows:ElectronicMailAddress",
401                                            electronicMailAddresses[i] );
402                }
403            }
404        }
405    
406        /**
407         * Appends the DOM representation of the <code>OperationsMetadata</code>- section to the
408         * passed <code>Element</code>.
409         * 
410         * @param root
411         */
412        protected static void appendOperationsMetadata( Element root,
413                                                       OperationsMetadata operationsMetadata ) {
414    
415            // 'ows:OperationsMetadata'-element
416            Element operationsMetadataNode = XMLTools.appendElement( root, OWSNS,
417                                                                     "ows:OperationsMetadata" );
418    
419            // append all Operations
420            Operation[] operations = operationsMetadata.getOperations();
421            for ( int i = 0; i < operations.length; i++ ) {
422                Operation operation = operations[i];
423    
424                // 'ows:Operation'-element
425                Element operationElement = XMLTools.appendElement( operationsMetadataNode, OWSNS,
426                                                                   "ows:Operation" );
427                operationElement.setAttribute( "name", operation.getName() );
428    
429                // 'ows:DCP'-elements
430                DCPType[] dcps = operation.getDCPs();
431                for ( int j = 0; j < dcps.length; j++ ) {
432                    appendDCP( operationElement, dcps[j] );
433                }
434    
435                // 'ows:Parameter'-elements
436                OWSDomainType[] parameters = operation.getParameters();
437                for ( int j = 0; j < parameters.length; j++ ) {
438                    appendParameter( operationElement, parameters[j], "ows:Parameter" );
439                }
440    
441                // 'ows:Metadata'-elements
442                Object[] metadata = operation.getMetadata();
443                if ( metadata != null ) {
444                    for ( int j = 0; j < metadata.length; j++ ) {
445                        appendMetadata( operationElement, metadata[j] );
446                    }
447                }
448            }
449    
450            // append general parameters
451            OWSDomainType[] parameters = operationsMetadata.getParameter();
452            for ( int i = 0; i < parameters.length; i++ ) {
453                appendParameter( operationsMetadataNode, parameters[i], "ows:Parameter" );
454            }
455    
456            // append constraints
457            OWSDomainType[] constraints = operationsMetadata.getConstraints();
458            for ( int i = 0; i < constraints.length; i++ ) {
459                appendParameter( operationsMetadataNode, constraints[i], "ows:Constraint" );
460            }
461        }
462    
463        /**
464         * Appends the DOM representation of a <code>DCPType</code> instance to the passed
465         * <code>Element</code>.
466         * 
467         * @param root
468         * @param dcp
469         */
470        protected static void appendDCP( Element root, DCPType dcp ) {
471    
472            // 'ows:DCP'-element
473            Element dcpNode = XMLTools.appendElement( root, OWSNS, "ows:DCP" );
474    
475            // currently, the only supported DCP is HTTP!
476            if ( dcp.getProtocol() instanceof HTTP ) {
477                HTTP http = (HTTP) dcp.getProtocol();
478    
479                // 'ows:HTTP'-element
480                Element httpNode = XMLTools.appendElement( dcpNode, OWSNS, "ows:HTTP" );
481    
482                // 'ows:Get'-elements
483                URL[] getURLs = http.getGetOnlineResources();
484                for ( int i = 0; i < getURLs.length; i++ ) {
485                    appendOnlineResource( httpNode, "ows:Get",
486                                          new OnlineResource( new Linkage( getURLs[i] ) ), OWSNS );
487                }
488    
489                // 'ows:Post'-elements
490                URL[] postURLs = http.getPostOnlineResources();
491                for ( int i = 0; i < postURLs.length; i++ ) {
492                    appendOnlineResource( httpNode, "ows:Post",
493                                          new OnlineResource( new Linkage( postURLs[i] ) ), OWSNS );
494                }
495            }
496        }
497    
498        /**
499         * Appends the DOM representation of a <code>OWSDomainType</code> instance to the passed
500         * <code>Element</code>.
501         * 
502         * @param root
503         * @param parameter
504         */
505        protected static void appendParameter( Element root, OWSDomainType parameter, String elementName ) {
506    
507            // 'ows:Parameter'-element
508            Element parameterNode = XMLTools.appendElement( root, OWSNS, elementName );
509            parameterNode.setAttribute( "name", parameter.getName() );
510    
511            // 'ows:Value'-elements
512            String[] values = parameter.getValues();
513            for ( int i = 0; i < values.length; i++ ) {
514                XMLTools.appendElement( parameterNode, OWSNS, "ows:Value", values[i] );
515            }
516        }
517    
518        /**
519         * Appends the DOM representation of a <code>Metadata</code> instance to the passed
520         * <code>Element</code>.
521         * 
522         * @param root
523         * @param metadata
524         */
525        protected static void appendMetadata( Element root, Object metadata ) {
526    
527            // TODO
528    
529        }
530    }