001: /*
002: JOpenChart Java Charting Library and Toolkit
003: Copyright (C) 2001 Sebastian Müller
004: http://jopenchart.sourceforge.net
005:
006: This library is free software; you can redistribute it and/or
007: modify it under the terms of the GNU Lesser General Public
008: License as published by the Free Software Foundation; either
009: version 2.1 of the License, or (at your option) any later version.
010:
011: This library is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019:
020: ObjectColumnChartDataModel.java
021: Created on 7. August 2001, 17:27
022: */
023:
024: package de.progra.charting.model;
025:
026: import de.progra.charting.CoordSystem;
027: import de.progra.charting.ChartUtilities;
028: import java.util.TreeSet;
029: import java.util.Set;
030: import java.util.HashMap;
031:
032: /**
033: * The ObjectChartDataModel implements a ChartDataModel for Charts,
034: * which have e.g. String values on the x-axis. This is especially useful
035: * for Barcharts and also for Piecharts, although those don't exactly have
036: * an x-axis.
037: * @author mueller
038: * @version 1.0
039: */
040: public class ObjectChartDataModel extends AbstractChartDataModel {
041:
042: /** The x-axis values. */
043: protected Object[] columns;
044:
045: /** The data values.*/
046: protected DataSet[] data;
047:
048: /** A HashMap containing the ordered data per axis. */
049: protected HashMap valuesbyaxis = new HashMap();
050:
051: /** The constraints for the first and second y-axes.*/
052: protected ChartDataModelConstraints constraints1, constraints2;
053:
054: /** Creates a new empty DefaultChartDataModel.
055: * Initializes all Objects and Arrays as empty ones.
056: */
057: public ObjectChartDataModel() {
058: data = new DefaultDataSet[0];
059: columns = new Object[0];
060:
061: TreeSet set1 = new TreeSet();
062: valuesbyaxis.put(new Integer(CoordSystem.FIRST_YAXIS), set1);
063:
064: TreeSet set2 = new TreeSet();
065: valuesbyaxis.put(new Integer(CoordSystem.SECOND_YAXIS), set2);
066:
067: constraints1 = new DefaultChartDataModelConstraints(this ,
068: CoordSystem.FIRST_YAXIS, false);
069: constraints2 = new DefaultChartDataModelConstraints(this ,
070: CoordSystem.SECOND_YAXIS, false);
071: }
072:
073: /** Creates new ObjectChartDataModel with the default axis binding.
074: * @param data the array of values. The first index specifies the
075: * datasets, the last one is the value index.
076: * @param columns the array of x-axis values. The length of the
077: * datasets and the length of the column should be equal and the columns should
078: * be ordered.
079: * @param rows the DataSet titles
080: */
081: public ObjectChartDataModel(Number[][] data, Object[] columns,
082: String rows[]) {
083: this ();
084:
085: this .columns = columns;
086:
087: this .data = new DefaultDataSet[data.length];
088:
089: TreeSet set = (TreeSet) valuesbyaxis.get(new Integer(
090: CoordSystem.FIRST_YAXIS));
091:
092: ChartUtilities.addDataToSet(set, data);
093:
094: for (int i = 0; i < data.length; i++) {
095: this .data[i] = new DefaultDataSet(data[i], columns,
096: CoordSystem.FIRST_YAXIS, rows[i]);
097: }
098: }
099:
100: /** Creates new ObjectChartDataModel.
101: * @param data the array of values. The first index specifies the
102: * datasets, the last one is the value index.
103: * @param columns the array of x-axis values. The length of the
104: * datasets and the length of the column should be equal and
105: * the columns should be ordered.
106: * @param rows the DataSet titles
107: */
108: public ObjectChartDataModel(int[][] data, Object[] columns,
109: String[] rows) {
110: this ();
111:
112: Number[][] numdata = ChartUtilities.transformArray(data);
113:
114: this .columns = columns;
115:
116: this .data = new DefaultDataSet[data.length];
117:
118: TreeSet set = (TreeSet) valuesbyaxis.get(new Integer(
119: CoordSystem.FIRST_YAXIS));
120:
121: ChartUtilities.addDataToSet(set, numdata);
122:
123: for (int i = 0; i < data.length; i++) {
124: this .data[i] = new DefaultDataSet(numdata[i], columns,
125: CoordSystem.FIRST_YAXIS, rows[i]);
126: }
127: }
128:
129: /** Creates new ObjectChartDataModel.
130: * @param data the array of values. The first index specifies the
131: * datasets, the last one is the value index.
132: * @param columns the array of x-axis values. The length of the
133: * datasets and the length of the column should be equal and
134: * the columns should be ordered.
135: *@param rows the DataSet titles
136: */
137: public ObjectChartDataModel(double[][] data, Object[] columns,
138: String[] rows) {
139: this ();
140:
141: Number[][] numdata = ChartUtilities.transformArray(data);
142:
143: this .columns = columns;
144:
145: this .data = new DefaultDataSet[data.length];
146:
147: TreeSet set = (TreeSet) valuesbyaxis.get(new Integer(
148: CoordSystem.FIRST_YAXIS));
149:
150: ChartUtilities.addDataToSet(set, numdata);
151:
152: for (int i = 0; i < data.length; i++) {
153: this .data[i] = new DefaultDataSet(numdata[i], columns,
154: CoordSystem.FIRST_YAXIS, rows[i]);
155: }
156: }
157:
158: /** Creates a new ObjectChartDataModel using the
159: * given array of DataSets, effectively enabling the creation
160: * of DataModels with differently sized DataSets. Internally, the DataSets
161: * are transformed into equally sized DataSets, where the missing data fields
162: * are filled with Double.NaN.
163: * @param ds the array of DataSets to be used.
164: * @param columns the array of column values. This needs to be supplied,
165: * because using Objects as x-axis values you need to have an ordered
166: * superset of all column values especially if different DataSets only
167: * contain some column values
168: */
169: public ObjectChartDataModel(DataSet[] ds, Object[] columns) {
170: this ();
171: data = ds;
172: this .columns = columns;
173:
174: TreeSet set;
175:
176: HashMap map = new HashMap();
177:
178: for (int i = 0; i < ds.length; i++) {
179: map.clear();
180: Number[] numdata = new Number[columns.length];
181:
182: for (int j = 0; j < columns.length; j++)
183: map.put(columns[j], new Double(Double.NaN));
184:
185: set = (TreeSet) valuesbyaxis.get(new Integer(ds[i]
186: .getYAxis()));
187:
188: for (int j = 0; j < ds[i].getDataSetLength(); j++) {
189: map.put(ds[i].getColumnValueAt(j), ds[i].getValueAt(j));
190: set.add(ds[i].getValueAt(j));
191: }
192:
193: for (int j = 0; j < columns.length; j++) {
194: numdata[j] = (Number) map.get(columns[j]);
195: }
196:
197: data[i] = new DefaultDataSet(numdata, columns,
198: CoordSystem.FIRST_YAXIS, ds[i].getTitle());
199: }
200: }
201:
202: /** Returns the length of a certain dataset.
203: * @param set the DataSet index
204: * @return the DataSet length
205: */
206: public int getDataSetLength(int set) {
207: return data[set].getDataSetLength();
208: }
209:
210: /** Returns the total amount of datasets.
211: * @return the amount of DataSet
212: */
213: public int getDataSetNumber() {
214: return data.length;
215: }
216:
217: /** Returns the title of the DataSet. This is the number of
218: * the DataSet per default.
219: * @param set the DataSet index
220: * @return the String title
221: */
222: public String getDataSetName(int set) {
223: return data[set].getTitle();
224: }
225:
226: /** Returns the axis to which a DataSet is attached
227: * @param set the DataSet index
228: * @return the axis constant
229: */
230: public int getAxisBinding(int set) {
231: return data[set].getYAxis();
232: }
233:
234: /** Returns the Value in a specific dataset at a certain index.
235: * @param set the DataSet index
236: * @param index the value index
237: * @return the Number value
238: */
239: public Number getValueAt(int set, int index) {
240: return (Number) data[set].getValueAt(index);
241: }
242:
243: /** Returns a ChartDataModelConstraints Object for a given axis.
244: * This way, there are different constraints for the first and for
245: * the second y-axis. If the model is empty, the maximum values are 1 and
246: * the minimum values are 0, thus enabling proper rendering.
247: * @param axis the axis constant
248: * @return the ChartDataModelConstraints for the defined y-axis
249: */
250: public ChartDataModelConstraints getChartDataModelConstraints(
251: final int axis) {
252: if (axis == CoordSystem.FIRST_YAXIS)
253: return constraints1;
254: else
255: return constraints2;
256: }
257:
258: /** Sets the ChartDataModelConstraints object for the given
259: * axis binding.
260: * @param axis the Axis constant
261: * @param constraints the ChartDataModelConstraints object
262: * @return a ChartDataModelConstraints object.
263: */
264: public void setChartDataModelConstraints(int axis,
265: ChartDataModelConstraints constraints) {
266: if (axis == CoordSystem.FIRST_YAXIS)
267: constraints1 = constraints;
268: else
269: constraints2 = constraints;
270: }
271:
272: /** Returns a specific column value.
273: * @return the column value or <code>null</code> if the column doesn't exist.
274: * @param col the column index
275: */
276: public Object getColumnValueAt(int col) {
277: if (col < columns.length)
278: return columns[col];
279: else
280: return null;
281: }
282:
283: /** Calls getColumnValueAt(int col).
284: * @return the column value or <code>null</code> if the column doesn't exist.
285: * @param col the column index
286: */
287: public Object getColumnValueAt(int set, int col) {
288: return getColumnValueAt(col);
289: }
290:
291: /** Returns an ordered set of all data values for the specified axis.
292: * This is called by the ChartDataModelConstraints classes.
293: */
294: protected TreeSet getOrderedValues(int axis) {
295: return (TreeSet) valuesbyaxis.get(new Integer(axis));
296: }
297:
298: /** Is called by the ChartDataModelConstraints Object to compute the minimum column value.
299: * @return Returns 0.0.
300: */
301: protected double getFirstColumnValue() {
302: return 0.0;
303: }
304:
305: /** Is called by the ChartDataModelConstraints Object to compute the maximum column value.
306: * @return Returns <code>columns.length</code>.
307: */
308: protected double getLastColumnValue() {
309: return Math.max((double) columns.length, 1.0);
310: }
311: }
|