001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wps/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/exse/
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     Aennchenstraße 19
030     53177 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.wps;
044    
045    import static org.deegree.ogcbase.CommonNamespaces.WPSNS;
046    
047    import java.io.ByteArrayOutputStream;
048    import java.io.IOException;
049    import java.io.StringReader;
050    import java.io.UnsupportedEncodingException;
051    import java.net.URI;
052    import java.net.URL;
053    import java.net.URLEncoder;
054    import java.util.Iterator;
055    import java.util.List;
056    import java.util.Map;
057    
058    import org.deegree.datatypes.Code;
059    import org.deegree.datatypes.values.TypedLiteral;
060    import org.deegree.datatypes.values.ValueRange;
061    import org.deegree.framework.util.CharsetUtils;
062    import org.deegree.framework.xml.XMLFragment;
063    import org.deegree.framework.xml.XMLTools;
064    import org.deegree.model.feature.FeatureCollection;
065    import org.deegree.model.feature.FeatureException;
066    import org.deegree.model.feature.GMLFeatureAdapter;
067    import org.deegree.model.spatialschema.Envelope;
068    import org.deegree.model.spatialschema.Position;
069    import org.deegree.ogcwebservices.ExceptionReport;
070    import org.deegree.ogcwebservices.MetadataType;
071    import org.deegree.ogcwebservices.OGCWebServiceException;
072    import org.deegree.ogcwebservices.getcapabilities.Contents;
073    import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
074    import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
075    import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification;
076    import org.deegree.ogcwebservices.getcapabilities.ServiceProvider;
077    import org.deegree.ogcwebservices.wps.capabilities.ProcessOfferings;
078    import org.deegree.ogcwebservices.wps.capabilities.WPSCapabilities;
079    import org.deegree.ogcwebservices.wps.capabilities.WPSCapabilitiesDocument;
080    import org.deegree.ogcwebservices.wps.describeprocess.ComplexData;
081    import org.deegree.ogcwebservices.wps.describeprocess.InputDescription;
082    import org.deegree.ogcwebservices.wps.describeprocess.LiteralInput;
083    import org.deegree.ogcwebservices.wps.describeprocess.LiteralOutput;
084    import org.deegree.ogcwebservices.wps.describeprocess.OutputDescription;
085    import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription;
086    import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescriptions;
087    import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescriptionsDocument;
088    import org.deegree.ogcwebservices.wps.describeprocess.SupportedCRSs;
089    import org.deegree.ogcwebservices.wps.describeprocess.SupportedComplexData;
090    import org.deegree.ogcwebservices.wps.describeprocess.SupportedUOMs;
091    import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.DataInputs;
092    import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.ProcessOutputs;
093    import org.deegree.ogcwebservices.wps.execute.ComplexValue;
094    import org.deegree.ogcwebservices.wps.execute.ExecuteDataInputs;
095    import org.deegree.ogcwebservices.wps.execute.ExecuteResponse;
096    import org.deegree.ogcwebservices.wps.execute.ExecuteResponseDocument;
097    import org.deegree.ogcwebservices.wps.execute.IOValue;
098    import org.deegree.ogcwebservices.wps.execute.OutputDefinition;
099    import org.deegree.ogcwebservices.wps.execute.OutputDefinitions;
100    import org.deegree.ogcwebservices.wps.execute.ProcessFailed;
101    import org.deegree.ogcwebservices.wps.execute.ProcessStarted;
102    import org.deegree.ogcwebservices.wps.execute.Status;
103    import org.deegree.ogcwebservices.wps.execute.IOValue.ComplexValueReference;
104    import org.deegree.owscommon.OWSMetadata;
105    import org.deegree.owscommon.com110.OWSAllowedValues;
106    import org.w3c.dom.Document;
107    import org.w3c.dom.Element;
108    import org.w3c.dom.Node;
109    import org.xml.sax.SAXException;
110    
111    /**
112     * XMLFactory.java
113     * 
114     * Created on 08.03.2006. 23:28:46h
115     * 
116     * @author <a href="mailto:christian@kiehle.org">Christian Kiehle</a>
117     * @author <a href="mailto:christian.heier@gmx.de">Christian Heier</a>
118     * 
119     * @version 1.0.
120     * 
121     * @since 2.0
122     */
123    public class XMLFactory extends org.deegree.owscommon.XMLFactory {
124    
125        /**
126         * 
127         * @param capabilities
128         * @return
129         * @throws InvalidCapabilitiesException
130         * @throws IOException
131         */
132        public static WPSCapabilitiesDocument export( WPSCapabilities capabilities )
133                                throws IOException {
134            
135            WPSCapabilitiesDocument capabilitiesDocument = new WPSCapabilitiesDocument();
136    
137            try {
138                capabilitiesDocument.createEmptyDocument();
139                Element root = capabilitiesDocument.getRootElement();
140    
141                ServiceIdentification serviceIdentification = capabilities.getServiceIdentification();
142                if ( serviceIdentification != null ) {
143                    appendServiceIdentification( root, serviceIdentification );
144                }
145    
146                ServiceProvider serviceProvider = capabilities.getServiceProvider();
147                if ( serviceProvider != null ) {
148                    appendServiceProvider( root, capabilities.getServiceProvider() );
149                }
150    
151                OperationsMetadata operationsMetadata = capabilities.getOperationsMetadata();
152                if ( operationsMetadata != null ) {
153                    appendOperationsMetadata( root, operationsMetadata );
154                }
155                Contents contents = capabilities.getContents();
156                if ( contents != null ) {
157                    // appendContents(root, contents);
158                }
159                ProcessOfferings processOfferings = capabilities.getProcessOfferings();
160                if ( null != processOfferings ) {
161                    appendProcessOfferings( root, processOfferings );
162                }
163    
164            } catch ( SAXException e ) {
165                LOG.logError( e.getMessage(), e );
166            }
167            
168            return capabilitiesDocument;
169        }
170    
171        /**
172         * Appends the DOM representation of the <code>wps:ProcessOfferings</code>- section to the
173         * passed <code>Element</code>.
174         * 
175         * @param root
176         * @param processOfferings
177         */
178        private static void appendProcessOfferings( Element root, ProcessOfferings processOfferings ) {
179            
180            // Add a <wps:ProcessOfferings>node to the <wps:Capabilities> node
181            Element processOfferingsNode = XMLTools.appendElement( root, WPSNS, "wps:ProcessOfferings", null );
182            // Add <wps:Process> nodes to the <wps:ProcessOfferings> node
183            List<ProcessBrief> processBriefTypeList = processOfferings.getProcessBriefTypesList();
184            if ( null != processBriefTypeList && 0 != processBriefTypeList.size() ) {
185                int size = processBriefTypeList.size();
186                for ( int i = 0; i < size; i++ ) {
187                    appendProcessBriefType( processOfferingsNode, processBriefTypeList.get( i ) );
188                }
189            }
190    
191            
192        }
193    
194        /**
195         * Appends the DOM representation of the <code>ProcessBriefType</code> instance to the passed
196         * <code>Element</code>.
197         * 
198         * @param processOfferingsNode
199         * @param processBriefType
200         */
201        private static void appendProcessBriefType( Element processOfferingsNode, ProcessBrief processBriefType ) {
202    
203            // Add a <wps:Process> node to the <wps:ProcessOfferings> node
204            Element processBriefTypeNode = XMLTools.appendElement( processOfferingsNode, WPSNS, "wps:Process" );
205            // Add optional attribute "processVersion" to <wps:Process> node if
206            // present
207            String processVersion = processBriefType.getProcessVersion();
208            if ( null != processVersion && !"".equals( processVersion ) ) {
209                processBriefTypeNode.setAttribute( "processVersion", processVersion );
210            }
211    
212            // Add mandatory node <ows:Identifier>
213            Code identifier = processBriefType.getIdentifier();
214            if ( null != identifier ) {
215                appendIdentifier( processBriefTypeNode, identifier );
216            } else {
217                LOG.logError( "identifier is null." );
218            }
219    
220            // Add mandatory node <ows:Title>
221            String title = processBriefType.getTitle();
222            if ( null != title ) {
223                appendTitle( processBriefTypeNode, title );
224            } else {
225                LOG.logError( "title is null." );
226            }
227    
228            // Add optional node <ows:Abstract/>
229    
230            String _abstract = processBriefType.getAbstract();
231            if ( null != _abstract ) {
232                appendAbstract( processBriefTypeNode, _abstract );
233            }
234    
235            // Add optional nodes <ows:Metadata/>
236            List<MetadataType> metaDataTypeList = processBriefType.getMetadata();
237            if ( null != metaDataTypeList && 0 != metaDataTypeList.size() ) {
238                int size = metaDataTypeList.size();
239                for ( int i = 0; i < size; i++ ) {
240                    appendMetaDataType( processBriefTypeNode, metaDataTypeList.get( i ) );
241                }
242            }
243            
244        }
245    
246        /**
247         * 
248         * @param e
249         * @param identifier
250         */
251        private static void appendIdentifier( Element e, Code identifier ) {
252    
253            String identifierString = identifier.getCode();
254    
255            if ( null != identifierString && !"".equals( identifierString ) ) {
256                XMLTools.appendElement( e, OWSNS, "ows:Identifier", identifierString );
257            } else {
258                LOG.logError( "identifier is empty." );
259            }
260            
261        }
262    
263        /**
264         * 
265         * @param e
266         * @param title
267         */
268        private static void appendTitle( Element e, String title ) {
269    
270            if ( !"".equals( title ) ) {
271                XMLTools.appendElement( e, OWSNS, "ows:Title", title );
272            } else {
273                LOG.logError( "title is empty." );
274            }
275            
276        }
277    
278        /**
279         * Appends the DOM representation of the <code>MetadataType</code> instance to the passed
280         * <code>Element</code>.
281         * 
282         * @param e
283         * @param metaDataType
284         */
285        private static void appendMetaDataType( Element e, MetadataType metaDataType ) {
286            
287            // Add optional node <ows:Metadata>
288            String metadataTypeValue = metaDataType.value;
289            if ( null != metadataTypeValue && !"".equals( metadataTypeValue ) ) {
290                Element metadataNode = XMLTools.appendElement( e, OWSNS, "ows:Metadata" );
291                metadataNode.setAttributeNS( XLNNS.toString(), "xlink:title", metadataTypeValue );
292            }
293            
294        }
295    
296        /**
297         * 
298         * @param processDescriptions
299         * @return
300         * @throws InvalidCapabilitiesException
301         * @throws IOException
302         */
303        public static ProcessDescriptionsDocument export( ProcessDescriptions processDescriptions )
304                                throws IOException {
305            ProcessDescriptionsDocument processDescriptionsDocument = new ProcessDescriptionsDocument();
306            try {
307                processDescriptionsDocument.createEmptyDocument();
308                Element root = processDescriptionsDocument.getRootElement();
309                List<ProcessDescription> processDescriptionList = processDescriptions.getProcessDescription();
310                if ( null != processDescriptionList ) {
311                    int processDescriptionListSize = processDescriptionList.size();
312                    for ( int i = 0; i < processDescriptionListSize; i++ ) {
313                        ProcessDescription processDescription = processDescriptionList.get( i );
314                        appendProcessDescription( root, processDescription );
315                    }
316                }
317            } catch ( SAXException sex ) {
318                LOG.logError( sex.getMessage(), sex );
319            }
320            
321            return processDescriptionsDocument;
322        }
323    
324        /**
325         * Appends the DOM representation of the <code>ProcessDescription</code> instance to the
326         * passed <code>Element</code>..
327         * 
328         * @param root
329         * @param processDescription
330         */
331        private static void appendProcessDescription( Element root, ProcessDescription processDescription ) {
332            
333    
334            // Add a <wps:ProcessDescription> node to the <wps:ProcessDescriptions>
335            // node
336            Element processDescriptionNode = XMLTools.appendElement( root, WPSNS, "wps:ProcessDescription", null );
337    
338            String statusSupported = Boolean.toString( processDescription.isStatusSupported() );
339            processDescriptionNode.setAttribute( "statusSupported", statusSupported );
340    
341            String storeSupported = Boolean.toString( processDescription.isStoreSupported() );
342            processDescriptionNode.setAttribute( "storeSupported", storeSupported );
343    
344            String processVersion = processDescription.getProcessVersion();
345            processDescriptionNode.setAttribute( "processVersion", processVersion );
346    
347            Code identifier = processDescription.getIdentifier();
348            if ( null != identifier ) {
349                appendIdentifier( processDescriptionNode, identifier );
350            } else {
351                LOG.logError( "Identifier is null." );
352            }
353    
354            String title = processDescription.getTitle();
355            if ( null != title ) {
356                appendTitle( processDescriptionNode, title );
357            } else {
358                LOG.logError( "title is null." );
359            }
360    
361            String _abstract = processDescription.getAbstract();
362            if ( null != _abstract ) {
363                appendAbstract( processDescriptionNode, _abstract );
364            }
365    
366            Element metaDataTypeNode = null;
367    
368            MetadataType metadataType = null;
369            List<MetadataType> metaDataTypeList = processDescription.getMetadata();
370            int metaDataTypeListSize = metaDataTypeList.size();
371            for ( int i = 0; i < metaDataTypeListSize; i++ ) {
372                metadataType = metaDataTypeList.get( i );
373                metaDataTypeNode = XMLTools.appendElement( processDescriptionNode, OWSNS, "ows:Metadata" );
374                metaDataTypeNode.setAttributeNS( XLNNS.toString(), "xlink:title", metadataType.value );
375            }
376    
377            DataInputs dataInputs = processDescription.getDataInputs();
378            appendDataInputs( processDescriptionNode, dataInputs );
379    
380            ProcessOutputs processOutputs = processDescription.getProcessOutputs();
381            appendProcessOutputs( processDescriptionNode, processOutputs );
382    
383            
384        }
385    
386        /**
387         * 
388         * @param e
389         * @param _abstract
390         */
391        private static void appendAbstract( Element e, String _abstract ) {
392            if ( !"".equals( _abstract ) ) {
393                XMLTools.appendElement( e, OWSNS, "ows:Abstract", _abstract );
394            } else {
395                LOG.logError( "abstract is empty." );
396            }
397            
398        }
399    
400        /**
401         * 
402         * @param processDescriptionNode
403         * @param dataInputs
404         */
405        private static void appendDataInputs( Element processDescriptionNode, DataInputs dataInputs ) {
406            
407            // Add a <wps:DataInputs> node to the <wps:ProcessDescription> node
408            Element dataInputsNode = XMLTools.appendElement( processDescriptionNode, WPSNS, "wps:DataInputs", null );
409            if ( null != dataInputs ) {
410                List<InputDescription> dataInputsList = dataInputs.getInputDescriptions();
411                InputDescription inputDescription = null;
412                int dataInputListSize = dataInputsList.size();
413                for ( int i = 0; i < dataInputListSize; i++ ) {
414                    inputDescription = dataInputsList.get( i );
415                    appendDataInput( dataInputsNode, inputDescription );
416                }
417            }
418            
419        }
420    
421        /**
422         * 
423         * @param dataInputsNode
424         * @param inputDescription
425         */
426        private static void appendDataInput( Element dataInputsNode, InputDescription inputDescription ) {
427            
428            // Add a <wps:DataInput> node to the <wps:DataInputs> node
429            Element inputNode = XMLTools.appendElement( dataInputsNode, WPSNS, "wps:Input", null );
430    
431            if ( null != inputNode ) {
432    
433                Code identifier = inputDescription.getIdentifier();
434                if ( null != identifier ) {
435                    appendIdentifier( inputNode, identifier );
436                } else {
437                    LOG.logError( "identifier is null." );
438                }
439    
440                String title = inputDescription.getTitle();
441                if ( null != title ) {
442                    appendTitle( inputNode, title );
443                } else {
444                    LOG.logError( "title is null." );
445                }
446    
447                String _abstract = inputDescription.getAbstract();
448                if ( null != _abstract ) {
449                    appendAbstract( inputNode, _abstract );
450                }
451    
452                try {
453    
454                    SupportedCRSs supportedCRSs = inputDescription.getBoundingBoxData();
455                    ComplexData complexData = inputDescription.getComplexData();
456                    LiteralInput literalInput = inputDescription.getLiteralData();
457    
458                    if ( null != supportedCRSs ) {
459                        appendBoundingBoxData( inputNode, supportedCRSs );
460                    } else if ( null != complexData ) {
461                        appendComplexData( inputNode, complexData );
462                    } else if ( null != literalInput ) {
463                        appendLiteralInput( inputNode, literalInput );
464                    } else {
465                        LOG.logError( "a required datatype description is missing." );
466                    }
467    
468                } catch ( Exception e ) {
469                    LOG.logError( e.getMessage(), e );
470                }
471    
472                XMLTools.appendElement( inputNode, WPSNS, "wps:MinimumOccurs",
473                                        String.valueOf( inputDescription.getMinimumOccurs() ) );
474            }
475            
476        }
477    
478        /**
479         * 
480         * @param root
481         * @param processOutputs
482         */
483        private static void appendProcessOutputs( Element root, ProcessOutputs processOutputs ) {
484            
485            if ( null != processOutputs ) {
486                // Add a <wps:ProcessOutputs> node to the <wps:ProcessDescription>
487                // node
488                Element processOutputsNode = XMLTools.appendElement( root, WPSNS, "wps:ProcessOutputs", null );
489                OutputDescription outputDescription = null;
490                List<OutputDescription> outputDescriptionList = processOutputs.getOutput();
491                int outputDescriptionListSize = outputDescriptionList.size();
492                for ( int i = 0; i < outputDescriptionListSize; i++ ) {
493                    outputDescription = outputDescriptionList.get( i );
494                    appendOutputDescription( processOutputsNode, outputDescription );
495                }
496            }
497            
498        }
499    
500        /**
501         * 
502         * @param processOutputsNode
503         * @param outputDescription
504         */
505        private static void appendOutputDescription( Element processOutputsNode, OutputDescription outputDescription ) {
506            
507            if ( null != outputDescription ) {
508    
509                Element outputNode = XMLTools.appendElement( processOutputsNode, WPSNS, "wps:Output", null );
510    
511                Code identifier = outputDescription.getIdentifier();
512                if ( null != identifier ) {
513                    appendIdentifier( outputNode, identifier );
514                } else {
515                    LOG.logError( "identifier is null." );
516                }
517    
518                String title = outputDescription.getTitle();
519                if ( null != title ) {
520                    appendTitle( outputNode, title );
521                } else {
522                    LOG.logError( "title is null." );
523                }
524    
525                String _abstract = outputDescription.getAbstract();
526                if ( null != _abstract ) {
527                    appendAbstract( outputNode, _abstract );
528                }
529    
530                SupportedCRSs supportedCRSs = outputDescription.getBoundingBoxOutput();
531                ComplexData complexData = outputDescription.getComplexOutput();
532                LiteralOutput literalOutput = outputDescription.getLiteralOutput();
533    
534                if ( null != supportedCRSs ) {
535                    appendBoundingBoxOutput( outputNode, supportedCRSs );
536                } else if ( null != complexData ) {
537                    appendComplexOutput( outputNode, complexData );
538                } else if ( null != literalOutput ) {
539                    appendLiteralOutput( outputNode, literalOutput );
540                } else {
541                    LOG.logError( "a required output datatype description is missing." );
542                }
543            }
544            
545        }
546    
547        /**
548         * 
549         * @param outputNode
550         * @param complexData
551         */
552        private static void appendComplexOutput( Element outputNode, ComplexData complexData ) {
553    
554            
555            String defaultEncoding = complexData.getDefaultEncoding();
556            String defaultFormat = complexData.getDefaultFormat();
557            String defaultSchema = complexData.getDefaultSchema();
558            Element complexDataNode = XMLTools.appendElement( outputNode, WPSNS, "wps:ComplexOutput", null );
559    
560            if ( null != defaultFormat && !"".equals( defaultFormat ) ) {
561                complexDataNode.setAttribute( "defaultFormat", defaultFormat );
562            }
563            if ( null != defaultEncoding && !"".equals( defaultEncoding ) ) {
564                complexDataNode.setAttribute( "defaultEncoding", defaultEncoding );
565            }
566            if ( null != defaultSchema && !"".equals( defaultSchema ) ) {
567                complexDataNode.setAttribute( "defaultSchema", defaultSchema );
568            }
569    
570            List<SupportedComplexData> supportedComplexDataList = complexData.getSupportedComplexData();
571            int supporteComplexDataListSize = supportedComplexDataList.size();
572            for ( int i = 0; i < supporteComplexDataListSize; i++ ) {
573                appendSupportedComplexData( complexDataNode, supportedComplexDataList.get( i ) );
574            }
575            
576        }
577    
578        /**
579         * 
580         * @param outputNode
581         * @param supportedCRSs
582         */
583        private static void appendBoundingBoxOutput( Element outputNode, SupportedCRSs supportedCRSs ) {
584            
585            URI defaultCrs = supportedCRSs.getDefaultCRS();
586            Element defaultCRSs = XMLTools.appendElement( outputNode, WPSNS, "wps:BoundingBoxOutput", null );
587            defaultCRSs.setAttribute( "defaultCRS", defaultCrs.toString() );
588    
589            List<URI> crsList = supportedCRSs.getCRS();
590            int crsListSize = crsList.size();
591            for ( int i = 0; i < crsListSize; i++ ) {
592                URI uri = crsList.get( i );
593                XMLTools.appendElement( defaultCRSs, WPSNS, "wps:CRS", uri.toString() );
594            }
595            
596        }
597    
598        /**
599         * 
600         * @param outputNode
601         * @param literalOutput
602         */
603        private static void appendLiteralOutput( Element outputNode, LiteralOutput literalOutput ) {
604            
605            Element literalOutputNode = XMLTools.appendElement( outputNode, WPSNS, "wps:LiteralOutput", null );
606            Element owsDataType = XMLTools.appendElement( literalOutputNode, OWSNS, "ows:DataType",
607                                                          literalOutput.getDataType().getName() );
608            owsDataType.setAttribute( "ows:reference", literalOutput.getDataType().getLink().getHref().toString() );
609            Element supportedUOMsNode = XMLTools.appendElement( literalOutputNode, WPSNS, "wps:SupportedUOMs", null );
610    
611            supportedUOMsNode.setAttribute( "defaultUOM",
612                                            literalOutput.getSupportedUOMs().getDefaultUOM().getLink().getHref().toString() );
613    
614            List<OWSMetadata> supportedUOMs = literalOutput.getSupportedUOMs().getUOM();
615            int size = supportedUOMs.size();
616            for ( int i = 0; i < size; i++ ) {
617                OWSMetadata uom = supportedUOMs.get( i );
618                Element uomNode = XMLTools.appendElement( supportedUOMsNode, OWSNS, "ows:UOM", null );
619                uomNode.setAttribute( "ows:reference", uom.getLink().getHref().toString() );
620            }
621            
622        }
623    
624        /**
625         * 
626         * @param inputNode
627         * @param complexData
628         */
629        private static void appendComplexData( Element inputNode, ComplexData complexData ) {
630            
631            String defaultEncoding = complexData.getDefaultEncoding();
632            String defaultFormat = complexData.getDefaultFormat();
633            String defaultSchema = complexData.getDefaultSchema();
634            Element complexDataNode = XMLTools.appendElement( inputNode, WPSNS, "wps:ComplexData", null );
635    
636            if ( null != defaultFormat && !"".equals( defaultFormat ) ) {
637                complexDataNode.setAttribute( "defaultFormat", defaultFormat );
638            }
639            if ( null != defaultEncoding && !"".equals( defaultEncoding ) ) {
640                complexDataNode.setAttribute( "defaultEncoding", defaultEncoding );
641            }
642            if ( null != defaultSchema && !"".equals( defaultSchema ) ) {
643                complexDataNode.setAttribute( "defaultSchema", defaultSchema );
644            }
645    
646            List<SupportedComplexData> supportedComplexDataList = complexData.getSupportedComplexData();
647            int supporteComplexDataListSize = supportedComplexDataList.size();
648            for ( int i = 0; i < supporteComplexDataListSize; i++ ) {
649                appendSupportedComplexData( complexDataNode, supportedComplexDataList.get( i ) );
650            }
651            
652        }
653    
654        /**
655         * 
656         * @param complexDataNode
657         * @param supportedComplexData
658         */
659        private static void appendSupportedComplexData( Element complexDataNode, SupportedComplexData supportedComplexData ) {
660            
661    
662            Element supportedComplexDataNode = XMLTools.appendElement( complexDataNode, WPSNS, "wps:SupportedComplexData",
663                                                                       null );
664    
665            XMLTools.appendElement( supportedComplexDataNode, WPSNS, "wps:Format", supportedComplexData.getFormat() );
666    
667            XMLTools.appendElement( supportedComplexDataNode, WPSNS, "wps:Encoding", supportedComplexData.getEncoding() );
668    
669            XMLTools.appendElement( supportedComplexDataNode, WPSNS, "wps:Schema", supportedComplexData.getSchema() );
670    
671            
672        }
673    
674        /**
675         * 
676         * @param inputNode
677         * @param literalInput
678         */
679        private static void appendLiteralInput( Element inputNode, LiteralInput literalInput ) {
680            
681            Element literalDataNode = XMLTools.appendElement( inputNode, WPSNS, "wps:LiteralData", null );
682            Element owsDataType = XMLTools.appendElement( literalDataNode, OWSNS, "ows:DataType",
683                                                          literalInput.getDataType().getName() );
684            owsDataType.setAttribute( "ows:reference", literalInput.getDataType().getLink().getHref().toString() );
685            appendLiteralInputTypes( literalDataNode, literalInput );
686    
687            
688        }
689    
690        /**
691         * 
692         * @param literalDataNode
693         * @param literalInput
694         */
695        private static void appendLiteralInputTypes( Element literalDataNode, LiteralInput literalInput ) {
696            
697            Element supportedUOMsNode = XMLTools.appendElement( literalDataNode, WPSNS, "wps:SupportedUOMs", null );
698    
699            SupportedUOMs supportedUOMs = literalInput.getSupportedUOMs();
700            if ( null != supportedUOMs ) {
701    
702                OWSMetadata defaultUOM = literalInput.getSupportedUOMs().getDefaultUOM();
703                if ( null != defaultUOM ) {
704                    supportedUOMsNode.setAttribute(
705                                                    "defaultUOM",
706                                                    literalInput.getSupportedUOMs().getDefaultUOM().getLink().getHref().toString() );
707                }
708    
709                List<OWSMetadata> supportedUOMsList = literalInput.getSupportedUOMs().getUOM();
710                int size = supportedUOMsList.size();
711                for ( int i = 0; i < size; i++ ) {
712                    OWSMetadata uom = supportedUOMsList.get( i );
713                    Element uomNode = XMLTools.appendElement( supportedUOMsNode, OWSNS, "ows:UOM", null );
714                    uomNode.setAttribute( "ows:reference", uom.getLink().getHref().toString() );
715                }
716            }
717    
718            // append <ows:AllowedValues> on <LiteralData>
719            OWSAllowedValues owsAllowedValues = literalInput.getAllowedValues();
720            if ( null != owsAllowedValues ) {
721                Element allowedValuesNode = XMLTools.appendElement( literalDataNode, OWSNS, "ows:AllowedValues", null );
722                TypedLiteral[] typedLiteralArray = owsAllowedValues.getOwsValues();
723                if ( null != typedLiteralArray ) {
724                    for ( int i = 0; i < typedLiteralArray.length; i++ ) {
725                        // append <ows:Value/> on <ows:AllowedValues>
726                        XMLTools.appendElement( allowedValuesNode, OWSNS, "ows:Value", typedLiteralArray[i].getValue() );
727                    }
728                }
729                // append <ows:Range> on <ows:AllowedValues>
730                ValueRange[] valueRangeArray = owsAllowedValues.getValueRanges();
731                if ( null != valueRangeArray ) {
732                    for ( int i = 0; i < valueRangeArray.length; i++ ) {
733                        Element owsRangeNode = XMLTools.appendElement( allowedValuesNode, OWSNS, "ows:Range" );
734                        String closure = valueRangeArray[i].getClosure().value;
735                        if ( null != closure ) {
736                            owsRangeNode.setAttribute( "ows:rangeClosure", closure );
737                        }
738                        String minimumValue = valueRangeArray[i].getMin().getValue();
739                        if ( null != minimumValue ) {
740                            XMLTools.appendElement( owsRangeNode, OWSNS, "ows:MinimumValue", minimumValue );
741                        }
742                        String maximumValue = valueRangeArray[i].getMax().getValue();
743                        if ( null != maximumValue ) {
744                            XMLTools.appendElement( owsRangeNode, OWSNS, "ows:MaximumValue", maximumValue );
745                        }
746                        TypedLiteral typedLiteralSpacing = valueRangeArray[i].getSpacing();
747                        if ( null != typedLiteralSpacing ) {
748                            String spacing = typedLiteralSpacing.getValue();
749                            if ( null != spacing ) {
750                                XMLTools.appendElement( owsRangeNode, OWSNS, "ows:Spacing", spacing );
751                            }
752                        }
753    
754                    }
755                }
756            }
757    
758            // append <ows:AnyValue> on <LiteralData>
759            boolean anyValueAllowed = literalInput.getAnyValue();
760            if ( false != anyValueAllowed ) {
761                XMLTools.appendElement( literalDataNode, OWSNS, "ows:AnyValue" );
762            }
763    
764            // append <ows:ValuesReference> on <LiteralData>
765            OWSMetadata owsValuesReference = literalInput.getValuesReference();
766            if ( null != owsValuesReference ) {
767                Element valuesReference = XMLTools.appendElement( literalDataNode, OWSNS, "ows:ValuesReference",
768                                                                  owsValuesReference.getName() );
769                String reference = owsValuesReference.getLink().getHref().toString();
770                if ( null != reference && !"".equals( reference ) ) {
771                    valuesReference.setAttribute( "ows:reference", reference );
772                }
773            }
774    
775            // append <ows:DefaultValue> on <LiteralData>
776            ValueRange defaultValue = literalInput.getDefaultValue();
777            if ( null != defaultValue ) {
778                Element owsRangeNode = XMLTools.appendElement( literalDataNode, OWSNS, "ows:DefaultValue" );
779                String closure = defaultValue.getClosure().value;
780                if ( null != closure ) {
781                    owsRangeNode.setAttribute( "ows:rangeClosure", closure );
782                }
783                String minimumValue = defaultValue.getMin().getValue();
784                if ( null != minimumValue ) {
785                    XMLTools.appendElement( owsRangeNode, OWSNS, "ows:MinimumValue", minimumValue );
786                }
787                String maximumValue = defaultValue.getMax().getValue();
788                if ( null != maximumValue ) {
789                    XMLTools.appendElement( owsRangeNode, OWSNS, "ows:MaximumValue", maximumValue );
790                }
791                String spacing = defaultValue.getSpacing().getValue();
792                if ( null != spacing ) {
793                    XMLTools.appendElement( owsRangeNode, OWSNS, "ows:Spacing", spacing );
794                }
795            }
796            
797        }
798    
799        /**
800         * 
801         * @param inputNode
802         * @param supportedCRSs
803         */
804        private static void appendBoundingBoxData( Element inputNode, SupportedCRSs supportedCRSs ) {
805            
806            URI defaultCrs = supportedCRSs.getDefaultCRS();
807            Element defaultCRSs = XMLTools.appendElement( inputNode, WPSNS, "wps:BoundingBoxData", null );
808            defaultCRSs.setAttribute( "defaultCRS", defaultCrs.toString() );
809    
810            List<URI> crsList = supportedCRSs.getCRS();
811            int crsListSize = crsList.size();
812            for ( int i = 0; i < crsListSize; i++ ) {
813                URI uri = crsList.get( i );
814                XMLTools.appendElement( defaultCRSs, WPSNS, "wps:CRS", uri.toString() );
815    
816            }
817            
818        }
819    
820        /**
821         * 
822         * @param executeResponse
823         * @return
824         */
825        public static ExecuteResponseDocument export( ExecuteResponse executeResponse ) {
826            
827            ExecuteResponseDocument executeResponseDocument = new ExecuteResponseDocument();
828    
829            try {
830                // Prepare empty ExecuteResponseDocument
831                executeResponseDocument.createEmptyDocument();
832    
833                // Get root of execute
834                Element root = executeResponseDocument.getRootElement();
835    
836                // Append optional statusLocation attribute
837                String statusLocation = executeResponse.getStatusLocation();
838                if ( null != statusLocation ) {
839                    root.setAttribute( "statusLocation", statusLocation );
840                }
841    
842                // Append mandatory <ows:Identifier> node
843                Code identifier = executeResponse.getIdentifier();
844                if ( null != identifier ) {
845                    appendIdentifier( root, identifier );
846                } else {
847                    LOG.logError( "identifier is null." );
848                }
849    
850                // Append mandatory <Status> node
851                appendStatus( root, executeResponse.getStatus() );
852    
853                // Append optional <DataInputs> node
854                ExecuteDataInputs executeDataInputs = executeResponse.getDataInputs();
855                if ( null != executeDataInputs ) {
856                    appendExecuteDataInputs( root, executeResponse.getDataInputs() );
857                }
858    
859                // Append optional <OutputDefinitions> node
860                OutputDefinitions outputDefinitions = executeResponse.getOutputDefinitions();
861                if ( null != outputDefinitions ) {
862                    appendOutputDefinitions( root, outputDefinitions );
863                }
864    
865                // Append optional <ProcessOutputs> node
866                ExecuteResponse.ProcessOutputs processOutputs = executeResponse.getProcessOutputs();
867                if ( null != processOutputs ) {
868                    appendExecuteProcessOutputs( root, processOutputs );
869                }
870    
871            } catch ( IOException e ) {
872                LOG.logError( e.getMessage(), e );
873            } catch ( SAXException e ) {
874                LOG.logError( e.getMessage(), e );
875            }
876            
877            return executeResponseDocument;
878        }
879    
880        /**
881         * 
882         * @param root
883         * @param status
884         */
885        private static void appendStatus( Element root, Status status ) {
886    
887            
888    
889            Element statusNode = XMLTools.appendElement( root, WPSNS, "Status" );
890    
891            String processSucceeded = status.getProcessSucceeded();
892    
893            ProcessFailed processFailed = status.getProcessFailed();
894    
895            String processAccepted = status.getProcessAccepted();
896    
897            ProcessStarted processStarted = status.getProcessStarted();
898    
899            if ( null != processSucceeded ) {
900                if ( "".equals( processSucceeded ) ) {
901                    XMLTools.appendElement( statusNode, WPSNS, "ProcessSucceeded" );
902                } else {
903                    XMLTools.appendElement( statusNode, WPSNS, "ProcessSucceeded", processSucceeded );
904                }
905            }
906    
907            else if ( null != processFailed ) {
908    
909                Element processfailedNode = XMLTools.appendElement( statusNode, WPSNS, "ProcessFailed" );
910    
911                ExceptionReport exceptionReport = processFailed.getExceptionReport();
912                if ( null != exceptionReport ) {
913                    Element execeptionReportNode = XMLTools.appendElement( processfailedNode, OWSNS, "ows:ExceptionReport" );
914                    String version = exceptionReport.getVersion();
915                    if ( null != version && !"".equals( version ) ) {
916                        execeptionReportNode.setAttribute( "version", version );
917                    }
918                    OGCWebServiceException[] ogcWebserviceExceptions = exceptionReport.getExceptions();
919                    int size = ogcWebserviceExceptions.length;
920                    if ( 0 < size ) {
921                        for ( int i = 0; i < size; i++ ) {
922                            appendException( execeptionReportNode, ogcWebserviceExceptions[i] );
923                        }
924                    }
925                }
926            }
927    
928            else if ( null != processAccepted ) {
929    
930                if ( "".equals( processAccepted ) ) {
931                    XMLTools.appendElement( statusNode, WPSNS, "ProcessAccepted" );
932                } else {
933                    XMLTools.appendElement( statusNode, WPSNS, "ProcessAccepted", processAccepted );
934                }
935            }
936    
937            else if ( null != processStarted ) {
938    
939                Element processStartedNode = null;
940                String processStartedMessage = processStarted.getValue();
941                if ( "".equals( processStartedMessage ) ) {
942                    processStartedNode = XMLTools.appendElement( statusNode, WPSNS, "ProcessStarted" );
943                } else {
944                    processStartedNode = XMLTools.appendElement( statusNode, WPSNS, "ProcessStarted", processStartedMessage );
945                }
946                int percentCompleted = processStarted.getPercentCompleted();
947                if ( 0 >= percentCompleted && percentCompleted <= 100 ) {
948                    processStartedNode.setAttribute( "PercentCompleted", String.valueOf( percentCompleted ) );
949                }
950            }
951            
952        }
953    
954        /**
955         * appends a xml representation of an <tt>OGCWebServiceException</tt> to the passed
956         * <tt>Element</tt> Overriding method of superclass because the nodes appended from that
957         * method do not conform with current ows specification
958         * 
959         * @param node
960         * @param ex
961         */
962        protected static void appendException( Element node, OGCWebServiceException ex ) {
963    
964            
965    
966            Element exceptionNode = XMLTools.appendElement( node, OWSNS, "ows:Exception" );
967    
968            if ( null != ex.getCode() ) {
969                exceptionNode.setAttribute( "exceptionCode", ex.getCode().value );
970            }
971            String locator = ex.getLocator();
972            try {
973                if ( null != locator ) {
974                    locator = URLEncoder.encode( locator, CharsetUtils.getSystemCharset() );
975                } else {
976                    locator = "-";
977                }
978            } catch ( UnsupportedEncodingException e ) {
979            }
980            exceptionNode.setAttribute( "locator", locator );
981            
982        }
983    
984        /**
985         * 
986         * @param root
987         * @param executeDataInputs
988         */
989        private static void appendExecuteDataInputs( Element root, ExecuteDataInputs executeDataInputs ) {
990    
991            
992    
993            Map<String, IOValue> inputs = executeDataInputs.getInputs();
994    
995            if ( null != inputs ) {
996    
997                int size = inputs.size();
998    
999                if ( 0 < size ) {
1000    
1001                    Iterator it = inputs.keySet().iterator();
1002    
1003                    Element dataInputsNode = XMLTools.appendElement( root, WPSNS, "DataInputs" );
1004    
1005                    while ( it.hasNext() ) {
1006    
1007                        IOValue ioValue = inputs.get( it.next() );
1008    
1009                        appendInput( dataInputsNode, ioValue );
1010                    }
1011                }
1012            }
1013            
1014        }
1015    
1016        /**
1017         * 
1018         * @param dataInputsNode
1019         * @param ioValue
1020         */
1021        private static void appendInput( Element dataInputsNode, IOValue ioValue ) {
1022    
1023            
1024    
1025            Element inputNode = XMLTools.appendElement( dataInputsNode, WPSNS, "Input" );
1026    
1027            Code identifier = ioValue.getIdentifier();
1028            if ( null != identifier ) {
1029                appendIdentifier( inputNode, identifier );
1030            } else {
1031                LOG.logError( "identifier is null." );
1032            }
1033    
1034            String title = ioValue.getTitle();
1035            if ( null != title ) {
1036                appendTitle( inputNode, title );
1037            } else {
1038                LOG.logError( "title is null." );
1039            }
1040    
1041            String _abstract = ioValue.getAbstract();
1042            if ( null != _abstract ) {
1043                appendAbstract( inputNode, _abstract );
1044            }
1045    
1046            ComplexValue complexValue = ioValue.getComplexValue();
1047            ComplexValueReference complexValueReference = ioValue.getComplexValueReference();
1048            TypedLiteral literalValue = ioValue.getLiteralValue();
1049            Envelope boundingBoxValue = ioValue.getBoundingBoxValue();
1050    
1051            if ( null != complexValue ) {
1052                appendComplexValue( inputNode, complexValue );
1053            } else if ( null != complexValueReference ) {
1054                appendComplexValueReference( inputNode, complexValueReference );
1055            } else if ( null != literalValue ) {
1056                appendLiteralValue( inputNode, literalValue );
1057            } else if ( null != boundingBoxValue ) {
1058                appendBoundingBoxValue( inputNode, boundingBoxValue );
1059            } else {
1060                LOG.logError( "a required input element is missing." );
1061            }
1062            
1063        }
1064    
1065        /**
1066         * 
1067         * @param e
1068         * @param complexValue
1069         */
1070        private static void appendComplexValue( Element e, ComplexValue complexValue ) {
1071            
1072            Element complexValueNode = XMLTools.appendElement( e, WPSNS, "ComplexValue" );
1073    
1074            String format = complexValue.getFormat();
1075            if ( null != format && !"".equals( format ) ) {
1076                complexValueNode.setAttribute( "format", format );
1077            }
1078    
1079            URI encoding = complexValue.getEncoding();
1080            if ( null != encoding ) {
1081                complexValueNode.setAttribute( "encoding", encoding.toString() );
1082            }
1083    
1084            URL schema = complexValue.getSchema();
1085            if ( null != schema ) {
1086                complexValueNode.setAttribute( "schema", schema.toString() );
1087            }
1088    
1089            Object content = complexValue.getContent();
1090    
1091            if ( content instanceof FeatureCollection ) {
1092    
1093                // TODO weird hack! are there better ways to append a
1094                // featurecollection to an element?
1095                FeatureCollection fc = (FeatureCollection) content;
1096                ByteArrayOutputStream bos = new ByteArrayOutputStream();
1097    
1098                try {
1099                    new GMLFeatureAdapter().export( fc, bos );
1100                } catch ( IOException e1 ) {
1101                    LOG.logError( "error exporting featurecollection." );
1102                } catch ( FeatureException e1 ) {
1103                    LOG.logError( "error exporting featurecollection." );
1104                }
1105    
1106                String gmlString = null;
1107                try {
1108                    gmlString = bos.toString( "UTF-8" );
1109                } catch ( UnsupportedEncodingException e1 ) {
1110                }
1111    
1112                XMLFragment xmlFragment = null;
1113                try {
1114                    xmlFragment = new XMLFragment( new StringReader( gmlString ), "http://fluggs-che" );
1115                } catch ( SAXException e1 ) {
1116                    LOG.logError( "error converting featurecollection to xmlfragment." );
1117                } catch ( IOException e1 ) {
1118                    LOG.logError( "error converting featurecollection to xmlfragment." );
1119                }
1120    
1121                Node fcElement = xmlFragment.getRootElement();
1122    
1123                Document owner = complexValueNode.getOwnerDocument();
1124    
1125                complexValueNode.appendChild( owner.importNode( fcElement, true ) );
1126    
1127            } else {
1128                // TODO implement output methods for complex value types other than
1129                // featurecollection
1130            }
1131    
1132            
1133        }
1134    
1135        /**
1136         * 
1137         * @param inputNode
1138         * @param complexValueReference
1139         */
1140        private static void appendComplexValueReference( Element inputNode, ComplexValueReference complexValueReference ) {
1141            
1142    
1143            Element complexValueReferenceNode = XMLTools.appendElement( inputNode, WPSNS, "ComplexValueReference" );
1144    
1145            String format = complexValueReference.getFormat();
1146            if ( null != format && !"".equals( format ) ) {
1147                complexValueReferenceNode.setAttribute( "format", format );
1148            }
1149    
1150            URI encoding = complexValueReference.getEncoding();
1151            if ( null != encoding ) {
1152                complexValueReferenceNode.setAttribute( "encoding", encoding.toString() );
1153            }
1154    
1155            URL schema = complexValueReference.getSchema();
1156            if ( null != schema ) {
1157                complexValueReferenceNode.setAttribute( "schema", schema.toString() );
1158            }
1159    
1160            URL reference = complexValueReference.getReference();
1161            if ( null != reference ) {
1162                complexValueReferenceNode.setAttributeNS( OWSNS.toString(), "ows:reference", reference.toString() );
1163            }
1164    
1165            
1166        }
1167    
1168        /**
1169         * 
1170         * @param inputNode
1171         * @param literalValue
1172         */
1173        private static void appendLiteralValue( Element inputNode, TypedLiteral literalValue ) {
1174    
1175            
1176    
1177            Element literalValueNode = XMLTools.appendElement( inputNode, WPSNS, "LiteralValue" );
1178    
1179            URI dataType = literalValue.getType();
1180            if ( null != dataType ) {
1181                literalValueNode.setAttribute( "dataType", dataType.toString() );
1182            }
1183    
1184            URI uom = literalValue.getUom();
1185            if ( null != uom ) {
1186                literalValueNode.setAttribute( "uom", uom.toString() );
1187            }
1188    
1189            String value = literalValue.getValue();
1190            if ( null != value && !"".equals( value ) ) {
1191                literalValueNode.setTextContent( value );
1192            }
1193    
1194            
1195        }
1196    
1197        /**
1198         * 
1199         * @param inputNode
1200         * @param boundingBoxValue
1201         */
1202        private static void appendBoundingBoxValue( Element inputNode, Envelope boundingBoxValue ) {
1203    
1204            
1205    
1206            Element boundingBoxValueNode = XMLTools.appendElement( inputNode, WPSNS, "BoundingBoxValue" );
1207    
1208            String crs = boundingBoxValue.getCoordinateSystem().getName();
1209            if ( null != crs ) {
1210                boundingBoxValueNode.setAttribute( "crs", crs );
1211            }
1212    
1213            int dimensions = boundingBoxValue.getCoordinateSystem().getDimension();
1214            if ( 0 != dimensions ) {
1215                boundingBoxValueNode.setAttribute( "dimensions", String.valueOf( dimensions ) );
1216            }
1217    
1218            Position positionMin = boundingBoxValue.getMin();
1219            if ( null != positionMin ) {
1220                XMLTools.appendElement( boundingBoxValueNode, OWSNS, "ows:LowerCorner",
1221                                        String.valueOf( positionMin.getX() ) + " " + String.valueOf( positionMin.getY() ) );
1222            }
1223    
1224            Position positionMax = boundingBoxValue.getMax();
1225            if ( null != positionMax ) {
1226                XMLTools.appendElement( boundingBoxValueNode, OWSNS, "ows:UpperCorner",
1227                                        String.valueOf( positionMax.getX() ) + " " + String.valueOf( positionMax.getY() ) );
1228            }
1229            
1230        }
1231    
1232        /**
1233         * 
1234         * @param root
1235         * @param outputDefintions
1236         */
1237        private static void appendOutputDefinitions( Element root, OutputDefinitions outputDefintions ) {
1238    
1239            
1240    
1241            Element outputDefinitionsNode = XMLTools.appendElement( root, WPSNS, "OutputDefinitions" );
1242    
1243            List<OutputDefinition> outputDefinitionsList = outputDefintions.getOutputDefinitions();
1244    
1245            if ( null != outputDefinitionsList ) {
1246    
1247                int size = outputDefinitionsList.size();
1248    
1249                if ( 0 < size ) {
1250                    for ( int i = 0; i < outputDefinitionsList.size(); i++ ) {
1251    
1252                        appendOutputDefinition( outputDefinitionsNode, outputDefinitionsList.get( i ) );
1253    
1254                    }
1255                }
1256            }
1257            
1258        }
1259    
1260        /**
1261         * 
1262         * @param outputDefinitionsNode
1263         * @param outputDefinition
1264         */
1265        private static void appendOutputDefinition( Element outputDefinitionsNode, OutputDefinition outputDefinition ) {
1266    
1267            
1268    
1269            Element outputNode = XMLTools.appendElement( outputDefinitionsNode, WPSNS, "Output" );
1270    
1271            String format = outputDefinition.getFormat();
1272            if ( null != format && !"".equals( format ) ) {
1273                outputNode.setAttribute( "format", format );
1274            }
1275    
1276            URI encoding = outputDefinition.getEncoding();
1277            if ( null != encoding ) {
1278                outputNode.setAttribute( "encoding", encoding.toString() );
1279            }
1280    
1281            URL schema = outputDefinition.getSchema();
1282            if ( null != schema ) {
1283                outputNode.setAttribute( "schema", schema.toString() );
1284            }
1285    
1286            URI uom = outputDefinition.getUom();
1287            if ( null != uom ) {
1288                outputNode.setAttribute( "uom", uom.toString() );
1289            }
1290    
1291            Code identifier = outputDefinition.getIdentifier();
1292            if ( null != identifier ) {
1293                appendIdentifier( outputNode, identifier );
1294            } else {
1295                LOG.logError( "identifier is null." );
1296            }
1297    
1298            String title = outputDefinition.getTitle();
1299            if ( null != title ) {
1300                appendTitle( outputNode, title );
1301            } else {
1302                LOG.logError( "title is null." );
1303            }
1304    
1305            String _abstract = outputDefinition.getAbstract();
1306            if ( null != _abstract ) {
1307                appendAbstract( outputNode, _abstract );
1308            }
1309            
1310        }
1311    
1312        /**
1313         * 
1314         * @param root
1315         * @param processOutputs
1316         */
1317        private static void appendExecuteProcessOutputs( Element root, ExecuteResponse.ProcessOutputs processOutputs ) {
1318    
1319            
1320    
1321            Element processOutputsNode = XMLTools.appendElement( root, WPSNS, "ProcessOutputs" );
1322    
1323            List<IOValue> processOutputsList = processOutputs.getOutputs();
1324            if ( null != processOutputsList ) {
1325    
1326                int size = processOutputsList.size();
1327                if ( 0 < size ) {
1328    
1329                    for ( int i = 0; i < size; i++ ) {
1330                        appendExecuteProcessOutput( processOutputsNode, processOutputsList.get( i ) );
1331                    }
1332                }
1333            }
1334            
1335        }
1336    
1337        /**
1338         * 
1339         * @param root
1340         * @param processOutputs
1341         */
1342        private static void appendExecuteProcessOutput( Element processOutputsNode, IOValue processOutput ) {
1343    
1344            
1345    
1346            Element outputNode = XMLTools.appendElement( processOutputsNode, WPSNS, "Output" );
1347    
1348            Code identifier = processOutput.getIdentifier();
1349            if ( null != identifier ) {
1350                appendIdentifier( outputNode, identifier );
1351            } else {
1352                LOG.logError( "identifier is null." );
1353            }
1354    
1355            String title = processOutput.getTitle();
1356            if ( null != title ) {
1357                appendTitle( outputNode, title );
1358            } else {
1359                LOG.logError( "title is null." );
1360            }
1361    
1362            String _abstract = processOutput.getAbstract();
1363            if ( null != _abstract ) {
1364                appendAbstract( outputNode, _abstract );
1365            }
1366    
1367            ComplexValue complexValue = processOutput.getComplexValue();
1368            ComplexValueReference complexValueReference = processOutput.getComplexValueReference();
1369            TypedLiteral literalValue = processOutput.getLiteralValue();
1370            Envelope boundingBoxValue = processOutput.getBoundingBoxValue();
1371    
1372            if ( null != complexValue ) {
1373                appendComplexValue( outputNode, complexValue );
1374            } else if ( null != complexValueReference ) {
1375                appendComplexValueReference( outputNode, complexValueReference );
1376            } else if ( null != literalValue ) {
1377                appendLiteralValue( outputNode, literalValue );
1378            } else if ( null != boundingBoxValue ) {
1379                appendBoundingBoxValue( outputNode, boundingBoxValue );
1380            } else {
1381                LOG.logError( "a required output element is missing." );
1382            }
1383            
1384        }
1385    
1386    }