001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }