/*******************************************************************************
* Copyright (c) 2010-2015 Henshin developers. All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
package de.tub.tfs.henshin.tggeditor.commands.delete.rule;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.henshin.model.And;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.NestedCondition;
import org.eclipse.emf.henshin.model.Not;
import org.eclipse.emf.henshin.model.Rule;
import org.eclipse.gef.commands.CompoundCommand;
import de.tub.tfs.henshin.tggeditor.util.SendNotify;
import de.tub.tfs.muvitor.commands.SimpleDeleteEObjectCommand;
/**
* The class DeleteNACCommand deletes a NAC.
* When executed it makes all the needed changes in the tree structure of
* the Formula in the lhs of the rule.
*/
public class DeleteNACCommand extends CompoundCommand {
/**
* NAC
*/
private Not nc;
/**
* Container of the NAC
*/
private And f;
/**
* lhs which contains NACs.
*/
private Graph lhs;
/**
* And to store the NAC before it's deletion.
*/
private And oldF;
/**
* The boolean left indicates if the NAC stands left side under And.
*/
private boolean left;
/**
* The Rule which has the NAC.
*/
private Rule rule;
/**
* Constructor
* @param nac
*/
public DeleteNACCommand(Graph nac) {
nc = (Not) ((NestedCondition)((EObject) nac).eContainer()).eContainer();
add(new SimpleDeleteEObjectCommand(nac));
}
/**
* @see org.eclipse.gef.commands.Command#canExecute()
*/
@Override
public boolean canExecute() {
return (nc != null);
}
/**
* Delete the NAC and change the tree structure of Formula under the lhs.
* The tree structure of the Formula consists of And and Not.
* And can further consist of two Not or one Not and one And.
* The case differentiation is:
* 1. NAC stands direct under the lhs
* 2. NAC stands under And under the lhs
* 3. NAC stands under And under And
* In each cases it's also considered if the NAC stands left or right.
*/
@Override
public void execute() {
if(nc.eContainer() instanceof Graph){
lhs = (Graph) nc.eContainer();
((Graph) nc.eContainer()).setFormula(null);
SendNotify.sendRemoveFormulaNotify(lhs.eContainer(), nc);
}else if(nc.eContainer() instanceof And){
f = (And) nc.eContainer();
if(f.getLeft().equals(nc)){
if(f.eContainer() instanceof Graph){
lhs = (Graph) f.eContainer();
rule = (Rule) ((Graph)f.eContainer()).eContainer();
((Graph) f.eContainer()).setFormula(f.getRight());
}else if(f.eContainer() instanceof And){
if(((And) f.eContainer()).getRight().equals(f)){
oldF = (And) f.eContainer();
left = false;
((And)f.eContainer()).setRight(f.getRight());
}else if(((And) f.eContainer()).getLeft().equals(f)){
oldF = (And) f.eContainer();
left = true;
((And)f.eContainer()).setLeft(f.getRight());
}
rule = getRule(oldF);
}
}else if(f.getRight().equals(nc)){
if(f.eContainer() instanceof Graph){
lhs = (Graph) f.eContainer();
rule = (Rule) ((Graph) f.eContainer()).eContainer();//
((Graph) f.eContainer()).setFormula(f.getLeft());
}else if(f.eContainer() instanceof And){
if(((And) f.eContainer()).getRight().equals(f)){
oldF = (And) f.eContainer();
left = false;
((And)f.eContainer()).setRight(f.getLeft());
}else if(((And) f.eContainer()).getLeft().equals(f)){
oldF = (And) f.eContainer();
left = true;
((And)f.eContainer()).setLeft(f.getLeft());
}
rule = getRule(oldF);
}
}
if (rule != null)
SendNotify.sendRemoveFormulaNotify((EObject) rule, nc);
}
super.execute();
}
@Override
public boolean canUndo() {
return true;
//return super.canUndo();
}
/**
* @see org.eclipse.gef.commands.Command#redo()
*/
@Override
public void redo() {
if(lhs != null && lhs.getFormula() != null){
lhs.setFormula(null);
SendNotify.sendRemoveFormulaNotify(lhs.eContainer(), nc);
}
else if(f != null) {
if (f instanceof And){
if(f.getLeft() != null && f.getLeft().equals(nc)){
if(lhs!= null && lhs instanceof Graph){
lhs.setFormula(f.getRight());
}else if(oldF != null && oldF instanceof And){
if(left == false){
oldF.setRight(f.getRight());
}else if(left == true){
oldF.setLeft(f.getRight());
}
}
}else if(f.getRight() != null && f.getRight().equals(nc)){
if(lhs!= null && lhs instanceof Graph){
lhs.setFormula(f.getLeft());
}else if(oldF != null && oldF instanceof And){
if(left == false){
oldF.setRight(f.getLeft());
}else if(left == true){
oldF.setLeft(f.getLeft());
}
}
}
SendNotify.sendRemoveFormulaNotify(rule, (EObject) nc);
}
}
super.redo();
}
/**
* @see org.eclipse.gef.commands.Command#undo()
*/
@Override
public void undo() {
if(lhs != null && lhs.getFormula() ==null){
lhs.setFormula(nc);
SendNotify.sendAddFormulaNotify(lhs.eContainer(), nc);
}else if(f != null) {
if (f instanceof And){
if(f.getLeft() != null && f.getLeft().equals(nc)){
if(lhs!= null && lhs instanceof Graph){
f.setRight(lhs.getFormula());
lhs.setFormula(f);
}else if(oldF != null && oldF instanceof And){
if(left == false){
f.setRight(oldF.getRight());
oldF.setRight(f);
}else if(left == true){
f.setRight(oldF.getLeft());
oldF.setLeft(f);
}
}
}else if(f.getRight() != null && f.getRight().equals(nc)){
if(lhs!= null && lhs instanceof Graph){
f.setLeft(lhs.getFormula());
lhs.setFormula(f);
}else if(oldF != null && oldF instanceof And){
if(left == false){
f.setLeft(oldF.getRight());
oldF.setRight(f);
}else if(left == true){
f.setLeft(oldF.getLeft());
oldF.setLeft(f);
}
}
}
SendNotify.sendAddFormulaNotify(rule, (EObject) nc);
}
}
super.undo();
}
private Rule getRule(And and){
Rule r = null;
while(and.eContainer() instanceof And){
and = (And) and.eContainer();
}
if(and.eContainer() instanceof Graph){
r = (Rule) ((Graph) and.eContainer()).eContainer();
}else{
System.out.println("and.eContainer() ist not instanceof Graph" + and.getClass());
}
return r;
}
}