org.eclipse.emf.common.command.CompoundCommand Maven / Gradle / Ivy
/**
*
*
* Copyright (c) 2002-2006 IBM Corporation and others.
* 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:
* IBM - Initial API and implementation
*
*
*
* $Id: CompoundCommand.java,v 1.6 2007/06/12 20:56:17 emerks Exp $
*/
package org.eclipse.emf.common.command;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.WrappedException;
/**
* A command that comprises a sequence of subcommands.
* Derived classes can control the way results are accumulated from the individual commands;
* the default behaviour is to return the result of the last command.
*/
public class CompoundCommand extends AbstractCommand
{
/**
* The list of subcommands.
*/
protected List commandList;
/**
* When {@link #resultIndex} is set to this,
* {@link #getResult} and {@link #getAffectedObjects} are delegated to the last command, if any, in the list.
*/
public static final int LAST_COMMAND_ALL = Integer.MIN_VALUE;
/**
* When {@link #resultIndex} is set to this,
* {@link #getResult} and {@link #getAffectedObjects}
* are set to the result of merging the corresponding collection of each command in the list.
*/
public static final int MERGE_COMMAND_ALL = Integer.MIN_VALUE - 1;
/**
* The index of the command whose result and affected objects are forwarded.
* Negative values have special meaning, as defined by the static constants.
* A value of -1 indicates that the last command in the list should be used.
* We could have more special behaviours implemented for other negative values.
*/
protected int resultIndex = MERGE_COMMAND_ALL;
/**
* Creates an empty instance.
*/
public CompoundCommand()
{
super();
commandList = new ArrayList();
}
/**
* Creates an instance with the given label.
* @param label the label.
*/
public CompoundCommand(String label)
{
super(label);
commandList = new ArrayList();
}
/**
* Creates an instance with the given label and description.
* @param label the label.
* @param description the description.
*/
public CompoundCommand(String label, String description)
{
super(label, description);
commandList = new ArrayList();
}
/**
* Creates an instance with the given list.
* @param commandList the list of commands.
*/
public CompoundCommand(List commandList)
{
super();
this.commandList = commandList;
}
/**
* Creates instance with the given label and list.
* @param label the label.
* @param commandList the list of commands.
*/
public CompoundCommand(String label, List commandList)
{
super(label);
this.commandList = commandList;
}
/**
* Creates an instance with the given label, description, and list.
* @param label the label.
* @param description the description.
* @param commandList the list of commands.
*/
public CompoundCommand(String label, String description, List commandList)
{
super(label, description);
this.commandList = commandList;
}
/**
* Creates an empty instance with the given result index.
* @param resultIndex the {@link #resultIndex}.
*/
public CompoundCommand(int resultIndex)
{
super();
this.resultIndex = resultIndex;
commandList = new ArrayList();
}
/**
* Creates an instance with the given result index and label.
* @param resultIndex the {@link #resultIndex}.
* @param label the label.
*/
public CompoundCommand(int resultIndex, String label)
{
super(label);
this.resultIndex = resultIndex;
commandList = new ArrayList();
}
/**
* Creates an instance with the given result index, label, and description.
* @param resultIndex the {@link #resultIndex}.
* @param label the label.
* @param description the description.
*/
public CompoundCommand(int resultIndex, String label, String description)
{
super(label, description);
this.resultIndex = resultIndex;
commandList = new ArrayList();
}
/**
* Creates an instance with the given result index and list.
* @param resultIndex the {@link #resultIndex}.
* @param commandList the list of commands.
*/
public CompoundCommand(int resultIndex, List commandList)
{
super();
this.resultIndex = resultIndex;
this.commandList = commandList;
}
/**
* Creates an instance with the given resultIndex, label, and list.
* @param resultIndex the {@link #resultIndex}.
* @param label the label.
* @param commandList the list of commands.
*/
public CompoundCommand(int resultIndex, String label, List commandList)
{
super(label);
this.resultIndex = resultIndex;
this.commandList = commandList;
}
/**
* Creates an instance with the given result index, label, description, and list.
* @param resultIndex the {@link #resultIndex}.
* @param label the label.
* @param description the description.
* @param commandList the list of commands.
*/
public CompoundCommand(int resultIndex, String label, String description, List commandList)
{
super(label, description);
this.resultIndex = resultIndex;
this.commandList = commandList;
}
/**
* Returns whether there are commands in the list.
* @return whether there are commands in the list.
*/
public boolean isEmpty()
{
return commandList.isEmpty();
}
/**
* Returns an unmodifiable view of the commands in the list.
* @return an unmodifiable view of the commands in the list.
*/
public List getCommandList()
{
return Collections.unmodifiableList(commandList);
}
/**
* Returns the index of the command whose result and affected objects are forwarded.
* Negative values have special meaning, as defined by the static constants.
* @return the index of the command whose result and affected objects are forwarded.
* @see #LAST_COMMAND_ALL
* @see #MERGE_COMMAND_ALL
*/
public int getResultIndex()
{
return resultIndex;
}
/**
* Returns whether all the commands can execute so that {@link #isExecutable} can be cached.
* An empty command list causes false
to be returned.
* @return whether all the commands can execute.
*/
@Override
protected boolean prepare()
{
if (commandList.isEmpty())
{
return false;
}
else
{
for (Command command : commandList)
{
if (!command.canExecute())
{
return false;
}
}
return true;
}
}
/**
* Calls {@link Command#execute} for each command in the list.
*/
public void execute()
{
for (ListIterator commands = commandList.listIterator(); commands.hasNext(); )
{
try
{
Command command = commands.next();
command.execute();
}
catch (RuntimeException exception)
{
// Skip over the command that threw the exception.
//
commands.previous();
try
{
// Iterate back over the executed commands to undo them.
//
while (commands.hasPrevious())
{
Command command = commands.previous();
if (command.canUndo())
{
command.undo();
}
else
{
break;
}
}
}
catch (RuntimeException nestedException)
{
CommonPlugin.INSTANCE.log
(new WrappedException
(CommonPlugin.INSTANCE.getString("_UI_IgnoreException_exception"), nestedException).fillInStackTrace());
}
throw exception;
}
}
}
/**
* Returns false
if any of the commands return false
for {@link Command#canUndo}.
* @return false
if any of the commands return false
for canUndo
.
*/
@Override
public boolean canUndo()
{
for (Command command : commandList)
{
if (!command.canUndo())
{
return false;
}
}
return true;
}
/**
* Calls {@link Command#undo} for each command in the list, in reverse order.
*/
@Override
public void undo()
{
for (ListIterator commands = commandList.listIterator(commandList.size()); commands.hasPrevious(); )
{
try
{
Command command = commands.previous();
command.undo();
}
catch (RuntimeException exception)
{
// Skip over the command that threw the exception.
//
commands.next();
try
{
// Iterate forward over the undone commands to redo them.
//
while (commands.hasNext())
{
Command command = commands.next();
command.redo();
}
}
catch (RuntimeException nestedException)
{
CommonPlugin.INSTANCE.log
(new WrappedException
(CommonPlugin.INSTANCE.getString("_UI_IgnoreException_exception"), nestedException).fillInStackTrace());
}
throw exception;
}
}
}
/**
* Calls {@link Command#redo} for each command in the list.
*/
public void redo()
{
for (ListIterator commands = commandList.listIterator(); commands.hasNext(); )
{
try
{
Command command = commands.next();
command.redo();
}
catch (RuntimeException exception)
{
// Skip over the command that threw the exception.
//
commands.previous();
try
{
// Iterate back over the executed commands to undo them.
//
while (commands.hasPrevious())
{
Command command = commands.previous();
command.undo();
}
}
catch (RuntimeException nestedException)
{
CommonPlugin.INSTANCE.log
(new WrappedException
(CommonPlugin.INSTANCE.getString("_UI_IgnoreException_exception"), nestedException).fillInStackTrace());
}
throw exception;
}
}
}
/**
* Determines the result by composing the results of the commands in the list;
* this is affected by the setting of {@link #resultIndex}.
* @return the result.
*/
@Override
public Collection> getResult()
{
if (commandList.isEmpty())
{
return Collections.EMPTY_LIST;
}
else if (resultIndex == LAST_COMMAND_ALL)
{
return commandList.get(commandList.size() - 1).getResult();
}
else if (resultIndex == MERGE_COMMAND_ALL)
{
return getMergedResultCollection();
}
else if (resultIndex < commandList.size())
{
return commandList.get(resultIndex).getResult();
}
else
{
return Collections.EMPTY_LIST;
}
}
/**
* Returns the merged collection of all command results.
* @return the merged collection of all command results.
*/
protected Collection> getMergedResultCollection()
{
Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy