1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors.
6  *
7  * Project Info:  http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
22  * USA.
23  *
24  * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
25  * Other names may be trademarks of their respective owners.]
26  *
27  * -------------
28  * PaintMap.java
29  * -------------
30  * (C) Copyright 2006-2013, by Object Refinery Limited.
31  *
32  * Original Author:  David Gilbert (for Object Refinery Limited);
33  * Contributor(s):   -;
34  *
35  * Changes:
36  * --------
37  * 27-Sep-2006 : Version 1 (DG);
38  * 17-Jan-2007 : Changed TreeMap to HashMap, so that different classes that
39  *               implement Comparable can be used as keys (DG);
40  * 02-Jul-2013 : Use ParamChecks class (DG);
41  *
42  */
43 
44 package org.jfree.chart;
45 
46 import java.awt.Paint;
47 import java.io.IOException;
48 import java.io.ObjectInputStream;
49 import java.io.ObjectOutputStream;
50 import java.io.Serializable;
51 import java.util.HashMap;
52 import java.util.Iterator;
53 import java.util.Map;
54 import java.util.Set;
55 import org.jfree.chart.util.ParamChecks;
56 
57 import org.jfree.io.SerialUtilities;
58 import org.jfree.util.PaintUtilities;
59 
60 /**
61  * A storage structure that maps <code>Comparable</code> instances with
62  * <code>Paint</code> instances.
63  * <br><br>
64  * To support cloning and serialization, you should only use keys that are
65  * cloneable and serializable.  Special handling for the <code>Paint</code>
66  * instances is included in this class.
67  *
68  * @since 1.0.3
69  */
70 public class PaintMap implements Cloneable, Serializable {
71 
72     /** For serialization. */
73     static final long serialVersionUID = -4639833772123069274L;
74 
75     /** Storage for the keys and values. */
76     private transient Map store;
77 
78     /**
79      * Creates a new (empty) map.
80      */
PaintMap()81     public PaintMap() {
82         this.store = new HashMap();
83     }
84 
85     /**
86      * Returns the paint associated with the specified key, or
87      * <code>null</code>.
88      *
89      * @param key  the key (<code>null</code> not permitted).
90      *
91      * @return The paint, or <code>null</code>.
92      *
93      * @throws IllegalArgumentException if <code>key</code> is
94      *     <code>null</code>.
95      */
getPaint(Comparable key)96     public Paint getPaint(Comparable key) {
97         ParamChecks.nullNotPermitted(key, "key");
98         return (Paint) this.store.get(key);
99     }
100 
101     /**
102      * Returns <code>true</code> if the map contains the specified key, and
103      * <code>false</code> otherwise.
104      *
105      * @param key  the key.
106      *
107      * @return <code>true</code> if the map contains the specified key, and
108      * <code>false</code> otherwise.
109      */
containsKey(Comparable key)110     public boolean containsKey(Comparable key) {
111         return this.store.containsKey(key);
112     }
113 
114     /**
115      * Adds a mapping between the specified <code>key</code> and
116      * <code>paint</code> values.
117      *
118      * @param key  the key (<code>null</code> not permitted).
119      * @param paint  the paint.
120      *
121      * @throws IllegalArgumentException if <code>key</code> is
122      *     <code>null</code>.
123      */
put(Comparable key, Paint paint)124     public void put(Comparable key, Paint paint) {
125         ParamChecks.nullNotPermitted(key, "key");
126         this.store.put(key, paint);
127     }
128 
129     /**
130      * Resets the map to empty.
131      */
clear()132     public void clear() {
133         this.store.clear();
134     }
135 
136     /**
137      * Tests this map for equality with an arbitrary object.
138      *
139      * @param obj  the object (<code>null</code> permitted).
140      *
141      * @return A boolean.
142      */
143     @Override
equals(Object obj)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     @Override
clone()176     public Object clone() throws CloneNotSupportedException {
177         // TODO: I think we need to make sure the keys are actually cloned,
178         // whereas the paint instances are always immutable so they're OK
179         return super.clone();
180     }
181 
182     /**
183      * Provides serialization support.
184      *
185      * @param stream  the output stream.
186      *
187      * @throws IOException  if there is an I/O error.
188      */
writeObject(ObjectOutputStream stream)189     private void writeObject(ObjectOutputStream stream) throws IOException {
190         stream.defaultWriteObject();
191         stream.writeInt(this.store.size());
192         Set keys = this.store.keySet();
193         Iterator iterator = keys.iterator();
194         while (iterator.hasNext()) {
195             Comparable key = (Comparable) iterator.next();
196             stream.writeObject(key);
197             Paint paint = getPaint(key);
198             SerialUtilities.writePaint(paint, stream);
199         }
200     }
201 
202     /**
203      * Provides serialization support.
204      *
205      * @param stream  the input stream.
206      *
207      * @throws IOException  if there is an I/O error.
208      * @throws ClassNotFoundException  if there is a classpath problem.
209      */
readObject(ObjectInputStream stream)210     private void readObject(ObjectInputStream stream)
211             throws IOException, ClassNotFoundException {
212         stream.defaultReadObject();
213         this.store = new HashMap();
214         int keyCount = stream.readInt();
215         for (int i = 0; i < keyCount; i++) {
216             Comparable key = (Comparable) stream.readObject();
217             Paint paint = SerialUtilities.readPaint(stream);
218             this.store.put(key, paint);
219         }
220     }
221 
222 }
223