    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/ogcwebservices/wpvs/WCSInvoker.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
    037    package org.deegree.ogcwebservices.wpvs;
    038
    039    import java.awt.Color;
    040    import java.awt.Graphics2D;
    041    import java.awt.Image;
    042    import java.awt.image.BufferedImage;
    043    import java.io.File;
    044    import java.io.IOException;
    045    import java.util.HashMap;
    046    import java.util.Map;
    047
    048    import javax.imageio.ImageIO;
    049    import javax.media.jai.JAI;
    050    import javax.media.jai.PlanarImage;
    051    import javax.media.jai.operator.TransposeDescriptor;
    052
    053    import org.deegree.datatypes.Code;
    054    import org.deegree.framework.log.ILogger;
    055    import org.deegree.framework.log.LoggerFactory;
    056    import org.deegree.framework.util.IDGenerator;
    057    import org.deegree.i18n.Messages;
    058    import org.deegree.model.coverage.grid.ImageGridCoverage;
    059    import org.deegree.model.spatialschema.Envelope;
    060    import org.deegree.model.spatialschema.Position;
    061    import org.deegree.ogcwebservices.OGCWebServiceException;
    062    import org.deegree.ogcwebservices.wcs.WCSException;
    063    import org.deegree.ogcwebservices.wcs.WCService;
    064    import org.deegree.ogcwebservices.wcs.getcoverage.DomainSubset;
    065    import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
    066    import org.deegree.ogcwebservices.wcs.getcoverage.Output;
    067    import org.deegree.ogcwebservices.wcs.getcoverage.ResultCoverage;
    068    import org.deegree.ogcwebservices.wcs.getcoverage.SpatialSubset;
    069    import org.deegree.ogcwebservices.wpvs.configuration.AbstractDataSource;
    070    import org.deegree.ogcwebservices.wpvs.configuration.LocalWCSDataSource;
    071    import org.deegree.ogcwebservices.wpvs.utils.ImageUtils;
    072    import org.deegree.ogcwebservices.wpvs.utils.ResolutionStripe;
    073
    074    /**
    075     * Invoker for a Web Coverage Service.
    076     *
    077     * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
    078     * @author last edited by: $Author: mschneider $
    079     *
    080     * $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    081     */
    082    public class WCSInvoker extends GetViewServiceInvoker {
    083
    084        private static final ILogger LOG = LoggerFactory.getLogger( WCSInvoker.class );
    085
    086        /* the rank represent the order in whoch the image will be painted */
    087        private int id;
    088
    089        /* whether the image will be used as texture or as data for the elevation model */
    090        private final boolean isElevationModelRequest;
    091
    092        private String requestFormat;
    093
    094        /**
    095         * Creates a new instance of this class.
    096         *
    097         * @param owner
    098         *            the handler that owns this invoker
    099         * @param id
    100         * @param requestFormat
    101         * @param isElevationModelRequest
    102         */
    103        public WCSInvoker( ResolutionStripe owner, int id, String requestFormat, boolean isElevationModelRequest ) {
    104            super( owner );
    105            this.id = id;
    106            this.isElevationModelRequest = isElevationModelRequest;
    107            this.requestFormat = requestFormat;
    108        }
    109
    110        @Override
    111        public void invokeService( AbstractDataSource dataSource ) {
    112
    113            if ( !( dataSource instanceof LocalWCSDataSource ) ) {
    114                LOG.logError( "The given AbstractDataSource is no WCSDataSource instance. It is needed for a WCSInvoker" );
    115                throw new RuntimeException( "DataSource should be a WCS-instance for a WCSInvoker" );
    116            }
    117
    118            WCService service = null;
    119            try {
    120                service = (WCService) dataSource.getOGCWebService();
    121            } catch ( OGCWebServiceException ogcwe ) {
    122                LOG.logError( ogcwe.getMessage() );
    123                throw new RuntimeException( ogcwe );
    124            }
    125            if ( service == null ) {
    126                throw new RuntimeException( "No Web Coverage Service instance available for WCSInvoker" );
    127            }
    128
    129            Object coverageResponse = null;
    130
    131            // check if the admin has configured a minimal dgm resolution, if so the request and
    132            // response resolution for the dgm must be set.
    133            int requestWidth = resolutionStripe.getRequestWidthForBBox();
    134            int requestHeight = resolutionStripe.getRequestHeightForBBox();
    135            if ( isElevationModelRequest ) {
    136                double minRes = ( (LocalWCSDataSource) dataSource ).getConfiguredMinimalDGMResolution();
    137                LOG.logDebug( "configured minimalResolution: " + minRes );
    138                if ( minRes > 0.0000001 ) {// 0d if not set
    139                    Envelope env = resolutionStripe.getSurface().getEnvelope();
    140                    if ( ( env.getWidth() / requestWidth ) < minRes ) {
    141                        requestWidth = (int) ( env.getWidth() / minRes );
    142                    }
    143                    if ( ( env.getHeight() / requestHeight ) < minRes ) {
    144                        requestHeight = (int) ( env.getHeight() / minRes );
    145                    }
    146                }
    147            }
    148
    149            try {
    150                GetCoverage getCoverageRequest = createGetCoverageRequest(
    151                                                                           ( (LocalWCSDataSource) dataSource ).getCoverageFilterCondition(),
    152                                                                           ( (LocalWCSDataSource) dataSource ).getDefaultFormat(),
    153                                                                           requestWidth, requestHeight );
    154                LOG.logDebug( "WCS request:" + getCoverageRequest );
    155                coverageResponse = service.doService( getCoverageRequest );
    156            } catch ( WCSException wcse ) {
    157                if ( !Thread.currentThread().isInterrupted() ) {
    158                    LOG.logError( Messages.getMessage( "WPVS_WCS_REQUEST_ERROR", "WCSException", dataSource.getName(),
    159                                                       wcse.getMessage() ) );
    160                    if ( !isElevationModelRequest ) {
    161                        resolutionStripe.setTextureRetrievalException( dataSource.getName().getFormattedString() + id, wcse );
    162                    }
    163                }
    164                return;
    165            } catch ( OGCWebServiceException ogcwse ) {
    166                if ( !Thread.currentThread().isInterrupted() ) {
    167                    LOG.logError( Messages.getMessage( "WPVS_WCS_REQUEST_ERROR", "OGCWebServiceException",
    168                                                       dataSource.getName(), ogcwse.getMessage() ) );
    169                    if ( !isElevationModelRequest ) {
    170                        resolutionStripe.setTextureRetrievalException( dataSource.getName().getFormattedString() + id,
    171                                                                       ogcwse );
    172                    }
    173                }
    174                return;
    175            } catch ( Throwable t ) {
    176                if ( !Thread.currentThread().isInterrupted() ) {
    177                    t.printStackTrace();
    178                }
    179                return;
    180            }
    181            if ( coverageResponse != null && coverageResponse instanceof ResultCoverage ) {
    182
    183                LOG.logDebug( "\t -> a valid response\n" );
    184                ResultCoverage response = (ResultCoverage) coverageResponse;
    185                if ( response.getCoverage() != null && response.getCoverage() instanceof ImageGridCoverage ) {
    186                    ImageGridCoverage igc = (ImageGridCoverage) response.getCoverage();
    187
    188                    BufferedImage image = igc.getAsImage( requestWidth, requestHeight );
    189                    if ( !isElevationModelRequest ) {
    190                        if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
    191                            try {
    192                                File f = new File( "wcs_texture_response.png" );
    193                                LOG.logDebug( "creating tmpfile for wcs texture response with name: " + f.toString() );
    194                                f.deleteOnExit();
    195                                ImageIO.write( image, "png", f );
    196                            } catch ( IOException e ) {
    197                                // TODO Auto-generated catch block
    198                                e.printStackTrace();
    199                            }
    200                        }
    201                        Color[] colors = ( (LocalWCSDataSource) dataSource ).getTransparentColors();
    202                        if ( colors != null && colors.length > 0 ) {
    203                            ImageUtils imgUtil = new ImageUtils( colors );
    204                            Image img = imgUtil.filterImage( image );
    205                            Graphics2D g2d = (Graphics2D) image.getGraphics();
    206                            g2d.drawImage( img, 0, 0, null );
    207                            g2d.dispose();
    208                        }
    209
    210                        if ( !resolutionStripe.addTexture( dataSource.getName().getFormattedString() + id, image ) ) {
    211                            LOG.logDebug( "could not add the texture" );
    212                        }
    213                    } else {
    214                        // the heightdata is in x and -y coordinates, they must be flipped before using
    215                        PlanarImage im2 = JAI.create( "transpose", image, TransposeDescriptor.FLIP_VERTICAL );
    216                        if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
    217                            try {
    218                                File f = new File( "wcs_dgm_response.png" );
    219                                LOG.logDebug( "creating tmpfile for wcs elevationmodel response with name: " + f.toString() );
    220                                f.deleteOnExit();
    221                                ImageIO.write( im2.getAsBufferedImage(), "png", f );
    222                            } catch ( Exception e ) {
    223                                // TODO Auto-generated catch block
    224                                e.printStackTrace();
    225                            }
    226                        }
    227                        resolutionStripe.setElevationModelFromHeightMap( im2.getAsBufferedImage() );
    228                    }
    229                } else {
    230                    LOG.logWarning( Messages.getMessage( "WPVS_IVALID_WCS_RESPONSE", dataSource.getName(),
    231                                                         "an ImageGridCoverage" ) );
    232                }
    233            } else {
    234                LOG.logWarning( Messages.getMessage( "WPVS_IVALID_WCS_RESPONSE", dataSource.getName(), "a ResultCoverage" ) );
    235            }
    236
    237        }
    238
    239        /**
    240         * Creates a getCoverage request for the given surface
    241         *
    242         * @param filterCondition
    243         * @param format
    244         * @param requestWidth
    245         *            the width of a request (which should take the configured dgm_res into account).
    246         * @param requestHeight
    247         *            the height of a request (which should take the configured dgm_res into account).
    248         * @return a new GetCoverageRequest.
    249         * @throws WCSException
    250         * @throws OGCWebServiceException
    251         */
    252        private GetCoverage createGetCoverageRequest( GetCoverage filterCondition, String format, int requestWidth,
    253                                                      int requestHeight )
    254                                throws WCSException, OGCWebServiceException {
    255
    256            // String format = "GeoTiff";
    257            if ( !isElevationModelRequest ) {
    258                if ( filterCondition.getOutput().getFormat() == null ) {
    259                    // fallback if no output format has been defined for a
    260                    // WCS datasource
    261                    format = requestFormat;
    262                } else {
    263                    format = filterCondition.getOutput().getFormat().getCode();
    264                }
    265                int pos = format.indexOf( '/' );
    266                if ( pos > -1 ) {
    267                    format = format.substring( pos + 1, format.length() );
    268                }
    269
    270                if ( format.indexOf( "svg" ) > -1 ) {
    271                    format = "png";
    272                }
    273            }
    274            Output output = GetCoverage.createOutput( resolutionStripe.getCRSName().getFormattedString(), null, format,
    275                                                      null );
    276
    277            // put mising parts in this map:
    278            Map<String, String> map = new HashMap<String, String>( 5 );
    279
    280            StringBuffer sb = new StringBuffer( 1000 );
    281            Envelope env = resolutionStripe.getSurface().getEnvelope();
    282            Position p = env.getMin();
    283            sb.append( p.getX() ).append( "," ).append( p.getY() ).append( "," );
    284            p = env.getMax();
    285            sb.append( p.getX() ).append( "," ).append( p.getY() );
    286            map.put( "BBOX", sb.toString() );
    287
    288            map.put( "WIDTH", String.valueOf( requestWidth ) );
    289            map.put( "HEIGHT", String.valueOf( requestHeight ) );
    290
    291            SpatialSubset sps = GetCoverage.createSpatialSubset( map, resolutionStripe.getCRSName().getFormattedString() );
    292
    293            Code code = filterCondition.getDomainSubset().getRequestSRS();
    294            DomainSubset domainSubset = new DomainSubset( code, sps, null );
    295
    296            IDGenerator idg = IDGenerator.getInstance();
    297
    298            GetCoverage getCoverageRequest = new GetCoverage( String.valueOf( idg.generateUniqueID() ),
    299                                                              filterCondition.getVersion(),
    300                                                              filterCondition.getSourceCoverage(), domainSubset, null,
    301                                                              filterCondition.getInterpolationMethod(), output );
    302
    303            return getCoverageRequest;
    304        }
    305
    306    }