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