package org.jgrasstools.gears.utils.style;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.FilenameUtils;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.filter.function.FilterFunction_offset;
import org.geotools.styling.ExternalGraphic;
import org.geotools.styling.FeatureTypeConstraint;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Fill;
import org.geotools.styling.Graphic;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.Mark;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.SLD;
import org.geotools.styling.SLDParser;
import org.geotools.styling.SLDTransformer;
import org.geotools.styling.Stroke;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.StyledLayerDescriptor;
import org.geotools.styling.Symbolizer;
import org.geotools.styling.UserLayer;
import org.jgrasstools.gears.utils.SldUtilities;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Function;
import org.opengis.style.GraphicalSymbol;
/**
* Style related utilities.
*
* @author Andrea Antonello (www.hydrologis.com)
*/
@SuppressWarnings("nls")
public class Utilities {
public static final String NONE = "- none -";
public static final String DEFAULT_SIZE = "5";
public static final String DEFAULT_WIDTH = "1";
public static final String DEFAULT_ROTATION = "0";
public static final String DEFAULT_OFFSET = "0";
public static final String DEFAULT_OPACITY = "1";
public static final String DEFAULT_COLOR = "#000000";
public static final String DEFAULT_MINSCALE = "0";
public static final String DEFAULT_MAXSCALE = "infinity";
// offset values
public static final int OFFSET_MAX = 1000;
public static final int OFFSET_MIN = -1000;
public static final int OFFSET_STEP = 10;
// displacement values
public static final int DISPLACEMENT_MAX = 1000;
public static final int DISPLACEMENT_MIN = -1000;
public static final int DISPLACEMENT_STEP = 10;
public static final String DEFAULT_GROUPNAME = "group ";
public static final String DEFAULT_STYLENAME = "default style";
public static final String SLD_EXTENTION = ".sld";
/**
* The SLD defined well known mark codes.
*/
public static final String[] wkMarkDefs = { //
"", //
"cross", //
"circle", //
"triangle", //
"X", //
"star", //
"arrow", //
"hatch", //
"square"//
};
/**
* The SLD defined well known mark names for gui use.
*/
public static final String[] wkMarkNames = { //
"", //
"cross", //
"circle", //
"triangle", //
"X", //
"star", //
"arrow", //
"hatch", //
"square"//
};
public static final String SHAPE_PREFIX = "shape://";
/**
* The custom shape mark names as needed by geotools.
*/
public static final String[] shapeMarkDefs = { //
"", //
SHAPE_PREFIX + "vertline", //
SHAPE_PREFIX + "horline", //
SHAPE_PREFIX + "slash", //
SHAPE_PREFIX + "backslash", //
SHAPE_PREFIX + "times", //
SHAPE_PREFIX + "dot", //
SHAPE_PREFIX + "plus" //
};
/**
* The custom shape mark names for gui.
*/
public static final String[] shapeMarkNames = { //
"", //
"vertical lines", //
"horizontal lines", //
"diagonal lines", //
"inverse diagonal lines", //
"crossed diagonal lines", //
"dots", //
"plus" //
};
/**
* A map of names for all the marks.
*/
public static final HashMap<String, String> markNamesToDef = new HashMap<>();
static {
// well known marks
markNamesToDef.put(wkMarkNames[0], wkMarkDefs[0]);
markNamesToDef.put(wkMarkNames[1], wkMarkDefs[1]);
markNamesToDef.put(wkMarkNames[2], wkMarkDefs[2]);
markNamesToDef.put(wkMarkNames[3], wkMarkDefs[3]);
markNamesToDef.put(wkMarkNames[4], wkMarkDefs[4]);
markNamesToDef.put(wkMarkNames[5], wkMarkDefs[5]);
markNamesToDef.put(wkMarkNames[6], wkMarkDefs[6]);
markNamesToDef.put(wkMarkNames[7], wkMarkDefs[7]);
markNamesToDef.put(wkMarkNames[8], wkMarkDefs[8]);
// custom shapes
markNamesToDef.put(shapeMarkNames[1], shapeMarkDefs[1]);
markNamesToDef.put(shapeMarkNames[2], shapeMarkDefs[2]);
markNamesToDef.put(shapeMarkNames[3], shapeMarkDefs[3]);
markNamesToDef.put(shapeMarkNames[4], shapeMarkDefs[4]);
markNamesToDef.put(shapeMarkNames[5], shapeMarkDefs[5]);
markNamesToDef.put(shapeMarkNames[6], shapeMarkDefs[6]);
markNamesToDef.put(shapeMarkNames[7], shapeMarkDefs[7]);
}
/**
* Getter for an array of all available marks.
*
* @return all mark names (for gui use).
*/
public static String[] getAllMarksArray() {
Set<String> keySet = markNamesToDef.keySet();
return (String[]) keySet.toArray(new String[keySet.size()]);
}
/**
* The SLD names of the line cap definitions.
*/
public static final String[] lineCapNames = { //
"", //
"butt", //
"round", //
"square" //
};
/**
* The SLD names of the line join definitions.
*/
public static final String[] verticalPlacementNames = { //
"bevel", //
"miter", //
"round" //
};
/**
* The SLD names of the line join definitions.
*/
public static final String[] lineJoinNames = { //
"", //
"bevel", //
"miter", //
"round" //
};
/**
* A map of user friendly names to the SLD names of line
* end styles.
*/
public static final HashMap<String, String> lineEndStyles = new HashMap<>();
static {
lineEndStyles.put("arrow - open", "shape://oarrow");
lineEndStyles.put("arrow - closed", "shape://carrow");
lineEndStyles.put("circle", "circle");
lineEndStyles.put("square", "square");
}
/**
* The default {@link StyleFactory} to use.
*/
public static StyleFactory sf = CommonFactoryFinder.getStyleFactory(GeoTools.getDefaultHints());
/**
* The default {@link FilterFactory} to use.
*/
public static FilterFactory ff = CommonFactoryFinder.getFilterFactory(GeoTools.getDefaultHints());
/**
* The default {@link StyleBuilder} to use.
*/
public static StyleBuilder sb = new StyleBuilder(sf, ff);
// /**
// * Utility class for working with Images, Features and Styles
// */
// private static Drawing d = Drawing.create();
/**
* Parse a file and extract the {@link StyledLayerDescriptor}.
*
* @param file the sld file to parse.
* @return the styled layer descriptor.
* @throws IOException
*/
public static StyledLayerDescriptor readStyle(File file) throws IOException {
SLDParser stylereader = new SLDParser(sf, file);
StyledLayerDescriptor sld = stylereader.parseSLD();
return sld;
}
/**
* Collect all {@link ExternalGraphic}s from the given {@link Rule}.
*
* @param rule the rule to check.
* @return the extracted {@link ExternalGraphic}s.
*/
public static List<ExternalGraphic> externalGraphicsFromRule(Rule rule) {
List<ExternalGraphic> gList = new ArrayList<ExternalGraphic>();
List<Symbolizer> symbolizers = rule.symbolizers();
if (symbolizers.size() != 0) {
for (Symbolizer symbolizer : symbolizers) {
Graphic[] graphics = new Graphic[2];
if (symbolizer instanceof PointSymbolizer) {
PointSymbolizer pointSymbolizer = (PointSymbolizer) symbolizer;
graphics[0] = pointSymbolizer.getGraphic();
} else if (symbolizer instanceof LineSymbolizer) {
LineSymbolizer lineSymbolizer = (LineSymbolizer) symbolizer;
Stroke stroke = lineSymbolizer.getStroke();
graphics[0] = stroke.getGraphicStroke();
} else if (symbolizer instanceof PolygonSymbolizer) {
PolygonSymbolizer polygonSymbolizer = (PolygonSymbolizer) symbolizer;
Stroke stroke = polygonSymbolizer.getStroke();
if (stroke != null)
graphics[0] = stroke.getGraphicStroke();
Fill fill = polygonSymbolizer.getFill();
if (fill != null)
graphics[1] = fill.getGraphicFill();
}
for (int i = 0; i < graphics.length; i++) {
if (graphics[i] != null) {
for (GraphicalSymbol gs : graphics[i].graphicalSymbols()) {
if ((gs != null) && (gs instanceof ExternalGraphic)) {
ExternalGraphic externalGraphic = (ExternalGraphic) gs;
gList.add(externalGraphic);
}
}
}
}
}
return gList;
}
return Collections.emptyList();
}
/**
* Collect all {@link ExternalGraphic}s from the given {@link Graphic}.
*
* @param graphic the graphic to check.
* @return the extracted {@link ExternalGraphic}s.
*/
public static List<ExternalGraphic> externalGraphicsFromGraphic(Graphic graphic) {
List<ExternalGraphic> gList = new ArrayList<ExternalGraphic>();
for (GraphicalSymbol gs : graphic.graphicalSymbols()) {
if ((gs != null) && (gs instanceof ExternalGraphic)) {
ExternalGraphic externalGraphic = (ExternalGraphic) gs;
gList.add(externalGraphic);
}
}
return gList;
}
/**
* Creates a default {@link Style} for a point.
*
* @return the default style.
*/
public static Style createDefaultPointStyle() {
FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle();
featureTypeStyle.rules().add(createDefaultPointRule());
Style style = sf.createStyle();
style.featureTypeStyles().add(featureTypeStyle);
return style;
}
/**
* Creates a default {@link Rule} for a point.
*
* @return the default rule.
*/
public static Rule createDefaultPointRule() {
Graphic graphic = sf.createDefaultGraphic();
Mark circleMark = sf.getCircleMark();
circleMark.setFill(sf.createFill(ff.literal("#" + Integer.toHexString(Color.RED.getRGB() & 0xffffff))));
circleMark.setStroke(sf.createStroke(ff.literal("#" + Integer.toHexString(Color.BLACK.getRGB() & 0xffffff)),
ff.literal(DEFAULT_WIDTH)));
graphic.graphicalSymbols().clear();
graphic.graphicalSymbols().add(circleMark);
graphic.setSize(ff.literal(DEFAULT_SIZE));
PointSymbolizer pointSymbolizer = sf.createPointSymbolizer();
Rule rule = sf.createRule();
rule.setName("New rule");
rule.symbolizers().add(pointSymbolizer);
pointSymbolizer.setGraphic(graphic);
return rule;
}
/**
* Creates a default {@link Style} for a polygon.
*
* @return the default style.
*/
public static Style createDefaultPolygonStyle() {
FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle();
featureTypeStyle.rules().add(createDefaultPolygonRule());
Style style = sf.createStyle();
style.featureTypeStyles().add(featureTypeStyle);
return style;
}
/**
* Creates a default {@link Rule} for a polygon.
*
* @return the default rule.
*/
public static Rule createDefaultPolygonRule() {
PolygonSymbolizer polygonSymbolizer = sf.createPolygonSymbolizer();
polygonSymbolizer.setFill(sf.createFill(ff.literal("#" + Integer.toHexString(Color.RED.getRGB() & 0xffffff))));
polygonSymbolizer.getFill().setOpacity(ff.literal(0.50));
polygonSymbolizer.setStroke(sf.createStroke(
ff.literal("#" + Integer.toHexString(Color.BLACK.getRGB() & 0xffffff)), ff.literal(DEFAULT_WIDTH)));
Rule rule = sf.createRule();
rule.setName("New rule");
rule.symbolizers().add(polygonSymbolizer);
return rule;
}
/**
* Creates a default {@link Style} for a line.
*
* @return the default style.
*/
public static Style createDefaultLineStyle() {
FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle();
featureTypeStyle.rules().add(createDefaultLineRule());
Style style = sf.createStyle();
style.featureTypeStyles().add(featureTypeStyle);
return style;
}
/**
* Creates a default {@link Rule} for a line.
*
* @return the default rule.
*/
public static Rule createDefaultLineRule() {
LineSymbolizer lineSymbolizer = sf.createLineSymbolizer();
lineSymbolizer.setStroke(
sf.createStroke(ff.literal("#" + Integer.toHexString(Color.BLACK.getRGB() & 0xffffff)), ff.literal(1)));
Rule rule = sf.createRule();
rule.setName("New rule");
rule.symbolizers().add(lineSymbolizer);
return rule;
}
// /**
// * Creates a default {@link TextSymbolizer} for a given type.
// *
// * @return the default symbolizer.
// */
// public static TextSymbolizer createDefaultTextSymbolizer(SLD type) {
// LabelPlacement labelPlacement = null;
//
// switch (type) {
// case POINT:
// case POLYGON:
// labelPlacement = sf.createPointPlacement(sf.createAnchorPoint(ff.literal(0.0), ff.literal(0.0)),
// sf.createDisplacement(ff.literal(0.0), ff.literal(0.0)), ff.literal(0.0));
// break;
// case LINE:
// labelPlacement = sf.createLinePlacement(ff.literal(10.0));
// break;
//
// default:
// throw new IllegalArgumentException();
// }
//
// Font font = sb.createFont("Arial", false, false, 12); //$NON-NLS-1$
// TextSymbolizer textSymbolizer = sf.createTextSymbolizer(sf.createFill(ff.literal(DEFAULT_COLOR)),
// new Font[] { font }, null, ff.literal("dummy"), labelPlacement, null);
//
// return textSymbolizer;
// }
//
// /**
// * Creates a default {@link TextSymbolizer} for a point.
// *
// * @return the default symbolizer.
// */
// public static Symbolizer createDefaultGeometrySymbolizer(SLD type) {
// Symbolizer symbolizer = null;
// switch (type) {
// case POINT:
// Rule defaultPointRule = createDefaultPointRule();
// symbolizer = defaultPointRule.getSymbolizers()[0];
// break;
// case POLYGON:
// Rule defaultPolygonRule = createDefaultPolygonRule();
// symbolizer = defaultPolygonRule.getSymbolizers()[0];
// break;
// case LINE:
// Rule defaultLineRule = createDefaultLineRule();
// symbolizer = defaultLineRule.getSymbolizers()[0];
// break;
//
// default:
// throw new IllegalArgumentException();
// }
//
// return symbolizer;
// }
/**
* Get the {@link PointSymbolizer} from the given rule.
*
* @param rule the rule to check for symbolizers.
* @return the first symbolizer found.
*/
public static PointSymbolizer pointSymbolizerFromRule(Rule rule) {
List<Symbolizer> symbolizers = rule.symbolizers();
PointSymbolizer pointSymbolizer = null;
for (Symbolizer symbolizer : symbolizers) {
if (symbolizer instanceof PointSymbolizer) {
pointSymbolizer = (PointSymbolizer) symbolizer;
break;
}
}
if (pointSymbolizer == null) {
throw new IllegalArgumentException();
}
return pointSymbolizer;
}
/**
* Get the {@link PolygonSymbolizer} from the given rule.
*
* @param rule the rule to check for symbolizers.
* @return the first symbolizer found.
*/
public static PolygonSymbolizer polygonSymbolizerFromRule(Rule rule) {
List<Symbolizer> symbolizers = rule.symbolizers();
PolygonSymbolizer polygonSymbolizer = null;
for (Symbolizer symbolizer : symbolizers) {
if (symbolizer instanceof PolygonSymbolizer) {
polygonSymbolizer = (PolygonSymbolizer) symbolizer;
break;
}
}
if (polygonSymbolizer == null) {
throw new IllegalArgumentException();
}
return polygonSymbolizer;
}
/**
* Get the {@link LineSymbolizer} from the given rule.
*
* @param rule the rule to check for symbolizers.
* @return the first symbolizer found.
*/
public static LineSymbolizer lineSymbolizerFromRule(Rule rule) {
List<Symbolizer> symbolizers = rule.symbolizers();
LineSymbolizer lineSymbolizer = null;
for (Symbolizer symbolizer : symbolizers) {
if (symbolizer instanceof LineSymbolizer) {
lineSymbolizer = (LineSymbolizer) symbolizer;
break;
}
}
if (lineSymbolizer == null) {
throw new IllegalArgumentException();
}
return lineSymbolizer;
}
/**
* Change the mark shape in a rule.
*
* @param rule the rule of which the mark has to be changed.
* @param wellKnownMarkName the name of the new mark.
*/
public static void substituteMark(Rule rule, String wellKnownMarkName) {
PointSymbolizer pointSymbolizer = Utilities.pointSymbolizerFromRule(rule);
Mark oldMark = SLD.mark(pointSymbolizer);
Graphic graphic = SLD.graphic(pointSymbolizer);
graphic.graphicalSymbols().clear();
Mark mark = Utilities.sf.createMark();
mark.setWellKnownName(Utilities.ff.literal(wellKnownMarkName));
if (oldMark != null) {
mark.setFill(oldMark.getFill());
mark.setStroke(oldMark.getStroke());
}
graphic.graphicalSymbols().add(mark);
}
/**
* Change the external graphic in a rule.
*
* @param rule the rule of which the external graphic has to be changed.
* @param path the path of the image.
*/
public static void substituteExternalGraphics(Rule rule, URL externalGraphicsUrl) {
String urlString = externalGraphicsUrl.toString();
String format = "";
if (urlString.toLowerCase().endsWith(".png")) {
format = "image/png";
} else if (urlString.toLowerCase().endsWith(".jpg")) {
format = "image/jpg";
} else if (urlString.toLowerCase().endsWith(".svg")) {
format = "image/svg+xml";
} else {
urlString = "";
try {
externalGraphicsUrl = new URL("file:");
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
PointSymbolizer pointSymbolizer = Utilities.pointSymbolizerFromRule(rule);
Graphic graphic = SLD.graphic(pointSymbolizer);
graphic.graphicalSymbols().clear();
ExternalGraphic exGraphic = sf.createExternalGraphic(externalGraphicsUrl, format);
graphic.graphicalSymbols().add(exGraphic);
}
public static String getFormat(String path) {
String format = "";
if (path.toLowerCase().endsWith(".png")) {
format = "image/png";
} else if (path.toLowerCase().endsWith(".jpg")) {
format = "image/jpg";
} else if (path.toLowerCase().endsWith(".gif")) {
format = "image/gif";
} else if (path.toLowerCase().endsWith(".svg")) {
format = "image/svg+xml";
}
return format;
}
/**
* Get the format of an {@link ExternalGraphic} from its path or name.
*
* @param name the path or file name to test against.
* @return teh format definition.
*/
public static String getExternalGraphicFormat(String name) {
String format = "";
if (name.toLowerCase().endsWith(".png")) {
format = "image/png";
} else if (name.toLowerCase().endsWith(".jpg")) {
format = "image/jpg";
} else if (name.toLowerCase().endsWith(".gif")) {
format = "image/gif";
} else if (name.toLowerCase().endsWith(".svg")) {
format = "image/svg+xml";
} else {
return null;
}
return format;
}
/**
* Changes the size of a mark inside a rule.
*
* @param rule the {@link Rule}.
* @param newSize the new size.
*/
public static void changeMarkSize(Rule rule, int newSize) {
PointSymbolizer pointSymbolizer = Utilities.pointSymbolizerFromRule(rule);
Graphic graphic = SLD.graphic(pointSymbolizer);
graphic.setSize(ff.literal(newSize));
// Mark oldMark = SLDs.mark(pointSymbolizer);
// oldMark.setSize(ff.literal(newSize));
// Graphic graphic = SLDs.graphic(pointSymbolizer);
}
/**
* Changes the rotation value inside a rule.
*
* @param rule the {@link Rule}.
* @param newRotation the new rotation value in degrees.
*/
public static void changeRotation(Rule rule, int newRotation) {
PointSymbolizer pointSymbolizer = Utilities.pointSymbolizerFromRule(rule);
Graphic graphic = SLD.graphic(pointSymbolizer);
graphic.setRotation(ff.literal(newRotation));
// Mark oldMark = SLDs.mark(pointSymbolizer);
// oldMark.setSize(ff.literal(newRotation));
}
/**
* Get the offset from a {@link Symbolizer}.
*
* @param symbolizer the symbolizer.
* @return the offset.
*/
@SuppressWarnings("rawtypes")
public static Point2D getOffset(Symbolizer symbolizer) {
Expression geometry = symbolizer.getGeometry();
if (geometry != null) {
if (geometry instanceof FilterFunction_offset) {
FilterFunction_offset offsetFunction = (FilterFunction_offset) geometry;
List parameters = offsetFunction.getParameters();
Expression xOffsetExpr = (Expression) parameters.get(1);
Expression yOffsetExpr = (Expression) parameters.get(2);
Double xOffsetDouble = xOffsetExpr.evaluate(null, Double.class);
Double yOffsetDouble = yOffsetExpr.evaluate(null, Double.class);
if (xOffsetDouble != null && yOffsetDouble != null) {
Point2D.Double point = new Point2D.Double(xOffsetDouble, yOffsetDouble);
return point;
}
}
}
return null;
}
/**
* Sets the offset in a symbolizer.
*
* @param symbolizer the symbolizer.
* @param text the text representing the offsets in the CSV form.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void setOffset(Symbolizer symbolizer, String text) {
if (text.indexOf(',') == -1) {
return;
}
String[] split = text.split(",");
if (split.length != 2) {
return;
}
double xOffset = Double.parseDouble(split[0]);
double yOffset = Double.parseDouble(split[1]);
Expression geometry = symbolizer.getGeometry();
if (geometry != null) {
if (geometry instanceof FilterFunction_offset) {
FilterFunction_offset offsetFunction = (FilterFunction_offset) geometry;
List parameters = offsetFunction.getParameters();
parameters.set(1, ff.literal(xOffset));
parameters.set(2, ff.literal(yOffset));
}
} else {
Function function =
ff.function("offset", ff.property("the_geom"), ff.literal(xOffset), ff.literal(yOffset));
symbolizer.setGeometry(function);
}
}
/**
* Checks if the list of {@link Rule}s supplied contains one with the supplied name.
*
* <p>If the rule is contained it adds an index to the name.
*
* @param rulesWrapper the list of rules to check.
* @param ruleName the name of the rule to find.
* @return the new name of the rule.
*/
public static String checkSameNameRule(List<RuleWrapper> rulesWrapper, String ruleName) {
int index = 1;
String name = ruleName.trim();
for (int i = 0; i < rulesWrapper.size(); i++) {
RuleWrapper ruleWrapper = rulesWrapper.get(i);
String tmpName = ruleWrapper.getName();
if (tmpName == null) {
continue;
}
tmpName = tmpName.trim();
if (tmpName.equals(name)) {
// name exists, change the name of the entering
if (name.endsWith(")")) {
name = name.trim().replaceFirst("\\([0-9]+\\)$", "(" + (index++) + ")");
} else {
name = name + " (" + (index++) + ")";
}
// start again
i = 0;
}
if (index == 1000) {
// something odd is going on
throw new RuntimeException();
}
}
return name;
}
/**
* Checks if the list of {@link FeatureTypeStyleWrapper}s supplied contains one with the supplied name.
*
* <p>If the rule is contained it adds an index to the name.
*
* @param ftsWrapperList the list of featureTypeStyles to check.
* @param ftsName the name of the featureTypeStyle to find.
* @return the new name of the featureTypeStyle.
*/
public static String checkSameNameFeatureTypeStyle(List<FeatureTypeStyleWrapper> ftsWrapperList, String ftsName) {
int index = 1;
String name = ftsName.trim();
for (int i = 0; i < ftsWrapperList.size(); i++) {
FeatureTypeStyleWrapper ftsWrapper = ftsWrapperList.get(i);
String tmpName = ftsWrapper.getName();
if (tmpName == null) {
continue;
}
tmpName = tmpName.trim();
if (tmpName.equals(name)) {
// name exists, change the name of the entering
if (name.endsWith(")")) {
name = name.trim().replaceFirst("\\([0-9]+\\)$", "(" + (index++) + ")");
} else {
name = name + " (" + (index++) + ")";
}
// start again
i = 0;
}
if (index == 1000) {
// something odd is going on
throw new RuntimeException();
}
}
return name;
}
/**
* Checks if the list of {@link StyleWrapper}s supplied contains one with the supplied name.
*
* <p>If the style is contained it adds an index to the name.
*
* @param styles the list of style wrappers to check.
* @param styleName the name of the style to find.
* @return the new name of the style.
*/
public static String checkSameNameStyle(List<StyleWrapper> styles, String styleName) {
int index = 1;
String name = styleName.trim();
for (int i = 0; i < styles.size(); i++) {
StyleWrapper styleWrapper = styles.get(i);
String tmpName = styleWrapper.getName();
if (tmpName == null) {
continue;
}
tmpName = tmpName.trim();
if (tmpName.equals(name)) {
// name exists, change the name of the entering
if (name.endsWith(")")) {
name = name.trim().replaceFirst("\\([0-9]+\\)$", "(" + (index++) + ")");
} else {
name = name + " (" + (index++) + ")";
}
// start again
i = 0;
}
if (index == 1000) {
// something odd is going on
throw new RuntimeException();
}
}
return name;
}
/**
* Converts a list of {@link Rule}s to a {@link Style} with the given name.
*
* @param rules the list of rules.
* @param name the name of the new style.
* @param oneFeaturetypestylePerRule switch to create a {@link FeatureTypeStyle} per {@link Rule}.
* @return the new style created.
*/
public static Style rulesToStyle(List<Rule> rules, String name, boolean oneFeaturetypestylePerRule) {
Style namedStyle = Utilities.sf.createStyle();
if (!oneFeaturetypestylePerRule) {
FeatureTypeStyle featureTypeStyle = Utilities.sf.createFeatureTypeStyle();
List<Rule> currentRules = featureTypeStyle.rules();
for (int i = 0; i < rules.size(); i++) {
Rule rule = rules.get(i);
currentRules.add(rule);
}
namedStyle.featureTypeStyles().add(featureTypeStyle);
} else {
for (int i = 0; i < rules.size(); i++) {
FeatureTypeStyle featureTypeStyle = Utilities.sf.createFeatureTypeStyle();
Rule rule = rules.get(i);
featureTypeStyle.rules().add(rule);
namedStyle.featureTypeStyles().add(featureTypeStyle);
}
}
namedStyle.setName(name);
return namedStyle;
}
/**
* Converts a style to its string representation to be written to file.
*
* @param style the style to convert.
* @return the style string.
* @throws Exception
*/
public static String styleToString(Style style) throws Exception {
StyledLayerDescriptor sld = sf.createStyledLayerDescriptor();
UserLayer layer = sf.createUserLayer();
layer.setLayerFeatureConstraints(new FeatureTypeConstraint[] { null });
sld.addStyledLayer(layer);
layer.addUserStyle(style);
SLDTransformer aTransformer = new SLDTransformer();
aTransformer.setIndentation(4);
String xml = aTransformer.transform(sld);
return xml;
}
/**
* Generates a style based on a graphic.
*
* @param graphicsPath the graphic.
* @return the generated style.
* @throws IOException
*/
public static StyleWrapper createStyleFromGraphic(File graphicsPath) throws IOException {
String name = graphicsPath.getName();
ExternalGraphic exGraphic = null;
if (name.toLowerCase().endsWith(".png")) {
exGraphic = sf.createExternalGraphic(graphicsPath.toURI().toURL(), "image/png");
} else if (name.toLowerCase().endsWith(".svg")) {
exGraphic = sf.createExternalGraphic(graphicsPath.toURI().toURL(), "image/svg+xml");
} else if (name.toLowerCase().endsWith(".sld")) {
StyledLayerDescriptor sld = readStyle(graphicsPath);
Style style = SldUtilities.getDefaultStyle(sld);
return new StyleWrapper(style);
}
if (exGraphic == null) {
throw new IOException("Style could not be created!");
}
Graphic gr = sf.createDefaultGraphic();
gr.graphicalSymbols().clear();
gr.graphicalSymbols().add(exGraphic);
Expression size = ff.literal(20);
gr.setSize(size);
Rule rule = sf.createRule();
PointSymbolizer pointSymbolizer = sf.createPointSymbolizer(gr, null);
rule.symbolizers().add(pointSymbolizer);
FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle();
featureTypeStyle.rules().add(rule);
Style namedStyle = sf.createStyle();
namedStyle.featureTypeStyles().add(featureTypeStyle);
namedStyle.setName(FilenameUtils.removeExtension(name));
return new StyleWrapper(namedStyle);
}
/**
* Returns a dash array from a dash string.
*
* @param dashStr the dash string definition.
* @return the dash array or null if the definition can't be parsed.
*/
public static float[] getDash(String dashStr) {
if (dashStr == null) {
return null;
}
String[] dashSplit = dashStr.split(","); //$NON-NLS-1$
int size = dashSplit.length;
float[] dash = new float[size];
try {
for (int i = 0; i < dash.length; i++) {
dash[i] = Float.parseFloat(dashSplit[i].trim());
}
return dash;
} catch (NumberFormatException e) {
return null;
}
}
/**
* Converts teh array to string.
*
* @param dashArray the dash array.
* @return the converted string.
*/
public static String getDashString(float[] dashArray) {
StringBuilder sb = null;
for (float f : dashArray) {
if (sb == null) {
sb = new StringBuilder(String.valueOf(f));
} else {
sb.append(",");
sb.append(String.valueOf(f));
}
}
return sb.toString();
}
/**
* Checks if a string is a number (currently Double, Float, Integer).
*
* @param value the string to check.
* @param adaptee the class to check against. If null, the more permissive {@link Double} will be used.
* @return the number or null, if the parsing fails.
*/
@SuppressWarnings("unchecked")
public static <T extends Number> T isNumber(String value, Class<T> adaptee) {
if (value == null) {
return null;
}
if (adaptee == null) {
adaptee = (Class<T>) Double.class;
}
if (adaptee.isAssignableFrom(Double.class)) {
try {
Double parsed = Double.parseDouble(value);
return adaptee.cast(parsed);
} catch (Exception e) {
return null;
}
} else if (adaptee.isAssignableFrom(Float.class)) {
try {
Float parsed = Float.parseFloat(value);
return adaptee.cast(parsed);
} catch (Exception e) {
return null;
}
} else if (adaptee.isAssignableFrom(Integer.class)) {
try {
Integer parsed = Integer.parseInt(value);
return adaptee.cast(parsed);
} catch (Exception e) {
// still try the double
Double number = isNumber(value, Double.class);
if (number != null) {
return adaptee.cast(number.intValue());
}
return null;
}
} else {
throw new IllegalArgumentException();
}
}
/**
* Convert a sld line join definition to the java awt value.
*
* @param sldJoin the sld join string.
* @return the awt value.
*/
public static int sld2awtJoin(String sldJoin) {
if (sldJoin.equals(lineJoinNames[1])) {
return BasicStroke.JOIN_BEVEL;
} else if (sldJoin.equals("") || sldJoin.equals(lineJoinNames[2])) {
return BasicStroke.JOIN_MITER;
} else if (sldJoin.equals(lineJoinNames[3])) {
return BasicStroke.JOIN_ROUND;
} else {
throw new IllegalArgumentException("unsupported line join");
}
}
/**
* Convert a sld line cap definition to the java awt value.
*
* @param sldCap the sld cap string.
* @return the awt value.
*/
public static int sld2awtCap(String sldCap) {
if (sldCap.equals("") || sldCap.equals(lineCapNames[1])) {
return BasicStroke.CAP_BUTT;
} else if (sldCap.equals(lineCapNames[2])) {
return BasicStroke.CAP_ROUND;
} else if (sldCap.equals(lineCapNames[3])) {
return BasicStroke.CAP_SQUARE;
} else {
throw new IllegalArgumentException("unsupported line cap");
}
}
}