001 // $HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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 }