Clone exception when copying ChartPanel to clipboard

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
lynnskii
Posts: 5
Joined: Wed Apr 20, 2016 8:37 am
antibot: No, of course not.

Clone exception when copying ChartPanel to clipboard

Post by lynnskii » Wed Apr 20, 2016 8:51 am

I am in the process of upgrading from v. 1.0.14 to 1.0.19 and am getting a CloneNotSupportedException when I try to copy a ChartPanel to the system clipboard in Windows via ChartPanel.doCopy().
java.lang.RuntimeException: java.lang.CloneNotSupportedException: Failed to clone.
at org.jfree.chart.util.CloneUtils.cloneMapValues(CloneUtils.java:100)
at org.jfree.chart.renderer.AbstractRenderer.clone(AbstractRenderer.java:3255)
at org.jfree.chart.renderer.xy.AbstractXYItemRenderer.clone(AbstractXYItemRenderer.java:1484)
at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.clone(XYLineAndShapeRenderer.java:1267)
at org.jfree.util.ObjectUtilities.clone(ObjectUtilities.java:170)
at org.jfree.chart.util.CloneUtils.cloneMapValues(CloneUtils.java:98)
at org.jfree.chart.plot.XYPlot.clone(XYPlot.java:5570)
at org.jfree.chart.JFreeChart.clone(JFreeChart.java:1721)
at org.jfree.chart.ChartTransferable.<init>(ChartTransferable.java:155)
at org.jfree.chart.ChartPanel.doCopy(ChartPanel.java:2695)

The exception ultimately stems from AbstractRenderer.clone() where it's trying to clone the itemLabelFontMap, which is a Map<Integer,Font>: clone.itemLabelFontMap = CloneUtils.cloneMapValues(this.itemLabelFontMap).
However, java.awt.Font does not implement the Cloneable interface, so the exception is thrown by CloneUtils.cloneMapValues().

In 1.0.14, this was stored as an ObjectList, and the clone method did the following (which didn't give me any problems)
clone.itemLabelFontList = (ObjectList) this.itemLabelFontList.clone();

Is this a bug in 1.0.19, or is there something I'm missing here?

alex80
Posts: 1
Joined: Sun Apr 17, 2016 5:03 pm
antibot: No, of course not.

Re: Clone exception when copying ChartPanel to clipboard

Post by alex80 » Wed Apr 20, 2016 1:21 pm

I think it's a bug...
Thinking about a quadcopter? Check this [url=hhttp://djibestdrones.com/dji-mavic-air-review/]Mavic Air 4 review[/url] before you make a purchase!

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Clone exception when copying ChartPanel to clipboard

Post by paradoxoff » Wed Apr 20, 2016 10:05 pm

alex80 wrote:I think it's a bug...
I agree. Instances of java.awt.Font are immutable AFAICS, so there is no need to clone anything.
I am wondering more and more whether the change from ObjectList to Map<Integer, AnObject> that was implemented a few versions ago was a good design decision.

lynnskii
Posts: 5
Joined: Wed Apr 20, 2016 8:37 am
antibot: No, of course not.

Re: Clone exception when copying ChartPanel to clipboard

Post by lynnskii » Wed Apr 20, 2016 10:16 pm

Do you happen to know offhand with what version that started?

My solution is either to go back to 1.0.14 (or later but before the change), or I've been playing around with making a CloneableFont class and subclassing the XYLineAndShapeRenderer to override the setXXX(Font) methods to use the CloneableFonts instead, which I'd rather not have to do if I can avoid it.

I also noticed while digging into the ChartPanel.doCopy() method, that there's a ChartTransferable class whose constructors take a cloneData boolean, but when I looked at the code, it's not doing anything with that boolean and always clones.

lynnskii
Posts: 5
Joined: Wed Apr 20, 2016 8:37 am
antibot: No, of course not.

Re: Clone exception when copying ChartPanel to clipboard

Post by lynnskii » Wed Apr 20, 2016 10:37 pm

Tried my CloneableFont and subclassing the renderer approach for giggles. It worked for the fonts, but now I'm running into the same issue for ItemLabelPosition objects. I have a feeling there will be more, so I'm going to ditch 1.0.19 and go back to before the Maps replaced the ObjectLists.

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Clone exception when copying ChartPanel to clipboard

Post by paradoxoff » Mon Apr 25, 2016 3:18 pm

lynnskii wrote:Do you happen to know offhand with what version that started?
I came across this change after reading this thread.
I can´t tell when this change was introduced. According to the thread above, David made this change while fixing a bug in the ObjectList class. However, the documentation of this class doesn´t mention a change after 2004.

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: Clone exception when copying ChartPanel to clipboard

Post by david.gilbert » Mon Apr 25, 2016 8:59 pm

Hi,

It's definitely a bug. I modified the unit test for cloning renderers to expose the bug, and fixed it for the upcoming 1.0.20 release. Here's the fix:

Code: Select all

# This patch file was generated by NetBeans IDE
# It uses platform neutral UTF-8 encoding and \n newlines.
--- AbstractRenderer.java (8a2e412)
+++ AbstractRenderer.java (b66a321)
@@ -93,6 +93,7 @@
  * 03-Jul-2013 : Use ParamChecks (DG);
  * 09-Apr-2014 : Remove use of ObjectList (DG);
  * 24-Aug-2014 : Add begin/endElementGroup() (DG);
+ * 25-Apr-2016 : Fix cloning test failuer (DG);
  *
  */
 
@@ -3286,7 +3287,7 @@
         // 'itemLabelFont' : immutable, no need to clone reference
         if (this.itemLabelFontMap != null) {
             clone.itemLabelFontMap 
-                    = CloneUtils.cloneMapValues(this.itemLabelFontMap);
+                    = new HashMap<Integer, Font>(this.itemLabelFontMap);
         }
         // 'baseItemLabelFont' : immutable, no need to clone reference
 
@@ -3320,7 +3321,8 @@
             clone.legendShapeList = (ShapeList) this.legendShapeList.clone();
         }
         if (this.legendTextFontMap != null) {
-            clone.legendTextFontMap = CloneUtils.cloneMapValues(
+            // Font objects are immutable so just shallow copy the map
+            clone.legendTextFontMap = new HashMap<Integer, Font>(
                     this.legendTextFontMap);
         }
         if (this.legendTextPaint != null) {
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

lynnskii
Posts: 5
Joined: Wed Apr 20, 2016 8:37 am
antibot: No, of course not.

Re: Clone exception when copying ChartPanel to clipboard

Post by lynnskii » Mon Apr 25, 2016 10:01 pm

David,

While you're in there fixing that, I experienced the same issue when trying to clone the maps with ItemLabelPosition, which is Serializable but not Cloneable. You might check for any others. Thanks.

// 'postiveItemLabelAnchor' : immutable, no need to clone reference
if (this.positiveItemLabelPositionMap != null) {
clone.positiveItemLabelPositionMap = CloneUtils.cloneMapValues(
this.positiveItemLabelPositionMap);
}
// 'baseItemLabelAnchor' : immutable, no need to clone reference

// 'negativeItemLabelAnchor' : immutable, no need to clone reference
if (this.negativeItemLabelPositionMap != null) {
clone.negativeItemLabelPositionMap = CloneUtils.cloneMapValues(
this.negativeItemLabelPositionMap);
}
// 'baseNegativeItemLabelAnchor' : immutable, no need to clone reference

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: Clone exception when copying ChartPanel to clipboard

Post by david.gilbert » Wed Apr 27, 2016 8:57 pm

Sure, I'll add those cases to the JUnit test first. It will be fixed for the next release.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Locked