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 * MultipleXYSeriesLabelGenerator.java 029 * ----------------------------------- 030 * (C) Copyright 2004-2022, by David Gilbert. 031 * 032 * Original Author: David Gilbert; 033 * Contributor(s): -; 034 * 035 */ 036 037package org.jfree.chart.labels; 038 039import org.jfree.chart.api.PublicCloneable; 040import org.jfree.chart.internal.Args; 041import org.jfree.chart.internal.HashUtils; 042import org.jfree.data.xy.XYDataset; 043 044import java.io.Serializable; 045import java.text.MessageFormat; 046import java.util.HashMap; 047import java.util.List; 048import java.util.Map; 049import java.util.Set; 050 051/** 052 * A series label generator for plots that use data from 053 * an {@link org.jfree.data.xy.XYDataset}. 054 */ 055public class MultipleXYSeriesLabelGenerator implements XYSeriesLabelGenerator, 056 Cloneable, PublicCloneable, Serializable { 057 058 /** For serialization. */ 059 private static final long serialVersionUID = 138976236941898560L; 060 061 /** The default item label format. */ 062 public static final String DEFAULT_LABEL_FORMAT = "{0}"; 063 064 /** The format pattern for the initial part of the label. */ 065 private final String formatPattern; 066 067 /** The format pattern for additional labels. */ 068 private final String additionalFormatPattern; 069 070 /** Storage for the additional series labels. */ 071 private Map seriesLabelLists; 072 073 /** 074 * Creates an item label generator using default number formatters. 075 */ 076 public MultipleXYSeriesLabelGenerator() { 077 this(DEFAULT_LABEL_FORMAT); 078 } 079 080 /** 081 * Creates a new series label generator. 082 * 083 * @param format the format pattern ({@code null} not permitted). 084 */ 085 public MultipleXYSeriesLabelGenerator(String format) { 086 Args.nullNotPermitted(format, "format"); 087 this.formatPattern = format; 088 this.additionalFormatPattern = "\n{0}"; 089 this.seriesLabelLists = new HashMap(); 090 } 091 092 /** 093 * Adds an extra label for the specified series. 094 * 095 * @param series the series index. 096 * @param label the label. 097 */ 098 public void addSeriesLabel(int series, String label) { 099 Integer key = series; 100 List labelList = (List) this.seriesLabelLists.get(key); 101 if (labelList == null) { 102 labelList = new java.util.ArrayList(); 103 this.seriesLabelLists.put(key, labelList); 104 } 105 labelList.add(label); 106 } 107 108 /** 109 * Clears the extra labels for the specified series. 110 * 111 * @param series the series index. 112 */ 113 public void clearSeriesLabels(int series) { 114 Integer key = series; 115 this.seriesLabelLists.put(key, null); 116 } 117 118 /** 119 * Generates a label for the specified series. This label will be 120 * used for the chart legend. 121 * 122 * @param dataset the dataset ({@code null} not permitted). 123 * @param series the series. 124 * 125 * @return A series label. 126 */ 127 @Override 128 public String generateLabel(XYDataset dataset, int series) { 129 Args.nullNotPermitted(dataset, "dataset"); 130 StringBuilder label = new StringBuilder(); 131 label.append(MessageFormat.format(this.formatPattern, 132 createItemArray(dataset, series))); 133 Integer key = series; 134 List extraLabels = (List) this.seriesLabelLists.get(key); 135 if (extraLabels != null) { 136 Object[] temp = new Object[1]; 137 for (int i = 0; i < extraLabels.size(); i++) { 138 temp[0] = extraLabels.get(i); 139 String labelAddition = MessageFormat.format( 140 this.additionalFormatPattern, temp); 141 label.append(labelAddition); 142 } 143 } 144 return label.toString(); 145 } 146 147 /** 148 * Creates the array of items that can be passed to the 149 * {@link MessageFormat} class for creating labels. 150 * 151 * @param dataset the dataset ({@code null} not permitted). 152 * @param series the series (zero-based index). 153 * 154 * @return The items (never {@code null}). 155 */ 156 protected Object[] createItemArray(XYDataset dataset, int series) { 157 Object[] result = new Object[1]; 158 result[0] = dataset.getSeriesKey(series).toString(); 159 return result; 160 } 161 162 /** 163 * Returns an independent copy of the generator. 164 * 165 * @return A clone. 166 * 167 * @throws CloneNotSupportedException if cloning is not supported. 168 */ 169 @Override 170 public Object clone() throws CloneNotSupportedException { 171 MultipleXYSeriesLabelGenerator clone 172 = (MultipleXYSeriesLabelGenerator) super.clone(); 173 clone.seriesLabelLists = new HashMap(); 174 Set keys = this.seriesLabelLists.keySet(); 175 for (Object key : keys) { 176 Object entry = this.seriesLabelLists.get(key); 177 Object toAdd = entry; 178 if (entry instanceof PublicCloneable) { 179 PublicCloneable pc = (PublicCloneable) entry; 180 toAdd = pc.clone(); 181 } 182 clone.seriesLabelLists.put(key, toAdd); 183 } 184 return clone; 185 } 186 187 /** 188 * Tests this object for equality with an arbitrary object. 189 * 190 * @param obj the other object ({@code null} permitted). 191 * 192 * @return A boolean. 193 */ 194 @Override 195 public boolean equals(Object obj) { 196 if (obj == this) { 197 return true; 198 } 199 if (!(obj instanceof MultipleXYSeriesLabelGenerator)) { 200 return false; 201 } 202 MultipleXYSeriesLabelGenerator that 203 = (MultipleXYSeriesLabelGenerator) obj; 204 if (!this.formatPattern.equals(that.formatPattern)) { 205 return false; 206 } 207 if (!this.additionalFormatPattern.equals( 208 that.additionalFormatPattern)) { 209 return false; 210 } 211 if (!this.seriesLabelLists.equals(that.seriesLabelLists)) { 212 return false; 213 } 214 return true; 215 } 216 217 /** 218 * Returns a hash code for this instance. 219 * 220 * @return A hash code. 221 */ 222 @Override 223 public int hashCode() { 224 int result = 127; 225 result = HashUtils.hashCode(result, this.formatPattern); 226 result = HashUtils.hashCode(result, this.additionalFormatPattern); 227 result = HashUtils.hashCode(result, this.seriesLabelLists); 228 return result; 229 } 230 231}