View Javadoc

1   /*
2    * This file is a part of CAST project.
3    * (c) Copyright 2007, AGH University of Science & Technology
4    * https://caribou.iisg.agh.edu.pl/trac/cast
5    *
6    * Licensed under the Eclipse Public License, Version 1.0 (the "License").
7    * You may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * http://www.eclipse.org/legal/epl-v10.html
10   */
11  /*
12   * File: DeleteModelElementsCommand.java
13   * Created: 2007-00-00
14   * Author: awos
15   * $Id: DeleteModelElementsCommand.java 3217 2009-08-19 12:00:08Z kpietak $
16   */
17  
18  package pl.edu.agh.cast.backward.command;
19  
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.util.HashSet;
23  import java.util.Set;
24  
25  import org.eclipse.core.runtime.IProgressMonitor;
26  import org.eclipse.gef.commands.Command;
27  import org.eclipse.jface.operation.IRunnableWithProgress;
28  
29  import pl.edu.agh.cast.Activator;
30  import pl.edu.agh.cast.backward.editor.EditorUtilBackward;
31  import pl.edu.agh.cast.model.visual.backward.Connection;
32  import pl.edu.agh.cast.model.visual.backward.ConnectionGroup;
33  import pl.edu.agh.cast.model.visual.backward.IDiagram;
34  import pl.edu.agh.cast.model.visual.backward.Node;
35  import pl.edu.agh.cast.util.IExceptionHandler;
36  import pl.edu.agh.cast.util.Messages;
37  
38  /**
39   * This command will be created multiple times because of the way delete requests work on edit parts. The exact same
40   * command is returned for all requests - GEF fires a single request for each model element to delete, and they're all
41   * aggregated into a single command.
42   *
43   * It should execute only once, deleting all elements at once, and undo only once, restoring them at once as well.
44   * That's what the _executed and _undone flags are for. GEF calls execute for a command created for each model element
45   * to be deleted - that's why this command's {@link #execute()} will be called multiple times, and we have to guard
46   * against that.
47   *
48   * @author AGH CAST Team
49   */
50  public class DeleteModelElementsCommand extends Command {
51  
52  	/**
53  	 * Id of the command.
54  	 */
55  	public static final Object ID = "pl.edu.agh.cast.schema.command.DeleteModelElementsCommand"; //$NON-NLS-1$
56  
57  	private Set<Connection> connections;
58  
59  	private Set<Node> nodes;
60  
61  	private IDiagram diagram;
62  
63  	private boolean executed = false;
64  
65  	private boolean undone = false;
66  
67  	/**
68  	 * Creates new instance of command to delete model elements.
69  	 *
70  	 * @param diagram
71  	 *            the diagram to operate on
72  	 */
73  	public DeleteModelElementsCommand(IDiagram diagram) {
74  		this.diagram = diagram;
75  		connections = new HashSet<Connection>();
76  		nodes = new HashSet<Node>();
77  	}
78  
79  	/**
80  	 * Adds {@link Connection} to remove.
81  	 *
82  	 * @param connection
83  	 *            connection to remove
84  	 */
85  	public void add(Connection connection) {
86  		connections.add(connection);
87  	}
88  
89  	/**
90  	 * Adds {@link ConnectionGroup} to remove.
91  	 *
92  	 * @param group
93  	 *            connection group to remove
94  	 */
95  	public void add(ConnectionGroup group) {
96  		connections.addAll(group.getAllConnections());
97  	}
98  
99  	/**
100 	 * Adds {@link Node} to remove.
101 	 *
102 	 * @param node
103 	 *            node to remove
104 	 */
105 	public void add(Node node) {
106 		nodes.add(node);
107 		for (ConnectionGroup cg : node.getConnectionGroups()) {
108 			connections.addAll(cg.getAllConnections());
109 		}
110 	}
111 
112 	/**
113 	 * {@inheritDoc}
114 	 *
115 	 * @see org.eclipse.gef.commands.Command#execute()
116 	 */
117 	@Override
118 	public void execute() {
119 		if (executed) {
120 			return;
121 		}
122 
123 		diagram.setSuppressEvents(true);
124 		EditorUtilBackward.runWithProgressMonitorInUIThread(new IRunnableWithProgress() {
125 			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
126 				doDeleteElements(monitor);
127 				monitor.subTask(Messages.DeleteModelElementsCommand_6);
128 				diagram.setSuppressEvents(false);
129 				monitor.done();
130 			}
131 		}, new IExceptionHandler() {
132 			public void handleException(Exception e) {
133 				Activator.getLogger().warn("Error removing model elements", e); //$NON-NLS-1$
134 				diagram.setSuppressEvents(false);
135 			}
136 		});
137 
138 		executed = true;
139 	}
140 
141 	private void doDeleteElements(IProgressMonitor progress) {
142 		int count = 110 * (nodes.size() + connections.size()) / 100;
143 		progress.beginTask(Messages.DeleteModelElementsCommand_0, count);
144 		progress.subTask(Messages.DeleteModelElementsCommand_1);
145 		for (Connection c : connections) {
146 			Connection foundConnection = diagram.findConnection(c.getSourceNode().getId(), c.getTargetNode().getId(), c
147 			        .getStartDate());
148 			diagram.removeConnection(foundConnection);
149 			progress.worked(1);
150 		}
151 		progress.subTask(Messages.DeleteModelElementsCommand_2);
152 		for (Node node : nodes) {
153 			diagram.removeNode(diagram.findNode(node.getId()));
154 			progress.worked(1);
155 		}
156 	}
157 
158 	/**
159 	 * {@inheritDoc}
160 	 *
161 	 * @see org.eclipse.gef.commands.Command#undo()
162 	 */
163 	@Override
164 	public void undo() {
165 		if (undone) {
166 			return;
167 		}
168 
169 		diagram.setSuppressEvents(true);
170 		EditorUtilBackward.runWithProgressMonitorInUIThread(new IRunnableWithProgress() {
171 			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
172 				doRestoreElements(monitor);
173 				monitor.subTask(Messages.DeleteModelElementsCommand_6);
174 				diagram.setSuppressEvents(false);
175 				monitor.done();
176 			}
177 		}, new IExceptionHandler() {
178 			public void handleException(Exception e) {
179 				Activator.getLogger().warn("Error undoing model element removal", e); //$NON-NLS-1$
180 				diagram.setSuppressEvents(false);
181 			}
182 		});
183 
184 		undone = true;
185 	}
186 
187 	private void doRestoreElements(IProgressMonitor progress) {
188 		int count = 110 * (nodes.size() + connections.size()) / 100;
189 		progress.beginTask(Messages.DeleteModelElementsCommand_3, count);
190 		progress.subTask(Messages.DeleteModelElementsCommand_4);
191 		for (Node node : nodes) {
192 			diagram.addNode(node);
193 			progress.worked(1);
194 		}
195 		progress.subTask(Messages.DeleteModelElementsCommand_5);
196 		for (Connection c : connections) {
197 			c.setSourceNode(diagram.findNode(c.getSourceNode().getId()));
198 			c.setTargetNode(diagram.findNode(c.getTargetNode().getId()));
199 			diagram.addConnection(c);
200 			progress.worked(1);
201 		}
202 	}
203 
204 	/**
205 	 * {@inheritDoc}
206 	 *
207 	 * @see org.eclipse.gef.commands.Command#redo()
208 	 */
209 	@Override
210 	public void redo() {
211 		executed = false;
212 		undone = false;
213 		execute();
214 	}
215 
216 }