/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-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; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.geotools.factory.CommonFactoryFinder; import org.geotools.filter.visitor.DuplicatingFilterVisitor; import org.geotools.util.SimpleInternationalString; import org.geotools.util.Utilities; import org.opengis.filter.Filter; import org.opengis.metadata.citation.OnLineResource; import org.opengis.style.GraphicLegend; import org.opengis.style.Rule; import org.opengis.style.StyleVisitor; import org.opengis.util.Cloneable; /** * Provides the default implementation of Rule. * * @author James Macgill * @author Johann Sorel (Geomatys) * * @source $URL$ * @version $Id$ */ public class RuleImpl implements org.geotools.styling.Rule, Cloneable { private List<Symbolizer> symbolizers = new ArrayList<Symbolizer>(); private List<org.geotools.styling.Graphic> legends = new ArrayList<org.geotools.styling.Graphic>(); private String name; private DescriptionImpl description = new DescriptionImpl(); private Filter filter = null; private boolean hasElseFilter = false; private double maxScaleDenominator = Double.POSITIVE_INFINITY; private double minScaleDenominator = 0.0; private OnLineResource online = null; /** * Creates a new instance of DefaultRule */ protected RuleImpl() { } /** * Creates a new instance of DefaultRule * * @param symbolizers DOCUMENT ME! */ protected RuleImpl(Symbolizer[] symbolizers) { this.symbolizers.addAll(Arrays.asList(symbolizers)); } protected RuleImpl(org.geotools.styling.Symbolizer[] symbolizers, org.opengis.style.Description desc, org.geotools.styling.Graphic[] legends, String name, Filter filter, boolean isElseFilter, double maxScale, double minScale){ setSymbolizers(symbolizers); description.setAbstract(desc.getAbstract()); description.setTitle(desc.getTitle()); setLegendGraphic(legends); this.name = name; this.filter = filter; hasElseFilter = isElseFilter; this.maxScaleDenominator = maxScale; this.minScaleDenominator = minScale; } /** Copy constructor */ public RuleImpl(Rule rule) { this.symbolizers = new ArrayList<Symbolizer>(); for( org.opengis.style.Symbolizer sym : rule.symbolizers() ){ if( sym instanceof Symbolizer ){ this.symbolizers.add( (Symbolizer) sym ); } } if( rule.getDescription() != null && rule.getDescription().getTitle() != null ){ this.description.setTitle( rule.getDescription().getTitle() ); } if( rule.getDescription() != null && rule.getDescription().getAbstract() != null ){ this.description.setTitle( rule.getDescription().getAbstract() ); } if( rule.getLegend() instanceof org.geotools.styling.Graphic ){ org.geotools.styling.Graphic graphic = (org.geotools.styling.Graphic) rule.getLegend(); setLegendGraphic( new org.geotools.styling.Graphic[]{ graphic } ); } this.name = rule.getName(); this.filter = rule.getFilter(); this.hasElseFilter = rule.isElseFilter(); this.maxScaleDenominator = rule.getMaxScaleDenominator(); this.minScaleDenominator = rule.getMinScaleDenominator(); } public org.geotools.styling.Graphic[] getLegendGraphic() { return legends.toArray(new org.geotools.styling.Graphic[0]); } @Deprecated public void addLegendGraphic(org.geotools.styling.Graphic graphic) { legends.add(graphic); } /** * A set of equivalent Graphics in different formats which can be used as a * legend against features stylized by the symbolizers in this rule. * * @param graphics An array of Graphic objects, any of which can be used as * the legend. */ @Deprecated public void setLegendGraphic(org.geotools.styling.Graphic[] graphics) { List<org.geotools.styling.Graphic> graphicList = Arrays.asList(graphics); this.legends = new ArrayList<Graphic>(graphicList); // this.legends.clear(); // this.legends.addAll(graphicList); } public GraphicLegend getLegend() { if(legends.isEmpty()) return null; else return legends.get(0); } public void setLegend(GraphicLegend legend) { legends.set(0, (Graphic) legend ); } public List<Symbolizer> symbolizers() { return symbolizers; } @Deprecated public void addSymbolizer(org.geotools.styling.Symbolizer symb) { this.symbolizers.add(symb); } @Deprecated public void setSymbolizers(org.geotools.styling.Symbolizer[] syms) { List<org.geotools.styling.Symbolizer> symbols = Arrays.asList(syms); this.symbolizers = new ArrayList<Symbolizer>(symbols); // this.symbolizers.clear(); // this.symbolizers.addAll(symbols); } @Deprecated public org.geotools.styling.Symbolizer[] getSymbolizers() { final org.geotools.styling.Symbolizer[] ret; ret = new org.geotools.styling.Symbolizer[symbolizers.size()]; for(int i=0, n=symbolizers.size(); i<n; i++){ ret[i] = symbolizers.get(i); } return ret; } public DescriptionImpl getDescription() { return description; } public void setDescription(org.opengis.style.Description description) { this.description = DescriptionImpl.cast(description); } public String getName() { return name; } /** * Getter for property abstractStr. * * @return Value of property abstractStr. */ public java.lang.String getAbstract() { if( description == null || description.getAbstract() == null ){ return null; } return description.getAbstract().toString(); } public void setName(String name) { this.name = name; } /** * Setter for property abstractStr. * * @param abstractStr New value of property abstractStr. */ public void setAbstract(java.lang.String abstractStr) { description.setAbstract( abstractStr != null ? new SimpleInternationalString( abstractStr ) : null ); } /** * Getter for property title. * * @return Value of property title. */ public java.lang.String getTitle() { if( description == null || description.getTitle() == null ){ return null; } return description.getTitle().toString(); } /** * Setter for property title. * * @param title New value of property title. */ public void setTitle(java.lang.String title) { this.description.setTitle( title != null ? new SimpleInternationalString(title) : null ); } public Filter getFilter() { return filter; } public void setFilter(Filter filter) { this.filter = filter; } public boolean isElseFilter() { return hasElseFilter; } /** * @deprecated use isElseFilter instead. */ @Deprecated public boolean hasElseFilter() { return hasElseFilter; } public void setIsElseFilter(boolean flag) { hasElseFilter = flag; } public void setElseFilter(boolean defaultb) { hasElseFilter = defaultb; } /** * * @deprecated use setIsElseFilter(true) */ @Deprecated public void setHasElseFilter() { hasElseFilter = true; } /** * Getter for property maxScaleDenominator. * * @return Value of property maxScaleDenominator. */ public double getMaxScaleDenominator() { return maxScaleDenominator; } /** * Setter for property maxScaleDenominator. * * @param maxScaleDenominator New value of property maxScaleDenominator. */ public void setMaxScaleDenominator(double maxScaleDenominator) { this.maxScaleDenominator = maxScaleDenominator; } /** * Getter for property minScaleDenominator. * * @return Value of property minScaleDenominator. */ public double getMinScaleDenominator() { return minScaleDenominator; } /** * Setter for property minScaleDenominator. * * @param minScaleDenominator New value of property minScaleDenominator. */ public void setMinScaleDenominator(double minScaleDenominator) { this.minScaleDenominator = minScaleDenominator; } public Object accept(StyleVisitor visitor,Object data) { return visitor.visit(this,data); } public void accept(org.geotools.styling.StyleVisitor visitor) { visitor.visit(this); } /** * Creates a deep copy clone of the rule. * * @see org.geotools.styling.Rule#clone() */ public Object clone() { try { RuleImpl clone = (RuleImpl) super.clone(); clone.name = name; clone.description.setAbstract(description.getAbstract()); clone.description.setTitle(description.getTitle()); if( filter == null ){ clone.filter = null; }else{ DuplicatingFilterVisitor visitor = new DuplicatingFilterVisitor(); clone.filter = (Filter) filter.accept(visitor, CommonFactoryFinder.getFilterFactory2(null)); } clone.hasElseFilter = hasElseFilter; clone.legends = new ArrayList<Graphic>(legends); clone.symbolizers = new ArrayList<Symbolizer>(symbolizers); clone.maxScaleDenominator = maxScaleDenominator; clone.minScaleDenominator = minScaleDenominator; return clone; } catch (CloneNotSupportedException e) { throw new RuntimeException("This will never happen", e); } } /** * Generates a hashcode for the Rule. * * <p> * For complex styles this can be an expensive operation since the hash * code is computed using all the hashcodes of the object within the * style. * </p> * * @return The hashcode. */ public int hashCode() { final int PRIME = 1000003; int result = 0; result = (PRIME * result) + symbolizers.hashCode(); result = (PRIME * result) + legends.hashCode(); if (name != null) { result = (PRIME * result) + name.hashCode(); } if (description != null) { result = (PRIME * result) + description.hashCode(); } if (filter != null) { result = (PRIME * result) + filter.hashCode(); } result = (PRIME * result) + (hasElseFilter ? 1 : 0); long temp = Double.doubleToLongBits(maxScaleDenominator); result = (PRIME * result) + (int) (temp >>> 32); result = (PRIME * result) + (int) (temp & 0xFFFFFFFF); temp = Double.doubleToLongBits(minScaleDenominator); result = (PRIME * result) + (int) (temp >>> 32); result = (PRIME * result) + (int) (temp & 0xFFFFFFFF); return result; } /** * Compares this Rule with another for equality. * * <p> * Two RuleImpls are equal if all their properties are equal. * </p> * * <p> * For complex styles this can be an expensive operation since it checks * all objects for equality. * </p> * * @param oth The other rule to compare with. * * @return True if this and oth are equal. */ public boolean equals(Object oth) { if (this == oth) { return true; } if (oth instanceof RuleImpl) { RuleImpl other = (RuleImpl) oth; return Utilities.equals(name, other.name) && Utilities.equals(description, other.description) && Utilities.equals(filter, other.filter) && (hasElseFilter == other.hasElseFilter) && Utilities.equals(legends, other.legends) && Utilities.equals(symbolizers, other.symbolizers) && (Double.doubleToLongBits(maxScaleDenominator) == Double .doubleToLongBits(other.maxScaleDenominator)) && (Double.doubleToLongBits(minScaleDenominator) == Double .doubleToLongBits(other.minScaleDenominator)); } return false; } @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append( "<RuleImpl"); if( name != null ){ buf.append(":"); buf.append( name ); } buf.append("> "); buf.append( filter ); if( symbolizers != null ){ buf.append( "\n" ); for( Symbolizer symbolizer : symbolizers ){ buf.append( "\t"); buf.append( symbolizer ); buf.append( "\n"); } } return buf.toString(); } public OnLineResource getOnlineResource() { return online; } public void setOnlineResource(OnLineResource online) { this.online = online; } static RuleImpl cast(Rule rule) { if( rule == null ){ return null; } else if (rule instanceof RuleImpl){ return (RuleImpl) rule; } else { RuleImpl copy = new RuleImpl( rule ); // replace with casting ... return copy; } } }