//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/ogcwebservices/wms/GetMapServiceInvokerForNL.java,v 1.51 2006/12/03 21:21:22 poth Exp $
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.ogcwebservices.wms;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.concurrent.DoServiceTask;
import org.deegree.framework.concurrent.Executor;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.CharsetUtils;
import org.deegree.framework.util.IDGenerator;
import org.deegree.framework.xml.XMLTools;
import org.deegree.graphics.MapFactory;
import org.deegree.graphics.Theme;
import org.deegree.graphics.sld.NamedLayer;
import org.deegree.graphics.sld.StyleUtils;
import org.deegree.graphics.sld.UserStyle;
import org.deegree.i18n.Messages;
import org.deegree.model.coverage.grid.ImageGridCoverage;
import org.deegree.model.crs.CRSFactory;
import org.deegree.model.crs.CRSTransformationException;
import org.deegree.model.crs.GeoTransformer;
import org.deegree.model.crs.IGeoTransformer;
import org.deegree.model.crs.UnknownCRSException;
import org.deegree.model.feature.FeatureCollection;
import org.deegree.model.filterencoding.ComplexFilter;
import org.deegree.model.filterencoding.FeatureFilter;
import org.deegree.model.filterencoding.FeatureId;
import org.deegree.model.filterencoding.Filter;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.GMLGeometryAdapter;
import org.deegree.ogcbase.PropertyPath;
import org.deegree.ogcwebservices.InconsistentRequestException;
import org.deegree.ogcwebservices.OGCWebServiceException;
import org.deegree.ogcwebservices.OGCWebServiceRequest;
import org.deegree.ogcwebservices.wcs.WCSException;
import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
import org.deegree.ogcwebservices.wcs.getcoverage.ResultCoverage;
import org.deegree.ogcwebservices.wfs.WFService;
import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType;
import org.deegree.ogcwebservices.wfs.operation.FeatureResult;
import org.deegree.ogcwebservices.wfs.operation.GetFeature;
import org.deegree.ogcwebservices.wfs.operation.Query;
import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
import org.deegree.ogcwebservices.wms.configuration.LocalWCSDataSource;
import org.deegree.ogcwebservices.wms.configuration.LocalWFSDataSource;
import org.deegree.ogcwebservices.wms.configuration.RemoteWMSDataSource;
import org.deegree.ogcwebservices.wms.operation.GetMap;
import org.deegree.ogcwebservices.wms.operation.GetMapResult;
import org.opengis.coverage.grid.GridCoverage;
import org.w3c.dom.Document;
/**
* Class for accessing the data of one layers datasource and creating a <tt>Theme</tt> from it.
*
* @version $Revision: 1.51 $
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author: poth $
*
* @version 1.0. $Revision: 1.51 $, $Date: 2006/12/03 21:21:22 $
*
* @since 2.0
*/
public class GetMapServiceInvokerForNL extends GetMapServiceInvoker {
private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvokerForNL.class );
private final GetMap request;
private NamedLayer layer = null;
private UserStyle style = null;
private AbstractDataSource datasource = null;
/**
* Creates a new ServiceInvokerForNL object.
*
* @param handler
* @param layer
* @param datasource
* @param style
* @param index
*/
GetMapServiceInvokerForNL( DefaultGetMapHandler handler, NamedLayer layer,
AbstractDataSource datasource, UserStyle style, double scale,
int index ) {
super( handler, index, scale );
this.layer = layer;
this.request = handler.getRequest();
this.style = style;
this.datasource = datasource;
}
/**
* central method for access the data assigned to a datasource
*
* @return the data
*/
public Object run() {
Object response = null;
if ( datasource != null ) {
OGCWebServiceRequest request = null;
try {
int type = datasource.getType();
switch ( type ) {
case AbstractDataSource.LOCALWFS:
case AbstractDataSource.REMOTEWFS: {
request = createGetFeatureRequest( (LocalWFSDataSource) datasource );
break;
}
case AbstractDataSource.LOCALWCS:
case AbstractDataSource.REMOTEWCS: {
request = createGetCoverageRequest( datasource );
break;
}
case AbstractDataSource.REMOTEWMS: {
String styleName = null;
if ( style != null ) {
styleName = style.getName();
}
request = GetMap.createGetMapRequest( datasource, handler.getRequest(),
styleName, layer.getName() );
break;
}
}
} catch ( Exception e ) {
e.printStackTrace();
OGCWebServiceException exce = new OGCWebServiceException(
getClass().getName(),
Messages.getMessage(
"WMS_ERRORQUERYCREATE",
e ) );
// exception can't be re-thrown because responsible GetMapHandler
// must collect all responses of all datasources
response = new Object[] { new Integer( index ), exce };
LOG.logError( e.getMessage(), e );
}
try {
// start reading data with a limited time frame. The time limit
// readed from the datasource muts be multiplied by 1000 because
// the method expects milliseconds as timelimit
Executor executor = Executor.getInstance();
DoServiceTask<Object> task = new DoServiceTask<Object>(
datasource.getOGCWebService(),
request );
Object o = executor.performSynchronously( task,
datasource.getRequestTimeLimit() * 1000 );
response = handleResponse( o );
} catch ( CancellationException e ) {
// exception can't be re-thrown because responsible GetMapHandler
// must collect all responses of all datasources
String s = Messages.getMessage( "WMS_TIMEOUTDATASOURCE",
new Integer( datasource.getRequestTimeLimit() ) );
LOG.logError( s, e );
if ( datasource.isFailOnException() ) {
OGCWebServiceException exce = new OGCWebServiceException( getClass().getName(),
s );
response = new Object[] { new Integer( index ), exce };
} else {
response = new Object[] { new Integer( index ), null };
}
} catch ( Throwable e ) {
// exception can't be re-thrown because responsible GetMapHandler
// must collect all responses of all datasources
String s = Messages.getMessage( "WMS_ERRORDOSERVICE", e.getMessage() );
LOG.logError( s, e );
if ( datasource.isFailOnException() ) {
OGCWebServiceException exce = new OGCWebServiceException( getClass().getName(),
s );
response = new Object[] { new Integer( index ), exce };
} else {
response = new Object[] { new Integer( index ), null };
}
}
}
return response;
}
/**
* creates a getFeature request considering the getMap request and the filterconditions defined
* in the submitted <tt>DataSource</tt> object. The request will be encapsualted within a
* <tt>OGCWebServiceEvent</tt>.
*
* @param ds
* @return GetFeature request object
* @throws Exception
*/
private GetFeature createGetFeatureRequest( LocalWFSDataSource ds )
throws Exception {
Envelope bbox = transformBBOX( ds );
List<PropertyPath> pp = null;
if ( style != null ) {
List<UserStyle> styleList = new ArrayList<UserStyle>();
styleList.add( style );
pp = StyleUtils.extractRequiredProperties( styleList, scaleDen );
} else {
pp = new ArrayList<PropertyPath>();
}
LOG.logDebug( "required properties: ", pp );
Map<String, URI> namesp = extractNameSpaceDef( pp );
// no filter condition has been defined
StringBuffer sb = new StringBuffer( 5000 );
sb.append( "<?xml version='1.0' encoding='" + CharsetUtils.getSystemCharset() + "'?>" );
sb.append( "<GetFeature xmlns='http://www.opengis.net/wfs' " );
sb.append( "xmlns:ogc='http://www.opengis.net/ogc' " );
sb.append( "xmlns:gml='http://www.opengis.net/gml' " );
sb.append( "xmlns:" ).append( ds.getName().getPrefix() ).append( '=' );
sb.append( "'" ).append( ds.getName().getNamespace() ).append( "' " );
Iterator iter = namesp.keySet().iterator();
while ( iter.hasNext() ) {
String pre = (String) iter.next();
URI nsp = namesp.get( pre );
if ( !pre.equals( "xmlns" ) && !pre.equals( ds.getName().getPrefix() ) ) {
sb.append( "xmlns:" ).append( pre ).append( "='" );
sb.append( nsp.toASCIIString() ).append( "' " );
}
}
sb.append( "service='WFS' version='1.1.0' " );
if ( ds.getType() == AbstractDataSource.LOCALWFS ) {
sb.append( "outputFormat='FEATURECOLLECTION'>" );
} else {
sb.append( "outputFormat='text/xml; subtype=gml/3.1.1'>" );
}
sb.append( "<Query typeName='" + ds.getName().getAsString() + "'>" );
for ( int j = 0; j < pp.size(); j++ ) {
if ( !pp.get( j ).getAsString().endsWith( "$SCALE" ) ) {
// $SCALE is a dynamicly created property of each feature
// and can not be requested
sb.append( "<PropertyName>" ).append( pp.get( j ).getAsString() );
sb.append( "</PropertyName>" );
}
}
Query query = ds.getQuery();
if ( query == null ) {
sb.append( "<ogc:Filter><ogc:BBOX>" );
sb.append( "<PropertyName>" );
sb.append( ds.getGeometryProperty().getAsString() );
sb.append( "</PropertyName>" );
sb.append( GMLGeometryAdapter.exportAsBox( bbox ) );
sb.append( "</ogc:BBOX>" );
sb.append( "</ogc:Filter></Query></GetFeature>" );
} else {
Filter filter = query.getFilter();
sb.append( "<ogc:Filter>" );
if ( filter instanceof ComplexFilter ) {
sb.append( "<ogc:And>" );
sb.append( "<ogc:BBOX>" );
sb.append( "<PropertyName>" );
sb.append( ds.getGeometryProperty().getAsString() );
sb.append( "</PropertyName>" );
sb.append( GMLGeometryAdapter.exportAsBox( bbox ) );
sb.append( "</ogc:BBOX>" );
// add filter as defined in the layers datasource description
// to the filter expression
org.deegree.model.filterencoding.Operation op = ( (ComplexFilter) filter ).getOperation();
sb.append( op.toXML() ).append( "</ogc:And>" );
} else {
ArrayList featureIds = ( (FeatureFilter) filter ).getFeatureIds();
if ( featureIds.size() > 1 ) {
sb.append( "<ogc:And>" );
}
for ( int i = 0; i < featureIds.size(); i++ ) {
FeatureId fid = (FeatureId) featureIds.get( i );
sb.append( fid.toXML() );
}
if ( featureIds.size() > 1 ) {
sb.append( "</ogc:And>" );
}
}
sb.append( "</ogc:Filter></Query></GetFeature>" );
}
LOG.logDebug( sb.toString() );
// create dom representation of the request
Document doc = XMLTools.parse( new StringReader( sb.toString() ) );
// create OGCWebServiceEvent object
IDGenerator idg = IDGenerator.getInstance();
GetFeature gfr = GetFeature.create( "" + idg.generateUniqueID(), doc.getDocumentElement() );
return gfr;
}
/**
* transforms the requested BBOX into the DefaultSRS of the assigend
* feature type
*
* @param ds
* @return the envelope
* @throws OGCWebServiceException
* @throws CRSTransformationException
* @throws UnknownCRSException
* @throws Proj4Exception
*/
private Envelope transformBBOX( LocalWFSDataSource ds )
throws OGCWebServiceException, CRSTransformationException,
UnknownCRSException {
Envelope bbox = request.getBoundingBox();
// transform request bounding box to the coordinate reference
// system the WFS holds the data if requesting CRS and WFS-Data
// crs are different
WFService wfs = (WFService) ds.getOGCWebService();
// WFSCapabilities capa = (WFSCapabilities)wfs.getWFSCapabilities();
WFSCapabilities capa = wfs.getCapabilities();
QualifiedName gn = ds.getName();
WFSFeatureType ft = capa.getFeatureTypeList().getFeatureType( gn );
if ( ft == null ) {
throw new OGCWebServiceException( Messages.getMessage( "WMS_UNKNOWNFT", ds.getName() ) );
}
// enable different formatations of the crs encoding for GML geometries
String GML_SRS = "http://www.opengis.net/gml/srs/";
String old_gml_srs = ft.getDefaultSRS().toASCIIString();
String old_srs;
if ( old_gml_srs.startsWith( GML_SRS ) ) {
old_srs = old_gml_srs.substring( 31 ).replace( '#', ':' ).toUpperCase();
} else {
old_srs = old_gml_srs;
}
String new_srs = request.getSrs();
String new_gml_srs;
if ( old_gml_srs.startsWith( GML_SRS ) ) {
new_gml_srs = GML_SRS + new_srs.replace( ':', '#' ).toLowerCase();
} else {
new_gml_srs = new_srs;
}
if ( !( old_srs.equalsIgnoreCase( new_gml_srs ) ) ) {
IGeoTransformer transformer = new GeoTransformer( CRSFactory.create( old_srs ) );
bbox = transformer.transform( bbox, this.handler.getRequestCRS() );
}
return bbox;
}
/**
* creates a getCoverage request considering the getMap request and the filterconditions defined
* in the submitted <tt>DataSource</tt> object The request will be encapsualted within a
* <tt>OGCWebServiceEvent</tt>.
*
* @param ds
* @return GetCoverage request object
* @throws InconsistentRequestException
*/
private GetCoverage createGetCoverageRequest( AbstractDataSource ds )
throws InconsistentRequestException {
Envelope bbox = request.getBoundingBox();
GetCoverage gcr = ( (LocalWCSDataSource) ds ).getGetCoverageRequest();
String crs = request.getSrs();
// if (gcr != null && gcr.getDomainSubset().getRequestSRS() != null) {
// crs = gcr.getDomainSubset().getRequestSRS().getCode();
// }
String format = request.getFormat();
int pos = format.indexOf( '/' );
if ( pos > -1 )
format = format.substring( pos + 1, format.length() );
if ( gcr != null && !"%default%".equals( gcr.getOutput().getFormat().getCode() ) ) {
format = gcr.getOutput().getFormat().getCode();
}
if ( format.indexOf( "svg" ) > -1 ) {
format = "tiff";
}
String version = "1.0.0";
if ( gcr != null && gcr.getVersion() != null ) {
version = gcr.getVersion();
}
String lay = ds.getName().getAsString();
if ( gcr != null && !"%default%".equals( gcr.getSourceCoverage() ) ) {
lay = gcr.getSourceCoverage();
}
String ipm = null;
if ( gcr != null && gcr.getInterpolationMethod() != null ) {
ipm = gcr.getInterpolationMethod().value;
}
// TODO
// handle rangesets e.g. time and elevation
StringBuffer sb = new StringBuffer( 1000 );
sb.append( "service=WCS&request=GetCoverage" );
sb.append( "&version=" ).append( version );
sb.append( "&COVERAGE=" ).append( lay );
sb.append( "&crs=" ).append( crs );
sb.append( "&response_crs=" ).append( crs );
sb.append( "&BBOX=" ).append( bbox.getMin().getX() ).append( ',' );
sb.append( bbox.getMin().getY() ).append( ',' ).append( bbox.getMax().getX() );
sb.append( ',' ).append( bbox.getMax().getY() );
sb.append( "&WIDTH=" ).append( request.getWidth() );
sb.append( "&HEIGHT=" ).append( request.getHeight() );
sb.append( "&FORMAT=" ).append( format );
sb.append( "&INTERPOLATIONMETHOD=" ).append( ipm );
try {
IDGenerator idg = IDGenerator.getInstance();
gcr = GetCoverage.create( "id" + idg.generateUniqueID(), sb.toString() );
} catch ( WCSException e ) {
throw new InconsistentRequestException( e.getMessage() );
} catch ( org.deegree.ogcwebservices.OGCWebServiceException e ) {
throw new InconsistentRequestException( e.getMessage() );
}
return gcr;
}
/**
*
* @param result
* @return the response objects
* @throws Exception
*/
private Object[] handleResponse( Object result )
throws Exception {
Object[] theme = null;
if ( result instanceof ResultCoverage ) {
theme = handleGetCoverageResponse( (ResultCoverage) result );
} else if ( result instanceof FeatureResult ) {
theme = handleGetFeatureResponse( (FeatureResult) result );
} else if ( result instanceof GetMapResult ) {
theme = handleGetMapResponse( (GetMapResult) result );
} else {
String s = Messages.getMessage( "WMS_UNKNOWNRESPONSEFORMAT" );
if ( datasource.isFailOnException() ) {
OGCWebServiceException exce = new OGCWebServiceException( getClass().getName(), s );
theme = new Object[] { new Integer( index ), exce };
} else {
theme = new Object[] { new Integer( index ), null };
}
}
return theme;
}
/**
* replaces all pixels within the passed image having a color that is defined to be transparent
* within their datasource with a transparent color.
*
* @param img
* @return modified image
*/
private BufferedImage setTransparentColors( BufferedImage img ) {
LOG.entering();
Color[] colors = null;
if ( datasource.getType() == AbstractDataSource.LOCALWCS ) {
LocalWCSDataSource ds = (LocalWCSDataSource) datasource;
colors = ds.getTransparentColors();
} else {
RemoteWMSDataSource ds = (RemoteWMSDataSource) datasource;
colors = ds.getTransparentColors();
}
if ( colors != null && colors.length > 0 ) {
int[] clrs = new int[colors.length];
for ( int i = 0; i < clrs.length; i++ ) {
clrs[i] = colors[i].getRGB();
}
if ( img.getType() != BufferedImage.TYPE_INT_ARGB ) {
// if the incoming image does not allow transparency
// it must be copyed to a image of ARGB type
BufferedImage tmp = new BufferedImage( img.getWidth(), img.getHeight(),
BufferedImage.TYPE_INT_ARGB );
Graphics g = tmp.getGraphics();
g.drawImage( img, 0, 0, null );
g.dispose();
img = tmp;
}
// TODO
// should be replaced by a JAI operation
int w = img.getWidth();
int h = img.getHeight();
for ( int i = 0; i < w; i++ ) {
for ( int j = 0; j < h; j++ ) {
int col = img.getRGB( i, j );
if ( shouldBeTransparent( colors, col ) ) {
img.setRGB( i, j, 0x00FFFFFF );
}
}
}
}
LOG.exiting();
return img;
}
/**
* @return true if the distance between the image color and at least of the colors to be truned
* to be transparent is less than 3 in an int RGB cube
*
* @param colors
* @param color
*/
private boolean shouldBeTransparent( Color[] colors, int color ) {
Color c2 = new Color( color );
int r = c2.getRed();
int g = c2.getGreen();
int b = c2.getBlue();
for ( int i = 0; i < colors.length; i++ ) {
int r1 = colors[i].getRed();
int g1 = colors[i].getGreen();
int b1 = colors[i].getBlue();
if ( Math.sqrt( ( r1 - r ) * ( r1 - r ) + ( g1 - g ) * ( g1 - g ) + ( b1 - b )
* ( b1 - b ) ) < 3 ) {
return true;
}
}
return false;
}
/**
* handles the response of a cascaded WMS and calls a factory to create <tt>DisplayElement</tt>
* and a <tt>Theme</tt> from it
*
* @param response
* @return the response objects
* @throws Exception
*/
private Object[] handleGetMapResponse( GetMapResult response )
throws Exception {
BufferedImage bi = (BufferedImage) response.getMap();
bi = setTransparentColors( bi );
GridCoverage gc = new ImageGridCoverage( null, request.getBoundingBox(), bi );
org.deegree.graphics.Layer rl = MapFactory.createRasterLayer( layer.getName(), gc );
Theme theme = MapFactory.createTheme( datasource.getName().getAsString(), rl );
Object[] ro = new Object[2];
ro[0] = new Integer( index );
ro[1] = theme;
return ro;
}
/**
* handles the response of a WFS and calls a factory to create <tt>DisplayElement</tt> and a
* <tt>Theme</tt> from it
*
* @param response
* @return the response objects
* @throws Exception
*/
private Object[] handleGetFeatureResponse( FeatureResult response )
throws Exception {
FeatureCollection fc = null;
Object o = response.getResponse();
if ( o instanceof FeatureCollection ) {
fc = (FeatureCollection) o;
} else {
throw new Exception( Messages.getMessage( "WMS_UNKNOWNDATAFORMATFT" ) );
}
LOG.logDebug( "result: " + fc );
org.deegree.graphics.Layer fl = MapFactory.createFeatureLayer(
layer.getName(),
this.handler.getRequestCRS(),
fc );
Object[] ro = new Object[2];
ro[0] = new Integer( index );
ro[1] = MapFactory.createTheme( datasource.getName().getAsString(), fl,
new UserStyle[] { style } );
return ro;
}
/**
* handles the response of a WCS and calls a factory to create <tt>DisplayElement</tt> and a
* <tt>Theme</tt> from it
*
* @param response
* @return the response objects
* @throws Exception
*/
private Object[] handleGetCoverageResponse( ResultCoverage response )
throws Exception {
LOG.entering();
ImageGridCoverage gc = (ImageGridCoverage) response.getCoverage();
Object[] ro = new Object[2];
if ( gc != null ) {
BufferedImage bi = gc.getAsImage( -1, -1 );
bi = setTransparentColors( bi );
gc = new ImageGridCoverage( null, request.getBoundingBox(), bi );
org.deegree.graphics.Layer rl = MapFactory.createRasterLayer( layer.getName(), gc );
ro[0] = new Integer( index );
ro[1] = MapFactory.createTheme( datasource.getName().getAsString(), rl );
} else {
throw new OGCWebServiceException( getClass().getName(),
Messages.getMessage( "WMS_NOCOVERAGE",
datasource.getName() ) );
}
return ro;
}
}
/***************************************************************************************************
* Changes to this class. What the people have been up to:
* $Log: GetMapServiceInvokerForNL.java,v $
* Revision 1.51 2006/12/03 21:21:22 poth
* support for requesting coverages in different CRS than its native one
*
* Revision 1.50 2006/11/29 13:00:36 schmitz
* Cleaned up WMS messages.
*
* Revision 1.49 2006/11/27 09:07:52 poth
* JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
*
* Revision 1.48 2006/11/24 10:44:43 schmitz
* Fixed bug in call to GetMap createGetMap.
*
* Revision 1.47 2006/11/24 09:33:13 schmitz
* Fixed a bug concerning layer specific scale hints.
* Using the central i18n mechanism.
* Changed the localwfs mechanism to just use one WFS and not recreate them.
*
* Revision 1.46 2006/11/22 14:05:06 schmitz
* Moved some createGetMapRequest methods to GetMap.
* Added a generic DoServiceTask.
*
* Revision 1.45 2006/10/17 20:31:17 poth
* *** empty log message ***
*
* Revision 1.44 2006/10/10 13:46:02 schmitz
* Updated the WMS GetMap and GetFeatureInfo requests to handle sublayers of layers as well.
*
* Revision 1.43 2006/10/10 09:22:38 poth
* bug fix - null checking for style
*
* Revision 1.42 2006/10/08 18:28:18 poth
* footer comment corrected
*
* Revision 1.41 2006/10/07 15:05:28 poth
* creation of GetFeature requests optimized in a way that just required properties will be requested
* Changes to this class. What the people have been up to:
* Revision 1.40 2006/09/27 16:46:41 poth
* transformation method signature changed
* Changes to this class. What the people have been up to:
* Revision 1.39 2006/09/15 09:18:29 schmitz
* Updated WMS to use SLD or SLD_BODY sld documents as default when also giving
* LAYERS and STYLES parameters at the same time.
* Changes to this class. What the people have been up to:
* Revision 1.38 2006/09/08 08:42:01 schmitz
* Updated the WMS to be 1.1.1 conformant once again.
* Cleaned up the WMS code.
* Added cite WMS test data.
* Changes to this class. What the people have been up to:
* Revision 1.37 2006/08/10 13:30:41 mschneider
* Changed TimeoutException to CancellationException (due to changes in Executor). See Executor annotations for further info.
* Changes to this class. What the people have been up to:
* Revision 1.36 2006/08/07 13:52:05 mschneider
* Refactored due to changes in deegree.framework.concurrent package.
* Changes to this class. What the people have been up to:
* Revision 1.35 2006/08/06 19:50:33 poth bug fix - exception handling
*
* Revision 1.34 2006/07/29 08:55:06 poth implementation changed to new
* org.deegree.framework.concurrent packeage
*
* Revision 1.33 2006/07/13 12:24:45 poth adaptions required according to changes in
* org.deegree.ogcwebservice.wms.operations.GetMap
*
* Revision 1.32 2006/07/04 20:55:39 poth bug fix - creating GetFeature request if a filer condition
* is defined
*
* Revision 1.31 2006/06/06 07:57:50 poth changes in logging
*
* Revision 1.30 2006/05/18 16:48:18 poth exception message externalized / bug fix -> GetCoverage
* returns null
*
**************************************************************************************************/