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