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 }