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 }