From: <mu...@us...> - 2007-10-08 14:15:10
|
Revision: 292 http://jfreechart.svn.sourceforge.net/jfreechart/?rev=292&view=rev Author: mungady Date: 2007-10-08 07:15:05 -0700 (Mon, 08 Oct 2007) Log Message: ----------- 2007-10-08 David Gilbert <dav...@ob...> * source/org/jfree/chart/renderer/category/MultiShapeRenderer.java: New file, * source/org/jfree/data/statistics/DefaultMultiValueCategoryDataset.java: Likewise, * source/org/jfree/data/statistics/MultiValueCategoryDataset.java: Likewise, * tests/org/jfree/chart/renderer/category/junit/MultiShapeRendererTests.java: Likewise, * tests/org/jfree/chart/renderer/category/junit/RendererCategoryPackageTests.java (suite): Added MultiShapeRendererTests, * tests/org/jfree/data/statistics/junit/DataStatisticsPackageTests.java (suite): Added DefaultMultiValueCategoryDatasetTests, * tests/org/jfree/data/statistics/junit/DefaultMultiValueCategoryDatasetTests.java: New file. Modified Paths: -------------- trunk/ChangeLog trunk/tests/org/jfree/chart/renderer/category/junit/RendererCategoryPackageTests.java trunk/tests/org/jfree/data/statistics/junit/DataStatisticsPackageTests.java Added Paths: ----------- trunk/source/org/jfree/chart/renderer/category/MultiShapeRenderer.java trunk/source/org/jfree/data/statistics/DefaultMultiValueCategoryDataset.java trunk/source/org/jfree/data/statistics/MultiValueCategoryDataset.java trunk/tests/org/jfree/chart/renderer/category/junit/MultiShapeRendererTests.java trunk/tests/org/jfree/data/statistics/junit/DefaultMultiValueCategoryDatasetTests.java Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-08 13:53:33 UTC (rev 291) +++ trunk/ChangeLog 2007-10-08 14:15:05 UTC (rev 292) @@ -1,3 +1,20 @@ +2007-10-08 David Gilbert <dav...@ob...> + + * source/org/jfree/chart/renderer/category/MultiShapeRenderer.java: + New file, + * source/org/jfree/data/statistics/DefaultMultiValueCategoryDataset.java: + Likewise, + * source/org/jfree/data/statistics/MultiValueCategoryDataset.java: + Likewise, + * tests/org/jfree/chart/renderer/category/junit/MultiShapeRendererTests.java: + Likewise, + * tests/org/jfree/chart/renderer/category/junit/RendererCategoryPackageTests.java + (suite): Added MultiShapeRendererTests, + * tests/org/jfree/data/statistics/junit/DataStatisticsPackageTests.java + (suite): Added DefaultMultiValueCategoryDatasetTests, + * tests/org/jfree/data/statistics/junit/DefaultMultiValueCategoryDatasetTests.java: + New file. + 2007-10-08 David Gilbert <dav...@ob...> * source/org/jfree/chart/plot/ValueMarker.java Added: trunk/source/org/jfree/chart/renderer/category/MultiShapeRenderer.java =================================================================== --- trunk/source/org/jfree/chart/renderer/category/MultiShapeRenderer.java (rev 0) +++ trunk/source/org/jfree/chart/renderer/category/MultiShapeRenderer.java 2007-10-08 14:15:05 UTC (rev 292) @@ -0,0 +1,551 @@ +/* =========================================================== + * JFreeChart : a free chart library for the Java(tm) platform + * =========================================================== + * + * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. + * + * Project Info: http://www.jfree.org/jfreechart/index.html + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * [Java is a trademark or registered trademark of Sun Microsystems, Inc. + * in the United States and other countries.] + * + * ----------------------- + * MultiShapeRenderer.java + * ----------------------- + * (C) Copyright 2007, by Object Refinery Limited and Contributors. + * + * Original Author: David Gilbert (for Object Refinery Limited); + * Contributor(s): David Forslund; + * + * Changes + * ------- + * 08-Oct-2007 : Version 1, based on patch 1780779 by David Forslund (DG); + * + */ + +package org.jfree.chart.renderer.category; + +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.List; + +import org.jfree.chart.LegendItem; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.event.RendererChangeEvent; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.util.BooleanList; +import org.jfree.chart.util.ObjectUtilities; +import org.jfree.chart.util.PublicCloneable; +import org.jfree.chart.util.ShapeUtilities; +import org.jfree.data.category.CategoryDataset; +import org.jfree.data.statistics.MultiValueCategoryDataset; + +/** + * A renderer that handles the multiple values from a + * {@link MultiValueCategoryDataset} by plotting a shape for each value for + * each given item in the dataset. + * + * @since 1.0.7 + */ +public class MultiShapeRenderer extends AbstractCategoryItemRenderer + implements Cloneable, PublicCloneable, Serializable { + + /** + * A table of flags that control (per series) whether or not shapes are + * filled. + */ + private BooleanList seriesShapesFilled; + + /** + * The default value returned by the getShapeFilled() method. + */ + private boolean baseShapesFilled; + + /** + * A flag that controls whether the fill paint is used for filling + * shapes. + */ + private boolean useFillPaint; + + /** + * A flag that controls whether outlines are drawn for shapes. + */ + private boolean drawOutlines; + + /** + * A flag that controls whether the outline paint is used for drawing shape + * outlines - if not, the regular series paint is used. + */ + private boolean useOutlinePaint; + + /** + * A flag that controls whether or not the x-position for each item is + * offset within the category according to the series. + */ + private boolean useSeriesOffset; + + /** + * The item margin used for series offsetting - this allows the positioning + * to match the bar positions of the {@link BarRenderer} class. + */ + private double itemMargin; + + /** + * Constructs a new renderer. + */ + public MultiShapeRenderer() { + this.seriesShapesFilled = new BooleanList(); + this.baseShapesFilled = true; + this.useFillPaint = false; + this.drawOutlines = false; + this.useOutlinePaint = false; + this.useSeriesOffset = true; + this.itemMargin = 0.20; + } + + /** + * Returns the flag that controls whether or not the x-position for each + * data item is offset within the category according to the series. + * + * @return A boolean. + * + * @see #setUseSeriesOffset(boolean) + */ + public boolean getUseSeriesOffset() { + return this.useSeriesOffset; + } + + /** + * Sets the flag that controls whether or not the x-position for each + * data item is offset within its category according to the series, and + * sends a {@link RendererChangeEvent} to all registered listeners. + * + * @param offset the offset. + * + * @see #getUseSeriesOffset() + */ + public void setUseSeriesOffset(boolean offset) { + this.useSeriesOffset = offset; + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Returns the item margin, which is the gap between items within a + * category (expressed as a percentage of the overall category width). + * This can be used to match the offset alignment with the bars drawn by + * a {@link BarRenderer}). + * + * @return The item margin. + * + * @see #setItemMargin(double) + * @see #getUseSeriesOffset() + */ + public double getItemMargin() { + return this.itemMargin; + } + + /** + * Sets the item margin, which is the gap between items within a category + * (expressed as a percentage of the overall category width), and sends + * a {@link RendererChangeEvent} to all registered listeners. + * + * @param margin the margin (0.0 <= margin < 1.0). + * + * @see #getItemMargin() + * @see #getUseSeriesOffset() + */ + public void setItemMargin(double margin) { + if (margin < 0.0 || margin >= 1.0) { + throw new IllegalArgumentException("Requires 0.0 <= margin < 1.0."); + } + this.itemMargin = margin; + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Returns <code>true</code> if outlines should be drawn for shapes, and + * <code>false</code> otherwise. + * + * @return A boolean. + * + * @see #setDrawOutlines(boolean) + */ + public boolean getDrawOutlines() { + return this.drawOutlines; + } + + /** + * Sets the flag that controls whether outlines are drawn for + * shapes, and sends a {@link RendererChangeEvent} to all registered + * listeners. + * <p/> + * In some cases, shapes look better if they do NOT have an outline, but + * this flag allows you to set your own preference. + * + * @param flag the flag. + * + * @see #getDrawOutlines() + */ + public void setDrawOutlines(boolean flag) { + this.drawOutlines = flag; + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Returns the flag that controls whether the outline paint is used for + * shape outlines. If not, the regular series paint is used. + * + * @return A boolean. + * + * @see #setUseOutlinePaint(boolean) + */ + public boolean getUseOutlinePaint() { + return this.useOutlinePaint; + } + + /** + * Sets the flag that controls whether the outline paint is used for shape + * outlines. + * + * @param use the flag. + * + * @see #getUseOutlinePaint() + */ + public void setUseOutlinePaint(boolean use) { + this.useOutlinePaint = use; + notifyListeners(new RendererChangeEvent(this)); + } + + // SHAPES FILLED + + /** + * Returns the flag used to control whether or not the shape for an item + * is filled. The default implementation passes control to the + * <code>getSeriesShapesFilled</code> method. You can override this method + * if you require different behaviour. + * + * @param series the series index (zero-based). + * @param item the item index (zero-based). + * @return A boolean. + */ + public boolean getItemShapeFilled(int series, int item) { + return getSeriesShapesFilled(series); + } + + /** + * Returns the flag used to control whether or not the shapes for a series + * are filled. + * + * @param series the series index (zero-based). + * @return A boolean. + */ + public boolean getSeriesShapesFilled(int series) { + Boolean flag = this.seriesShapesFilled.getBoolean(series); + if (flag != null) { + return flag.booleanValue(); + } + else { + return this.baseShapesFilled; + } + + } + + /** + * Sets the 'shapes filled' flag for a series. + * + * @param series the series index (zero-based). + * @param filled the flag. + */ + public void setSeriesShapesFilled(int series, Boolean filled) { + this.seriesShapesFilled.setBoolean(series, filled); + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Sets the 'shapes filled' flag for a series. + * + * @param series the series index (zero-based). + * @param filled the flag. + */ + public void setSeriesShapesFilled(int series, boolean filled) { + this.seriesShapesFilled.setBoolean(series, Boolean.valueOf(filled)); + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Returns the base 'shape filled' attribute. + * + * @return The base flag. + */ + public boolean getBaseShapesFilled() { + return this.baseShapesFilled; + } + + /** + * Sets the base 'shapes filled' flag. + * + * @param flag the flag. + */ + public void setBaseShapesFilled(boolean flag) { + this.baseShapesFilled = flag; + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Returns <code>true</code> if the renderer should use the fill paint + * setting to fill shapes, and <code>false</code> if it should just + * use the regular paint. + * + * @return A boolean. + */ + public boolean getUseFillPaint() { + return this.useFillPaint; + } + + /** + * Sets the flag that controls whether the fill paint is used to fill + * shapes, and sends a {@link RendererChangeEvent} to all + * registered listeners. + * + * @param flag the flag. + */ + public void setUseFillPaint(boolean flag) { + this.useFillPaint = flag; + notifyListeners(new RendererChangeEvent(this)); + } + + /** + * Draw a single data item. + * + * @param g2 the graphics device. + * @param state the renderer state. + * @param dataArea the area in which the data is drawn. + * @param plot the plot. + * @param domainAxis the domain axis. + * @param rangeAxis the range axis. + * @param dataset the dataset. + * @param row the row index (zero-based). + * @param column the column index (zero-based). + * @param pass the pass index. + */ + public void drawItem(Graphics2D g2, CategoryItemRendererState state, + Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, + ValueAxis rangeAxis, CategoryDataset dataset, int row, int column, + int pass) { + + // do nothing if item is not visible + if (!getItemVisible(row, column)) { + return; + } + + PlotOrientation orientation = plot.getOrientation(); + + MultiValueCategoryDataset d = (MultiValueCategoryDataset) dataset; + List values = d.getValues(row, column); + if (values == null) { + return; + } + int valueCount = values.size(); + for (int i = 0; i < valueCount; i++) { + // current data point... + double x1; + if (this.useSeriesOffset) { + x1 = domainAxis.getCategorySeriesMiddle(dataset.getColumnKey( + column), dataset.getRowKey(row), dataset, + this.itemMargin, dataArea, plot.getDomainAxisEdge()); + } + else { + x1 = domainAxis.getCategoryMiddle(column, getColumnCount(), + dataArea, plot.getDomainAxisEdge()); + } + Number n = (Number) values.get(i); + double value = n.doubleValue(); + double y1 = rangeAxis.valueToJava2D(value, dataArea, + plot.getRangeAxisEdge()); + + Shape shape = getItemShape(row, column); + if (orientation == PlotOrientation.HORIZONTAL) { + shape = ShapeUtilities.createTranslatedShape(shape, y1, x1); + } + else if (orientation == PlotOrientation.VERTICAL) { + shape = ShapeUtilities.createTranslatedShape(shape, x1, y1); + } + if (getItemShapeFilled(row, column)) { + if (this.useFillPaint) { + g2.setPaint(getItemFillPaint(row, column)); + } + else { + g2.setPaint(getItemPaint(row, column)); + } + g2.fill(shape); + } + if (this.drawOutlines) { + if (this.useOutlinePaint) { + g2.setPaint(getItemOutlinePaint(row, column)); + } + else { + g2.setPaint(getItemPaint(row, column)); + } + g2.setStroke(getItemOutlineStroke(row, column)); + g2.draw(shape); + } + } + + } + + /** + * Returns a legend item for a series. + * + * @param datasetIndex the dataset index (zero-based). + * @param series the series index (zero-based). + * + * @return The legend item. + */ + public LegendItem getLegendItem(int datasetIndex, int series) { + + CategoryPlot cp = getPlot(); + if (cp == null) { + return null; + } + + if (isSeriesVisible(series) && isSeriesVisibleInLegend(series)) { + CategoryDataset dataset = cp.getDataset(datasetIndex); + String label = getLegendItemLabelGenerator().generateLabel( + dataset, series); + String description = label; + String toolTipText = null; + if (getLegendItemToolTipGenerator() != null) { + toolTipText = getLegendItemToolTipGenerator().generateLabel( + dataset, series); + } + String urlText = null; + if (getLegendItemURLGenerator() != null) { + urlText = getLegendItemURLGenerator().generateLabel( + dataset, series); + } + Shape shape = lookupSeriesShape(series); + Paint paint = lookupSeriesPaint(series); + Paint fillPaint = (this.useFillPaint + ? getItemFillPaint(series, 0) : paint); + boolean shapeOutlineVisible = this.drawOutlines; + Paint outlinePaint = (this.useOutlinePaint + ? getItemOutlinePaint(series, 0) : paint); + Stroke outlineStroke = lookupSeriesOutlineStroke(series); + LegendItem result = new LegendItem(label, description, toolTipText, + urlText, true, shape, getItemShapeFilled(series, 0), + fillPaint, shapeOutlineVisible, outlinePaint, outlineStroke, + false, new Line2D.Double(-7.0, 0.0, 7.0, 0.0), + getItemStroke(series, 0), getItemPaint(series, 0)); + result.setDataset(dataset); + result.setDatasetIndex(datasetIndex); + result.setSeriesKey(dataset.getRowKey(series)); + result.setSeriesIndex(series); + return result; + } + return null; + + } + + /** + * Tests this renderer for equality with an arbitrary object. + * + * @param obj the object (<code>null</code> permitted). + * @return A boolean. + */ + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof MultiShapeRenderer)) { + return false; + } + MultiShapeRenderer that = (MultiShapeRenderer) obj; + if (!ObjectUtilities.equal(this.seriesShapesFilled, + that.seriesShapesFilled)) { + return false; + } + if (this.baseShapesFilled != that.baseShapesFilled) { + return false; + } + if (this.useFillPaint != that.useFillPaint) { + return false; + } + if (this.drawOutlines != that.drawOutlines) { + return false; + } + if (this.useOutlinePaint != that.useOutlinePaint) { + return false; + } + if (this.useSeriesOffset != that.useSeriesOffset) { + return false; + } + if (this.itemMargin != that.itemMargin) { + return false; + } + return super.equals(obj); + } + + /** + * Returns an independent copy of the renderer. + * + * @return A clone. + * + * @throws CloneNotSupportedException should not happen. + */ + public Object clone() throws CloneNotSupportedException { + MultiShapeRenderer clone = (MultiShapeRenderer) super.clone(); + clone.seriesShapesFilled + = (BooleanList) this.seriesShapesFilled.clone(); + return clone; + } + + /** + * Provides serialization support. + * + * @param stream the output stream. + * @throws java.io.IOException if there is an I/O error. + */ + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + + } + + /** + * Provides serialization support. + * + * @param stream the input stream. + * @throws java.io.IOException if there is an I/O error. + * @throws ClassNotFoundException if there is a classpath problem. + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + + } + +} Added: trunk/source/org/jfree/data/statistics/DefaultMultiValueCategoryDataset.java =================================================================== --- trunk/source/org/jfree/data/statistics/DefaultMultiValueCategoryDataset.java (rev 0) +++ trunk/source/org/jfree/data/statistics/DefaultMultiValueCategoryDataset.java 2007-10-08 14:15:05 UTC (rev 292) @@ -0,0 +1,404 @@ +/* =========================================================== + * JFreeChart : a free chart library for the Java(tm) platform + * =========================================================== + * + * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. + * + * Project Info: http://www.jfree.org/jfreechart/index.html + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * [Java is a trademark or registered trademark of Sun Microsystems, Inc. + * in the United States and other countries.] + * + * ------------------------------------- + * DefaultMultiValueCategoryDataset.java + * ------------------------------------- + * (C) Copyright 2007, by David Forslund and Contributors. + * + * Original Author: David Forslund; + * Contributor(s): David Gilbert (for Object Refinery Limited);; + * + * Changes + * ------- + * 08-Oct-2007 : Version 1, see patch 1780779 (DG); + * + */ + +package org.jfree.data.statistics; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.jfree.chart.util.PublicCloneable; +import org.jfree.data.KeyedObjects2D; +import org.jfree.data.Range; +import org.jfree.data.RangeInfo; +import org.jfree.data.general.AbstractDataset; +import org.jfree.data.general.DatasetChangeEvent; + +/** + * A category dataset that defines multiple values for each item. + * + * @since 1.0.7 + */ +public class DefaultMultiValueCategoryDataset extends AbstractDataset + implements MultiValueCategoryDataset, RangeInfo, PublicCloneable { + + /** + * Storage for the data. + */ + protected KeyedObjects2D data; + + /** + * The minimum range value. + */ + private Number minimumRangeValue; + + /** + * The maximum range value. + */ + private Number maximumRangeValue; + + /** + * The range of values. + */ + private Range rangeBounds; + + /** + * Creates a new dataset. + */ + public DefaultMultiValueCategoryDataset() { + this.data = new KeyedObjects2D(); + this.minimumRangeValue = null; + this.maximumRangeValue = null; + this.rangeBounds = new Range(0.0, 0.0); + } + + /** + * Adds a list of values to the dataset (<code>null</code> and Double.NaN + * items are automatically removed) and sends a {@link DatasetChangeEvent} + * to all registered listeners. + * + * @param values a list of values (<code>null</code> not permitted). + * @param rowKey the row key (<code>null</code> not permitted). + * @param columnKey the column key (<code>null</code> not permitted). + */ + public void add(List values, Comparable rowKey, Comparable columnKey) { + + if (values == null) { + throw new IllegalArgumentException("Null 'values' argument."); + } + if (rowKey == null) { + throw new IllegalArgumentException("Null 'rowKey' argument."); + } + if (columnKey == null) { + throw new IllegalArgumentException("Null 'columnKey' argument."); + } + List vlist = new ArrayList(values.size()); + Iterator iterator = values.listIterator(); + while (iterator.hasNext()) { + Object obj = iterator.next(); + if (obj instanceof Number) { + Number n = (Number) obj; + double v = n.doubleValue(); + if (!Double.isNaN(v)) { + vlist.add(n); + } + } + } + Collections.sort(vlist); + this.data.addObject(vlist, rowKey, columnKey); + + if (vlist.size() > 0) { + double maxval = Double.NEGATIVE_INFINITY; + double minval = Double.POSITIVE_INFINITY; + for (int i = 0; i < vlist.size(); i++) { + Number n = (Number) vlist.get(i); + double v = n.doubleValue(); + minval = Math.min(minval, v); + maxval = Math.max(maxval, v); + } + + // update the cached range values... + if (this.maximumRangeValue == null) { + this.maximumRangeValue = new Double(maxval); + } + else if (maxval > this.maximumRangeValue.doubleValue()) { + this.maximumRangeValue = new Double(maxval); + } + + if (this.minimumRangeValue == null) { + this.minimumRangeValue = new Double(minval); + } + else if (minval < this.minimumRangeValue.doubleValue()) { + this.minimumRangeValue = new Double(minval); + } + this.rangeBounds = new Range(this.minimumRangeValue.doubleValue(), + this.maximumRangeValue.doubleValue()); + } + + fireDatasetChanged(); + } + + /** + * Returns a list (possibly empty) of the values for the specified item. + * The returned list should be unmodifiable. + * + * @param row the row index (zero-based). + * @param column the column index (zero-based). + * + * @return The list of values. + */ + public List getValues(int row, int column) { + List values = (List) this.data.getObject(row, column); + if (values != null) { + return Collections.unmodifiableList(values); + } + else { + return null; + } + } + + /** + * Returns a list (possibly empty) of the values for the specified item. + * The returned list should be unmodifiable. + * + * @param rowKey the row key (<code>null</code> not permitted). + * @param columnKey the column key (<code>null</code> not permitted). + * + * @return The list of values. + */ + public List getValues(Comparable rowKey, Comparable columnKey) { + return Collections.unmodifiableList((List) this.data.getObject(rowKey, + columnKey)); + } + + /** + * Returns the average value for the specified item. + * + * @param row the row key. + * @param column the column key. + * + * @return The average value. + */ + public Number getValue(Comparable row, Comparable column) { + List l = (List) this.data.getObject(row, column); + double average = 0.0d; + int count = 0; + if (l != null && l.size() > 0) { + for (int i = 0; i < l.size(); i++) { + Number n = (Number) l.get(i); + average += n.doubleValue(); + count += 1; + } + if (count > 0) { + average = average / count; + } + } + if (count == 0) { + return null; + } + return new Double(average); + } + + /** + * Returns the average value for the specified item. + * + * @param row the row index. + * @param column the column index. + * + * @return The average value. + */ + public Number getValue(int row, int column) { + List l = (List) this.data.getObject(row, column); + double average = 0.0d; + int count = 0; + if (l != null && l.size() > 0) { + for (int i = 0; i < l.size(); i++) { + Number n = (Number) l.get(i); + average += n.doubleValue(); + count += 1; + } + if (count > 0) { + average = average / count; + } + } + if (count == 0) { + return null; + } + return new Double(average); + } + + /** + * Returns the column index for a given key. + * + * @param key the column key. + * + * @return The column index. + */ + public int getColumnIndex(Comparable key) { + return this.data.getColumnIndex(key); + } + + /** + * Returns a column key. + * + * @param column the column index (zero-based). + * + * @return The column key. + */ + public Comparable getColumnKey(int column) { + return this.data.getColumnKey(column); + } + + /** + * Returns the column keys. + * + * @return The keys. + */ + public List getColumnKeys() { + return this.data.getColumnKeys(); + } + + /** + * Returns the row index for a given key. + * + * @param key the row key. + * + * @return The row index. + */ + public int getRowIndex(Comparable key) { + return this.data.getRowIndex(key); + } + + /** + * Returns a row key. + * + * @param row the row index (zero-based). + * + * @return The row key. + */ + public Comparable getRowKey(int row) { + return this.data.getRowKey(row); + } + + /** + * Returns the row keys. + * + * @return The keys. + */ + public List getRowKeys() { + return this.data.getRowKeys(); + } + + /** + * Returns the number of rows in the table. + * + * @return The row count. + */ + public int getRowCount() { + return this.data.getRowCount(); + } + + /** + * Returns the number of columns in the table. + * + * @return The column count. + */ + public int getColumnCount() { + return this.data.getColumnCount(); + } + + /** + * Returns the minimum y-value in the dataset. + * + * @param includeInterval a flag that determines whether or not the + * y-interval is taken into account. + * + * @return The minimum value. + */ + public double getRangeLowerBound(boolean includeInterval) { + double result = Double.NaN; + if (this.minimumRangeValue != null) { + result = this.minimumRangeValue.doubleValue(); + } + return result; + } + + /** + * Returns the maximum y-value in the dataset. + * + * @param includeInterval a flag that determines whether or not the + * y-interval is taken into account. + * + * @return The maximum value. + */ + public double getRangeUpperBound(boolean includeInterval) { + double result = Double.NaN; + if (this.maximumRangeValue != null) { + result = this.maximumRangeValue.doubleValue(); + } + return result; + } + + /** + * Returns the range of the values in this dataset's range. + * + * @param includeInterval a flag that determines whether or not the + * y-interval is taken into account. + * @return The range. + */ + public Range getRangeBounds(boolean includeInterval) { + return this.rangeBounds; + } + + /** + * Tests this dataset for equality with an arbitrary object. + * + * @param obj the object (<code>null</code> permitted). + * + * @return A boolean. + */ + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof DefaultMultiValueCategoryDataset)) { + return false; + } + DefaultMultiValueCategoryDataset that + = (DefaultMultiValueCategoryDataset) obj; + return this.data.equals(that.data); + } + + /** + * Returns a clone of this instance. + * + * @return A clone. + * + * @throws CloneNotSupportedException if the dataset cannot be cloned. + */ + public Object clone() throws CloneNotSupportedException { + DefaultMultiValueCategoryDataset clone + = (DefaultMultiValueCategoryDataset) super.clone(); + clone.data = (KeyedObjects2D) this.data.clone(); + return clone; + } +} Added: trunk/source/org/jfree/data/statistics/MultiValueCategoryDataset.java =================================================================== --- trunk/source/org/jfree/data/statistics/MultiValueCategoryDataset.java (rev 0) +++ trunk/source/org/jfree/data/statistics/MultiValueCategoryDataset.java 2007-10-08 14:15:05 UTC (rev 292) @@ -0,0 +1,76 @@ +/* =========================================================== + * JFreeChart : a free chart library for the Java(tm) platform + * =========================================================== + * + * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. + * + * Project Info: http://www.jfree.org/jfreechart/index.html + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * [Java is a trademark or registered trademark of Sun Microsystems, Inc. + * in the United States and other countries.] + * + * ------------------------------ + * MultiValueCategoryDataset.java + * ------------------------------ + * (C) Copyright 2007, by David Forslund and Contributors. + * + * Original Author: David Forslund; + * Contributor(s): David Gilbert (for Object Refinery Limited);; + * + * Changes + * ------- + * 08-Oct-2007 : Version 1, see patch 1780779 (DG); + * + */ + +package org.jfree.data.statistics; + +import org.jfree.data.category.CategoryDataset; + +import java.util.List; + +/** + * A category dataset that defines multiple values for each item. + * + * @since 1.0.7 + */ +public interface MultiValueCategoryDataset extends CategoryDataset { + + /** + * Returns a list (possibly empty) of the values for the specified item. + * The returned list should be unmodifiable. + * + * @param row the row index (zero-based). + * @param column the column index (zero-based). + * + * @return The list of values. + */ + public List getValues(int row, int column); + + /** + * Returns a list (possibly empty) of the values for the specified item. + * The returned list should be unmodifiable. + * + * @param rowKey the row key (<code>null</code> not permitted). + * @param columnKey the column key (<code>null</code> not permitted). + * + * @return The list of values. + */ + public List getValues(Comparable rowKey, Comparable columnKey); + +} \ No newline at end of file Added: trunk/tests/org/jfree/chart/renderer/category/junit/MultiShapeRendererTests.java =================================================================== --- trunk/tests/org/jfree/chart/renderer/category/junit/MultiShapeRendererTests.java (rev 0) +++ trunk/tests/org/jfree/chart/renderer/category/junit/MultiShapeRendererTests.java 2007-10-08 14:15:05 UTC (rev 292) @@ -0,0 +1,217 @@ +/* =========================================================== + * JFreeChart : a free chart library for the Java(tm) platform + * =========================================================== + * + * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. + * + * Project Info: http://www.jfree.org/jfreechart/index.html + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * [Java is a trademark or registered trademark of Sun Microsystems, Inc. + * in the United States and other countries.] + * + * ---------------------------- + * MultiShapeRendererTests.java + * ---------------------------- + * (C) Copyright 2007, by Object Refinery Limited and Contributors. + * + * Original Author: David Gilbert (for Object Refinery Limited); + * Contributor(s): -; + * + * Changes + * ------- + * 08-Oct-2007 : Version 1 (DG); + * + */ + +package org.jfree.chart.renderer.category.junit; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.jfree.chart.renderer.category.MultiShapeRenderer; + +/** + * Tests for the {@link MultiShapeRenderer} class. + */ +public class MultiShapeRendererTests extends TestCase { + + /** + * Returns the tests as a test suite. + * + * @return The test suite. + */ + public static Test suite() { + return new TestSuite(MultiShapeRendererTests.class); + } + + /** + * Constructs a new set of tests. + * + * @param name the name of the tests. + */ + public MultiShapeRendererTests(String name) { + super(name); + } + + /** + * Test that the equals() method distinguishes all fields. + */ + public void testEquals() { + + MultiShapeRenderer r1 = new MultiShapeRenderer(); + MultiShapeRenderer r2 = new MultiShapeRenderer(); + assertEquals(r1, r2); + + r1.setSeriesShapesFilled(1, true); + assertFalse(r1.equals(r2)); + r2.setSeriesShapesFilled(1, true); + assertTrue(r1.equals(r2)); + + r1.setBaseShapesFilled(false); + assertFalse(r1.equals(r2)); + r2.setBaseShapesFilled(false); + assertTrue(r1.equals(r2)); + + r1.setUseFillPaint(true); + assertFalse(r1.equals(r2)); + r2.setUseFillPaint(true); + assertTrue(r1.equals(r2)); + + r1.setDrawOutlines(true); + assertFalse(r1.equals(r2)); + r2.setDrawOutlines(true); + assertTrue(r1.equals(r2)); + + r1.setUseOutlinePaint(true); + assertFalse(r1.equals(r2)); + r2.setUseOutlinePaint(true); + assertTrue(r1.equals(r2)); + + r1.setUseSeriesOffset(false); + assertFalse(r1.equals(r2)); + r2.setUseSeriesOffset(false); + assertTrue(r1.equals(r2)); + + } + + /** + * Two objects that are equal are required to return the same hashCode. + */ + public void testHashcode() { + MultiShapeRenderer r1 = new MultiShapeRenderer(); + MultiShapeRenderer r2 = new MultiShapeRenderer(); + assertTrue(r1.equals(r2)); + int h1 = r1.hashCode(); + int h2 = r2.hashCode(); + assertEquals(h1, h2); + } + + /** + * Confirm that cloning works. + */ + public void testCloning() { + MultiShapeRenderer r1 = new MultiShapeRenderer(); + MultiShapeRenderer r2 = null; + try { + r2 = (MultiShapeRenderer) r1.clone(); + } + catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assertTrue(r1 != r2); + assertTrue(r1.getClass() == r2.getClass()); + assertTrue(r1.equals(r2)); + + assertTrue(checkIndependence(r1, r2)); + + } + + /** + * Checks that the two renderers are equal but independent of one another. + * + * @param r1 renderer 1. + * @param r2 renderer 2. + * + * @return A boolean. + */ + private boolean checkIndependence(MultiShapeRenderer r1, + MultiShapeRenderer r2) { + + // should be equal... + if (!r1.equals(r2)) { + return false; + } + + // and independent... + r1.setSeriesShapesFilled(1, true); + if (r1.equals(r2)) { + return false; + } + r2.setSeriesShapesFilled(1, true); + if (!r1.equals(r2)) { + return false; + } + + r1.setBaseShapesFilled(false); + r2.setBaseShapesFilled(true); + if (r1.equals(r2)) { + return false; + } + r2.setBaseShapesFilled(false); + if (!r1.equals(r2)) { + return false; + } + return true; + + } + + /** + * Serialize an instance, restore it, and check for equality. + */ + public void testSerialization() { + + MultiShapeRenderer r1 = new MultiShapeRenderer(); + MultiShapeRenderer r2 = null; + + try { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(buffer); + out.writeObject(r1); + out.close(); + + ObjectInput in = new ObjectInputStream( + new ByteArrayInputStream(buffer.toByteArray())); + r2 = (MultiShapeRenderer) in.readObject(); + in.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + assertEquals(r1, r2); + + } + +} Modified: trunk/tests/org/jfree/chart/renderer/category/junit/RendererCategoryPackageTests.java =================================================================== --- trunk/tests/org/jfree/chart/renderer/category/junit/RendererCategoryPackageTests.java 2007-10-08 13:53:33 UTC (rev 291) +++ trunk/tests/org/jfree/chart/renderer/category/junit/RendererCategoryPackageTests.java 2007-10-08 14:15:05 UTC (rev 292) @@ -2,7 +2,7 @@ * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * - * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. + * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * @@ -27,18 +27,17 @@ * --------------------------------- * RendererCategoryPackageTests.java * --------------------------------- - * (C) Copyright 2004, 2005, by Object Refinery Limited. + * (C) Copyright 2004-2007, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * - * $Id: RendererCategoryPackageTests.java,v 1.1.2.1 2006/10/03 15:41:34 mungady Exp $ - * * Changes: * -------- * 23-Aug-2004 : Restructured org.jfree.chart.renderer package (DG); * 18-Jan-2005 : Added main() method. * 15-Jun-2005 : Added new tests for StatisticalLineAndShapeRendererTests (DG); + * 08-Oct-2007 : Added MultiShapeRendererTests (DG); * */ @@ -77,6 +76,7 @@ suite.addTestSuite(LineAndShapeRendererTests.class); suite.addTestSuite(LineRenderer3DTests.class); suite.addTestSuite(MinMaxCategoryRendererTests.class); + suite.addTestSuite(MultiShapeRendererTests.class); suite.addTestSuite(StackedAreaRendererTests.class); suite.addTestSuite(StackedBarRendererTests.class); suite.addTestSuite(StackedBarRenderer3DTests.class); Modified: trunk/tests/org/jfree/data/statistics/junit/DataStatisticsPackageTests.java =================================================================== --- trunk/tests/org/jfree/data/statistics/junit/DataStatisticsPackageTests.java 2007-10-08 13:53:33 UTC (rev 291) +++ trunk/tests/org/jfree/data/statistics/junit/DataStatisticsPackageTests.java 2007-10-08 14:15:05 UTC (rev 292) @@ -2,7 +2,7 @@ * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * - * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. + * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * @@ -27,13 +27,11 @@ * ------------------------------- * DataStatisticsPackageTests.java * ------------------------------- - * (C) Copyright 2003-2005, by Object Refinery Limited and Contributors. + * (C) Copyright 2003-2007, by Object Refinery Limited and Contributors. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * - * $Id: DataStatisticsPackageTests.java,v 1.1.2.1 2006/10/03 15:41:41 mungady Exp $ - * * Changes * ------- * 28-Aug-2003 : Version 1 (DG); @@ -68,6 +66,7 @@ suite.addTestSuite(BoxAndWhiskerCalculatorTests.class); suite.addTestSuite(BoxAndWhiskerItemTests.class); suite.addTestSuite(DefaultBoxAndWhiskerCategoryDatasetTests.class); + suite.addTestSuite(DefaultMultiValueCategoryDatasetTests.class); suite.addTestSuite(DefaultStatisticalCategoryDatasetTests.class); suite.addTestSuite(HistogramBinTests.class); suite.addTestSuite(HistogramDatasetTests.class); Added: trunk/tests/org/jfree/data/statistics/junit/DefaultMultiValueCategoryDatasetTests.java =================================================================== --- trunk/tests/org/jfree/data/statistics/junit/DefaultMultiValueCategoryDatasetTests.java (rev 0) +++ trunk/tests/org/jfree/data/statistics/junit/DefaultMultiValueCategoryDatasetTests.java 2007-10-08 14:15:05 UTC (rev 292) @@ -0,0 +1,294 @@ +/* =========================================================== + * JFreeChart : a free chart library for the Java(tm) platform + * =========================================================== + * + * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. + * + * Project Info: http://www.jfree.org/jfreechart/index.html + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * [Java is a trademark or registered trademark of Sun Microsystems, Inc. + * in the United States and other countries.] + * + * ------------------------------------------ + * DefaultMultiValueCategoryDatasetTests.java + * ------------------------------------------ + * (C) Copyright 2007, by Object Refinery Limited and Contributors. + * + * Original Author: David Gilbert (for Object Refinery Limited); + * Contributor(s): -; + * + * Changes + * ------- + * 28-Sep-2007 : Version 1 (DG); + * + */ + +package org.jfree.data.statistics.junit; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.jfree.data.UnknownKeyException; +import org.jfree.data.statistics.DefaultMultiValueCategoryDataset; + +/** + * Tests for the {@link DefaultMultiValueCategoryDataset} class. + */ +public class DefaultMultiValueCategoryDatasetTests extends TestCase { + + /** + * Returns the tests as a test suite. + * + * @return The test suite. + */ + public static Test suite() { + return new TestSuite(DefaultMultiValueCategoryDatasetTests.class); + } + + /** + * Constructs a new set of tests. + * + * @param name the name of the tests. + */ + public DefaultMultiValueCategoryDatasetTests(String name) { + super(name); + } + + /** + * Some checks for the getValue() method. + */ + public void testGetValue() { + DefaultMultiValueCategoryDataset d + = new DefaultMultiValueCategoryDataset(); + List values = new ArrayList(); + values.add(new Integer(1)); + values.add(new Integer(2)); + d.add(values, "R1", "C1"); + assertEquals(new Double(1.5), d.getValue("R1", "C1")); + boolean pass = false; + try { + d.getValue("XX", "C1"); + } + catch (UnknownKeyException e) { + pass = true; + } + assertTrue(pass); + + pass = false; + try { + d.getValue("R1", "XX"); + } + catch (UnknownKeyException e) { + pass = true; + } + assertTrue(pass); + } + + /** + * A simple check for the getValue(int, int) method. + */ + public void testGetValue2() { + DefaultMultiValueCategoryDataset d + = new DefaultMultiValueCategoryDataset(); + boolean pass = false; + try { + /* Number n =*/ d.getValue(0, 0); + } + catch (IndexOutOfBoundsException e) { + pass = true; + } + assertTrue(pass); + } + + /** + * Some tests for the getRowCount() method. + */ + public void testGetRowCount() { + DefaultMultiValueCategoryDataset d + = new DefaultMultiValueCategoryDataset(); + assertTrue(d.getRowCount() == 0); + List values = new ArrayList(); + d.add(values, "R1", "C1"); + assertTrue(d.getRowCount() == 1); + + d.add(values, "R2", "C1"); + assertTrue(d.getRowCount() == 2); + + d.add(values, "R2", "C1"); + assertTrue(d.getRowCount() == 2); + } + + /** + * Some tests for the getColumnCount() method. + */ + public void testGetColumnCount() { + DefaultMultiValueCategoryDataset d + = new DefaultMultiValueCategoryDataset(); + assertTrue(d.getColumnCount() == 0); + + List values = new ArrayList(); + d.add(values, "R1", "C1"); + assertTrue(d.getColumnCount() == 1); + + d.add(values, "R1", "C2"); + assertTrue(d.getColumnCount() == 2); + + d.add(values, "R1", "C2"); + assertTrue(d.getColumnCount() == 2); + + } + + /** + * Confirm that the equals method can distinguish all the required fields. + */ + public void testEquals() { + DefaultMultiValueCategoryDataset d1 + = new DefaultMultiValueCategoryDataset(); + DefaultMultiValueCategoryDataset d2 + = new DefaultMultiValueCategoryDataset(); + assertTrue(d1.equals(d2)); + assertTrue(d2.equals(d1)); + + List values = new ArrayList(); + d1.add(values, "R1", "C1"); + assertFalse(d1.equals(d2)); + d2.add(values, "R1", "C1"); + assertTrue(d1.equals(d2)); + + values.add(new Integer(99)); + d1.add(values, "R1", "C1"); + assertFalse(d1.equals(d2)); + d2.add(values, "R1", "C1"); + assertTrue(d1.equals(d2)); + + values.add(new Integer(99)); + d1.add(values, "R1", "C2"); + assertFalse(d1.equals(d2)); + d2.add(values, "R1", "C2"); + assertTrue(d1.equals(d2)); + } + + /** + * Serialize an instance, restore it, and check for equality. + */ + public void testSerialization() { + + DefaultMultiValueCategoryDataset d1 + = new DefaultMultiValueCategoryDataset(); + DefaultMultiValueCategoryDataset d2 + = new DefaultMultiValueCategoryDataset(); + + try { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(buffer); + out.writeObject(d1); + out.close(); + + ObjectInput in = new ObjectInputStream( + new ByteArrayInputStream(buffer.toByteArray())); + d2 = (DefaultMultiValueCategoryDataset) in.readObject(); + in.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + assertEquals(d1, d2); + + } + + /** + * Some checks for the add() method. + */ + public void testAddValue() { + DefaultMultiValueCategoryDataset d1 + = new DefaultMultiValueCategoryDataset(); + + boolean pass = false; + try { + d1.add(null, "R1", "C1"); + } + catch (IllegalArgumentException e) { + pass = true; + } + assertTrue(pass); + + List values = new ArrayList(); + d1.add(values, "R2", "C1"); + assertEquals(values, d1.getValues("R2", "C1")); + + pass = false; + try { + d1.add(values, null, "C2"); + } + catch (IllegalArgumentException e) { + pass = true; + } + assertTrue(pass); + } + + /** + * Confirm that cloning works. + */ + public void testCloning() { + DefaultMultiValueCategoryDataset d1 + = new DefaultMultiValueCategoryDataset(); + DefaultMultiValueCategoryDataset d2 = null; + try { + d2 = (DefaultMultiValueCategoryDataset) d1.clone(); + } + catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assertTrue(d1 != d2); + assertTrue(d1.getClass() == d2.getClass()); + assertTrue(d1.equals(d2)); + + // try a dataset with some content... + List values = new ArrayList(); + values.add(new Integer(99)); + d1.add(values, "R1", "C1"); + try { + d2 = (DefaultMultiValueCategoryDataset) d1.clone(); + } + catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assertTrue(d1 != d2); + assertTrue(d1.getClass() == d2.getClass()); + assertTrue(d1.equals(d2)); + + // check that the clone doesn't share the same underlying arrays. + List values2 = new ArrayList(); + values2.add(new Integer(111)); + d1.add(values2, "R2", "C2"); + assertFalse(d1.equals(d2)); + d2.add(values2, "R2", "C2"); + assertTrue(d1.equals(d2)); + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |