    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    }