1. /* ===========================================================
  2. * JFreeChart : a free chart library for the Java(tm) platform
  3. * ===========================================================
  4. *
  5. * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
  6. *
  7. * Project Info: http://www.jfree.org/jfreechart/index.html
  8. *
  9. * This library is free software; you can redistribute it and/or modify it under the terms
  10. * of the GNU Lesser General Public License as published by the Free Software Foundation;
  11. * either version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  14. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License along with this
  18. * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. *
  21. * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  22. * in the United States and other countries.]
  23. *
  24. * ------------------
  25. * KeyedObject2D.java
  26. * ------------------
  27. * (C) Copyright 2003-2005, by Object Refinery Limited.
  28. *
  29. * Original Author: David Gilbert (for Object Refinery Limited);
  30. * Contributor(s): -;
  31. *
  32. * $Id: KeyedObjects2D.java,v 1.4 2005/01/14 17:33:20 mungady Exp $
  33. *
  34. * Changes
  35. * -------
  36. * 05-Feb-2003 : Version 1 (DG);
  37. * 01-Mar-2004 : Added equals() and clone() methods and implemented Serializable (DG);
  38. *
  39. */
  40. package org.jfree.data;
  41. import java.io.Serializable;
  42. import java.util.Collections;
  43. import java.util.Iterator;
  44. import java.util.List;
  45. /**
  46. * A data structure that stores zero, one or many objects, where each object is associated with
  47. * two keys (a 'row' key and a 'column' key).
  48. */
  49. public class KeyedObjects2D implements Cloneable, Serializable {
  50. /** The row keys. */
  51. private List rowKeys;
  52. /** The column keys. */
  53. private List columnKeys;
  54. /** The row data. */
  55. private List rows;
  56. /**
  57. * Creates a new instance (initially empty).
  58. */
  59. public KeyedObjects2D() {
  60. this.rowKeys = new java.util.ArrayList();
  61. this.columnKeys = new java.util.ArrayList();
  62. this.rows = new java.util.ArrayList();
  63. }
  64. /**
  65. * Returns the row count.
  66. *
  67. * @return The row count.
  68. */
  69. public int getRowCount() {
  70. return this.rowKeys.size();
  71. }
  72. /**
  73. * Returns the column count.
  74. *
  75. * @return The column count.
  76. */
  77. public int getColumnCount() {
  78. return this.columnKeys.size();
  79. }
  80. /**
  81. * Returns the object for a given row and column.
  82. *
  83. * @param row the row index.
  84. * @param column the column index.
  85. *
  86. * @return The object.
  87. */
  88. public Object getObject(int row, int column) {
  89. Object result = null;
  90. KeyedObjects rowData = (KeyedObjects) this.rows.get(row);
  91. if (rowData != null) {
  92. Comparable columnKey = (Comparable) this.columnKeys.get(column);
  93. if (columnKey != null) {
  94. result = rowData.getObject(columnKey);
  95. }
  96. }
  97. return result;
  98. }
  99. /**
  100. * Returns the key for a given row.
  101. *
  102. * @param row the row index (zero based).
  103. *
  104. * @return The row index.
  105. */
  106. public Comparable getRowKey(int row) {
  107. return (Comparable) this.rowKeys.get(row);
  108. }
  109. /**
  110. * Returns the row index for a given key.
  111. *
  112. * @param key the key.
  113. *
  114. * @return The row index.
  115. */
  116. public int getRowIndex(Comparable key) {
  117. return this.rowKeys.indexOf(key);
  118. }
  119. /**
  120. * Returns the row keys.
  121. *
  122. * @return The row keys (never <code>null</code>).
  123. */
  124. public List getRowKeys() {
  125. return Collections.unmodifiableList(this.rowKeys);
  126. }
  127. /**
  128. * Returns the key for a given column.
  129. *
  130. * @param column the column.
  131. *
  132. * @return The key.
  133. */
  134. public Comparable getColumnKey(int column) {
  135. return (Comparable) this.columnKeys.get(column);
  136. }
  137. /**
  138. * Returns the column index for a given key.
  139. *
  140. * @param key the key.
  141. *
  142. * @return The column index.
  143. */
  144. public int getColumnIndex(Comparable key) {
  145. return this.columnKeys.indexOf(key);
  146. }
  147. /**
  148. * Returns the column keys.
  149. *
  150. * @return The column keys (never <code>null</code>).
  151. */
  152. public List getColumnKeys() {
  153. return Collections.unmodifiableList(this.columnKeys);
  154. }
  155. /**
  156. * Returns the object for the given row and column keys.
  157. *
  158. * @param rowKey the row key.
  159. * @param columnKey the column key.
  160. *
  161. * @return The object.
  162. */
  163. public Object getObject(Comparable rowKey, Comparable columnKey) {
  164. Object result = null;
  165. int row = this.rowKeys.indexOf(rowKey);
  166. if (row >= 0) {
  167. KeyedObjects rowData = (KeyedObjects) this.rows.get(row);
  168. result = rowData.getObject(columnKey);
  169. }
  170. return result;
  171. }
  172. /**
  173. * Adds an object to the table. Performs the same function as setObject().
  174. *
  175. * @param object the object.
  176. * @param rowKey the row key.
  177. * @param columnKey the column key.
  178. */
  179. public void addObject(Object object,
  180. Comparable rowKey,
  181. Comparable columnKey) {
  182. setObject(object, rowKey, columnKey);
  183. }
  184. /**
  185. * Adds or updates an object.
  186. *
  187. * @param object the object.
  188. * @param rowKey the row key.
  189. * @param columnKey the column key.
  190. */
  191. public void setObject(Object object,
  192. Comparable rowKey,
  193. Comparable columnKey) {
  194. KeyedObjects row;
  195. int rowIndex = this.rowKeys.indexOf(rowKey);
  196. if (rowIndex >= 0) {
  197. row = (KeyedObjects) this.rows.get(rowIndex);
  198. }
  199. else {
  200. this.rowKeys.add(rowKey);
  201. row = new KeyedObjects();
  202. this.rows.add(row);
  203. }
  204. row.setObject(columnKey, object);
  205. int columnIndex = this.columnKeys.indexOf(columnKey);
  206. if (columnIndex < 0) {
  207. this.columnKeys.add(columnKey);
  208. }
  209. }
  210. /**
  211. * Removes an object.
  212. *
  213. * @param rowKey the row key.
  214. * @param columnKey the column key.
  215. */
  216. public void removeObject(Comparable rowKey, Comparable columnKey) {
  217. setObject(null, rowKey, columnKey);
  218. // actually, a null value is different to a value that doesn't exist at all.
  219. // need to fix this code.
  220. }
  221. /**
  222. * Removes a row.
  223. *
  224. * @param rowIndex the row index.
  225. */
  226. public void removeRow(int rowIndex) {
  227. this.rowKeys.remove(rowIndex);
  228. this.rows.remove(rowIndex);
  229. }
  230. /**
  231. * Removes a row.
  232. *
  233. * @param rowKey the row key.
  234. */
  235. public void removeRow(Comparable rowKey) {
  236. removeRow(getRowIndex(rowKey));
  237. }
  238. /**
  239. * Removes a column.
  240. *
  241. * @param columnIndex the column index.
  242. */
  243. public void removeColumn(int columnIndex) {
  244. Comparable columnKey = getColumnKey(columnIndex);
  245. removeColumn(columnKey);
  246. }
  247. /**
  248. * Removes a column.
  249. *
  250. * @param columnKey the column key.
  251. */
  252. public void removeColumn(Comparable columnKey) {
  253. Iterator iterator = this.rows.iterator();
  254. while (iterator.hasNext()) {
  255. KeyedObjects rowData = (KeyedObjects) iterator.next();
  256. rowData.removeValue(columnKey);
  257. }
  258. this.columnKeys.remove(columnKey);
  259. }
  260. /**
  261. * Tests this object for equality with an arbitrary object.
  262. *
  263. * @param obj the object to test (<code>null</code> permitted).
  264. *
  265. * @return a boolean.
  266. */
  267. public boolean equals(Object obj) {
  268. if (obj == null) {
  269. return false;
  270. }
  271. if (obj == this) {
  272. return true;
  273. }
  274. if (!(obj instanceof KeyedObjects2D)) {
  275. return false;
  276. }
  277. KeyedObjects2D ko2D = (KeyedObjects2D) obj;
  278. if (!getRowKeys().equals(ko2D.getRowKeys())) {
  279. return false;
  280. }
  281. if (!getColumnKeys().equals(ko2D.getColumnKeys())) {
  282. return false;
  283. }
  284. int rowCount = getRowCount();
  285. if (rowCount != ko2D.getRowCount()) {
  286. return false;
  287. }
  288. int colCount = getColumnCount();
  289. if (colCount != ko2D.getColumnCount()) {
  290. return false;
  291. }
  292. for (int r = 0; r < rowCount; r++) {
  293. for (int c = 0; c < colCount; c++) {
  294. Object v1 = getObject(r, c);
  295. Object v2 = ko2D.getObject(r, c);
  296. if (v1 == null) {
  297. if (v2 != null) {
  298. return false;
  299. }
  300. }
  301. else {
  302. if (!v1.equals(v2)) {
  303. return false;
  304. }
  305. }
  306. }
  307. }
  308. return true;
  309. }
  310. /**
  311. * Returns a hashcode for this object.
  312. *
  313. * @return A hashcode.
  314. */
  315. public int hashCode() {
  316. int result;
  317. result = this.rowKeys.hashCode();
  318. result = 29 * result + this.columnKeys.hashCode();
  319. result = 29 * result + this.rows.hashCode();
  320. return result;
  321. }
  322. /**
  323. * Returns a clone.
  324. *
  325. * @return A clone.
  326. *
  327. * @throws CloneNotSupportedException this class will not throw this exception, but subclasses
  328. * (if any) might.
  329. */
  330. public Object clone() throws CloneNotSupportedException {
  331. return super.clone();
  332. }
  333. }