001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * --------------
028 * StrokeMap.java
029 * --------------
030 * (C) Copyright 2006, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * $Id: StrokeMap.java,v 1.1.2.1 2006/09/27 17:06:59 mungady Exp $
036 *
037 * Changes:
038 * --------
039 * 27-Sep-2006 : Version 1 (DG);
040 *
041 */
042
043 package org.jfree.chart;
044
045 import java.awt.Stroke;
046 import java.io.IOException;
047 import java.io.ObjectInputStream;
048 import java.io.ObjectOutputStream;
049 import java.io.Serializable;
050 import java.util.Iterator;
051 import java.util.Map;
052 import java.util.Set;
053 import java.util.TreeMap;
054
055 import org.jfree.io.SerialUtilities;
056 import org.jfree.util.ObjectUtilities;
057
058 /**
059 * A storage structure that maps <code>Comparable</code> instances with
060 * <code>Stroke</code> instances.
061 * <br><br>
062 * To support cloning and serialization, you should only use keys that are
063 * cloneable and serializable. Special handling for the <code>Stroke</code>
064 * instances is included in this class.
065 *
066 * @since 1.0.3
067 */
068 public class StrokeMap implements Cloneable, Serializable {
069
070 /** Storage for the keys and values. */
071 private transient Map store;
072
073 /**
074 * Creates a new (empty) map.
075 */
076 public StrokeMap() {
077 this.store = new TreeMap();
078 }
079
080 /**
081 * Returns the stroke associated with the specified key, or
082 * <code>null</code>.
083 *
084 * @param key the key (<code>null</code> not permitted).
085 *
086 * @return The stroke, or <code>null</code>.
087 *
088 * @throws IllegalArgumentException if <code>key</code> is
089 * <code>null</code>.
090 */
091 public Stroke getStroke(Comparable key) {
092 if (key == null) {
093 throw new IllegalArgumentException("Null 'key' argument.");
094 }
095 return (Stroke) this.store.get(key);
096 }
097
098 /**
099 * Returns <code>true</code> if the map contains the specified key, and
100 * <code>false</code> otherwise.
101 *
102 * @param key the key.
103 *
104 * @return <code>true</code> if the map contains the specified key, and
105 * <code>false</code> otherwise.
106 */
107 public boolean containsKey(Comparable key) {
108 return this.store.containsKey(key);
109 }
110
111 /**
112 * Adds a mapping between the specified <code>key</code> and
113 * <code>stroke</code> values.
114 *
115 * @param key the key (<code>null</code> not permitted).
116 * @param stroke the stroke.
117 */
118 public void put(Comparable key, Stroke stroke) {
119 if (key == null) {
120 throw new IllegalArgumentException("Null 'key' argument.");
121 }
122 this.store.put(key, stroke);
123 }
124
125 /**
126 * Resets the map to empty.
127 */
128 public void clear() {
129 this.store.clear();
130 }
131
132 /**
133 * Tests this map for equality with an arbitrary object.
134 *
135 * @param obj the object (<code>null</code> permitted).
136 *
137 * @return A boolean.
138 */
139 public boolean equals(Object obj) {
140 if (obj == this) {
141 return true;
142 }
143 if (!(obj instanceof StrokeMap)) {
144 return false;
145 }
146 StrokeMap that = (StrokeMap) obj;
147 if (this.store.size() != that.store.size()) {
148 return false;
149 }
150 Set keys = this.store.keySet();
151 Iterator iterator = keys.iterator();
152 while (iterator.hasNext()) {
153 Comparable key = (Comparable) iterator.next();
154 Stroke s1 = getStroke(key);
155 Stroke s2 = that.getStroke(key);
156 if (!ObjectUtilities.equal(s1, s2)) {
157 return false;
158 }
159 }
160 return true;
161 }
162
163 /**
164 * Returns a clone of this <code>StrokeMap</code>.
165 *
166 * @return A clone of this instance.
167 *
168 * @throws CloneNotSupportedException if any key is not cloneable.
169 */
170 public Object clone() throws CloneNotSupportedException {
171 // TODO: I think we need to make sure the keys are actually cloned,
172 // whereas the stroke instances are always immutable so they're OK
173 return super.clone();
174 }
175
176 /**
177 * Provides serialization support.
178 *
179 * @param stream the output stream.
180 *
181 * @throws IOException if there is an I/O error.
182 */
183 private void writeObject(ObjectOutputStream stream) throws IOException {
184 stream.defaultWriteObject();
185 stream.writeInt(this.store.size());
186 Set keys = this.store.keySet();
187 Iterator iterator = keys.iterator();
188 while (iterator.hasNext()) {
189 Comparable key = (Comparable) iterator.next();
190 stream.writeObject(key);
191 Stroke stroke = getStroke(key);
192 SerialUtilities.writeStroke(stroke, stream);
193 }
194 }
195
196 /**
197 * Provides serialization support.
198 *
199 * @param stream the input stream.
200 *
201 * @throws IOException if there is an I/O error.
202 * @throws ClassNotFoundException if there is a classpath problem.
203 */
204 private void readObject(ObjectInputStream stream)
205 throws IOException, ClassNotFoundException {
206 stream.defaultReadObject();
207 this.store = new TreeMap();
208 int keyCount = stream.readInt();
209 for (int i = 0; i < keyCount; i++) {
210 Comparable key = (Comparable) stream.readObject();
211 Stroke stroke = SerialUtilities.readStroke(stream);
212 this.store.put(key, stroke);
213 }
214 }
215
216 }