If I open ptII/ptolemy/actor/lib/Sinewave.xml and save it, then
the VersionAttribute gets added:

 <property name="_createdBy" class="ptolemy.kernel.util.VersionAttribute" 
value="2.1-devel"/>

Unfortunately, if I then try to run a model that uses Sinewave.xml,
I get a clone not supported exception:

cxh@cooley 21% java -classpath $PTII ptolemy.actor.gui.MoMLSimpleApplication 
ptolemy/moml/demo/modulation.xml
Error encountered in:
<entity name="carrier" class="ptolemy.actor.lib.Sinewave">
java.lang.CloneNotSupportedException: The field associated with CURRENT_VERSION could 
not be automatically cloned because field is final.  This can be caused if the field 
is not defined in a public class.
        at ptolemy.kernel.util.NamedObj.clone(NamedObj.java:450)
        at ptolemy.kernel.util.Attribute.clone(Attribute.java:103)
        at ptolemy.kernel.util.NamedObj.clone(NamedObj.java:377)
        at ptolemy.kernel.Entity.clone(Entity.java:154)
        at ptolemy.kernel.ComponentEntity.clone(ComponentEntity.java:125)
        at ptolemy.kernel.CompositeEntity.clone(CompositeEntity.java:206)
        at ptolemy.actor.CompositeActor.clone(CompositeActor.java:193)
        at ptolemy.moml.MoMLParser._createEntity(MoMLParser.java:1917)
        at ptolemy.moml.MoMLParser.startElement(MoMLParser.java:1127)
        at com.microstar.xml.XmlParser.parseElement(XmlParser.java:945)
        at com.microstar.xml.XmlParser.parseContent(XmlParser.java:1118)
        at com.microstar.xml.XmlParser.parseElement(XmlParser.java:947)
        at com.microstar.xml.XmlParser.parseDocument(XmlParser.java:496)
        at com.microstar.xml.XmlParser.doParse(XmlParser.java:176)
        at com.microstar.xml.XmlParser.parse(XmlParser.java:146)
        at ptolemy.moml.MoMLParser.parse(MoMLParser.java:618)
        at ptolemy.moml.MoMLParser.parse(MoMLParser.java:599)
        at ptolemy.moml.MoMLParser.parse(MoMLParser.java:584)
        at 
ptolemy.actor.gui.MoMLSimpleApplication.<init>(MoMLSimpleApplication.java:96)
        at ptolemy.actor.gui.MoMLSimpleApplication.main(MoMLSimpleApplication.java:149)



The problem is that VersionAttribute.CURRENT_VERSION is declared as:

    public static final VersionAttribute CURRENT_VERSION;

    static {
        try {
            CURRENT_VERSION = new VersionAttribute("2.1-devel");
        } catch (Exception ex) {
            throw new ExceptionInInitializerError(
                    "Failed to create CURRENT_VERSION: "
                    + KernelException.stackTraceToString(ex));
        }
    }

The reason we have a blank final and a static body is because the
VersionAttribute constructor will throw an IllegalActionException if
the value of the argument is not properly format, so we can't do

    public static final VersionAttribute CURRENT_VERSION = 
           new VersionAttribute("2.1-devel");
because we are not catching the exception


It looks like NamedObj.clone() was throwing the exception:

            for (int i = 0; i < fields.length; i++) {
                try {
                    // VersionAttribute has a final field
                    if (fields[i].get(newObject) instanceof Settable) {
                        fields[i].set(newObject,
                                newObject.getAttribute(fields[i].getName()));
                    }
                } catch (IllegalAccessException e) {

                    // FIXME: This would be a nice 
                    // place for exception chaining.
                    throw new CloneNotSupportedException(
                            "The field associated with " 
                            + fields[i].getName() 
                            + " could not be automatically cloned because "
                            + e.getMessage() + ".  This can be caused if "
                            + "the field is not defined in a public class.");
                }



I added a check to see if the field in question is final.

            for (int i = 0; i < fields.length; i++) {
                try {
>                   // VersionAttribute has a final field
>                   if ( !Modifier.isFinal(fields[i].getModifiers())
                            && fields[i].get(newObject) instanceof Settable) {
                        fields[i].set(newObject,
                                newObject.getAttribute(fields[i].getName()));
                    }
                } catch (IllegalAccessException e) {

                    // FIXME: This would be a nice 
                    // place for exception chaining.
                    throw new CloneNotSupportedException(
                            "The field associated with " 
                            + fields[i].getName() 
                            + " could not be automatically cloned because "
                            + e.getMessage() + ".  This can be caused if "
                            + "the field is not defined in a public class.");
                }


This seems to work, and I added a test to VersionAttribute.tcl that
replicates this error by attempting to clone a VersionAttribute.


Oddly, ptjacl seems to have problems with static fields in clones.

In the example below, I clone a NamedObj, and I get get
the static fields of the master with java::info fields -static,
but not of the clone?

%     set n [java::new ptolemy.kernel.util.NamedObj "my NamedObj"]
java0x11
% set nClone [$n clone] 
java0x12
% java::info fields -static $n
COMPLETE CLASSNAME FULLNAME LINKS CONTENTS DEEP ATTRIBUTES
% java::info fields -static $nClone
% 

I'm pretty sure the bug is in ptjacl.  The java::field method has
a similar problem.

Comments?

BTW - Clone and final objects is covered in 
http://developer.java.sun.com/developer/JDCTechTips/2001/tt0306.html

-Christopher

----------------------------------------------------------------------------
Posted to the ptolemy-hackers mailing list.  Please send administrative
mail for this list to: [EMAIL PROTECTED]

Reply via email to