001    // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wcs/WCService.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    package org.deegree.ogcwebservices.wcs;
044    
045    import java.awt.image.BufferedImage;
046    import java.io.IOException;
047    import java.io.InputStream;
048    import java.net.URL;
049    import java.util.ArrayList;
050    import java.util.List;
051    import java.util.Properties;
052    
053    import org.deegree.crs.exceptions.CRSException;
054    import org.deegree.datatypes.parameter.GeneralParameterValueIm;
055    import org.deegree.datatypes.parameter.OperationParameterIm;
056    import org.deegree.framework.log.ILogger;
057    import org.deegree.framework.log.LoggerFactory;
058    import org.deegree.framework.util.StringTools;
059    import org.deegree.io.JDBCConnection;
060    import org.deegree.io.oraclegeoraster.GeoRasterDescription;
061    import org.deegree.model.coverage.Coverage;
062    import org.deegree.model.coverage.grid.AbstractGridCoverage;
063    import org.deegree.model.coverage.grid.DatabaseIndexedGCMetadata;
064    import org.deegree.model.coverage.grid.Format;
065    import org.deegree.model.coverage.grid.GridCoverageExchange;
066    import org.deegree.model.coverage.grid.GridCoverageReader;
067    import org.deegree.model.coverage.grid.ImageGridCoverage;
068    import org.deegree.model.crs.CRSFactory;
069    import org.deegree.model.crs.CRSTransformationException;
070    import org.deegree.model.crs.GeoTransformer;
071    import org.deegree.model.crs.UnknownCRSException;
072    import org.deegree.model.spatialschema.Envelope;
073    import org.deegree.ogcwebservices.InvalidParameterValueException;
074    import org.deegree.ogcwebservices.OGCWebService;
075    import org.deegree.ogcwebservices.OGCWebServiceException;
076    import org.deegree.ogcwebservices.OGCWebServiceRequest;
077    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
078    import org.deegree.ogcwebservices.wcs.configuration.DatabaseResolution;
079    import org.deegree.ogcwebservices.wcs.configuration.Directory;
080    import org.deegree.ogcwebservices.wcs.configuration.DirectoryResolution;
081    import org.deegree.ogcwebservices.wcs.configuration.Extension;
082    import org.deegree.ogcwebservices.wcs.configuration.File;
083    import org.deegree.ogcwebservices.wcs.configuration.FileResolution;
084    import org.deegree.ogcwebservices.wcs.configuration.OracleGeoRasterResolution;
085    import org.deegree.ogcwebservices.wcs.configuration.Resolution;
086    import org.deegree.ogcwebservices.wcs.configuration.Shape;
087    import org.deegree.ogcwebservices.wcs.configuration.ShapeResolution;
088    import org.deegree.ogcwebservices.wcs.configuration.WCSConfiguration;
089    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescription;
090    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
091    import org.deegree.ogcwebservices.wcs.describecoverage.DescribeCoverage;
092    import org.deegree.ogcwebservices.wcs.describecoverage.InvalidCoverageDescriptionExcpetion;
093    import org.deegree.ogcwebservices.wcs.getcapabilities.ContentMetadata;
094    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSGetCapabilities;
095    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSRequestValidator;
096    import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
097    import org.deegree.ogcwebservices.wcs.getcoverage.ResultCoverage;
098    import org.deegree.ogcwebservices.wcs.getcoverage.SpatialSubset;
099    import org.xml.sax.SAXException;
100    
101    /**
102     * @version $Revision: 9593 $
103     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
104     * @author last edited by: $Author: otonnhofer $
105     * 
106     * @version 1.0. $Revision: 9593 $, $Date: 2008-01-17 15:43:50 +0100 (Do, 17 Jan 2008) $
107     * 
108     * @since 2.0
109     */
110    
111    public class WCService implements OGCWebService {
112    
113        private static final ILogger LOG = LoggerFactory.getLogger( WCService.class );
114    
115        private int nor = 5;
116    
117        private int degree = 3;
118    
119        /**
120         * 
121         */
122        private WCSConfiguration configuration = null;
123    
124        /**
125         * creates a WCService from a configuration
126         * 
127         * @param configuration
128         */
129        public WCService( WCSConfiguration configuration ) {
130            this.configuration = configuration;
131            URL url = WCService.class.getResource( "crstransform.properties" );
132            Properties props = new Properties();
133            try {
134                InputStream is = url.openStream();
135                props.load( is );
136                is.close();
137                nor = Integer.parseInt( props.getProperty( "number_of_reference_points" ) );
138                degree = Integer.parseInt( props.getProperty( "degree" ) );
139            } catch ( Exception e ) {
140                LOG.logError( e.getMessage(), e );
141                LOG.logInfo( "could not load definiton for crs transformation parameters, use default values" );
142            }
143        }
144    
145        /**
146         * returns the capabilities of the WCS
147         * 
148         * @return capabilities of the WCS
149         */
150        public OGCCapabilities getCapabilities() {
151            return configuration;
152        }
153    
154        /**
155         * @param request
156         * @return a CoverageDescription fitting the request
157         * @throws OGCWebServiceException
158         *             if an exception occurs in the process of creating the description.
159         */
160        private CoverageDescription describeCoverage( DescribeCoverage request )
161                                throws OGCWebServiceException {
162    
163            WCSRequestValidator.validate( configuration, request );
164            CoverageOffering[] co = null;
165            try {
166                co = getCoverageOfferings( request );
167            } catch ( IOException ioe ) {
168                LOG.logError( StringTools.stackTraceToString( ioe ) );
169                throw new OGCWebServiceException( ioe.getMessage() );
170            } catch ( SAXException saxe ) {
171                LOG.logError( StringTools.stackTraceToString( saxe ) );
172                throw new OGCWebServiceException( saxe.getMessage() );
173            }
174            CoverageDescription cd = new CoverageDescription( co, request.getVersion() );
175            return cd;
176        }
177    
178        /**
179         * @param request
180         * @return a given Coverage for the request
181         * @throws OGCWebServiceException
182         *             if any kind of exception occurs
183         */
184        private Coverage getCoverage( GetCoverage request )
185                                throws OGCWebServiceException {
186    
187            WCSRequestValidator.validate( configuration, request );
188            Coverage cov = null;
189            if ( request.getOutput().getFormat().getCode().equals( "GML" ) ) {
190                CoverageOffering co;
191                try {
192                    co = getCoverageOffering( request );
193                } catch ( InvalidCoverageDescriptionExcpetion e ) {
194                    LOG.logError( "CoverageDescription is not valid", e );
195                    throw new OGCWebServiceException( getClass().getName(), "CoverageDescription is not valid: "
196                                                                            + e.getMessage() );
197                } catch ( IOException e ) {
198                    LOG.logError( "could not read CoverageDescription", e );
199                    throw new OGCWebServiceException( getClass().getName(), "could not read CoverageDescription: "
200                                                                            + e.getMessage() );
201                } catch ( SAXException e ) {
202                    LOG.logError( "could not parse CoverageDescription", e );
203                    throw new OGCWebServiceException( getClass().getName(), "could not parse CoverageDescription: "
204                                                                            + e.getMessage() );
205                }
206                Envelope env = request.getDomainSubset().getSpatialSubset().getEnvelope();
207                BufferedImage bi = new BufferedImage( 2, 2, BufferedImage.TYPE_INT_ARGB );
208                cov = new ImageGridCoverage( co, env, bi );
209            } else {
210                cov = readCoverage( request );
211            }
212    
213            return cov;
214        }
215    
216        /**
217         * method for event based request procrssing
218         * 
219         * @param request
220         *            object containing the request.
221         * @return depending on the request one of, {@link WCSGetCapabilities}, {@link GetCoverage} or
222         *         {@link DescribeCoverage}
223         */
224        public Object doService( OGCWebServiceRequest request )
225                                throws OGCWebServiceException {
226    
227            Object response = null;
228            if ( request instanceof WCSGetCapabilities ) {
229                WCSRequestValidator.validate( configuration, request );
230                response = getCapabilities();
231            } else if ( request instanceof GetCoverage ) {
232                Coverage cov = getCoverage( (GetCoverage) request );
233                response = new ResultCoverage( cov, cov.getClass(), ( (GetCoverage) request ).getOutput().getFormat(),
234                                               (GetCoverage) request );
235            } else if ( request instanceof DescribeCoverage ) {
236                response = describeCoverage( (DescribeCoverage) request );
237            }
238            return response;
239        }
240    
241        /**
242         * returns the <code>CoverageOffering</code> s according to the coverages names contained in
243         * the passed request. If the request doesn't contain one or more named coverage
244         * <code>CoverageOffering</code> s for all coverages known by the WCS will be returned.
245         * 
246         * @param request
247         *            DescribeCoverage request
248         * @return the configured coverings
249         * @throws IOException
250         * @throws SAXException
251         * @throws InvalidCoverageDescriptionExcpetion
252         */
253        private CoverageOffering[] getCoverageOfferings( DescribeCoverage request )
254                                throws IOException, SAXException, InvalidCoverageDescriptionExcpetion {
255    
256            String[] coverages = request.getCoverages();
257            CoverageOffering[] co = null;
258            ContentMetadata cm = configuration.getContentMetadata();
259            if ( coverages.length == 0 ) {
260                // get descriptions of all coverages
261                CoverageOfferingBrief[] cob = cm.getCoverageOfferingBrief();
262                co = new CoverageOffering[cob.length];
263                for ( int i = 0; i < cob.length; i++ ) {
264                    URL url = cob[i].getConfiguration();
265                    CoverageDescription cd = CoverageDescription.createCoverageDescription( url );
266                    co[i] = cd.getCoverageOffering( cob[i].getName() );
267                }
268            } else {
269                // get descriptions of all requested coverages
270                co = new CoverageOffering[coverages.length];
271                for ( int i = 0; i < coverages.length; i++ ) {
272                    CoverageOfferingBrief cob = cm.getCoverageOfferingBrief( coverages[i] );
273                    URL url = cob.getConfiguration();
274                    CoverageDescription cd = CoverageDescription.createCoverageDescription( url );
275                    co[i] = cd.getCoverageOffering( cob.getName() );
276                }
277            }
278    
279            return co;
280        }
281    
282        /**
283         * The method reads and returns the coverage described by the passed request.
284         * 
285         * @param request
286         * @return a Coverage read from the given resolution
287         * @throws InvalidCoverageDescriptionExcpetion
288         */
289        private Coverage readCoverage( GetCoverage request )
290                                throws InvalidCoverageDescriptionExcpetion, InvalidParameterValueException,
291                                OGCWebServiceException {
292    
293            Coverage result = null;
294    
295            try {
296                CoverageOffering co = getCoverageOffering( request );
297                
298                Resolution[] resolutions = getResolutions( co, request );
299                if ( resolutions == null || resolutions.length == 0 ) {
300                    throw new InvalidParameterValueException(
301                                                              "No data source defined the requested combination of spatial resolution and ranges" );
302                }
303                GridCoverageReader reader = null;
304       
305                LOG.logDebug( "getting responsible GridCoverageReader" );
306                if ( resolutions[0] instanceof FileResolution ) {
307                    reader = getFileReader( resolutions, co, request );
308                } else if ( resolutions[0] instanceof ShapeResolution ) {
309                    reader = getShapeReader( resolutions, co, request );
310                } else if ( resolutions[0] instanceof DirectoryResolution ) {
311                    reader = getDirectoryReader( resolutions, co, request );
312                } else if ( resolutions[0] instanceof OracleGeoRasterResolution ) {
313                    reader = getOracleGeoRasterReader( resolutions, co, request );
314                } else if ( resolutions[0] instanceof DatabaseResolution ) {
315                    reader = getDatabaseRasterReader( resolutions, co, request );
316                }
317    
318                LOG.logDebug( "resolution reader: " + resolutions[0] );
319                LOG.logDebug( "found reader: " + reader.getClass() );
320                List<GeneralParameterValueIm> list = new ArrayList<GeneralParameterValueIm>( 20 );
321                
322                Envelope gridSize = (Envelope) request.getDomainSubset().getSpatialSubset().getGrid();
323                Envelope targetEnv = request.getDomainSubset().getSpatialSubset().getEnvelope();
324                
325                int width = (int)(gridSize.getWidth() + 1);
326                int height = (int)(gridSize.getHeight() + 1);
327                OperationParameterIm op = new OperationParameterIm( "width", null, new Integer( width ) );
328                list.add( new GeneralParameterValueIm( op ) );
329                op = new OperationParameterIm( "height", null, new Integer( height ) );
330                list.add( new GeneralParameterValueIm( op ) );
331                GeneralParameterValueIm[] gpvs = new GeneralParameterValueIm[list.size()];
332                result = reader.read( list.toArray( gpvs ) );
333                if ( result == null ) {
334                    throw new InvalidCoverageDescriptionExcpetion(
335                                                                   "Couldn't read a coverage for the requested resolution and/or area" );
336                }
337                LOG.logDebug( "found result: " + result );
338    
339                // transform Coverage into another CRS if required
340                String crs = request.getOutput().getCrs().getCode();
341                if ( crs == null ) {
342                    crs = request.getDomainSubset().getRequestSRS().getCode();
343                }
344                if ( !crs.equalsIgnoreCase( co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0] ) ) {
345                    LOG.logDebug( "transforming coverage to " + crs );
346                    GeoTransformer gt = new GeoTransformer( crs );
347                    
348                    result = gt.transform( (AbstractGridCoverage) result, targetEnv, width, height, nor, degree, null );
349                }
350    
351            } catch ( IOException e ) {
352                LOG.logError( e.getMessage(), e );
353                throw new OGCWebServiceException( e.getMessage() );
354            } catch ( SAXException e ) {
355                LOG.logError( e.getMessage(), e );
356                throw new OGCWebServiceException( e.getMessage() );
357            } catch ( CRSTransformationException e ) {
358                LOG.logError( e.getMessage(), e );
359                throw new OGCWebServiceException( e.getMessage() );
360            } catch ( UnknownCRSException e ) {
361                LOG.logError( e.getMessage(), e );
362                throw new OGCWebServiceException( e.getMessage() );
363            }
364            return result;
365        }
366    
367        /**
368         * returns the <code>CoverageOffering</code> describing the access to the data sources behind
369         * the requested coverage
370         * 
371         * @param request
372         *            GetCoverage request
373         * @return the Coverage Offering fitting the request
374         * @throws IOException
375         * @throws SAXException
376         * @throws InvalidCoverageDescriptionExcpetion
377         */
378        private CoverageOffering getCoverageOffering( GetCoverage request )
379                                throws IOException, SAXException, InvalidCoverageDescriptionExcpetion {
380    
381            ContentMetadata cm = configuration.getContentMetadata();
382            CoverageOfferingBrief cob = cm.getCoverageOfferingBrief( request.getSourceCoverage() );
383            URL url = cob.getConfiguration();
384            CoverageDescription cd = CoverageDescription.createCoverageDescription( url );
385            return cd.getCoverageOffering( request.getSourceCoverage() );
386        }
387    
388        /**
389         * returns the <code>Resolution</code> s matching the scale, region and range parameters of
390         * the passed request
391         * 
392         * @param co
393         * @param request
394         * @return the <code>Resolution</code> s matching the scale, region and range parameters of
395         *         the passed request
396         * @throws CRSException
397         * @throws CRSTransformationException
398         */
399        private Resolution[] getResolutions( CoverageOffering co, GetCoverage request )
400                                throws UnknownCRSException, CRSTransformationException {
401    
402            Extension extension = co.getExtension();
403            Resolution[] res = extension.getResolutions( calcSpatialResolution( co, request ) );
404    
405            return res;
406        }
407    
408        /**
409         * calculates the spatial resolution of the coverage described by a GetCoverage request
410         * 
411         * @param co
412         * @param request
413         * @return
414         * @throws UnknownCRSException
415         * @throws CRSTransformationException
416         */
417        private double calcSpatialResolution( CoverageOffering co, GetCoverage request )
418                                throws UnknownCRSException, CRSTransformationException {
419    
420            SpatialSubset sps = request.getDomainSubset().getSpatialSubset();
421            // determine resolution of the requested coverage
422            Envelope env = calculateRequestEnvelope( request, co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0] );
423            Envelope grid = (Envelope) sps.getGrid();
424            double qx = env.getWidth() / grid.getWidth();
425            double qy = env.getHeight() / grid.getHeight();
426            double reso = qx;
427            // if x- and y-direction has different resolution in the GetCoverage
428            // request use the finest
429            if ( qy < qx ) {
430                reso = qy;
431            }
432            return reso;
433        }
434    
435        /**
436         * returns a <code>GridCoverageReader</code> for accessing the data source of the target
437         * coverage of the passed GetCoverage request. The reader will be constructed from all
438         * <code>File</code> s matching the filter conditions defined in the passed GeCoverage
439         * request. <BR>
440         * At the moment just the first field of the passed <code>Resolution</code> array will be
441         * considered!
442         * 
443         * @param resolutions
444         *            <code>Resolution</code> to get a reader for
445         * @param co
446         *            description of the requested coverage
447         * @param request
448         * @return <code>GridCoverageReader</code>
449         * @throws IOException
450         * @throws UnknownCRSException
451         * @throws CRSTransformationException
452         */
453        private GridCoverageReader getFileReader( Resolution[] resolutions, CoverageOffering co, GetCoverage request )
454                                throws IOException, InvalidParameterValueException, UnknownCRSException,
455                                CRSTransformationException {
456    
457            String nativeCRS = co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
458            // calculates the envevole to be used by the created GridCoverageReader
459            Envelope envelope = calculateRequestEnvelope( request, nativeCRS );
460    
461            File[] files = ( (FileResolution) resolutions[0] ).getFiles();
462            List<File> list = new ArrayList<File>();
463            for ( int i = 0; i < files.length; i++ ) {
464                Envelope fileEnv = files[i].getEnvelope();
465                if ( fileEnv.intersects( envelope ) ) {
466                    list.add( files[i] );
467                }
468            }
469            files = list.toArray( new File[list.size()] );
470    
471            GridCoverageExchange gce = new GridCoverageExchange( null );
472            Format format = new Format( co.getSupportedFormats().getNativeFormat() );
473            GridCoverageReader reader = gce.getReader( files, co, envelope, format );
474    
475            return reader;
476        }
477    
478        /**
479         * returns a <code>GridCoverageReader</code> for accessing the data source of the target
480         * coverage of the passed GetCoverage request. The reader will be constructed from all
481         * <code>Shape</code> s matching the filter conditions defined in the passed GeCoverage
482         * request. At least this should be just one! <BR>
483         * At the moment just the first field of the passed <code>Resolution</code> array will be
484         * considered!
485         * 
486         * @param resolutions
487         * @param co
488         * @param request
489         * @return a GridCoverageReader which is able to read shape files.
490         * @throws IOException
491         * @throws UnknownCRSException
492         * @throws CRSTransformationException
493         */
494        private GridCoverageReader getShapeReader( Resolution[] resolutions, CoverageOffering co, GetCoverage request )
495                                throws IOException, InvalidParameterValueException, UnknownCRSException,
496                                CRSTransformationException {
497    
498            String nativeCRS = co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
499            // calculates the envevole to be used by the created GridCoverageReader
500            Envelope envelope = calculateRequestEnvelope( request, nativeCRS );
501    
502            Shape shape = ( (ShapeResolution) resolutions[0] ).getShape();
503    
504            GridCoverageExchange gce = new GridCoverageExchange( null );
505            Format format = new Format( co.getSupportedFormats().getNativeFormat() );
506            return gce.getReader( shape, co, envelope, format );
507    
508        }
509    
510        /**
511         * returns a <code>GridCoverageReader</code> for accessing the data source of the target
512         * coverage of the passed GetCoverage request. The reader will be constructed from all
513         * <code>Directory</code> s matching the filter conditions defined in the passed GeCoverage
514         * request. At least this should be just one! <BR>
515         * At the moment just the first field of the passed <code>Resolution</code> array will be
516         * considered!
517         * 
518         * @param resolutions
519         * @param co
520         * @param request
521         * @return the GridCoverageReader which reads directories
522         * @throws IOException
523         * @throws UnknownCRSException
524         * @throws CRSTransformationException
525         */
526        private GridCoverageReader getDirectoryReader( Resolution[] resolutions, CoverageOffering co, GetCoverage request )
527                                throws IOException, InvalidParameterValueException, UnknownCRSException,
528                                CRSTransformationException {
529    
530            String nativeCRS = co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
531            // calculates the envevole to be used by the created GridCoverageReader
532            Envelope envelope = calculateRequestEnvelope( request, nativeCRS );
533    
534            Directory[] dirs = ( (DirectoryResolution) resolutions[0] ).getDirectories( envelope );
535    
536            GridCoverageExchange gce = new GridCoverageExchange( null );
537            Format format = new Format( co.getSupportedFormats().getNativeFormat() );
538    
539            GridCoverageReader reader = gce.getReader( dirs, co, envelope, format );
540    
541            return reader;
542        }
543    
544        /**
545         * 
546         * @param resolutions
547         * @param co
548         * @param request
549         * @return
550         * @throws CRSTransformationException
551         * @throws UnknownCRSException
552         * @throws IOException
553         * @throws InvalidParameterValueException
554         */
555        private GridCoverageReader getDatabaseRasterReader( Resolution[] resolutions, CoverageOffering co,
556                                                            GetCoverage request )
557                                throws UnknownCRSException, CRSTransformationException, InvalidParameterValueException,
558                                IOException {
559    
560            String nativeCRS = co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
561            // calculates the envevole to be used by the created GridCoverageReader
562            Envelope envelope = calculateRequestEnvelope( request, nativeCRS );
563    
564            DatabaseResolution dr = (DatabaseResolution) resolutions[0];
565    
566            GridCoverageExchange gce = new GridCoverageExchange( null );
567            Format format = new Format( co.getSupportedFormats().getNativeFormat() );
568            double reso = calcSpatialResolution( co, request );
569            DatabaseIndexedGCMetadata digcmd = new DatabaseIndexedGCMetadata( dr.getJDBCConnection(), (float) reso,
570                                                                              dr.getTable(), dr.getRootDir(), false );
571    
572            return gce.getReader( digcmd, co, envelope, format );
573        }
574    
575        /**
576         * returns a <code>GridCoverageReader</code> for accessing the data source of the target
577         * coverage of the passed GetCoverage request. The reader will be constructed from the JDBCV
578         * connnection defined in the CoverageDescription extension.<BR>
579         * At the moment just the first field of the passed <code>Resolution</code> array will be
580         * considered!
581         * 
582         * @param resolutions
583         * @param co
584         * @param request
585         * @return a <code>GridCoverageReader</code>.
586         * @throws InvalidParameterValueException
587         * @throws IOException
588         * @throws UnknownCRSException
589         * @throws CRSTransformationException
590         */
591        private GridCoverageReader getOracleGeoRasterReader( Resolution[] resolutions, CoverageOffering co,
592                                                             GetCoverage request )
593                                throws InvalidParameterValueException, IOException, UnknownCRSException,
594                                CRSTransformationException {
595    
596            String nativeCRS = co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
597            // calculates the envevole to be used by the created GridCoverageReader
598            Envelope envelope = calculateRequestEnvelope( request, nativeCRS );
599    
600            JDBCConnection jdbc = ( (OracleGeoRasterResolution) resolutions[0] ).getJDBCConnection();
601            String table = ( (OracleGeoRasterResolution) resolutions[0] ).getTable();
602            String rdtTable = ( (OracleGeoRasterResolution) resolutions[0] ).getRdtTable();
603            String column = ( (OracleGeoRasterResolution) resolutions[0] ).getColumn();
604            String identification = ( (OracleGeoRasterResolution) resolutions[0] ).getIdentification();
605            int level = ( (OracleGeoRasterResolution) resolutions[0] ).getLevel();
606            GeoRasterDescription grd = new GeoRasterDescription( jdbc, table, rdtTable, column, identification, level );
607    
608            GridCoverageExchange gce = new GridCoverageExchange( null );
609            Format format = new Format( co.getSupportedFormats().getNativeFormat() );
610    
611            return gce.getReader( grd, co, envelope, format );
612    
613        }
614    
615        /**
616         * According to WCS 1.0.0 the CRS of the GetCoverage request BBOX can be different to the
617         * desired CRS of the resulting coverage. This method transforms the request CRS to the output
618         * CRS if requiered. At the moment deegree WCS doesn't support transformation of grid coverages
619         * so the output CRS will always be the native CRS of te data.
620         * 
621         * @param request
622         * @param nativeCrs
623         * @return a boundingbox of the request
624         * @throws CRSTransformationException
625         * @throws UnknownCRSException
626         */
627        private Envelope calculateRequestEnvelope( GetCoverage request, String nativeCrs )
628                                throws UnknownCRSException, CRSTransformationException {
629    
630            SpatialSubset spsu = request.getDomainSubset().getSpatialSubset();
631            Envelope envelope = spsu.getEnvelope();
632            
633            String reqCrs = request.getDomainSubset().getRequestSRS().getCode();
634    
635            GeoTransformer gt = new GeoTransformer( nativeCrs );
636            Envelope result = gt.transform( envelope, CRSFactory.create( reqCrs ), true );
637            
638            return result;
639    
640        }
641    
642    }