001 // $HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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: mschneider $
077 *
078 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
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", exc.getMessage() );
137 if ( exc.getCode() != null ) {
138 e.setAttribute( "exceptionCode", exc.getCode().value );
139 }
140
141 String locator = exc.getLocator();
142 try {
143 if ( locator != null ) {
144 locator = URLEncoder.encode( locator, CharsetUtils.getSystemCharset() );
145 } else {
146 locator = "unknown";
147 }
148 } catch ( UnsupportedEncodingException _ ) {
149 // if catched why not do something -> setting locator to "unknown"
150 locator = "unknown";
151 }
152 e.setAttribute( "locator", locator );
153 }
154
155 return doc;
156
157 }
158
159 /**
160 * appends a xml representation of an <tt>OGCWebServiceException</tt> to the passed <tt>Element</tt>
161 *
162 * @param node
163 * @param ex
164 * @param namespace
165 * if true, the ogc prefix (bound to the ogc namespace) will be appended
166 */
167 protected static void appendException( Element node, OGCWebServiceException ex, boolean namespace ) {
168
169 if ( namespace ) {
170 node = XMLTools.appendElement( node, OGCNS, POGC + "ServiceException", ex.getMessage() );
171 } else {
172 node = XMLTools.appendElement( node, null, "ServiceException", ex.getMessage() );
173 }
174
175 if ( ex.getCode() != null ) {
176 node.setAttribute( "code", ex.getCode().value );
177 }
178 String locator = ex.getLocator();
179 try {
180 if ( locator != null ) {
181 locator = URLEncoder.encode( locator, CharsetUtils.getSystemCharset() );
182 } else {
183 locator = "unknown";
184 }
185 } catch ( UnsupportedEncodingException e ) {
186 // if catched why not do something -> setting locator to "unknown"
187 locator = "unknown";
188 }
189 node.setAttribute( "locator", locator );
190 }
191
192 /**
193 * Appends the DOM representation of the <code>ServiceIdentification</code>- section to the passed
194 * <code>Element</code>.
195 *
196 * @param root
197 * @param serviceIdentification
198 */
199 protected static void appendServiceIdentification( Element root, ServiceIdentification serviceIdentification ) {
200
201 // 'ServiceIdentification'-element
202 Element serviceIdentificationNode = XMLTools.appendElement( root, OWSNS, "ows:ServiceIdentification" );
203
204 // 'ServiceType'-element
205 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceType",
206 serviceIdentification.getServiceType().getCode() );
207
208 // 'ServiceTypeVersion'-elements
209 String[] versions = serviceIdentification.getServiceTypeVersions();
210 for ( int i = 0; i < versions.length; i++ ) {
211 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceTypeVersion", versions[i] );
212 }
213
214 // 'Title'-element
215 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Title", serviceIdentification.getTitle() );
216
217 // 'Abstract'-element
218 if ( serviceIdentification.getAbstract() != null ) {
219 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Abstract",
220 serviceIdentification.getAbstract() );
221 }
222
223 // 'Keywords'-element
224 appendOWSKeywords( serviceIdentificationNode, serviceIdentification.getKeywords() );
225
226 // 'Fees'-element
227 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Fees", serviceIdentification.getFees() );
228
229 // 'AccessConstraints'-element
230 String[] constraints = serviceIdentification.getAccessConstraints();
231 if ( constraints != null ) {
232 for ( int i = 0; i < constraints.length; i++ ) {
233 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:AccessConstraints", constraints[i] );
234 }
235 }
236 }
237
238 /**
239 * Appends a <code>ows:Keywords</code> -element for each <code>Keywords</code> object of the passed array to the
240 * passed <code>Element</code>.
241 *
242 * @param xmlNode
243 * @param keywords
244 */
245 protected static void appendOWSKeywords( Element xmlNode, Keywords[] keywords ) {
246 if ( keywords != null ) {
247 for ( int i = 0; i < keywords.length; i++ ) {
248 Element node = XMLTools.appendElement( xmlNode, OWSNS, "ows:Keywords" );
249 appendOWSKeywords( node, keywords[i] );
250 }
251 }
252 }
253
254 /**
255 * Appends a <code>ows:Keywords</code> -element to the passed <code>Element</code> and fills it with the available
256 * keywords.
257 *
258 * @param xmlNode
259 * @param keywords
260 */
261 protected static void appendOWSKeywords( Element xmlNode, Keywords keywords ) {
262 if ( keywords != null ) {
263 String[] kw = keywords.getKeywords();
264 for ( int i = 0; i < kw.length; i++ ) {
265 XMLTools.appendElement( xmlNode, OWSNS, "ows:Keyword", kw[i] );
266 }
267 TypeCode typeCode = keywords.getTypeCode();
268 if ( typeCode != null ) {
269 Element node = XMLTools.appendElement( xmlNode, OWSNS, "ows:Type", typeCode.getCode() );
270 if ( typeCode.getCodeSpace() != null ) {
271 node.setAttribute( "codeSpace", typeCode.getCodeSpace().toString() );
272 }
273 }
274 }
275 }
276
277 /**
278 * Appends the DOM representation of the <code>ServiceProvider</code>- section to the passed <code>Element</code>.
279 *
280 * @param root
281 * @param serviceProvider
282 */
283 protected static void appendServiceProvider( Element root, ServiceProvider serviceProvider ) {
284
285 // 'ServiceProvider'-element
286 Element serviceProviderNode = XMLTools.appendElement( root, OWSNS, "ows:ServiceProvider" );
287
288 // 'ProviderName'-element
289 XMLTools.appendElement( serviceProviderNode, OWSNS, "ows:ProviderName", serviceProvider.getProviderName() );
290
291 // 'ProviderSite'-element
292 if ( serviceProvider.getProviderSite() != null ) {
293 Element providerSiteNode = XMLTools.appendElement( serviceProviderNode, OWSNS, "ows:ProviderSite" );
294 appendSimpleLinkAttributes( providerSiteNode, serviceProvider.getProviderSite() );
295 }
296
297 // 'ServiceContact'-element
298 Element serviceContactNode = XMLTools.appendElement( serviceProviderNode, OWSNS, "ows:ServiceContact" );
299
300 // 'IndividualName'-element
301 XMLTools.appendElement( serviceContactNode, OWSNS, "ows:IndividualName", serviceProvider.getIndividualName() );
302
303 // 'PositionName'-element
304 if ( serviceProvider.getPositionName() != null ) {
305 XMLTools.appendElement( serviceContactNode, OWSNS, "ows:PositionName", serviceProvider.getPositionName() );
306 }
307
308 // 'ContactInfo'-element
309 ContactInfo contactInfo = serviceProvider.getContactInfo();
310 if ( contactInfo != null ) {
311 Element contactInfoNode = XMLTools.appendElement( serviceContactNode, OWSNS, "ows:ContactInfo" );
312 Phone phone = contactInfo.getPhone();
313 if ( phone != null ) {
314 appendPhone( contactInfoNode, phone );
315 }
316 Address address = contactInfo.getAddress();
317 if ( address != null ) {
318 appendAddress( contactInfoNode, address );
319 }
320 OnlineResource onlineResource = contactInfo.getOnLineResource();
321 if ( onlineResource != null ) {
322 appendOnlineResource( contactInfoNode, "ows:OnlineResource", onlineResource, OWSNS );
323 }
324 String hoursOfService = contactInfo.getHoursOfService();
325 if ( hoursOfService != null ) {
326 XMLTools.appendElement( contactInfoNode, OWSNS, "ows:HoursOfService", hoursOfService );
327 }
328 String contactInstructions = contactInfo.getContactInstructions();
329 if ( contactInstructions != null ) {
330 XMLTools.appendElement( contactInfoNode, OWSNS, "ows:ContactInstructions", contactInstructions );
331 }
332 }
333 TypeCode role = serviceProvider.getRole();
334 if ( role != null ) {
335 Element roleElement = XMLTools.appendElement( serviceContactNode, OWSNS, "ows:Role", role.getCode() );
336 if ( role.getCodeSpace() != null ) {
337 roleElement.setAttribute( "codeSpace", role.getCodeSpace().toString() );
338 }
339 }
340 }
341
342 /**
343 * Appends the DOM representation of the <code>Phone</code> -section to the passed <code>Element</code>.
344 *
345 * @param root
346 * @param phone
347 */
348 protected static void appendPhone( Element root, Phone phone ) {
349
350 // 'Phone'-element
351 Element phoneNode = XMLTools.appendElement( root, OWSNS, "ows:Phone" );
352
353 // 'Voice'-elements
354 String[] voiceNumbers = phone.getVoice();
355 for ( int i = 0; i < voiceNumbers.length; i++ ) {
356 XMLTools.appendElement( phoneNode, OWSNS, "ows:Voice", voiceNumbers[i] );
357 }
358
359 // 'Facsimile'-elements
360 String[] facsimileNumbers = phone.getFacsimile();
361 for ( int i = 0; i < facsimileNumbers.length; i++ ) {
362 XMLTools.appendElement( phoneNode, OWSNS, "ows:Facsimile", facsimileNumbers[i] );
363 }
364 }
365
366 /**
367 * Appends the DOM representation of the <code>Address</code> -section to the passed <code>Element</code>.
368 *
369 * @param root
370 * @param address
371 */
372 protected static void appendAddress( Element root, Address address ) {
373
374 // 'Address'-element
375 Element addressNode = XMLTools.appendElement( root, OWSNS, "ows:Address" );
376
377 // 'DeliveryPoint'-elements
378 String[] deliveryPoints = address.getDeliveryPoint();
379 for ( int i = 0; i < deliveryPoints.length; i++ ) {
380 XMLTools.appendElement( addressNode, OWSNS, "ows:DeliveryPoint", deliveryPoints[i] );
381 }
382
383 // 'City'-element
384 if ( address.getCity() != null ) {
385 XMLTools.appendElement( addressNode, OWSNS, "ows:City", address.getCity() );
386 }
387
388 // 'AdministrativeArea'-element
389 if ( address.getAdministrativeArea() != null ) {
390 XMLTools.appendElement( addressNode, OWSNS, "ows:AdministrativeArea", address.getAdministrativeArea() );
391 }
392
393 // 'PostalCode'-element
394 if ( address.getPostalCode() != null ) {
395 XMLTools.appendElement( addressNode, OWSNS, "ows:PostalCode", address.getPostalCode() );
396 }
397
398 // 'Country'-element
399 if ( address.getCountry() != null ) {
400 XMLTools.appendElement( addressNode, OWSNS, "ows:Country", address.getCountry() );
401 }
402
403 // 'ElectronicMailAddress'-elements
404 String[] electronicMailAddresses = address.getElectronicMailAddress();
405 if ( address.getElectronicMailAddress() != null ) {
406 for ( int i = 0; i < electronicMailAddresses.length; i++ ) {
407 XMLTools.appendElement( addressNode, OWSNS, "ows:ElectronicMailAddress", electronicMailAddresses[i] );
408 }
409 }
410 }
411
412 /**
413 * Appends the DOM representation of the <code>OperationsMetadata</code>- section to the passed <code>Element</code>
414 * .
415 *
416 * @param root
417 */
418 protected static void appendOperationsMetadata( Element root, OperationsMetadata operationsMetadata ) {
419
420 // 'ows:OperationsMetadata'-element
421 Element operationsMetadataNode = XMLTools.appendElement( root, OWSNS, "ows:OperationsMetadata" );
422
423 // append all Operations
424 Operation[] operations = operationsMetadata.getOperations();
425 for ( int i = 0; i < operations.length; i++ ) {
426 Operation operation = operations[i];
427
428 // 'ows:Operation'-element
429 Element operationElement = XMLTools.appendElement( operationsMetadataNode, OWSNS, "ows:Operation" );
430 operationElement.setAttribute( "name", operation.getName() );
431
432 // 'ows:DCP'-elements
433 DCPType[] dcps = operation.getDCPs();
434 for ( int j = 0; j < dcps.length; j++ ) {
435 appendDCP( operationElement, dcps[j] );
436 }
437
438 // 'ows:Parameter'-elements
439 OWSDomainType[] parameters = operation.getParameters();
440 for ( int j = 0; j < parameters.length; j++ ) {
441 appendParameter( operationElement, parameters[j], "ows:Parameter" );
442 }
443
444 // 'ows:Metadata'-elements
445 Object[] metadata = operation.getMetadata();
446 if ( metadata != null ) {
447 for ( int j = 0; j < metadata.length; j++ ) {
448 appendMetadata( operationElement, metadata[j] );
449 }
450 }
451 }
452
453 // append general parameters
454 OWSDomainType[] parameters = operationsMetadata.getParameter();
455 for ( int i = 0; i < parameters.length; i++ ) {
456 appendParameter( operationsMetadataNode, parameters[i], "ows:Parameter" );
457 }
458
459 // append constraints
460 OWSDomainType[] constraints = operationsMetadata.getConstraints();
461 for ( int i = 0; i < constraints.length; i++ ) {
462 appendParameter( operationsMetadataNode, constraints[i], "ows:Constraint" );
463 }
464 }
465
466 /**
467 * Appends the DOM representation of a <code>DCPType</code> instance to the passed <code>Element</code>.
468 *
469 * @param root
470 * @param dcp
471 */
472 protected static void appendDCP( Element root, DCPType dcp ) {
473
474 // 'ows:DCP'-element
475 Element dcpNode = XMLTools.appendElement( root, OWSNS, "ows:DCP" );
476
477 // currently, the only supported DCP is HTTP!
478 if ( dcp.getProtocol() instanceof HTTP ) {
479 HTTP http = (HTTP) dcp.getProtocol();
480
481 // 'ows:HTTP'-element
482 Element httpNode = XMLTools.appendElement( dcpNode, OWSNS, "ows:HTTP" );
483
484 // 'ows:Get'-elements
485 URL[] getURLs = http.getGetOnlineResources();
486 for ( int i = 0; i < getURLs.length; i++ ) {
487 appendOnlineResource( httpNode, "ows:Get", new OnlineResource( new Linkage( getURLs[i] ) ), OWSNS );
488 }
489
490 // 'ows:Post'-elements
491 URL[] postURLs = http.getPostOnlineResources();
492 for ( int i = 0; i < postURLs.length; i++ ) {
493 appendOnlineResource( httpNode, "ows:Post", 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 <code>Element</code>.
500 *
501 * @param root
502 * @param parameter
503 */
504 protected static void appendParameter( Element root, OWSDomainType parameter, String elementName ) {
505
506 // 'ows:Parameter'-element
507 Element parameterNode = XMLTools.appendElement( root, OWSNS, elementName );
508 parameterNode.setAttribute( "name", parameter.getName() );
509
510 // 'ows:Value'-elements
511 String[] values = parameter.getValues();
512 for ( int i = 0; i < values.length; i++ ) {
513 XMLTools.appendElement( parameterNode, OWSNS, "ows:Value", values[i] );
514 }
515 }
516
517 /**
518 * Appends the DOM representation of a <code>Metadata</code> instance to the passed <code>Element</code>.
519 *
520 * @param root
521 * @param metadata
522 */
523 protected static void appendMetadata( Element root, Object metadata ) {
524
525 // TODO
526
527 }
528
529 /**
530 * @param exc
531 * @return the exported new document
532 */
533 public static XMLFragment exportExceptionReportWFS( OGCWebServiceException exc ) {
534 XMLFragment doc = new XMLFragment( new QualifiedName( "ows", "ExceptionReport", OWSNS ) );
535 Element root = doc.getRootElement();
536 root.setAttribute( "version", "1.1.0" );
537
538 Element e = appendElement( root, OWSNS, "ows:Exception" );
539 if ( exc.getCode() != null ) {
540 e.setAttribute( "exceptionCode", exc.getCode().value );
541 } else {
542 e.setAttribute( "exceptionCode", NOAPPLICABLECODE.value );
543 }
544
545 String locator = exc.getLocator();
546 try {
547 if ( locator != null ) {
548 locator = encode( locator, getSystemCharset() );
549 } else {
550 locator = "unknown";
551 }
552 } catch ( UnsupportedEncodingException _ ) {
553 // if caught why not do something -> setting locator to "unknown"
554 locator = "unknown";
555 }
556 e.setAttribute( "locator", locator );
557
558 appendElement( e, OWSNS, "ows:ExceptionText", exc.getMessage() );
559
560 return doc;
561 }
562
563 /**
564 * @param exc
565 * @return the exported exception
566 */
567 public static XMLFragment exportExceptionReportWFS100( OGCWebServiceException exc ) {
568 XMLFragment doc = new XMLFragment( new QualifiedName( "ogc", "ServiceExceptionReport", OGCNS ) );
569 Element root = doc.getRootElement();
570 root.setAttribute( "version", "1.2.0" );
571
572 Element e = appendElement( root, OGCNS, "ogc:ServiceException", exc.getMessage() );
573 e.setAttribute( "code", exc.getCode() == null ? NOAPPLICABLECODE.value : exc.getCode().value );
574
575 String locator = exc.getLocator();
576 try {
577 if ( locator != null ) {
578 locator = encode( locator, getSystemCharset() );
579 } else {
580 locator = "unknown";
581 }
582 } catch ( UnsupportedEncodingException _ ) {
583 // if caught why not do something -> setting locator to "unknown"
584 locator = "unknown";
585 }
586 e.setAttribute( "locator", locator );
587
588 return doc;
589 }
590
591 /**
592 * @param elem
593 * @param name
594 * @param value
595 */
596 public static void maybeSetAttribute( Element elem, String name, String value ) {
597 if ( value != null ) {
598 elem.setAttribute( name, value );
599 }
600 }
601
602 }