001    // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wms/GetLegendGraphicHandler.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 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 is limited to
075     * handle requests containing a named style or using the (named) styles defined in a passed or
076     * referenced SLD. featuretype and rule are not supported yet.
077     * 
078     * @version $Revision: 9345 $
079     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
080     * @author last edited by: $Author: apoth $
081     * 
082     * @version 1.0. $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 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         * 
099         * @param capabilities
100         * @param request
101         *            request to perform
102         */
103        public GetLegendGraphicHandler( WMSConfigurationType capabilities, GetLegendGraphic request ) {
104            this.configuration = capabilities;
105            this.request = request;
106        }
107    
108        /**
109         * performs the request and returns the result of it.
110         * 
111         * @return the result object
112         * @throws OGCWebServiceException
113         */
114        public GetLegendGraphicResult performGetLegendGraphic()
115                                throws OGCWebServiceException {
116    
117            validate( request );
118            LegendElement lege = getSymbol( request );
119            BufferedImage bi = null;
120            try {
121                bi = lege.exportAsImage( request.getFormat() );
122            } catch ( Exception e ) {
123                LOG.logError( e.getMessage(), e );
124                throw new OGCWebServiceException( getClass().getName(), e.getMessage() );
125            }
126    
127            GetLegendGraphicResult res = WMSProtocolFactory.createGetLegendGraphicResponse( request, bi );
128    
129            return res;
130        }
131    
132        /**
133         * validates if the passed request is valid against the WMS it was sent to and the SLD maybe
134         * contained or referenced in/by the request.
135         * 
136         * @param request
137         *            request to validate
138         */
139        private void validate( GetLegendGraphic request )
140                                throws OGCWebServiceException {
141    
142            String layerName = request.getLayer();
143            String style = request.getStyle();
144    
145            if ( request.getSLD() == null && request.getSLD_Body() == null ) {
146                Layer layer = configuration.getLayer( layerName );
147                if ( layer == null ) {
148                    String s = Messages.getMessage( "WMS_UNKNOWNLAYER", layerName );
149                    throw new LayerNotDefinedException( s );
150                }
151                if ( getNamedStyle( style ) == null ) {
152                    String s = Messages.getMessage( "WMS_STYLENOTKNOWN", style );
153                    throw new StyleNotDefinedException( s );
154                }
155            } else {
156                try {
157                    if ( request.getSLD() != null ) {
158                        sld = SLDFactory.createSLD( request.getSLD() );
159                    } else {
160                        sld = SLDFactory.createSLD( request.getSLD_Body() );
161                    }
162                    // check if layer and style are present
163                    org.deegree.graphics.sld.AbstractLayer[] sldLayers = sld.getLayers();
164                    boolean found = false;
165                    for ( int i = 0; i < sldLayers.length; i++ ) {
166                        if ( layerName.equals( sldLayers[i].getName() ) ) {
167                            org.deegree.graphics.sld.AbstractStyle[] sldStyles = sldLayers[i].getStyles();
168                            for ( int k = 0; k < sldStyles.length; k++ ) {
169                                if ( sldStyles[k].getName().equals( style ) ) {
170                                    found = true;
171                                    break;
172                                }
173                            }
174                            if ( found )
175                                break;
176                        }
177                    }
178                    if ( !found ) {
179                        String s = Messages.getMessage( "WMS_LAYERNOTKNOWN", layerName );
180                        throw new OGCWebServiceException( getClass().getName(), s );
181                    }
182    
183                } catch ( Exception e ) {
184                    LOG.logError( e.getMessage(), e );
185                    String s = Messages.getMessage( "WMS_INVALIDSLDREF" );
186                    throw new OGCWebServiceException( getClass().getName(), s );
187                }
188    
189            }
190    
191        }
192    
193        private org.deegree.ogcwebservices.wms.capabilities.Style getNamedStyle( String name ) {
194            String layerName = request.getLayer();
195            Layer layer = configuration.getLayer( layerName );
196            org.deegree.ogcwebservices.wms.capabilities.Style[] styles = layer.getStyles();
197            for ( int i = 0; i < styles.length; i++ ) {
198                if ( styles[i].getName().equals( name ) ) {
199                    return styles[i];
200                }
201            }
202            return null;
203        }
204    
205        /**
206         * @param request
207         * @return the symbol
208         * @throws WebServiceException
209         */
210        private LegendElement getSymbol( GetLegendGraphic request )
211                                throws OGCWebServiceException {
212    
213            LegendElement le = null;
214            try {
215                if ( request.getSLD() == null && request.getSLD_Body() == null ) {
216                    le = getFromWellKnownStyle();
217                } else {
218                    le = getFromSLDStyle();
219                }
220            } catch ( Exception e ) {
221                LOG.logError( e.getMessage(), e );
222                String s = Messages.getMessage( "WMS_LEGENDELEM" );
223                throw new OGCWebServiceException( getClass().getName(), s );
224            }
225    
226            return le;
227        }
228    
229        /**
230         * creates a LegendElement from a style known by the WMS
231         */
232        private LegendElement getFromWellKnownStyle()
233                                throws OGCWebServiceException {
234    
235            String layerName = request.getLayer();
236            String styleName = request.getStyle();
237            LegendElement le = null;
238            LegendFactory lf = new LegendFactory();
239    
240            try {
241                // get Layer object from the WMS capabilities
242                Layer layer = configuration.getLayer( layerName );
243                // get the Style section from the matching the requested style
244                org.deegree.ogcwebservices.wms.capabilities.Style nStyle = getNamedStyle( styleName );
245                LegendURL[] lURLs = nStyle.getLegendURL();
246                OperationsMetadata om = configuration.getOperationMetadata();
247                Operation op = om.getOperation( new QualifiedName( "GetLegendGraphic" ) );
248                URL url = null;
249                if ( op != null ) {
250                    // TODO
251                    // should check if really HTTP
252                    List<DCP> dcpList = op.getDCP();
253                    HTTP http = (HTTP) dcpList.get( 0 );
254                    url = http.getLinks().get( 0 ).getLinkage().getHref();
255                    if ( lURLs[0].getOnlineResource().getHost().equals( url.getHost() ) ) {
256                        String s = StringTools.concat( 200, "GetLegendGraphic request ",
257                                                       "to the WMS itself has been set has defined ",
258                                                       "as LegendURL for layer: ", layerName );
259                        LOG.logInfo( s );
260                        // avoid cyclic calling of WMS
261                        UserStyle style = layer.getStyle( styleName );
262                        if ( style != null ) {
263                            // drawing legend symbol
264                            String title = configuration.getLayer( layerName ).getTitle();
265                            le = lf.createLegendElement( style, request.getWidth(), request.getHeight(), title );
266                        } else {
267                            s = Messages.getMessage( "WMS_GENERALSTYLEERROR", styleName );
268                            throw new OGCWebServiceException( getClass().getName(), s );
269                        }
270                    } else {
271                        // if a legend url is defined will be used for creating the legend
272                        // symbol; otherwise it will be tried to create the legend symbol
273                        // dynamicly
274                        try {
275                            BufferedImage bi = ImageUtils.loadImage( lURLs[0].getOnlineResource() );
276                            le = lf.createLegendElement( bi );
277                        } catch ( Exception e ) {
278                            String s = StringTools.concat( 200, "can not open legen URL: ", lURLs[0].getOnlineResource(),
279                                                           "; try to create ", "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(), request.getHeight(), title );
286                            } else {
287                                s = Messages.getMessage( "WMS_GENERALSTYLEERROR", styleName );
288                                throw new OGCWebServiceException( getClass().getName(), s );
289                            }
290                        }
291    
292                    }
293                }
294    
295            } catch ( Exception e ) {
296                LOG.logError( e.getMessage(), e );
297                throw new OGCWebServiceException( e.getMessage() );
298            }
299            return le;
300        }
301    
302        /**
303         * creates a LegendElement from a style defined in the SLD document passed/referenced by/in the
304         * request
305         */
306        private LegendElement getFromSLDStyle()
307                                throws OGCWebServiceException {
308    
309            String layerName = request.getLayer();
310            String styleName = request.getStyle();
311            LegendElement le = null;
312            LegendFactory lf = new LegendFactory();
313    
314            try {
315                org.deegree.graphics.sld.AbstractLayer[] sldLayers = sld.getLayers();
316                for ( int i = 0; i < sldLayers.length; i++ ) {
317                    if ( layerName.equals( sldLayers[i].getName() ) ) {
318                        org.deegree.graphics.sld.AbstractStyle[] sldStyles = sldLayers[i].getStyles();
319                        org.deegree.graphics.sld.AbstractStyle style = null;
320                        if ( styleName == null ) {
321                            style = sldStyles[0];
322                        } else {
323                            for ( int k = 0; k < sldStyles.length; k++ ) {
324                                if ( sldStyles[k].getName().equals( styleName ) ) {
325                                    style = sldStyles[k];
326                                    break;
327                                }
328                            }
329                        }
330                        String title = configuration.getLayer( layerName ).getTitle();
331                        le = lf.createLegendElement( style, request.getWidth(), request.getHeight(), title );
332                    }
333                }
334            } catch ( Exception e ) {
335                LOG.logError( e.getMessage(), e );
336                throw new OGCWebServiceException( StringTools.stackTraceToString( e.getStackTrace() ) );
337            }
338    
339            return le;
340        }
341    
342    }