001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, 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 * PaintMap.java
029 * -------------
030 * (C) Copyright 2006, 2007, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * $Id: PaintMap.java,v 1.1.2.2 2007/01/17 10:08:19 mungady Exp $
036 *
037 * Changes:
038 * --------
039 * 27-Sep-2006 : Version 1 (DG);
040 * 17-Jan-2007 : Changed TreeMap to HashMap, so that different classes that
041 * implement Comparable can be used as keys (DG);
042 *
043 */
044
045 package org.jfree.chart;
046
047 import java.awt.Paint;
048 import java.io.IOException;
049 import java.io.ObjectInputStream;
050 import java.io.ObjectOutputStream;
051 import java.io.Serializable;
052 import java.util.HashMap;
053 import java.util.Iterator;
054 import java.util.Map;
055 import java.util.Set;
056
057 import org.jfree.io.SerialUtilities;
058 import org.jfree.util.PaintUtilities;
059
060 /**
061 * A storage structure that maps <code>Comparable</code> instances with
062 * <code>Paint</code> instances.
063 * <br><br>
064 * To support cloning and serialization, you should only use keys that are
065 * cloneable and serializable. Special handling for the <code>Paint</code>
066 * instances is included in this class.
067 *
068 * @since 1.0.3
069 */
070 public class PaintMap implements Cloneable, Serializable {
071
072 /** Storage for the keys and values. */
073 private transient Map store;
074
075 /**
076 * Creates a new (empty) map.
077 */
078 public PaintMap() {
079 this.store = new HashMap();
080 }
081
082 /**
083 * Returns the paint associated with the specified key, or
084 * <code>null</code>.
085 *
086 * @param key the key (<code>null</code> not permitted).
087 *
088 * @return The paint, or <code>null</code>.
089 *
090 * @throws IllegalArgumentException if <code>key</code> is
091 * <code>null</code>.
092 */
093 public Paint getPaint(Comparable key) {
094 if (key == null) {
095 throw new IllegalArgumentException("Null 'key' argument.");
096 }
097 return (Paint) this.store.get(key);
098 }
099
100 /**
101 * Returns <code>true</code> if the map contains the specified key, and
102 * <code>false</code> otherwise.
103 *
104 * @param key the key.
105 *
106 * @return <code>true</code> if the map contains the specified key, and
107 * <code>false</code> otherwise.
108 */
109 public boolean containsKey(Comparable key) {
110 return this.store.containsKey(key);
111 }
112
113 /**
114 * Adds a mapping between the specified <code>key</code> and
115 * <code>paint</code> values.
116 *
117 * @param key the key (<code>null</code> not permitted).
118 * @param paint the paint.
119 *
120 * @throws IllegalArgumentException if <code>key</code> is
121 * <code>null</code>.
122 */
123 public void put(Comparable key, Paint paint) {
124 if (key == null) {
125 throw new IllegalArgumentException("Null 'key' argument.");
126 }
127 this.store.put(key, paint);
128 }
129
130 /**
131 * Resets the map to empty.
132 */
133 public void clear() {
134 this.store.clear();
135 }
136
137 /**
138 * Tests this map for equality with an arbitrary object.
139 *
140 * @param obj the object (<code>null</code> permitted).
141 *
142 * @return A boolean.
143 */
144 public boolean equals(Object obj) {
145 if (obj == this) {
146 return true;
147 }
148 if (!(obj instanceof PaintMap)) {
149 return false;
150 }
151 PaintMap that = (PaintMap) obj;
152 if (this.store.size() != that.store.size()) {
153 return false;
154 }
155 Set keys = this.store.keySet();
156 Iterator iterator = keys.iterator();
157 while (iterator.hasNext()) {
158 Comparable key = (Comparable) iterator.next();
159 Paint p1 = getPaint(key);
160 Paint p2 = that.getPaint(key);
161 if (!PaintUtilities.equal(p1, p2)) {
162 return false;
163 }
164 }
165 return true;
166 }
167
168 /**
169 * Returns a clone of this <code>PaintMap</code>.
170 *
171 * @return A clone of this instance.
172 *
173 * @throws CloneNotSupportedException if any key is not cloneable.
174 */
175 public Object clone() throws CloneNotSupportedException {
176 // TODO: I think we need to make sure the keys are actually cloned,
177 // whereas the paint instances are always immutable so they're OK
178 return super.clone();
179 }
180
181 /**
182 * Provides serialization support.
183 *
184 * @param stream the output stream.
185 *
186 * @throws IOException if there is an I/O error.
187 */
188 private void writeObject(ObjectOutputStream stream) throws IOException {
189 stream.defaultWriteObject();
190 stream.writeInt(this.store.size());
191 Set keys = this.store.keySet();
192 Iterator iterator = keys.iterator();
193 while (iterator.hasNext()) {
194 Comparable key = (Comparable) iterator.next();
195 stream.writeObject(key);
196 Paint paint = getPaint(key);
197 SerialUtilities.writePaint(paint, stream);
198 }
199 }
200
201 /**
202 * Provides serialization support.
203 *
204 * @param stream the input stream.
205 *
206 * @throws IOException if there is an I/O error.
207 * @throws ClassNotFoundException if there is a classpath problem.
208 */
209 private void readObject(ObjectInputStream stream)
210 throws IOException, ClassNotFoundException {
211 stream.defaultReadObject();
212 this.store = new HashMap();
213 int keyCount = stream.readInt();
214 for (int i = 0; i < keyCount; i++) {
215 Comparable key = (Comparable) stream.readObject();
216 Paint paint = SerialUtilities.readPaint(stream);
217 this.store.put(key, paint);
218 }
219 }
220
221 }