[Schmitzm-commits] r1706 - in trunk/schmitzm-gt/src/main/java: . de/schmitzm/geotools de/schmitzm/geotools/org de/schmitzm/geotools/org/geotools de/schmitzm/geotools/org/geotools/styling de/schmitzm/geotools/org/geotools/styling/visitor de/schmitzm/geotools/selection de/schmitzm/geotools/styling org org/geotools org/geotools/styling

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Sep 2 21:05:32 CEST 2011


Author: keeb
Date: 2011-09-02 21:05:30 +0200 (Fri, 02 Sep 2011)
New Revision: 1706

Added:
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/SLDTransformer.java
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/visitor/
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/visitor/DuplicatingStyleVisitor.java
   trunk/schmitzm-gt/src/main/java/org/
   trunk/schmitzm-gt/src/main/java/org/geotools/
   trunk/schmitzm-gt/src/main/java/org/geotools/styling/
   trunk/schmitzm-gt/src/main/java/org/geotools/styling/visitor/
Modified:
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/styling/StylingUtil.java
Log:
Replaced DuplicatingStyleVisitor and SLDTransformer with trunk-version of geotools to implement proper RGB-Band Contrastenhancement

Added: trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/SLDTransformer.java
===================================================================
--- trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/SLDTransformer.java	2011-09-02 16:41:28 UTC (rev 1705)
+++ trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/SLDTransformer.java	2011-09-02 19:05:30 UTC (rev 1706)
@@ -0,0 +1,1246 @@
+/*
+ * 	  Diese Klasse ist übergangsweise drin. 
+ * 	  Kopie aus 8.0 trunk um RGB RasterZeugs zu implementieren
+ *    2.9.2011
+ *    
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ * 
+ *    (C) 2003-2008, Open Source Geospatial Foundation (OSGeo)
+ *    
+ *    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 de.schmitzm.geotools.org.geotools.styling;
+
+import org.geotools.styling.*;
+import java.awt.Color;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.measure.quantity.Length;
+import javax.measure.unit.Unit;
+
+import org.geotools.data.DataStore;
+import org.geotools.data.FeatureSource;
+import org.geotools.factory.CommonFactoryFinder;
+import org.geotools.feature.FeatureCollection;
+import org.geotools.filter.FilterTransformer;
+import org.geotools.gml.producer.FeatureTransformer;
+import org.geotools.referencing.CRS;
+import org.geotools.xml.transform.TransformerBase;
+import org.geotools.xml.transform.Translator;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.filter.Filter;
+import org.opengis.filter.FilterFactory;
+import org.opengis.filter.FilterFactory2;
+import org.opengis.filter.expression.Expression;
+import org.opengis.filter.expression.Literal;
+import org.opengis.filter.expression.PropertyName;
+import org.opengis.referencing.ReferenceIdentifier;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.style.ContrastMethod;
+import org.opengis.style.SemanticType;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+
+/**
+ * Produces SLD to an output stream.
+ *
+ * @author Ian Schneider
+ *
+ * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/library/main/src/main/java/org/geotools/styling/SLDTransformer.java $
+ */
+public class SLDTransformer extends TransformerBase {
+    /** The logger for this package. */
+    private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geotools.styling");
+
+    static final String XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
+    
+    static final FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);
+
+    /**
+     * Additional namespace mappings to emit in the start element of the
+     * generated. Each entry has a URI key and an associated prefix string
+     * value.
+     */
+    final private Map uri2prefix;
+    
+    /**
+     * Construct a new instance of <code>SLDTransformer</code> with the
+     * default namespace mappings usually found in a simple Styled Layer
+     * Descriptor element.
+     */
+    public SLDTransformer() {
+        this(null);
+    }
+
+    /**
+     * Construct a new instance of <code>SLDTransformer</code> with the
+     * additional namespace mappings contained in <code>nsBindings</code>.
+     * <p>
+     * The designated collection contains mappings of {@link URI} to associated
+     * prefix (string) to emit in the generated XML element.
+     */
+    public SLDTransformer(Map nsBindings) {
+        super();
+        if (nsBindings == null || nsBindings.isEmpty()) {
+            uri2prefix = new HashMap();
+        } else {
+            uri2prefix = new HashMap(nsBindings.size());
+            int count = 0;
+            for (Iterator it = nsBindings.entrySet().iterator(); it.hasNext();) {
+                Map.Entry e = (Entry) it.next();
+                URI uri = (URI) e.getKey();
+                String prefix = (String) e.getValue();
+                if (uri != null && prefix != null) {
+                    uri2prefix.put(uri, prefix.trim());
+                    count++;
+                }
+            }
+            LOGGER.info("Added [" + count
+                    + "] namespace entries resulting in [" + uri2prefix.size()
+                    + "] distinct entries");
+        }
+    }
+
+    public Translator createTranslator(ContentHandler handler) {
+        Translator result = new SLDTranslator(handler);
+        // add pre-configured namespace mappings
+        if (!uri2prefix.isEmpty()) {
+            for (Iterator it = uri2prefix.entrySet().iterator(); it.hasNext();) {
+                Map.Entry e = (Entry) it.next();
+                URI uri = (URI) e.getKey();
+                if (uri != null) {
+                    String prefix = (String) e.getValue();
+                    // FIXME handle default namespace and possible clash with
+                    // one already known to the namespace-support delegate; i.e.
+                    // the entry with an empty prefix
+                    String uriStr = String.valueOf(uri);
+                    result.getNamespaceSupport().declarePrefix(prefix, uriStr);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Currently does nothing.
+     * 
+     * @param args
+     *            DOCUMENT ME!
+     * 
+     * @throws Exception
+     *             DOCUMENT ME!
+     */
+    public static final void main(String[] args) throws Exception {
+        java.net.URL url = new java.io.File(args[0]).toURI().toURL();
+        SLDParser s = new SLDParser( CommonFactoryFinder.getStyleFactory( null), url);
+        SLDTransformer transformer = new SLDTransformer();
+        transformer.setIndentation(4);
+        transformer.transform(s.readXML(),
+            new FileOutputStream(System.getProperty("java.io.tmpdir")
+                + "/junk.eraseme"));
+    }
+    /**
+     * Translates the Style data structure into a series of XML events
+     * that can be encoded etc...
+     * <p>
+     * This Translator makes use of the following (currently hardcoded) information:
+     * <ul>
+     * <li>prefix: sld
+     * <li>namespace: http://www.opengis.net/sld
+     * </ul>
+     * @author Jody
+     */
+    static class SLDTranslator extends TranslatorSupport implements StyleVisitor {
+        /**
+         * Handles any Filters used in our data structure.
+         */
+        FilterTransformer.FilterTranslator filterTranslator;
+
+        /**
+         * Translates into the default of prefix "sld" for "http://www.opengis.net/sld".
+         * 
+         * @param handler
+         */
+        public SLDTranslator(ContentHandler handler) {
+            this( handler, "sld", "http://www.opengis.net/sld");
+        }
+
+        /**
+         * Translates
+         * @param handler
+         */
+        public SLDTranslator(ContentHandler handler, String prefix, String uri ) {
+            super(handler, prefix, uri );
+            filterTranslator = new FilterTransformer.FilterTranslator(handler);
+            addNamespaceDeclarations(filterTranslator);
+        }
+        
+        boolean isNull( Expression expr ){
+            if( expr == null ) return true;
+            if( expr == Expression.NIL ) return true;
+            if( expr instanceof Literal ){
+                Literal literal = (Literal) expr;
+                return literal.getValue() == null;
+            }
+            return false; // must be some other non null thing
+        }
+            
+        boolean isDefault( Expression expr, Object defaultValue ){
+            if( defaultValue == null ) return isNull( expr );
+            
+            if( expr == null ) return false;
+            if( expr == Expression.NIL ) return false;
+            if( expr instanceof Literal ){
+                Literal literal = (Literal) expr;
+                if( defaultValue.equals( literal.getValue() )){
+                    return true;
+                }
+                if( defaultValue.toString().equals( literal.getValue().toString() ) ){
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        /**
+         * Utility method used to quickly package up the provided expression.
+         * @param element
+         * @param expr
+         */
+        void element(String element, Expression expr) {
+            element(element, expr, null);
+        }
+
+        /**
+         * Utility method used to quickly package up the provided expression.
+         * @param element
+         * @param expr
+         */
+        void element(String element, Expression expr, Object defaultValue) {
+            element(element, expr, defaultValue, null);
+        }
+        
+        void element(String element, Expression expr, Object defaultValue, AttributesImpl atts) {
+            if( expr == null || expr == Expression.NIL ) return;
+            
+            // skip encoding if we are using the default value
+            if (expr instanceof Literal) {
+                if(defaultValue != null) {
+                    Object value = expr.evaluate(null, defaultValue.getClass());
+                    if(value != null && !value.equals(defaultValue)) {
+                        element(element, value.toString(), atts);
+                    } 
+                } else {
+                    String value = expr.evaluate(null, String.class);
+                    if(value != null) {
+                        element(element, value, atts);
+                    }
+                }
+                return;
+            }
+            
+            start(element, atts);
+            filterTranslator.encode(expr);
+            end(element);
+        }
+        
+        /**
+         * To be used when the expression is a single literal whose 
+         * value must be written out as element.
+         * <p>
+         * For Example OverlapBehaviour is represented as an expression but v 1.0.0
+         * specifications do not define it as an expression.  (&ltAVERAGE/&gt)
+         * </p>
+         * 
+         */
+        void elementLiteral(String element, Expression e, String defaultValue){
+        	if (e == null || e == Expression.NIL) return;
+        	
+        	final String value = e.evaluate(null, String.class);
+        	if(defaultValue == null || !defaultValue.equals(value)) {
+            	start(element);
+            	start(value);
+            	end(value);
+            	end(element);
+        	}
+        }
+
+        public void visit(PointPlacement pp) {
+            start("LabelPlacement");
+            start("PointPlacement");
+            pp.getAnchorPoint().accept(this);
+            
+            visit( pp.getDisplacement() );
+
+            encodeValue("Rotation", null, pp.getRotation(), Double.valueOf(0.0));
+            end("PointPlacement");
+            end("LabelPlacement");
+        }
+
+        public void visit(Stroke stroke) {
+            start("Stroke");
+
+            if (stroke.getGraphicFill() != null) {
+            	start("GraphicFill");
+                stroke.getGraphicFill().accept(this);
+                end("GraphicFill");
+            }
+
+            if (stroke.getGraphicStroke() != null) {
+            	start("GraphicStroke");
+                stroke.getGraphicStroke().accept(this);
+                end("GraphicStroke");
+            }
+
+            encodeCssParam("stroke", stroke.getColor(), Color.BLACK);
+            encodeCssParam("stroke-linecap", stroke.getLineCap(), "butt");
+            encodeCssParam("stroke-linejoin", stroke.getLineJoin(), "miter");
+            encodeCssParam("stroke-opacity", stroke.getOpacity(), 1.0);
+            encodeCssParam("stroke-width", stroke.getWidth(), 1.0);
+            encodeCssParam("stroke-dashoffset", stroke.getDashOffset(), 0.0);
+
+            float[] dash = stroke.getDashArray();
+
+            if (dash != null) {
+                StringBuffer sb = new StringBuffer();
+    
+                for (int i = 0; i < dash.length; i++) {
+                    sb.append(dash[i]);
+                    if(i < dash.length - 1) {
+                        sb.append(" ");
+                    }
+                }
+    
+                encodeCssParam("stroke-dasharray", ff.literal(sb.toString()));
+    
+            }
+            end("Stroke");
+        }
+
+        public void visit(LinePlacement lp) {
+            start("LabelPlacement");
+            start("LinePlacement");
+            element("PerpendicularOffset", lp.getPerpendicularOffset());
+            end("LinePlacement");
+            end("LabelPlacement");
+        }
+
+        public void visit(AnchorPoint ap) {
+            start("AnchorPoint");
+            element("AnchorPointX", ap.getAnchorPointX());
+            element("AnchorPointY", ap.getAnchorPointY());
+            end("AnchorPoint");
+        }
+
+        public void visit(TextSymbolizer text) {
+            if (text == null) {
+                return;
+            }
+
+            // adds the uom attribute according to the OGC SE specification
+            AttributesImpl atts = new AttributesImpl();
+        	Unit<Length> uom = text.getUnitOfMeasure();
+			if(uom != null)
+				atts.addAttribute("", "uom", "uom", "", UomOgcMapping.get(uom).getSEString());
+
+            start("TextSymbolizer", atts);
+
+            encodeGeometryExpression(text.getGeometry());
+
+            if (text.getLabel() != null) {
+                element("Label", text.getLabel());
+            }
+
+            if ((text.getFonts() != null) && (text.getFonts().length != 0)) {
+                start("Font");
+
+                Font[] fonts = text.getFonts();
+
+                for (int i = 0; i < fonts.length; i++) {
+                    encodeCssParam("font-family", fonts[i].getFontFamily());
+                }
+
+                encodeCssParam("font-size", fonts[0].getFontSize());
+                encodeCssParam("font-style", fonts[0].getFontStyle());
+                encodeCssParam("font-weight", fonts[0].getFontWeight());
+                end("Font");
+            }
+
+            if (text.getPlacement() != null) {
+                text.getPlacement().accept(this);
+            }
+
+            if (text.getHalo() != null) {
+                text.getHalo().accept(this);
+            }
+
+            if (text.getFill() != null) {
+                text.getFill().accept(this);
+            }
+
+            if (text instanceof TextSymbolizer2){
+            	TextSymbolizer2 text2 = (TextSymbolizer2) text;
+            	if (text2.getGraphic() != null) visit(text2.getGraphic());
+            	if (text2.getSnippet() != null) element("Snippet", text2.getSnippet());
+            	if (text2.getFeatureDescription() != null) element("FeatureDescription", text2.getFeatureDescription());
+            	OtherText otherText = text2.getOtherText();
+				if (otherText != null) {
+            	    AttributesImpl otherTextAtts = new AttributesImpl();
+            	    otherTextAtts.addAttribute("", "target", "target", "", otherText.getTarget());
+					element("OtherText",otherText.getText(), null, otherTextAtts);
+            	}
+            }
+            
+            if (text.getPriority() != null) {
+                element("Priority", text.getPriority());
+            }
+            
+            if (text.getOptions() != null) {
+                encodeVendorOptions(text.getOptions());
+            }
+            
+            end("TextSymbolizer");
+        }
+
+		public void visit(RasterSymbolizer raster) {
+			if (raster == null) {
+				return;
+			}
+
+			// adds the uom attribute according to the OGC SE specification
+            AttributesImpl atts = new AttributesImpl();
+        	Unit<Length> uom = raster.getUnitOfMeasure();
+			if(uom != null)
+				atts.addAttribute("", "uom", "uom", "", UomOgcMapping.get(uom).getSEString());
+
+			start("RasterSymbolizer", atts);
+
+			encodeGeometryExpression(raster.getGeometry());
+
+			element("Opacity", raster.getOpacity(), 1.0);
+
+			if (raster.getChannelSelection() != null) {
+				final ChannelSelection cs = raster.getChannelSelection();				
+				if (cs.getGrayChannel() != null) {
+				    start("ChannelSelection");
+				    SelectedChannelType gray = cs.getGrayChannel();
+				    
+				    start("GrayChannel");
+				    gray.accept(this);
+					end("GrayChannel");
+                    
+					end("ChannelSelection");                    					
+				} else if( cs.getRGBChannels() != null && cs.getRGBChannels().length ==3 && cs.getRGBChannels()[0] != null && cs.getRGBChannels()[1] != null && cs.getRGBChannels()[2] != null){				    
+				    start("ChannelSelection");
+	                SelectedChannelType[] rgb = cs.getRGBChannels();
+				    
+				    start("RedChannel");
+	                rgb[0].accept(this);
+					end("RedChannel");
+
+					start("GreenChannel");
+					rgb[1].accept(this);
+					end("GreenChannel");
+
+					start("BlueChannel");
+					rgb[2].accept(this);
+					end("BlueChannel");
+
+					end("ChannelSelection");					
+				}
+				else {
+				    // we have an invalid ChannelSelection ?
+				}
+			}
+			
+			if (raster.getOverlap() != null) {
+				Expression overlaps = raster.getOverlap();
+				if( overlaps instanceof PropertyName){
+				    final String pn = ((PropertyName)overlaps).getPropertyName();
+				    if("RANDOM".equals(pn)) {
+    	                start("OverlapBehavior");				    
+    	                start(pn);
+    	                end(pn);
+    	                end("OverlapBehavior");
+				    }
+				} else {
+					//this expression needs to be converted to a single string and then written
+					//1.0.0 specs don't allow it to be written as an expression
+					elementLiteral("OverlapBehavior",overlaps, "RANDOM");
+				}
+			}
+
+			ColorMap colorMap = raster.getColorMap();
+            if (colorMap != null && colorMap.getColorMapEntries() != null && colorMap.getColorMapEntries().length > 0) {
+				colorMap.accept(this);
+			}
+			
+			if (raster.getContrastEnhancement() != null){
+				raster.getContrastEnhancement().accept(this);
+			}
+			
+			if (raster.getShadedRelief() != null) {
+				raster.getShadedRelief().accept(this);
+			}
+			
+			if (raster.getImageOutline() != null) {
+				start("ImageOutline");
+				raster.getImageOutline().accept(this);
+				end("ImageOutline");
+			}
+
+			end("RasterSymbolizer");
+		}
+
+         public void visit(ColorMap colorMap) {
+                // The type of the ColorMap is stored in an attribute "type" and may store
+                // string-values: "ramp", "intervals" or "values".
+                AttributesImpl atts = new AttributesImpl();
+                String typeString;
+                if (colorMap.getType() == ColorMap.TYPE_INTERVALS)
+                	typeString = "intervals";
+                else if (colorMap.getType() == ColorMap.TYPE_VALUES)
+                	typeString = "values";
+                else
+                	typeString = "ramp"; // Also the default in the parser
+                if(!"ramp".equals(typeString)) {
+                    atts.addAttribute("", "type", "type", "", typeString);
+                }
+                
+                if(colorMap.getExtendedColors()) {
+                    atts.addAttribute("", "extended", "extended", "", typeString);
+                }
+
+                start("ColorMap", atts);
+                ColorMapEntry[] mapEntries = colorMap.getColorMapEntries();
+                for (int i = 0; i < mapEntries.length; i++) {
+                	mapEntries[i].accept(this);
+                }
+                end("ColorMap");
+        }
+
+        public void visit(ColorMapEntry colorEntry) {
+        	if (colorEntry != null) {
+                AttributesImpl atts = new AttributesImpl();
+                atts.addAttribute("", "color", "color", "",colorEntry.getColor().evaluate(null, String.class));
+                if (colorEntry.getOpacity() != null) {
+                	atts.addAttribute("", "opacity", "opacity", "", colorEntry.getOpacity().toString());
+                }
+        		if (colorEntry.getQuantity() != null) {
+        			atts.addAttribute("", "quantity", "quantity", "", colorEntry.getQuantity().toString());
+        		}
+        		if (colorEntry.getLabel() != null) {
+        			atts.addAttribute("", "label", "label", "", colorEntry.getLabel());
+        		}
+                element("ColorMapEntry", (String) null, atts);
+        	}
+        }
+        
+        public void visit(Symbolizer sym) {
+            try {
+                contentHandler.startElement("", "!--", "!--", NULL_ATTS);
+                chars("Unidentified Symbolizer " + sym.getClass());
+                contentHandler.endElement("", "--", "--");
+            } catch (SAXException se) {
+                throw new RuntimeException(se);
+            }
+        }
+
+        public void visit(PolygonSymbolizer poly) {
+        	
+        	// adds the uom attribute according to the OGC SE specification
+            AttributesImpl atts = new AttributesImpl();
+        	Unit<Length> uom = poly.getUnitOfMeasure();
+			if(uom != null)
+				atts.addAttribute("", "uom", "uom", "", UomOgcMapping.get(uom).getSEString());
+
+            start("PolygonSymbolizer", atts);
+            encodeGeometryExpression(poly.getGeometry());
+
+            if (poly.getFill() != null) {
+                poly.getFill().accept(this);
+            }
+
+            if (poly.getStroke() != null) {
+                poly.getStroke().accept(this);
+            }
+
+            end("PolygonSymbolizer");
+        }
+
+        public void visit(ExternalGraphic exgr) {
+            start("ExternalGraphic");
+
+            AttributesImpl atts = new AttributesImpl();
+        	atts.addAttribute(XMLNS_NAMESPACE, "xlink", "xmlns:xlink", "", XLINK_NAMESPACE);
+            atts.addAttribute(XLINK_NAMESPACE, "type", "xlink:type", "", "simple");
+            atts.addAttribute(XLINK_NAMESPACE, "xlink", "xlink:href","", exgr.getOnlineResource().getLinkage().toString());
+            element("OnlineResource", (String) null, atts);
+
+            element("Format", exgr.getFormat());
+
+            end("ExternalGraphic");
+        }
+
+        public void visit(LineSymbolizer line) {
+
+        	// adds the uom attribute according to the OGC SE specification
+            AttributesImpl atts = new AttributesImpl();
+        	Unit<Length> uom = line.getUnitOfMeasure();
+			if(uom != null)
+				atts.addAttribute("", "uom", "uom", "", UomOgcMapping.get(uom).getSEString());
+
+        	start("LineSymbolizer", atts);
+            encodeGeometryExpression(line.getGeometry());
+
+            if( line.getStroke() != null ){
+                line.getStroke().accept(this);
+            }
+            end("LineSymbolizer");
+        }
+
+        public void visit(Fill fill) {
+            start("Fill");
+
+            if (fill.getGraphicFill() != null) {
+            	start("GraphicFill");
+                fill.getGraphicFill().accept(this);
+                end("GraphicFill");
+            }
+
+            encodeCssParam("fill", fill.getColor(), "#808080");
+            encodeCssParam("fill-opacity", fill.getOpacity(), 1.0);
+            end("Fill");
+        }
+
+        public void visit(Rule rule) {
+            start("Rule");
+            if (rule.getName() != null) element("Name", rule.getName());
+            if (rule.getTitle() != null) element("Title", rule.getTitle());
+            if (rule.getAbstract() != null) element("Abstract", rule.getAbstract());
+
+            Graphic[] gr = rule.getLegendGraphic();
+            for (int i = 0; i < gr.length; i++) {
+                start("LegendGraphic");
+            	gr[i].accept(this);
+                end("LegendGraphic");
+            }
+            
+            Filter filter = rule.getFilter();
+            if( filter == null || filter == Filter.INCLUDE ){
+                // no filter
+            } else {
+                visit(filter);
+            }
+
+            if (rule.isElseFilter()) {
+                start("ElseFilter");
+                end("ElseFilter");
+            }
+
+            if (rule.getMinScaleDenominator() != 0.0) {
+                element("MinScaleDenominator",
+                    rule.getMinScaleDenominator() + "");
+            }
+
+            if (rule.getMaxScaleDenominator() != Double.POSITIVE_INFINITY) {
+                element("MaxScaleDenominator",
+                    rule.getMaxScaleDenominator() + "");
+            }
+
+            Symbolizer[] sym = rule.getSymbolizers();
+            for (int i = 0; i < sym.length; i++) {
+                sym[i].accept(this);
+            }
+
+            end("Rule");
+        }
+
+        public void visit(Mark mark) {
+            start("Mark");
+            if (mark.getWellKnownName() != null && !"square".equals(mark.getWellKnownName().evaluate(null))) {
+            	element("WellKnownName", mark.getWellKnownName().toString());
+            }
+
+            if (mark.getFill() != null) {
+                mark.getFill().accept(this);
+            }
+
+            if (mark.getStroke() != null) {
+                mark.getStroke().accept(this);
+            }
+
+            end("Mark");
+        }
+
+        public void visit(PointSymbolizer ps) {
+
+            // adds the uom attribute according to the OGC SE specification
+            AttributesImpl atts = new AttributesImpl();
+        	Unit<Length> uom = ps.getUnitOfMeasure();
+			if(uom != null)
+				atts.addAttribute("", "uom", "uom", "", UomOgcMapping.get(uom).getSEString());
+
+            start("PointSymbolizer", atts);
+
+            encodeGeometryExpression(ps.getGeometry());
+
+            ps.getGraphic().accept(this);
+            
+            end("PointSymbolizer");
+        }
+
+        public void visit(Halo halo) {
+        	start("Halo");
+        	if (halo.getRadius() != null) {
+	            encodeValue("Radius", null, halo.getRadius(), null);
+        	}
+            if (halo.getFill() != null) {
+            	halo.getFill().accept(this);
+            }
+            end("Halo");
+        }
+
+        public void visit(Graphic gr) {
+            start("Graphic");
+
+            //encodeGeometryProperty(gr.getGeometryPropertyName());
+
+            Symbol[] symbols = gr.getSymbols();
+
+            for (int i = 0; i < symbols.length; i++) {
+                symbols[i].accept(this);
+            }
+
+            element("Opacity", gr.getOpacity(), 1.0);
+            element("Size", gr.getSize());
+            element("Rotation", gr.getRotation(), 0.0);
+            visit(gr.getDisplacement());
+
+            end("Graphic");
+        }
+        
+        public void visit(StyledLayerDescriptor sld) {
+            AttributesImpl atts = new AttributesImpl();
+            atts.addAttribute("", "version", "version", "", "1.0.0");
+        	start("StyledLayerDescriptor", atts);
+
+        	if ((sld.getName() != null) && (sld.getName().length() > 0)) {
+        		element("Name", sld.getName()); //optional
+        	}
+        	if ((sld.getTitle() != null) && (sld.getTitle().length() > 0)) {
+        		element("Title", sld.getTitle()); //optional
+        	}
+        	if ((sld.getAbstract() != null) && (sld.getAbstract().length() > 0)) {
+        		element("Abstract", sld.getAbstract()); //optional
+        	}
+
+        	StyledLayer[] layers = sld.getStyledLayers();
+            
+            for (int i = 0; i < layers.length; i++) {
+                if (layers[i] instanceof NamedLayer) {
+                    visit((NamedLayer) layers[i]);
+                } else if (layers[i] instanceof UserLayer) {
+                    visit((UserLayer) layers[i]);
+                } else {
+                    throw new IllegalArgumentException("StyledLayer '"
+                        + layers[i].getClass().toString() + "' not found");
+                }
+            }
+
+            end("StyledLayerDescriptor");
+        }
+
+        public void visit(NamedLayer layer) {
+            start("NamedLayer");
+            element("Name", layer.getName());
+
+            FeatureTypeConstraint[] lfc = layer.getLayerFeatureConstraints();
+            if ((lfc != null) && lfc.length > 0) {
+            	start("LayerFeatureConstraints"); //optional
+	            for (int i = 0; i < lfc.length; i++) {
+	                visit(lfc[i]);
+	            }
+	        	end("LayerFeatureConstraints");
+            }
+            
+            Style[] styles = layer.getStyles();
+
+            for (int i = 0; i < styles.length; i++) {
+                visit(styles[i]);
+            }
+
+            end("NamedLayer");
+        }
+
+        public void visit(UserLayer layer) {
+            start("UserLayer");
+
+            if ((layer.getName() != null) && (layer.getName().length() > 0)) {
+                element("Name", layer.getName()); //optional
+            }
+
+            DataStore inlineFDS = layer.getInlineFeatureDatastore();
+            if (inlineFDS != null) {
+                visitInlineFeatureType(inlineFDS, layer.getInlineFeatureType());
+            } else if (layer.getRemoteOWS() != null) {
+                visit(layer.getRemoteOWS());
+            }
+
+        	start("LayerFeatureConstraints"); //required
+            FeatureTypeConstraint[] lfc = layer.getLayerFeatureConstraints();
+            if ((lfc != null) && lfc.length > 0) {
+            	for (int i = 0; i < lfc.length; i++) {
+            		visit(lfc[i]);
+            	}
+            } else { //create an empty FeatureTypeConstraint, since it is required
+            	start("FeatureTypeConstraint");
+            	end("FeatureTypeConstraint");
+            }
+        	end("LayerFeatureConstraints");
+
+            Style[] styles = layer.getUserStyles();
+
+            for (int i = 0; i < styles.length; i++) {
+                visit(styles[i]);
+            }
+
+            end("UserLayer");
+        }
+
+        private void visitInlineFeatureType(DataStore dataStore, SimpleFeatureType featureType) {
+            start("InlineFeature");
+            try {
+                final String ftName = featureType.getTypeName();
+                final FeatureSource<SimpleFeatureType, SimpleFeature> fs = dataStore.getFeatureSource(ftName);
+                final FeatureCollection<SimpleFeatureType, SimpleFeature> fc = fs.getFeatures();
+                final FeatureTransformer ftrax = new FeatureTransformer();
+                ftrax.setCollectionNamespace(null);
+                ftrax.setCollectionPrefix(null);
+                ftrax.setGmlPrefixing(true);
+                ftrax.setIndentation(2);
+                final CoordinateReferenceSystem crs = featureType.getGeometryDescriptor()
+                        .getCoordinateReferenceSystem();
+                String srsName = null;
+                if (crs == null) {
+                    LOGGER.warning("Null CRS in feature type named [" + ftName + "]. Ignore CRS");
+                } else {
+                    srsName = null; // single implementation of toSRS
+                    if (srsName == null) {
+                        // fallback on origional code
+                        // assume the first named identifier of this CRS is its
+                        // fully
+                        // qualified code; e.g. authoriy and SRID
+                        Set<ReferenceIdentifier> ids = crs.getIdentifiers();
+                        if (ids == null || ids.isEmpty()) {
+                            LOGGER.warning("Null or empty set of named identifiers " + "in CRS ["
+                                    + crs + "] of feature type named [" + ftName + "]. Ignore CRS");
+                        } else {
+                            for (ReferenceIdentifier id : ids) {
+                                if (id != null) {
+                                    srsName = String.valueOf(id);
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    if (srsName != null) {
+                        // Some Server implementations using older versions of this
+                        // library barf on a fully qualified CRS name with messages
+                        // like : "couldnt decode SRS - EPSG:EPSG:4326. currently
+                        // only supporting EPSG #"; looks like they only needs the
+                        // SRID. adjust
+                        final int ndx = srsName.indexOf(':');
+                        if (ndx > 0) {
+                            LOGGER.info("Reducing CRS name [" + srsName + "] to its SRID");
+                            srsName = srsName.substring(ndx + 1).trim();
+                        }
+                    }
+                }
+                if (srsName != null) {
+                    ftrax.setSrsName(srsName);
+                }
+                
+                final String defaultNS = this.getDefaultNamespace();
+                ftrax.getFeatureTypeNamespaces().declareDefaultNamespace("", defaultNS);
+                final String ns = featureType.getName().getNamespaceURI();
+                if (ns == null) {
+                    LOGGER.info("Null namespace URI in feature type named [" + ftName
+                            + "]. Ignore namespace in features");
+                } else {
+                    // find the URI's prefix mapping in this namespace support
+                    // delegate and use it; otherwise ignore it
+                    final String prefix = this.nsSupport.getPrefix(ns);
+                    if (prefix != null)
+                        ftrax.getFeatureTypeNamespaces().declareNamespace(featureType, prefix, ns);
+                }
+                final Translator t = ftrax
+                        .createTranslator(this.contentHandler);
+                t.encode(fc);
+            } catch (IOException ignored) {
+            }
+            end("InlineFeature");
+        }
+        
+        public void visit(RemoteOWS remoteOWS) {
+            start("RemoteOWS");
+            element("Service", remoteOWS.getService());
+            element("OnlineResource", remoteOWS.getOnlineResource());
+            end("RemoteOWS");
+        }
+
+        public void visit(FeatureTypeConstraint ftc) {
+            start("FeatureTypeConstraint");
+
+            if (ftc != null) {
+                element("FeatureTypeName", ftc.getFeatureTypeName());
+                visit(ftc.getFilter());
+
+                Extent[] extent = ftc.getExtents();
+
+                for (int i = 0; i < extent.length; i++) {
+                    visit(extent[i]);
+                }
+            }
+
+            end("FeatureTypeConstraint");
+        }
+
+        public void visit(Extent extent) {
+            start("Extent");
+            element("Name", extent.getName());
+            element("Value", extent.getValue());
+            end("Extent");
+        }
+
+		public void visit(Filter filter) {
+		    try {
+                contentHandler.startElement("", "", "ogc:Filter", NULL_ATTS);
+                filterTranslator.encode(filter);
+                contentHandler.endElement("","","ogc:Filter");
+            } catch (SAXException se) {
+                throw new RuntimeException(se);
+            }
+		}
+
+        public void visit(Style style) {
+            if (style instanceof NamedStyle) {
+                start("NamedStyle");
+                element("Name", style.getName());
+                end("NamedStyle");
+            } else {
+                start("UserStyle");
+                element("Name", style.getName());
+                element("Title", style.getTitle());
+                if(style.isDefault()) {
+                    element("IsDefault", "1");
+                }
+                elementSafe("Abstract", style.getAbstract());
+                FeatureTypeStyle[] fts = style.getFeatureTypeStyles();
+                for (int i = 0; i < fts.length; i++) {
+                    visit(fts[i]);
+                }
+                end("UserStyle");
+            }        
+        }
+
+        public void visit(FeatureTypeStyle fts) {
+            start("FeatureTypeStyle");
+
+            if ((fts.getName() != null) && (fts.getName().length() > 0)) {
+                element("Name", fts.getName());
+            }
+
+            if ((fts.getTitle() != null) && (fts.getTitle().length() > 0)) {
+                element("Title", fts.getTitle());
+            }
+
+            if ((fts.getAbstract() != null) && (fts.getAbstract().length() > 0)) {
+                element("Abstract", fts.getAbstract());
+            }
+
+            if ((fts.featureTypeNames() != null) && (fts.featureTypeNames().size() > 0)) {
+                element("FeatureTypeName", fts.featureTypeNames().iterator().next().toString());
+            }
+
+            String[] sti = fts.getSemanticTypeIdentifiers();
+
+            if(sti.length == 1 && sti[0].equals(SemanticType.ANY.toString())) {
+                // skip, it's the default
+            } else {
+                for (int i = 0; i < sti.length; i++) {
+                    element("SemanticTypeIdentifier", sti[i]);
+                }
+            }
+            
+
+            Rule[] rules = fts.getRules();
+
+            for (int i = 0; i < rules.length; i++) {
+                rules[i].accept(this);
+            }
+
+            end("FeatureTypeStyle");
+        }
+
+        public void visit(Displacement dis) {
+            if (dis == null){
+                return;
+            }
+
+            // We don't want to get huge SLDs with default values. So if displacement = 0 and 0 we
+            // drop it.
+            Expression dx = dis.getDisplacementX();
+            Expression dy = dis.getDisplacementY();
+            if( isNull(dx) && isNull(dy)){
+                return;
+            }
+            if( isDefault(dx,0) && isDefault(dy,0)){
+                return;
+            }
+
+            start("Displacement");
+            element("DisplacementX", dis.getDisplacementX());
+            element("DisplacementY", dis.getDisplacementY());
+            end("Displacement");
+        }
+
+        void encodeGeometryProperty(String name) {
+            if ((name == null) || (name.trim().length() == 0)) {
+                return;
+            }
+            //create a property name out the name and encode it
+            FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
+            Expression expression = ff.property(name);
+            
+            start("Geometry");
+            filterTranslator.encode(expression);
+            end("Geometry");
+            
+        }
+        
+        void encodeGeometryExpression(Expression geom) {
+            if ((geom == null)) {
+                return;
+            }
+            
+            start("Geometry");
+            filterTranslator.encode(geom);
+            end("Geometry");
+            
+        }
+        
+        void encodeCssParam(String name, Expression expression) {
+            encodeCssParam(name, expression, null);
+        }
+
+        void encodeCssParam(String name, Expression expression, Object defaultValue) {
+            if (expression == null) {
+                return; // protect ourselves from things like a null Stroke Color
+            }
+
+            AttributesImpl atts = new AttributesImpl();
+            atts.addAttribute("", "name", "name", "", name);
+            encodeValue("CssParameter", atts, expression, defaultValue);
+        }
+        
+        void encodeValue(String elementName, Attributes atts, Expression expression, Object defaultValue) {
+            if (expression == null) {
+                return; // protect ourselves from things like a null Stroke Color
+            }
+            
+            // skip encoding if we are using the default value
+            if (expression instanceof Literal && defaultValue != null) {
+                Object value = expression.evaluate(null, defaultValue.getClass());
+                if(value != null && value.equals(defaultValue)) {
+                    return;
+                }
+            }
+
+            if(atts == null) {
+                atts = NULL_ATTS;
+            }
+            if(expression instanceof Literal) {
+                // use more compact encoding
+                element(elementName, expression.evaluate(null, String.class), atts);
+            } else {
+                start(elementName, atts);
+                filterTranslator.encode(expression);
+                end(elementName);
+            }
+        }
+
+        void encodeVendorOptions(Map options) {
+            if (options != null) {
+                Iterator it = options.keySet().iterator();
+                while (it.hasNext()) {
+                    String key = (String) it.next();
+                    String value = (String) options.get(key);
+                    encodeVendorOption(key, value);
+                }
+            }
+        }
+        
+        void encodeVendorOption(String key, String value) {
+            AttributesImpl atts = new AttributesImpl();
+            atts.addAttribute("", "name", "name", "", key);
+            start("VendorOption", atts);
+            chars(value);
+            end("VendorOption");
+        }
+        
+        public void encode(Style[] styles) {
+            try {
+                contentHandler.startDocument();
+
+                start("StyledLayerDescriptor", NULL_ATTS);
+                start("NamedLayer", NULL_ATTS); //this is correct?
+                
+                for (int i = 0, ii = styles.length; i < ii; i++) {
+                    styles[i].accept(this);
+                }
+
+                end("NamedLayer");
+                end("StyledLayerDescriptor");
+
+                contentHandler.endDocument();
+            } catch (SAXException se) {
+                throw new RuntimeException(se);
+            }
+        }
+
+        public void encode(StyledLayerDescriptor sld) {
+            try {
+                contentHandler.startDocument();
+                sld.accept(this);
+                contentHandler.endDocument();
+            } catch (SAXException se) {
+                throw new RuntimeException(se);
+            }
+        }
+
+        public void encode(Object o) throws IllegalArgumentException {
+            if (o instanceof StyledLayerDescriptor) {
+                encode((StyledLayerDescriptor) o);
+            } else if (o instanceof Style[]) {
+                encode((Style[]) o);
+            } else {
+                Class c = o.getClass();
+
+                try {
+                    java.lang.reflect.Method m = c.getMethod("accept",
+                            new Class[] { StyleVisitor.class });
+                    m.invoke(o, new Object[] { this });
+                } catch (NoSuchMethodException nsme) {
+                    throw new IllegalArgumentException("Cannot encode " + o);
+				} catch (Exception e) {
+					throw new RuntimeException(
+							"Internal transformation exception", e);
+				}
+			}
+		}
+
+		public void visit(ContrastEnhancement ce) {
+			if (ce == null || ce.getMethod() == null)
+				return;
+			
+			start("ContrastEnhancement");
+			// histogram
+			ContrastMethod method = ce.getMethod();
+			if (method != null && !ContrastMethod.NONE.equals(method)) {
+				String val = method.name();
+				val = val.substring(0, 1).toUpperCase() + val.substring(1).toLowerCase();
+				start(val);
+				end(val);
+			}
+			
+			//gamma
+			Expression exp = (Literal)ce.getGammaValue();
+			if (exp != null) {
+				//gamma is a double so the actual value needs to be printed here
+				element("GammaValue",  ((Literal)exp).getValue().toString());
+//				element("GammaValue", exp);
+			}
+			end("ContrastEnhancement");
+
+		}
+
+		public void visit(ImageOutline outline) {
+			if(outline==null)
+				return;
+			start("ImageOutline");
+			outline.getSymbolizer().accept(this);
+			end("ImageOutline");
+		}
+
+		public void visit(ChannelSelection cs) {
+			if(cs==null)
+				return;
+			start("ChannelSelection");
+			final SelectedChannelType[] sct = cs.getSelectedChannels();
+			for (int i = 0; i < sct.length && sct != null; i++)
+				visit(sct[i]);
+			end("ChannelSelection");
+
+		}
+
+		public void visit(OverlapBehavior ob) {
+			start("OverlapBehavior");
+			final String pn = (String) ob.getValue();
+			start(pn);
+			end(pn);
+			end("OverlapBehavior");
+
+		}
+
+		public void visit(SelectedChannelType sct) {
+			element("SourceChannelName", sct.getChannelName());
+			final ContrastEnhancement ce = sct.getContrastEnhancement();
+			if (ce != null)
+				ce.accept(this);
+
+		}
+
+		public void visit(ShadedRelief sr) {
+			start("ShadedRelief");
+			//brightnessonly
+			if(sr.isBrightnessOnly())
+				element("BrightnessOnly", "true");
+			else
+				element("BrightnessOnly", "false");
+			
+			//relief factor
+			if(sr.getReliefFactor()!=null)
+			{
+//				element("ReliefFactor",sr.getReliefFactor());
+				//this expression needs to be converted to a single string and then written
+				//1.0.0 specs don't allow it to be written as an expression
+				Literal l = (Literal)sr.getReliefFactor();
+				element("ReliefFactor",  l.getValue().toString());
+			}
+			end("ShadedRelief");
+
+		}
+	}
+}
\ No newline at end of file


Property changes on: trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/SLDTransformer.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/visitor/DuplicatingStyleVisitor.java
===================================================================
--- trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/visitor/DuplicatingStyleVisitor.java	2011-09-02 16:41:28 UTC (rev 1705)
+++ trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/visitor/DuplicatingStyleVisitor.java	2011-09-02 19:05:30 UTC (rev 1706)
@@ -0,0 +1,1047 @@
+/*
+ *    Diese Klasse ist übergangsweise drin. 
+ * 	  Kopie aus 8.0 trunk um RGB RasterZeugs zu implementieren
+ *    2.9.2011
+ *    
+ *    GeoTools - The Open Source Java GIS Toolkit
+ *    http://geotools.org
+ * 
+ *    (C) 2006-2008, Open Source Geospatial Foundation (OSGeo)
+ *    
+ *    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 de.schmitzm.geotools.org.geotools.styling.visitor;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.geotools.factory.CommonFactoryFinder;
+import org.geotools.filter.visitor.DuplicatingFilterVisitor;
+import org.geotools.styling.AnchorPoint;
+import org.geotools.styling.ChannelSelection;
+import org.geotools.styling.ColorMap;
+import org.geotools.styling.ColorMapEntry;
+import org.geotools.styling.ContrastEnhancement;
+import org.geotools.styling.DescriptionImpl;
+import org.geotools.styling.Displacement;
+import org.geotools.styling.Extent;
+import org.geotools.styling.ExternalGraphic;
+import org.geotools.styling.FeatureTypeConstraint;
+import org.geotools.styling.FeatureTypeStyle;
+import org.geotools.styling.FeatureTypeStyleImpl;
+import org.geotools.styling.Fill;
+import org.geotools.styling.Font;
+import org.geotools.styling.Graphic;
+import org.geotools.styling.Halo;
+import org.geotools.styling.ImageOutline;
+import org.geotools.styling.LabelPlacement;
+import org.geotools.styling.LinePlacement;
+import org.geotools.styling.LineSymbolizer;
+import org.geotools.styling.Mark;
+import org.geotools.styling.NamedLayer;
+import org.geotools.styling.OtherText;
+import org.geotools.styling.OtherTextImpl;
+import org.geotools.styling.OverlapBehavior;
+import org.geotools.styling.PointPlacement;
+import org.geotools.styling.PointSymbolizer;
+import org.geotools.styling.PolygonSymbolizer;
+import org.geotools.styling.RasterSymbolizer;
+import org.geotools.styling.Rule;
+import org.geotools.styling.SelectedChannelType;
+import org.geotools.styling.ShadedRelief;
+import org.geotools.styling.Stroke;
+import org.geotools.styling.Style;
+import org.geotools.styling.StyleFactory;
+import org.geotools.styling.StyleFactoryImpl;
+import org.geotools.styling.StyleVisitor;
+import org.geotools.styling.StyledLayer;
+import org.geotools.styling.StyledLayerDescriptor;
+import org.geotools.styling.Symbol;
+import org.geotools.styling.Symbolizer;
+import org.geotools.styling.TextSymbolizer;
+import org.geotools.styling.TextSymbolizer2;
+import org.geotools.styling.UserLayer;
+import org.opengis.filter.Filter;
+import org.opengis.filter.FilterFactory2;
+import org.opengis.filter.expression.Expression;
+import org.opengis.style.ContrastMethod;
+import org.opengis.style.Description;
+
+/**
+ * Creates a deep copy of a Style, this class is *NOT THREAD SAFE*.
+ * <p>
+ * This class makes use of an internal stack to story the copied result,
+ * retrieve with a call to getCopy() after visiting:<pre><code>
+ * DuplicatingStyleVisitor copyStyle = new DuplicatingStyleVisitor();
+ * rule.accepts( copyStyle );
+ * Rule rule = (Rule) copyStyle.getCopy();
+ * </code></pre>
+ * <p>
+ * This class is often used as a base for an anoymous subclass where
+ * a style transformation is needed (such as removing PointSymbolizers
+ * or changing the scale - see RescaleStyleVisitor for an example).
+ * </p>
+ * @author Jesse Eichar
+ *
+ *
+ * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/library/main/src/main/java/org/geotools/styling/visitor/DuplicatingStyleVisitor.java $
+ */
+public class DuplicatingStyleVisitor implements StyleVisitor {
+	
+    protected final StyleFactory sf;
+    protected final FilterFactory2 ff;
+    protected boolean STRICT;
+
+    /**
+     * We are using aggregation here to contain our DuplicatingFilterVisitor.
+     */
+    protected final DuplicatingFilterVisitor copyFilter;
+    
+    /**
+     * This is our internal stack; used to maintain state as we copy sub elements.
+     */
+    protected Stack<Object> pages=new Stack<Object>();  
+    
+    public DuplicatingStyleVisitor() {
+		this( CommonFactoryFinder.getStyleFactory( null ) );
+	}	
+
+    public DuplicatingStyleVisitor(StyleFactory styleFactory) {
+	    this( styleFactory, CommonFactoryFinder.getFilterFactory2( null ));
+	}
+
+    public DuplicatingStyleVisitor(StyleFactory styleFactory, FilterFactory2 filterFactory ) {
+		this.copyFilter = new DuplicatingFilterVisitor( filterFactory );
+		this.sf=styleFactory;
+		this.ff=filterFactory;
+		this.STRICT = false;
+	}
+
+    /**
+	 * True if we should enforce equality after a copy.
+	 * @param strict
+	 */
+    public void setStrict(boolean strict) {
+        STRICT = strict;
+    }
+
+    public Object getCopy() {
+		return pages.peek();
+	}
+	
+    public void visit(StyledLayerDescriptor sld) {
+        StyledLayerDescriptor copy = null;
+
+        StyledLayer[] layers = sld.getStyledLayers();
+        StyledLayer[] layersCopy = new StyledLayer[layers.length];
+        final int length=layers.length;
+        for (int i = 0; i < length; i++) {
+            if (layers[i] instanceof UserLayer) {
+                ((UserLayer) layers[i]).accept(this);
+                layersCopy[i] = (UserLayer) pages.pop();
+            } else if (layers[i] instanceof NamedLayer) {
+                ((NamedLayer) layers[i]).accept(this);
+                layersCopy[i] = (NamedLayer) pages.pop();
+            }
+        }
+
+        copy = sf.createStyledLayerDescriptor();
+        copy.setAbstract(sld.getAbstract());
+        copy.setName(sld.getName());
+        copy.setTitle(sld.getTitle());
+        copy.setStyledLayers(layersCopy);
+
+        if( STRICT && !copy.equals( sld )){
+            throw new IllegalStateException("Was unable to duplicate provided SLD:"+sld );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(NamedLayer layer) {
+        NamedLayer copy = null;
+
+        Style[] style = layer.getStyles();
+        Style[] styleCopy = new Style[style.length];
+        int length=style.length;
+        for (int i = 0; i < length; i++) {
+            if (style[i] != null) {
+                style[i].accept(this);
+                styleCopy[i] = (Style) pages.pop();
+            }
+        }
+
+        FeatureTypeConstraint[] lfc = layer.getLayerFeatureConstraints();
+        FeatureTypeConstraint[] lfcCopy = new FeatureTypeConstraint[lfc.length];
+
+        length=lfc.length;
+        for (int i = 0; i < length; i++) {
+            if (lfc[i] != null) {
+                lfc[i].accept(this);
+                lfcCopy[i] = (FeatureTypeConstraint) pages.pop();
+            }
+        }
+
+        copy = sf.createNamedLayer();
+        copy.setName(layer.getName());
+        length=styleCopy.length;
+        for (int i = 0; i < length; i++) {
+            copy.addStyle(styleCopy[i]);
+        }
+
+        copy.setLayerFeatureConstraints(lfcCopy);
+        pages.push(copy);
+    }
+
+    public void visit(UserLayer layer) {
+        UserLayer copy = null;
+
+       
+        Style[] style = layer.getUserStyles();
+         int length=style.length;
+        Style[] styleCopy = new Style[length];
+        for (int i = 0; i < length; i++) {
+            if (style[i] != null) {
+                style[i].accept(this);
+                styleCopy[i] = (Style) pages.pop();
+            }
+        }
+
+        FeatureTypeConstraint[] lfc = layer.getLayerFeatureConstraints();
+        FeatureTypeConstraint[] lfcCopy = new FeatureTypeConstraint[lfc.length];
+
+        length=lfc.length;
+        for (int i = 0; i < length; i++) {
+            if (lfc[i] != null) {
+                lfc[i].accept(this);
+                lfcCopy[i] = (FeatureTypeConstraint) pages.pop();
+            }
+        }
+
+        copy = sf.createUserLayer();
+        copy.setName(layer.getName());
+        copy.setUserStyles(styleCopy);
+        copy.setLayerFeatureConstraints(lfcCopy);
+
+        if( STRICT && !copy.equals( layer )){
+            throw new IllegalStateException("Was unable to duplicate provided UserLayer:"+layer );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(Style style) {
+        Style copy = null;
+
+        FeatureTypeStyle[] fts = style.getFeatureTypeStyles();
+        final int length=fts.length;
+        FeatureTypeStyle[] ftsCopy = new FeatureTypeStyle[length];
+        for (int i = 0; i < length; i++) {
+            if (fts[i] != null) {
+                fts[i].accept(this);
+                ftsCopy[i] = (FeatureTypeStyle) pages.pop();
+            }
+        }
+
+        copy = sf.createStyle();
+        copy.setAbstract(style.getAbstract());
+        copy.setName(style.getName());
+        copy.setTitle(style.getTitle());
+        copy.setFeatureTypeStyles(ftsCopy);
+
+        if( STRICT && !copy.equals( style )){
+            throw new IllegalStateException("Was unable to duplicate provided Style:"+style );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(Rule rule) {
+        Rule copy = null;
+
+        
+        
+        Filter filterCopy = null;
+
+        if (rule.getFilter() != null) {
+            Filter filter = rule.getFilter();
+            filterCopy = copy( filter );
+        }
+        
+        Symbolizer[] symsCopy = rule.getSymbolizers();
+        for (int i = 0; i < symsCopy.length; i++) {
+        	symsCopy[i] = copy(symsCopy[i]);
+		}
+        
+        Graphic[] legendCopy = rule.getLegendGraphic();
+        for (int i = 0; i < legendCopy.length; i++) {
+			legendCopy[i] = copy(legendCopy[i]);
+		}
+        
+        Description descCopy = rule.getDescription();
+        descCopy = copy(descCopy);
+        
+        copy = sf.createRule();
+        copy.setSymbolizers(symsCopy);
+        copy.setDescription(descCopy);
+        copy.setLegendGraphic(legendCopy);
+        copy.setName(rule.getName());
+        copy.setFilter(filterCopy);
+        copy.setElseFilter(rule.isElseFilter());
+        copy.setMaxScaleDenominator(rule.getMaxScaleDenominator());
+        copy.setMinScaleDenominator(rule.getMinScaleDenominator());
+
+        if( STRICT && !copy.equals( rule )){
+            throw new IllegalStateException("Was unable to duplicate provided Rule:"+rule );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(FeatureTypeStyle fts) {
+        
+        
+        FeatureTypeStyle copy = new FeatureTypeStyleImpl( (FeatureTypeStyleImpl)fts);
+
+//        copy = new StyleFactoryImpl().createFeatureTypeStyle(
+//                fts.getRules(), 
+//                fts.getSemanticTypeIdentifiers(),
+//                fts.featureInstanceIDs(),
+//                fts.getFeatureTypeName(),
+//                fts.getDescription(),
+//                fts.getName());
+        
+        
+        Rule[] rules = fts.getRules();
+        int length=rules.length;
+        Rule[] rulesCopy = new Rule[length];
+        for (int i = 0; i < length; i++) {
+            if (rules[i] != null) {
+                rules[i].accept(this);
+                rulesCopy[i] = (Rule) pages.pop();
+            }
+        }
+//
+//        copy = sf.createFeatureTypeStyle();
+//        copy.setName(fts.getName());
+//        copy.setTitle(fts.getTitle());
+//        copy.setAbstract(fts.getAbstract());
+//        copy.setFeatureTypeName(fts.getFeatureTypeName());
+        copy.setRules(rulesCopy);
+//        copy.setSemanticTypeIdentifiers((String[]) fts.getSemanticTypeIdentifiers().clone());
+        
+        if( STRICT && !copy.equals( fts )){
+            throw new IllegalStateException("Was unable to duplicate provided FeatureTypeStyle:"+fts );
+        }
+        pages.push(copy);
+    }
+    
+    /**
+     * Null safe expression copy.
+     * <p>
+     * This method will perform a null check, and save you some lines of code:<pre><code>
+     * copy.setBackgroundColor( copyExpr( fill.getColor()) );
+     * </code></pre>
+     * @param sion
+     * @return copy of expression or null if expression was null
+     */    
+    protected Expression copy( Expression expression ){
+        if( expression == null  ) return null;
+        return (Expression) expression.accept( copyFilter, ff );
+    }
+    
+    /**
+     * Null safe copy of filter.
+     */
+    protected Filter copy( Filter filter ){
+        if( filter == null ) return null;
+        return (Filter) filter.accept( copyFilter, ff );        
+    }
+    
+    /**
+     * Null safe graphic copy
+     * @param graphic
+     * @return copy of graphic or null if not provided
+     */
+    protected Graphic copy( Graphic graphic ){
+        if( graphic == null ) return null;
+        
+        graphic.accept(this);
+        return (Graphic) pages.pop();
+    }
+    
+    /**
+     * Null safe fill copy
+     * @param graphic
+     * @return copy of graphic or null if not provided
+     */
+    protected Fill copy( Fill fill ){
+        if( fill == null ) return null;
+        
+        fill.accept(this);
+        return (Fill) pages.pop();
+    }
+    
+    /**
+     * Null safe copy of float array.
+     * @param array
+     * @return copy of array or null if not provided
+     */
+    protected float[] copy(float[] array) {
+        if( array == null ) return null;
+        
+        float copy[] = new float[ array.length];
+        System.arraycopy( array, 0, copy, 0, array.length );
+        return copy;
+    }
+    
+    /**
+     * Null safe map copy, used for external graphic custom properties.
+     * @param customProperties
+     * @return copy of map
+     */
+    @SuppressWarnings("unchecked")
+    protected <K,V> Map<K,V> copy(Map<K,V> customProperties) {
+        if( customProperties == null ) return null;
+        return new HashMap<K,V>( customProperties );
+    }
+    
+    /**
+     * Null safe copy of stroke.
+     * @param stroke
+     * @return copy of stroke if provided
+     */
+    protected Stroke copy( Stroke stroke ){
+        if( stroke == null ) return null;
+        stroke.accept(this);
+        return (Stroke) pages.pop();
+    }
+    
+    /**
+     * Null safe copy of shaded relief.
+     * @param shaded
+     * @return copy of shaded or null if not provided
+     */
+    protected ShadedRelief copy(ShadedRelief shaded) {
+        if( shaded == null ) return null;
+        Expression reliefFactor = copy( shaded.getReliefFactor() );
+        ShadedRelief copy = sf.createShadedRelief( reliefFactor );
+        copy.setBrightnessOnly( shaded.isBrightnessOnly() );
+        
+        return copy;
+    }
+    
+    /**
+     * Null safe copy of description
+     * @param shaded
+     * @return copy of shaded or null if not provided
+     */
+    protected Description copy(Description desc) {
+        if( desc == null ) return null;
+        DescriptionImpl copy = new DescriptionImpl(desc.getTitle(), desc.getAbstract());
+        return copy;
+    }
+    
+    protected ExternalGraphic copy( ExternalGraphic externalGraphic){
+        if( externalGraphic == null ) return null;
+        externalGraphic.accept(this);
+        return (ExternalGraphic) pages.pop();
+    }
+    
+    protected Mark copy( Mark mark){
+        if( mark == null ) return null;
+        mark.accept(this);
+        return (Mark) pages.pop();
+    }
+    
+    protected ColorMapEntry copy(ColorMapEntry entry) {
+        if( entry == null ) return null;
+        
+        entry.accept( this );
+        return (ColorMapEntry) pages.pop();
+    }
+    
+    protected Symbolizer copy(Symbolizer symbolizer) {
+        if( symbolizer == null ) return null;
+        
+        symbolizer.accept(this);
+        return (Symbolizer) pages.pop();
+    }
+    
+    protected OverlapBehavior copy(OverlapBehavior ob) {
+        if( ob == null ) return null;
+        
+        ob.accept(this);
+        return (OverlapBehavior) pages.pop();
+    }
+    
+    protected ContrastEnhancement copy(ContrastEnhancement contrast) {
+        if( contrast == null ) return null;
+        
+        ContrastEnhancement copy = sf.createContrastEnhancement();
+        copy.setGammaValue( copy( contrast.getGammaValue()));
+        if (contrast.getMethod() == ContrastMethod.HISTOGRAM) copy.setType(ff.literal("Histogram"));
+        if (contrast.getMethod() == ContrastMethod.NORMALIZE) copy.setType(ff.literal("Normalize"));
+//        if(contrast.getType() != null) {
+//            copy.setType(contrast.getType());
+//        }
+        return copy;
+    }
+    
+    protected ColorMap copy(ColorMap colorMap) {
+        if( colorMap == null ) return null;
+        
+        colorMap.accept(this);
+        return (ColorMap) pages.pop();
+    }
+    
+    protected SelectedChannelType[] copy( SelectedChannelType[] channels){
+        if( channels == null ) return null;
+        
+        SelectedChannelType[] copy = new SelectedChannelType[ channels.length ];
+        for( int i=0; i< channels.length ; i++){
+            copy[i] = copy( channels[i] );
+        }
+        return copy;
+    }
+    
+    protected SelectedChannelType copy(SelectedChannelType selectedChannelType) {
+        if( selectedChannelType == null ) return null;
+        
+        ContrastEnhancement enhancement = copy( selectedChannelType.getContrastEnhancement() );
+        String name = selectedChannelType.getChannelName();
+        SelectedChannelType copy = sf.createSelectedChannelType( name, enhancement);
+        
+        return copy;
+    }
+    
+    protected ChannelSelection copy(ChannelSelection channelSelection) {
+        if( channelSelection == null ) return null;
+     
+        SelectedChannelType[] channels = copy( channelSelection.getSelectedChannels() );
+        ChannelSelection copy = sf.createChannelSelection( channels);
+        copy.setGrayChannel( copy( channelSelection.getGrayChannel() ));
+        copy.setRGBChannels( copy( channelSelection.getRGBChannels() ));
+        return copy;
+    }
+    
+    /**
+     * Null safe copy of font array.
+     * <p>
+     * Right now style visitor does not let us visit fonts!
+     * @param fonts
+     * @return copy of provided fonts
+     */
+    protected Font[] copy(Font[] fonts) {
+        if( fonts == null ) return null;
+        Font copy[] = new Font[ fonts.length ];
+        for( int i=0; i<fonts.length; i++){
+            copy[i] = copy( fonts[i] );
+        }
+        return copy;
+    }
+    
+    /** Null safe copy of a single font */
+    protected Font copy(Font font) {
+        if( font == null) return font;
+        
+        Expression fontFamily = copy( font.getFontFamily() );
+        Expression fontStyle = copy( font.getFontStyle() );
+        Expression fontWeight = copy( font.getFontWeight() );
+        Expression fontSize = copy( font.getFontSize() );
+        Font copy = sf.createFont(fontFamily, fontStyle, fontWeight, fontSize);
+        return copy;
+    }
+    
+    /**
+     * Null safe copy of halo.
+     * @param halo 
+     * @return copy of halo if provided
+     */
+    protected Halo copy( Halo halo){
+        if( halo == null ) return null;
+        halo.accept(this);
+        return (Halo) pages.pop();
+    }
+    
+    /**
+     * Null safe copy of displacement.
+     * @param displacement
+     * @return copy of displacement if provided
+     */
+    protected Displacement copy(Displacement displacement) {
+        if( displacement == null ) return null;
+        displacement.accept(this);
+        return (Displacement) pages.pop();
+    }
+    
+    protected LabelPlacement copy(LabelPlacement placement) {
+        if( placement == null ) return null;
+        placement.accept(this);
+        return (LabelPlacement) pages.pop();
+    }
+
+    protected Symbol copy(Symbol symbol) {
+        if( symbol == null ) return null;
+        symbol.accept(this);
+        return (Symbol) pages.pop();
+    }
+    
+    /**
+     * Null safe copy of anchor point.
+     * @param anchorPoint
+     * @return copy of anchor point if provided
+     */
+    protected AnchorPoint copy(AnchorPoint anchorPoint) {
+        if( anchorPoint == null ) return null;
+        anchorPoint.accept(this);
+        return (AnchorPoint) pages.pop();
+    }
+
+    public void visit(Fill fill) {
+        Fill copy = sf.getDefaultFill();
+        copy.setBackgroundColor( copy( fill.getBackgroundColor()) );
+        copy.setColor(copy( fill.getColor()));
+        copy.setGraphicFill( copy(fill.getGraphicFill()));
+        copy.setOpacity( copy(fill.getOpacity()));
+        
+        if( STRICT && !copy.equals( fill )){
+            throw new IllegalStateException("Was unable to duplicate provided Fill:"+fill );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(Stroke stroke) {
+        Stroke copy = sf.getDefaultStroke();
+        copy.setColor( copy(stroke.getColor()));
+        copy.setDashArray( copy(stroke.getDashArray()));
+        copy.setDashOffset( copy( stroke.getDashOffset()));
+        copy.setGraphicFill( copy(stroke.getGraphicFill()));
+        copy.setGraphicStroke( copy( stroke.getGraphicStroke()));
+        copy.setLineCap(copy(stroke.getLineCap()));
+        copy.setLineJoin( copy(stroke.getLineJoin()));
+        copy.setOpacity( copy(stroke.getOpacity()));
+        copy.setWidth( copy(stroke.getWidth()));
+
+        if( STRICT && !copy.equals( stroke)){
+            throw new IllegalStateException("Was unable to duplicate provided Stroke:"+stroke );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(Symbolizer sym) {
+        if( sym instanceof RasterSymbolizer){
+            visit( (RasterSymbolizer) sym );            
+        }
+        else if( sym instanceof LineSymbolizer){
+            visit( (LineSymbolizer) sym );            
+        }
+        else if( sym instanceof PolygonSymbolizer){
+            visit( (PolygonSymbolizer) sym );            
+        }
+        else if( sym instanceof PointSymbolizer){
+            visit( (PointSymbolizer) sym );            
+        }
+        else if( sym instanceof TextSymbolizer){
+            visit( (TextSymbolizer) sym );            
+        }
+        else {
+            throw new RuntimeException("visit(Symbolizer) unsupported");
+        }
+    }
+
+    public void visit(PointSymbolizer ps) {
+        PointSymbolizer copy = sf.getDefaultPointSymbolizer();
+        
+        copy.setGeometry(copy(ps.getGeometry()));
+        
+        copy.setUnitOfMeasure(ps.getUnitOfMeasure());
+        copy.setGraphic( copy( ps.getGraphic() ));
+        
+        if( STRICT ){
+            if( !copy.equals( ps )){
+                throw new IllegalStateException("Was unable to duplicate provided Graphic:"+ps );
+            }
+        }
+        pages.push(copy);
+    }
+
+    public void visit(LineSymbolizer line) {
+        LineSymbolizer copy = sf.getDefaultLineSymbolizer();
+        
+        copy.setGeometry(copy(line.getGeometry()));
+        
+        copy.setUnitOfMeasure(line.getUnitOfMeasure());
+        copy.setStroke( copy( line.getStroke()));
+        
+        if( STRICT && !copy.equals( line )){
+            throw new IllegalStateException("Was unable to duplicate provided LineSymbolizer:"+line );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(PolygonSymbolizer poly) {
+        PolygonSymbolizer copy = sf.createPolygonSymbolizer();
+        copy.setFill( copy( poly.getFill()));
+        
+        copy.setGeometry(copy(poly.getGeometry()));
+        
+        copy.setUnitOfMeasure(poly.getUnitOfMeasure());
+        copy.setStroke(copy(poly.getStroke()));
+        
+        if( STRICT && !copy.equals( poly )){
+            throw new IllegalStateException("Was unable to duplicate provided PolygonSymbolizer:"+poly );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(TextSymbolizer text) {
+        TextSymbolizer copy = sf.createTextSymbolizer();
+        
+        copy.setFill( copy( text.getFill()));
+        copy.setFont( copy( text.getFont()));
+        
+        copy.setGeometry(copy(text.getGeometry()));
+        
+        copy.setUnitOfMeasure(text.getUnitOfMeasure());
+        copy.setHalo( copy( text.getHalo() ));
+        copy.setLabel( copy( text.getLabel()));
+        copy.setLabelPlacement( copy( text.getLabelPlacement()));
+        copy.setPriority( copy( text.getPriority()));
+        copy.getOptions().putAll(text.getOptions());
+        
+        if (text instanceof TextSymbolizer2){
+        	TextSymbolizer2 text2 = (TextSymbolizer2) text;
+        	TextSymbolizer2 copy2 = (TextSymbolizer2) copy;
+        	
+        	copy2.setGraphic( copy(text2.getGraphic()));
+        	copy2.setSnippet(copy(text2.getSnippet()));
+        	copy2.setFeatureDescription(copy(text2.getFeatureDescription()));
+        	copy2.setOtherText(copy(text2.getOtherText()));
+        }
+        
+        if( STRICT && !copy.equals( text )){
+            throw new IllegalStateException("Was unable to duplicate provided TextSymbolizer:"+text );
+        }
+        pages.push(copy);
+    }
+
+	public void visit(RasterSymbolizer raster) {
+        RasterSymbolizer copy = sf.createRasterSymbolizer();
+        copy.setChannelSelection( copy( raster.getChannelSelection() ));
+        copy.setColorMap( copy( raster.getColorMap() ));
+        copy.setContrastEnhancement( copy( raster.getContrastEnhancement()));
+        
+        copy.setGeometry(copy(raster.getGeometry()));
+        
+        copy.setUnitOfMeasure(raster.getUnitOfMeasure());
+        copy.setImageOutline( copy( raster.getImageOutline()));
+        copy.setOpacity( copy( raster.getOpacity() ));
+        copy.setOverlap( copy( raster.getOverlap()));
+        copy.setShadedRelief( copy( raster.getShadedRelief()));
+        
+        if( STRICT && !copy.equals( raster )){
+            throw new IllegalStateException("Was unable to duplicate provided raster:"+raster );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(Graphic gr) {
+        Graphic copy = null;
+
+        Displacement displacementCopy = copy( gr.getDisplacement() );
+        ExternalGraphic[] externalGraphicsCopy = copy( gr.getExternalGraphics() );
+        Mark[] marksCopy = copy( gr.getMarks() );
+        Expression opacityCopy = copy( gr.getOpacity() );
+        Expression rotationCopy = copy( gr.getRotation() );
+        Expression sizeCopy = copy( gr.getSize() );        
+        
+        // Looks like Symbols are a "view" of marks and external graphics?
+        // Symbol[] symbolCopys = copy( gr.getSymbols() );
+
+        copy = sf.createDefaultGraphic();
+        
+        copy.setDisplacement(displacementCopy);
+        copy.setExternalGraphics(externalGraphicsCopy);
+        copy.setMarks(marksCopy);
+        copy.setOpacity((Expression) opacityCopy);
+        copy.setRotation((Expression) rotationCopy);
+        copy.setSize((Expression) sizeCopy);
+        // copy.setSymbols(symbolCopys);
+        
+        if( STRICT ){
+            if( !copy.equals( gr )){
+                throw new IllegalStateException("Was unable to duplicate provided Graphic:"+gr );
+            }
+        }
+        pages.push(copy);
+    }
+    
+    private Mark[] copy(Mark[] marks) {
+        if( marks == null) return null;
+        Mark[] copy = new Mark[marks.length];
+        for (int i = 0; i < marks.length; i++) {
+            copy[i] = copy( marks[i]);
+        }
+        return copy;
+    }
+    
+    private Symbol[] copy(Symbol[] symbols) {
+        if( symbols == null) return null;
+        Symbol[] copy = new Symbol[symbols.length];
+        for (int i = 0; i < symbols.length; i++) {
+            copy[i] = copy( symbols[i]);
+        }
+        return copy;
+    }
+    
+    private ExternalGraphic[] copy(ExternalGraphic[] externalGraphics) {
+        if( externalGraphics == null) return null;
+        ExternalGraphic[] copy = new ExternalGraphic[externalGraphics.length];
+        for (int i = 0; i < externalGraphics.length; i++) {
+            copy[i] = copy( externalGraphics[i]);
+        }
+        return copy;
+    }
+    
+    public void visit(Mark mark) {
+        Mark copy = null;
+
+        copy = sf.createMark();
+        copy.setFill(copy( mark.getFill() ));
+        copy.setStroke(copy( mark.getStroke() ));
+        copy.setWellKnownName(copy( mark.getWellKnownName() ));
+        
+        if( STRICT && !copy.equals( mark )){
+            throw new IllegalStateException("Was unable to duplicate provided Mark:"+mark );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(ExternalGraphic exgr) {
+        URL uri = null;
+        try {
+            uri = exgr.getLocation();
+        }
+        catch (MalformedURLException huh ){
+            
+        }
+        String format = exgr.getFormat();
+        ExternalGraphic copy = sf.createExternalGraphic(uri, format);
+        copy.setCustomProperties( copy(exgr.getCustomProperties()));
+        
+        if( STRICT && !copy.equals( exgr )){
+            throw new IllegalStateException("Was unable to duplicate provided ExternalGraphic:"+exgr );
+        }
+        pages.push(copy);       
+    }
+
+    public void visit(PointPlacement pp) {
+        PointPlacement copy = sf.getDefaultPointPlacement();
+        copy.setAnchorPoint( copy( pp.getAnchorPoint() ));
+        copy.setDisplacement( copy(pp.getDisplacement()));
+        copy.setRotation( copy( pp.getRotation() ));
+
+        if( STRICT && !copy.equals( pp )){
+            throw new IllegalStateException("Was unable to duplicate provided PointPlacement:"+pp );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(AnchorPoint ap) {        
+        Expression x = copy( ap.getAnchorPointX() );
+        Expression y = copy( ap.getAnchorPointY() );
+        AnchorPoint copy = sf.createAnchorPoint(x, y);
+        
+        if( STRICT && !copy.equals( ap)){
+            throw new IllegalStateException("Was unable to duplicate provided AnchorPoint:"+ap);
+        }        
+        pages.push(copy);
+    }
+
+    public void visit(Displacement dis) {
+        Expression x = copy( dis.getDisplacementX() );
+        Expression y = copy( dis.getDisplacementY() );
+        Displacement copy = sf.createDisplacement(x, y);
+        
+        if( STRICT && !copy.equals( dis )){
+            throw new IllegalStateException("Was unable to duplicate provided Displacement:"+dis );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(LinePlacement lp) {
+        Expression offset = copy( lp.getPerpendicularOffset());
+        LinePlacement copy = sf.createLinePlacement(offset);
+        copy.setAligned( lp.isAligned() );
+        copy.setGap( copy(lp.getGap()) );
+        copy.setGeneralized( lp.isGeneralizeLine() );
+        copy.setInitialGap( copy(lp.getInitialGap()) );
+        copy.setRepeated( lp.isRepeated() );
+
+        if( STRICT && !copy.equals( lp )){
+            throw new IllegalStateException("Was unable to duplicate provided LinePlacement:"+lp );
+        }
+        pages.push(copy);
+    }
+
+    public void visit(Halo halo) {
+        Fill fill = copy(halo.getFill());
+        Expression radius = copy(halo.getRadius());
+        Halo copy = sf.createHalo(fill, radius);
+
+        if (STRICT && !copy.equals(halo)) {
+            throw new IllegalStateException("Was unable to duplicate provided raster:" + halo);
+        }
+        pages.push(copy);
+    }
+
+    public void visit(FeatureTypeConstraint ftc) {
+        String typeName = ftc.getFeatureTypeName();
+        Filter filter = copy(ftc.getFilter());
+        Extent[] extents = copy(ftc.getExtents());
+        FeatureTypeConstraint copy = sf.createFeatureTypeConstraint(typeName, filter, extents);
+
+        if (STRICT && !copy.equals(ftc)) {
+            throw new IllegalStateException("Was unable to duplicate provided FeatureTypeConstraint:" + ftc);
+        }
+        pages.push(copy);
+    }
+
+    protected Extent[] copy(Extent[] extents) {
+        if (extents == null) {
+            return null;
+        }
+        Extent[] copy = new Extent[extents.length];
+        for (int i = 0; i < extents.length; i++) {
+            copy[i] = copy(extents[i]);
+        }
+        return copy;
+    }
+
+    protected Extent copy(Extent extent) {
+        String name = extent.getName();
+        String value = extent.getValue();
+        Extent copy = sf.createExtent(name, value);
+        return copy;
+    }
+    
+    
+    private OtherText copy(OtherText otherText) {
+    	if (otherText == null) return null;
+    	
+        // TODO: add methods to the factory to create OtherText instances
+    	// sf.createOtherText();
+    	OtherTextImpl copy = new OtherTextImpl();
+    	copy.setTarget( otherText.getTarget() );
+    	copy.setText( copy(otherText.getText()) );
+		return copy;
+	}
+
+    
+    public void visit(ColorMap colorMap) {
+        ColorMap copy = sf.createColorMap();
+        copy.setType(colorMap.getType());
+        copy.setExtendedColors(colorMap.getExtendedColors());
+        ColorMapEntry[] entries = colorMap.getColorMapEntries();
+        if (entries != null) {
+            for (int i = 0; i < entries.length; i++) {
+                ColorMapEntry entry = entries[i];
+                copy.addColorMapEntry(copy(entry));
+            }
+        }
+        if (STRICT && !copy.equals(colorMap)) {
+            throw new IllegalStateException("Was unable to duplicate provided ColorMap:" + colorMap);
+        }
+        pages.push(copy);
+    }
+
+    public void visit(ColorMapEntry colorMapEntry) {
+        ColorMapEntry copy = sf.createColorMapEntry();
+        copy.setColor(copy(colorMapEntry.getColor()));
+        copy.setLabel(colorMapEntry.getLabel());
+        copy.setOpacity(copy(colorMapEntry.getOpacity()));
+        copy.setQuantity(colorMapEntry.getQuantity());
+
+        if (STRICT && !copy.equals(colorMapEntry)) {
+            throw new IllegalStateException("Was unable to duplicate provided ColorMapEntry:" + colorMapEntry);
+        }
+        pages.push(copy);
+    }
+    
+    public void visit(ContrastEnhancement contrastEnhancement) {
+        final ContrastEnhancement copy = sf.createContrastEnhancement();
+        copy.setType(contrastEnhancement.getType());
+        copy.setGammaValue(contrastEnhancement.getGammaValue());
+        if (STRICT && !copy.equals(contrastEnhancement)) {
+            throw new IllegalStateException("Was unable to duplicate provided contrastEnhancement:" + contrastEnhancement);
+        }
+        pages.push(copy);
+
+    }
+
+    public void visit(ImageOutline outline) {
+        //copy the symbolizer
+        final Symbolizer symb = outline.getSymbolizer();
+        final Symbolizer copySymb = copy(symb);
+
+        final ImageOutline copy = sf.createImageOutline(copySymb);
+        copy.setSymbolizer(copySymb);
+        if (STRICT && !copy.equals(outline)) {
+            throw new IllegalStateException("Was unable to duplicate provided ImageOutline:" + outline);
+        }
+        pages.push(copy);
+
+    }
+
+    public void visit(ChannelSelection cs) {
+        //get the channels
+        final SelectedChannelType sct[] = copy(cs.getSelectedChannels());
+        final ChannelSelection copy = sf.createChannelSelection(sct);
+        if (STRICT && !copy.equals(cs)) {
+            throw new IllegalStateException("Was unable to duplicate provided ChannelSelection:" + cs);
+        }
+        pages.push(copy);
+
+    }
+    
+    public void visit(OverlapBehavior ob) {
+        final String behavior = (String) ob.getValue();
+        if (behavior.equalsIgnoreCase(OverlapBehavior.AVERAGE_RESCTRICTION)) {
+            pages.push(OverlapBehavior.AVERAGE_RESCTRICTION);
+        } else if (behavior.equalsIgnoreCase(OverlapBehavior.EARLIEST_ON_TOP_RESCTRICTION)) {
+            pages.push(OverlapBehavior.EARLIEST_ON_TOP_RESCTRICTION);
+        } else if (behavior.equalsIgnoreCase(OverlapBehavior.LATEST_ON_TOP_RESCTRICTION)) {
+            pages.push(OverlapBehavior.LATEST_ON_TOP_RESCTRICTION);
+        } else if (behavior.equalsIgnoreCase(OverlapBehavior.RANDOM_RESCTRICTION)) {
+            pages.push(OverlapBehavior.RANDOM_RESCTRICTION);
+        } else {
+            throw new IllegalStateException("Was unable to duplicate provided OverlapBehavior:" + ob);
+        }
+    }
+
+    public void visit(SelectedChannelType sct) {
+        final SelectedChannelType copy = sf.createSelectedChannelType(sct.getChannelName(), copy(sct.getContrastEnhancement()));
+        if (STRICT && !copy.equals(sct)) {
+            throw new IllegalStateException("Was unable to duplicate provided SelectedChannelType:" + sct);
+        }
+        pages.push(copy);
+    }
+
+    public void visit(ShadedRelief sr) {
+        final ShadedRelief copy = sf.createShadedRelief(copy(sr.getReliefFactor()));
+        copy.setBrightnessOnly(sr.isBrightnessOnly());
+        if (STRICT && !copy.equals(sr)) {
+            throw new IllegalStateException("Was unable to duplicate provided ShadedRelief:" + sr);
+        }
+        pages.push(copy);
+
+    }
+}
\ No newline at end of file


Property changes on: trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/org/geotools/styling/visitor/DuplicatingStyleVisitor.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
===================================================================
--- trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/selection/FeatureMapLayerSelectionSynchronizer.java	2011-09-02 16:41:28 UTC (rev 1705)
+++ trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/selection/FeatureMapLayerSelectionSynchronizer.java	2011-09-02 19:05:30 UTC (rev 1706)
@@ -60,7 +60,6 @@
 import org.geotools.map.MapLayer;
 import org.geotools.styling.FeatureTypeStyle;
 import org.geotools.styling.Style;
-import org.geotools.styling.visitor.DuplicatingStyleVisitor;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.filter.Filter;
@@ -73,6 +72,7 @@
 import de.schmitzm.geotools.gui.XMapPaneEvent;
 import de.schmitzm.geotools.map.event.FeatureSelectedEvent;
 import de.schmitzm.geotools.map.event.JMapPaneListener;
+import de.schmitzm.geotools.org.geotools.styling.visitor.DuplicatingStyleVisitor;
 import de.schmitzm.geotools.styling.StyledFeaturesInterface;
 import de.schmitzm.geotools.styling.StylingUtil;
 import de.schmitzm.geotools.styling.StylingUtil.SelectionStylesTypes;

Modified: trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/styling/StylingUtil.java
===================================================================
--- trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/styling/StylingUtil.java	2011-09-02 16:41:28 UTC (rev 1705)
+++ trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/styling/StylingUtil.java	2011-09-02 19:05:30 UTC (rev 1706)
@@ -110,7 +110,6 @@
 import org.geotools.styling.Rule;
 import org.geotools.styling.RuleImpl;
 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;
@@ -118,7 +117,6 @@
 import org.geotools.styling.StyledLayerDescriptor;
 import org.geotools.styling.Symbolizer;
 import org.geotools.styling.TextSymbolizer;
-import org.geotools.styling.visitor.DuplicatingStyleVisitor;
 import org.geotools.util.NumberRange;
 import org.geotools.xml.Parser;
 import org.jdom.Element;
@@ -150,6 +148,8 @@
 import de.schmitzm.geotools.feature.FeatureUtil.GeometryForm;
 import de.schmitzm.geotools.grid.GridUtil;
 import de.schmitzm.geotools.gui.XMapPane;
+import de.schmitzm.geotools.org.geotools.styling.SLDTransformer;
+import de.schmitzm.geotools.org.geotools.styling.visitor.DuplicatingStyleVisitor;
 import de.schmitzm.geotools.selection.FeatureMapLayerSelectionSynchronizer;
 import de.schmitzm.io.IOUtil;
 import de.schmitzm.lang.LangUtil;



More information about the Schmitzm-commits mailing list