All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotools.styling.visitor.DuplicatingStyleVisitor Maven / Gradle / Ivy

/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2006 - 2015, 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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.stream.Collectors;
import javax.swing.*;
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.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.Description;
import org.opengis.style.ExternalMark;
import org.opengis.style.GraphicalSymbol;

/**
 * Creates a deep copy of a Style, this class is *NOT THREAD SAFE*.
 *
 * 

This class makes use of an internal stack to story the copied result, retrieve with a call to * getCopy() after visiting: * *


 * DuplicatingStyleVisitor copyStyle = new DuplicatingStyleVisitor();
 * rule.accepts( copyStyle );
 * Rule rule = (Rule) copyStyle.getCopy();
 * 
* *

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). * * @author Jesse Eichar */ 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 pages = new Stack(); public DuplicatingStyleVisitor() { this(CommonFactoryFinder.getStyleFactory(null)); } public DuplicatingStyleVisitor(StyleFactory styleFactory) { this(styleFactory, CommonFactoryFinder.getFilterFactory2(null)); } public DuplicatingStyleVisitor(StyleFactory styleFactory, FilterFactory2 filterFactory) { this(styleFactory, filterFactory, new DuplicatingFilterVisitor(filterFactory)); } /** * Builds a new duplicating style visitor using a custom {@link DuplicatingStyleVisitor} * * @param styleFactory Creates new style objects during style duplication * @param filterFactory Creates new filters and expressions during style duplication * @param filterCloner Copies filters during style duplication */ public DuplicatingStyleVisitor( StyleFactory styleFactory, FilterFactory2 filterFactory, DuplicatingFilterVisitor filterCloner) { this.copyFilter = filterCloner; this.sf = styleFactory; this.ff = filterFactory; this.STRICT = false; } /** True if we should enforce equality after a copy. */ 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; List ftsCopy = new ArrayList<>(); for (FeatureTypeStyle fts : style.featureTypeStyles()) { if (fts != null) { fts.accept(this); ftsCopy.add((FeatureTypeStyle) pages.pop()); } } copy = sf.createStyle(); copy.getDescription().setAbstract(style.getDescription().getAbstract()); copy.setName(style.getName()); copy.getDescription().setTitle(style.getDescription().getTitle()); copy.featureTypeStyles().addAll(ftsCopy); copy.setBackground(copy(style.getBackground())); 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); } List symsCopy = rule.symbolizers().stream().map(s -> copy(s)).collect(Collectors.toList()); Graphic legendCopy = copy((Graphic) rule.getLegend()); Description descCopy = rule.getDescription(); descCopy = copy(descCopy); copy = sf.createRule(); copy.symbolizers().addAll(symsCopy); copy.setDescription(descCopy); copy.setLegend(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(fts); // copy = new StyleFactoryImpl().createFeatureTypeStyle( // fts.getRules(), // fts.getSemanticTypeIdentifiers(), // fts.featureInstanceIDs(), // fts.getFeatureTypeName(), // fts.getDescription(), // fts.getName()); List rulesCopy = fts.rules() .stream() .filter(r -> r != null) .map( r -> { r.accept(this); return (Rule) pages.pop(); }) .collect(Collectors.toList()); // // copy = sf.createFeatureTypeStyle(); // copy.setName(fts.getName()); // copy.setTitle(fts.getTitle()); // copy.setAbstract(fts.getAbstract()); // copy.setFeatureTypeName(fts.getFeatureTypeName()); copy.rules().clear(); copy.rules().addAll(rulesCopy); // copy.setSemanticTypeIdentifiers((String[]) // fts.getSemanticTypeIdentifiers().clone()); if (fts.getTransformation() != null) { copy.setTransformation(copy(fts.getTransformation())); } if (fts.getOnlineResource() != null) { copy.setOnlineResource(fts.getOnlineResource()); } copy.getOptions().clear(); copy.getOptions().putAll(fts.getOptions()); if (STRICT && !copy.equals(fts)) { throw new IllegalStateException( "Was unable to duplicate provided FeatureTypeStyle:" + fts); } pages.push(copy); } /** * Copy list of expressions. * * @return copy of expressions or null if list was null */ protected List copyExpressions(List expressions) { if (expressions == null) return null; List copy = new ArrayList(expressions.size()); for (Expression expression : expressions) { copy.add(copy(expression)); } return copy; } /** * Null safe expression copy. * *

This method will perform a null check, and save you some lines of code: * *


     * copy.setBackgroundColor( copyExpr( fill.getColor()) );
     * 
* * @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 * * @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 * * @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. * * @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. * * @return copy of map */ @SuppressWarnings("unchecked") protected Map copy(Map customProperties) { if (customProperties == null) return null; return new HashMap(customProperties); } /** * Null safe copy of 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. * * @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 * * @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(); } private ExternalMark copy(org.geotools.styling.ExternalMark other) { if (other == null) { return null; } else if (other.getInlineContent() != null) { return sf.externalMark(other.getInlineContent()); } else { return sf.externalMark( other.getOnlineResource(), other.getFormat(), other.getMarkIndex()); } } 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())); copy.setMethod(contrast.getMethod()); copy.setOptions(contrast.getOptions()); 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()); Expression name = (Expression) selectedChannelType.getChannelName().accept(copyFilter, null); SelectedChannelType copy = sf.createSelectedChannelType(name, enhancement); return copy; } protected ChannelSelection copy(ChannelSelection channelSelection) { if (channelSelection == null) return null; if (channelSelection.getGrayChannel() != null) { return sf.createChannelSelection( new SelectedChannelType[] {copy(channelSelection.getGrayChannel())}); } else { return sf.createChannelSelection(copy(channelSelection.getRGBChannels())); } } /** * Null safe copy of font list. * *

Right now style visitor does not let us visit fonts! * * @return copy of provided fonts */ protected List copyFonts(List fonts) { if (fonts == null) { return null; } List copy = new ArrayList(fonts.size()); for (Font font : fonts) { copy.add(copy(font)); } return copy; } /** Null safe copy of a single font */ protected Font copy(Font font) { if (font == null) return font; List fontFamily = copyExpressions(font.getFamily()); Expression fontStyle = copy(font.getStyle()); Expression fontWeight = copy(font.getWeight()); Expression fontSize = copy(font.getSize()); Font copy = sf.font(fontFamily, fontStyle, fontWeight, fontSize); return copy; } /** * Null safe copy of 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. * * @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. * * @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.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(copyExpressions(stroke.dashArray())); 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())); copy.getOptions().putAll(ps.getOptions()); 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())); copy.getOptions().putAll(line.getOptions()); copy.setPerpendicularOffset(line.getPerpendicularOffset()); 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())); copy.getOptions().putAll(poly.getOptions()); 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.fonts().clear(); copy.fonts().addAll(copyFonts(text.fonts())); 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.setOverlapBehavior(raster.getOverlapBehavior()); 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()); List symbolsCopy = copy(gr.graphicalSymbols()); Expression opacityCopy = copy(gr.getOpacity()); Expression rotationCopy = copy(gr.getRotation()); Expression sizeCopy = copy(gr.getSize()); AnchorPoint anchorCopy = copy(gr.getAnchorPoint()); copy = sf.createDefaultGraphic(); copy.setDisplacement(displacementCopy); copy.graphicalSymbols().clear(); copy.graphicalSymbols().addAll(symbolsCopy); copy.setOpacity(opacityCopy); copy.setRotation(rotationCopy); copy.setSize(sizeCopy); copy.setAnchorPoint(anchorCopy); if (STRICT) { if (!copy.equals(gr)) { throw new IllegalStateException("Was unable to duplicate provided Graphic:" + gr); } } pages.push(copy); } private List copy(List symbols) { List copy = new ArrayList<>(symbols.size()); for (GraphicalSymbol symbol : symbols) { if (symbol instanceof Symbol) { copy.add(copy((Symbol) symbol)); } else { throw new RuntimeException("Don't know how to copy " + symbol); } } 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())); copy.setExternalMark(copy(mark.getExternalMark())); 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(); Icon inlineContent = exgr.getInlineContent(); ExternalGraphic copy; if (inlineContent != null) { copy = sf.createExternalGraphic(inlineContent, format); } else { 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(copy(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.setMethod(contrastEnhancement.getMethod()); copy.setOptions(contrastEnhancement.getOptions()); 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) { ChannelSelection copy = copy(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); } }