/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.graphics.legend;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.graphics.sld.AbstractStyle;
import org.deegree.graphics.sld.FeatureTypeStyle;
import org.deegree.graphics.sld.Rule;
import org.deegree.graphics.sld.StyledLayerDescriptor;
import org.deegree.graphics.sld.UserStyle;
import org.deegree.model.filterencoding.ComplexFilter;
import org.deegree.model.filterencoding.Filter;
import org.deegree.model.filterencoding.Literal;
import org.deegree.model.filterencoding.LogicalOperation;
import org.deegree.model.filterencoding.Operation;
import org.deegree.model.filterencoding.OperationDefines;
import org.deegree.model.filterencoding.PropertyIsCOMPOperation;
import org.deegree.model.filterencoding.PropertyIsLikeOperation;
import org.deegree.model.filterencoding.PropertyName;
import org.deegree.model.filterencoding.SpatialOperation;
/**
* factory class for creating legend elements/images to be used
* with WMS GetLegendGraphic request
*
* @version $Revision: 1.15 $
* @author $author$
*/
public class LegendFactory {
private static final ILogger LOG = LoggerFactory.getLogger( LegendFactory.class );
private String label = "";
private String legendtitle = "";
/**
* creates a <tt>LegendElement</tt> using the passed
* <tt>BufferedImage</tt>
*
* @return <tt>LegendElement</tt>
*/
public LegendElement createLegendElement(BufferedImage legendImage) {
return new LegendElement(legendImage);
}
/**
* creates a <tt>LegendElement</tt> from a SLD <tt>Style</tt>.
* Depending on the <tt>Style</tt> the returned <tt>LegendElement</tt>
* may is a <tt>LegendElementCollection</tt>.
*
* @return <tt>LegendElement</tt>
*/
public LegendElement createLegendElement(AbstractStyle style, int width,
int height, String title) throws LegendException {
setLegendTitle(title);
if (style instanceof UserStyle) {
LegendElement le = null;
FeatureTypeStyle[] fts = ((UserStyle) style).getFeatureTypeStyles();
LegendElementCollection lec = new LegendElementCollection();
for (int a = 0; a < fts.length; a++) {
// legendtitle
if (title != null && title.length() > 0) {
if ( ((UserStyle) style).getTitle() != null ) {
setLegendTitle( title );
} else {
setLegendTitle( title );
}
} else {
setLegendTitle(fts[a].getName());
}
Rule[] rules = fts[a].getRules();
for (int b = 0; b < rules.length; b++) {
if (rules[b].getFilter() != null) {
Filter f = rules[b].getFilter();
String category = rules[b].getTitle();
if ( category == null ) {
category = rules[b].getName();
}
if ( category == null ) {
category = getPropertyNameFromFilter(f);
}
le = new LegendElement(new Rule[] { rules[b] }, category,
0, 4, true, width, height);
lec.addLegendElement(le);
} else {
String category = ((UserStyle) style).getTitle();
if ( category == null ) {
category = ((UserStyle) style).getName();
}
if ( category == null ) {
category = title;
}
category = "";
le = new LegendElement(rules, category, 0, 4, true, width, height);
}
}
}
if (lec.getSize() >= 1) {
lec.setTitle(getLegendTitle());
return lec;
}
return le;
}
throw new LegendException(
"LegendFactory: Error in creating the LegendElement:\n"
+ "Given style is not a valid UserStyle.");
}
/**
* creates an empty <tt>LegendElementCollection</tt>
*
* @return <tt>LegendElementCollection</tt>
*/
public LegendElementCollection createLegendElementCollection() {
return new LegendElementCollection();
}
/**
* creates a <tt>LegendElementCollection</tt> and fills it with the passed
* <tt>LegendElement</tt>s.
*
* @return <tt>LegendElementCollection</tt>
*/
public LegendElementCollection createLegendElementCollection(
LegendElement[] legendElements) {
LegendElementCollection lec = new LegendElementCollection();
for (int i = 0; i < legendElements.length; i++) {
lec.addLegendElement(legendElements[i]);
}
return lec;
}
/**
*
* @param sld
* @param width
* @param height
* @return @throws
* LegendException
*/
public BufferedImage[] createAllThumbnails(StyledLayerDescriptor sld,
int width, int height,
String mime) throws LegendException {
ArrayList list = new ArrayList();
org.deegree.graphics.sld.AbstractLayer[] nl = sld.getNamedLayers();
for (int i = 0; i < nl.length; i++) {
AbstractStyle[] styles = nl[i].getStyles();
for (int j = 0; j < styles.length; j++) {
if (styles[j] instanceof UserStyle) {
list.add(styles[j]);
}
}
}
nl = sld.getUserLayers();
for (int i = 0; i < nl.length; i++) {
AbstractStyle[] styles = nl[i].getStyles();
for (int j = 0; j < styles.length; j++) {
if (styles[j] instanceof UserStyle) {
list.add(styles[j]);
}
}
}
LegendElement le = null;
BufferedImage bi_temp = null; // just temporary
BufferedImage[] buffi = new BufferedImage[list.size()]; // @return
for (int i = 0; i < list.size(); i++) {
AbstractStyle style = (AbstractStyle) list.get(i);
String name = style.getName();
name = name.replace(':', '_');
LOG.logInfo( "creating: " + name );
le = createLegendElement(style, width, height, "");
bi_temp = le.exportAsImage(mime);
buffi[i] = bi_temp;
}
return buffi;
}
/**
* gets the property-names for creating the legend text
*/
private String getPropertyNameFromFilter(Filter filter)
throws LegendException {
ComplexFilter cf = (ComplexFilter) filter;
LOG.logDebug( "Name der Operation: " + cf.getOperation().getOperatorName() +
"\n" + cf.toXML() );
Operation operation = cf.getOperation();
String ret = getPropertyNameFromOperation(operation);
return ret;
}
/**
*
* @param operation
* @return @throws
* LegendException
*/
private String getPropertyNameFromOperation(Operation operation)
throws LegendException {
String legendlabel = "";
// determines the operation
// IS COM
if (operation instanceof PropertyIsCOMPOperation) {
PropertyIsCOMPOperation pCOMPo = (PropertyIsCOMPOperation) operation;
// gets the PropertyName of the operation for creating a legendtitle
if (pCOMPo.getFirstExpression() instanceof PropertyName) {
PropertyName propertyname = (PropertyName) pCOMPo
.getFirstExpression();
// setLegendTitleFilterProperty(propertyname.getValue());
legendlabel += propertyname.getValue();
} else {
throw new LegendException(
"LegendElement_Impl: An error occured "
+ "during the parsing of the Filter in the SLD."
+ "First Operation Expression is not of type Literal");
}
legendlabel += getOperationString(pCOMPo.getOperatorId());
// gets the Literal of the operation
if (pCOMPo.getSecondExpression() instanceof Literal) {
Literal literal = (Literal) pCOMPo.getSecondExpression();
legendlabel += literal.getValue();
} else {
throw new LegendException(
"LegendElement_Impl: An error occured "
+ "during the parsing of the Filter in the SLD."
+ "Second Operation Expression is not of type Literal");
}
// LOGICAL
} else if (operation instanceof LogicalOperation) {
LogicalOperation logOp = (LogicalOperation) operation;
String operatorstring = getOperationString(logOp.getOperatorId());
// Operator-ID: AND = 200, OR = 201, NOT = 202
if (logOp.getOperatorId() == OperationDefines.AND) {
List<Operation> andlist = logOp.getArguments();
String andstring = "";
for (int i = 0; i < andlist.size(); i++) {
andstring += getPropertyNameFromOperation( andlist.get(i) );
if (i < andlist.size() - 1) {
andstring += operatorstring;
}
}
legendlabel = andstring;
} else if (logOp.getOperatorId() == OperationDefines.OR) {
List<Operation> orlist = logOp.getArguments();
String orstring = "";
for (int i = 0; i < orlist.size(); i++) {
orstring += getPropertyNameFromOperation( orlist.get(i) );
if (i < orlist.size() - 1) {
orstring += operatorstring;
}
}
legendlabel = orstring;
} else if (logOp.getOperatorId() == OperationDefines.NOT) {
List<Operation> notlist = logOp.getArguments();
String notstring = getPropertyNameFromOperation( notlist.get(0) );
// not is followed by brackets: not (ID = 1 and ID = 2)
legendlabel = operatorstring + "(" + notstring + ")";
}
// SPATIAL
} else if (operation instanceof SpatialOperation) {
SpatialOperation spatop = (SpatialOperation) operation;
legendlabel = "spatial operation" + spatop;
// PROPERTY IS LIKE
} else if (operation instanceof PropertyIsLikeOperation) {
PropertyIsLikeOperation prilop = (PropertyIsLikeOperation) operation;
legendlabel = prilop.getPropertyName().getValue()
+ getOperationString(prilop.getOperatorId())
+ prilop.getLiteral().getValue();
// LOGICAL
} else {
LOG.logWarning( operation.toString() );
// TODO implement other filter-operations and ELSE!
throw new LegendException("Filter-Operation <"
+ operation.getOperatorName()
+ "> is no PropertyIsCOMPOperation.");
}
return legendlabel;
}
/**
*
* @param operationID
* @return
*/
private String getOperationString(int operationID) {
String operationString = "";
switch (operationID) {
case OperationDefines.PROPERTYISEQUALTO:
operationString = " = ";
break;
case OperationDefines.PROPERTYISLESSTHAN:
operationString = " < ";
break;
case OperationDefines.PROPERTYISGREATERTHAN:
operationString = " > ";
break;
case OperationDefines.PROPERTYISLESSTHANOREQUALTO:
operationString = " <= ";
break;
case OperationDefines.PROPERTYISGREATERTHANOREQUALTO:
operationString = " >= ";
break;
case OperationDefines.PROPERTYISLIKE:
operationString = " is like ";
break;
case OperationDefines.PROPERTYISNULL:
operationString = " is NULL ";
break;
case OperationDefines.PROPERTYISBETWEEN:
operationString = " is between ";
break;
case OperationDefines.AND:
operationString = " and ";
break;
case OperationDefines.OR:
operationString = " or ";
break;
case OperationDefines.NOT:
operationString = " not ";
break;
}
return operationString;
}
/**
* sets the label of the <tt>LegendElement</tt>
*
* @param label
* label of the <tt>LegendElement</tt>
*
*/
public void setLabel(String label) {
this.label = label;
}
/**
* returns the label set to <tt>LegendElement</tt>. If no label is set,
* the method returns <tt>null</tt>
*
* @return label of the <tt>LegendElement</tt> or <tt>null</tt>
*
* @uml.property name="label"
*/
public String getLabel() {
return this.label;
}
/**
* @return
*/
protected String getLegendTitle() {
return this.legendtitle;
}
/**
* @param string
*/
private void setLegendTitle(String string) {
this.legendtitle = string;
}
/**
* @return
* private String getLegendTitleFilterProperty() { return
* legendtitlefilterproperty; }
*/
/**
* @param string
*
* private void setLegendTitleFilterProperty(String string) {
* legendtitlefilterproperty = string; }
*/
}
/* ******************************************************************************
* Changes to this class. What the people have been up to: $Log:
* LegendFactory.java,v $ Revision 1.2 2004/07/09 07:45:40 ap no message
*
* Revision 1.1 2004/06/24 06:22:06 ap no message
*
* Revision 1.5 2004/06/07 13:39:12 tf code adapted to wfs1 refactoring
*
* Revision 1.4 2004/05/27 06:39:45 ap no message
*
* Revision 1.3 2004/05/24 15:48:45 ap no message
*
* Revision 1.2 2004/05/24 07:11:45 ap no message
*
* Revision 1.1 2004/05/22 10:02:55 ap no message
*
* Revision 1.14 2004/05/14 07:45:59 poth no message
*
* Revision 1.13 2004/04/07 10:58:46 axel_schaefer bugfix
*
******************************************************************************/