001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }