001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2016, by Object Refinery Limited. All rights reserved. 006 * 007 * http://www.object-refinery.com/orsoncharts/index.html 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package com.orsoncharts.data; 034 035import java.io.Serializable; 036import java.util.ArrayList; 037import java.util.List; 038 039import com.orsoncharts.util.ArgChecks; 040 041/** 042 * A list of {@code (key, value)} pairs. 043 * <br><br> 044 * This is the basic structure of the data required for a pie chart. 045 * <br><br> 046 * NOTE: This class is serializable, but the serialization format is subject 047 * to change in future releases and should not be relied upon for persisting 048 * instances of this class. 049 */ 050@SuppressWarnings("serial") 051public final class DefaultKeyedValues<T> implements KeyedValues<T>, 052 Serializable { 053 054 /** Storage for the data items. */ 055 private List<KeyedValue<T>> data; 056 057 /** 058 * Creates a new (empty) list of keyed values. 059 */ 060 public DefaultKeyedValues() { 061 this(new ArrayList<Comparable<?>>()); 062 } 063 064 /** 065 * Creates a new instance with the specified keys (each associated with 066 * a {@code null} value). There is usually no need to specify any 067 * keys in advance, so you will normally use the default constructor. This 068 * constructor is provided for the convenience of some internal code. 069 * 070 * @param keys the keys ({@code null} not permitted). 071 */ 072 public DefaultKeyedValues(List<Comparable<?>> keys) { 073 ArgChecks.nullNotPermitted(keys, "keys"); 074 this.data = new ArrayList<KeyedValue<T>>(); 075 for (Comparable<?> key : keys) { 076 this.data.add(new DefaultKeyedValue<T>(key, null)); 077 } 078 } 079 080 /** 081 * Clears all the data. 082 */ 083 public void clear() { 084 this.data.clear(); 085 } 086 087 /** 088 * Adds a value or, if there is an existing value with the same key, updates 089 * an existing value. 090 * 091 * @param key the key ({@code null} not permitted) 092 * @param value the value. 093 */ 094 public void put(Comparable<?> key, T value) { 095 ArgChecks.nullNotPermitted(key, "key"); 096 DefaultKeyedValue<T> dkv; 097 int index = getIndex(key); 098 if (index >= 0) { 099 dkv = (DefaultKeyedValue<T>) this.data.get(index); 100 dkv.setValue(value); 101 } else { 102 this.data.add(new DefaultKeyedValue<T>(key, value)); 103 } 104 } 105 106 /** 107 * Removes the item with the specified key, if there is one. 108 * 109 * @param key the key ({@code null} not permitted). 110 */ 111 public void remove(Comparable<?> key) { 112 ArgChecks.nullNotPermitted(key, "key"); 113 int index = getIndex(key); 114 if (index >= 0) { 115 remove(index); 116 } 117 } 118 119 /** 120 * Removes the item with the specified index. 121 * 122 * @param index the index. 123 */ 124 public void remove(int index) { 125 this.data.remove(index); 126 } 127 128 /** 129 * Returns the key for the item with the specified index. 130 * 131 * @param index the item index. 132 * 133 * @return The key. 134 */ 135 @Override 136 public Comparable<?> getKey(int index) { 137 KeyedValue<T> kv = this.data.get(index); 138 return kv.getKey(); 139 } 140 141 /** 142 * Returns the index of the item with the specified key, or {@code -1} 143 * if there is no such item. 144 * 145 * @param key the key ({@code null} not permitted). 146 * 147 * @return The item index, or {@code -1}. 148 */ 149 @Override 150 public int getIndex(Comparable<?> key) { 151 ArgChecks.nullNotPermitted(key, "key"); 152 for (int i = 0; i < this.data.size(); i++) { 153 KeyedValue<T> kv = this.data.get(i); 154 if (kv.getKey().equals(key)) { 155 return i; 156 } 157 } 158 return -1; 159 } 160 161 /** 162 * Returns a list of all the keys. Note that the list will be a copy, so 163 * modifying it will not impact this data structure. 164 * 165 * @return A list of keys (possibly empty, but never {@code null}). 166 */ 167 @Override 168 public List<Comparable<?>> getKeys() { 169 List<Comparable<?>> keys = new ArrayList<Comparable<?>>(); 170 for (KeyedValue<T> kv : this.data) { 171 keys.add(kv.getKey()); 172 } 173 return keys; 174 } 175 176 /** 177 * Returns the value with the specified key. 178 * 179 * @param key the key ({@code null} not permitted). 180 * 181 * @return The value (possibly {@code null}). 182 */ 183 @Override 184 public T getValue(Comparable<?> key) { 185 // arg checking is performed by getIndex() 186 int index = getIndex(key); 187 if (index < 0) { 188 return null; 189 } 190 return getValue(index); 191 } 192 193 /** 194 * Returns the number of items in the list. 195 * 196 * @return The number of items in the list. 197 */ 198 @Override 199 public int getItemCount() { 200 return this.data.size(); 201 } 202 203 /** 204 * Returns the value for the specified item. 205 * 206 * @param item the item index. 207 * 208 * @return The value (possibly {@code null}). 209 */ 210 @Override 211 public T getValue(int item) { 212 KeyedValue<T> kv = this.data.get(item); 213 return kv.getValue(); 214 } 215 216 /** 217 * Returns the value for the specified item, as a double primitive, 218 * provided that the data value is an instance of {@code Number}. 219 * 220 * @param item the item index. 221 * 222 * @return The value. 223 */ 224 @Override 225 public double getDoubleValue(int item) { 226 T n = getValue(item); 227 if (n != null && n instanceof Number) { 228 return ((Number) n).doubleValue(); 229 } 230 return Double.NaN; 231 } 232 233 /** 234 * Tests this instance for equality with an arbitrary object. 235 * 236 * @param obj the object to test against ({@code null} permitted). 237 * 238 * @return A boolean. 239 */ 240 @Override 241 public boolean equals(Object obj) { 242 if (obj == this) { 243 return true; 244 } 245 if (!(obj instanceof DefaultKeyedValues<?>)) { 246 return false; 247 } 248 DefaultKeyedValues<?> that = (DefaultKeyedValues<?>) obj; 249 if (!this.data.equals(that.data)) { 250 return false; 251 } 252 return true; 253 } 254}