    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 * StandardCategoryURLGenerator.java
    029 * ---------------------------------
    030 * (C) Copyright 2002-2008, by Richard Atkinson and Contributors.
    031 *
    032 * Original Author:  Richard Atkinson;
    033 * Contributors:     David Gilbert (for Object Refinery Limited);
    034 *                   Cleland Early;
    035 *
    036 * Changes:
    037 * --------
    038 * 05-Aug-2002 : Version 1, contributed by Richard Atkinson;
    039 * 29-Aug-2002 : Reversed seriesParameterName and itemParameterName in
    040 *               constructor.  Never should have been the other way round.
    041 *               Also updated JavaDoc (RA);
    042 * 09-Oct-2002 : Fixed errors reported by Checkstyle (DG);
    043 * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
    044 * 23-Mar-2003 : Implemented Serializable (DG);
    045 * 13-Aug-2003 : Implemented Cloneable (DG);
    046 * 23-Dec-2003 : Added fix for bug 861282 (DG);
    047 * 21-May-2004 : Added URL encoding - see patch 947854 (DG);
    048 * 13-Jan-2004 : Fixed for compliance with XHTML 1.0 (DG);
    049 * ------------- JFREECHART 1.0.x ---------------------------------------------
    050 * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
    051 * 17-Apr-2007 : Use new URLUtilities class to encode URLs (DG);
    052 *
    053 */
    054
    055package org.jfree.chart.urls;
    056
    057import java.io.Serializable;
    058
    059import org.jfree.data.category.CategoryDataset;
    060import org.jfree.util.ObjectUtilities;
    061
    062/**
    063 * A URL generator that can be assigned to a
    064 * {@link org.jfree.chart.renderer.category.CategoryItemRenderer}.
    065 */
    066public class StandardCategoryURLGenerator implements CategoryURLGenerator,
    067        Cloneable, Serializable {
    068
    069    /** For serialization. */
    070    private static final long serialVersionUID = 2276668053074881909L;
    071
    072    /** Prefix to the URL */
    073    private String prefix = "index.html";
    074
    075    /** Series parameter name to go in each URL */
    076    private String seriesParameterName = "series";
    077
    078    /** Category parameter name to go in each URL */
    079    private String categoryParameterName = "category";
    080
    081    /**
    082     * Creates a new generator with default settings.
    083     */
    084    public StandardCategoryURLGenerator() {
    085        super();
    086    }
    087
    088    /**
    089     * Constructor that overrides default prefix to the URL.
    090     *
    091     * @param prefix  the prefix to the URL (<code>null</code> not permitted).
    092     */
    093    public StandardCategoryURLGenerator(String prefix) {
    094        if (prefix == null) {
    095            throw new IllegalArgumentException("Null 'prefix' argument.");
    096        }
    097        this.prefix = prefix;
    098    }
    099
    100    /**
    101     * Constructor that overrides all the defaults.
    102     *
    103     * @param prefix  the prefix to the URL (<code>null</code> not permitted).
    104     * @param seriesParameterName  the name of the series parameter to go in
    105     *                             each URL (<code>null</code> not permitted).
    106     * @param categoryParameterName  the name of the category parameter to go in
    107     *                               each URL (<code>null</code> not permitted).
    108     */
    109    public StandardCategoryURLGenerator(String prefix,
    110                                        String seriesParameterName,
    111                                        String categoryParameterName) {
    112
    113        if (prefix == null) {
    114            throw new IllegalArgumentException("Null 'prefix' argument.");
    115        }
    116        if (seriesParameterName == null) {
    117            throw new IllegalArgumentException(
    118                    "Null 'seriesParameterName' argument.");
    119        }
    120        if (categoryParameterName == null) {
    121            throw new IllegalArgumentException(
    122                    "Null 'categoryParameterName' argument.");
    123        }
    124        this.prefix = prefix;
    125        this.seriesParameterName = seriesParameterName;
    126        this.categoryParameterName = categoryParameterName;
    127
    128    }
    129
    130    /**
    131     * Generates a URL for a particular item within a series.
    132     *
    133     * @param dataset  the dataset.
    134     * @param series  the series index (zero-based).
    135     * @param category  the category index (zero-based).
    136     *
    137     * @return The generated URL.
    138     */
    139    public String generateURL(CategoryDataset dataset, int series,
    140                              int category) {
    141        String url = this.prefix;
    142        Comparable seriesKey = dataset.getRowKey(series);
    143        Comparable categoryKey = dataset.getColumnKey(category);
    144        boolean firstParameter = url.indexOf("?") == -1;
    145        url += firstParameter ? "?" : "&amp;";
    146        url += this.seriesParameterName + "=" + URLUtilities.encode(
    147                seriesKey.toString(), "UTF-8");
    148        url += "&amp;" + this.categoryParameterName + "="
    149                + URLUtilities.encode(categoryKey.toString(), "UTF-8");
    150        return url;
    151    }
    152
    153    /**
    154     * Returns an independent copy of the URL generator.
    155     *
    156     * @return A clone.
    157     *
    158     * @throws CloneNotSupportedException not thrown by this class, but
    159     *         subclasses (if any) might.
    160     */
    161    public Object clone() throws CloneNotSupportedException {
    162        // all attributes are immutable, so we can just return the super.clone()
    163        // FIXME: in fact, the generator itself is immutable, so cloning is
    164        // not necessary
    165        return super.clone();
    166    }
    167
    168    /**
    169     * Tests the generator for equality with an arbitrary object.
    170     *
    171     * @param obj  the object (<code>null</code> permitted).
    172     *
    173     * @return A boolean.
    174     */
    175    public boolean equals(Object obj) {
    176        if (obj == this) {
    177            return true;
    178        }
    179        if (!(obj instanceof StandardCategoryURLGenerator)) {
    180            return false;
    181        }
    182        StandardCategoryURLGenerator that = (StandardCategoryURLGenerator) obj;
    183        if (!ObjectUtilities.equal(this.prefix, that.prefix)) {
    184            return false;
    185        }
    186
    187        if (!ObjectUtilities.equal(this.seriesParameterName,
    188                that.seriesParameterName)) {
    189            return false;
    190        }
    191        if (!ObjectUtilities.equal(this.categoryParameterName,
    192                that.categoryParameterName)) {
    193            return false;
    194        }
    195        return true;
    196    }
    197
    198    /**
    199     * Returns a hash code.
    200     *
    201     * @return A hash code.
    202     */
    203    public int hashCode() {
    204        int result;
    205        result = (this.prefix != null ? this.prefix.hashCode() : 0);
    206        result = 29 * result
    207            + (this.seriesParameterName != null
    208                    ? this.seriesParameterName.hashCode() : 0);
    209        result = 29 * result
    210            + (this.categoryParameterName != null
    211                    ? this.categoryParameterName.hashCode() : 0);
    212        return result;
    213    }
    214
    215}