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