/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2008 - 2009, 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; 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.
*/
package org.geotoolkit.sld.xml;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.imageio.ImageIO;
import javax.measure.quantity.Length;
import javax.measure.Unit;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.apache.sis.measure.Units;
import org.geotoolkit.util.NamesExt;
import org.geotoolkit.ogc.xml.OGC110toGTTransformer;
import org.geotoolkit.se.xml.v110.AnchorPointType;
import org.geotoolkit.se.xml.v110.ChannelSelectionType;
import org.geotoolkit.se.xml.v110.ColorMapType;
import org.geotoolkit.se.xml.v110.ContrastEnhancementType;
import org.geotoolkit.se.xml.v110.CoverageStyleType;
import org.geotoolkit.se.xml.v110.DescriptionType;
import org.geotoolkit.se.xml.v110.DisplacementType;
import org.geotoolkit.se.xml.v110.ExternalGraphicType;
import org.geotoolkit.se.xml.v110.FeatureTypeStyleType;
import org.geotoolkit.se.xml.v110.FillType;
import org.geotoolkit.se.xml.v110.FontType;
import org.geotoolkit.se.xml.v110.GeometryType;
import org.geotoolkit.se.xml.v110.GraphicFillType;
import org.geotoolkit.se.xml.v110.GraphicStrokeType;
import org.geotoolkit.se.xml.v110.GraphicType;
import org.geotoolkit.se.xml.v110.HaloType;
import org.geotoolkit.se.xml.v110.ImageOutlineType;
import org.geotoolkit.se.xml.v110.LabelPlacementType;
import org.geotoolkit.se.xml.v110.LegendGraphicType;
import org.geotoolkit.se.xml.v110.LinePlacementType;
import org.geotoolkit.se.xml.v110.LineSymbolizerType;
import org.geotoolkit.se.xml.v110.MarkType;
import org.geotoolkit.se.xml.v110.MethodType;
import org.geotoolkit.se.xml.v110.ModeType;
import org.geotoolkit.se.xml.v110.OnlineResourceType;
import org.geotoolkit.se.xml.v110.ParameterValueType;
import org.geotoolkit.se.xml.v110.PointPlacementType;
import org.geotoolkit.se.xml.v110.PointSymbolizerType;
import org.geotoolkit.se.xml.v110.PolygonSymbolizerType;
import org.geotoolkit.se.xml.v110.RasterSymbolizerType;
import org.geotoolkit.se.xml.v110.RuleType;
import org.geotoolkit.se.xml.v110.ShadedReliefType;
import org.geotoolkit.se.xml.v110.StrokeType;
import org.geotoolkit.se.xml.v110.SvgParameterType;
import org.geotoolkit.se.xml.v110.SymbolizerType;
import org.geotoolkit.se.xml.v110.TextSymbolizerType;
import org.geotoolkit.se.xml.v110.ThreshholdsBelongToType;
import org.geotoolkit.se.xml.v110.CategorizeType;
import org.geotoolkit.se.xml.v110.ChangeCaseType;
import org.geotoolkit.se.xml.v110.ColorReplacementType;
import org.geotoolkit.se.xml.v110.ConcatenateType;
import org.geotoolkit.se.xml.v110.FormatDateType;
import org.geotoolkit.se.xml.v110.FormatNumberType;
import org.geotoolkit.se.xml.v110.InterpolateType;
import org.geotoolkit.se.xml.v110.InterpolationPointType;
import org.geotoolkit.se.xml.v110.MapItemType;
import org.geotoolkit.se.xml.v110.RecodeType;
import org.geotoolkit.se.xml.v110.StringLengthType;
import org.geotoolkit.se.xml.v110.StringPositionType;
import org.geotoolkit.se.xml.v110.SubstringType;
import org.geotoolkit.se.xml.v110.TrimType;
import org.geotoolkit.se.xml.vext.ColorItemType;
import org.geotoolkit.se.xml.vext.JenksType;
import org.geotoolkit.se.xml.vext.RangeType;
import org.geotoolkit.se.xml.vext.RecolorType;
import org.geotoolkit.style.DefaultColorReplacement;
import org.geotoolkit.style.MutableFeatureTypeStyle;
import org.geotoolkit.style.MutableRule;
import org.geotoolkit.style.MutableStyle;
import org.geotoolkit.style.StyleConstants;
import org.geotoolkit.style.MutableStyleFactory;
import org.geotoolkit.style.function.Categorize;
import org.geotoolkit.style.function.ColorItem;
import org.geotoolkit.style.function.Interpolate;
import org.geotoolkit.style.function.InterpolationPoint;
import org.geotoolkit.style.function.Jenks;
import org.geotoolkit.style.function.Method;
import org.geotoolkit.style.function.Mode;
import org.geotoolkit.style.function.RecolorFunction;
import org.geotoolkit.style.function.ThreshholdsBelongTo;
import org.apache.sis.util.logging.Logging;
import org.geotoolkit.se.xml.v110.InlineContentType;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Function;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.metadata.citation.OnlineResource;
import org.opengis.util.FactoryException;
import org.opengis.style.AnchorPoint;
import org.opengis.style.ChannelSelection;
import org.opengis.style.ColorMap;
import org.opengis.style.ColorReplacement;
import org.opengis.style.ContrastEnhancement;
import org.opengis.style.ContrastMethod;
import org.opengis.style.Description;
import org.opengis.style.Displacement;
import org.opengis.style.ExternalGraphic;
import org.opengis.style.ExternalMark;
import org.opengis.style.Fill;
import org.opengis.style.Font;
import org.opengis.style.Graphic;
import org.opengis.style.GraphicFill;
import org.opengis.style.GraphicLegend;
import org.opengis.style.GraphicStroke;
import org.opengis.style.GraphicalSymbol;
import org.opengis.style.Halo;
import org.opengis.style.LabelPlacement;
import org.opengis.style.LinePlacement;
import org.opengis.style.LineSymbolizer;
import org.opengis.style.Mark;
import org.opengis.style.OverlapBehavior;
import org.opengis.style.PointPlacement;
import org.opengis.style.PointSymbolizer;
import org.opengis.style.PolygonSymbolizer;
import org.opengis.style.RasterSymbolizer;
import org.opengis.style.SelectedChannelType;
import org.opengis.style.SemanticType;
import org.opengis.style.ShadedRelief;
import org.opengis.style.Stroke;
import org.opengis.style.Symbolizer;
import org.opengis.style.TextSymbolizer;
/**
* Transform a SE v1.1.0 symbology in GT classes.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class SE110toGTTransformer extends OGC110toGTTransformer {
private static final String GENERIC_ANY = "generic:any";
private static final String GENERIC_POINT = "generic:point";
private static final String GENERIC_LINE = "generic:line";
private static final String GENERIC_POLYGON = "generic:polygon";
private static final String GENERIC_TEXT = "generic:text";
private static final String GENERIC_RASTER = "generic:raster";
private static final String UOM_METRE = "http://www.opengeospatial.org/se/units/metre";
private static final String UOM_FOOT = "http://www.opengeospatial.org/se/units/foot";
private static final String UOM_PIXEL = "http://www.opengeospatial.org/se/units/pixel";
protected final MutableStyleFactory styleFactory;
protected final StyleXmlIO xmlUtilities = new StyleXmlIO();
public SE110toGTTransformer(final FilterFactory2 filterFactory,final MutableStyleFactory styleFactory){
super(filterFactory);
this.styleFactory = styleFactory;
}
public SE110toGTTransformer(final FilterFactory2 filterFactory,final MutableStyleFactory styleFactory, final Map<String, String> namespaceMapping){
super(filterFactory, namespaceMapping);
this.styleFactory = styleFactory;
}
public Description visitDescription(final DescriptionType dt) {
if (dt == null) {
return StyleConstants.DEFAULT_DESCRIPTION;
} else {
return styleFactory.description(
(dt.getTitle() == null) ? null : dt.getTitle(),
(dt.getAbstract() == null) ? null : dt.getAbstract());
}
}
public OnlineResource visitOnlineResource(final org.geotoolkit.se.xml.v110.OnlineResourceType ort) {
URI uri = null;
try {
uri = new URI(ort.getHref());
} catch (URISyntaxException ex) {
Logging.getLogger("org.geotoolkit.sld.xml").log(Level.WARNING, null, ex);
}
if (uri != null) {
return styleFactory.onlineResource(uri);
}
return null;
}
public String visitGeom(final GeometryType geometry) {
if(geometry == null || geometry.getPropertyName() == null || geometry.getPropertyName().getContent() == null || geometry.getPropertyName().getContent().trim().isEmpty()) return null;
return geometry.getPropertyName().getContent();
}
public Object visitSVG(final SvgParameterType svg) {
// JAXBElementFunctionType>
// String
// JAXBElementExpressionType>
// JAXBElementLiteralType>
// JAXBElementBinaryOperatorType>
// JAXBElementBinaryOperatorType>
// JAXBElementBinaryOperatorType>
// JAXBElementPropertyNameType>
// JAXBElementBinaryOperatorType>
if(SEJAXBStatics.STROKE_DASHARRAY.equalsIgnoreCase(svg.getName()) ){
final List<Serializable> content = svg.getContent();
Object value = null;
for(final Serializable obj : content){
if(obj instanceof String && !obj.toString().trim().isEmpty()){
value = obj.toString();
}else if(obj instanceof JAXBElement<?>){
value = visitExpression( (JAXBElement<?>)obj );
}
}
if(value != null){
//its a float array
final float[] values = new float[]{0,0};
final String[] parts = value.toString().split(" ");
for(int i=0;i < parts.length && i<2 ;i++){
try{
final Float f = Float.valueOf(parts[i]);
values[i] = f.floatValue();
}catch(NumberFormatException ne){}
}
return values;
}else{
return null;
}
}
final List<Serializable> content = svg.getContent();
for(final Serializable obj : content){
if(obj instanceof String && !obj.toString().trim().isEmpty()){
return filterFactory.literal(obj.toString());
}else if(obj instanceof JAXBElement<?>){
return visitExpression( (JAXBElement<?>)obj );
}
}
if(!content.isEmpty()){
//we arrived here with finding a real value but the content is not empty
//so it's an empty string value
return filterFactory.literal("");
}
return null;
}
public Unit<Length> visitUOM(final String uom) {
if(uom == null) return Units.POINT;
if(UOM_METRE.equalsIgnoreCase(uom)){
return Units.METRE;
}else if(UOM_FOOT.equalsIgnoreCase(uom)){
return Units.FOOT;
}else if(UOM_PIXEL.equalsIgnoreCase(uom)){
return Units.POINT;
}else{
return Units.POINT;
}
}
/**
* Transform a JaxBelement in Expression.
*/
@Override
public Expression visitExpression(final JAXBElement<?> jax){
//Added in SE1.1-----
// JAXBElementMapItemType>
// JAXBElementInterpolateType>
// JAXBElementConcatenateType>
// JAXBElementChangeCaseType>
// JAXBElementTrimType>
// JAXBElementFormatDateType>
// JAXBElementCategorizeType>
// JAXBElementInterpolationPointType>
// JAXBElementStringLengthType>
// JAXBElementRecodeType>
// JAXBElementnet.opengis.se.FunctionType>
// JAXBElementFormatNumberType>
// JAXBElementSubstringType>
// JAXBElementStringPositionType>
try{
return super.visitExpression(jax);
}catch(IllegalArgumentException ex){
final String expName = jax.getName().toString();
final Object obj = jax.getValue();
if(obj instanceof MapItemType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof InterpolateType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof ConcatenateType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof ChangeCaseType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof TrimType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof FormatDateType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof CategorizeType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof InterpolationPointType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof StringLengthType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof RecodeType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof FormatNumberType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof SubstringType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}else if(obj instanceof StringPositionType){
throw new IllegalArgumentException("Not supported yet : Name > " + expName +" JAXB > " + jax + " OBJECT >" + obj);
}
}
throw new IllegalArgumentException("Unknowed expression element" + jax);
}
/**
* Transform a parametervaluetype in Expression.
*/
public Expression visitExpression(final org.geotoolkit.se.xml.v110.ParameterValueType param) {
if(param == null) return null;
// Objects of the following type(s) are allowed in the list
// JAXBElementFunctionType> ---NS
// String ---k
// JAXBElementExpressionType> ---k
// JAXBElementLiteralType> ---k
// JAXBElementBinaryOperatorType> ---k
// JAXBElementBinaryOperatorType> ---k
// JAXBElementBinaryOperatorType> ---k
// JAXBElementPropertyNameType> ---k
// JAXBElementBinaryOperatorType> ---k
Expression result = Expression.NIL;
final List<Serializable> sers = param.getContent();
if (sers.size() == 1) {
final Serializable ser = sers.get(0);
if (ser instanceof String) {
result = filterFactory.literal((String) ser);
} else if (ser instanceof JAXBElement<?>) {
final JAXBElement<?> jax = (JAXBElement<?>) ser;
result = visitExpression(jax);
}
} else {
for (final Serializable ser : sers) {
if (ser instanceof JAXBElement<?>) {
final JAXBElement<?> jax = (JAXBElement<?>) ser;
result = visitExpression(jax);
break;
}
}
}
return result;
}
/**
* If expression is an empty property name, null is returned.
* @param exp
* @return
*/
private static Expression notEmpty(Expression exp){
if(exp instanceof PropertyName && ((PropertyName)exp).getPropertyName().trim().isEmpty()){
return null;
}
return exp;
}
//Style, FTS and Rule-------------------------------------------------------
/**
* Transform a SLD v1.1 userstyle in GT style.
*/
public MutableStyle visitUserStyle(final org.geotoolkit.sld.xml.v110.UserStyle us) throws FactoryException {
if(us == null){
return null;
}else{
final MutableStyle mls = styleFactory.style();
mls.setName(us.getName());
mls.setDescription(visitDescription(us.getDescription()));
final Boolean def = us.isIsDefault();
mls.setDefault( (def != null)? def : false);
final List<Object> ftss = us.getFeatureTypeStyleOrCoverageStyleOrOnlineResource();
for(final Object obj : ftss){
MutableFeatureTypeStyle fts = visitFTS(obj);
mls.featureTypeStyles().add(fts);
}
return mls;
}
}
/**
* Transform a SLD v1.1 FeatureTypeStyle or CoverageStyle in GT FTS.
*/
public MutableFeatureTypeStyle visitFTS(final Object obj) throws FactoryException{
if(obj == null) return null;
if(obj instanceof OnlineResourceType){
final OnlineResourceType ort = (OnlineResourceType) obj;
final OnlineResource or = visitOnlineResource(ort);
if(or != null){
try{
return xmlUtilities.readFeatureTypeStyle(or, Specification.SymbologyEncoding.V_1_1_0);
}catch(JAXBException ex){
Logging.getLogger("org.geotoolkit.sld.xml").log(Level.WARNING, null, ex);
}
return null;
}
}else if(obj instanceof CoverageStyleType){
final MutableFeatureTypeStyle fts = styleFactory.featureTypeStyle();
final CoverageStyleType cst = (CoverageStyleType) obj;
fts.setName(cst.getName());
fts.setDescription( visitDescription(cst.getDescription()));
fts.semanticTypeIdentifiers().addAll( visitSemantics(cst.getSemanticTypeIdentifier()));
if(cst.getCoverageName() != null){
fts.featureTypeNames().add(NamesExt.create(cst.getCoverageName()));
}
if(cst.getRuleOrOnlineResource() == null || cst.getRuleOrOnlineResource().isEmpty()){
}else{
for(Object objRule : cst.getRuleOrOnlineResource()){
fts.rules().add(visitRule(objRule) );
}
}
return fts;
}else if(obj instanceof FeatureTypeStyleType){
final MutableFeatureTypeStyle fts = styleFactory.featureTypeStyle();
final FeatureTypeStyleType ftst = (FeatureTypeStyleType) obj;
fts.setName(ftst.getName());
fts.setDescription( visitDescription(ftst.getDescription()));
fts.semanticTypeIdentifiers().addAll( visitSemantics(ftst.getSemanticTypeIdentifier()));
if(ftst.getFeatureTypeName() != null){
fts.featureTypeNames().add(NamesExt.create(ftst.getFeatureTypeName()));
}
if(ftst.getRuleOrOnlineResource() == null || ftst.getRuleOrOnlineResource().isEmpty()){
}else{
for(final Object objRule : ftst.getRuleOrOnlineResource()){
fts.rules().add(visitRule(objRule) );
}
}
return fts;
}
return null;
}
/**
* Transform SLD v1.1 semantics in GT semantics.
*/
public Collection<? extends SemanticType> visitSemantics(final List<String> strs){
if(strs == null || strs.isEmpty()){
return Collections.emptyList();
}
final Collection<SemanticType> semantics = new ArrayList<SemanticType>();
for(final String str : strs){
if(GENERIC_ANY.equalsIgnoreCase(str)){
semantics.add( SemanticType.ANY );
}else if(GENERIC_POINT.equalsIgnoreCase(str)){
semantics.add( SemanticType.POINT );
}else if(GENERIC_LINE.equalsIgnoreCase(str)){
semantics.add( SemanticType.LINE );
}else if(GENERIC_POLYGON.equalsIgnoreCase(str)){
semantics.add( SemanticType.POLYGON );
}else if(GENERIC_TEXT.equalsIgnoreCase(str)){
semantics.add( SemanticType.TEXT );
}else if(GENERIC_RASTER.equalsIgnoreCase(str)){
semantics.add( SemanticType.RASTER );
}else{
semantics.add( SemanticType.valueOf(str) );
}
}
return semantics;
}
/**
* Trasnform SLD v1.1 rule in GT Rule.
*/
public MutableRule visitRule(final Object objRule) throws FactoryException {
if(objRule instanceof OnlineResourceType){
final OnlineResourceType ortRule = (OnlineResourceType) objRule;
return visitRule(ortRule);
} else if (objRule instanceof RuleType) {
final RuleType rt = (RuleType) objRule;
return visitRule(rt);
}
return null;
}
/**
* Trasnform SLD v1.1 rule in GT Rule.
*/
public MutableRule visitRule(final OnlineResourceType ort) throws FactoryException {
final OnlineResource or = visitOnlineResource(ort);
if(or != null) {
try{
return xmlUtilities.readRule(or, Specification.SymbologyEncoding.V_1_1_0);
} catch (JAXBException ex) {
Logging.getLogger("org.geotoolkit.sld.xml").log(Level.WARNING, null, ex);
}
return null;
}
return null;
}
/**
* Trasnform SLD v1.1 rule in GT Rule.
*/
public MutableRule visitRule(final org.geotoolkit.se.xml.v110.RuleType rt)
throws FactoryException {
final MutableRule rule = styleFactory.rule();
rule.setName(rt.getName());
rule.setDescription( visitDescription(rt.getDescription()) );
rule.setElseFilter(rt.getElseFilter() != null);
rule.setFilter(visitFilter(rt.getFilter()));
rule.setLegendGraphic(visitLegend(rt.getLegendGraphic()));
rule.setMaxScaleDenominator((rt.getMaxScaleDenominator() == null) ? Double.MAX_VALUE : rt.getMaxScaleDenominator());
rule.setMinScaleDenominator((rt.getMinScaleDenominator() == null) ? 0 : rt.getMinScaleDenominator());
if(rt.getSymbolizer() == null || rt.getSymbolizer().isEmpty()){
}else{
for(final JAXBElement<?> jax : rt.getSymbolizer()) {
final Object st = jax.getValue();
if (st == null) {
continue;
}else if(st instanceof SymbolizerType){
rule.symbolizers().add(visit((SymbolizerType)st));
}else if(st instanceof Symbolizer){
rule.symbolizers().add((Symbolizer)st);
}
}
}
return rule;
}
//Symbolizers---------------------------------------------------------------
/**
* Transform a SLD v1.1 symbolizers in GT Symbolizers.
*/
public Collection<? extends Symbolizer> visitSymbolizers(final List<JAXBElement<? extends SymbolizerType>> objs){
if( objs == null || objs.isEmpty()){
return Collections.emptyList();
}
final Collection<Symbolizer> rs = new ArrayList<Symbolizer>();
for(JAXBElement<? extends SymbolizerType> jax : objs){
final SymbolizerType st = jax.getValue();
if(st == null) continue;
rs.add( visit(st));
}
return rs;
}
public Symbolizer visit(final SymbolizerType st) {
if (st instanceof PointSymbolizerType) {
final PointSymbolizerType pst = (PointSymbolizerType) st;
return visit(pst);
} else if (st instanceof LineSymbolizerType) {
final LineSymbolizerType pst = (LineSymbolizerType) st;
return visit(pst);
} else if (st instanceof PolygonSymbolizerType) {
final PolygonSymbolizerType pst = (PolygonSymbolizerType) st;
return visit(pst);
} else if (st instanceof TextSymbolizerType) {
final TextSymbolizerType pst = (TextSymbolizerType) st;
return visit(pst);
} else if (st instanceof RasterSymbolizerType) {
final RasterSymbolizerType pst = (RasterSymbolizerType) st;
return visit(pst);
} else if(st instanceof Symbolizer){
//jaxbelement is a conform opengis symbolizer
//this element is an extension symbolizer
return (Symbolizer) st;
}
throw new IllegalArgumentException("Unknowned Symbolizer : " + st.getClass().toString());
}
/**
* Transform a SLD v1.1 point symbolizer in GT point symbolizer.
*/
public PointSymbolizer visit(final PointSymbolizerType pst) {
if(pst == null) return null;
final Graphic graphic = (pst.getGraphic() == null) ? styleFactory.graphic() : visit(pst.getGraphic());
final Unit uom = visitUOM(pst.getUom());
final Expression geom = notEmpty(visitExpression(pst.getGeometry()));
final String name = pst.getName();
final Description desc = visitDescription(pst.getDescription());
return styleFactory.pointSymbolizer(name,geom,desc,uom,graphic);
}
/**
* Transform a SLD v1.1 line symbolizer in GT line symbolizer.
*/
public LineSymbolizer visit(final LineSymbolizerType lst) {
if(lst == null) return null;
final Stroke stroke = visit(lst.getStroke());
final Expression offset = (lst.getPerpendicularOffset() == null) ? filterFactory.literal(0) : visitExpression(lst.getPerpendicularOffset());
final Unit uom = visitUOM(lst.getUom());
final Expression geom = notEmpty(visitExpression( lst.getGeometry()));
final String name = lst.getName();
final Description desc = visitDescription(lst.getDescription());
return styleFactory.lineSymbolizer(name,geom,desc,uom,stroke, offset);
}
/**
* Transform a SLD v1.1 polygon symbolizer in GT polygon symbolizer.
*/
public PolygonSymbolizer visit(final PolygonSymbolizerType pst) {
if(pst == null) return null;
final Stroke stroke = visit(pst.getStroke());
final Fill fill = visit(pst.getFill());
final Displacement disp = (pst.getDisplacement() == null)? styleFactory.displacement(0, 0) : visit(pst.getDisplacement());
final Expression offset = (pst.getPerpendicularOffset() == null) ? filterFactory.literal(0) : visitExpression(pst.getPerpendicularOffset());
final Unit uom = visitUOM(pst.getUom());
final Expression geom = notEmpty(visitExpression( pst.getGeometry()));
final String name = pst.getName();
final Description desc = visitDescription(pst.getDescription());
return styleFactory.polygonSymbolizer(name,geom,desc,uom,stroke, fill, disp, offset);
}
/**
* Transform a SLD v1.1 raster symbolizer in GT raster symbolizer.
*/
public RasterSymbolizer visit(final RasterSymbolizerType rst) {
if(rst == null) return null;
final Expression opacity = (rst.getOpacity() == null) ? filterFactory.literal(1) : visitExpression(rst.getOpacity());
final ChannelSelection selection = visit(rst.getChannelSelection());
final OverlapBehavior overlap = visitOverLap(rst.getOverlapBehavior());
final ColorMap colorMap = visit(rst.getColorMap());
final ContrastEnhancement enchance = visit(rst.getContrastEnhancement());
final ShadedRelief relief = visit(rst.getShadedRelief());
final Symbolizer outline = visit(rst.getImageOutline());
final Unit uom = visitUOM(rst.getUom());
final Expression geom = notEmpty(visitExpression( rst.getGeometry()));
final String name = rst.getName();
final Description desc = visitDescription(rst.getDescription());
return styleFactory.rasterSymbolizer(name,geom,desc,uom,opacity, selection, overlap, colorMap, enchance, relief, outline);
}
/**
* Transform a SLD v1.1 text symbolizer in GT text symbolizer.
*/
public TextSymbolizer visit(final TextSymbolizerType tst) {
if(tst == null) return null;
final Expression label = visitExpression(tst.getLabel());
final Font font = (tst.getFont() == null) ? styleFactory.font() : visit(tst.getFont());
final LabelPlacement placement = (tst.getLabelPlacement() == null) ? styleFactory.pointPlacement() : visit(tst.getLabelPlacement());
final Halo halo = (tst.getHalo() == null)? styleFactory.halo(Color.WHITE, 0) : visit(tst.getHalo());
final Fill fill = (tst.getFill() == null)? styleFactory.fill() : visit(tst.getFill());
final Unit uom = visitUOM(tst.getUom());
final Expression geom = notEmpty(visitExpression( tst.getGeometry()));
final String name = tst.getName();
final Description desc = visitDescription(tst.getDescription());
if(label == null) return null;
return styleFactory.textSymbolizer(name,geom,desc,uom,label, font, placement, halo, fill);
}
//Sub elements -------------------------------------------------------------
public Map<Expression,List<Symbolizer>> visitRanges(final List<JAXBElement<RangeType>> types){
final Map<Expression,List<Symbolizer>> ranges = new LinkedHashMap<Expression, List<Symbolizer>>();
for(final JAXBElement<RangeType> type : types){
final RangeType rt = type.getValue();
final Expression exp = visitExpression(rt.getThreshold());
final List<Symbolizer> symbols = new ArrayList<Symbolizer>();
for(final JAXBElement<? extends SymbolizerType> jst : rt.getSymbolizer()){
final SymbolizerType st = jst.getValue();
if(st == null) continue;
symbols.add(visit(st));
}
ranges.put(exp, symbols);
}
return ranges;
}
/**
* Transform a SLD v1.1 legend in GT legend.
*/
public GraphicLegend visitLegend(final LegendGraphicType legendGraphic) {
if(legendGraphic == null || legendGraphic.getGraphic() == null){
return null;
}
final Graphic graphic = visit(legendGraphic.getGraphic());
if(graphic != null){
return styleFactory.graphicLegend(graphic);
}
return null;
}
/**
* Transform a SLD v1.1 graphic in GT graphic.
*/
public Graphic visit(final GraphicType graphic) {
if(graphic == null) return null;
final List<GraphicalSymbol> symbols = new ArrayList<GraphicalSymbol>();
for(final Object obj : graphic.getExternalGraphicOrMark()){
if(obj instanceof MarkType){
symbols.add( visit((MarkType)obj));
}else if(obj instanceof ExternalGraphicType){
symbols.add( visit((ExternalGraphicType)obj));
}
}
final Expression opacity = visitExpression(graphic.getOpacity());
final Expression size = visitExpression(graphic.getSize());
final Expression rotation = visitExpression(graphic.getRotation());
final AnchorPoint anchor = visit(graphic.getAnchorPoint());
final Displacement disp = visit(graphic.getDisplacement());
return styleFactory.graphic(symbols, opacity, size, rotation, anchor, disp);
}
/**
* Transform a SLD v1.1 stroke in GT stroke.
*/
public Stroke visit(final StrokeType strk) {
if(strk == null) return null;
final GraphicFill fill = visit(strk.getGraphicFill());
final GraphicStroke stroke = visit(strk.getGraphicStroke());
Expression color = Expression.NIL;
Expression opacity = Expression.NIL;
Expression width = Expression.NIL;
Expression join = Expression.NIL;
Expression cap = Expression.NIL;
float[] dashes = null;
Expression offset = Expression.NIL;
final List<SvgParameterType> params = strk.getSvgParameter();
for(final SvgParameterType svg : params){
if(SEJAXBStatics.STROKE.equalsIgnoreCase(svg.getName())){
color = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.STROKE_OPACITY.equalsIgnoreCase(svg.getName())){
opacity = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.STROKE_WIDTH.equalsIgnoreCase(svg.getName())){
width = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.STROKE_LINEJOIN.equalsIgnoreCase(svg.getName())){
join = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.STROKE_LINECAP.equalsIgnoreCase(svg.getName())){
cap = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.STROKE_DASHARRAY.equalsIgnoreCase(svg.getName())){
dashes = (float[])visitSVG(svg);
}else if(SEJAXBStatics.STROKE_DASHOFFSET.equalsIgnoreCase(svg.getName())){
offset = (Expression)visitSVG(svg);
}
}
if(fill != null){
return styleFactory.stroke(fill, color, opacity, width, join, cap, dashes, offset);
}else if(stroke != null){
return styleFactory.stroke(stroke, color, opacity, width, join, cap, dashes, offset);
}else{
return styleFactory.stroke(color, opacity, width, join, cap, dashes, offset);
}
}
/**
* Transform a SLD v1.1 fill in GT fill.
*/
public Fill visit(final FillType fl) {
if(fl == null) return null;
final GraphicFill fill = visit(fl.getGraphicFill());
Expression color = Expression.NIL;
Expression opacity = Expression.NIL;
final List<SvgParameterType> params = fl.getSvgParameter();
for(final SvgParameterType svg : params){
if(SEJAXBStatics.FILL.equalsIgnoreCase(svg.getName())){
color = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.FILL_OPACITY.equalsIgnoreCase(svg.getName())){
opacity = (Expression)visitSVG(svg);
}
}
return styleFactory.fill(fill, color, opacity);
}
/**
* Transform a SLD v1.1 displacement in GT displacement.
*/
public Displacement visit(final DisplacementType displacement) {
if(displacement == null) return null;
final Expression x = visitExpression(displacement.getDisplacementX());
final Expression y = visitExpression(displacement.getDisplacementY());
return styleFactory.displacement(x, y);
}
/**
* Transform a SLD v1.1 overlap in GT overlap.
*/
public OverlapBehavior visitOverLap(final String overlapBehavior) {
if(SEJAXBStatics.OVERLAP_AVERAGE.equalsIgnoreCase(overlapBehavior)){
return OverlapBehavior.AVERAGE;
}else if(SEJAXBStatics.OVERLAP_EARLIEST_ON_TOP.equalsIgnoreCase(overlapBehavior)){
return OverlapBehavior.EARLIEST_ON_TOP;
}else if(SEJAXBStatics.OVERLAP_LATEST_ON_TOP.equalsIgnoreCase(overlapBehavior)){
return OverlapBehavior.LATEST_ON_TOP;
}else if(SEJAXBStatics.OVERLAP_RANDOM.equalsIgnoreCase(overlapBehavior)){
return OverlapBehavior.RANDOM;
}else{
return OverlapBehavior.RANDOM;
}
}
/**
* Transform a SLD v1.1 channelselection in GT channel selection
*/
public ChannelSelection visit(final ChannelSelectionType channelSelection) {
if(channelSelection == null) return null;
if(channelSelection.getGrayChannel() != null){
final SelectedChannelType sct = visit(channelSelection.getGrayChannel());
return styleFactory.channelSelection(sct);
}else{
return styleFactory.channelSelection(
visit(channelSelection.getRedChannel()),
visit(channelSelection.getGreenChannel()),
visit(channelSelection.getBlueChannel()));
}
}
/**
* Transform a SLD v1.1 colormap in GT colormap.
*/
public ColorMap visit(final ColorMapType colorMap) {
if(colorMap == null) return null;
Function function = null;
if (colorMap.getCategorize() != null) {
function = visit(colorMap.getCategorize());
} else if(colorMap.getInterpolate() != null) {
function = visit(colorMap.getInterpolate());
} else if (colorMap.getJenks() != null) {
function = visit(colorMap.getJenks());
}
return styleFactory.colorMap(function);
}
/**
* Transform a SLD v1.1 contrastEnchancement in GT contrastEnchancement.
*/
public ContrastEnhancement visit(final ContrastEnhancementType contrastEnhancement) {
if(contrastEnhancement == null) return null;
final Expression gamma = filterFactory.literal(contrastEnhancement.getGammaValue());
ContrastMethod type = ContrastMethod.NONE;
if(contrastEnhancement.getHistogram() != null){
type = ContrastMethod.HISTOGRAM;
}else if(contrastEnhancement.getNormalize() != null){
type = ContrastMethod.NORMALIZE;
}
return styleFactory.contrastEnhancement(gamma,type);
}
/**
* Transform a SLD v1.1 outline in GT outline.
*/
public Symbolizer visit(final ImageOutlineType imageOutline) {
if(imageOutline == null) return null;
if(imageOutline.getLineSymbolizer() != null){
return visit(imageOutline.getLineSymbolizer());
}else if(imageOutline.getPolygonSymbolizer() != null){
return visit(imageOutline.getPolygonSymbolizer());
}
return null;
}
/**
* Transform a SLD v1.1 shadedRelief in GT shadedRelief.
*/
public ShadedRelief visit(final ShadedReliefType shadedRelief) {
if(shadedRelief == null) return null;
final boolean bright = shadedRelief.isBrightnessOnly();
final Expression relief = filterFactory.literal(shadedRelief.getReliefFactor());
return styleFactory.shadedRelief(relief,bright);
}
/**
* Transform a SLD v1.1 font in GT font.
*/
public Font visit(final FontType font) {
if(font == null) return null;
final List<Expression> family = new ArrayList<Expression>();
Expression style = Expression.NIL;
Expression weight = Expression.NIL;
Expression size = Expression.NIL;
final List<SvgParameterType> params = font.getSvgParameter();
for(final SvgParameterType svg : params){
if(SEJAXBStatics.FONT_FAMILY.equalsIgnoreCase(svg.getName())){
family.add( (Expression)visitSVG(svg) );
}else if(SEJAXBStatics.FONT_STYLE.equalsIgnoreCase(svg.getName())){
style = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.FONT_WEIGHT.equalsIgnoreCase(svg.getName())){
weight = (Expression)visitSVG(svg);
}else if(SEJAXBStatics.FONT_SIZE.equalsIgnoreCase(svg.getName())){
size = (Expression)visitSVG(svg);
}
}
return styleFactory.font(family, style, weight, size);
}
/**
* Transform a SLD v1.1 halo in GT halo.
*/
public Halo visit(final HaloType halo) {
if(halo == null) return null;
final Fill fill = visit(halo.getFill());
final Expression radius = visitExpression(halo.getRadius());
return styleFactory.halo(fill, radius);
}
/**
* Transform a SLD v1.1 label placement in GT label placement.
*/
public LabelPlacement visit(final LabelPlacementType labelPlacement) {
if(labelPlacement == null) return null;
if(labelPlacement.getLinePlacement() != null){
return visit(labelPlacement.getLinePlacement());
}else if(labelPlacement.getPointPlacement() != null){
return visit(labelPlacement.getPointPlacement());
}else{
return null;
}
}
/**
* Transform a SLD v1.1 anchor in GT anchor.
*/
public AnchorPoint visit(final AnchorPointType anchorPoint) {
if(anchorPoint == null) return null;
final Expression x = visitExpression(anchorPoint.getAnchorPointX());
final Expression y = visitExpression(anchorPoint.getAnchorPointY());
return styleFactory.anchorPoint(x, y);
}
public Mark visit(final MarkType markType) {
if(markType == null) return null;
final Expression wkn = filterFactory.literal(markType.getWellKnownName());
final ExternalMark external = null;
// ExternalMark = visit(markType.get)
final Fill fill = visit(markType.getFill());
final Stroke stroke = visit(markType.getStroke());
return styleFactory.mark(wkn, fill, stroke);
}
public ExternalGraphic visit(final ExternalGraphicType externalGraphicType) {
if(externalGraphicType == null) return null;
OnlineResource resource = null;
//check online resource
if(externalGraphicType.getOnlineResource()!=null){
resource = visitOnlineResource(externalGraphicType.getOnlineResource());
}
Icon icon = null;
//check inline content
if(externalGraphicType.getInlineContent() != null){
final InlineContentType ict = externalGraphicType.getInlineContent();
final List<Object> contents = ict.getContent();
for(Object obj : contents){
if(obj instanceof String){
try{
final byte[] b64 = Base64.decode((String)obj);
final ByteArrayInputStream is = new ByteArrayInputStream(b64);
final BufferedImage image = ImageIO.read(is);
icon = new ImageIcon(image);
}catch(IOException ex){
Logging.getLogger("org.geotoolkit.sld.xml").log(Level.WARNING, null, ex);
}
}
}
}
final String format = externalGraphicType.getFormat();
//rebuild color replacements
final Collection<ColorReplacement> replaces = new ArrayList<>();
for(final ColorReplacementType crt : externalGraphicType.getColorReplacement()){
final RecodeType rt = crt.getRecode();
if(rt != null){
for(final MapItemType mit : rt.getMapItem()){
final double d = mit.getData();
final Expression val = visitExpression(mit.getValue());
}
}
final RecolorType rc = crt.getRecolor();
if(rc != null){
List<ColorItem> items = new ArrayList<ColorItem>();
for(final ColorItemType mit : rc.getColorItem()){
final Literal data = (Literal) visitExpression(mit.getData());
final Literal value = (Literal) visitExpression(mit.getValue());
items.add(new ColorItem(data, value));
}
RecolorFunction recolor = new RecolorFunction(items,null);
replaces.add(new DefaultColorReplacement(recolor));
}
}
if (resource != null){
return styleFactory.externalGraphic(resource, format, replaces);
} else if (icon != null){
return styleFactory.externalGraphic(icon, replaces);
} else {
return null;
}
}
/**
* Transform a SLD v1.1 graphic fill in GT graphic fill.
*/
public GraphicFill visit(final GraphicFillType graphicFill) {
if(graphicFill == null || graphicFill.getGraphic() == null){
return null;
}
final Graphic graphic = visit(graphicFill.getGraphic());
if(graphic != null){
return styleFactory.graphicFill(graphic);
}
return null;
}
/**
* Transform a SLD v1.1 graphic stroke in GT graphic stroke.
*/
public GraphicStroke visit(final GraphicStrokeType graphicStroke) {
if(graphicStroke == null || graphicStroke.getGraphic() == null){
return null;
}
final Graphic graphic = visit(graphicStroke.getGraphic());
if(graphic != null){
final Expression gap = visitExpression(graphicStroke.getGap());
final Expression initialGap = visitExpression(graphicStroke.getInitialGap());
return styleFactory.graphicStroke(graphic,gap,initialGap);
}
return null;
}
/**
* Transform a SLD v1.1 selected channel in GT selected channel.
*/
public SelectedChannelType visit(final org.geotoolkit.se.xml.v110.SelectedChannelType channel) {
if(channel == null) return null;
final String name = channel.getSourceChannelName();
final ContrastEnhancement enchance = (channel.getContrastEnhancement() == null) ?
StyleConstants.DEFAULT_CONTRAST_ENHANCEMENT : visit(channel.getContrastEnhancement());
return styleFactory.selectedChannelType(name, enchance);
}
/**
* Transform a SLD v1.1 categorize function in GT categorize function.
*/
public Categorize visit(final CategorizeType categorize) {
if(categorize == null) return null;
final Literal fallback = filterFactory.literal(categorize.getFallbackValue());
final Expression lookup = visitExpression(categorize.getLookupValue());
final Expression value = visitExpression(categorize.getValue());
final ThreshholdsBelongTo belongs;
if(ThreshholdsBelongToType.PRECEDING.equals(categorize.getThreshholdsBelongTo()) ){
belongs = ThreshholdsBelongTo.PRECEDING;
}else {
belongs = ThreshholdsBelongTo.SUCCEEDING;
}
final Map<Expression,Expression> values = new HashMap<>();
values.put(StyleConstants.CATEGORIZE_LESS_INFINITY, value);
final List<JAXBElement<ParameterValueType>> elements = categorize.getThresholdAndTValue();
for(int i=0, n=elements.size(); i<n;){
final Expression key = visitExpression(elements.get(i).getValue());
final Expression val = visitExpression(elements.get(i+1).getValue());
values.put(key, val);
i+=2;
}
return styleFactory.categorizeFunction(lookup,values,belongs,fallback);
}
/**
* Transform a SLD v1.1 interpolate function in GT interpolate function.
*/
public Interpolate visit(final InterpolateType interpolate) {
if(interpolate == null) return null;
final Literal fallback = filterFactory.literal(interpolate.getFallbackValue());
final Expression lookup = visitExpression(interpolate.getLookupValue());
final Method method;
if(MethodType.COLOR.equals(interpolate.getMethod()) ){
method = Method.COLOR;
}else{
method = Method.NUMERIC;
}
final Mode mode;
if(ModeType.COSINE.equals(interpolate.getMode()) ){
mode = Mode.COSINE;
}else if(ModeType.CUBIC.equals(interpolate.getMode()) ){
mode = Mode.CUBIC;
}else {
mode = Mode.LINEAR;
}
final List<InterpolationPoint> values = new ArrayList<InterpolationPoint>();
for(final InterpolationPointType ip : interpolate.getInterpolationPoint()){
values.add(
styleFactory.interpolationPoint(
ip.getData(),
visitExpression(ip.getValue())
)
);
}
return styleFactory.interpolateFunction(lookup,values,method,mode,fallback);
}
/**
* Transform a SLD v1.1 jenks function in GT jenks function.
*/
public Jenks visit(final JenksType jenks) {
if(jenks == null) return null;
final Literal fallback = filterFactory.literal(jenks.getFallbackValue());
final Literal classNumber = filterFactory.literal(jenks.getClassNumber());
final Literal palette = filterFactory.literal(jenks.getPalette());
final double[] noData = jenks.getNoData();
final List<Literal> noDataLiteral = new ArrayList<Literal>();
if (noData != null) {
for (int i = 0; i < noData.length; i++) {
noDataLiteral.add(filterFactory.literal(noData[i]));
}
}
return styleFactory.jenksFunction(classNumber, palette, fallback, noDataLiteral);
}
/**
* Transform a SLD v1.1 lineplacement in GT line placement.
*/
public LinePlacement visit(final LinePlacementType linePlacement) {
if(linePlacement == null) return null;
final Expression offset = visitExpression(linePlacement.getPerpendicularOffset());
final Expression initial = visitExpression(linePlacement.getInitialGap());
final Expression gap = visitExpression(linePlacement.getGap());
Boolean repeated = linePlacement.isIsRepeated();
Boolean aligned = linePlacement.isIsAligned();
Boolean generalize = linePlacement.isGeneralizeLine();
if(repeated == null) repeated = Boolean.FALSE;
if(aligned == null) aligned = Boolean.FALSE;
if(generalize == null) generalize = Boolean.FALSE;
return styleFactory.linePlacement(offset, initial, gap, repeated, aligned, generalize);
}
/**
* Transform a SLD v1.1 pointplacement in GT point placement.
*/
public PointPlacement visit(final PointPlacementType pointPlacement) {
if(pointPlacement == null) return null;
final AnchorPoint anchor = visit(pointPlacement.getAnchorPoint());
final Displacement disp = visit(pointPlacement.getDisplacement());
final Expression rotation = visitExpression(pointPlacement.getRotation());
return styleFactory.pointPlacement(anchor, disp, rotation);
}
}