001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wfs/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 package org.deegree.ogcwebservices.wfs; 044 045 import java.io.IOException; 046 import java.io.StringReader; 047 import java.net.URI; 048 import java.util.Collection; 049 import java.util.Iterator; 050 import java.util.List; 051 import java.util.Map; 052 053 import org.deegree.datatypes.QualifiedName; 054 import org.deegree.framework.log.ILogger; 055 import org.deegree.framework.log.LoggerFactory; 056 import org.deegree.framework.util.StringTools; 057 import org.deegree.framework.xml.XMLException; 058 import org.deegree.framework.xml.XMLParsingException; 059 import org.deegree.framework.xml.XMLTools; 060 import org.deegree.io.datastore.FeatureId; 061 import org.deegree.model.feature.Feature; 062 import org.deegree.model.feature.FeatureException; 063 import org.deegree.model.feature.FeatureProperty; 064 import org.deegree.model.feature.GMLFeatureAdapter; 065 import org.deegree.model.filterencoding.Filter; 066 import org.deegree.model.filterencoding.Function; 067 import org.deegree.model.filterencoding.capabilities.FilterCapabilities; 068 import org.deegree.model.metadata.iso19115.Keywords; 069 import org.deegree.model.spatialschema.Envelope; 070 import org.deegree.model.spatialschema.Geometry; 071 import org.deegree.model.spatialschema.GeometryException; 072 import org.deegree.ogcbase.CommonNamespaces; 073 import org.deegree.ogcbase.PropertyPath; 074 import org.deegree.ogcbase.SortProperty; 075 import org.deegree.ogcwebservices.getcapabilities.Contents; 076 import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata; 077 import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification; 078 import org.deegree.ogcwebservices.getcapabilities.ServiceProvider; 079 import org.deegree.ogcwebservices.wfs.capabilities.FeatureTypeList; 080 import org.deegree.ogcwebservices.wfs.capabilities.FormatType; 081 import org.deegree.ogcwebservices.wfs.capabilities.GMLObject; 082 import org.deegree.ogcwebservices.wfs.capabilities.Operation; 083 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 084 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument; 085 import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType; 086 import org.deegree.ogcwebservices.wfs.operation.GetFeature; 087 import org.deegree.ogcwebservices.wfs.operation.GetFeatureDocument; 088 import org.deegree.ogcwebservices.wfs.operation.Lock; 089 import org.deegree.ogcwebservices.wfs.operation.LockFeature; 090 import org.deegree.ogcwebservices.wfs.operation.LockFeatureDocument; 091 import org.deegree.ogcwebservices.wfs.operation.LockFeatureResponse; 092 import org.deegree.ogcwebservices.wfs.operation.LockFeatureResponseDocument; 093 import org.deegree.ogcwebservices.wfs.operation.Query; 094 import org.deegree.ogcwebservices.wfs.operation.GetFeature.RESULT_TYPE; 095 import org.deegree.ogcwebservices.wfs.operation.transaction.Delete; 096 import org.deegree.ogcwebservices.wfs.operation.transaction.Insert; 097 import org.deegree.ogcwebservices.wfs.operation.transaction.InsertResults; 098 import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction; 099 import org.deegree.ogcwebservices.wfs.operation.transaction.TransactionDocument; 100 import org.deegree.ogcwebservices.wfs.operation.transaction.TransactionResponse; 101 import org.deegree.ogcwebservices.wfs.operation.transaction.TransactionResponseDocument; 102 import org.deegree.ogcwebservices.wfs.operation.transaction.Update; 103 import org.w3c.dom.Document; 104 import org.w3c.dom.Element; 105 import org.xml.sax.SAXException; 106 107 /** 108 * Responsible for the generation of XML representations of objects from the WFS context. 109 * 110 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a> 111 * @author last edited by: $Author: apoth $ 112 * 113 * @version $Revision: 9348 $, $Date: 2007-12-27 17:59:14 +0100 (Do, 27 Dez 2007) $ 114 */ 115 public class XMLFactory extends org.deegree.owscommon.XMLFactory { 116 117 private static final URI WFS = CommonNamespaces.WFSNS; 118 119 private static final URI OGCNS = CommonNamespaces.OGCNS; 120 121 private static final String PRE_WFS = CommonNamespaces.WFS_PREFIX + ":"; 122 123 private static final URI DEEGREEWFS = CommonNamespaces.DEEGREEWFS; 124 125 private static final ILogger LOG = LoggerFactory.getLogger( XMLFactory.class ); 126 127 /** 128 * Exports a <code>WFSCapabilities</code> instance to a <code>WFSCapabilitiesDocument</code>. 129 * 130 * @param capabilities 131 * @return DOM representation of the <code>WFSCapabilities</code> 132 * @throws IOException 133 * if XML template could not be loaded 134 */ 135 public static WFSCapabilitiesDocument export( WFSCapabilities capabilities ) 136 throws IOException { 137 138 WFSCapabilitiesDocument capabilitiesDocument = new WFSCapabilitiesDocument(); 139 140 try { 141 capabilitiesDocument.createEmptyDocument(); 142 Element root = capabilitiesDocument.getRootElement(); 143 144 ServiceIdentification serviceIdentification = capabilities.getServiceIdentification(); 145 if ( serviceIdentification != null ) { 146 appendServiceIdentification( root, serviceIdentification ); 147 } 148 149 ServiceProvider serviceProvider = capabilities.getServiceProvider(); 150 if ( serviceProvider != null ) { 151 appendServiceProvider( root, capabilities.getServiceProvider() ); 152 } 153 154 OperationsMetadata operationsMetadata = capabilities.getOperationsMetadata(); 155 if ( operationsMetadata != null ) { 156 appendOperationsMetadata( root, operationsMetadata ); 157 } 158 FeatureTypeList featureTypeList = capabilities.getFeatureTypeList(); 159 if ( featureTypeList != null ) { 160 appendFeatureTypeList( root, featureTypeList ); 161 } 162 GMLObject[] servesGMLObjectTypes = capabilities.getServesGMLObjectTypeList(); 163 if ( servesGMLObjectTypes != null ) { 164 appendGMLObjectTypeList( root, WFS, PRE_WFS + "ServesGMLObjectTypeList", servesGMLObjectTypes ); 165 } 166 GMLObject[] supportsGMLObjectTypes = capabilities.getSupportsGMLObjectTypeList(); 167 if ( supportsGMLObjectTypes != null ) { 168 appendGMLObjectTypeList( root, WFS, PRE_WFS + "SupportsGMLObjectTypeList", supportsGMLObjectTypes ); 169 } 170 Contents contents = capabilities.getContents(); 171 if ( contents != null ) { 172 // appendContents(root, contents); 173 } 174 175 FilterCapabilities filterCapabilities = capabilities.getFilterCapabilities(); 176 if ( filterCapabilities != null ) { 177 org.deegree.model.filterencoding.XMLFactory.appendFilterCapabilities110( root, filterCapabilities ); 178 } 179 } catch ( SAXException e ) { 180 LOG.logError( e.getMessage(), e ); 181 } 182 return capabilitiesDocument; 183 } 184 185 /** 186 * Exports a <code>WFSCapabilities</code> instance to a <code>WFSCapabilitiesDocument</code>. 187 * 188 * @param capabilities 189 * @param sections 190 * names of sections to be exported, may contain 'All' 191 * @return DOM representation of the <code>WFSCapabilities</code> 192 * @throws IOException 193 * if XML template could not be loaded 194 */ 195 public static WFSCapabilitiesDocument export( WFSCapabilities capabilities, String[] sections ) 196 throws IOException { 197 198 // TODO only export requested sections 199 return export( capabilities ); 200 } 201 202 /** 203 * Appends the DOM representation of the {@link ServiceIdentification} section to the passed 204 * {@link Element}. 205 * 206 * @param root 207 * @param serviceIdentification 208 */ 209 protected static void appendServiceIdentification( Element root, ServiceIdentification serviceIdentification ) { 210 211 // 'ServiceIdentification'-element 212 Element serviceIdentificationNode = XMLTools.appendElement( root, OWSNS, "ows:ServiceIdentification" ); 213 214 // the optional title element 215 String tmp = serviceIdentification.getTitle(); 216 if ( tmp != null && !"".equals( tmp ) ) { 217 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Title", tmp ); 218 } 219 220 // the optional abstract element 221 tmp = serviceIdentification.getAbstract(); 222 if ( tmp != null && !"".equals( tmp ) ) { 223 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Abstract", tmp ); 224 } 225 226 // the optional keywords element 227 appendKeywords( serviceIdentificationNode, serviceIdentification.getKeywords(), OWSNS ); 228 229 // 'ServiceType'-element 230 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceType", 231 serviceIdentification.getServiceType().getCode() ); 232 233 // 'ServiceTypeVersion'-elements 234 String[] versions = serviceIdentification.getServiceTypeVersions(); 235 for ( int i = 0; i < versions.length; i++ ) { 236 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceTypeVersion", versions[i] ); 237 } 238 239 // 'Fees'-element 240 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Fees", serviceIdentification.getFees() ); 241 242 // 'AccessConstraints'-element 243 String[] constraints = serviceIdentification.getAccessConstraints(); 244 if ( constraints != null ) { 245 for ( int i = 0; i < constraints.length; i++ ) { 246 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:AccessConstraints", constraints[i] ); 247 } 248 } 249 } 250 251 /** 252 * Appends a <code>ows:Keywords</code> -element for each <code>Keywords</code> object of the 253 * passed array to the passed <code>Element</code>. 254 * 255 * @param xmlNode 256 * @param keywords 257 * @param namespaceURI 258 */ 259 protected static void appendKeywords( Element xmlNode, Keywords[] keywords, URI namespaceURI ) { 260 if ( keywords != null ) { 261 for ( int i = 0; i < keywords.length; i++ ) { 262 Element node = XMLTools.appendElement( xmlNode, namespaceURI, "ows:Keywords" ); 263 appendKeywords( node, keywords[i], namespaceURI ); 264 } 265 } 266 } 267 268 /** 269 * Appends a <code>Keyword</code> -element to the passed <code>Element</code> and fills it 270 * with the available keywords. 271 * 272 * @param xmlNode 273 * @param keywords 274 * @param namespaceURI 275 */ 276 protected static void appendKeywords( Element xmlNode, Keywords keywords, URI namespaceURI ) { 277 if ( keywords != null ) { 278 String[] kw = keywords.getKeywords(); 279 for ( int i = 0; i < kw.length; i++ ) { 280 XMLTools.appendElement( xmlNode, namespaceURI, "ows:Keyword", kw[i] ); 281 } 282 if ( keywords.getThesaurusName() != null ) { 283 XMLTools.appendElement( xmlNode, namespaceURI, "ows:Type", keywords.getThesaurusName() ); 284 } 285 } 286 } 287 288 /** 289 * Exports a <code>GetFeature</code> instance to a <code>GetFeatureDocument</code>. 290 * 291 * @param getFeature 292 * request to be exported 293 * @return XML representation of the <code>GetFeature</code> request 294 * @throws IOException 295 * @throws XMLParsingException 296 */ 297 public static GetFeatureDocument export( GetFeature getFeature ) 298 throws IOException, XMLParsingException { 299 300 GetFeatureDocument xml = new GetFeatureDocument(); 301 try { 302 xml.load( XMLFactory.class.getResource( "GetFeatureTemplate.xml" ) ); 303 } catch ( SAXException e ) { 304 throw new XMLParsingException( "could not parse GetFeatureTemplate.xml", e ); 305 } 306 Element root = xml.getRootElement(); 307 root.setAttribute( "outputFormat", getFeature.getOutputFormat() ); 308 root.setAttribute( "service", "WFS" ); 309 root.setAttribute( "version", getFeature.getVersion() ); 310 if ( getFeature.getHandle() != null ) { 311 root.setAttribute( "handle", getFeature.getHandle() ); 312 } 313 if ( getFeature.getResultType() == RESULT_TYPE.HITS ) { 314 root.setAttribute( "resultType", "hits" ); 315 } else { 316 root.setAttribute( "resultType", "results" ); 317 } 318 root.setAttribute( "maxFeatures", "" + getFeature.getMaxFeatures() ); 319 if ( getFeature.getStartPosition() > 0 ) { 320 root.setAttribute( "startPosition", "" + getFeature.getStartPosition() ); 321 } 322 if ( getFeature.getTraverseXLinkDepth() > 0 ) { 323 root.setAttribute( "traverseXLinkDepth", "" + getFeature.getTraverseXLinkDepth() ); 324 } 325 if ( getFeature.getTraverseXLinkExpiry() > 0 ) { 326 root.setAttribute( "traverseXLinkExpiry", "" + getFeature.getTraverseXLinkExpiry() ); 327 } 328 Query[] queries = getFeature.getQuery(); 329 for ( int i = 0; i < queries.length; i++ ) { 330 appendQuery( root, queries[i] ); 331 } 332 return xml; 333 } 334 335 /** 336 * Exports a {@link LockFeature} request instance to a {@link LockFeatureDocument}. 337 * 338 * @param request 339 * request to be exported 340 * @return XML representation of the <code>LockFeature</code> request 341 * @throws IOException 342 * @throws XMLParsingException 343 * @throws SAXException 344 */ 345 public static LockFeatureDocument export( LockFeature request ) 346 throws IOException, XMLParsingException, SAXException { 347 348 LockFeatureDocument doc = new LockFeatureDocument(); 349 doc.createEmptyDocument(); 350 351 Element root = doc.getRootElement(); 352 root.setAttribute( "version", request.getVersion() ); 353 root.setAttribute( "service", "WFS" ); 354 if ( request.getHandle() != null ) { 355 root.setAttribute( "handle", request.getHandle() ); 356 } 357 root.setAttribute( "expiry", "" + request.getExpiry() ); 358 root.setAttribute( "lockAction", "" + request.getLockAction() ); 359 360 List<Lock> locks = request.getLocks(); 361 for ( Lock lock : locks ) { 362 appendLock( root, lock ); 363 } 364 return doc; 365 } 366 367 /** 368 * Appends the XML representation of the given {@link Lock} to the given element. 369 * 370 * @param root 371 * @param lock 372 */ 373 private static void appendLock( Element root, Lock lock ) 374 throws IOException, XMLParsingException { 375 376 Element lockElement = XMLTools.appendElement( root, WFS, PRE_WFS + "Lock" ); 377 if ( lock.getHandle() != null ) { 378 lockElement.setAttribute( "handle", lock.getHandle() ); 379 } 380 QualifiedName typeName = lock.getTypeName(); 381 if ( typeName.getPrefix() != null ) { 382 lockElement.setAttribute( "xmlns:" + typeName.getPrefix(), typeName.getNamespace().toASCIIString() ); 383 } 384 lockElement.setAttribute( "typeName", typeName.getPrefixedName() ); 385 386 // copy filter into Lock element 387 if ( lock.getFilter() != null ) { 388 StringReader sr = new StringReader( lock.getFilter().toXML().toString() ); 389 Document doc; 390 try { 391 doc = XMLTools.parse( sr ); 392 } catch ( SAXException e ) { 393 throw new XMLParsingException( "Could not parse filter.", e ); 394 } 395 Element elem = XMLTools.appendElement( lockElement, OGCNS, "ogc:Filter" ); 396 XMLTools.copyNode( doc.getDocumentElement(), elem ); 397 } 398 } 399 400 /** 401 * Exports a {@link LockFeatureResponse} instance to its XML representation. 402 * 403 * @param response 404 * response to be exported 405 * @return XML representation of the <code>LockFeatureResponse</code> 406 * @throws IOException 407 * @throws SAXException 408 */ 409 public static LockFeatureResponseDocument export( LockFeatureResponse response ) 410 throws IOException, SAXException { 411 412 LockFeatureResponseDocument doc = new LockFeatureResponseDocument(); 413 doc.createEmptyDocument(); 414 415 Element root = doc.getRootElement(); 416 XMLTools.appendElement( root, WFS, PRE_WFS + "LockId", response.getLockId() ); 417 String[] fids = response.getFeaturesLocked(); 418 if ( fids.length != 0 ) { 419 Element featuresLockedElement = XMLTools.appendElement( root, WFS, PRE_WFS + "FeaturesLocked" ); 420 for ( String fid : fids ) { 421 appendFeatureId( featuresLockedElement, fid ); 422 } 423 } 424 fids = response.getFeaturesNotLocked(); 425 if ( fids.length != 0 ) { 426 Element featuresNotLockedElement = XMLTools.appendElement( root, WFS, PRE_WFS + "FeaturesNotLocked" ); 427 for ( String fid : fids ) { 428 appendFeatureId( featuresNotLockedElement, fid ); 429 } 430 } 431 return doc; 432 } 433 434 /** 435 * Exports a {@link Transaction} instance to its XML representation. 436 * 437 * @param transaction 438 * transaction to export 439 * @return XML representation of transaction 440 * @throws IOException 441 * @throws XMLParsingException 442 */ 443 public static TransactionDocument export( Transaction transaction ) 444 throws IOException, XMLParsingException { 445 446 TransactionDocument xml = new TransactionDocument(); 447 try { 448 xml.createEmptyDocument(); 449 } catch ( SAXException e ) { 450 throw new IOException( e.getMessage() ); 451 } 452 Element root = xml.getRootElement(); 453 List ops = transaction.getOperations(); 454 for ( int i = 0; i < ops.size(); i++ ) { 455 try { 456 if ( ops.get( i ) instanceof Insert ) { 457 appendInsert( root, (Insert) ops.get( i ) ); 458 } else if ( ops.get( i ) instanceof Update ) { 459 appendUpdate( root, (Update) ops.get( i ) ); 460 } else if ( ops.get( i ) instanceof Delete ) { 461 appendDelete( root, (Delete) ops.get( i ) ); 462 } 463 } catch ( Exception e ) { 464 LOG.logError( e.getMessage(), e ); 465 throw new XMLParsingException( e.getMessage() ); 466 } 467 } 468 return xml; 469 } 470 471 /** 472 * Adds the XML representation of a <code>Delete</code> operation to the given element. 473 * 474 * @param root 475 * @param delete 476 */ 477 private static void appendDelete( Element root, Delete delete ) { 478 Element el = XMLTools.appendElement( root, WFS, "Delete" ); 479 if ( delete.getHandle() != null ) { 480 el.setAttribute( "handle", delete.getHandle() ); 481 } 482 // TODO What about the namespace binding here? 483 el.setAttribute( "typeName", delete.getTypeName().getPrefixedName() ); 484 485 Filter filter = delete.getFilter(); 486 if ( filter != null ) { 487 org.deegree.model.filterencoding.XMLFactory.appendFilter( el, filter ); 488 } 489 root.appendChild( el ); 490 } 491 492 /** 493 * Adds the XML representation of an <code>Update</code> operation to the given element. 494 * <p> 495 * Respects the deegree-specific extension to the Update operation: instead of specifying 496 * properties and their values, it's also possible to only specify just one feature that 497 * replaces the matched feature. 498 * 499 * @param root 500 * @param update 501 * @throws SAXException 502 * @throws IOException 503 * @throws FeatureException 504 * @throws GeometryException 505 */ 506 private static void appendUpdate( Element root, Update update ) 507 throws FeatureException, IOException, SAXException, GeometryException { 508 509 Element el = XMLTools.appendElement( root, WFS, "Update" ); 510 if ( update.getHandle() != null ) { 511 el.setAttribute( "handle", update.getHandle() ); 512 } 513 // TODO What about the namespace binding here? 514 el.setAttribute( "typeName", update.getTypeName().getPrefixedName() ); 515 516 Feature replacement = update.getFeature(); 517 if ( replacement != null ) { 518 GMLFeatureAdapter adapter = new GMLFeatureAdapter(); 519 adapter.append( root, replacement ); 520 } else { 521 Map<PropertyPath, FeatureProperty> replaces = update.getReplacementProperties(); 522 for ( PropertyPath propertyName : replaces.keySet() ) { 523 Element propElement = XMLTools.appendElement( el, WFS, "Property" ); 524 Element nameElement = XMLTools.appendElement( propElement, WFS, "Name" ); 525 org.deegree.ogcbase.XMLFactory.appendPropertyPath( nameElement, propertyName ); 526 527 // append property value 528 Object propValue = replaces.get( propertyName ).getValue(); 529 if ( propValue != null ) { 530 Element valueElement = XMLTools.appendElement( propElement, WFS, "Value" ); 531 if ( propValue instanceof Feature ) { 532 GMLFeatureAdapter adapter = new GMLFeatureAdapter(); 533 adapter.append( valueElement, (Feature) propValue ); 534 } else if ( propValue instanceof Geometry ) { 535 appendGeometry( valueElement, (Geometry) propValue ); 536 } else { 537 XMLTools.setNodeValue( valueElement, propValue.toString() ); 538 } 539 } 540 } 541 } 542 543 Filter filter = update.getFilter(); 544 if ( filter != null ) { 545 org.deegree.model.filterencoding.XMLFactory.appendFilter( el, filter ); 546 } 547 root.appendChild( el ); 548 } 549 550 /** 551 * Adds the XML representation of an <code>Insert</code> operation to the given element. 552 * 553 * @param root 554 * @param insert 555 * @throws SAXException 556 * @throws IOException 557 * @throws FeatureException 558 */ 559 private static void appendInsert( Element root, Insert insert ) 560 throws IOException, FeatureException, XMLException, SAXException { 561 562 Element el = XMLTools.appendElement( root, WFS, "Insert" ); 563 if ( insert.getHandle() != null ) { 564 el.setAttribute( "handle", insert.getHandle() ); 565 } 566 if ( insert.getIdGen() != null ) { 567 el.setAttribute( "idgen", insert.getIdGen().name() ); 568 } 569 570 GMLFeatureAdapter adapter = new GMLFeatureAdapter(); 571 adapter.append( el, insert.getFeatures() ); 572 } 573 574 /** 575 * Exports an instance of {@link TransactionResponse} to its XML representation. 576 * 577 * @param response 578 * TransactionResponse to export 579 * @return XML representation of TransactionResponse 580 * @throws IOException 581 */ 582 public static TransactionResponseDocument export( TransactionResponse response ) 583 throws IOException { 584 585 TransactionResponseDocument xml = new TransactionResponseDocument(); 586 try { 587 xml.createEmptyDocument(); 588 } catch ( SAXException e ) { 589 throw new IOException( e.getMessage() ); 590 } 591 592 Element root = xml.getRootElement(); 593 appendTransactionSummary( root, response.getTotalInserted(), response.getTotalUpdated(), 594 response.getTotalDeleted() ); 595 appendInsertResults( root, response.getInsertResults() ); 596 return xml; 597 } 598 599 /** 600 * Appends a 'wfs:TransactionSummary' element to the given element. 601 * 602 * @param root 603 * @param totalInserted 604 * @param totalUpdated 605 * @param totalDeleted 606 */ 607 private static void appendTransactionSummary( Element root, int totalInserted, int totalUpdated, int totalDeleted ) { 608 Element taSummary = XMLTools.appendElement( root, WFS, PRE_WFS + "TransactionSummary" ); 609 XMLTools.appendElement( taSummary, WFS, PRE_WFS + "totalInserted", "" + totalInserted ); 610 XMLTools.appendElement( taSummary, WFS, PRE_WFS + "totalUpdated", "" + totalUpdated ); 611 XMLTools.appendElement( taSummary, WFS, PRE_WFS + "totalDeleted", "" + totalDeleted ); 612 } 613 614 /** 615 * Appends an 'wfs:InsertResults' element to the given element (only if necessary). 616 * 617 * @param root 618 * @param insertResults 619 */ 620 private static void appendInsertResults( Element root, Collection<InsertResults> insertResults ) { 621 if ( insertResults.size() > 0 ) { 622 Element insertResultsElement = XMLTools.appendElement( root, WFS, PRE_WFS + "InsertResults" ); 623 Iterator<InsertResults> iter = insertResults.iterator(); 624 while ( iter.hasNext() ) { 625 appendFeatureIds( insertResultsElement, iter.next() ); 626 } 627 } 628 } 629 630 /** 631 * Appends a 'wfs:Feature' element to the given element. 632 * 633 * @param root 634 * @param results 635 */ 636 private static void appendFeatureIds( Element root, InsertResults results ) { 637 Element featureElement = XMLTools.appendElement( root, WFS, PRE_WFS + "Feature" ); 638 String handle = results.getHandle(); 639 if ( handle != null ) { 640 featureElement.setAttribute( "handle", handle ); 641 } 642 Iterator<FeatureId> iter = results.getFeatureIDs().iterator(); 643 while ( iter.hasNext() ) { 644 Element featureIdElement = XMLTools.appendElement( featureElement, OGCNS, "ogc:FeatureId" ); 645 featureIdElement.setAttribute( "fid", iter.next().getAsString() ); 646 } 647 } 648 649 /** 650 * Appends the XML representation of the given {@link Query} instance to an element. 651 * 652 * @param query 653 */ 654 private static void appendQuery( Element root, Query query ) 655 throws IOException, XMLParsingException { 656 657 Element queryElem = XMLTools.appendElement( root, WFS, PRE_WFS + "Query" ); 658 if ( query.getHandle() != null ) { 659 queryElem.setAttribute( "handle", query.getHandle() ); 660 } 661 if ( query.getFeatureVersion() != null ) { 662 queryElem.setAttribute( "featureVersion", query.getFeatureVersion() ); 663 } 664 QualifiedName[] qn = query.getTypeNames(); 665 String[] na = new String[qn.length]; 666 for ( int i = 0; i < na.length; i++ ) { 667 na[i] = qn[i].getPrefixedName(); 668 queryElem.setAttribute( "xmlns:" + qn[i].getPrefix(), qn[i].getNamespace().toASCIIString() ); 669 } 670 String tn = StringTools.arrayToString( na, ',' ); 671 queryElem.setAttribute( "typeName", tn ); 672 673 if ( query.getSrsName() != null ) { 674 queryElem.setAttribute( "srsName", query.getSrsName() ); 675 } 676 677 String[] aliases = query.getAliases(); 678 if ( aliases != null && aliases.length != 0 ) { 679 StringBuffer aliasesList = new StringBuffer( aliases[0] ); 680 for ( int i = 1; i < aliases.length; i++ ) { 681 aliasesList.append( ' ' ); 682 aliasesList.append( aliases[i] ); 683 } 684 queryElem.setAttribute( "aliases", aliasesList.toString() ); 685 } 686 687 PropertyPath[] propertyNames = query.getPropertyNames(); 688 for ( int i = 0; i < propertyNames.length; i++ ) { 689 Element propertyNameElement = XMLTools.appendElement( queryElem, WFS, PRE_WFS + "PropertyName" ); 690 appendPropertyPath( propertyNameElement, propertyNames[i] ); 691 } 692 Function[] fn = query.getFunctions(); 693 // copy function definitions into query node 694 if ( fn != null ) { 695 for ( int i = 0; i < fn.length; i++ ) { 696 StringReader sr = new StringReader( fn[i].toXML().toString() ); 697 Document doc; 698 try { 699 doc = XMLTools.parse( sr ); 700 } catch ( SAXException e ) { 701 throw new XMLParsingException( "could not parse filter function", e ); 702 } 703 XMLTools.copyNode( doc.getDocumentElement(), queryElem ); 704 } 705 } 706 // copy filter into query node 707 if ( query.getFilter() != null ) { 708 StringReader sr = new StringReader( query.getFilter().toXML().toString() ); 709 Document doc; 710 try { 711 doc = XMLTools.parse( sr ); 712 } catch ( SAXException e ) { 713 throw new XMLParsingException( "could not parse filter", e ); 714 } 715 Element elem = XMLTools.appendElement( queryElem, OGCNS, "ogc:Filter" ); 716 XMLTools.copyNode( doc.getDocumentElement(), elem ); 717 } 718 719 SortProperty[] sp = query.getSortProperties(); 720 if ( sp != null ) { 721 Element sortBy = XMLTools.appendElement( queryElem, OGCNS, "ogc:SortBy" ); 722 for ( int i = 0; i < sp.length; i++ ) { 723 Element sortProp = XMLTools.appendElement( sortBy, OGCNS, "ogc:SortProperty" ); 724 XMLTools.appendElement( sortProp, OGCNS, "ogc:PropertyName", sp[i].getSortProperty().getAsString() ); 725 if ( !sp[i].getSortOrder() ) { 726 XMLTools.appendElement( sortBy, OGCNS, "ogc:SortOrder", "DESC" ); 727 } 728 } 729 } 730 } 731 732 /** 733 * Appends the XML representation of the <code>wfs:FeatureTypeList</code>- section to the 734 * passed <code>Element</code>. 735 * 736 * @param root 737 * @param featureTypeList 738 */ 739 public static void appendFeatureTypeList( Element root, FeatureTypeList featureTypeList ) { 740 741 Element featureTypeListNode = XMLTools.appendElement( root, WFS, PRE_WFS + "FeatureTypeList", null ); 742 Operation[] operations = featureTypeList.getGlobalOperations(); 743 if ( operations != null ) { 744 Element operationsNode = XMLTools.appendElement( featureTypeListNode, WFS, PRE_WFS + "Operations" ); 745 for ( int i = 0; i < operations.length; i++ ) { 746 XMLTools.appendElement( operationsNode, WFS, PRE_WFS + "Operation", operations[i].getOperation() ); 747 } 748 } 749 WFSFeatureType[] featureTypes = featureTypeList.getFeatureTypes(); 750 if ( featureTypes != null ) { 751 for ( int i = 0; i < featureTypes.length; i++ ) { 752 appendWFSFeatureType( featureTypeListNode, featureTypes[i] ); 753 } 754 } 755 756 757 } 758 759 /** 760 * Appends the XML representation of the <code>WFSFeatureType</code> instance to the passed 761 * <code>Element</code>. 762 * 763 * @param root 764 * @param featureType 765 */ 766 public static void appendWFSFeatureType( Element root, WFSFeatureType featureType ) { 767 768 Element featureTypeNode = XMLTools.appendElement( root, WFS, PRE_WFS + "FeatureType" ); 769 770 if ( featureType.getName().getPrefix() != null ) { 771 XMLTools.appendNSBinding( featureTypeNode, featureType.getName().getPrefix(), 772 featureType.getName().getNamespace() ); 773 } 774 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Name", featureType.getName().getPrefixedName() ); 775 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Title", featureType.getTitle() ); 776 String abstract_ = featureType.getAbstract(); 777 if ( abstract_ != null ) { 778 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Abstract", featureType.getAbstract() ); 779 } 780 Keywords[] keywords = featureType.getKeywords(); 781 if ( keywords != null ) { 782 appendOWSKeywords( featureTypeNode, keywords ); 783 } 784 URI defaultSrs = featureType.getDefaultSRS(); 785 if ( defaultSrs != null ) { 786 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "DefaultSRS", defaultSrs.toString() ); 787 URI[] otherSrs = featureType.getOtherSrs(); 788 if ( otherSrs != null ) { 789 for ( int i = 0; i < otherSrs.length; i++ ) { 790 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "OtherSRS", otherSrs[i].toString() ); 791 } 792 } 793 } else { 794 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Title" ); 795 } 796 Operation[] operations = featureType.getOperations(); 797 if ( operations != null ) { 798 Element operationsNode = XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Operations" ); 799 for ( int i = 0; i < operations.length; i++ ) { 800 XMLTools.appendElement( operationsNode, WFS, PRE_WFS + "Operation", operations[i].getOperation() ); 801 } 802 } 803 FormatType[] formats = featureType.getOutputFormats(); 804 if ( formats != null ) { 805 appendOutputFormats( featureTypeNode, formats ); 806 } 807 Envelope[] wgs84BoundingBoxes = featureType.getWgs84BoundingBoxes(); 808 for ( int i = 0; i < wgs84BoundingBoxes.length; i++ ) { 809 appendWgs84BoundingBox( featureTypeNode, wgs84BoundingBoxes[i] ); 810 } 811 } 812 813 /** 814 * Appends the XML representation of the <code>wfs:ServesGMLObjectTypeList</code>- section to 815 * the passed <code>Element</code> as a new element with the given qualified name. 816 * 817 * @param root 818 * @param elementNS 819 * @param elementName 820 * @param gmlObjectTypes 821 */ 822 public static void appendGMLObjectTypeList( Element root, URI elementNS, String elementName, 823 GMLObject[] gmlObjectTypes ) { 824 825 Element gmlObjectTypeListNode = XMLTools.appendElement( root, elementNS, elementName ); 826 for ( int i = 0; i < gmlObjectTypes.length; i++ ) { 827 appendGMLObjectTypeType( gmlObjectTypeListNode, gmlObjectTypes[i] ); 828 } 829 } 830 831 /** 832 * Appends the XML representation of the given {@link GMLObject} (as a 833 * <code>wfs:GMLObjectType</code> element) to the passed <code>Element</code>. 834 * 835 * @param root 836 * @param gmlObjectType 837 */ 838 public static void appendGMLObjectTypeType( Element root, GMLObject gmlObjectType ) { 839 840 Element gmlObjectTypeNode = XMLTools.appendElement( root, WFS, PRE_WFS + "GMLObjectType" ); 841 842 if ( gmlObjectType.getName().getPrefix() != null ) { 843 XMLTools.appendNSBinding( gmlObjectTypeNode, gmlObjectType.getName().getPrefix(), 844 gmlObjectType.getName().getNamespace() ); 845 } 846 XMLTools.appendElement( gmlObjectTypeNode, WFS, PRE_WFS + "Name", gmlObjectType.getName().getPrefixedName() ); 847 if ( gmlObjectType.getTitle() != null ) { 848 XMLTools.appendElement( gmlObjectTypeNode, WFS, PRE_WFS + "Title", gmlObjectType.getTitle() ); 849 } 850 String abstract_ = gmlObjectType.getAbstract(); 851 if ( abstract_ != null ) { 852 XMLTools.appendElement( gmlObjectTypeNode, WFS, PRE_WFS + "Abstract", gmlObjectType.getAbstract() ); 853 } 854 Keywords[] keywords = gmlObjectType.getKeywords(); 855 if ( keywords != null ) { 856 appendOWSKeywords( gmlObjectTypeNode, keywords ); 857 } 858 FormatType[] formats = gmlObjectType.getOutputFormats(); 859 if ( formats != null ) { 860 appendOutputFormats( gmlObjectTypeNode, formats ); 861 } 862 } 863 864 /** 865 * Appends the XML representation of the given {@link Envelope} (as an 866 * <code>ows:WGS84BoundingBoxType</code> element) to the passed <code>Element</code>. 867 * 868 * @param root 869 * @param envelope 870 */ 871 public static void appendWgs84BoundingBox( Element root, Envelope envelope ) { 872 Element wgs84BoundingBoxElement = XMLTools.appendElement( root, OWSNS, "ows:WGS84BoundingBox" ); 873 XMLTools.appendElement( wgs84BoundingBoxElement, OWSNS, "ows:LowerCorner", envelope.getMin().getX() + " " 874 + envelope.getMin().getY() ); 875 XMLTools.appendElement( wgs84BoundingBoxElement, OWSNS, "ows:UpperCorner", envelope.getMax().getX() + " " 876 + envelope.getMax().getY() ); 877 } 878 879 /** 880 * Appends the XML representation of the given {@link FormatType}s as (as a 881 * <code>wfs:OutputFormats</code> element) to the passed <code>Element</code>. 882 * 883 * @param root 884 * @param formats 885 */ 886 public static void appendOutputFormats( Element root, FormatType[] formats ) { 887 888 Element outputFormatsNode = XMLTools.appendElement( root, WFS, PRE_WFS + "OutputFormats" ); 889 for ( int i = 0; i < formats.length; i++ ) { 890 Element formatNode = XMLTools.appendElement( outputFormatsNode, WFS, PRE_WFS + "Format", 891 formats[i].getValue() ); 892 if ( formats[i].getInFilter() != null ) { 893 formatNode.setAttributeNS( DEEGREEWFS.toString(), "deegree:inFilter", 894 formats[i].getInFilter().toString() ); 895 } 896 if ( formats[i].getOutFilter() != null ) { 897 formatNode.setAttributeNS( DEEGREEWFS.toString(), "deegree:outFilter", 898 formats[i].getOutFilter().toString() ); 899 } 900 if ( formats[i].getSchemaLocation() != null ) { 901 formatNode.setAttributeNS( DEEGREEWFS.toString(), "deegree:schemaLocation", 902 formats[i].getSchemaLocation().toString() ); 903 } 904 } 905 } 906 }