    001/* ===========================================================
    002 * JFreeChart : a free chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C) Copyright 2000-2011, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    025 * Other names may be trademarks of their respective owners.]
    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
    043package org.jfree.chart;
    044
    045import java.awt.Paint;
    046import java.io.IOException;
    047import java.io.ObjectInputStream;
    048import java.io.ObjectOutputStream;
    049import java.io.Serializable;
    050import java.util.HashMap;
    051import java.util.Iterator;
    052import java.util.Map;
    053import java.util.Set;
    054
    055import org.jfree.io.SerialUtilities;
    056import 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 */
    068public 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}