if (propertyName.equals("multiport") && isIOPort) {
// Special properties that affect the behaviour of a port
// NOTE: UNDO: Consider refactoring these clauses
// to remove the duplicate values
// The previous value is needed to generate undo MoML
IOPort currentIOPort = (IOPort) _current;
// The mere presense of a named property "multiport"
// makes the enclosing port a multiport, unless it
// has value false.
// Get the previous value to use when generating the
// undo MoML
boolean previousValue = currentIOPort.isMultiport();
// Default for new value is true, unless it is explicitly false.
boolean newValue = true;
if ((value != null) && value.trim().toLowerCase().equals("false")) {
newValue = false;
}
// If this object is a derived object, then its I/O status
// cannot be changed.
if ((_current.getDerivedLevel() < Integer.MAX_VALUE)
&& (((IOPort) _current).isMultiport() != newValue)) {
throw new IllegalActionException(_current,
"Cannot change whether this port is "
+ "a multiport. That property is fixed by "
+ "the class definition.");
}
((IOPort) _current).setMultiport(newValue);
// Propagate.
Iterator derivedObjects = _current.getDerivedList().iterator();
while (derivedObjects.hasNext()) {
IOPort derived = (IOPort) derivedObjects.next();
derived.setMultiport(newValue);
}
_pushContext();
_current = _current.getAttribute(propertyName);
_namespace = _DEFAULT_NAMESPACE;
// Handle undo
if (_undoEnabled) {
_undoContext.appendUndoMoML("<property name=\"" + propertyName
+ "\" value=\"");
// Use what was there before.
_undoContext.appendUndoMoML(previousValue + "\" >\n");
// Continue undoing and also use an end tag as a
// property can contain other properties
_undoContext.setChildrenUndoable(true);
_undoContext.appendClosingUndoMoML("</property>\n");
}
} else if (propertyName.equals("output") && isIOPort) {
// Special properties that affect the behaviour of a port
// NOTE: UNDO: Consider refactoring these clauses
// to remove the duplicate values
// The previous value is needed to generate undo MoML
IOPort currentIOPort = (IOPort) _current;
// Get the previous value to use when generating the
// undo MoML
boolean previousValue = currentIOPort.isOutput();
// Default for new value is true, unless it is explicitly false.
boolean newValue = true;
if ((value != null) && value.trim().toLowerCase().equals("false")) {
newValue = false;
}
// If this object is a derived object, then its I/O status
// cannot be changed.
if ((_current.getDerivedLevel() < Integer.MAX_VALUE)
&& (((IOPort) _current).isOutput() != newValue)) {
throw new IllegalActionException(_current,
"Cannot change whether this port is "
+ "an output. That property is fixed by "
+ "the class definition.");
}
((IOPort) _current).setOutput(newValue);
// Propagate.
Iterator derivedObjects = _current.getDerivedList().iterator();
while (derivedObjects.hasNext()) {
IOPort derived = (IOPort) derivedObjects.next();
derived.setOutput(newValue);
}
_pushContext();
_current = _current.getAttribute(propertyName);
_namespace = _DEFAULT_NAMESPACE;
// Handle undo
if (_undoEnabled) {
_undoContext.appendUndoMoML("<property name=\"" + propertyName
+ "\" value=\"");
// Use what was there before
_undoContext.appendUndoMoML(previousValue + "\" >\n");
// Continue undoing and also use an end tag as a
// property can contain other properties
_undoContext.setChildrenUndoable(true);
_undoContext.appendClosingUndoMoML("</property>\n");
}
} else if (propertyName.equals("input") && isIOPort) {
// Special properties that affect the behaviour of a port
// NOTE: UNDO: Consider refactoring these clauses
// to remove the duplicate values
// The previous value is needed to generate undo MoML
IOPort currentIOPort = (IOPort) _current;
// Get the previous value to use when generating the
// undo MoML
boolean previousValue = currentIOPort.isInput();
// Default for new value is true, unless it is explicitly false.
boolean newValue = true;
if ((value != null) && value.trim().toLowerCase().equals("false")) {
newValue = false;
}
// If this object is a derived object, then its I/O status
// cannot be changed.
if ((_current.getDerivedLevel() < Integer.MAX_VALUE)
&& (((IOPort) _current).isInput() != newValue)) {
throw new IllegalActionException(_current,
"Cannot change whether this port is "
+ "an input. That property is fixed by "
+ "the class definition.");
}
((IOPort) _current).setInput(newValue);
// Propagate.
Iterator derivedObjects = _current.getDerivedList().iterator();
while (derivedObjects.hasNext()) {
IOPort derived = (IOPort) derivedObjects.next();
derived.setInput(newValue);
}
_pushContext();
_current = _current.getAttribute(propertyName);
_namespace = _DEFAULT_NAMESPACE;
// Handle undo
if (_undoEnabled) {
_undoContext.appendUndoMoML("<property name=\"" + propertyName
+ "\" value=\"");
// Use what was there before
_undoContext.appendUndoMoML(previousValue + "\" >\n");
// Continue undoing and also use an end tag as a
// property can contain other properties
_undoContext.setChildrenUndoable(true);
_undoContext.appendClosingUndoMoML("</property>\n");
}
} else {
// Ordinary attribute.
NamedObj property = null;
if (_current != null) {
property = _current.getAttribute(propertyName);
}
Class newClass = null;
if (className != null) {
try {
newClass = Class.forName(className, true, _classLoader);
} catch (NoClassDefFoundError ex) {
throw new XmlException("Failed to find class '" + className
+ "'", _currentExternalEntity(), _getLineNumber(),
_getColumnNumber(), ex);
} catch (SecurityException ex) {
// An applet might throw this.
throw new XmlException("Failed to find class '" + className
+ "'", _currentExternalEntity(), _getLineNumber(),
_getColumnNumber(), ex);
}
}
// If there is a previous property with this name
// (property is not null), then we check that the
// property is an instance of the specified class.
// If it is, then we set the value of the property.
// Otherwise, we try to replace it, something that
// will only work if it is a singleton (it might throw
// NameDuplicationException).
boolean previouslyExisted = (property != null);
// Even if the object previously existed, if the
// class does not match, we may create a new object.
boolean createdNew = false;
// Also need the previous value, if any, to generate undo MoML.
String oldClassName = null;
String oldValue = null;
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());
}
}