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 }