package org.framed.orm.ui.command.shapes; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.gef.commands.Command; import org.framed.orm.model.Model; import org.framed.orm.model.ModelElement; import org.framed.orm.model.Relation; import org.framed.orm.model.Shape; import org.framed.orm.model.Type; /** * Through this command all {@link Shape}s can be deleted(removed from the model tree). * * @author Kay Bierzynski * */ public class ORMShapeDeleteCommand extends Command { /** The {@link Shape} to be removed. */ protected Shape shape; /** The {@link Model} from which the {@link Shape} should be removed. */ protected Model parent; /** * A list, which contains all {@link Relation}s that are connected to the {@link Shape} 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 Shape}. 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 Shape}. 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 * and the relations list is initialized. * */ public ORMShapeDeleteCommand() { super.setLabel("ORMShapeDelete"); relations = new ArrayList<Relation>(); } /** * {@inheritDoc} In this method the {@link Shape} is deleted/removed from the model tree through * setting the parent {@link Model} reference on null and through the deletion of all * {@link Relation}s which connected to this {@link Shape}. */ @Override public void execute() { detachLinks(); shape.setContainer(null); } /** * {@inheritDoc} This command is undone though resetting of the parent {@link Model} reference on * the initial value and through the recreation of all {@link Relation}s which connected to this * {@link Shape}. */ @Override public void undo() { reattachLinks(); shape.setContainer(parent); } /** * Detach/Delete all {@link Relation}s from this {@link Shape} and their source/target * {@link Shape} and storing the connection information in local data structures. */ protected void detachLinks() { if (shape.getType().equals(Type.ROLE_GROUP)) { detachLinksRoleGroup(); } sourceLinks = new HashMap<Relation, ModelElement>(); targetLinks = new HashMap<Relation, ModelElement>(); relations.addAll(shape.getIncomingRelations()); relations.addAll(shape.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 Shape} and their source/target * {@link Shape}. */ private void reattachLinks() { for (Relation relation : relations) { relation.setSource(sourceLinks.get(relation)); relation.setTarget(targetLinks.get(relation)); relation.setContainer(parent); } } /** * Setter for the {@link Shape}, which is to be removed in this command. The local parent variable * is set here as well. * * @param shape org.framed.orm.model.Shape * */ public void setShape(final Shape shape) { this.shape = shape; this.parent = shape.getContainer(); } /** * Because a {@link Relation} from type rolegroup has a child model, which can contain other child models * through role groups. Not only the {@link Relation}s connected to this roleGroup must be * detached/deleted the {@link Relation}s connected to the children and their children of this * roleGroup child model must be detached/deleted as well. For that reason the first thing, which is * done in this method is to gather all children and their children of this roleGroup in a * single list. After that the {@link Relation}s connected to children are added to relations * list. * */ private void detachLinksRoleGroup() { ArrayList<Shape> items = new ArrayList<Shape>(); for (ModelElement ele : shape.getModel().getElements()) { if (ele instanceof Shape) { items.add((Shape) ele); } } gatherRoleGroupsItems(items); for (Shape item : items) { // add all relations with the source not in the RG and the target in the RG for (Relation rel : item.getIncomingRelations()) { if (!items.contains(rel.getSource())) relations.add(rel); } // add all relations with the source in the RG and the target not in the RG for (Relation rel : item.getOutgoingRelations()) { if (!items.contains(rel.getTarget())) relations.add(rel); } } } /** * This method puts adds the children of the children and so on of the {@link Reletion}s from type * role group child model to the list, which was given initaily. * */ private void gatherRoleGroupsItems(final List<Shape> items) { List<Shape> items2 = new ArrayList<Shape>(); for (Shape item : items) { if (item.getType().equals(Type.ROLE_GROUP)) { for (ModelElement ele : item.getModel().getElements()) { if (ele instanceof Shape) { items2.add((Shape) ele); } } gatherRoleGroupsItems(items2); } } items.addAll(items2); } }