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: // OpenGIS dependencies
020: import org.geotools.event.AbstractGTComponent;
021: import org.geotools.factory.CommonFactoryFinder;
022: import org.geotools.factory.GeoTools;
023: import org.opengis.filter.FilterFactory;
024: import org.opengis.filter.expression.Expression;
025: import org.opengis.util.Cloneable;
026:
027: /**
028: * DOCUMENT ME!
029: *
030: * @author Ian Turton, CCG
031: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/styling/MarkImpl.java $
032: * @version $Id: MarkImpl.java 27862 2007-11-12 19:51:19Z desruisseaux $
033: */
034: public class MarkImpl extends AbstractGTComponent implements Mark,
035: Cloneable {
036: /** The logger for the default core module. */
037: private static final java.util.logging.Logger LOGGER = org.geotools.util.logging.Logging
038: .getLogger("org.geotools.styling");
039:
040: //TODO: Make container ready
041: private final FilterFactory filterFactory;
042: private Fill fill;
043: private Stroke stroke;
044:
045: //Polygon shape;
046: private Expression wellKnownName = null;
047: private Expression rotation = null;
048: private Expression size = null;
049:
050: /**
051: * Creates a new instance of DefaultMark
052: */
053: public MarkImpl() {
054: this (CommonFactoryFinder.getFilterFactory(GeoTools
055: .getDefaultHints()));
056: }
057:
058: public MarkImpl(String name) {
059: this (CommonFactoryFinder.getFilterFactory(GeoTools
060: .getDefaultHints()));
061: LOGGER.fine("creating " + name + " type mark");
062: setWellKnownName(name);
063: }
064:
065: public MarkImpl(FilterFactory filterFactory) {
066: this .filterFactory = filterFactory;
067: LOGGER.fine("creating defaultMark");
068:
069: try {
070: StyleFactory sfac = new StyleFactoryImpl();
071: fill = sfac.getDefaultFill();
072: stroke = sfac.getDefaultStroke();
073:
074: wellKnownName = filterFactory.literal("square");
075: size = filterFactory.literal(new Integer(6));
076: rotation = filterFactory.literal(new Double(0.0));
077: } catch (org.geotools.filter.IllegalFilterException ife) {
078: severe("<init>", "Failed to build default mark: ", ife);
079: }
080: }
081:
082: /**
083: * Convenience method for logging a message with an exception.
084: *
085: * @param method DOCUMENT ME!
086: * @param message DOCUMENT ME!
087: * @param exception DOCUMENT ME!
088: */
089: private static void severe(final String method,
090: final String message, final Exception exception) {
091: final java.util.logging.LogRecord record = new java.util.logging.LogRecord(
092: java.util.logging.Level.SEVERE, message);
093: record.setSourceMethodName(method);
094: record.setThrown(exception);
095: LOGGER.log(record);
096: }
097:
098: /**
099: * This parameter defines which fill style to use when rendering the Mark.
100: *
101: * @return the Fill definition to use when rendering the Mark.
102: */
103: public Fill getFill() {
104: return fill;
105: }
106:
107: /**
108: * This paramterer defines which stroke style should be used when rendering
109: * the Mark.
110: *
111: * @return The Stroke definition to use when rendering the Mark.
112: */
113: public Stroke getStroke() {
114: return stroke;
115: }
116:
117: /**
118: * This parameter gives the well-known name of the shape of the mark.<br>
119: * Allowed names include at least "square", "circle", "triangle", "star",
120: * "cross" and "x" though renderers may draw a different symbol instead if
121: * they don't have a shape for all of these.<br>
122: *
123: * @return The well-known name of a shape. The default value is "square".
124: */
125: public Expression getWellKnownName() {
126: return wellKnownName;
127: }
128:
129: /**
130: * Setter for property fill.
131: *
132: * @param fill New value of property fill.
133: */
134: public void setFill(org.geotools.styling.Fill fill) {
135: Fill old = this .fill;
136: this .fill = fill;
137: fireChildChanged("fill", fill, old);
138: }
139:
140: /**
141: * Setter for property stroke.
142: *
143: * @param stroke New value of property stroke.
144: */
145: public void setStroke(Stroke stroke) {
146: Stroke old = this .stroke;
147: this .stroke = stroke;
148: fireChildChanged("stroke", stroke, old);
149: }
150:
151: public void setSize(Expression size) {
152: Expression old = this .size;
153: this .size = size;
154: fireChildChanged("size", size, old);
155: }
156:
157: public void setSize(int size) {
158: setSize(filterFactory.literal(size));
159: }
160:
161: /**
162: * Setter for property wellKnownName.
163: *
164: * @param wellKnownName New value of property wellKnownName.
165: */
166: public void setWellKnownName(Expression wellKnownName) {
167: LOGGER.entering("DefaultMark", "setWellKnownName");
168:
169: Expression old = this .wellKnownName;
170: this .wellKnownName = wellKnownName;
171:
172: fireChildChanged("wellKnownName", wellKnownName, old);
173: }
174:
175: public void setWellKnownName(String name) {
176: setWellKnownName(filterFactory.literal(name));
177: }
178:
179: public void setRotation(Expression rotation) {
180: Expression old = this .rotation;
181: this .rotation = rotation;
182: fireChildChanged("rotation", rotation, old);
183: }
184:
185: public void setRotation(double rotation) {
186: setRotation(filterFactory.literal(rotation));
187: }
188:
189: /**
190: * Getter for property size.
191: *
192: * @return Value of property size.
193: */
194: public Expression getSize() {
195: return size;
196: }
197:
198: /**
199: * Getter for property rotation.
200: *
201: * @return Value of property rotation.
202: */
203: public Expression getRotation() {
204: return rotation;
205: }
206:
207: public String toString() {
208: return wellKnownName.toString();
209: }
210:
211: public void accept(StyleVisitor visitor) {
212: visitor.visit(this );
213: }
214:
215: /**
216: * Creates a deep copy of the Mark.
217: *
218: * <p>
219: * Only the fill and stroke are cloned since Expressions should be
220: * immutable.
221: * </p>
222: *
223: * @see org.geotools.styling.Mark#clone()
224: */
225: public Object clone() {
226: try {
227: MarkImpl clone = (MarkImpl) super .clone();
228: if (fill != null) {
229: clone.fill = (Fill) ((Cloneable) fill).clone();
230: }
231: if (stroke != null) {
232: clone.stroke = (Stroke) stroke.clone();
233: }
234:
235: return clone;
236: } catch (CloneNotSupportedException e) {
237: // this will never happen
238: throw new RuntimeException("Failed to clone MarkImpl");
239: }
240: }
241:
242: /**
243: * The hashcode override for the MarkImpl.
244: *
245: * @return the Hashcode.
246: */
247: public int hashCode() {
248: final int PRIME = 1000003;
249: int result = 0;
250:
251: if (fill != null) {
252: result = (PRIME * result) + fill.hashCode();
253: }
254:
255: if (stroke != null) {
256: result = (PRIME * result) + stroke.hashCode();
257: }
258:
259: if (wellKnownName != null) {
260: result = (PRIME * result) + wellKnownName.hashCode();
261: }
262:
263: if (rotation != null) {
264: result = (PRIME * result) + rotation.hashCode();
265: }
266:
267: if (size != null) {
268: result = (PRIME * result) + size.hashCode();
269: }
270:
271: return result;
272: }
273:
274: /**
275: * Compares this MarkImpl with another for equality.
276: *
277: * <p>
278: * Two MarkImpls are equal if they have the same well Known Name, the same
279: * size and rotation and the same stroke and fill.
280: * </p>
281: *
282: * @param oth The Other MarkImpl to compare with.
283: *
284: * @return True if this and oth are equal.
285: */
286: public boolean equals(Object oth) {
287: if (this == oth) {
288: return true;
289: }
290:
291: if (oth == null) {
292: return false;
293: }
294:
295: if (oth.getClass() != getClass()) {
296: return false;
297: }
298:
299: MarkImpl other = (MarkImpl) oth;
300:
301: // check expressions first - easiest
302: if (this .wellKnownName == null) {
303: if (other.wellKnownName != null) {
304: return false;
305: }
306: } else {
307: if (!this .wellKnownName.equals(other.wellKnownName)) {
308: return false;
309: }
310: }
311:
312: if (this .rotation == null) {
313: if (other.rotation != null) {
314: return false;
315: }
316: } else {
317: if (!this .rotation.equals(other.rotation)) {
318: return false;
319: }
320: }
321:
322: if (this .size == null) {
323: if (other.size != null) {
324: return false;
325: }
326: } else {
327: if (!this .size.equals(other.size)) {
328: return false;
329: }
330: }
331:
332: if (this .fill == null) {
333: if (other.fill != null) {
334: return false;
335: }
336: } else {
337: if (!this .fill.equals(other.fill)) {
338: return false;
339: }
340: }
341:
342: if (this .stroke == null) {
343: if (other.stroke != null) {
344: return false;
345: }
346: } else {
347: if (!this .stroke.equals(other.stroke)) {
348: return false;
349: }
350: }
351:
352: return true;
353: }
354: }
|