001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/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 (Thu, 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 }