final StringBuffer failmoml = new StringBuffer();
moml.append("<group>\n");
failmoml.append("<group>\n");
// Make the request in the context of the container.
final CompositeEntity container = (CompositeEntity) getPtolemyModel();
String relationName = "";
// Flag specifying whether we have actually created any MoML.
boolean appendedMoML = false;
try {
// create moml to unlink any existing.
appendedMoML = _unlinkMoML(container, moml, linkHead, linkTail,
linkRelation);
// create moml to make the new links.
relationName = _linkMoML(container, moml, failmoml,
(NamedObj) newLinkHead, linkTail);
// FIXME: Above can return an empty name, so the following
// test is not quite right.
appendedMoML = appendedMoML || (relationName != null);
} catch (Exception ex) {
// The link is bad... remove it.
_linkSet.remove(link);
link.setHead(null);
link.setTail(null);
dispatchGraphEvent(new GraphEvent(ActorGraphModel.this,
GraphEvent.STRUCTURE_CHANGED, getRoot()));
}
moml.append("</group>\n");
failmoml.append("</group>\n");
final String relationNameToAdd = relationName;
final boolean nonEmptyMoML = appendedMoML;
// Here the source IS the graph model, because we need to
// handle the event dispatch specially: An event is only
// dispatched if both the head and the tail are attached.
// This rather obnoxious hack is here because edge creation
// is tricky and we can't rerender the edge while we are dragging
// it.
MoMLChangeRequest request = new MoMLChangeRequest(
ActorGraphModel.this, container, moml.toString()) {
protected void _execute() throws Exception {
// If nonEmptyMoML is false, then the MoML code is empty.
// Do not execute it, as this will put spurious empty
// junk on the undo stack.
if (nonEmptyMoML) {
super._execute();
}
link.setHead(newLinkHead);
if (relationNameToAdd != null) {
ComponentRelation relation = container
.getRelation(relationNameToAdd);
if (relation == null) {
throw new InternalErrorException(
"Tried to find relation with name "
+ relationNameToAdd
+ " in context " + container);
}
link.setRelation(relation);
} else {
link.setRelation(null);
}
}
};
// Handle what happens if the mutation fails.
request.addChangeListener(new LinkChangeListener(link, container,
failmoml));
request.setUndoable(true);
container.requestChange(request);
}