001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2007, by Object Refinery Limited 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     * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025     * in the United States and other countries.]
026     *
027     * --------------------------------------
028     * DefaultStatisticalCategoryDataset.java
029     * --------------------------------------
030     * (C) Copyright 2002-2007, by Pascal Collet and Contributors.
031     *
032     * Original Author:  Pascal Collet;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *
035     * $Id: DefaultStatisticalCategoryDataset.java,v 1.8.2.4 2007/02/02 15:50:24 mungady Exp $
036     *
037     * Changes
038     * -------
039     * 21-Aug-2002 : Version 1, contributed by Pascal Collet (DG);
040     * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG);
041     * 05-Feb-2003 : Revised implementation to use KeyedObjects2D (DG);
042     * 28-Aug-2003 : Moved from org.jfree.data --> org.jfree.data.statistics (DG);
043     * 06-Oct-2003 : Removed incorrect Javadoc text (DG);
044     * 18-Nov-2004 : Updated for changes in RangeInfo interface (DG);
045     * 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0 
046     *               release (DG);
047     * 01-Feb-2005 : Changed minimumRangeValue and maximumRangeValue from Double
048     *               to double (DG);
049     * 05-Feb-2005 : Implemented equals() method (DG);
050     * ------------- JFREECHART 1.0.x ---------------------------------------------
051     * 08-Aug-2006 : Reworked implementation of RangeInfo methods (DG);
052     * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
053     * 
054     */
055    
056    package org.jfree.data.statistics;
057    
058    import java.util.List;
059    
060    import org.jfree.data.KeyedObjects2D;
061    import org.jfree.data.Range;
062    import org.jfree.data.RangeInfo;
063    import org.jfree.data.general.AbstractDataset;
064    
065    /**
066     * A convenience class that provides a default implementation of the
067     * {@link StatisticalCategoryDataset} interface.
068     */
069    public class DefaultStatisticalCategoryDataset extends AbstractDataset
070        implements StatisticalCategoryDataset, RangeInfo {
071    
072        /** Storage for the data. */
073        private KeyedObjects2D data;
074    
075        /** The minimum range value. */
076        private double minimumRangeValue;
077    
078        /** The minimum range value including the standard deviation. */
079        private double minimumRangeValueIncStdDev;
080        
081        /** The maximum range value. */
082        private double maximumRangeValue;
083    
084        /** The maximum range value including the standard deviation. */
085        private double maximumRangeValueIncStdDev;
086    
087        /**
088         * Creates a new dataset.
089         */
090        public DefaultStatisticalCategoryDataset() {
091            this.data = new KeyedObjects2D();
092            this.minimumRangeValue = Double.NaN;
093            this.maximumRangeValue = Double.NaN;
094            this.minimumRangeValueIncStdDev = Double.NaN;
095            this.maximumRangeValueIncStdDev = Double.NaN;
096        }
097    
098        /**
099         * Returns the mean value for an item.
100         *
101         * @param row  the row index (zero-based).
102         * @param column  the column index (zero-based).
103         *
104         * @return The mean value.
105         */
106        public Number getMeanValue(int row, int column) {
107            Number result = null;
108            MeanAndStandardDeviation masd 
109                = (MeanAndStandardDeviation) this.data.getObject(row, column);
110            if (masd != null) {
111                result = masd.getMean();
112            }
113            return result;
114        }
115    
116        /**
117         * Returns the value for an item (for this dataset, the mean value is
118         * returned).
119         *
120         * @param row  the row index.
121         * @param column  the column index.
122         *
123         * @return The value.
124         */
125        public Number getValue(int row, int column) {
126            return getMeanValue(row, column);
127        }
128    
129        /**
130         * Returns the value for an item (for this dataset, the mean value is
131         * returned).
132         *
133         * @param rowKey  the row key.
134         * @param columnKey  the columnKey.
135         *
136         * @return The value.
137         */
138        public Number getValue(Comparable rowKey, Comparable columnKey) {
139            return getMeanValue(rowKey, columnKey);
140        }
141    
142        /**
143         * Returns the mean value for an item.
144         *
145         * @param rowKey  the row key.
146         * @param columnKey  the columnKey.
147         *
148         * @return The mean value.
149         */
150        public Number getMeanValue(Comparable rowKey, Comparable columnKey) {
151            Number result = null;
152            MeanAndStandardDeviation masd
153                = (MeanAndStandardDeviation) this.data.getObject(rowKey, columnKey);
154            if (masd != null) {
155                result = masd.getMean();
156            }
157            return result;
158        }
159    
160        /**
161         * Returns the standard deviation value for an item.
162         *
163         * @param row  the row index (zero-based).
164         * @param column  the column index (zero-based).
165         *
166         * @return The standard deviation.
167         */
168        public Number getStdDevValue(int row, int column) {
169            Number result = null;
170            MeanAndStandardDeviation masd 
171                = (MeanAndStandardDeviation) this.data.getObject(row, column);
172            if (masd != null) {
173                result = masd.getStandardDeviation();
174            }
175            return result;
176        }
177    
178        /**
179         * Returns the standard deviation value for an item.
180         *
181         * @param rowKey  the row key.
182         * @param columnKey  the columnKey.
183         *
184         * @return The standard deviation.
185         */
186        public Number getStdDevValue(Comparable rowKey, Comparable columnKey) {
187            Number result = null;
188            MeanAndStandardDeviation masd
189                = (MeanAndStandardDeviation) this.data.getObject(rowKey, columnKey);
190            if (masd != null) {
191                result = masd.getStandardDeviation();
192            }
193            return result;
194        }
195    
196        /**
197         * Returns the column index for a given key.
198         *
199         * @param key  the column key.
200         *
201         * @return The column index.
202         */
203        public int getColumnIndex(Comparable key) {
204            return this.data.getColumnIndex(key);
205        }
206    
207        /**
208         * Returns a column key.
209         *
210         * @param column  the column index (zero-based).
211         *
212         * @return The column key.
213         */
214        public Comparable getColumnKey(int column) {
215            return this.data.getColumnKey(column);
216        }
217    
218        /**
219         * Returns the column keys.
220         *
221         * @return The keys.
222         */
223        public List getColumnKeys() {
224            return this.data.getColumnKeys();
225        }
226    
227        /**
228         * Returns the row index for a given key.
229         *
230         * @param key  the row key.
231         *
232         * @return The row index.
233         */
234        public int getRowIndex(Comparable key) {
235            return this.data.getRowIndex(key);
236        }
237    
238        /**
239         * Returns a row key.
240         *
241         * @param row  the row index (zero-based).
242         *
243         * @return The row key.
244         */
245        public Comparable getRowKey(int row) {
246            return this.data.getRowKey(row);
247        }
248    
249        /**
250         * Returns the row keys.
251         *
252         * @return The keys.
253         */
254        public List getRowKeys() {
255            return this.data.getRowKeys();
256        }
257    
258        /**
259         * Returns the number of rows in the table.
260         *
261         * @return The row count.
262         */
263        public int getRowCount() {
264            return this.data.getRowCount();
265        }
266    
267        /**
268         * Returns the number of columns in the table.
269         *
270         * @return The column count.
271         */
272        public int getColumnCount() {
273            return this.data.getColumnCount();
274        }
275    
276        /**
277         * Adds a mean and standard deviation to the table.
278         *
279         * @param mean  the mean.
280         * @param standardDeviation  the standard deviation.
281         * @param rowKey  the row key.
282         * @param columnKey  the column key.
283         */
284        public void add(double mean, double standardDeviation,
285                        Comparable rowKey, Comparable columnKey) {
286            add(new Double(mean), new Double(standardDeviation), rowKey, columnKey);
287        }
288    
289        /**
290         * Adds a mean and standard deviation to the table.
291         *
292         * @param mean  the mean.
293         * @param standardDeviation  the standard deviation.
294         * @param rowKey  the row key.
295         * @param columnKey  the column key.
296         */
297        public void add(Number mean, Number standardDeviation,
298                        Comparable rowKey, Comparable columnKey) {
299            MeanAndStandardDeviation item = new MeanAndStandardDeviation(
300                    mean, standardDeviation);
301            this.data.addObject(item, rowKey, columnKey);
302            double m = 0.0;
303            double sd = 0.0;
304            if (mean != null) {
305                m = mean.doubleValue();
306            }
307            if (standardDeviation != null) {
308                sd = standardDeviation.doubleValue();   
309            }
310            
311            if (!Double.isNaN(m)) {
312                if (Double.isNaN(this.maximumRangeValue) 
313                        || m > this.maximumRangeValue) {
314                    this.maximumRangeValue = m;
315                }
316            }
317            
318            if (!Double.isNaN(m + sd)) {
319                if (Double.isNaN(this.maximumRangeValueIncStdDev) 
320                        || (m + sd) > this.maximumRangeValueIncStdDev) {
321                    this.maximumRangeValueIncStdDev = m + sd;
322                }
323            }
324    
325            if (!Double.isNaN(m)) {
326                if (Double.isNaN(this.minimumRangeValue) 
327                        || m < this.minimumRangeValue) {
328                    this.minimumRangeValue = m;
329                }
330            }
331    
332            if (!Double.isNaN(m - sd)) {
333                if (Double.isNaN(this.minimumRangeValueIncStdDev) 
334                        || (m - sd) < this.minimumRangeValueIncStdDev) {
335                    this.minimumRangeValueIncStdDev = m - sd;
336                }
337            }
338    
339            fireDatasetChanged();
340        }
341    
342        /**
343         * Returns the minimum y-value in the dataset.
344         *
345         * @param includeInterval  a flag that determines whether or not the
346         *                         y-interval is taken into account (ignored for
347         *                         this dataset).
348         * 
349         * @return The minimum value.
350         */
351        public double getRangeLowerBound(boolean includeInterval) {
352            return this.minimumRangeValue;        
353        }
354    
355        /**
356         * Returns the maximum y-value in the dataset.
357         *
358         * @param includeInterval  a flag that determines whether or not the
359         *                         y-interval is taken into account (ignored for
360         *                         this dataset).
361         * 
362         * @return The maximum value.
363         */
364        public double getRangeUpperBound(boolean includeInterval) {
365            return this.maximumRangeValue;        
366        }
367    
368        /**
369         * Returns the range of the values in this dataset's range.
370         *
371         * @param includeInterval  a flag that determines whether or not the
372         *                         y-interval is taken into account.
373         * 
374         * @return The range.
375         */
376        public Range getRangeBounds(boolean includeInterval) {
377            Range result = null;
378            if (includeInterval) {
379                if (!Double.isNaN(this.minimumRangeValueIncStdDev) 
380                        && !Double.isNaN(this.maximumRangeValueIncStdDev))
381                result = new Range(this.minimumRangeValueIncStdDev, 
382                        this.maximumRangeValueIncStdDev);
383            }
384            else {
385                if (!Double.isNaN(this.minimumRangeValue) 
386                        && !Double.isNaN(this.maximumRangeValue))
387                result = new Range(this.minimumRangeValue, this.maximumRangeValue);            
388            }
389            return result;
390        }
391    
392        /**
393         * Tests this instance for equality with an arbitrary object.
394         * 
395         * @param obj  the object (<code>null</code> permitted).
396         * 
397         * @return A boolean.
398         */
399        public boolean equals(Object obj) {
400            if (obj == this) {
401                return true;   
402            }
403            if (!(obj instanceof DefaultStatisticalCategoryDataset)) {
404                return false;   
405            }
406            DefaultStatisticalCategoryDataset that 
407                = (DefaultStatisticalCategoryDataset) obj;
408            if (!this.data.equals(that.data)) {
409                return false;   
410            }
411            return true;
412        }
413    }