package com.xrosstools.xunit.editor.commands;
import org.eclipse.gef.commands.Command;
import com.xrosstools.xunit.editor.model.ChainNode;
import com.xrosstools.xunit.editor.model.CompositeUnitNode;
import com.xrosstools.xunit.editor.model.UnitNode;
import com.xrosstools.xunit.editor.model.UnitNodeContainer;
public class UnitNodeAddNodeCommand extends Command {
private CompositeHandler compositeHandler = new CompositeHandler();
private DefaultHandler defaultHandler = new DefaultHandler();
private Object parent;
private UnitNode unit;
private Object oldParent;
private UnitNode newNode;
private boolean performed;
private UnitNode combinedNode;
private int index;
public UnitNodeAddNodeCommand(Object parent, UnitNode unit, Object oldParent, UnitNode newNode){
this.parent = parent;
this.unit = unit;
this.oldParent = oldParent;
this.newNode = newNode;
}
public void execute() {
performed = false;
// This prevent dragging start, end, validator or locator
if(!(oldParent instanceof UnitNodeContainer))
return;
if(unit instanceof CompositeUnitNode)
compositeHandler.execute();
if(!performed)
defaultHandler.execute();
}
public String getLabel() {
return "Add node";
}
public void redo() {
execute();
}
public void undo() {
if(!performed)
return;
UnitNodeAddCommandHandler handler =
combinedNode == null ? compositeHandler : defaultHandler;
handler.undo();
}
private interface UnitNodeAddCommandHandler{
void execute();
void undo();
}
private class CompositeHandler implements UnitNodeAddCommandHandler {
public void execute(){
UnitNodeContainer container = ((CompositeUnitNode)unit).getContainerNode();
UnitNodeContainer oldContainer = (UnitNodeContainer)oldParent;
index = oldContainer.indexOf(newNode);
oldContainer.remove(newNode);
performed = container.add(newNode);
if(performed)
return;
// if add failed (loop is not empty or bi-branch
// has no available branch), add the node back to original
// container
oldContainer.add(index, newNode);
}
public void undo(){
UnitNodeContainer container = ((CompositeUnitNode)unit).getContainerNode();
UnitNodeContainer oldContainer = (UnitNodeContainer)oldParent;
container.remove(newNode);
oldContainer.add(index, newNode);
performed = false;
}
}
private class DefaultHandler implements UnitNodeAddCommandHandler {
public void execute(){
if(parent instanceof UnitNodeContainer)
combineToContainer();
}
public void undo(){
if(combinedNode == null)
return;
if(parent instanceof UnitNodeContainer)
splitFromContainer();
}
private void combineToContainer(){
UnitNodeContainer container = (UnitNodeContainer)parent;
UnitNodeContainer oldContainer = (UnitNodeContainer)oldParent;
if(!container.contains(unit))
return;
int newIndex = container.indexOf(unit);
index = oldContainer.indexOf(newNode);
oldContainer.remove(newNode);
String label = unit.getInputLabel();
container.remove(unit);
// Only allow combine to chain
combinedNode = new ChainNode(unit, newNode);
container.add(newIndex, combinedNode);
combinedNode.setInputLabel(label);
performed = true;
}
private void splitFromContainer(){
UnitNodeContainer container = (UnitNodeContainer)parent;
UnitNodeContainer oldContainer = (UnitNodeContainer)oldParent;
int newIndex = container.indexOf(combinedNode);
if(newIndex < 0)
return;
String label = combinedNode.getInputLabel();
container.remove(combinedNode);
container.add(newIndex, unit);
unit.setInputLabel(label);
oldContainer.add(index, newNode);
performed = false;
}
}
}