001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2002, Centre for Computational Geography
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.styling;
018:
019: import org.geotools.event.AbstractGTComponent;
020: import org.geotools.event.GTList;
021: import org.opengis.filter.Filter;
022: import org.geotools.resources.Utilities;
023: import org.opengis.util.Cloneable;
024:
025: // J2SE dependencies
026: import java.util.Arrays;
027: import java.util.List;
028:
029: /**
030: * Provides the default implementation of Rule.
031: *
032: * @author James Macgill
033: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/styling/RuleImpl.java $
034: * @version $Id: RuleImpl.java 25848 2007-06-14 23:01:57Z saul.farber $
035: */
036: public class RuleImpl extends AbstractGTComponent implements Rule,
037: Cloneable {
038: private List symbolizers = new GTList(this , "symbolizers");
039: private List graphics = new GTList(this , "graphics");
040: private String name;
041: private String title;
042: private String abstractStr;
043: private Filter filter = null;
044: private boolean hasElseFilter = false;
045: private double maxScaleDenominator = Double.POSITIVE_INFINITY;
046: private double minScaleDenominator = 0.0;
047:
048: /**
049: * Creates a new instance of DefaultRule
050: */
051: protected RuleImpl() {
052: }
053:
054: /**
055: * Creates a new instance of DefaultRule
056: *
057: * @param symbolizers DOCUMENT ME!
058: */
059: protected RuleImpl(Symbolizer[] symbolizers) {
060: this .symbolizers.addAll(Arrays.asList(symbolizers));
061: }
062:
063: public Graphic[] getLegendGraphic() {
064: return (Graphic[]) graphics.toArray(new Graphic[0]);
065: }
066:
067: public void addLegendGraphic(Graphic graphic) {
068: graphics.add(graphic);
069: }
070:
071: /**
072: * A set of equivalent Graphics in different formats which can be used as a
073: * legend against features stylized by the symbolizers in this rule.
074: *
075: * @param graphics An array of Graphic objects, any of which can be used as
076: * the legend.
077: */
078: public void setLegendGraphic(Graphic[] graphics) {
079: List graphicList = Arrays.asList(graphics);
080:
081: this .graphics.clear();
082: this .graphics.addAll(graphicList);
083: }
084:
085: public void addSymbolizer(Symbolizer symb) {
086: this .symbolizers.add(symb);
087: }
088:
089: public void setSymbolizers(Symbolizer[] syms) {
090: List symbols = Arrays.asList(syms);
091: this .symbolizers.clear();
092: this .symbolizers.addAll(symbols);
093: }
094:
095: public Symbolizer[] getSymbolizers() {
096: return (Symbolizer[]) symbolizers
097: .toArray(new Symbolizer[symbolizers.size()]);
098: }
099:
100: /**
101: * Getter for property abstractStr.
102: *
103: * @return Value of property abstractStr.
104: */
105: public java.lang.String getAbstract() {
106: return abstractStr;
107: }
108:
109: /**
110: * Setter for property abstractStr.
111: *
112: * @param abstractStr New value of property abstractStr.
113: */
114: public void setAbstract(java.lang.String abstractStr) {
115: this .abstractStr = abstractStr;
116: fireChanged();
117: }
118:
119: /**
120: * Getter for property name.
121: *
122: * @return Value of property name.
123: */
124: public java.lang.String getName() {
125: return name;
126: }
127:
128: /**
129: * Setter for property name.
130: *
131: * @param name New value of property name.
132: */
133: public void setName(java.lang.String name) {
134: this .name = name;
135: fireChanged();
136: }
137:
138: /**
139: * Getter for property title.
140: *
141: * @return Value of property title.
142: */
143: public java.lang.String getTitle() {
144: return title;
145: }
146:
147: /**
148: * Setter for property title.
149: *
150: * @param title New value of property title.
151: */
152: public void setTitle(java.lang.String title) {
153: this .title = title;
154: fireChanged();
155: }
156:
157: public Filter getFilter() {
158: return filter;
159: }
160:
161: public void setFilter(Filter filter) {
162: Filter old = this .filter;
163: this .filter = filter;
164: fireChildChanged("filter", filter, old);
165: }
166:
167: public boolean hasElseFilter() {
168: return hasElseFilter;
169: }
170:
171: public void setIsElseFilter(boolean flag) {
172: hasElseFilter = flag;
173: fireChanged();
174: }
175:
176: public void setHasElseFilter() {
177: hasElseFilter = true;
178: fireChanged();
179: }
180:
181: /**
182: * Getter for property maxScaleDenominator.
183: *
184: * @return Value of property maxScaleDenominator.
185: */
186: public double getMaxScaleDenominator() {
187: return maxScaleDenominator;
188: }
189:
190: /**
191: * Setter for property maxScaleDenominator.
192: *
193: * @param maxScaleDenominator New value of property maxScaleDenominator.
194: */
195: public void setMaxScaleDenominator(double maxScaleDenominator) {
196: this .maxScaleDenominator = maxScaleDenominator;
197: fireChanged();
198: }
199:
200: /**
201: * Getter for property minScaleDenominator.
202: *
203: * @return Value of property minScaleDenominator.
204: */
205: public double getMinScaleDenominator() {
206: return minScaleDenominator;
207: }
208:
209: /**
210: * Setter for property minScaleDenominator.
211: *
212: * @param minScaleDenominator New value of property minScaleDenominator.
213: */
214: public void setMinScaleDenominator(double minScaleDenominator) {
215: this .minScaleDenominator = minScaleDenominator;
216: fireChanged();
217: }
218:
219: public void accept(StyleVisitor visitor) {
220: visitor.visit(this );
221: }
222:
223: /**
224: * Creates a deep copy clone of the rule.
225: *
226: * @see org.geotools.styling.Rule#clone()
227: */
228: public Object clone() {
229: try {
230: RuleImpl clone = (RuleImpl) super .clone();
231: clone.graphics = new GTList(clone, "graphics");
232: clone.symbolizers = new GTList(clone, "symbolizers");
233: clone.filter = filter; // TODO: we must duplicate!
234:
235: Graphic[] legends = new Graphic[graphics.size()];
236:
237: for (int i = 0; i < legends.length; i++) {
238: Graphic legend = (Graphic) graphics.get(i);
239: legends[i] = (Graphic) ((Cloneable) legend).clone();
240: }
241:
242: clone.setLegendGraphic(legends);
243:
244: Symbolizer[] symbArray = new Symbolizer[symbolizers.size()];
245:
246: for (int i = 0; i < symbArray.length; i++) {
247: Symbolizer symb = (Symbolizer) symbolizers.get(i);
248: symbArray[i] = (Symbolizer) ((Cloneable) symb).clone();
249: }
250:
251: clone.setSymbolizers(symbArray);
252:
253: return clone;
254: } catch (CloneNotSupportedException e) {
255: throw new RuntimeException("This will never happen", e);
256: }
257: }
258:
259: /**
260: * Generates a hashcode for the Rule.
261: *
262: * <p>
263: * For complex styles this can be an expensive operation since the hash
264: * code is computed using all the hashcodes of the object within the
265: * style.
266: * </p>
267: *
268: * @return The hashcode.
269: */
270: public int hashCode() {
271: final int PRIME = 1000003;
272: int result = 0;
273: result = (PRIME * result) + symbolizers.hashCode();
274:
275: if (graphics != null) {
276: result = (PRIME * result) + graphics.hashCode();
277: }
278:
279: if (name != null) {
280: result = (PRIME * result) + name.hashCode();
281: }
282:
283: if (title != null) {
284: result = (PRIME * result) + title.hashCode();
285: }
286:
287: if (abstractStr != null) {
288: result = (PRIME * result) + abstractStr.hashCode();
289: }
290:
291: if (filter != null) {
292: result = (PRIME * result) + filter.hashCode();
293: }
294:
295: result = (PRIME * result) + (hasElseFilter ? 1 : 0);
296:
297: long temp = Double.doubleToLongBits(maxScaleDenominator);
298: result = (PRIME * result) + (int) (temp >>> 32);
299: result = (PRIME * result) + (int) (temp & 0xFFFFFFFF);
300: temp = Double.doubleToLongBits(minScaleDenominator);
301: result = (PRIME * result) + (int) (temp >>> 32);
302: result = (PRIME * result) + (int) (temp & 0xFFFFFFFF);
303:
304: return result;
305: }
306:
307: /**
308: * Compares this Rule with another for equality.
309: *
310: * <p>
311: * Two RuleImpls are equal if all their properties are equal.
312: * </p>
313: *
314: * <p>
315: * For complex styles this can be an expensive operation since it checks
316: * all objects for equality.
317: * </p>
318: *
319: * @param oth The other rule to compare with.
320: *
321: * @return True if this and oth are equal.
322: */
323: public boolean equals(Object oth) {
324: if (this == oth) {
325: return true;
326: }
327:
328: if (oth instanceof RuleImpl) {
329: RuleImpl other = (RuleImpl) oth;
330:
331: return Utilities.equals(name, other.name)
332: && Utilities.equals(title, other.title)
333: && Utilities.equals(abstractStr, other.abstractStr)
334: && Utilities.equals(filter, other.filter)
335: && (hasElseFilter == other.hasElseFilter)
336: && Utilities.equals(graphics, other.graphics)
337: && Utilities.equals(symbolizers, other.symbolizers)
338: && (Double.doubleToLongBits(maxScaleDenominator) == Double
339: .doubleToLongBits(other.maxScaleDenominator))
340: && (Double.doubleToLongBits(minScaleDenominator) == Double
341: .doubleToLongBits(other.minScaleDenominator));
342: }
343:
344: return false;
345: }
346: }
|