/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2010 Geomatys
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotoolkit.style;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.factory.Hints;
import org.geotoolkit.gui.swing.tree.DefaultMutableTreeNode;
import org.geotoolkit.gui.swing.tree.MutableTreeNode;
import org.geotoolkit.lang.Static;
import org.geotoolkit.sld.DefaultSLDFactory;
import org.geotoolkit.sld.MutableSLDFactory;
import org.geotoolkit.sld.MutableStyledLayerDescriptor;
import org.geotoolkit.sld.MutableUserLayer;
import org.apache.sis.util.ArgumentChecks;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.expression.Expression;
import org.opengis.sld.Layer;
import org.opengis.sld.StyledLayerDescriptor;
import org.opengis.sld.UserLayer;
import org.opengis.style.FeatureTypeStyle;
import org.opengis.style.Fill;
import org.opengis.style.Graphic;
import org.opengis.style.LineSymbolizer;
import org.opengis.style.PointSymbolizer;
import org.opengis.style.PolygonSymbolizer;
import org.opengis.style.RasterSymbolizer;
import org.opengis.style.Rule;
import org.opengis.style.Stroke;
import org.opengis.style.Style;
import org.opengis.style.Symbolizer;
import org.opengis.style.TextSymbolizer;
/**
* Convenient methods to transform a style in tree.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public final class StyleUtilities extends Static {
private static final MutableStyleFactory SF = (MutableStyleFactory) FactoryFinder.getStyleFactory(
new Hints(Hints.STYLE_FACTORY, MutableStyleFactory.class));
private static final FilterFactory FF = FactoryFinder.getFilterFactory(null);
private static final MutableSLDFactory SLDF = new DefaultSLDFactory();
private StyleUtilities(){}
public static MutableStyledLayerDescriptor copy(final StyledLayerDescriptor sld){
ArgumentChecks.ensureNonNull("sld", sld);
final MutableStyledLayerDescriptor copy = SLDF.createSLD();
copy.setName(sld.getName());
copy.setVersion(sld.getVersion());
copy.setDescription(sld.getDescription());
for(Layer layer : sld.layers()){
if(layer instanceof UserLayer){
copy.layers().add(copy((UserLayer)layer));
}else{
//copy.layers().add(layer);
}
}
return copy;
}
public static MutableUserLayer copy(final UserLayer layer){
ArgumentChecks.ensureNonNull("layer", layer);
final MutableUserLayer copy = SLDF.createUserLayer();
copy.setName(layer.getName());
//copy.setConstraints(layer.getConstraints());
copy.setDescription(layer.getDescription());
copy.setSource(layer.getSource());
for(Style style : layer.styles()){
copy.styles().add(copy(style));
}
return copy;
}
public static MutableStyle copy(final Style style){
return copy(style,1d);
}
public static MutableStyle copy(final Style style, final double opacity){
ArgumentChecks.ensureNonNull("style", style);
final MutableStyle copy = SF.style();
copy.setDefault(style.isDefault());
copy.setDefaultSpecification(style.getDefaultSpecification());
copy.setDescription(style.getDescription());
copy.setName(style.getName());
for(FeatureTypeStyle fts : style.featureTypeStyles()){
copy.featureTypeStyles().add(copy(fts,opacity));
}
return copy;
}
public static MutableFeatureTypeStyle copy(final FeatureTypeStyle fts){
return copy(fts,1d);
}
public static MutableFeatureTypeStyle copy(final FeatureTypeStyle fts, final double opacity){
ArgumentChecks.ensureNonNull("fts", fts);
final MutableFeatureTypeStyle copy = SF.featureTypeStyle();
copy.semanticTypeIdentifiers().addAll(fts.semanticTypeIdentifiers());
copy.setDescription(fts.getDescription());
copy.setFeatureInstanceIDs(fts.getFeatureInstanceIDs());
copy.setName(fts.getName());
copy.setOnlineResource(fts.getOnlineResource());
for(Rule r : fts.rules()){
copy.rules().add(copy(r,opacity));
}
return copy;
}
public static MutableRule copy(final Rule rule){
return copy(rule,1d);
}
public static MutableRule copy(final Rule rule, final double opacity){
ArgumentChecks.ensureNonNull("rule", rule);
final MutableRule copy = SF.rule();
copy.setDescription(rule.getDescription());
copy.setElseFilter(rule.isElseFilter());
copy.setFilter(rule.getFilter());
copy.setLegendGraphic(rule.getLegend());
copy.setMaxScaleDenominator(rule.getMaxScaleDenominator());
copy.setMinScaleDenominator(rule.getMinScaleDenominator());
copy.setName(rule.getName());
copy.setOnlineResource(rule.getOnlineResource());
for(Symbolizer symbol : rule.symbolizers()){
copy.symbolizers().add(copy(symbol,opacity));
}
return copy;
}
public static Symbolizer copy(final Symbolizer symbol, final double opacity){
ArgumentChecks.ensureNonNull("symbol", symbol);
if(opacity == 1){
//no need to modify the symbol
return symbol;
}
if(symbol instanceof PointSymbolizer){
final PointSymbolizer ps = (PointSymbolizer) symbol;
final Graphic gra = ps.getGraphic();
return SF.pointSymbolizer(
ps.getName(),
ps.getGeometryPropertyName(),
ps.getDescription(),
ps.getUnitOfMeasure(),
SF.graphic(
gra.graphicalSymbols(),
correctOpacity(gra.getOpacity(),opacity),
gra.getSize(),
gra.getRotation(),
gra.getAnchorPoint(),
gra.getDisplacement())
);
}else if(symbol instanceof LineSymbolizer){
final LineSymbolizer ps = (LineSymbolizer) symbol;
return SF.lineSymbolizer(
ps.getName(),
ps.getGeometryPropertyName(),
ps.getDescription(),
ps.getUnitOfMeasure(),
correctOpacity(ps.getStroke(), opacity),
ps.getPerpendicularOffset());
}else if(symbol instanceof PolygonSymbolizer){
final PolygonSymbolizer ps = (PolygonSymbolizer) symbol;
final Stroke str = ps.getStroke();
return SF.polygonSymbolizer(
ps.getName(),
ps.getGeometryPropertyName(),
ps.getDescription(),
ps.getUnitOfMeasure(),
correctOpacity(ps.getStroke(), opacity),
correctOpacity(ps.getFill(), opacity),
ps.getDisplacement(),
ps.getPerpendicularOffset());
}else if(symbol instanceof TextSymbolizer){
final TextSymbolizer ps = (TextSymbolizer) symbol;
return SF.textSymbolizer(
ps.getName(),
ps.getGeometryPropertyName(),
ps.getDescription(),
ps.getUnitOfMeasure(),
ps.getLabel(),
ps.getFont(),
ps.getLabelPlacement(),
SF.halo(
correctOpacity(ps.getHalo().getFill(), opacity),
ps.getHalo().getRadius()),
correctOpacity(ps.getFill(), opacity));
}else if(symbol instanceof RasterSymbolizer){
final RasterSymbolizer ps = (RasterSymbolizer) symbol;
return SF.rasterSymbolizer(
ps.getName(),
ps.getGeometryPropertyName(),
ps.getDescription(),
ps.getUnitOfMeasure(),
correctOpacity(ps.getOpacity(),opacity),
ps.getChannelSelection(),
ps.getOverlapBehavior(),
ps.getColorMap(),
ps.getContrastEnhancement(),
ps.getShadedRelief(),
ps.getImageOutline());
}else{
return symbol;
}
}
private static Fill correctOpacity(final Fill fl, final double opacity){
ArgumentChecks.ensureNonNull("fill", fl);
return SF.fill(
fl.getGraphicFill(),
fl.getColor(),
correctOpacity(fl.getOpacity(),opacity));
}
private static Stroke correctOpacity(final Stroke str, final double opacity){
return SF.stroke(
str.getGraphicFill(),
str.getColor(),
correctOpacity(str.getOpacity(),opacity),
str.getWidth(),
str.getLineJoin(),
str.getLineCap(),
str.getDashArray(),
str.getDashOffset());
}
private static Expression correctOpacity(final Expression exp, final double opacity){
return FF.multiply(exp, FF.literal(opacity));
}
public static MutableTreeNode asTreeNode(final MutableStyle element){
return new StyleNode(element);
}
public static MutableTreeNode asTreeNode(final MutableFeatureTypeStyle element){
return new FTSNode(element);
}
public static MutableTreeNode asTreeNode(final MutableRule element){
return new RuleNode(element);
}
public static MutableTreeNode asTreeNode(final Symbolizer element){
return new SymbolNode(element);
}
private static class StyleNode extends DefaultMutableTreeNode{
private MutableStyle element;
public StyleNode(final MutableStyle element){
super(element);
this.element = element;
//todo must add listener mecanism
for(MutableFeatureTypeStyle fts : element.featureTypeStyles()){
add(asTreeNode(fts));
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Style : ").append(element.getClass().getSimpleName()).append(' ');
sb.append(element.getName()).append(element.getDescription());
return sb.toString();
}
}
private static class FTSNode extends DefaultMutableTreeNode{
private MutableFeatureTypeStyle element;
public FTSNode(final MutableFeatureTypeStyle element){
super(element);
this.element = element;
//todo must add listener mecanism
for(MutableRule rule : element.rules()){
add(asTreeNode(rule));
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("FTS : ").append(element.getClass().getSimpleName()).append(' ');
sb.append(element.getName()).append(element.getDescription());
return sb.toString();
}
}
private static class RuleNode extends DefaultMutableTreeNode{
private MutableRule element;
public RuleNode(final MutableRule element){
super(element);
this.element = element;
//todo must add listener mecanism
for(Symbolizer symbol : element.symbolizers()){
add(asTreeNode(symbol));
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Rule : ").append(element.getClass().getSimpleName()).append(' ');
sb.append(element.getName()).append(element.getDescription());
return sb.toString();
}
}
private static class SymbolNode extends DefaultMutableTreeNode{
private Symbolizer element;
public SymbolNode(final Symbolizer element){
super(element);
this.element = element;
//todo must add listener mecanism
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Symbol : ").append(element.getClass().getSimpleName()).append(' ');
sb.append(element.getName()).append(element.getDescription());
return sb.toString();
}
}
}