001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wfs/XMLFactory.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2007 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: rbezema $ 112 * 113 * @version $Revision: 7889 $, $Date: 2007-08-02 11:51:48 +0200 (Do, 02 Aug 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 {@link Element}. 204 * 205 * @param root 206 * @param serviceIdentification 207 */ 208 protected static void appendServiceIdentification( Element root, ServiceIdentification serviceIdentification ) { 209 210 // 'ServiceIdentification'-element 211 Element serviceIdentificationNode = XMLTools.appendElement( root, OWSNS, "ows:ServiceIdentification" ); 212 213 // 'ServiceType'-element 214 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceType", 215 serviceIdentification.getServiceType().getCode() ); 216 217 // 'ServiceTypeVersion'-elements 218 String[] versions = serviceIdentification.getServiceTypeVersions(); 219 for ( int i = 0; i < versions.length; i++ ) { 220 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:ServiceTypeVersion", versions[i] ); 221 } 222 223 // 'Fees'-element 224 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:Fees", serviceIdentification.getFees() ); 225 226 // 'AccessConstraints'-element 227 String[] constraints = serviceIdentification.getAccessConstraints(); 228 if ( constraints != null ) { 229 for ( int i = 0; i < constraints.length; i++ ) { 230 XMLTools.appendElement( serviceIdentificationNode, OWSNS, "ows:AccessConstraints", constraints[i] ); 231 } 232 } 233 } 234 235 /** 236 * Exports a <code>GetFeature</code> instance to a <code>GetFeatureDocument</code>. 237 * 238 * @param getFeature 239 * request to be exported 240 * @return XML representation of the <code>GetFeature</code> request 241 * @throws IOException 242 * @throws XMLParsingException 243 */ 244 public static GetFeatureDocument export( GetFeature getFeature ) 245 throws IOException, XMLParsingException { 246 247 GetFeatureDocument xml = new GetFeatureDocument(); 248 try { 249 xml.load( XMLFactory.class.getResource( "GetFeatureTemplate.xml" ) ); 250 } catch ( SAXException e ) { 251 throw new XMLParsingException( "could not parse GetFeatureTemplate.xml", e ); 252 } 253 Element root = xml.getRootElement(); 254 root.setAttribute( "outputFormat", getFeature.getOutputFormat() ); 255 root.setAttribute( "service", "WFS" ); 256 root.setAttribute( "version", getFeature.getVersion() ); 257 if ( getFeature.getHandle() != null ) { 258 root.setAttribute( "handle", getFeature.getHandle() ); 259 } 260 if ( getFeature.getResultType() == RESULT_TYPE.HITS ) { 261 root.setAttribute( "resultType", "hits" ); 262 } else { 263 root.setAttribute( "resultType", "results" ); 264 } 265 root.setAttribute( "maxFeatures", "" + getFeature.getMaxFeatures() ); 266 if ( getFeature.getStartPosition() > 0 ) { 267 root.setAttribute( "startPosition", "" + getFeature.getStartPosition() ); 268 } 269 if ( getFeature.getTraverseXLinkDepth() > 0 ) { 270 root.setAttribute( "traverseXLinkDepth", "" + getFeature.getTraverseXLinkDepth() ); 271 } 272 if ( getFeature.getTraverseXLinkExpiry() > 0 ) { 273 root.setAttribute( "traverseXLinkExpiry", "" + getFeature.getTraverseXLinkExpiry() ); 274 } 275 Query[] queries = getFeature.getQuery(); 276 for ( int i = 0; i < queries.length; i++ ) { 277 appendQuery( root, queries[i] ); 278 } 279 return xml; 280 } 281 282 /** 283 * Exports a {@link LockFeature} request instance to a {@link LockFeatureDocument}. 284 * 285 * @param request 286 * request to be exported 287 * @return XML representation of the <code>LockFeature</code> request 288 * @throws IOException 289 * @throws XMLParsingException 290 * @throws SAXException 291 */ 292 public static LockFeatureDocument export( LockFeature request ) 293 throws IOException, XMLParsingException, SAXException { 294 295 LockFeatureDocument doc = new LockFeatureDocument(); 296 doc.createEmptyDocument(); 297 298 Element root = doc.getRootElement(); 299 root.setAttribute( "version", request.getVersion() ); 300 root.setAttribute( "service", "WFS" ); 301 if ( request.getHandle() != null ) { 302 root.setAttribute( "handle", request.getHandle() ); 303 } 304 root.setAttribute( "expiry", "" + request.getExpiry() ); 305 root.setAttribute( "lockAction", "" + request.getLockAction() ); 306 307 List<Lock> locks = request.getLocks(); 308 for ( Lock lock : locks ) { 309 appendLock( root, lock ); 310 } 311 return doc; 312 } 313 314 /** 315 * Appends the XML representation of the given {@link Lock} to the given element. 316 * 317 * @param root 318 * @param lock 319 */ 320 private static void appendLock( Element root, Lock lock ) 321 throws IOException, XMLParsingException { 322 323 Element lockElement = XMLTools.appendElement( root, WFS, PRE_WFS + "Lock" ); 324 if ( lock.getHandle() != null ) { 325 lockElement.setAttribute( "handle", lock.getHandle() ); 326 } 327 QualifiedName typeName = lock.getTypeName(); 328 if ( typeName.getPrefix() != null ) { 329 lockElement.setAttribute( "xmlns:" + typeName.getPrefix(), typeName.getNamespace().toASCIIString() ); 330 } 331 lockElement.setAttribute( "typeName", typeName.getPrefixedName() ); 332 333 // copy filter into Lock element 334 if ( lock.getFilter() != null ) { 335 StringReader sr = new StringReader( lock.getFilter().toXML().toString() ); 336 Document doc; 337 try { 338 doc = XMLTools.parse( sr ); 339 } catch ( SAXException e ) { 340 throw new XMLParsingException( "Could not parse filter.", e ); 341 } 342 Element elem = XMLTools.appendElement( lockElement, OGCNS, "ogc:Filter" ); 343 XMLTools.copyNode( doc.getDocumentElement(), elem ); 344 } 345 } 346 347 /** 348 * Exports a {@link LockFeatureResponse} instance to its XML representation. 349 * 350 * @param response 351 * response to be exported 352 * @return XML representation of the <code>LockFeatureResponse</code> 353 * @throws IOException 354 * @throws SAXException 355 */ 356 public static LockFeatureResponseDocument export( LockFeatureResponse response ) 357 throws IOException, SAXException { 358 359 LockFeatureResponseDocument doc = new LockFeatureResponseDocument(); 360 doc.createEmptyDocument(); 361 362 Element root = doc.getRootElement(); 363 XMLTools.appendElement( root, WFS, PRE_WFS + "LockId", response.getLockId() ); 364 String[] fids = response.getFeaturesLocked(); 365 if ( fids.length != 0 ) { 366 Element featuresLockedElement = XMLTools.appendElement( root, WFS, PRE_WFS + "FeaturesLocked" ); 367 for ( String fid : fids ) { 368 appendFeatureId( featuresLockedElement, fid ); 369 } 370 } 371 fids = response.getFeaturesNotLocked(); 372 if ( fids.length != 0 ) { 373 Element featuresNotLockedElement = XMLTools.appendElement( root, WFS, PRE_WFS + "FeaturesNotLocked" ); 374 for ( String fid : fids ) { 375 appendFeatureId( featuresNotLockedElement, fid ); 376 } 377 } 378 return doc; 379 } 380 381 /** 382 * Exports a {@link Transaction} instance to its XML representation. 383 * 384 * @param transaction 385 * transaction to export 386 * @return XML representation of transaction 387 * @throws IOException 388 * @throws XMLParsingException 389 */ 390 public static TransactionDocument export( Transaction transaction ) 391 throws IOException, XMLParsingException { 392 393 TransactionDocument xml = new TransactionDocument(); 394 try { 395 xml.createEmptyDocument(); 396 } catch ( SAXException e ) { 397 throw new IOException( e.getMessage() ); 398 } 399 Element root = xml.getRootElement(); 400 List ops = transaction.getOperations(); 401 for ( int i = 0; i < ops.size(); i++ ) { 402 try { 403 if ( ops.get( i ) instanceof Insert ) { 404 appendInsert( root, (Insert) ops.get( i ) ); 405 } else if ( ops.get( i ) instanceof Update ) { 406 appendUpdate( root, (Update) ops.get( i ) ); 407 } else if ( ops.get( i ) instanceof Delete ) { 408 appendDelete( root, (Delete) ops.get( i ) ); 409 } 410 } catch ( Exception e ) { 411 LOG.logError( e.getMessage(), e ); 412 throw new XMLParsingException( e.getMessage() ); 413 } 414 } 415 return xml; 416 } 417 418 /** 419 * Adds the XML representation of a <code>Delete</code> operation to the given element. 420 * 421 * @param root 422 * @param delete 423 */ 424 private static void appendDelete( Element root, Delete delete ) { 425 Element el = XMLTools.appendElement( root, WFS, "Delete" ); 426 if ( delete.getHandle() != null ) { 427 el.setAttribute( "handle", delete.getHandle() ); 428 } 429 // TODO What about the namespace binding here? 430 el.setAttribute( "typeName", delete.getTypeName().getPrefixedName() ); 431 432 Filter filter = delete.getFilter(); 433 if ( filter != null ) { 434 org.deegree.model.filterencoding.XMLFactory.appendFilter( el, filter ); 435 } 436 root.appendChild( el ); 437 } 438 439 /** 440 * Adds the XML representation of an <code>Update</code> operation to the given element. 441 * <p> 442 * Respects the deegree-specific extension to the Update operation: instead of specifying properties and their 443 * values, it's also possible to only specify just one feature that replaces the matched feature. 444 * 445 * @param root 446 * @param update 447 * @throws SAXException 448 * @throws IOException 449 * @throws FeatureException 450 * @throws GeometryException 451 */ 452 private static void appendUpdate( Element root, Update update ) 453 throws FeatureException, IOException, SAXException, GeometryException { 454 455 Element el = XMLTools.appendElement( root, WFS, "Update" ); 456 if ( update.getHandle() != null ) { 457 el.setAttribute( "handle", update.getHandle() ); 458 } 459 // TODO What about the namespace binding here? 460 el.setAttribute( "typeName", update.getTypeName().getPrefixedName() ); 461 462 Feature replacement = update.getFeature(); 463 if ( replacement != null ) { 464 GMLFeatureAdapter adapter = new GMLFeatureAdapter(); 465 adapter.append( root, replacement ); 466 } else { 467 Map<PropertyPath, FeatureProperty> replaces = update.getReplacementProperties(); 468 for ( PropertyPath propertyName : replaces.keySet() ) { 469 Element propElement = XMLTools.appendElement( el, WFS, "Property" ); 470 Element nameElement = XMLTools.appendElement( propElement, WFS, "Name" ); 471 org.deegree.ogcbase.XMLFactory.appendPropertyPath( nameElement, propertyName ); 472 473 // append property value 474 Object propValue = replaces.get( propertyName ).getValue(); 475 if ( propValue != null ) { 476 Element valueElement = XMLTools.appendElement( propElement, WFS, "Value" ); 477 if ( propValue instanceof Feature ) { 478 GMLFeatureAdapter adapter = new GMLFeatureAdapter(); 479 adapter.append( valueElement, (Feature) propValue ); 480 } else if ( propValue instanceof Geometry ) { 481 appendGeometry( valueElement, (Geometry) propValue ); 482 } else { 483 XMLTools.setNodeValue( valueElement, propValue.toString() ); 484 } 485 } 486 } 487 } 488 489 Filter filter = update.getFilter(); 490 if ( filter != null ) { 491 org.deegree.model.filterencoding.XMLFactory.appendFilter( el, filter ); 492 } 493 root.appendChild( el ); 494 } 495 496 /** 497 * Adds the XML representation of an <code>Insert</code> operation to the given element. 498 * 499 * @param root 500 * @param insert 501 * @throws SAXException 502 * @throws IOException 503 * @throws FeatureException 504 */ 505 private static void appendInsert( Element root, Insert insert ) 506 throws IOException, FeatureException, XMLException, SAXException { 507 508 Element el = XMLTools.appendElement( root, WFS, "Insert" ); 509 if ( insert.getHandle() != null ) { 510 el.setAttribute( "handle", insert.getHandle() ); 511 } 512 if ( insert.getIdGen() != null ) { 513 el.setAttribute( "idgen", insert.getIdGen().name() ); 514 } 515 516 GMLFeatureAdapter adapter = new GMLFeatureAdapter(); 517 adapter.append( el, insert.getFeatures() ); 518 } 519 520 /** 521 * Exports an instance of {@link TransactionResponse} to its XML representation. 522 * 523 * @param response 524 * TransactionResponse to export 525 * @return XML representation of TransactionResponse 526 * @throws IOException 527 */ 528 public static TransactionResponseDocument export( TransactionResponse response ) 529 throws IOException { 530 531 TransactionResponseDocument xml = new TransactionResponseDocument(); 532 try { 533 xml.createEmptyDocument(); 534 } catch ( SAXException e ) { 535 throw new IOException( e.getMessage() ); 536 } 537 538 Element root = xml.getRootElement(); 539 appendTransactionSummary( root, response.getTotalInserted(), response.getTotalUpdated(), 540 response.getTotalDeleted() ); 541 appendInsertResults( root, response.getInsertResults() ); 542 return xml; 543 } 544 545 /** 546 * Appends a 'wfs:TransactionSummary' element to the given element. 547 * 548 * @param root 549 * @param totalInserted 550 * @param totalUpdated 551 * @param totalDeleted 552 */ 553 private static void appendTransactionSummary( Element root, int totalInserted, int totalUpdated, int totalDeleted ) { 554 Element taSummary = XMLTools.appendElement( root, WFS, PRE_WFS + "TransactionSummary" ); 555 XMLTools.appendElement( taSummary, WFS, PRE_WFS + "totalInserted", "" + totalInserted ); 556 XMLTools.appendElement( taSummary, WFS, PRE_WFS + "totalUpdated", "" + totalUpdated ); 557 XMLTools.appendElement( taSummary, WFS, PRE_WFS + "totalDeleted", "" + totalDeleted ); 558 } 559 560 /** 561 * Appends an 'wfs:InsertResults' element to the given element (only if necessary). 562 * 563 * @param root 564 * @param insertResults 565 */ 566 private static void appendInsertResults( Element root, Collection<InsertResults> insertResults ) { 567 if ( insertResults.size() > 0 ) { 568 Element insertResultsElement = XMLTools.appendElement( root, WFS, PRE_WFS + "InsertResults" ); 569 Iterator<InsertResults> iter = insertResults.iterator(); 570 while ( iter.hasNext() ) { 571 appendFeatureIds( insertResultsElement, iter.next() ); 572 } 573 } 574 } 575 576 /** 577 * Appends a 'wfs:Feature' element to the given element. 578 * 579 * @param root 580 * @param results 581 */ 582 private static void appendFeatureIds( Element root, InsertResults results ) { 583 Element featureElement = XMLTools.appendElement( root, WFS, PRE_WFS + "Feature" ); 584 String handle = results.getHandle(); 585 if ( handle != null ) { 586 featureElement.setAttribute( "handle", handle ); 587 } 588 Iterator<FeatureId> iter = results.getFeatureIDs().iterator(); 589 while ( iter.hasNext() ) { 590 Element featureIdElement = XMLTools.appendElement( featureElement, OGCNS, "ogc:FeatureId" ); 591 featureIdElement.setAttribute( "fid", iter.next().getAsString() ); 592 } 593 } 594 595 /** 596 * Appends the XML representation of the given {@link Query} instance to an element. 597 * 598 * @param query 599 */ 600 private static void appendQuery( Element root, Query query ) 601 throws IOException, XMLParsingException { 602 603 Element queryElem = XMLTools.appendElement( root, WFS, PRE_WFS + "Query" ); 604 if ( query.getHandle() != null ) { 605 queryElem.setAttribute( "handle", query.getHandle() ); 606 } 607 if ( query.getFeatureVersion() != null ) { 608 queryElem.setAttribute( "featureVersion", query.getFeatureVersion() ); 609 } 610 QualifiedName[] qn = query.getTypeNames(); 611 String[] na = new String[qn.length]; 612 for ( int i = 0; i < na.length; i++ ) { 613 na[i] = qn[i].getPrefixedName(); 614 queryElem.setAttribute( "xmlns:" + qn[i].getPrefix(), qn[i].getNamespace().toASCIIString() ); 615 } 616 String tn = StringTools.arrayToString( na, ',' ); 617 queryElem.setAttribute( "typeName", tn ); 618 619 if (query.getSrsName() != null) { 620 queryElem.setAttribute( "srsName", query.getSrsName() ); 621 } 622 623 String[] aliases = query.getAliases(); 624 if ( aliases != null && aliases.length != 0 ) { 625 StringBuffer aliasesList = new StringBuffer( aliases[0] ); 626 for ( int i = 1; i < aliases.length; i++ ) { 627 aliasesList.append( ' ' ); 628 aliasesList.append( aliases[i] ); 629 } 630 queryElem.setAttribute( "aliases", aliasesList.toString() ); 631 } 632 633 PropertyPath[] propertyNames = query.getPropertyNames(); 634 for ( int i = 0; i < propertyNames.length; i++ ) { 635 Element propertyNameElement = XMLTools.appendElement( queryElem, WFS, PRE_WFS + "PropertyName" ); 636 appendPropertyPath( propertyNameElement, propertyNames[i] ); 637 } 638 Function[] fn = query.getFunctions(); 639 // copy function definitions into query node 640 if ( fn != null ) { 641 for ( int i = 0; i < fn.length; i++ ) { 642 StringReader sr = new StringReader( fn[i].toXML().toString() ); 643 Document doc; 644 try { 645 doc = XMLTools.parse( sr ); 646 } catch ( SAXException e ) { 647 throw new XMLParsingException( "could not parse filter function", e ); 648 } 649 XMLTools.copyNode( doc.getDocumentElement(), queryElem ); 650 } 651 } 652 // copy filter into query node 653 if ( query.getFilter() != null ) { 654 StringReader sr = new StringReader( query.getFilter().toXML().toString() ); 655 Document doc; 656 try { 657 doc = XMLTools.parse( sr ); 658 } catch ( SAXException e ) { 659 throw new XMLParsingException( "could not parse filter", e ); 660 } 661 Element elem = XMLTools.appendElement( queryElem, OGCNS, "ogc:Filter" ); 662 XMLTools.copyNode( doc.getDocumentElement(), elem ); 663 } 664 665 SortProperty[] sp = query.getSortProperties(); 666 if ( sp != null ) { 667 Element sortBy = XMLTools.appendElement( queryElem, OGCNS, "ogc:SortBy" ); 668 for ( int i = 0; i < sp.length; i++ ) { 669 Element sortProp = XMLTools.appendElement( sortBy, OGCNS, "ogc:SortProperty" ); 670 XMLTools.appendElement( sortProp, OGCNS, "ogc:PropertyName", sp[i].getSortProperty().getAsString() ); 671 if ( !sp[i].getSortOrder() ) { 672 XMLTools.appendElement( sortBy, OGCNS, "ogc:SortOrder", "DESC" ); 673 } 674 } 675 } 676 } 677 678 /** 679 * Appends the XML representation of the <code>wfs:FeatureTypeList</code>- section to the passed 680 * <code>Element</code>. 681 * 682 * @param root 683 * @param featureTypeList 684 */ 685 public static void appendFeatureTypeList( Element root, FeatureTypeList featureTypeList ) { 686 687 Element featureTypeListNode = XMLTools.appendElement( root, WFS, PRE_WFS + "FeatureTypeList", null ); 688 Operation[] operations = featureTypeList.getGlobalOperations(); 689 if ( operations != null ) { 690 Element operationsNode = XMLTools.appendElement( featureTypeListNode, WFS, PRE_WFS + "Operations" ); 691 for ( int i = 0; i < operations.length; i++ ) { 692 XMLTools.appendElement( operationsNode, WFS, PRE_WFS + "Operation", operations[i].getOperation() ); 693 } 694 } 695 WFSFeatureType[] featureTypes = featureTypeList.getFeatureTypes(); 696 if ( featureTypes != null ) { 697 for ( int i = 0; i < featureTypes.length; i++ ) { 698 appendWFSFeatureType( featureTypeListNode, featureTypes[i] ); 699 } 700 } 701 702 LOG.exiting(); 703 } 704 705 /** 706 * Appends the XML representation of the <code>WFSFeatureType</code> instance to the passed <code>Element</code>. 707 * 708 * @param root 709 * @param featureType 710 */ 711 public static void appendWFSFeatureType( Element root, WFSFeatureType featureType ) { 712 713 Element featureTypeNode = XMLTools.appendElement( root, WFS, PRE_WFS + "FeatureType" ); 714 715 if ( featureType.getName().getPrefix() != null ) { 716 XMLTools.appendNSBinding( featureTypeNode, featureType.getName().getPrefix(), 717 featureType.getName().getNamespace() ); 718 } 719 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Name", featureType.getName().getPrefixedName() ); 720 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Title", featureType.getTitle() ); 721 String abstract_ = featureType.getAbstract(); 722 if ( abstract_ != null ) { 723 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Abstract", featureType.getAbstract() ); 724 } 725 Keywords[] keywords = featureType.getKeywords(); 726 if ( keywords != null ) { 727 appendOWSKeywords( featureTypeNode, keywords ); 728 } 729 URI defaultSrs = featureType.getDefaultSRS(); 730 if ( defaultSrs != null ) { 731 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "DefaultSRS", defaultSrs.toString() ); 732 URI[] otherSrs = featureType.getOtherSrs(); 733 if ( otherSrs != null ) { 734 for ( int i = 0; i < otherSrs.length; i++ ) { 735 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "OtherSRS", otherSrs[i].toString() ); 736 } 737 } 738 } else { 739 XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Title" ); 740 } 741 Operation[] operations = featureType.getOperations(); 742 if ( operations != null ) { 743 Element operationsNode = XMLTools.appendElement( featureTypeNode, WFS, PRE_WFS + "Operations" ); 744 for ( int i = 0; i < operations.length; i++ ) { 745 XMLTools.appendElement( operationsNode, WFS, PRE_WFS + "Operation", operations[i].getOperation() ); 746 } 747 } 748 FormatType[] formats = featureType.getOutputFormats(); 749 if ( formats != null ) { 750 appendOutputFormats( featureTypeNode, formats ); 751 } 752 Envelope[] wgs84BoundingBoxes = featureType.getWgs84BoundingBoxes(); 753 for ( int i = 0; i < wgs84BoundingBoxes.length; i++ ) { 754 appendWgs84BoundingBox( featureTypeNode, wgs84BoundingBoxes[i] ); 755 } 756 } 757 758 /** 759 * Appends the XML representation of the <code>wfs:ServesGMLObjectTypeList</code>- section to the passed 760 * <code>Element</code> as a new element with the given qualified name. 761 * 762 * @param root 763 * @param elementNS 764 * @param elementName 765 * @param gmlObjectTypes 766 */ 767 public static void appendGMLObjectTypeList( Element root, URI elementNS, String elementName, 768 GMLObject[] gmlObjectTypes ) { 769 770 Element gmlObjectTypeListNode = XMLTools.appendElement( root, elementNS, elementName ); 771 for ( int i = 0; i < gmlObjectTypes.length; i++ ) { 772 appendGMLObjectTypeType( gmlObjectTypeListNode, gmlObjectTypes[i] ); 773 } 774 } 775 776 /** 777 * Appends the XML representation of the given {@link GMLObject} (as a <code>wfs:GMLObjectType</code> element) to 778 * the passed <code>Element</code>. 779 * 780 * @param root 781 * @param gmlObjectType 782 */ 783 public static void appendGMLObjectTypeType( Element root, GMLObject gmlObjectType ) { 784 785 Element gmlObjectTypeNode = XMLTools.appendElement( root, WFS, PRE_WFS + "GMLObjectType" ); 786 787 if ( gmlObjectType.getName().getPrefix() != null ) { 788 XMLTools.appendNSBinding( gmlObjectTypeNode, gmlObjectType.getName().getPrefix(), 789 gmlObjectType.getName().getNamespace() ); 790 } 791 XMLTools.appendElement( gmlObjectTypeNode, WFS, PRE_WFS + "Name", gmlObjectType.getName().getPrefixedName() ); 792 if ( gmlObjectType.getTitle() != null ) { 793 XMLTools.appendElement( gmlObjectTypeNode, WFS, PRE_WFS + "Title", gmlObjectType.getTitle() ); 794 } 795 String abstract_ = gmlObjectType.getAbstract(); 796 if ( abstract_ != null ) { 797 XMLTools.appendElement( gmlObjectTypeNode, WFS, PRE_WFS + "Abstract", gmlObjectType.getAbstract() ); 798 } 799 Keywords[] keywords = gmlObjectType.getKeywords(); 800 if ( keywords != null ) { 801 appendOWSKeywords( gmlObjectTypeNode, keywords ); 802 } 803 FormatType[] formats = gmlObjectType.getOutputFormats(); 804 if ( formats != null ) { 805 appendOutputFormats( gmlObjectTypeNode, formats ); 806 } 807 } 808 809 /** 810 * Appends the XML representation of the given {@link Envelope} (as an <code>ows:WGS84BoundingBoxType</code> 811 * element) to the passed <code>Element</code>. 812 * 813 * @param root 814 * @param envelope 815 */ 816 public static void appendWgs84BoundingBox( Element root, Envelope envelope ) { 817 Element wgs84BoundingBoxElement = XMLTools.appendElement( root, OWSNS, "ows:WGS84BoundingBox" ); 818 XMLTools.appendElement( wgs84BoundingBoxElement, OWSNS, "ows:LowerCorner", envelope.getMin().getX() + " " 819 + envelope.getMin().getY() ); 820 XMLTools.appendElement( wgs84BoundingBoxElement, OWSNS, "ows:UpperCorner", envelope.getMax().getX() + " " 821 + envelope.getMax().getY() ); 822 } 823 824 /** 825 * Appends the XML representation of the given {@link FormatType}s as (as a <code>wfs:OutputFormats</code> 826 * element) to the passed <code>Element</code>. 827 * 828 * @param root 829 * @param formats 830 */ 831 public static void appendOutputFormats( Element root, FormatType[] formats ) { 832 833 Element outputFormatsNode = XMLTools.appendElement( root, WFS, PRE_WFS + "OutputFormats" ); 834 for ( int i = 0; i < formats.length; i++ ) { 835 Element formatNode = XMLTools.appendElement( outputFormatsNode, WFS, PRE_WFS + "Format", formats[i].getValue() ); 836 if ( formats[i].getInFilter() != null ) { 837 formatNode.setAttributeNS( DEEGREEWFS.toString(), "deegree:inFilter", 838 formats[i].getInFilter().toString() ); 839 } 840 if ( formats[i].getOutFilter() != null ) { 841 formatNode.setAttributeNS( DEEGREEWFS.toString(), "deegree:outFilter", 842 formats[i].getOutFilter().toString() ); 843 } 844 if ( formats[i].getSchemaLocation() != null ) { 845 formatNode.setAttributeNS( DEEGREEWFS.toString(), "deegree:schemaLocation", 846 formats[i].getSchemaLocation().toString() ); 847 } 848 } 849 } 850 }