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