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