001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2022, by David Gilbert 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-2021, by Richard Atkinson and Contributors. 031 * 032 * Original Author: Richard Atkinson; 033 * Contributors: David Gilbert; 034 * Cleland Early; 035 * 036 */ 037 038package org.jfree.chart.urls; 039 040import java.io.Serializable; 041import java.io.UnsupportedEncodingException; 042import java.net.URLEncoder; 043import java.util.Objects; 044 045import org.jfree.chart.internal.Args; 046 047import org.jfree.data.category.CategoryDataset; 048 049/** 050 * A URL generator that can be assigned to a 051 * {@link org.jfree.chart.renderer.category.CategoryItemRenderer}. 052 */ 053public class StandardCategoryURLGenerator implements CategoryURLGenerator, 054 Cloneable, Serializable { 055 056 /** For serialization. */ 057 private static final long serialVersionUID = 2276668053074881909L; 058 059 /** Prefix to the URL */ 060 private String prefix = "index.html"; 061 062 /** Series parameter name to go in each URL */ 063 private String seriesParameterName = "series"; 064 065 /** Category parameter name to go in each URL */ 066 private String categoryParameterName = "category"; 067 068 /** 069 * Creates a new generator with default settings. 070 */ 071 public StandardCategoryURLGenerator() { 072 super(); 073 } 074 075 /** 076 * Constructor that overrides default prefix to the URL. 077 * 078 * @param prefix the prefix to the URL ({@code null} not permitted). 079 */ 080 public StandardCategoryURLGenerator(String prefix) { 081 Args.nullNotPermitted(prefix, "prefix"); 082 this.prefix = prefix; 083 } 084 085 /** 086 * Constructor that overrides all the defaults. 087 * 088 * @param prefix the prefix to the URL ({@code null} not permitted). 089 * @param seriesParameterName the name of the series parameter to go in 090 * each URL ({@code null} not permitted). 091 * @param categoryParameterName the name of the category parameter to go in 092 * each URL ({@code null} not permitted). 093 */ 094 public StandardCategoryURLGenerator(String prefix, 095 String seriesParameterName, String categoryParameterName) { 096 097 Args.nullNotPermitted(prefix, "prefix"); 098 Args.nullNotPermitted(seriesParameterName, 099 "seriesParameterName"); 100 Args.nullNotPermitted(categoryParameterName, 101 "categoryParameterName"); 102 this.prefix = prefix; 103 this.seriesParameterName = seriesParameterName; 104 this.categoryParameterName = categoryParameterName; 105 106 } 107 108 /** 109 * Generates a URL for a particular item within a series. 110 * 111 * @param dataset the dataset. 112 * @param series the series index (zero-based). 113 * @param category the category index (zero-based). 114 * 115 * @return The generated URL. 116 */ 117 @Override 118 public String generateURL(CategoryDataset dataset, int series, 119 int category) { 120 String url = this.prefix; 121 Comparable seriesKey = dataset.getRowKey(series); 122 Comparable categoryKey = dataset.getColumnKey(category); 123 boolean firstParameter = !url.contains("?"); 124 url += firstParameter ? "?" : "&"; 125 try { 126 url += this.seriesParameterName + "=" + URLEncoder.encode( 127 seriesKey.toString(), "UTF-8"); 128 url += "&" + this.categoryParameterName + "=" 129 + URLEncoder.encode(categoryKey.toString(), "UTF-8"); 130 } catch (UnsupportedEncodingException ex) { 131 throw new RuntimeException(ex); // this won't happen :) 132 } 133 return url; 134 } 135 136 /** 137 * Returns an independent copy of the URL generator. 138 * 139 * @return A clone. 140 * 141 * @throws CloneNotSupportedException not thrown by this class, but 142 * subclasses (if any) might. 143 */ 144 @Override 145 public Object clone() throws CloneNotSupportedException { 146 // all attributes are immutable, so we can just return the super.clone() 147 // FIXME: in fact, the generator itself is immutable, so cloning is 148 // not necessary 149 return super.clone(); 150 } 151 152 /** 153 * Tests the generator for equality with an arbitrary object. 154 * 155 * @param obj the object ({@code null} permitted). 156 * 157 * @return A boolean. 158 */ 159 @Override 160 public boolean equals(Object obj) { 161 if (obj == this) { 162 return true; 163 } 164 if (!(obj instanceof StandardCategoryURLGenerator)) { 165 return false; 166 } 167 StandardCategoryURLGenerator that = (StandardCategoryURLGenerator) obj; 168 if (!Objects.equals(this.prefix, that.prefix)) { 169 return false; 170 } 171 172 if (!Objects.equals(this.seriesParameterName, that.seriesParameterName)) { 173 return false; 174 } 175 if (!Objects.equals(this.categoryParameterName, that.categoryParameterName)) { 176 return false; 177 } 178 return true; 179 } 180 181 /** 182 * Returns a hash code. 183 * 184 * @return A hash code. 185 */ 186 @Override 187 public int hashCode() { 188 int result; 189 result = (this.prefix != null ? this.prefix.hashCode() : 0); 190 result = 29 * result 191 + (this.seriesParameterName != null 192 ? this.seriesParameterName.hashCode() : 0); 193 result = 29 * result 194 + (this.categoryParameterName != null 195 ? this.categoryParameterName.hashCode() : 0); 196 return result; 197 } 198 199}