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 }