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