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