/*
* 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 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.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.UserLayer;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.expression.Expression;
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$
*/
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 = new StyleFactoryImpl().createRule(
symsCopy,
descCopy,
legendCopy,
rule.getName(),
filterCopy,
rule.isElseFilter(),
rule.getMaxScaleDenominator(),
rule.getMinScaleDenominator());
// Graphic[] legendGraphic = rule.getLegendGraphic();
// Graphic[] legendGraphicCopy = new Graphic[legendGraphic.length];
//
// int length=legendGraphic.length;
// for (int i = 0; i < length; i++) {
// if (legendGraphic[i] != null) {
// legendGraphic[i].accept(this);
// legendGraphicCopy[i] = (Graphic) pages.pop();
// }
// }
//
// Symbolizer[] symbolizer = rule.getSymbolizers();
// Symbolizer[] symbolizerCopy = new Symbolizer[symbolizer.length];
//
// length=symbolizer.length;
// for (int i = 0; i < length; i++) {
// if (symbolizer[i] != null) {
// symbolizer[i].accept(this);
// symbolizerCopy[i] = (Symbolizer) pages.pop();
// }
// }
//
// copy = sf.createRule();
// copy.setAbstract(rule.getAbstract());
// copy.setFilter(filterCopy);
// copy.setIsElseFilter(rule.hasElseFilter());
// copy.setLegendGraphic(legendGraphicCopy);
// copy.setMinScaleDenominator(rule.getMinScaleDenominator());
// copy.setMaxScaleDenominator(rule.getMaxScaleDenominator());
// copy.setName(rule.getName());
// copy.setTitle(rule.getTitle());
// copy.setSymbolizers(symbolizerCopy);
// int length=legendGraphic.length;
// for (int i = 0; i < length; i++) {
// if (legendGraphic[i] != null) {
// legendGraphic[i].accept(this);
// legendGraphicCopy[i] = (Graphic) pages.pop();
// }
// }
//
// Symbolizer[] symbolizer = rule.getSymbolizers();
// ArrayList<Symbolizer> symbolizerList = new ArrayList<Symbolizer>();
//
//
// length=symbolizer.length;
// for (int i = 0; i < length; i++) {
// if (symbolizer[i] == null) continue;
//
// symbolizer[i].accept(this);
// Symbolizer symbolizerCopy = (Symbolizer) pages.pop();
//
// if( symbolizerCopy == null ) continue;
//
// symbolizerList.add( symbolizerCopy );
// }
// Symbolizer[] symbolizerCopy = symbolizerList.toArray( new Symbolizer[0] );
//
// copy = sf.createRule();
// copy.setAbstract(rule.getAbstract());
// copy.setFilter(filterCopy);
// copy.setIsElseFilter(rule.hasElseFilter());
// copy.setLegendGraphic(legendGraphicCopy);
// copy.setMinScaleDenominator(rule.getMinScaleDenominator());
// copy.setMaxScaleDenominator(rule.getMaxScaleDenominator());
// copy.setName(rule.getName());
// copy.setTitle(rule.getTitle());
// copy.setSymbolizers(symbolizerCopy);
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()));
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.setGeometryPropertyName( ps.getGeometryPropertyName());
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.setGeometryPropertyName( line.getGeometryPropertyName());
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.setGeometryPropertyName( poly.getGeometryPropertyName());
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.setGeometryPropertyName( text.getGeometryPropertyName() );
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( 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.setGeometryPropertyName( raster.getGeometryPropertyName());
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.setGeometryPropertyName(gr.getGeometryPropertyName());
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.setRotation( copy( mark.getRotation() ));
copy.setSize(copy( mark.getSize() ));
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);
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;
}
public void visit(ColorMap colorMap) {
ColorMap copy = sf.createColorMap();
copy.setType(colorMap.getType());
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);
}
}