/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.featureinfo;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Icon;
import org.geotools.renderer.style.DynamicSymbolFactoryFinder;
import org.geotools.renderer.style.ExpressionExtractor;
import org.geotools.renderer.style.ExternalGraphicFactory;
import org.geotools.renderer.style.SLDStyleFactory;
import org.geotools.styling.AbstractStyleVisitor;
import org.geotools.styling.ExternalGraphic;
import org.geotools.styling.Graphic;
import org.geotools.styling.Mark;
import org.geotools.styling.Stroke;
import org.geotools.util.logging.Logging;
import org.opengis.feature.Feature;
import org.opengis.filter.expression.Expression;
import org.opengis.style.GraphicalSymbol;
/**
* Evaluates a meta-buffer against the specified feature. Can be called with multiple subsequent
* features and will accumulate the largest available buffer.
*
* @author Andrea Aime - GeoSolutions
*/
public class DynamicBufferEstimator extends AbstractStyleVisitor {
static final Logger LOGGER = Logging.getLogger(VectorRenderingLayerIdentifier.class);
Feature feature;
double buffer;
public void setFeature(Feature feature) {
this.feature = feature;
}
public int getBuffer() {
return (int) Math.ceil(buffer);
}
@Override
public void visit(Stroke stroke) {
Expression width = stroke.getWidth();
if (width != null) {
Double w = width.evaluate(feature, Double.class);
if (w != null && w > buffer) {
buffer = w;
}
}
}
@Override
public void visit(Graphic gr) {
try {
Expression grSize = gr.getSize();
if (grSize != null) {
Double size = grSize.evaluate(feature, Double.class);
if (size != null) {
buffer = Math.max(buffer, size);
}
return;
}
// no fixed size, proceed
for (GraphicalSymbol gs : gr.graphicalSymbols()) {
if (gs instanceof ExternalGraphic) {
ExternalGraphic eg = (ExternalGraphic) gs;
Icon icon = null;
if (eg.getInlineContent() != null) {
icon = eg.getInlineContent();
} else {
String location = eg.getLocation().toExternalForm();
// expand embedded cql expression
Expression expanded = ExpressionExtractor.extractCqlExpressions(location);
Iterator<ExternalGraphicFactory> it = DynamicSymbolFactoryFinder
.getExternalGraphicFactories();
while (it.hasNext()) {
try {
icon = it.next().getIcon(feature, expanded, eg.getFormat(), -1);
} catch (Exception e) {
LOGGER.log(Level.FINE,
"Error occurred evaluating external graphic", e);
}
}
}
// evaluate the icon if found, if not SLD asks us to go to the next one
if (icon != null) {
if (icon != null) {
int size = Math.max(icon.getIconHeight(), icon.getIconWidth());
if (size > buffer) {
buffer = size;
}
return;
}
}
} else if (gs instanceof Mark) {
// if we get here it means size was null
if (SLDStyleFactory.DEFAULT_MARK_SIZE > buffer) {
buffer = SLDStyleFactory.DEFAULT_MARK_SIZE;
}
}
}
} catch (ClassCastException e) {
LOGGER.info("Could not parse graphic size, " + "it's a literal but not a Number...");
} catch (Exception e) {
LOGGER.log(Level.INFO, "Error occured during the graphic size estimation, "
+ "meta buffer estimate cannot be performed", e);
}
}
}