001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/graphics/legend/LegendFactory.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 package org.deegree.graphics.legend; 037 038 import java.awt.image.BufferedImage; 039 import java.util.ArrayList; 040 import java.util.List; 041 042 import org.deegree.framework.log.ILogger; 043 import org.deegree.framework.log.LoggerFactory; 044 import org.deegree.graphics.sld.AbstractStyle; 045 import org.deegree.graphics.sld.FeatureTypeStyle; 046 import org.deegree.graphics.sld.Rule; 047 import org.deegree.graphics.sld.StyledLayerDescriptor; 048 import org.deegree.graphics.sld.UserStyle; 049 import org.deegree.model.filterencoding.ComplexFilter; 050 import org.deegree.model.filterencoding.Filter; 051 import org.deegree.model.filterencoding.Literal; 052 import org.deegree.model.filterencoding.LogicalOperation; 053 import org.deegree.model.filterencoding.Operation; 054 import org.deegree.model.filterencoding.OperationDefines; 055 import org.deegree.model.filterencoding.PropertyIsCOMPOperation; 056 import org.deegree.model.filterencoding.PropertyIsLikeOperation; 057 import org.deegree.model.filterencoding.PropertyName; 058 import org.deegree.model.filterencoding.SpatialOperation; 059 060 /** 061 * factory class for creating legend elements/images to be used with WMS GetLegendGraphic request 062 * 063 * @version $Revision: 18195 $ 064 * @author $author$ 065 */ 066 public class LegendFactory { 067 068 private static final ILogger LOG = LoggerFactory.getLogger( LegendFactory.class ); 069 070 private String label = ""; 071 072 private String legendtitle = ""; 073 074 /** 075 * creates a <tt>LegendElement</tt> using the passed <tt>BufferedImage</tt> 076 * 077 * @param legendImage 078 * to build the legend from 079 * 080 * @return <tt>LegendElement</tt> 081 */ 082 public LegendElement createLegendElement( BufferedImage legendImage ) { 083 return new LegendElement( legendImage ); 084 } 085 086 /** 087 * creates a <tt>LegendElement</tt> from a SLD <tt>Style</tt>. Depending on the <tt>Style</tt> the returned 088 * <tt>LegendElement</tt> may is a <tt>LegendElementCollection</tt>. 089 * 090 * @param style 091 * @param width 092 * @param height 093 * @param title 094 * 095 * @return <tt>LegendElement</tt> 096 * @throws LegendException 097 */ 098 public LegendElement createLegendElement( AbstractStyle style, int width, int height, String title ) 099 throws LegendException { 100 101 setLegendTitle( title ); 102 103 if ( style instanceof UserStyle ) { 104 105 LegendElement le = null; 106 107 FeatureTypeStyle[] fts = ( (UserStyle) style ).getFeatureTypeStyles(); 108 LegendElementCollection lec = new LegendElementCollection(); 109 110 for ( int a = 0; a < fts.length; a++ ) { 111 // legendtitle 112 if ( title != null && title.length() > 0 ) { 113 if ( ( (UserStyle) style ).getTitle() != null ) { 114 setLegendTitle( ( (UserStyle) style ).getTitle() ); 115 } else { 116 setLegendTitle( title ); 117 } 118 } else { 119 setLegendTitle( fts[a].getName() ); 120 } 121 Rule[] rules = fts[a].getRules(); 122 123 for ( int b = 0; b < rules.length; b++ ) { 124 125 if ( rules[b].getFilter() != null ) { 126 Filter f = rules[b].getFilter(); 127 String category = rules[b].getTitle(); 128 if ( category == null ) { 129 category = rules[b].getName(); 130 } 131 if ( category == null ) { 132 category = getPropertyNameFromFilter( f ); 133 } 134 le = new LegendElement( new Rule[] { rules[b] }, category, 0, 4, true, width, height ); 135 lec.addLegendElement( le ); 136 } else { 137 String category = ( (UserStyle) style ).getTitle(); 138 if ( category == null ) { 139 category = ( (UserStyle) style ).getName(); 140 } 141 if ( category == null ) { 142 category = title; 143 } 144 category = ""; 145 le = new LegendElement( rules, category, 0, 4, true, width, height ); 146 } 147 } 148 } 149 150 if ( lec.getSize() >= 1 ) { 151 lec.setTitle( getLegendTitle() ); 152 return lec; 153 } 154 return le; 155 } 156 throw new LegendException( "LegendFactory: Error in creating the LegendElement:\n" 157 + "Given style is not a valid UserStyle." ); 158 } 159 160 /** 161 * creates an empty <tt>LegendElementCollection</tt> 162 * 163 * @return <tt>LegendElementCollection</tt> 164 */ 165 public LegendElementCollection createLegendElementCollection() { 166 return new LegendElementCollection(); 167 } 168 169 /** 170 * creates a <tt>LegendElementCollection</tt> and fills it with the passed <tt>LegendElement</tt>s. 171 * 172 * @param legendElements 173 * to fill 174 * 175 * @return <tt>LegendElementCollection</tt> 176 */ 177 public LegendElementCollection createLegendElementCollection( LegendElement[] legendElements ) { 178 LegendElementCollection lec = new LegendElementCollection(); 179 180 for ( int i = 0; i < legendElements.length; i++ ) { 181 lec.addLegendElement( legendElements[i] ); 182 } 183 return lec; 184 } 185 186 /** 187 * 188 * @param sld 189 * @param width 190 * @param height 191 * @param mime 192 * of the thumbs 193 * @return an array of thumb nails, which may be empty 194 * @throws LegendException 195 */ 196 public BufferedImage[] createAllThumbnails( StyledLayerDescriptor sld, int width, int height, String mime ) 197 throws LegendException { 198 199 List<AbstractStyle> list = new ArrayList<AbstractStyle>(); 200 201 org.deegree.graphics.sld.AbstractLayer[] nl = sld.getNamedLayers(); 202 for ( int i = 0; i < nl.length; i++ ) { 203 AbstractStyle[] styles = nl[i].getStyles(); 204 for ( int j = 0; j < styles.length; j++ ) { 205 if ( styles[j] instanceof UserStyle ) { 206 list.add( styles[j] ); 207 } 208 } 209 } 210 211 nl = sld.getUserLayers(); 212 for ( int i = 0; i < nl.length; i++ ) { 213 AbstractStyle[] styles = nl[i].getStyles(); 214 for ( int j = 0; j < styles.length; j++ ) { 215 if ( styles[j] instanceof UserStyle ) { 216 list.add( styles[j] ); 217 } 218 } 219 } 220 221 LegendElement le = null; 222 BufferedImage bi_temp = null; // just temporary 223 BufferedImage[] buffi = new BufferedImage[list.size()]; // @return 224 225 for ( int i = 0; i < list.size(); i++ ) { 226 AbstractStyle style = list.get( i ); 227 String name = style.getName(); 228 name = name.replace( ':', '_' ); 229 LOG.logInfo( "creating: " + name ); 230 le = createLegendElement( style, width, height, "" ); 231 bi_temp = le.exportAsImage( mime ); 232 buffi[i] = bi_temp; 233 } 234 235 return buffi; 236 } 237 238 /** 239 * gets the property-names for creating the legend text 240 */ 241 private String getPropertyNameFromFilter( Filter filter ) 242 throws LegendException { 243 ComplexFilter cf = (ComplexFilter) filter; 244 245 LOG.logDebug( "Name der Operation: " + cf.getOperation().getOperatorName() + "\n" + cf.toXML() ); 246 Operation operation = cf.getOperation(); 247 String ret = getPropertyNameFromOperation( operation ); 248 return ret; 249 250 } 251 252 /** 253 * 254 * @param operation 255 * @return the legend label of the operation or an empty String. 256 * @throws LegendException 257 */ 258 private String getPropertyNameFromOperation( Operation operation ) 259 throws LegendException { 260 261 String legendlabel = ""; 262 263 // determines the operation 264 // IS COM 265 if ( operation instanceof PropertyIsCOMPOperation ) { 266 PropertyIsCOMPOperation pCOMPo = (PropertyIsCOMPOperation) operation; 267 // gets the PropertyName of the operation for creating a legendtitle 268 if ( pCOMPo.getFirstExpression() instanceof PropertyName ) { 269 PropertyName propertyname = (PropertyName) pCOMPo.getFirstExpression(); 270 // setLegendTitleFilterProperty(propertyname.getValue()); 271 legendlabel += propertyname.getValue(); 272 } else { 273 throw new LegendException( "LegendElement_Impl: An error occured " 274 + "during the parsing of the Filter in the SLD." 275 + "First Operation Expression is not of type Literal" ); 276 } 277 legendlabel += getOperationString( pCOMPo.getOperatorId() ); 278 // gets the Literal of the operation 279 if ( pCOMPo.getSecondExpression() instanceof Literal ) { 280 Literal literal = (Literal) pCOMPo.getSecondExpression(); 281 legendlabel += literal.getValue(); 282 } else { 283 throw new LegendException( "LegendElement_Impl: An error occured " 284 + "during the parsing of the Filter in the SLD." 285 + "Second Operation Expression is not of type Literal" ); 286 } 287 // LOGICAL 288 } else if ( operation instanceof LogicalOperation ) { 289 LogicalOperation logOp = (LogicalOperation) operation; 290 String operatorstring = getOperationString( logOp.getOperatorId() ); 291 292 // Operator-ID: AND = 200, OR = 201, NOT = 202 293 if ( logOp.getOperatorId() == OperationDefines.AND ) { 294 List<Operation> andlist = logOp.getArguments(); 295 String andstring = ""; 296 for ( int i = 0; i < andlist.size(); i++ ) { 297 andstring += getPropertyNameFromOperation( andlist.get( i ) ); 298 if ( i < andlist.size() - 1 ) { 299 andstring += operatorstring; 300 } 301 } 302 legendlabel = andstring; 303 } else if ( logOp.getOperatorId() == OperationDefines.OR ) { 304 List<Operation> orlist = logOp.getArguments(); 305 String orstring = ""; 306 for ( int i = 0; i < orlist.size(); i++ ) { 307 orstring += getPropertyNameFromOperation( orlist.get( i ) ); 308 if ( i < orlist.size() - 1 ) { 309 orstring += operatorstring; 310 } 311 } 312 legendlabel = orstring; 313 } else if ( logOp.getOperatorId() == OperationDefines.NOT ) { 314 List<Operation> notlist = logOp.getArguments(); 315 String notstring = getPropertyNameFromOperation( notlist.get( 0 ) ); 316 // not is followed by brackets: not (ID = 1 and ID = 2) 317 legendlabel = operatorstring + "(" + notstring + ")"; 318 } 319 320 // SPATIAL 321 } else if ( operation instanceof SpatialOperation ) { 322 323 SpatialOperation spatop = (SpatialOperation) operation; 324 325 legendlabel = "spatial operation" + spatop; 326 // PROPERTY IS LIKE 327 } else if ( operation instanceof PropertyIsLikeOperation ) { 328 329 PropertyIsLikeOperation prilop = (PropertyIsLikeOperation) operation; 330 331 legendlabel = prilop.getPropertyName().getValue() + getOperationString( prilop.getOperatorId() ) 332 + prilop.getLiteral().getValue(); 333 // LOGICAL 334 } else { 335 LOG.logWarning( operation.toString() ); 336 // TODO implement other filter-operations and ELSE! 337 throw new LegendException( "Filter-Operation <" + operation.getOperatorName() 338 + "> is no PropertyIsCOMPOperation." ); 339 } 340 341 return legendlabel; 342 343 } 344 345 /** 346 * 347 * @param operationID 348 * @return the string representation of the given operation. 349 */ 350 private String getOperationString( int operationID ) { 351 String operationString = ""; 352 353 switch ( operationID ) { 354 case OperationDefines.PROPERTYISEQUALTO: 355 operationString = " = "; 356 break; 357 case OperationDefines.PROPERTYISLESSTHAN: 358 operationString = " < "; 359 break; 360 case OperationDefines.PROPERTYISGREATERTHAN: 361 operationString = " > "; 362 break; 363 case OperationDefines.PROPERTYISLESSTHANOREQUALTO: 364 operationString = " <= "; 365 break; 366 case OperationDefines.PROPERTYISGREATERTHANOREQUALTO: 367 operationString = " >= "; 368 break; 369 case OperationDefines.PROPERTYISLIKE: 370 operationString = " is like "; 371 break; 372 case OperationDefines.PROPERTYISNULL: 373 operationString = " is NULL "; 374 break; 375 case OperationDefines.PROPERTYISBETWEEN: 376 operationString = " is between "; 377 break; 378 case OperationDefines.AND: 379 operationString = " and "; 380 break; 381 case OperationDefines.OR: 382 operationString = " or "; 383 break; 384 case OperationDefines.NOT: 385 operationString = " not "; 386 break; 387 } 388 389 return operationString; 390 } 391 392 /** 393 * sets the label of the <tt>LegendElement</tt> 394 * 395 * @param label 396 * label of the <tt>LegendElement</tt> 397 * 398 */ 399 public void setLabel( String label ) { 400 this.label = label; 401 } 402 403 /** 404 * returns the label set to <tt>LegendElement</tt>. If no label is set, the method returns <tt>null</tt> 405 * 406 * @return label of the <tt>LegendElement</tt> or <tt>null</tt> 407 * 408 */ 409 public String getLabel() { 410 return this.label; 411 } 412 413 /** 414 * @return the title of the legend. 415 */ 416 protected String getLegendTitle() { 417 return this.legendtitle; 418 } 419 420 /** 421 * @param string 422 */ 423 private void setLegendTitle( String string ) { 424 this.legendtitle = string; 425 } 426 427 }