package org.esa.snap.rcp.layermanager.layersrc.shapefile;
import com.bc.ceres.swing.figure.FigureStyle;
import com.bc.ceres.swing.figure.support.DefaultFigureStyle;
import org.esa.snap.core.datamodel.PlainFeatureFactory;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureTypes;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.SLD;
import org.geotools.styling.SLDParser;
import org.geotools.styling.Stroke;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.Symbolizer;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import java.awt.BasicStroke;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SLDUtils {
private static final StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);
public static File getSLDFile(File shapeFile) {
String filename = shapeFile.getAbsolutePath();
if (filename.endsWith(".shp") || filename.endsWith(".dbf")
|| filename.endsWith(".shx")) {
filename = filename.substring(0, filename.length() - 4);
filename += ".sld";
} else if (filename.endsWith(".SHP") || filename.endsWith(".DBF")
|| filename.endsWith(".SHX")) {
filename = filename.substring(0, filename.length() - 4);
filename += ".SLD";
}
return new File(filename);
}
public static Style[] loadSLD(File shapeFile) {
File sld = getSLDFile(shapeFile);
if (sld.exists()) {
return createFromSLD(sld);
} else {
return new Style[0];
}
}
public static Style[] createFromSLD(File sld) {
try {
SLDParser stylereader = new SLDParser(styleFactory, sld.toURI().toURL());
return stylereader.readXML();
} catch (IOException e) {
e.printStackTrace();
}
return new Style[0];
}
/**
* Converts the styling information in the style into CSS styles for all given features in the collection.
*
* @param style The style.
* @param defaultCss The CSS default value.
* @param featureCollection The collection that should be styled.
* @param styledCollection the collection that will contain the styled features.
*/
public static void applyStyle(Style style, String defaultCss,
FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection,
FeatureCollection<SimpleFeatureType, SimpleFeature> styledCollection) {
List<FeatureTypeStyle> featureTypeStyles = style.featureTypeStyles();
SimpleFeatureType featureType = featureCollection.getSchema();
SimpleFeatureType styledFeatureType = styledCollection.getSchema();
List<SimpleFeature> featuresToStyle = new ArrayList<SimpleFeature>(featureCollection.size());
Iterator<SimpleFeature> iterator = featureCollection.iterator();
while (iterator.hasNext()) {
featuresToStyle.add(iterator.next());
}
for (FeatureTypeStyle fts : featureTypeStyles) {
if (isFeatureTypeStyleActive(featureType, fts)) {
List<Rule> ruleList = new ArrayList<Rule>();
List<Rule> elseRuleList = new ArrayList<Rule>();
for (Rule rule : fts.rules()) {
if (rule.isElseFilter()) {
elseRuleList.add(rule);
} else {
ruleList.add(rule);
}
}
Iterator<SimpleFeature> featureIterator = featuresToStyle.iterator();
while (featureIterator.hasNext()) {
SimpleFeature simpleFeature = featureIterator.next();
SimpleFeature styledFeature = processRules(simpleFeature, styledFeatureType, ruleList,
elseRuleList);
if (styledFeature != null) {
styledCollection.add(styledFeature);
featureIterator.remove();
}
}
}
}
for (SimpleFeature simpleFeature : featuresToStyle) {
styledCollection.add(createStyledFeature(styledFeatureType, simpleFeature, defaultCss));
}
}
public static SimpleFeature processRules(SimpleFeature sf, SimpleFeatureType styledSFT, List<Rule> ruleList,
List<Rule> elseRuleList) {
Filter filter;
boolean doElse = true;
Symbolizer[] symbolizers;
for (Rule rule : ruleList) {
filter = rule.getFilter();
if ((filter == null) || filter.evaluate(sf)) {
doElse = false;
symbolizers = rule.getSymbolizers();
SimpleFeature styledFeature = processSymbolizers(styledSFT, sf, symbolizers);
if (styledFeature != null) {
return styledFeature;
}
}
}
if (doElse) {
for (Rule rule : elseRuleList) {
symbolizers = rule.getSymbolizers();
SimpleFeature styledFeature = processSymbolizers(styledSFT, sf, symbolizers);
if (styledFeature != null) {
return styledFeature;
}
}
}
return null;
}
public static SimpleFeature processSymbolizers(SimpleFeatureType sft, SimpleFeature feature,
Symbolizer[] symbolizers) {
for (Symbolizer symbolizer : symbolizers) {
if (symbolizer instanceof LineSymbolizer) {
LineSymbolizer lineSymbolizer = (LineSymbolizer) symbolizer;
Stroke stroke = lineSymbolizer.getStroke();
Color strokeColor = SLD.color(stroke);
int width = SLD.width(stroke);
FigureStyle figureStyle = DefaultFigureStyle.createLineStyle(strokeColor, new BasicStroke(width));
String cssStyle = figureStyle.toCssString();
return createStyledFeature(sft, feature, cssStyle);
} else if (symbolizer instanceof PolygonSymbolizer) {
PolygonSymbolizer polygonSymbolizer = (PolygonSymbolizer) symbolizer;
Color fillColor = SLD.color(polygonSymbolizer.getFill());
Stroke stroke = polygonSymbolizer.getStroke();
Color strokeColor = SLD.color(stroke);
int width = SLD.width(stroke);
FigureStyle figureStyle = DefaultFigureStyle.createPolygonStyle(fillColor, strokeColor,
new BasicStroke(width));
String cssStyle = figureStyle.toCssString();
return createStyledFeature(sft, feature, cssStyle);
}
}
return null;
}
public static boolean isFeatureTypeStyleActive(SimpleFeatureType ftype, FeatureTypeStyle fts) {
return ((ftype.getTypeName() != null)
&& (ftype.getTypeName().equalsIgnoreCase(fts.getFeatureTypeName()) ||
FeatureTypes.isDecendedFrom(ftype, null, fts.getFeatureTypeName())));
}
public static SimpleFeatureType createStyledFeatureType(SimpleFeatureType type) {
SimpleFeatureTypeBuilder sftb = new SimpleFeatureTypeBuilder();
sftb.init(type);
sftb.add(PlainFeatureFactory.ATTRIB_NAME_STYLE_CSS, String.class);
return sftb.buildFeatureType();
}
public static SimpleFeature createStyledFeature(SimpleFeatureType type, SimpleFeature feature, String styleCSS) {
SimpleFeatureBuilder sfb = new SimpleFeatureBuilder(type);
sfb.init(feature);
sfb.set(PlainFeatureFactory.ATTRIB_NAME_STYLE_CSS, styleCSS);
return sfb.buildFeature(feature.getID());
}
}