001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wps/describeprocess/ProcessDescriptionDocument.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.describeprocess;
044    
045    import static org.deegree.ogcbase.CommonNamespaces.OWSNS;
046    
047    import java.net.URI;
048    import java.net.URISyntaxException;
049    import java.util.ArrayList;
050    import java.util.List;
051    
052    import org.deegree.datatypes.Code;
053    import org.deegree.datatypes.values.Closure;
054    import org.deegree.datatypes.values.TypedLiteral;
055    import org.deegree.datatypes.values.ValueRange;
056    import org.deegree.datatypes.xlink.SimpleLink;
057    import org.deegree.framework.xml.XMLFragment;
058    import org.deegree.framework.xml.XMLParsingException;
059    import org.deegree.framework.xml.XMLTools;
060    import org.deegree.ogcwebservices.MetadataType;
061    import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.DataInputs;
062    import org.deegree.ogcwebservices.wps.describeprocess.ProcessDescription.ProcessOutputs;
063    import org.deegree.owscommon.OWSMetadata;
064    import org.deegree.owscommon.com110.OWSAllowedValues;
065    import org.w3c.dom.Element;
066    
067    /**
068     * ProcessDescriptionDocument.java
069     * 
070     * Created on 10.03.2006. 15:18:02h
071     * 
072     * @author <a href="mailto:christian@kiehle.org">Christian Kiehle</a>
073     * @author <a href="mailto:christian.heier@gmx.de">Christian Heier</a>
074     * 
075     * @version 1.0.
076     * 
077     * @since 2.0
078     */
079    
080    public class ProcessDescriptionDocument extends XMLFragment {
081    
082        /**
083         * 
084         * @return
085         * @throws XMLParsingException
086         */
087    
088        @SuppressWarnings("unchecked")
089        public ProcessDescription parseProcessDescription()
090                                throws XMLParsingException {
091    
092            Element root = getRootElement();
093    
094            Element processDescriptionNode = (Element) XMLTools.getRequiredNode( root, "wps:ProcessDescription", nsContext );
095    
096            String responsibleClass = getResponsibleClass( processDescriptionNode );
097    
098            Code identifier = getIdentifier( processDescriptionNode );
099    
100            String title = getTitle( processDescriptionNode );
101    
102            String _abstract = getAbstract( processDescriptionNode );
103    
104            List<MetadataType> metadataTypeList = getMetadata( processDescriptionNode );
105    
106            DataInputs dataInputs = null;
107    
108            ProcessOutputs processOutputs = null;
109    
110            // Get optional attribute "processVersion" from <wps:ProcessDescription>
111            // node
112            String processVersion = null;
113            String versionAttribute = processDescriptionNode.getAttribute( "processVersion" );
114            if ( null != versionAttribute && !"".equals( versionAttribute ) ) {
115                processVersion = versionAttribute;
116            }
117    
118            // Get optional attribute "storeSupported" from <wps:ProcessDescription>
119            // node
120            boolean storeSupported = false;
121            String storeSupportedAttribute = processDescriptionNode.getAttribute( "storeSupported" );
122            if ( null != storeSupportedAttribute && !"".equals( storeSupportedAttribute ) ) {
123                storeSupported = Boolean.valueOf( storeSupportedAttribute );
124            }
125    
126            // Get optional attribute "statusSupported" from
127            // <wps:ProcessDescription> node
128            boolean statusSupported = false;
129            String statusSupportedAttribute = processDescriptionNode.getAttribute( "statusSupported" );
130            if ( null != statusSupportedAttribute && !"".equals( statusSupportedAttribute ) ) {
131                statusSupported = Boolean.valueOf( statusSupportedAttribute );
132            }
133    
134            // Get optional node <wps:DataInputs> from <wps:ProcessDescription> node
135    
136            Element dataInputsNode = (Element) XMLTools.getRequiredNode( processDescriptionNode, "wps:DataInputs",
137                                                                         nsContext );
138    
139            if ( null != dataInputsNode ) {
140    
141                List inputNodesList = XMLTools.getNodes( dataInputsNode, "wps:Input", nsContext );
142    
143                if ( null != inputNodesList && 0 != inputNodesList.size() ) {
144    
145                    int size = inputNodesList.size();
146                    dataInputs = new DataInputs();
147                    List inputDescriptions = new ArrayList<InputDescription>( size );
148                    for ( int i = 0; i < size; i++ ) {
149    
150                        inputDescriptions.add( i, getInputDescription( (Element) inputNodesList.get( i ) ) );
151                    }
152                    dataInputs.setInputDescriptions( inputDescriptions );
153                }
154            }
155    
156            // Get mandatory node <wps:ProcessOutputs> from <wps:ProcessDescription>
157            // node.
158    
159            Element processOutputsNode = (Element) XMLTools.getRequiredNode( processDescriptionNode, "wps:ProcessOutputs",
160                                                                             nsContext );
161    
162            List outputNodesList = XMLTools.getRequiredNodes( processOutputsNode, "wps:Output", nsContext );
163            int size = outputNodesList.size();
164            processOutputs = new ProcessOutputs();
165            processOutputs.output = new ArrayList<OutputDescription>( size );
166            for ( int i = 0; i < size; i++ ) {
167    
168                processOutputs.output.add( i, getOutputDescription( (Element) outputNodesList.get( i ) ) );
169            }
170    
171            return new ProcessDescription( responsibleClass, identifier, title, _abstract, processVersion,
172                                           metadataTypeList, dataInputs, processOutputs, statusSupported, storeSupported );
173    
174        }
175    
176        private String getResponsibleClass( Element processDescriptionNode )
177                                throws XMLParsingException {
178    
179            // Get resonsible class for process execution from deegreeParams section
180            String responsibleClass = null;
181            Element deegreeParamsNode = (Element) XMLTools.getRequiredNode( processDescriptionNode,
182                                                                            "deegreewps:deegreeParams", nsContext );
183            responsibleClass = XMLTools.getRequiredNodeAsString( deegreeParamsNode, "deegreewps:responsibleClass/text()",
184                                                                 nsContext );
185    
186            return responsibleClass;
187        }
188    
189        /**
190         * @param processDescriptionNode
191         * @throws XMLParsingException
192         */
193        private List<MetadataType> getMetadata( Element e )
194                                throws XMLParsingException {
195            List<MetadataType> metadataTypeList = null;
196    
197            // Get optional nodes <ows:Metadata>
198            List metadataTypeNodes = XMLTools.getNodes( e, "ows:Metadata", nsContext );
199            if ( null != metadataTypeNodes && 0 != metadataTypeNodes.size() ) {
200                int size = metadataTypeNodes.size();
201                metadataTypeList = new ArrayList<MetadataType>( size );
202                for ( int i = 0; i < size; i++ ) {
203                    metadataTypeList.add( i, getMetadataType( (Element) metadataTypeNodes.get( i ) ) );
204                }
205            }
206            return metadataTypeList;
207        }
208    
209        /**
210         * @param processDescriptionNode
211         * @throws XMLParsingException
212         */
213        private String getAbstract( Element e )
214                                throws XMLParsingException {
215            String _abstract = null;
216    
217            // Get optional node <ows:Abstract>
218            String owsAbstract = XMLTools.getNodeAsString( e, "ows:Abstract/text()", nsContext, null );
219            if ( null != owsAbstract && !"".equals( owsAbstract ) ) {
220                _abstract = owsAbstract;
221            }
222            return _abstract;
223        }
224    
225        /**
226         * @param processDescriptionNode
227         * @throws XMLParsingException
228         */
229        private String getTitle( Element e )
230                                throws XMLParsingException {
231            // Get required node <ows:Title>
232            return XMLTools.getRequiredNodeAsString( e, "ows:Title/text()", nsContext );
233        }
234    
235        /**
236         * @param processDescriptionNode
237         * @throws XMLParsingException
238         */
239        private Code getIdentifier( Element e )
240                                throws XMLParsingException {
241            // Get required node <ows:Identifier>
242            String identifierAsString = XMLTools.getRequiredNodeAsString( e, "ows:Identifier/text()", nsContext );
243            return new Code( identifierAsString, null );
244        }
245    
246        /**
247         * Creates an object representation of a <code>ows:Metadata</code> section.
248         * 
249         * @param metadataTypeNode
250         * @return object representation of the <code>ows:Metadata</code> section
251         */
252        private MetadataType getMetadataType( Element metadataTypeNode ) {
253    
254            // FIXME MetadataType contained in Deegree does not correspond with
255            // current OWS MetadataType definition
256            MetadataType metadataType = null;
257    
258            // Only attribute xlink:title supported by now, e.g. <ows:Metadata
259            // xlink:title="buffer"/>
260            String title = metadataTypeNode.getAttributeNS( XLNNS.toString(), "title" );
261    
262            if ( null != title && !"".equals( title ) ) {
263                metadataType = new MetadataType();
264                metadataType.value = title;
265            }
266    
267            return metadataType;
268        }
269    
270        private InputDescription getInputDescription( Element inputDescriptionNode )
271                                throws XMLParsingException {
272    
273            Code identifier = getIdentifier( inputDescriptionNode );
274    
275            String title = getTitle( inputDescriptionNode );
276    
277            String _abstract = getAbstract( inputDescriptionNode );
278    
279            ComplexData complexData = null;
280    
281            LiteralInput literalData = null;
282    
283            SupportedCRSs boundingBoxData = null;
284    
285            Element boundingBoxDataNode = (Element) XMLTools.getNode( inputDescriptionNode, "wps:BoundingBoxData",
286                                                                      nsContext );
287    
288            Element complexDataNode = (Element) XMLTools.getNode( inputDescriptionNode, "wps:ComplexData", nsContext );
289    
290            Element literalDataNode = (Element) XMLTools.getNode( inputDescriptionNode, "wps:LiteralData", nsContext );
291    
292            if ( null == boundingBoxDataNode && null == complexDataNode && null == literalDataNode ) {
293                throw new XMLParsingException( "A required data type is missing!" );
294            }
295    
296            if ( null != boundingBoxDataNode && null == complexDataNode && null == literalDataNode ) {
297                boundingBoxData = getSupportedCRSsType( boundingBoxDataNode );
298            }
299            if ( null == boundingBoxDataNode && null != complexDataNode && null == literalDataNode ) {
300                complexData = getComplexDataType( complexDataNode );
301            }
302            if ( null == boundingBoxDataNode && null == complexDataNode && null != literalDataNode ) {
303                literalData = getLiteralInputType( literalDataNode );
304    
305            }
306            int occurs = XMLTools.getNodeAsInt( inputDescriptionNode, "wps:MinimumOccurs/text()", nsContext, 1 );
307    
308            return new InputDescription( identifier, title, _abstract, boundingBoxData, complexData, literalData, occurs );
309        }
310    
311        @SuppressWarnings("unchecked")
312        private SupportedCRSs getSupportedCRSsType( Element boundingBoxDataNode )
313                                throws XMLParsingException {
314    
315            List<URI> crsList = null;
316    
317            // Get required nodes <wps:CRS>
318            List<Element> crsNodes = XMLTools.getRequiredElements( boundingBoxDataNode, "wps:CRS", nsContext );
319            if ( null != crsNodes && 0 != crsNodes.size() ) {
320                int size = crsNodes.size();
321                crsList = new ArrayList<URI>( size );
322                for ( int i = 0; i < size; i++ ) {
323    
324                    String crs = XMLTools.getNodeAsString( crsNodes.get( i ), "/text()", nsContext, null );
325    
326                    crsList.add( i, buildURIFromString( crs ) );
327                }
328            }
329    
330            // Get required attribute "defaultCRS" from node <wps:BoundingBoxData>
331            URI defaultCRS = buildURIFromString( boundingBoxDataNode.getAttribute( "defaultCRS" ) );
332    
333            return new SupportedCRSs( crsList, defaultCRS );
334    
335        }
336    
337        /**
338         * @param complexDataNode
339         * @return
340         * @throws XMLParsingException
341         */
342        private ComplexData getComplexDataType( Element complexDataNode )
343                                throws XMLParsingException {
344            String defaultEncoding = null;
345            String defaultFormat = null;
346            String defaultSchema = null;
347            List<SupportedComplexData> supportedComplexDataList = null;
348    
349            // Get optional attribute "defaultFormat" from <wps:ComplexData> node
350            String defaultFormatAttribute = complexDataNode.getAttribute( "defaultFormat" );
351            if ( null != defaultFormatAttribute && !"".equals( defaultFormatAttribute ) ) {
352                defaultFormat = defaultFormatAttribute;
353            }
354    
355            // Get optional attribute "defaultEncoding" from <wps:ComplexData> node
356            String defaultEncodingAttribute = complexDataNode.getAttribute( "defaultEncoding" );
357            if ( null != defaultEncodingAttribute && !"".equals( defaultEncodingAttribute ) ) {
358                defaultEncoding = defaultEncodingAttribute;
359            }
360    
361            // Get optional attribute "defaultSchema" from <wps:ComplexData> node
362            String defaultSchemaAttribute = complexDataNode.getAttribute( "defaultSchema" );
363            if ( null != defaultSchemaAttribute && !"".equals( defaultSchemaAttribute ) ) {
364                defaultSchema = defaultSchemaAttribute;
365            }
366    
367            List supportedComplexDataNodes = XMLTools.getNodes( complexDataNode, "wps:SupportedComplexData", nsContext );
368            if ( null != supportedComplexDataNodes && 0 != supportedComplexDataNodes.size() ) {
369                int size = supportedComplexDataNodes.size();
370                supportedComplexDataList = new ArrayList<SupportedComplexData>( size );
371                for ( int i = 0; i < size; i++ ) {
372                    supportedComplexDataList.add( i, getSupportedComplexData( (Element) supportedComplexDataNodes.get( i ) ) );
373                }
374            }
375    
376            return new ComplexData( defaultEncoding, defaultFormat, defaultSchema, supportedComplexDataList );
377        }
378    
379        /**
380         * @param element
381         * @return
382         * @throws XMLParsingException
383         */
384        private SupportedComplexData getSupportedComplexData( Element supportedComplexDataNode )
385                                throws XMLParsingException {
386            String encoding = null;
387            String format = null;
388            String schema = null;
389    
390            // Get optional node <wps:Encoding>
391            String wpsEncoding = XMLTools.getNodeAsString( supportedComplexDataNode, "wps:Encoding/text()", nsContext, null );
392            if ( null != wpsEncoding && !"".equals( wpsEncoding ) ) {
393                encoding = wpsEncoding;
394            }
395    
396            // Get optional node <wps:Format>
397            String wpsFormat = XMLTools.getNodeAsString( supportedComplexDataNode, "wps:Format/text()", nsContext, null );
398            if ( null != wpsFormat && !"".equals( wpsFormat ) ) {
399                format = wpsFormat;
400            }
401    
402            // Get optional node <wps:Schema>
403            String wpsSchema = XMLTools.getNodeAsString( supportedComplexDataNode, "wps:Schema/text()", nsContext, null );
404            if ( null != wpsSchema && !"".equals( wpsSchema ) ) {
405                schema = wpsSchema;
406            }
407            return new SupportedComplexData( encoding, format, schema );
408        }
409    
410        /**
411         * @return
412         */
413        private LiteralInput getLiteralInputType( Element literalDataNode )
414                                throws XMLParsingException {
415            OWSMetadata domainMetadataType = null;
416            SupportedUOMs supportedUOMsType = null;
417            OWSAllowedValues allowedValues = null;
418            boolean anyValueAllowed = false;
419            ValueRange defaultValue = null;
420            OWSMetadata valuesReference = null;
421    
422            // Get optional node <ows:DataType>
423            Element dataTypeNode = (Element) XMLTools.getNode( literalDataNode, "ows:DataType", nsContext );
424            if ( null != dataTypeNode ) {
425                domainMetadataType = getDomainMetadataTypeFromContent( dataTypeNode );
426            }
427    
428            // Get optional node <wps:SupportedUOMs>
429            Element supportedUOMsNode = (Element) XMLTools.getNode( literalDataNode, "wps:SupportedUOMs", nsContext );
430            if ( null != supportedUOMsNode ) {
431                supportedUOMsType = getSupportedUOMs( supportedUOMsNode );
432            }
433    
434            // Get optional node <wps:AllowedValues>
435            Element allowedValuesNode = (Element) XMLTools.getNode( literalDataNode, "ows:AllowedValues", nsContext );
436            // Get optional node <wps:AnyValue>
437            Element anyValueNode = (Element) XMLTools.getNode( literalDataNode, "ows:AnyValue", nsContext );
438            // Get optional node <wps:ValuesReference>
439            Element valuesReferenceNode = (Element) XMLTools.getNode( literalDataNode, "ows:ValuesReference", nsContext );
440    
441            if ( null != allowedValuesNode && null == anyValueNode && null == valuesReferenceNode ) {
442                allowedValues = getOWSAllowedValues( allowedValuesNode );
443            } else if ( null == allowedValuesNode && null != anyValueNode && null == valuesReferenceNode ) {
444                anyValueAllowed = true;
445            } else if ( null == allowedValuesNode && null == anyValueNode && null != valuesReferenceNode ) {
446                String reference = valuesReferenceNode.getAttributeNS( OWSNS.toString(), "reference" );
447                String value = XMLTools.getNodeAsString( valuesReferenceNode, "/text()", nsContext, null );
448                if ( null != value ) {
449                    URI referenceURI = buildURIFromString( reference );
450                    valuesReference = new OWSMetadata( null, new SimpleLink( referenceURI ), value );
451                }
452            } else {
453                throw new XMLParsingException( "A required data type is missing!" );
454            }
455    
456            // Get optional node <wps:DefaultValue>
457            Element defaultValueNode = (Element) XMLTools.getNode( literalDataNode, "ows:DefaultValue", nsContext );
458            if ( null != defaultValueNode ) {
459                defaultValue = getOwsRange( defaultValueNode );
460            }
461    
462            return new LiteralInput( domainMetadataType, supportedUOMsType, allowedValues, anyValueAllowed, defaultValue,
463                                     valuesReference );
464        }
465    
466        private URI buildURIFromString( String reference )
467                                throws XMLParsingException {
468            URI referenceURI = null;
469            try {
470                referenceURI = new URI( reference );
471            } catch ( URISyntaxException e ) {
472                String msg = "The URI syntax is malformed. " + e.getMessage();
473                LOG.logError( msg );
474                throw new XMLParsingException( msg, e );
475            }
476            return referenceURI;
477        }
478    
479        private SupportedUOMs getSupportedUOMs( Element supportedUOMsNode )
480                                throws XMLParsingException {
481            List uomNodesList = XMLTools.getNodes( supportedUOMsNode, "ows:UOM", nsContext );
482    
483            List<OWSMetadata> domainMetadataTypeList = null;
484            if ( null != uomNodesList && 0 != uomNodesList.size() ) {
485                int uomNodesListSize = uomNodesList.size();
486                domainMetadataTypeList = new ArrayList<OWSMetadata>( uomNodesListSize );
487                for ( int i = 0; i < uomNodesListSize; i++ ) {
488                    Element nodeListElement = (Element) uomNodesList.get( i );
489    
490                    domainMetadataTypeList.add( i, getDomainMetadataTypeFromAttribute( nodeListElement ) );
491                }
492            }
493            String defaultuom = supportedUOMsNode.getAttribute( "defaultUOM" );
494            URI defaultUOMURI = buildURIFromString( defaultuom );
495            OWSMetadata defaultUOMObject = new OWSMetadata( null, new SimpleLink( defaultUOMURI ), null );
496    
497            return new SupportedUOMs( defaultUOMObject, domainMetadataTypeList );
498        }
499    
500        private OWSMetadata getDomainMetadataTypeFromContent( Element e )
501                                throws XMLParsingException {
502            String owsDataType = XMLTools.getNodeAsString( e, "/text()", nsContext, null );
503            String reference = e.getAttributeNS( OWSNS.toString(), "reference" );
504            URI referenceURI = buildURIFromString( reference );
505            return new OWSMetadata( null, new SimpleLink( referenceURI ), owsDataType );
506        }
507    
508        private OWSMetadata getDomainMetadataTypeFromAttribute( Element e )
509                                throws XMLParsingException {
510            String reference = e.getAttributeNS( OWSNS.toString(), "reference" );
511            URI referenceURI = buildURIFromString( reference );
512    
513            return new OWSMetadata( null, new SimpleLink( referenceURI ), null );
514        }
515    
516        @SuppressWarnings("unchecked")
517        private OWSAllowedValues getOWSAllowedValues( Element e )
518                                throws XMLParsingException {
519            TypedLiteral[] owsValues = null;
520            ValueRange[] valueRanges = null;
521    
522            // gets a Node list of type ows:Value
523            List owsValueNodeList = XMLTools.getNodes( e, "ows:Value", nsContext );
524    
525            if ( null != owsValueNodeList && 0 != owsValueNodeList.size() ) {
526                int size = owsValueNodeList.size();
527                owsValues = new TypedLiteral[size];
528                for ( int i = 0; i < size; i++ ) {
529                    owsValues[i] = ( getOwsValue( (Element) owsValueNodeList.get( i ) ) );
530                }
531            }
532    
533            List owsRangeNodeList = XMLTools.getNodes( e, "ows:Range", nsContext );
534    
535            if ( null != owsRangeNodeList && 0 != owsRangeNodeList.size() ) {
536                int size = owsRangeNodeList.size();
537                valueRanges = new ValueRange[size];
538                for ( int i = 0; i < size; i++ ) {
539                    valueRanges[i] = ( getOwsRange( (Element) owsRangeNodeList.get( i ) ) );
540                }
541            }
542    
543            return new OWSAllowedValues( owsValues, valueRanges );
544        }
545    
546        /**
547         * @param element
548         * @return
549         * @throws XMLParsingException
550         */
551        private ValueRange getOwsRange( Element element )
552                                throws XMLParsingException {
553    
554            TypedLiteral maximum = getOwsValue( (Element) XMLTools.getNode( element, "ows:MaximumValue", nsContext ) );
555    
556            TypedLiteral minimum = getOwsValue( (Element) XMLTools.getNode( element, "ows:MinimumValue", nsContext ) );
557    
558            Closure rangeClosure = null;
559    
560            String rangeClosureAttribute = element.getAttributeNS( OWSNS.toString(), "rangeClosure" );
561            if ( "closed".equalsIgnoreCase( rangeClosureAttribute ) ) {
562                rangeClosure = new Closure( Closure.CLOSED );
563            } else if ( "open".equalsIgnoreCase( rangeClosureAttribute ) ) {
564                rangeClosure = new Closure( Closure.OPENED );
565            } else if ( "closed-open".equalsIgnoreCase( rangeClosureAttribute ) ) {
566                rangeClosure = new Closure( Closure.CLOSED_OPENED );
567            } else if ( "open-closed".equalsIgnoreCase( rangeClosureAttribute ) ) {
568                rangeClosure = new Closure( Closure.OPENED_CLOSED );
569            } else {
570                throw new XMLParsingException( "Attribute range closure contains invalid value." );
571            }
572    
573            TypedLiteral spacing = null;
574    
575            Element spacingNode = (Element) XMLTools.getNode( element, "ows:Spacing", nsContext );
576            if ( null != spacingNode ) {
577                spacing = getOwsValue( spacingNode );
578            }
579    
580            return new ValueRange( minimum, maximum, spacing, null, null, false, rangeClosure );
581        }
582    
583        /**
584         * @param element
585         * @return
586         * @throws XMLParsingException
587         */
588        private TypedLiteral getOwsValue( Element element )
589                                throws XMLParsingException {
590            String value = XMLTools.getNodeAsString( element, "/text()", nsContext, null );
591            return new TypedLiteral( value, null );
592        }
593    
594        /**
595         * @param element
596         * @return
597         * @throws XMLParsingException
598         */
599        private OutputDescription getOutputDescription( Element outputDescriptionNode )
600                                throws XMLParsingException {
601            Code identifier = getIdentifier( outputDescriptionNode );
602    
603            String title = getTitle( outputDescriptionNode );
604    
605            String _abstract = getAbstract( outputDescriptionNode );
606    
607            Element boundingBoxOutputNode = (Element) XMLTools.getNode( outputDescriptionNode, "wps:BoundingBoxOutput",
608                                                                        nsContext );
609            Element complexOutputNode = (Element) XMLTools.getNode( outputDescriptionNode, "wps:ComplexOutput", nsContext );
610            Element literalOutputNode = (Element) XMLTools.getNode( outputDescriptionNode, "wps:LiteralOutput", nsContext );
611    
612            SupportedCRSs boundingBoxOutput = null;
613            ComplexData complexOutput = null;
614            LiteralOutput literalOutput = null;
615    
616            if ( null != boundingBoxOutputNode && null == complexOutputNode && null == literalOutputNode ) {
617                boundingBoxOutput = getSupportedCRSsType( boundingBoxOutputNode );
618            } else if ( null == boundingBoxOutputNode && null != complexOutputNode && null == literalOutputNode ) {
619                complexOutput = getComplexDataType( complexOutputNode );
620            } else if ( null == boundingBoxOutputNode && null == complexOutputNode && null != literalOutputNode ) {
621                Element dataTypeNode = (Element) XMLTools.getNode( literalOutputNode, "ows:DataType", nsContext );
622                OWSMetadata domainMetadataType = getDomainMetadataTypeFromContent( dataTypeNode );
623                Element supportedUOMsNode = (Element) XMLTools.getNode( literalOutputNode, "wps:SupportedUOMs", nsContext );
624                SupportedUOMs supportedUOMsType = null;
625                if ( null != supportedUOMsNode ) {
626                    supportedUOMsType = getSupportedUOMs( supportedUOMsNode );
627                }
628                literalOutput = new LiteralOutput( domainMetadataType, supportedUOMsType );
629            } else {
630                throw new XMLParsingException( "A required data type is missing!" );
631            }
632    
633            return new OutputDescription( identifier, title, _abstract, boundingBoxOutput, complexOutput, literalOutput );
634        }
635    
636    }