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 }