// The entity attribute is optional.
String entityName = (String) _attributes.get("entity");
// Delete the corresponding ParameterPort, if any.
Port toDelete = null;
try {
toDelete = _searchForPort(portName);
} catch (XmlException ex) {
// Ignore, there is no port by that name.
}
// Find the corresponding ParameterPort and delete it
if (toDelete != null) {
NamedObj container = toDelete.getContainer();
if (container != null && container instanceof Entity) {
Attribute attribute = ((Entity) container)
.getAttribute(portName);
if (attribute != null
&& attribute instanceof PortParameter) {
DeleteRequest request = new DeleteRequest(
_DELETE_PROPERTY, attribute.getName(), null);
// Only defer if we are in a class, entity, or
// model context, which is equivalent to the
// _current being an instance of
// InstantiableNamedObj.
if ((_deleteRequests != null)
&& _current instanceof InstantiableNamedObj) {
_deleteRequests.add(request);
} else {
// Very likely, the context is null, in which
// case the following will throw an exception.
// We defer to it in case somehow a link request
// is being made at the top level with a non-null
// context (e.g. via a change request).
request.execute();
}
}
}
}
// Link is stored and processed last, but before deletions.
DeleteRequest request = new DeleteRequest(_DELETE_PORT,
portName, entityName);
// Only defer if we are in a class, entity, or model context,
// which is equivalent to the _current being an instance of
// InstantiableNamedObj.
if ((_deleteRequests != null)
&& _current instanceof InstantiableNamedObj) {
_deleteRequests.add(request);
} else {
// Very likely, the context is null, in which
// case the following will throw an exception.
// We defer to it in case somehow a link request
// is being made at the top level with a non-null
// context (e.g. via a change request).
request.execute();
}
// NOTE: deletePort is not supposed to have anything
// inside it, so we do not push the context.
//////////////////////////////////////////////////////////////
//// deleteProperty
} else if (elementName.equals("deleteProperty")) {
String propName = (String) _attributes.get("name");
_checkForNull(propName,
"No name for element \"deleteProperty\"");
// Link is stored and processed last, but before deletions.
DeleteRequest request = new DeleteRequest(_DELETE_PROPERTY,
propName, null);
// We use toDelete to find any PortParameters
Attribute toDelete = _searchForAttribute(propName);
// Only defer if we are in a class, entity, or model context,
// which is equivalent to the _current being an instance of
// InstantiableNamedObj.
if ((_deleteRequests != null)
&& _current instanceof InstantiableNamedObj) {
_deleteRequests.add(request);
} else {
// Very likely, the context is null, in which
// case the following will throw an exception.
// We defer to it in case somehow a link request
// is being made at the top level with a non-null
// context (e.g. via a change request).
request.execute();
}
// Find the corresponding PortParameter and delete it
NamedObj container = toDelete.getContainer();
if (container != null && container instanceof Entity) {
Port port = ((Entity) container).getPort(propName);
if (port != null && port instanceof ParameterPort) {
request = new DeleteRequest(_DELETE_PORT, port
.getName(), container.getFullName());
// Only defer if we are in a class, entity, or
// model context, which is equivalent to the
// _current being an instance of
// InstantiableNamedObj.
if ((_deleteRequests != null)
&& _current instanceof InstantiableNamedObj) {
_deleteRequests.add(request);
} else {
// Very likely, the context is null, in which
// case the following will throw an exception.
// We defer to it in case somehow a link request
// is being made at the top level with a non-null
// context (e.g. via a change request).
request.execute();
}
}
}
// NOTE: deleteProperty is not supposed to have anything
// inside it, so we do not push the context.
//////////////////////////////////////////////////////////////
//// deleteRelation
} else if (elementName.equals("deleteRelation")) {
String relationName = (String) _attributes.get("name");
_checkForNull(relationName,
"No name for element \"deleteRelation\"");
// Link is stored and processed last, but before deletions.
DeleteRequest request = new DeleteRequest(_DELETE_RELATION,
relationName, null);
// Only defer if we are in a class, entity, or model context,
// which is equivalent to the _current being an instance of
// InstantiableNamedObj.
if ((_deleteRequests != null)
&& _current instanceof InstantiableNamedObj) {
_deleteRequests.add(request);
} else {
// Very likely, the context is null, in which
// case the following will throw an exception.
// We defer to it in case somehow a link request
// is being made at the top level with a non-null
// context (e.g. via a change request).
request.execute();
}
// NOTE: deleteRelation is not supposed to have anything
// inside it, so we do not push the context.
//////////////////////////////////////////////////////////////
//// director
} else if (elementName.equals("director")) {
// NOTE: The director element is deprecated.
// Use a property instead. This is kept here so that
// this parser can read older MoML files.
// NOTE: We do not check for a previously existing director.
// There is presumably no harm in just creating a new one.
String className = (String) _attributes.get("class");
_checkForNull(className, "No class for element \"director\"");
String dirName = (String) _attributes.get("name");
_checkForNull(dirName, "No name for element \"director\"");
_checkClass(_current, CompositeActor.class,
"Element \"director\" found inside an element that "
+ "is not a CompositeActor. It is: " + _current);
Object[] arguments = new Object[2];
arguments[0] = _current;
arguments[1] = dirName;
// NamedObj container = _current;
_pushContext();
Class newClass = Class.forName(className, true, _classLoader);
// NOTE: No propagation occurs here... Hopefully, deprecated
// elements are not used with class structures.
_current = _createInstance(newClass, arguments);
_namespace = _DEFAULT_NAMESPACE;
//////////////////////////////////////////////////////////////
//// display
} else if (elementName.equals("display")) {
String displayName = (String) _attributes.get("name");
if (_current != null) {
// Propagate.
Iterator derivedObjects = _current.getDerivedList()
.iterator();
String currentName = _current.getName();
while (derivedObjects.hasNext()) {
NamedObj derived = (NamedObj) derivedObjects.next();
// If the derived object has the same
// name as the old name, then we assume it
// should change.
if (derived.getName().equals(currentName)) {
if (displayName != null) {
if (displayName.equals(currentName)) {
// The displayName is the same as the
// name, so it should be reset to null.
derived.setDisplayName(null);
} else {
derived.setDisplayName(displayName);
}
}
}
}
// Now change the display name.
String oldDisplayName = _current.getDisplayName();
if (displayName != null) {
if (displayName.equals(currentName)
|| displayName.equals("")) {
// The displayName is the same as the
// name, so it should be reset to null.
_current.setDisplayName(null);
} else {
_current.setDisplayName(displayName);
}
// Handle the undo aspect if needed
if (_undoEnabled) {
// Simply create in the undo MoML another display element.
_undoContext.appendUndoMoML("<display name=\""
+ StringUtilities
.escapeForXML(oldDisplayName)
+ "\"/>\n");
// Do not need to continue generating undo MoML
// as rename does not have any child elements
_undoContext.setChildrenUndoable(false);
}
}
}
//////////////////////////////////////////////////////////////
//// doc
} else if (elementName.equals("doc")) {
_currentDocName = (String) _attributes.get("name");
_currentCharData = new StringBuffer();
// Count doc tags so that they can nest.
_docNesting++;
//////////////////////////////////////////////////////////////
//// entity
} else if (elementName.equals("entity")
|| elementName.equals("model")) {
// NOTE: The "model" element is deprecated. It is treated
// exactly as an entity.
String className = (String) _attributes.get("class");
String entityName = (String) _attributes.get("name");
_checkForNull(entityName, "No name for element \"entity\"");
String source = (String) _attributes.get("source");
// For undo purposes need to know if the entity existed
// already
Entity entity = _searchForEntity(entityName, _current);
boolean existedAlready = (entity != null);
boolean converted = false;
if (existedAlready) {
// Check whether it was previously a class, in which case
// it is being converted to an entity.
if (entity.isClassDefinition()) {
entity.setClassDefinition(false);
converted = true;
}
} else {
NamedObj candidate = _createEntity(className, entityName,
source);
if (candidate instanceof Entity) {
entity = (Entity) candidate;
entity.setClassName(className);
} else {
throw new IllegalActionException(_current,
"Attempt to create an entity named "
+ entityName + " from a class that "
+ "is not a subclass of Entity: "
+ className);
}
}
// NOTE: The entity may be at the top level, in
// which case _deleteRequests is null.
if (_deleteRequests != null) {
_deleteRequestStack.push(_deleteRequests);
pushedDeleteRequests = true;
}
_deleteRequests = new LinkedList();
// NOTE: The entity may be at the top level, in
// which case _linkRequests is null.
if (_linkRequests != null) {
_linkRequestStack.push(_linkRequests);
pushedLinkRequests = true;
}
_linkRequests = new LinkedList();
if (_current != null) {
_pushContext();
} else if (_toplevel == null) {
// NOTE: We used to set _toplevel to newEntity, but
// this isn't quite right because the entity may have a
// composite name.
_toplevel = entity.toplevel();
// Ensure that if any change requests occur as a
// consequence of adding items to this top level,
// that execution of those change requests is deferred
// until endDocument().
_toplevel.setDeferringChangeRequests(true);
// As early as possible, set URL attribute.
// This is needed in case any of the parameters
// refer to files whose location is relative
// to the URL location.
if (_xmlFile != null) {
// Add a URL attribute to the toplevel to
// indicate where it was read from.
URIAttribute attribute = new URIAttribute(_toplevel,
"_uri");
attribute.setURL(_xmlFile);
}
}
_current = entity;
_namespace = _DEFAULT_NAMESPACE;
if (_undoEnabled) {
// Handle the undo aspect.
if (existedAlready) {
if (!converted) {
_undoContext.appendUndoMoML("<entity name=\""
+ entityName + "\" >\n");
// Need to continue undoing and use an end tag
_undoContext.appendClosingUndoMoML("</entity>\n");
} else {
// Converted from a class to an entity, so reverse this.
_undoContext.appendUndoMoML("<class name=\""
+ entityName + "\" >\n");
// Need to continue undoing and use an end tag
_undoContext.appendClosingUndoMoML("</class>\n");
}
_undoContext.setChildrenUndoable(true);
} else {
_undoContext.appendUndoMoML("<deleteEntity name=\""
+ entityName + "\" />\n");
// Do not need to continue generating undo MoML
// as the deleteEntity takes care of all
// contained MoML
_undoContext.setChildrenUndoable(false);
_undoContext.setUndoable(false);
// Prevent any further undo entries for this context.
_undoEnabled = false;
}
}
//////////////////////////////////////////////////////////////
//// group
} else if (elementName.equals("group")) {
String groupName = (String) _attributes.get("name");
if (groupName != null) {
// Defining a namespace.
_namespaces.push(_namespace);
_namespaceTranslations.push(_namespaceTranslationTable);
_namespacesPushed = true;
if (groupName.equals("auto")) {
_namespace = _AUTO_NAMESPACE;
_namespaceTranslationTable = new HashMap();
} else {
_namespace = groupName;
}
} else {
_namespaces.push(_DEFAULT_NAMESPACE);
_namespaceTranslations.push(_namespaceTranslationTable);
_namespacesPushed = true;
_namespace = _DEFAULT_NAMESPACE;
_namespaceTranslationTable = new HashMap();
}
// Link and unlink requests are processed when the
// group closes.
// NOTE: The entity may be at the top level, in
// which case _deleteRequests is null.
if (_deleteRequests != null) {
_deleteRequestStack.push(_deleteRequests);
pushedDeleteRequests = true;
}
_deleteRequests = new LinkedList();
// NOTE: The entity may be at the top level, in
// which case _linkRequests is null.
if (_linkRequests != null) {
_linkRequestStack.push(_linkRequests);
pushedLinkRequests = true;
}
_linkRequests = new LinkedList();
// Handle the undo aspect.
if (_undoEnabled) {
// NOTE: for groups with namespaces, rely on the names
// already being part of undo MoML names instead of
// tracking the namespace prefix
_undoContext.appendUndoMoML("<group>\n");
// Need to continue undoing and use an end tag
_undoContext.appendClosingUndoMoML("</group>\n");
_undoContext.setChildrenUndoable(true);
}
//////////////////////////////////////////////////////////////
//// input
} else if (elementName.equals("input")) {
String source = (String) _attributes.get("source");
_checkForNull(source, "No source for element \"input\"");
boolean skip = false;
if (inputFileNamesToSkip != null) {
// If inputFileNamesToSkip contains a string
// that matches the end of source, then skip
// parsing the source file. We use this for testing
// configurations that have optional parts like
// Matlab or javacomm.
Iterator inputFileNames = inputFileNamesToSkip.iterator();
while (inputFileNames.hasNext()) {
String inputFileName = (String) inputFileNames.next();
if (source.endsWith(inputFileName)) {
skip = true;
break;
}
}
}
if (!skip) {
// NOTE: The base attribute has been deprecated. Ignore.
// Read external file in the current context, but with
// a new parser.
boolean modified = isModified();
MoMLParser newParser = new MoMLParser(_workspace,
_classLoader);
newParser.setContext(_current);
setModified(modified);
_parse(newParser, _base, source);
}
//////////////////////////////////////////////////////////////
//// link
} else if (elementName.equals("link")) {
String portName = (String) _attributes.get("port");
// Port can be null if we are linking two vertices.
// _checkForNull(portName, "No port for element \"link\"");
// Relation attribute now optional
String relationName = (String) _attributes.get("relation");
String insertAtSpec = (String) _attributes.get("insertAt");
String insertInsideAtSpec = (String) _attributes
.get("insertInsideAt");
// Link is stored and processed last, but before deletions.
LinkRequest request;
if (portName != null) {
request = new LinkRequest(portName, relationName,
insertAtSpec, insertInsideAtSpec);
} else {
String relation1Name = (String) _attributes
.get("relation1");
String relation2Name = (String) _attributes
.get("relation2");
request = new LinkRequest(relation1Name, relation2Name);
}
if (_linkRequests != null) {
_linkRequests.add(request);
} else {
// Very likely, the context is null, in which
// case the following will throw an exception.
// We defer to it in case somehow a link request
// is being made at the top level with a non-null
// context (e.g. via a change request).
request.execute();
}
//////////////////////////////////////////////////////////////
//// port
} else if (elementName.equals("port")) {
String className = (String) _attributes.get("class");
String portName = (String) _attributes.get("name");
_checkForNull(portName, "No name for element \"port\"");
_checkClass(_current, Entity.class,
"Element \"port\" found inside an element that "
+ "is not an Entity. It is: " + _current);
Entity container = (Entity) _current;
Class newClass = null;
if ((className != null) && !className.trim().equals("")) {
newClass = Class.forName(className, true, _classLoader);
}
Port port = container.getPort(portName);
// Flag used to generate correct undo MoML
boolean alreadyExisted = (port != null);
if (port != null) {
if (newClass != null) {
// Previously existing port with the specified name.
_checkClass(port, newClass, "port named \"" + portName
+ "\" exists and is not an instance of "
+ className);
}
} else {
// No previously existing port with this name.
// 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 = container.getDerivedList();
Iterator derivedObjects = derivedList.iterator();
while (derivedObjects.hasNext()) {
Entity derived = (Entity) derivedObjects.next();
if (derived.getPort(portName) != null) {
throw new IllegalActionException(
container,
"Cannot create port because a subclass or instance "
+ "contains a port with the same name: "
+ derived.getPort(portName)
.getFullName());
}
}
if (newClass == null) {
// Classname is not given. Invoke newPort() on the
// container.
port = container.newPort(portName);
if ((_topObjectsCreated != null)
&& (container == _originalContext)) {
_topObjectsCreated.add(port);
}
// Propagate.
// NOTE: Propagated ports will not use newPort(),
// but rather will use clone. Classes that override
// newPort() to perform special actions will no longer
// work, possibly!
port.propagateExistence();
} else {
// Classname is given.
Object[] arguments = new Object[2];
arguments[0] = container;
arguments[1] = portName;
port = (Port) _createInstance(newClass, arguments);
// Propagate.
port.propagateExistence();
}
}
_pushContext();
_current = port;