001    // $HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcwebservices/wcs/describecoverage/CoverageDescriptionDocument.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.ogcwebservices.wcs.describecoverage;
037    
038    import java.io.IOException;
039    import java.net.MalformedURLException;
040    import java.net.URI;
041    import java.net.URISyntaxException;
042    import java.net.URL;
043    
044    import org.deegree.datatypes.Code;
045    import org.deegree.datatypes.CodeList;
046    import org.deegree.datatypes.time.TimeSequence;
047    import org.deegree.datatypes.values.Values;
048    import org.deegree.framework.util.StringTools;
049    import org.deegree.framework.xml.ElementList;
050    import org.deegree.framework.xml.XMLParsingException;
051    import org.deegree.framework.xml.XMLTools;
052    import org.deegree.model.crs.UnknownCRSException;
053    import org.deegree.model.metadata.iso19115.Keywords;
054    import org.deegree.model.spatialschema.Envelope;
055    import org.deegree.ogcbase.CommonNamespaces;
056    import org.deegree.ogcbase.GMLDocument;
057    import org.deegree.ogcbase.InvalidGMLException;
058    import org.deegree.ogcbase.OGCDocument;
059    import org.deegree.ogcbase.OGCException;
060    import org.deegree.ogcwebservices.LonLatEnvelope;
061    import org.deegree.ogcwebservices.MetadataLink;
062    import org.deegree.ogcwebservices.MetadataType;
063    import org.deegree.ogcwebservices.OGCWebServiceException;
064    import org.deegree.ogcwebservices.SupportedFormats;
065    import org.deegree.ogcwebservices.SupportedSRSs;
066    import org.deegree.ogcwebservices.wcs.InterpolationMethod;
067    import org.deegree.ogcwebservices.wcs.SupportedInterpolations;
068    import org.deegree.ogcwebservices.wcs.WCSException;
069    import org.deegree.ogcwebservices.wcs.configuration.Extension;
070    import org.deegree.ogcwebservices.wcs.configuration.ExtensionDocument;
071    import org.w3c.dom.Element;
072    import org.xml.sax.SAXException;
073    
074    /**
075     * <ul>
076     * <li> usage of srsName from gml:Envelope is not supoorted yet. deegree Envelope doesn't uses CRSs
077     * <li> gml:Grid and gml:Polygon is not yet supported by the deegree WCS
078     * </ul>
079     *
080     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
081     * @author last edited by: $Author: mschneider $
082     *
083     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
084     */
085    public class CoverageDescriptionDocument extends OGCDocument {
086    
087        public static final String XML_TEMPLATE = "CoverageDescriptionTemplate.xml";
088    
089        private static URI WCSNS = CommonNamespaces.WCSNS;
090    
091        private static URI GMLNS = CommonNamespaces.GMLNS;
092    
093        private static URI DGRNS = CommonNamespaces.DEEGREEWCS;
094    
095        /**
096         * @throws IOException
097         * @throws SAXException
098         * @see "org.deegree.framework.xml.XMLFragment#createEmptyDocument()"
099         */
100        public void createEmptyDocument()
101                                throws IOException, SAXException {
102            URL url = CoverageDescriptionDocument.class.getResource( XML_TEMPLATE );
103            if ( url == null ) {
104                throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." );
105            }
106            load( url );
107        }
108    
109        /**
110         * returns the version of the CoverageDescription
111         *
112         * @return the version of the CoverageDescription
113         * @throws InvalidCoverageDescriptionExcpetion
114         */
115        public String getVersion()
116                                throws InvalidCoverageDescriptionExcpetion {
117            try {
118                return XMLTools.getRequiredAttrValue( "version", null, getRootElement() );
119            } catch ( XMLParsingException e ) {
120                String s = e.getMessage() + "\n" + StringTools.stackTraceToString( e );
121                throw new InvalidCoverageDescriptionExcpetion( s );
122            }
123        }
124    
125        /**
126         * creates a <tt>CoverageDescription</tt> instance from the DOM document encapsulated by this
127         * class
128         *
129         * @return created <tt>CoverageDescription</tt> instance
130         * @throws InvalidCoverageDescriptionExcpetion
131         * @throws UnknownCRSException
132         */
133        public CoverageOffering[] getCoverageOfferings()
134                                throws InvalidCoverageDescriptionExcpetion, UnknownCRSException {
135    
136            try {
137                ElementList el = XMLTools.getChildElements( "CoverageOffering", WCSNS, getRootElement() );
138                CoverageOffering[] co = getCoverageOfferings( el );
139                return co;
140            } catch ( XMLParsingException e ) {
141                String s = e.getMessage() + "\n" + StringTools.stackTraceToString( e );
142                throw new InvalidCoverageDescriptionExcpetion( s );
143            } catch ( WCSException e ) {
144                String s = e.getMessage() + "\n" + StringTools.stackTraceToString( e );
145                throw new InvalidCoverageDescriptionExcpetion( s );
146            } catch ( OGCException e ) {
147                String s = e.getMessage() + "\n" + StringTools.stackTraceToString( e );
148                throw new InvalidCoverageDescriptionExcpetion( s );
149            }
150    
151        }
152    
153        /**
154         * creates an array of <tt>CoverageOffering</tt> objects contained in the enclosing
155         * CoverageDescrption element.
156         *
157         * @param el
158         *            list of CoverageOffering elements
159         * @return array of <tt>CoverageOffering</tt> objects
160         * @throws XMLParsingException
161         * @throws UnknownCRSException
162         */
163        private CoverageOffering[] getCoverageOfferings( ElementList el )
164                                throws XMLParsingException, WCSException, OGCException, UnknownCRSException {
165            CoverageOffering[] co = new CoverageOffering[el.getLength()];
166    
167            for ( int i = 0; i < co.length; i++ ) {
168                co[i] = getCoverageOffering( el.item( i ) );
169            }
170    
171            return co;
172        }
173    
174        /**
175         * @param element
176         * @return
177         * @throws XMLParsingException
178         * @throws UnknownCRSException
179         */
180        private CoverageOffering getCoverageOffering( Element element )
181                                throws XMLParsingException, WCSException, OGCException, UnknownCRSException {
182    
183            String name = XMLTools.getRequiredStringValue( "name", WCSNS, element );
184            String label = XMLTools.getStringValue( "label", WCSNS, element, name );
185            String desc = XMLTools.getStringValue( "description", WCSNS, element, null );
186            Element elem = XMLTools.getChildElement( "metadataLink", WCSNS, element );
187            MetadataLink mLink = parseMetadataLink( elem );
188            elem = XMLTools.getRequiredChildElement( "lonLatEnvelope", WCSNS, element );
189            LonLatEnvelope lonLatEnvelope = parseLonLatEnvelope( elem );
190            ElementList el = XMLTools.getChildElements( "keywords", WCSNS, element );
191            Keywords[] keywords = parseKeywords( el, WCSNS );
192            elem = XMLTools.getRequiredChildElement( "domainSet", WCSNS, element );
193            DomainSet domainSet = getDomainSet( elem );
194            RangeSet rangeSet = null;
195            elem = XMLTools.getRequiredChildElement( "rangeSet", WCSNS, element );
196            if ( elem != null ) {
197                elem = XMLTools.getRequiredChildElement( "RangeSet", WCSNS, elem );
198                rangeSet = getRangeSet( elem );
199            }
200            elem = XMLTools.getRequiredChildElement( "supportedCRSs", WCSNS, element );
201            SupportedSRSs supportedCRSs = getSupportedCRSs( elem );
202            elem = XMLTools.getRequiredChildElement( "supportedFormats", WCSNS, element );
203            SupportedFormats supportedFormats = getSupportedFomarts( elem );
204            elem = XMLTools.getRequiredChildElement( "supportedInterpolations", WCSNS, element );
205            SupportedInterpolations supInterpol = getSupportedInterpolations( elem );
206            elem = XMLTools.getChildElement( "Extension", DGRNS, element );
207    
208            Extension extension = null;
209            if ( elem != null ) {
210                ExtensionDocument eb = new ExtensionDocument( elem, getSystemId() );
211                extension = eb.getExtension();
212            }
213    
214            return new CoverageOffering( name, label, desc, mLink, lonLatEnvelope, keywords, domainSet, rangeSet,
215                                         supportedCRSs, supportedFormats, supInterpol, extension );
216        }
217    
218        /**
219         * creates a <tt>MetadataLink</tt> object from the passed element.
220         *
221         * @param element
222         * @return created <tt>MetadataLink</tt>
223         * @throws XMLParsingException
224         */
225        private MetadataLink parseMetadataLink( Element element )
226                                throws XMLParsingException {
227            if ( element == null )
228                return null;
229    
230            try {
231                URL reference = new URL( XMLTools.getAttrValue( element, "xlink:href" ) );
232                String title = XMLTools.getAttrValue( element, "xlink:title" );
233                URI about = new URI( XMLTools.getAttrValue( element, null, "about", null ) );
234                String tmp = XMLTools.getAttrValue( element, null, "metadataType", null );
235                MetadataType metadataType = new MetadataType( tmp );
236    
237                return new MetadataLink( reference, title, about, metadataType );
238            } catch ( MalformedURLException e ) {
239                throw new XMLParsingException( "Couldn't parse metadataLink reference\n"
240                                               + StringTools.stackTraceToString( e ) );
241            } catch ( URISyntaxException e ) {
242                throw new XMLParsingException( "Couldn't parse metadataLink about\n" + StringTools.stackTraceToString( e ) );
243            }
244        }
245    
246        /**
247         * creates a <tt>DomainSet</tt> from the passed element. Not all possible sub elements are
248         * supported at the moment by deegree (see class comment)
249         *
250         * @param element
251         * @return
252         * @throws XMLParsingException
253         * @throws InvalidCoverageDescriptionExcpetion
254         * @throws WCSException
255         * @throws UnknownCRSException
256         */
257        private DomainSet getDomainSet( Element element )
258                                throws XMLParsingException, InvalidCoverageDescriptionExcpetion, WCSException,
259                                UnknownCRSException {
260            Element elem = XMLTools.getRequiredChildElement( "spatialDomain", WCSNS, element );
261            SpatialDomain sd = getSpatialDomain( elem );
262            elem = XMLTools.getChildElement( "temporalDomain", WCSNS, element );
263            TimeSequence seq = null;
264            if ( elem != null ) {
265                try {
266                    seq = parseTimeSequence( elem, WCSNS );
267                } catch ( OGCWebServiceException e ) {
268                    String s = e.getMessage() + "\n" + StringTools.stackTraceToString( e );
269                    throw new InvalidCoverageDescriptionExcpetion( s );
270                }
271            }
272            return new DomainSet( sd, seq );
273        }
274    
275        /**
276         * creates a <tt>SpatialDomain</tt> object from the passe element. At the moment deegree
277         * doesn't support gml:Grid and gml:Polygon elements for defining a spatial domain of a
278         * coverage.
279         *
280         * @param element
281         * @return created <tt>SpatialDomain</tt>
282         * @throws XMLParsingException
283         * @throws InvalidCoverageDescriptionExcpetion
284         * @throws WCSException
285         * @throws UnknownCRSException
286         */
287        private SpatialDomain getSpatialDomain( Element element )
288                                throws InvalidCoverageDescriptionExcpetion, WCSException, UnknownCRSException {
289            if ( XMLTools.getChildElement( "Grid", GMLNS, element ) != null ) {
290                throw new InvalidCoverageDescriptionExcpetion( "GML Grid for SpatialDomain is not "
291                                                               + "supported by the deegree WCS yet." );
292            }
293            if ( XMLTools.getChildElement( "Polygon", GMLNS, element ) != null ) {
294                throw new InvalidCoverageDescriptionExcpetion( "GML Polygon for SpatialDomain is not "
295                                                               + "supported by the deegree WCS yet." );
296            }
297            ElementList el = XMLTools.getChildElements( "Envelope", GMLNS, element );
298            Envelope[] envelops = getEnvelopes( el );
299            return new SpatialDomain( envelops );
300        }
301    
302        /**
303         * creates an array of <tt>Envelope</tt>s from the passed element list
304         *
305         * @param el
306         * @return created array of <tt>Envelope</tt>s
307         * @throws XMLParsingException
308         * @throws InvalidCoverageDescriptionExcpetion
309         * @throws UnknownCRSException
310         */
311        private Envelope[] getEnvelopes( ElementList el )
312                                throws InvalidCoverageDescriptionExcpetion, UnknownCRSException {
313            if ( el.getLength() == 0 ) {
314                throw new InvalidCoverageDescriptionExcpetion( "at least one envelope must be"
315                                                               + "defined in a spatialDomain" );
316            }
317            Envelope[] envelopes = new Envelope[el.getLength()];
318            for ( int i = 0; i < envelopes.length; i++ ) {
319                try {
320                    envelopes[i] = GMLDocument.parseEnvelope( el.item( i ) );
321                } catch ( InvalidGMLException e ) {
322                    String s = e.getMessage() + "\n" + StringTools.stackTraceToString( e );
323                    throw new InvalidCoverageDescriptionExcpetion( s );
324                }
325            }
326            return envelopes;
327        }
328    
329        /**
330         * creates a <tt>RangeSet</tt> object from the passed element
331         *
332         * @param element
333         * @return created <tt>RangeSet</tt>
334         * @throws XMLParsingException
335         * @throws WCSException
336         * @throws OGCException
337         */
338        private RangeSet getRangeSet( Element element )
339                                throws XMLParsingException, WCSException, OGCException {
340            try {
341                String name = XMLTools.getRequiredStringValue( "name", WCSNS, element );
342                String label = XMLTools.getStringValue( "label", WCSNS, element, name );
343                String desc = XMLTools.getStringValue( "description", WCSNS, element, null );
344                Element elem = XMLTools.getChildElement( "metadataLink", WCSNS, element );
345                MetadataLink mLink = parseMetadataLink( elem );
346                String tmp = XMLTools.getAttrValue( element, null, "semantic", null );
347                URI semantic = null;
348                if ( tmp != null ) {
349                    semantic = new URI( tmp );
350                }
351    
352                tmp = XMLTools.getAttrValue( element, null, "refSys", null );
353                URI refSys = null;
354                if ( tmp != null ) {
355                    refSys = new URI( tmp );
356                }
357    
358                String refSysLabel = XMLTools.getAttrValue( element, null, "refSysLabel", null );
359    
360                AxisDescription[] axisDescription = null;
361                ElementList el = XMLTools.getChildElements( "axisDescription", WCSNS, element );
362                if ( elem != null ) {
363                    elem = XMLTools.getChildElement( "AxisDescription", WCSNS, element );
364                    axisDescription = getAxisDescriptions( el );
365                }
366                elem = XMLTools.getChildElement( "nullValues", WCSNS, element );
367                Values nullValues = parseValues( elem, WCSNS );
368                return new RangeSet( name, label, desc, mLink, semantic, refSys, refSysLabel, nullValues, axisDescription );
369            } catch ( URISyntaxException e ) {
370                throw new XMLParsingException( "couldn't parse URI from typedLiteral\n"
371                                               + StringTools.stackTraceToString( e ) );
372            }
373    
374        }
375    
376        /**
377         * creates an array of <tt>AxisDescription</tt>s from the passed element list
378         *
379         * @param el
380         * @return created array of <tt>AxisDescription</tt>s
381         * @throws XMLParsingException
382         * @throws WCSException
383         * @throws OGCException
384         */
385        private AxisDescription[] getAxisDescriptions( ElementList el )
386                                throws XMLParsingException, WCSException, OGCException {
387            AxisDescription[] ad = new AxisDescription[el.getLength()];
388            for ( int i = 0; i < ad.length; i++ ) {
389                Element elem = XMLTools.getRequiredChildElement( "AxisDescription", WCSNS, el.item( i ) );
390                ad[i] = getAxisDescription( elem );
391            }
392            return ad;
393        }
394    
395        /**
396         * creates an <tt>AxisDescription</tt> object from the passed element
397         *
398         * @param element
399         * @return created <tt>AxisDescription</tt>
400         * @throws XMLParsingException
401         * @throws WCSException
402         * @throws OGCException
403         */
404        private AxisDescription getAxisDescription( Element element )
405                                throws XMLParsingException, WCSException, OGCException {
406            try {
407                String tmp = XMLTools.getAttrValue( element, null, "semantic", null );
408                URI semantic = null;
409                if ( tmp != null ) {
410                    semantic = new URI( tmp );
411                }
412    
413                tmp = XMLTools.getAttrValue( element, null, "refSys", null );
414                URI refSys = null;
415                if ( tmp != null ) {
416                    refSys = new URI( tmp );
417                }
418    
419                String refSysLabel = XMLTools.getAttrValue( element, null, "refSysLabel", null );
420    
421                String name = XMLTools.getRequiredStringValue( "name", WCSNS, element );
422                String label = XMLTools.getStringValue( "label", WCSNS, element, name );
423                String desc = XMLTools.getStringValue( "description", WCSNS, element, null );
424                Element elem = XMLTools.getChildElement( "metadataLink", WCSNS, element );
425                MetadataLink mLink = parseMetadataLink( elem );
426                elem = XMLTools.getRequiredChildElement( "values", WCSNS, element );
427                Values values = parseValues( elem, WCSNS );
428                return new AxisDescription( name, label, desc, mLink, semantic, refSys, refSysLabel, values );
429            } catch ( URISyntaxException e ) {
430                throw new XMLParsingException( "couldn't parse URI from AxisDescription\n"
431                                               + StringTools.stackTraceToString( e ) );
432            }
433        }
434    
435        /**
436         * creates a <tt>SupportedSRSs</tt> object from the passed element
437         *
438         * @param element
439         * @return created <tt>SupportedSRSs</tt>
440         * @throws XMLParsingException
441         */
442        private SupportedSRSs getSupportedCRSs( Element element )
443                                throws XMLParsingException {
444            ElementList el = XMLTools.getChildElements( "requestResponseCRSs", WCSNS, element );
445            CodeList[] requestResponseCRSs = parseCodeListArray( el );
446            el = XMLTools.getChildElements( "requestCRSs", WCSNS, element );
447            CodeList[] requestCRSs = parseCodeListArray( el );
448            el = XMLTools.getChildElements( "responseCRSs", WCSNS, element );
449            CodeList[] responseCRSs = parseCodeListArray( el );
450            el = XMLTools.getChildElements( "nativeCRSs", WCSNS, element );
451            CodeList[] nativeCRSs = parseCodeListArray( el );
452            return new SupportedSRSs( requestResponseCRSs, requestCRSs, responseCRSs, nativeCRSs );
453        }
454    
455        /**
456         * creates a <tt>SupportedFormats</tt> object from the passed element
457         *
458         * @param element
459         * @return
460         * @throws XMLParsingException
461         */
462        private SupportedFormats getSupportedFomarts( Element element )
463                                throws XMLParsingException {
464            String nativeFormat = XMLTools.getAttrValue( element, null, "nativeFormat", null );
465            ElementList el = XMLTools.getChildElements( "formats", WCSNS, element );
466            CodeList[] formats = parseCodeListArray( el );
467            Code nativeF = new Code( nativeFormat );
468            return new SupportedFormats( formats, nativeF );
469        }
470    
471        /**
472         * creates a <tt>SupportedInterpolations<tt> object from the passed element
473         * @param element
474         * @return created <tt>SupportedInterpolations<tt>
475         * @throws XMLParsingException
476         */
477        private SupportedInterpolations getSupportedInterpolations( Element element ) {
478            String tmp = XMLTools.getAttrValue( element, null, "default", "nearest neighbor" );
479            InterpolationMethod def = new InterpolationMethod( tmp );
480    
481            ElementList el = XMLTools.getChildElements( "interpolationMethod", WCSNS, element );
482            InterpolationMethod[] ims = new InterpolationMethod[el.getLength()];
483            for ( int i = 0; i < ims.length; i++ ) {
484                tmp = XMLTools.getStringValue( el.item( i ) );
485                ims[i] = new InterpolationMethod( tmp );
486            }
487            return new SupportedInterpolations( ims, def );
488        }
489    
490    }