if (previouslyExisted) {
oldClassName = property.getClass().getName();
if (property instanceof Settable) {
Settable settable = (Settable) property;
oldValue = settable.getExpression();
}
}
if (!previouslyExisted
|| ((newClass != null) && !newClass.isInstance(property))) {
// The following will result in a
// NameDuplicationException if there is a previous
// property and it is not a singleton.
try {
// No previously existing attribute with this name,
// or the class name of the previous entity doesn't
// match.
if (newClass == null) {
newClass = Attribute.class;
}
// An attribute is not usually a top-level element,
// but it might be (e.g. when editing icons).
if (_current == null) {
// If we want to be able to edit icons, we
// have to allow this.
// Invoke the constructor.
Object[] arguments = new Object[2];
arguments[0] = _workspace;
arguments[1] = propertyName;
property = _createInstance(newClass, arguments);
_toplevel = property;
} else {
// First check that there will be no name collision
// when this is propagated. Note that we need to
// include all derived objects, irrespective of whether
// they are locally changed.
List derivedList = _current.getDerivedList();
Iterator derivedObjects = derivedList.iterator();
while (derivedObjects.hasNext()) {
NamedObj derived = (NamedObj) derivedObjects.next();
Attribute other = derived
.getAttribute(propertyName);
if ((other != null)
&& !(other instanceof Singleton)) {
throw new IllegalActionException(
_current,
"Cannot create attribute because a subclass or instance "
+ "contains an attribute with the same name: "
+ derived.getAttribute(
propertyName)
.getFullName());
}
}
// Invoke the constructor.
Object[] arguments = new Object[2];
arguments[0] = _current;
arguments[1] = propertyName;
property = _createInstance(newClass, arguments);
if (property instanceof ptolemy.actor.Director) {
_loadIconForClass(className, property);
}
// Check that the result is an instance of Attribute.
if (!(property instanceof Attribute)) {
// NOTE: Need to get rid of the object.
// Unfortunately, setContainer() is not defined,
// so we have to find the right class.
if (property instanceof ComponentEntity) {
((ComponentEntity) property).setContainer(null);
} else if (property instanceof Port) {
((Port) property).setContainer(null);
} else if (property instanceof ComponentRelation) {
((ComponentRelation) property)
.setContainer(null);
}
throw new XmlException("Property is not an "
+ "instance of Attribute. ",
_currentExternalEntity(), _getLineNumber(),
_getColumnNumber());
}
// Propagate.
property.propagateExistence();
}
if (value != null) {
if (property == null) {
throw new XmlException("Property does not exist: "
+ propertyName + "\n",
_currentExternalEntity(), _getLineNumber(),
_getColumnNumber());
}
if (!(property instanceof Settable)) {
throw new XmlException(
"Property cannot be assigned a value: "
+ property.getFullName()
+ " (instance of "
+ property.getClass().toString()
+ ")\n", _currentExternalEntity(),
_getLineNumber(), _getColumnNumber());
}
Settable settable = (Settable) property;
settable.setExpression(value);
_paramsToParse.add(property);
// Propagate. This has the side effect of marking
// the object overridden.
property.propagateValue();
}
createdNew = true;
} catch (NameDuplicationException ex) {
// Ignore, so we can try to set the value.
// The createdNew variable will still be false.
}
}
if (!createdNew) {
// Previously existing property with this name,
// whose class name exactly matches, or the class
// name does not match, but a NameDuplicationException
// was thrown (meaning the attribute was not
// a singleton).
// If value is null and the property already
// exists, then there is nothing to do.
if (value != null) {
if (!(property instanceof Settable)) {
throw new XmlException("Property is not an "
+ "instance of Settable, "
+ "so can't set the value.",
_currentExternalEntity(), _getLineNumber(),
_getColumnNumber());
}
Settable settable = (Settable) property;
//String previousValue = settable.getExpression();
// NOTE: It is not correct to do nothing even
// if the value is not changed. If the value of
// of an instance parameter is explicitly set,
// and that value happens to be the same as the
// value in the base class, then it should keep
// that value even if the base class later changes.
// if (!value.equals(previousValue)) {
settable.setExpression(value);
// Propagate. This has the side effect of marking
// the object overridden.
property.propagateValue();