package org.framed.orm.ui.command.connectionkinds;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.draw2d.Bendpoint;
import org.eclipse.gef.commands.Command;
import org.framed.orm.geometry.RelativePoint;
import org.framed.orm.model.Model;
import org.framed.orm.model.ModelElement;
import org.framed.orm.model.Relation;
import org.framed.orm.model.Type;
import org.framed.orm.ui.editPart.connectionkinds.ORMRelationshipConstraintEditPart;
/**
* Through this command all {@link Relation}s except the {@link Relation}s from type cyclic, total, acyclic, reflexive
* and irreflexive(relationshipConstraints) can be deleted(removed from the model tree). The
* relationshipConstraints need an extra command, because after every deletion of a
* relationshipConstraint the {@link ORMRelationshipConstraintEditPart} of the other
* relationshipConstraints from the same {@link Relation} from type relationship muste be refreshed.
*
* @author Kay Bierzynski
* */
public class ORMRelationDeleteCommand extends Command {
/** The {@link Relation} to be removed. */
private Relation relation;
/** The {@link Model} from which the {@link Relation} should be removed. */
private Model parent;
/** The source/start {@link ModelElement} of the {@link Relation} to be removed. */
private ModelElement source;
/** The target/end {@link ModelElement} of the {@link Relation} to be removed. */
private ModelElement target;
/**
* A list, which stores the {@link Bendpoint}s positions for the case that the user wants to undo
* this command.
*/
private ArrayList<RelativePoint> bendpoints = new ArrayList<RelativePoint>();
/**
* A list, which contains all {@link Relation}s that are connected to the {@link Relation} to be
* removed. This list necessary for the case that the user wants to undo this command.
*/
protected List<Relation> relations;
/**
* Sources for the {@link Relation}s that start or end at this {@link Relation}. This list
* necessary for the case that the user wants to undo this command.
*/
private Map<Relation, ModelElement> sourceLinks;
/**
* Targets for the {@link Relation}s that start or end at this {@link Relation}. This list
* necessary for the case that the user wants to undo this command.
*/
private Map<Relation, ModelElement> targetLinks;
/**
* Constructor of this command, where the label is set, which describes this command to the user.
*
*/
public ORMRelationDeleteCommand() {
super.setLabel("ORMRelationDelete");
relations = new ArrayList<Relation>();
}
/**
* This method tests if the conditions for executing this command are fulfilled,
*
* @return true if the parameter relation is set.
*/
@Override
public boolean canExecute() {
return relation != null;
}
/**
* {@inheritDoc} In this method all the attributes of the {@link Relation} to be removed are
* stored in variables in case that the user wants to undone this command. After this part the
* {@link Relation} is removed from the source, the {@link Model} and the target and all of it's
* {@link Bendpoint}s are deleted. In case of {@link Relation} from relationship the connection
* anchor shape is deleted as well.
*
*/
@Override
public void execute() {
parent = relation.getContainer();
source = relation.getSource();
target = relation.getTarget();
bendpoints.addAll(relation.getBendpoints());
if (relation.getType().equals(Type.RELATIONSHIP)) {
detachLinks();
relation.getConnectionAnchor().setContainer(null);
}
relation.setSource(null);
relation.setTarget(null);
relation.setContainer(null);
relation.getBendpoints().clear();
}
/**
* {@inheritDoc} This command is undone through the recreation/ invoking of the {@link Relation}
* into the model tree through setting it's attributes. In case of {@link Relation} from
* relationship the connection anchor shape is inovked into the modle tree as well.
*/
@Override
public void undo() {
relation.setSource(source);
relation.setTarget(target);
relation.setContainer(parent);
relation.getBendpoints().addAll(bendpoints);
if (relation.getType().equals(Type.RELATIONSHIP)) {
reattachLinks();
relation.getConnectionAnchor().setContainer(parent);
}
}
/**
* Detach/Delete all {@link Relation}s from this {@link Relation} and their source/target
* {@link Relation} and storing the connection information in local data structures.
*/
protected void detachLinks() {
sourceLinks = new HashMap<Relation, ModelElement>();
targetLinks = new HashMap<Relation, ModelElement>();
relations.addAll(relation.getConnectionAnchor().getIncomingRelations());
relations.addAll(relation.getConnectionAnchor().getOutgoingRelations());
for (Relation relation : relations) {
sourceLinks.put(relation, relation.getSource());
targetLinks.put(relation, relation.getTarget());
relation.setSource(null);
relation.setTarget(null);
relation.setContainer(null);
}
}
/**
* Reattach/Recreate all {@link Relation}s to this {@link Relation} and their source/target
* {@link Relation}.
*/
private void reattachLinks() {
for (Relation relation : relations) {
relation.setSource(sourceLinks.get(relation));
relation.setTarget(targetLinks.get(relation));
relation.setContainer(parent);
}
}
/**
* Setter for the {@link Relation}, which is deleted/removed in this command.
*
* @param relation org.framed.orm.model.Relation
* */
public void setRelation(final Relation relaiton) {
relation = relaiton;
}
}