001    // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wms/GetLegendGraphicHandler.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     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     ---------------------------------------------------------------------------*/
044    package org.deegree.ogcwebservices.wms;
045    
046    import java.awt.image.BufferedImage;
047    import java.net.URL;
048    import java.util.List;
049    
050    import org.deegree.datatypes.QualifiedName;
051    import org.deegree.framework.log.ILogger;
052    import org.deegree.framework.log.LoggerFactory;
053    import org.deegree.framework.util.ImageUtils;
054    import org.deegree.framework.util.StringTools;
055    import org.deegree.graphics.legend.LegendElement;
056    import org.deegree.graphics.legend.LegendFactory;
057    import org.deegree.graphics.sld.SLDFactory;
058    import org.deegree.graphics.sld.StyledLayerDescriptor;
059    import org.deegree.graphics.sld.UserStyle;
060    import org.deegree.i18n.Messages;
061    import org.deegree.ogcwebservices.OGCWebServiceException;
062    import org.deegree.ogcwebservices.wms.capabilities.Layer;
063    import org.deegree.ogcwebservices.wms.capabilities.LegendURL;
064    import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationType;
065    import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic;
066    import org.deegree.ogcwebservices.wms.operation.GetLegendGraphicResult;
067    import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory;
068    import org.deegree.owscommon_new.DCP;
069    import org.deegree.owscommon_new.HTTP;
070    import org.deegree.owscommon_new.Operation;
071    import org.deegree.owscommon_new.OperationsMetadata;
072    
073    /**
074     * performs a GetLegendGraphic request. The capability of the deegree implementation
075     * is limited to handle requests containing a named style or using the (named) styles
076     * defined in a passed or referenced SLD. featuretype and rule are not supported yet.
077     *
078     * @version $Revision: 6259 $
079     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
080     * @author last edited by: $Author: bezema $
081     *
082     * @version 1.0. $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
083     *
084     * @since 1.1
085     */
086    class GetLegendGraphicHandler {
087    
088        private static final ILogger LOG = LoggerFactory.getLogger( GetLegendGraphicHandler.class );
089    
090        private WMSConfigurationType configuration = null;
091    
092        private StyledLayerDescriptor sld = null;
093    
094        private GetLegendGraphic request = null;
095    
096        /**
097         * Creates a new GetMapHandler object.        
098         * @param capabilities 
099         * @param request request to perform
100         */
101        public GetLegendGraphicHandler( WMSConfigurationType capabilities, GetLegendGraphic request ) {
102            this.configuration = capabilities;
103            this.request = request;
104        }
105    
106        /**
107         * performs the request and returns the result of it.
108         * @return the result object
109         * @throws OGCWebServiceException 
110         */
111        public GetLegendGraphicResult performGetLegendGraphic()
112                                throws OGCWebServiceException {
113    
114            validate( request );
115            LegendElement lege = getSymbol( request );
116            BufferedImage bi = null;
117            try {
118                bi = lege.exportAsImage( request.getFormat() );
119            } catch ( Exception e ) {
120                LOG.logError( e.getMessage(), e );
121                throw new OGCWebServiceException( getClass().getName(), e.getMessage() );
122            }
123    
124            GetLegendGraphicResult res = WMSProtocolFactory.createGetLegendGraphicResponse( request, bi );
125    
126            return res;
127        }
128    
129        /**
130         * validates if the passed request is valid against the WMS it was sent to
131         * and the SLD maybe contained or referenced in/by the request.
132         * @param request request to validate
133         */
134        private void validate( GetLegendGraphic request )
135                                throws OGCWebServiceException {
136    
137            String layerName = request.getLayer();
138            String style = request.getStyle();
139    
140            if ( request.getSLD() == null && request.getSLD_Body() == null ) {
141                Layer layer = configuration.getLayer( layerName );
142                if ( layer == null ) {
143                    String s = Messages.getMessage( "WMS_UNKNOWNLAYER", layerName );
144                    throw new LayerNotDefinedException( s );
145                }
146                if ( getNamedStyle( style ) == null ) {
147                    String s = Messages.getMessage( "WMS_STYLENOTKNOWN", style );
148                    throw new StyleNotDefinedException( s );
149                }
150            } else {
151                try {
152                    if ( request.getSLD() != null ) {
153                        sld = SLDFactory.createSLD( request.getSLD() );
154                    } else {
155                        sld = SLDFactory.createSLD( request.getSLD_Body() );
156                    }
157                    // check if layer and style are present
158                    org.deegree.graphics.sld.AbstractLayer[] sldLayers = sld.getLayers();
159                    boolean found = false;
160                    for ( int i = 0; i < sldLayers.length; i++ ) {
161                        if ( layerName.equals( sldLayers[i].getName() ) ) {
162                            org.deegree.graphics.sld.AbstractStyle[] sldStyles = sldLayers[i].getStyles();
163                            for ( int k = 0; k < sldStyles.length; k++ ) {
164                                if ( sldStyles[k].getName().equals( style ) ) {
165                                    found = true;
166                                    break;
167                                }
168                            }
169                            if ( found )
170                                break;
171                        }
172                    }
173                    if ( !found ) {
174                        String s = Messages.getMessage( "WMS_LAYERNOTKNOWN",
175                                                        layerName );
176                        throw new OGCWebServiceException( getClass().getName(), s );
177                    }
178    
179                } catch ( Exception e ) {
180                    LOG.logError( e.getMessage(), e );
181                    String s = Messages.getMessage( "WMS_INVALIDSLDREF" );
182                    throw new OGCWebServiceException( getClass().getName(), s );
183                }
184    
185            }
186    
187        }
188    
189        private org.deegree.ogcwebservices.wms.capabilities.Style getNamedStyle( String name ) {
190            String layerName = request.getLayer();
191            Layer layer = configuration.getLayer( layerName );
192            org.deegree.ogcwebservices.wms.capabilities.Style[] styles = layer.getStyles();
193            for ( int i = 0; i < styles.length; i++ ) {
194                if ( styles[i].getName().equals( name ) ) {
195                    return styles[i];
196                }
197            }
198            return null;
199        }
200    
201        /**
202         * @param request
203         * @return the symbol
204         * @throws WebServiceException
205         */
206        private LegendElement getSymbol( GetLegendGraphic request )
207                                throws OGCWebServiceException {
208    
209            LegendElement le = null;
210            try {
211                if ( request.getSLD() == null && request.getSLD_Body() == null ) {
212                    le = getFromWellKnownStyle();
213                } else {
214                    le = getFromSLDStyle();
215                }
216            } catch ( Exception e ) {
217                LOG.logError( e.getMessage(), e );
218                String s = Messages.getMessage( "WMS_LEGENDELEM" );
219                throw new OGCWebServiceException( getClass().getName(), s );
220            }
221    
222            return le;
223        }
224    
225        /**
226         * creates a LegendElement from a style known by the WMS
227         */
228        private LegendElement getFromWellKnownStyle()
229                                throws OGCWebServiceException {
230    
231            String layerName = request.getLayer();
232            String styleName = request.getStyle();
233            LegendElement le = null;
234            LegendFactory lf = new LegendFactory();
235    
236            try {
237                // get Layer object from the WMS capabilities
238                Layer layer = configuration.getLayer( layerName );
239                // get the Style section from the matching the requested style
240                org.deegree.ogcwebservices.wms.capabilities.Style nStyle = getNamedStyle( styleName );
241                LegendURL[] lURLs = nStyle.getLegendURL();
242                OperationsMetadata om = configuration.getOperationMetadata();
243                Operation op = om.getOperation( new QualifiedName( "GetLegendGraphic" ) );
244                URL url = null;
245                if ( op != null ) {
246                    // TODO
247                    // should check if really HTTP
248                    List<DCP> dcpList = op.getDCP();
249                    HTTP http = (HTTP) dcpList.get( 0 );
250                    url = http.getLinks().get( 0 ).getLinkage().getHref();
251                    if ( lURLs[0].getOnlineResource().getHost().equals( url.getHost() ) ) {
252                        String s = StringTools.concat( 200, "GetLegendGraphic request ",
253                                                       "to the WMS itself has been set has defined ",
254                                                       "as LegendURL for layer: ", layerName );
255                        LOG.logInfo( s );
256                        // avoid cyclic calling of WMS
257                        UserStyle style = layer.getStyle( styleName );
258                        if ( style != null ) {
259                            // drawing legend symbol
260                            String title = configuration.getLayer( layerName ).getTitle();
261                            le = lf.createLegendElement( style, request.getWidth(),
262                                                         request.getHeight(), title );
263                        } else {
264                            s = Messages.getMessage( "WMS_GENERALSTYLEERROR",
265                                                     styleName );
266                            throw new OGCWebServiceException( getClass().getName(), s );
267                        }
268                    } else {
269                        // if a legend url is defined will be used for creating the legend
270                        // symbol; otherwise it will be tried to create the legend symbol
271                        // dynamicly       
272                        try {
273                            BufferedImage bi = ImageUtils.loadImage( lURLs[0].getOnlineResource() );
274                            le = lf.createLegendElement( bi );
275                        } catch ( Exception e ) {
276                            String s = StringTools.concat( 200, "can not open legen URL: ",
277                                                           lURLs[0].getOnlineResource(),
278                                                           "; try to create ",
279                                                           "legend symbol dynamicly." );
280                            LOG.logInfo( s );
281                            UserStyle style = layer.getStyle( styleName );
282                            if ( style != null ) {
283                                // drawing legend symbol
284                                String title = configuration.getLayer( layerName ).getTitle();
285                                le = lf.createLegendElement( style, request.getWidth(),
286                                                             request.getHeight(), title );
287                            } else {
288                                s = Messages.getMessage( "WMS_GENERALSTYLEERROR",
289                                                         styleName );
290                                throw new OGCWebServiceException( getClass().getName(), s );
291                            }
292                        }
293    
294                    }
295                }
296    
297            } catch ( Exception e ) {
298                LOG.logError( e.getMessage(), e );
299                throw new OGCWebServiceException( e.getMessage() );
300            }
301            return le;
302        }
303    
304        /**
305         * creates a LegendElement from a style defined in the SLD document 
306         * passed/referenced by/in the request
307         */
308        private LegendElement getFromSLDStyle()
309                                throws OGCWebServiceException {
310    
311            String layerName = request.getLayer();
312            String styleName = request.getStyle();
313            LegendElement le = null;
314            LegendFactory lf = new LegendFactory();
315    
316            try {
317                org.deegree.graphics.sld.AbstractLayer[] sldLayers = sld.getLayers();
318                for ( int i = 0; i < sldLayers.length; i++ ) {
319                    if ( layerName.equals( sldLayers[i].getName() ) ) {
320                        org.deegree.graphics.sld.AbstractStyle[] sldStyles = sldLayers[i].getStyles();
321                        org.deegree.graphics.sld.AbstractStyle style = null;
322                        if ( styleName == null ) {
323                            style = sldStyles[0];
324                        } else {
325                            for ( int k = 0; k < sldStyles.length; k++ ) {
326                                if ( sldStyles[k].getName().equals( styleName ) ) {
327                                    style = sldStyles[k];
328                                    break;
329                                }
330                            }
331                        }
332                        String title = configuration.getLayer( layerName ).getTitle();
333                        le = lf.createLegendElement( style, request.getWidth(), request.getHeight(),
334                                                     title );
335                    }
336                }
337            } catch ( Exception e ) {
338                LOG.logError( e.getMessage(), e );
339                throw new OGCWebServiceException( StringTools.stackTraceToString( e.getStackTrace() ) );
340            }
341    
342            return le;
343        }
344    
345    }
346    /* ********************************************************************
347     Changes to this class. What the people have been up to:
348     $Log$
349     Revision 1.22  2006/11/29 13:00:36  schmitz
350     Cleaned up WMS messages.
351    
352     Revision 1.21  2006/11/24 09:33:12  schmitz
353     Fixed a bug concerning layer specific scale hints.
354     Using the central i18n mechanism.
355     Changed the localwfs mechanism to just use one WFS and not recreate them.
356    
357     Revision 1.20  2006/09/08 08:42:01  schmitz
358     Updated the WMS to be 1.1.1 conformant once again.
359     Cleaned up the WMS code.
360     Added cite WMS test data.
361    
362     Revision 1.19  2006/08/29 09:48:47  poth
363     bug fix
364    
365     Revision 1.18  2006/08/23 07:10:21  schmitz
366     Renamed the owscommon_neu package to owscommon_new.
367    
368     Revision 1.17  2006/08/22 10:25:01  schmitz
369     Updated the WMS to use the new OWS common package.
370     Updated the rest of deegree to use the new data classes returned
371     by the updated WMS methods/capabilities.
372    
373     Revision 1.16  2006/07/28 08:01:27  schmitz
374     Updated the WMS for 1.1.1 compliance.
375     Fixed some documentation.
376    
377     Revision 1.15  2006/07/11 14:08:37  schmitz
378     Fixed some documentation warnings.
379    
380     Revision 1.14  2006/06/06 13:20:03  poth
381     bug fix - avoiding cyclic GetLegendGraphic requests
382    
383     Revision 1.13  2006/06/06 07:57:50  poth
384     changes in logging
385    
386     Revision 1.12  2006/05/29 06:37:29  poth
387     supported for requesting named layer groups are added (layers which include layers which include layers ... see WMS spec)
388    
389     Revision 1.11  2006/04/06 20:25:29  poth
390     *** empty log message ***
391    
392     Revision 1.10  2006/04/04 20:39:43  poth
393     *** empty log message ***
394    
395     Revision 1.9  2006/03/30 21:20:27  poth
396     *** empty log message ***
397    
398     Revision 1.8  2006/03/07 21:40:20  poth
399     *** empty log message ***
400    
401     Revision 1.7  2006/03/02 12:58:38  poth
402     *** empty log message ***
403    
404    
405     ********************************************************************** */