001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wms/GetMapServiceInvokerForNL.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2007 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 Aennchenstr. 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 package org.deegree.ogcwebservices.wms; 044 045 import java.awt.Color; 046 import java.awt.Graphics; 047 import java.awt.image.BufferedImage; 048 import java.io.StringReader; 049 import java.net.URI; 050 import java.util.ArrayList; 051 import java.util.Iterator; 052 import java.util.List; 053 import java.util.Map; 054 import java.util.concurrent.CancellationException; 055 056 import org.deegree.datatypes.QualifiedName; 057 import org.deegree.datatypes.Types; 058 import org.deegree.framework.concurrent.DoServiceTask; 059 import org.deegree.framework.concurrent.Executor; 060 import org.deegree.framework.log.ILogger; 061 import org.deegree.framework.log.LoggerFactory; 062 import org.deegree.framework.util.CharsetUtils; 063 import org.deegree.framework.util.IDGenerator; 064 import org.deegree.framework.xml.XMLFragment; 065 import org.deegree.framework.xml.XMLTools; 066 import org.deegree.graphics.MapFactory; 067 import org.deegree.graphics.Theme; 068 import org.deegree.graphics.sld.NamedLayer; 069 import org.deegree.graphics.sld.StyleUtils; 070 import org.deegree.graphics.sld.UserStyle; 071 import org.deegree.i18n.Messages; 072 import org.deegree.model.coverage.grid.GridCoverage; 073 import org.deegree.model.coverage.grid.ImageGridCoverage; 074 import org.deegree.model.crs.CRSException; 075 import org.deegree.model.crs.CRSFactory; 076 import org.deegree.model.crs.CRSTransformationException; 077 import org.deegree.model.crs.GeoTransformer; 078 import org.deegree.model.crs.IGeoTransformer; 079 import org.deegree.model.feature.Feature; 080 import org.deegree.model.feature.FeatureCollection; 081 import org.deegree.model.feature.FeatureProperty; 082 import org.deegree.model.feature.schema.FeatureType; 083 import org.deegree.model.feature.schema.PropertyType; 084 import org.deegree.model.filterencoding.ComplexFilter; 085 import org.deegree.model.filterencoding.FeatureFilter; 086 import org.deegree.model.filterencoding.FeatureId; 087 import org.deegree.model.filterencoding.Filter; 088 import org.deegree.model.spatialschema.Envelope; 089 import org.deegree.model.spatialschema.GMLGeometryAdapter; 090 import org.deegree.model.spatialschema.Geometry; 091 import org.deegree.model.spatialschema.GeometryException; 092 import org.deegree.model.spatialschema.WKTAdapter; 093 import org.deegree.ogcbase.PropertyPath; 094 import org.deegree.ogcbase.PropertyPathFactory; 095 import org.deegree.ogcwebservices.InconsistentRequestException; 096 import org.deegree.ogcwebservices.OGCWebServiceException; 097 import org.deegree.ogcwebservices.OGCWebServiceRequest; 098 import org.deegree.ogcwebservices.wcs.WCSException; 099 import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage; 100 import org.deegree.ogcwebservices.wcs.getcoverage.ResultCoverage; 101 import org.deegree.ogcwebservices.wfs.WFService; 102 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 103 import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType; 104 import org.deegree.ogcwebservices.wfs.operation.FeatureResult; 105 import org.deegree.ogcwebservices.wfs.operation.GetFeature; 106 import org.deegree.ogcwebservices.wfs.operation.Query; 107 import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource; 108 import org.deegree.ogcwebservices.wms.configuration.LocalWCSDataSource; 109 import org.deegree.ogcwebservices.wms.configuration.LocalWFSDataSource; 110 import org.deegree.ogcwebservices.wms.configuration.RemoteWMSDataSource; 111 import org.deegree.ogcwebservices.wms.operation.GetMap; 112 import org.deegree.ogcwebservices.wms.operation.GetMapResult; 113 import org.w3c.dom.Document; 114 115 /** 116 * Class for accessing the data of one layers datasource and creating a <tt>Theme</tt> from it. 117 * 118 * @version $Revision: 7978 $ 119 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 120 * @author last edited by: $Author: aschmitz $ 121 * 122 * @version 1.0. $Revision: 7978 $, $Date: 2007-08-10 13:04:16 +0200 (Fr, 10 Aug 2007) $ 123 * 124 * @since 2.0 125 */ 126 public class GetMapServiceInvokerForNL extends GetMapServiceInvoker { 127 128 private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvokerForNL.class ); 129 130 private final GetMap request; 131 132 private NamedLayer layer = null; 133 134 private UserStyle style = null; 135 136 private AbstractDataSource datasource = null; 137 138 /** 139 * Creates a new ServiceInvokerForNL object. 140 * 141 * @param handler 142 * @param layer 143 * @param datasource 144 * @param style 145 * @param index 146 */ 147 GetMapServiceInvokerForNL( DefaultGetMapHandler handler, NamedLayer layer, AbstractDataSource datasource, 148 UserStyle style, double scale, int index ) { 149 150 super( handler, index, scale ); 151 152 this.layer = layer; 153 this.request = handler.getRequest(); 154 this.style = style; 155 this.datasource = datasource; 156 } 157 158 /** 159 * central method for access the data assigned to a datasource 160 * 161 * @return the data 162 */ 163 public Object run() { 164 165 Object response = null; 166 if ( datasource != null ) { 167 OGCWebServiceRequest request = null; 168 try { 169 int type = datasource.getType(); 170 switch ( type ) { 171 case AbstractDataSource.LOCALWFS: 172 case AbstractDataSource.REMOTEWFS: { 173 request = createGetFeatureRequest( (LocalWFSDataSource) datasource ); 174 break; 175 } 176 case AbstractDataSource.LOCALWCS: 177 case AbstractDataSource.REMOTEWCS: { 178 request = createGetCoverageRequest( datasource, this.request ); 179 break; 180 } 181 case AbstractDataSource.REMOTEWMS: { 182 String styleName = null; 183 184 if ( style != null ) { 185 styleName = style.getName(); 186 } 187 188 request = GetMap.createGetMapRequest( datasource, handler.getRequest(), styleName, layer.getName() ); 189 LOG.logDebug( "GetMap request: " + request.toString() ); 190 break; 191 } 192 } 193 } catch ( Exception e ) { 194 e.printStackTrace(); 195 OGCWebServiceException exce = new OGCWebServiceException( getClass().getName(), 196 Messages.getMessage( "WMS_ERRORQUERYCREATE", 197 e ) ); 198 // exception can't be re-thrown because responsible GetMapHandler 199 // must collect all responses of all datasources 200 response = new Object[] { new Integer( index ), exce }; 201 LOG.logError( e.getMessage(), e ); 202 } 203 204 try { 205 // start reading data with a limited time frame. The time limit 206 // readed from the datasource muts be multiplied by 1000 because 207 // the method expects milliseconds as timelimit 208 Executor executor = Executor.getInstance(); 209 DoServiceTask<Object> task = new DoServiceTask<Object>( datasource.getOGCWebService(), request ); 210 Object o = executor.performSynchronously( task, datasource.getRequestTimeLimit() * 1000 ); 211 response = handleResponse( o ); 212 } catch ( CancellationException e ) { 213 // exception can't be re-thrown because responsible GetMapHandler 214 // must collect all responses of all datasources 215 String s = Messages.getMessage( "WMS_TIMEOUTDATASOURCE", new Integer( datasource.getRequestTimeLimit() ) ); 216 LOG.logError( s, e ); 217 if ( datasource.isFailOnException() ) { 218 OGCWebServiceException exce = new OGCWebServiceException( getClass().getName(), s ); 219 response = new Object[] { new Integer( index ), exce }; 220 } else { 221 response = new Object[] { new Integer( index ), null }; 222 } 223 } catch ( Throwable e ) { 224 // exception can't be re-thrown because responsible GetMapHandler 225 // must collect all responses of all datasources 226 String s = Messages.getMessage( "WMS_ERRORDOSERVICE", e.getMessage() ); 227 LOG.logError( s, e ); 228 if ( datasource.isFailOnException() ) { 229 OGCWebServiceException exce = new OGCWebServiceException( getClass().getName(), s ); 230 response = new Object[] { new Integer( index ), exce }; 231 } else { 232 response = new Object[] { new Integer( index ), null }; 233 } 234 } 235 } 236 237 LOG.logDebug( "Layer " + layer.getName() + " returned." ); 238 239 return response; 240 } 241 242 /** 243 * creates a getFeature request considering the getMap request and the filterconditions defined 244 * in the submitted <tt>DataSource</tt> object. The request will be encapsualted within a 245 * <tt>OGCWebServiceEvent</tt>. 246 * 247 * @param ds 248 * @return GetFeature request object 249 * @throws Exception 250 */ 251 private GetFeature createGetFeatureRequest( LocalWFSDataSource ds ) 252 throws Exception { 253 254 Envelope bbox = transformBBOX( ds ); 255 256 List<PropertyPath> pp = null; 257 if ( style != null ) { 258 List<UserStyle> styleList = new ArrayList<UserStyle>(); 259 styleList.add( style ); 260 pp = StyleUtils.extractRequiredProperties( styleList, scaleDen ); 261 } else { 262 pp = new ArrayList<PropertyPath>(); 263 } 264 PropertyPath geomPP = PropertyPathFactory.createPropertyPath( ds.getGeometryProperty() ); 265 if ( !pp.contains( geomPP ) ) { 266 pp.add( geomPP ); 267 } 268 269 LOG.logDebug( "required properties: ", pp ); 270 Map<String, URI> namesp = extractNameSpaceDef( pp ); 271 272 // no filter condition has been defined 273 StringBuffer sb = new StringBuffer( 5000 ); 274 sb.append( "<?xml version='1.0' encoding='" + CharsetUtils.getSystemCharset() + "'?>" ); 275 sb.append( "<GetFeature xmlns='http://www.opengis.net/wfs' " ); 276 sb.append( "xmlns:ogc='http://www.opengis.net/ogc' " ); 277 sb.append( "xmlns:gml='http://www.opengis.net/gml' " ); 278 sb.append( "xmlns:" ).append( ds.getName().getPrefix() ).append( '=' ); 279 sb.append( "'" ).append( ds.getName().getNamespace() ).append( "' " ); 280 Iterator<String> iter = namesp.keySet().iterator(); 281 while ( iter.hasNext() ) { 282 String pre = iter.next(); 283 URI nsp = namesp.get( pre ); 284 if ( !pre.equals( "xmlns" ) && !pre.equals( ds.getName().getPrefix() ) ) { 285 sb.append( "xmlns:" ).append( pre ).append( "='" ); 286 sb.append( nsp.toASCIIString() ).append( "' " ); 287 } 288 } 289 290 sb.append( "service='WFS' version='1.1.0' " ); 291 if ( ds.getType() == AbstractDataSource.LOCALWFS ) { 292 sb.append( "outputFormat='FEATURECOLLECTION'>" ); 293 } else { 294 sb.append( "outputFormat='text/xml; subtype=gml/3.1.1'>" ); 295 } 296 sb.append( "<Query typeName='" + ds.getName().getPrefixedName() + "'>" ); 297 298 for ( int j = 0; j < pp.size(); j++ ) { 299 if ( !pp.get( j ).getAsString().endsWith( "$SCALE" ) ) { 300 // $SCALE is a dynamicly created property of each feature 301 // and can not be requested 302 sb.append( "<PropertyName>" ).append( pp.get( j ).getAsString() ); 303 sb.append( "</PropertyName>" ); 304 } 305 } 306 307 Query query = ds.getQuery(); 308 if ( query == null ) { 309 sb.append( "<ogc:Filter><ogc:BBOX>" ); 310 sb.append( "<PropertyName>" ); 311 sb.append( ds.getGeometryProperty().getPrefixedName() ); 312 sb.append( "</PropertyName>" ); 313 sb.append( GMLGeometryAdapter.exportAsBox( bbox ) ); 314 sb.append( "</ogc:BBOX>" ); 315 sb.append( "</ogc:Filter></Query></GetFeature>" ); 316 } else { 317 Filter filter = query.getFilter(); 318 sb.append( "<ogc:Filter>" ); 319 if ( filter instanceof ComplexFilter ) { 320 sb.append( "<ogc:And>" ); 321 sb.append( "<ogc:BBOX>" ); 322 sb.append( "<PropertyName>" ); 323 sb.append( ds.getGeometryProperty().getPrefixedName() ); 324 sb.append( "</PropertyName>" ); 325 sb.append( GMLGeometryAdapter.exportAsBox( bbox ) ); 326 sb.append( "</ogc:BBOX>" ); 327 328 // add filter as defined in the layers datasource description 329 // to the filter expression 330 org.deegree.model.filterencoding.Operation op = ( (ComplexFilter) filter ).getOperation(); 331 sb.append( op.toXML() ).append( "</ogc:And>" ); 332 } else { 333 ArrayList<FeatureId> featureIds = ( (FeatureFilter) filter ).getFeatureIds(); 334 if ( featureIds.size() > 1 ) { 335 sb.append( "<ogc:And>" ); 336 } 337 for ( int i = 0; i < featureIds.size(); i++ ) { 338 FeatureId fid = featureIds.get( i ); 339 sb.append( fid.toXML() ); 340 } 341 if ( featureIds.size() > 1 ) { 342 sb.append( "</ogc:And>" ); 343 } 344 } 345 sb.append( "</ogc:Filter></Query></GetFeature>" ); 346 } 347 348 // create dom representation of the request 349 Document doc = XMLTools.parse( new StringReader( sb.toString() ) ); 350 351 LOG.logDebug( "GetFeature request: " + new XMLFragment( doc, "http://www.systemid.org" ).getAsPrettyString() ); 352 353 // create OGCWebServiceEvent object 354 IDGenerator idg = IDGenerator.getInstance(); 355 GetFeature gfr = GetFeature.create( "" + idg.generateUniqueID(), doc.getDocumentElement() ); 356 357 return gfr; 358 } 359 360 /** 361 * transforms the requested BBOX into the DefaultSRS of the assigend feature type 362 * 363 * @param ds 364 * @return the envelope 365 * @throws OGCWebServiceException 366 * @throws CRSTransformationException 367 * @throws CRSException 368 * @throws Proj4Exception 369 */ 370 private Envelope transformBBOX( LocalWFSDataSource ds ) 371 throws OGCWebServiceException, CRSTransformationException, CRSException { 372 Envelope bbox = request.getBoundingBox(); 373 // transform request bounding box to the coordinate reference 374 // system the WFS holds the data if requesting CRS and WFS-Data 375 // crs are different 376 WFService wfs = (WFService) ds.getOGCWebService(); 377 // WFSCapabilities capa = (WFSCapabilities)wfs.getWFSCapabilities(); 378 WFSCapabilities capa = wfs.getCapabilities(); 379 QualifiedName gn = ds.getName(); 380 WFSFeatureType ft = capa.getFeatureTypeList().getFeatureType( gn ); 381 382 if ( ft == null ) { 383 throw new OGCWebServiceException( Messages.getMessage( "WMS_UNKNOWNFT", ds.getName() ) ); 384 } 385 386 // enable different formatations of the crs encoding for GML geometries 387 String GML_SRS = "http://www.opengis.net/gml/srs/"; 388 String old_gml_srs = ft.getDefaultSRS().toASCIIString(); 389 String old_srs; 390 if ( old_gml_srs.startsWith( GML_SRS ) ) { 391 old_srs = old_gml_srs.substring( 31 ).replace( '#', ':' ).toUpperCase(); 392 } else { 393 old_srs = old_gml_srs; 394 } 395 396 String new_srs = request.getSrs(); 397 String new_gml_srs; 398 if ( old_gml_srs.startsWith( GML_SRS ) ) { 399 new_gml_srs = GML_SRS + new_srs.replace( ':', '#' ).toLowerCase(); 400 } else { 401 new_gml_srs = new_srs; 402 } 403 404 if ( !( old_srs.equalsIgnoreCase( new_gml_srs ) ) ) { 405 IGeoTransformer transformer = new GeoTransformer( CRSFactory.create( old_srs ) ); 406 bbox = transformer.transform( bbox, this.handler.getRequestCRS() ); 407 } 408 return bbox; 409 } 410 411 /** 412 * creates a getCoverage request considering the getMap request and the filterconditions defined 413 * in the submitted <tt>DataSource</tt> object The request will be encapsualted within a 414 * <tt>OGCWebServiceEvent</tt>. 415 * 416 * @param ds 417 * @return GetCoverage request object 418 * @throws InconsistentRequestException 419 */ 420 protected static GetCoverage createGetCoverageRequest( AbstractDataSource ds, GetMap request ) 421 throws InconsistentRequestException { 422 423 Envelope bbox = request.getBoundingBox(); 424 425 GetCoverage gcr = ( (LocalWCSDataSource) ds ).getGetCoverageRequest(); 426 427 String crs = request.getSrs(); 428 // if (gcr != null && gcr.getDomainSubset().getRequestSRS() != null) { 429 // crs = gcr.getDomainSubset().getRequestSRS().getCode(); 430 // } 431 String format = request.getFormat(); 432 int pos = format.indexOf( '/' ); 433 if ( pos > -1 ) 434 format = format.substring( pos + 1, format.length() ); 435 if ( gcr != null && !"%default%".equals( gcr.getOutput().getFormat().getCode() ) ) { 436 format = gcr.getOutput().getFormat().getCode(); 437 } 438 if ( format.indexOf( "svg" ) > -1 ) { 439 format = "tiff"; 440 } 441 442 String version = "1.0.0"; 443 if ( gcr != null && gcr.getVersion() != null ) { 444 version = gcr.getVersion(); 445 } 446 String lay = ds.getName().getPrefixedName(); 447 if ( gcr != null && !"%default%".equals( gcr.getSourceCoverage() ) ) { 448 lay = gcr.getSourceCoverage(); 449 } 450 String ipm = null; 451 if ( gcr != null && gcr.getInterpolationMethod() != null ) { 452 ipm = gcr.getInterpolationMethod().value; 453 } 454 455 // TODO 456 // handle rangesets e.g. time and elevation 457 StringBuffer sb = new StringBuffer( 1000 ); 458 sb.append( "service=WCS&request=GetCoverage" ); 459 sb.append( "&version=" ).append( version ); 460 sb.append( "&COVERAGE=" ).append( lay ); 461 sb.append( "&crs=" ).append( crs ); 462 sb.append( "&response_crs=" ).append( crs ); 463 sb.append( "&BBOX=" ).append( bbox.getMin().getX() ).append( ',' ); 464 sb.append( bbox.getMin().getY() ).append( ',' ).append( bbox.getMax().getX() ); 465 sb.append( ',' ).append( bbox.getMax().getY() ); 466 sb.append( "&WIDTH=" ).append( request.getWidth() ); 467 sb.append( "&HEIGHT=" ).append( request.getHeight() ); 468 sb.append( "&FORMAT=" ).append( format ); 469 sb.append( "&INTERPOLATIONMETHOD=" ).append( ipm ); 470 try { 471 IDGenerator idg = IDGenerator.getInstance(); 472 gcr = GetCoverage.create( "id" + idg.generateUniqueID(), sb.toString() ); 473 } catch ( WCSException e ) { 474 throw new InconsistentRequestException( e.getMessage() ); 475 } catch ( org.deegree.ogcwebservices.OGCWebServiceException e ) { 476 throw new InconsistentRequestException( e.getMessage() ); 477 } 478 479 LOG.logDebug( "GetCoverage request: " + sb.toString() ); 480 481 return gcr; 482 483 } 484 485 /** 486 * 487 * @param result 488 * @return the response objects 489 * @throws Exception 490 */ 491 private Object[] handleResponse( Object result ) 492 throws Exception { 493 494 Object[] theme = null; 495 if ( result instanceof ResultCoverage ) { 496 theme = handleGetCoverageResponse( (ResultCoverage) result ); 497 } else if ( result instanceof FeatureResult ) { 498 theme = handleGetFeatureResponse( (FeatureResult) result ); 499 } else if ( result instanceof GetMapResult ) { 500 theme = handleGetMapResponse( (GetMapResult) result ); 501 } else { 502 String s = Messages.getMessage( "WMS_UNKNOWNRESPONSEFORMAT" ); 503 if ( datasource.isFailOnException() ) { 504 OGCWebServiceException exce = new OGCWebServiceException( getClass().getName(), s ); 505 theme = new Object[] { new Integer( index ), exce }; 506 } else { 507 theme = new Object[] { new Integer( index ), null }; 508 } 509 } 510 return theme; 511 } 512 513 /** 514 * replaces all pixels within the passed image having a color that is defined to be transparent 515 * within their datasource with a transparent color. 516 * 517 * @param img 518 * @return modified image 519 */ 520 private BufferedImage setTransparentColors( BufferedImage img ) { 521 522 Color[] colors = null; 523 if ( datasource.getType() == AbstractDataSource.LOCALWCS ) { 524 LocalWCSDataSource ds = (LocalWCSDataSource) datasource; 525 colors = ds.getTransparentColors(); 526 } else { 527 RemoteWMSDataSource ds = (RemoteWMSDataSource) datasource; 528 colors = ds.getTransparentColors(); 529 } 530 531 if ( colors != null && colors.length > 0 ) { 532 533 int[] clrs = new int[colors.length]; 534 for ( int i = 0; i < clrs.length; i++ ) { 535 clrs[i] = colors[i].getRGB(); 536 } 537 538 if ( img.getType() != BufferedImage.TYPE_INT_ARGB ) { 539 // if the incoming image does not allow transparency 540 // it must be copyed to a image of ARGB type 541 BufferedImage tmp = new BufferedImage( img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB ); 542 Graphics g = tmp.getGraphics(); 543 g.drawImage( img, 0, 0, null ); 544 g.dispose(); 545 img = tmp; 546 } 547 548 // TODO 549 // should be replaced by a JAI operation 550 int w = img.getWidth(); 551 int h = img.getHeight(); 552 for ( int i = 0; i < w; i++ ) { 553 for ( int j = 0; j < h; j++ ) { 554 int col = img.getRGB( i, j ); 555 if ( shouldBeTransparent( colors, col ) ) { 556 img.setRGB( i, j, 0x00FFFFFF ); 557 } 558 } 559 } 560 561 } 562 563 return img; 564 } 565 566 /** 567 * @return true if the distance between the image color and at least of the colors to be truned 568 * to be transparent is less than 3 in an int RGB cube 569 * 570 * @param colors 571 * @param color 572 */ 573 private boolean shouldBeTransparent( Color[] colors, int color ) { 574 Color c2 = new Color( color ); 575 int r = c2.getRed(); 576 int g = c2.getGreen(); 577 int b = c2.getBlue(); 578 for ( int i = 0; i < colors.length; i++ ) { 579 int r1 = colors[i].getRed(); 580 int g1 = colors[i].getGreen(); 581 int b1 = colors[i].getBlue(); 582 if ( Math.sqrt( ( r1 - r ) * ( r1 - r ) + ( g1 - g ) * ( g1 - g ) + ( b1 - b ) * ( b1 - b ) ) < 3 ) { 583 return true; 584 } 585 } 586 return false; 587 } 588 589 /** 590 * handles the response of a cascaded WMS and calls a factory to create <tt>DisplayElement</tt> 591 * and a <tt>Theme</tt> from it 592 * 593 * @param response 594 * @return the response objects 595 * @throws Exception 596 */ 597 private Object[] handleGetMapResponse( GetMapResult response ) 598 throws Exception { 599 600 BufferedImage bi = (BufferedImage) response.getMap(); 601 602 bi = setTransparentColors( bi ); 603 GridCoverage gc = new ImageGridCoverage( null, request.getBoundingBox(), bi ); 604 org.deegree.graphics.Layer rl = MapFactory.createRasterLayer( layer.getName(), gc ); 605 Theme theme = MapFactory.createTheme( datasource.getName().getPrefixedName(), rl, new UserStyle[] { style } ); 606 Object[] ro = new Object[2]; 607 ro[0] = new Integer( index ); 608 ro[1] = theme; 609 return ro; 610 611 } 612 613 /** 614 * handles the response of a WFS and calls a factory to create <tt>DisplayElement</tt> and a 615 * <tt>Theme</tt> from it 616 * 617 * @param response 618 * @return the response objects 619 * @throws Exception 620 */ 621 private Object[] handleGetFeatureResponse( FeatureResult response ) 622 throws Exception { 623 624 FeatureCollection fc = null; 625 626 Object o = response.getResponse(); 627 if ( o instanceof FeatureCollection ) { 628 fc = (FeatureCollection) o; 629 } else { 630 throw new Exception( Messages.getMessage( "WMS_UNKNOWNDATAFORMATFT" ) ); 631 } 632 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 633 LOG.logDebug( "result: " + fc ); 634 for ( int i = 0; i < fc.size(); ++i ) { 635 outputGeometries( fc.getFeature( i ) ); 636 } 637 } 638 639 org.deegree.graphics.Layer fl = MapFactory.createFeatureLayer( layer.getName(), this.handler.getRequestCRS(), 640 fc ); 641 642 Object[] ro = new Object[2]; 643 ro[0] = new Integer( index ); 644 ro[1] = MapFactory.createTheme( datasource.getName().getPrefixedName(), fl, new UserStyle[] { style } ); 645 return ro; 646 } 647 648 private void outputGeometries( Feature feature ) { 649 if ( feature == null ) { 650 return; 651 } 652 FeatureType ft = feature.getFeatureType(); 653 PropertyType[] propertyTypes = ft.getProperties(); 654 for ( PropertyType pt : propertyTypes ) { 655 if ( pt.getType() == Types.FEATURE ) { 656 FeatureProperty[] fp = feature.getProperties( pt.getName() ); 657 if ( fp != null ) { 658 for ( int i = 0; i < fp.length; i++ ) { 659 outputGeometries( (Feature) fp[i].getValue() ); 660 } 661 } 662 } else if ( pt.getType() == Types.GEOMETRY ) { 663 Geometry g = feature.getDefaultGeometryPropertyValue(); 664 if ( g != null ) { 665 try { 666 LOG.logDebug( "geometrie: " + WKTAdapter.export( g ).toString() ); 667 } catch ( GeometryException e ) { 668 LOG.logDebug( "Geometry couldn't be converted to Well Known Text: " + g ); 669 } 670 } 671 } 672 } 673 } 674 675 /** 676 * handles the response of a WCS and calls a factory to create <tt>DisplayElement</tt> and a 677 * <tt>Theme</tt> from it 678 * 679 * @param response 680 * @return the response objects 681 * @throws Exception 682 */ 683 private Object[] handleGetCoverageResponse( ResultCoverage response ) 684 throws Exception { 685 ImageGridCoverage gc = (ImageGridCoverage) response.getCoverage(); 686 Object[] ro = new Object[2]; 687 if ( gc != null ) { 688 BufferedImage bi = gc.getAsImage( -1, -1 ); 689 690 bi = setTransparentColors( bi ); 691 692 gc = new ImageGridCoverage( null, request.getBoundingBox(), bi ); 693 694 org.deegree.graphics.Layer rl = MapFactory.createRasterLayer( layer.getName(), gc ); 695 696 ro[0] = new Integer( index ); 697 ro[1] = MapFactory.createTheme( datasource.getName().getPrefixedName(), rl, new UserStyle[] { style } ); 698 } else { 699 throw new OGCWebServiceException( getClass().getName(), Messages.getMessage( "WMS_NOCOVERAGE", 700 datasource.getName() ) ); 701 } 702 return ro; 703 } 704 705 }