    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2008, 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-2008, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * Changes:
    036     * --------
    037     * 27-Sep-2006 : Version 1 (DG);
    038     * 17-Jan-2007 : Changed TreeMap to HashMap, so that different classes that
    039     *               implement Comparable can be used as keys (DG);
    040     *
    041     */
    042
    043    package org.jfree.chart;
    044
    045    import java.awt.Paint;
    046    import java.io.IOException;
    047    import java.io.ObjectInputStream;
    048    import java.io.ObjectOutputStream;
    049    import java.io.Serializable;
    050    import java.util.HashMap;
    051    import java.util.Iterator;
    052    import java.util.Map;
    053    import java.util.Set;
    054
    055    import org.jfree.io.SerialUtilities;
    056    import org.jfree.util.PaintUtilities;
    057
    058    /**
    059     * A storage structure that maps <code>Comparable</code> instances with
    060     * <code>Paint</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>Paint</code>
    064     * instances is included in this class.
    065     *
    066     * @since 1.0.3
    067     */
    068    public class PaintMap implements Cloneable, Serializable {
    069
    070        /** For serialization. */
    071        static final long serialVersionUID = -4639833772123069274L;
    072
    073        /** Storage for the keys and values. */
    074        private transient Map store;
    075
    076        /**
    077         * Creates a new (empty) map.
    078         */
    079        public PaintMap() {
    080            this.store = new HashMap();
    081        }
    082
    083        /**
    084         * Returns the paint associated with the specified key, or
    085         * <code>null</code>.
    086         *
    087         * @param key  the key (<code>null</code> not permitted).
    088         *
    089         * @return The paint, or <code>null</code>.
    090         *
    091         * @throws IllegalArgumentException if <code>key</code> is
    092         *     <code>null</code>.
    093         */
    094        public Paint getPaint(Comparable key) {
    095            if (key == null) {
    096                throw new IllegalArgumentException("Null 'key' argument.");
    097            }
    098            return (Paint) this.store.get(key);
    099        }
    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         */
    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         */
    124        public void put(Comparable key, Paint paint) {
    125            if (key == null) {
    126                throw new IllegalArgumentException("Null 'key' argument.");
    127            }
    128            this.store.put(key, paint);
    129        }
    130
    131        /**
    132         * Resets the map to empty.
    133         */
    134        public void clear() {
    135            this.store.clear();
    136        }
    137
    138        /**
    139         * Tests this map for equality with an arbitrary object.
    140         *
    141         * @param obj  the object (<code>null</code> permitted).
    142         *
    143         * @return A boolean.
    144         */
    145        public boolean equals(Object obj) {
    146            if (obj == this) {
    147                return true;
    148            }
    149            if (!(obj instanceof PaintMap)) {
    150                return false;
    151            }
    152            PaintMap that = (PaintMap) obj;
    153            if (this.store.size() != that.store.size()) {
    154                return false;
    155            }
    156            Set keys = this.store.keySet();
    157            Iterator iterator = keys.iterator();
    158            while (iterator.hasNext()) {
    159                Comparable key = (Comparable) iterator.next();
    160                Paint p1 = getPaint(key);
    161                Paint p2 = that.getPaint(key);
    162                if (!PaintUtilities.equal(p1, p2)) {
    163                    return false;
    164                }
    165            }
    166            return true;
    167        }
    168
    169        /**
    170         * Returns a clone of this <code>PaintMap</code>.
    171         *
    172         * @return A clone of this instance.
    173         *
    174         * @throws CloneNotSupportedException if any key is not cloneable.
    175         */
    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         */
    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         */
    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    }