[91352] take advantage of base's default encoding preference for content type
diff --git a/bundles/org.eclipse.wst.sse.core/config/override.properties b/bundles/org.eclipse.wst.sse.core/config/override.properties
index 06ad11b..70438b1 100644
--- a/bundles/org.eclipse.wst.sse.core/config/override.properties
+++ b/bundles/org.eclipse.wst.sse.core/config/override.properties
@@ -15,6 +15,9 @@
# Note: there is no integrety checking to see if the validCharsetName is indeed
# valid for a given VM, so errors would only show up when attempted to
# be used.
+
+# No translation necessary
+
# format: anyname=validjavaCharsetName
ISO-8859-8-I=ISO-8859-8
X-SJIS=Shift_JIS
diff --git a/bundles/org.eclipse.wst.sse.core/plugin.xml b/bundles/org.eclipse.wst.sse.core/plugin.xml
index 5c3216c..a0205cf 100644
--- a/bundles/org.eclipse.wst.sse.core/plugin.xml
+++ b/bundles/org.eclipse.wst.sse.core/plugin.xml
@@ -20,12 +20,7 @@
-->
<import plugin="org.eclipse.text" export="true"/>
- <!-- need to re-export emf.common since our API depends on it,
- such as StructuredTextUndoManager's getCommmand method returns an
- emf.common.Command
- -->
- <import plugin="org.eclipse.emf.common" export="true"/>
-
+
<import plugin="org.eclipse.core.runtime"/>
<import plugin="org.eclipse.core.filebuffers"/>
<import plugin="org.eclipse.wst.xml.uriresolver"/>
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedIO.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedIO.java
index d30f6c9..02285ef 100644
--- a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedIO.java
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedIO.java
@@ -243,7 +243,7 @@
byte[] BOM = (byte[]) contentDescription.getProperty(IContentDescription.BYTE_ORDER_MARK);
//result = (EncodingMemento)
// contentDescription.getProperty(IContentDescriptionExtended.ENCODING_MEMENTO);
- result = createEncodingMemento(BOM, javaCharset, detectedCharset, unSupportedCharset, null, null);
+ result = createEncodingMemento(BOM, javaCharset, detectedCharset, unSupportedCharset, appropriateDefault, null);
if (!result.isValid()) {
result.setAppropriateDefault(appropriateDefault);
// integrity check for debugging "invalid" cases.
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentTypeEncodingPreferences.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentTypeEncodingPreferences.java
index 7ed07ba..432ad24 100644
--- a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentTypeEncodingPreferences.java
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentTypeEncodingPreferences.java
@@ -13,6 +13,8 @@
package org.eclipse.wst.sse.core.internal.encoding;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.wst.sse.core.internal.encoding.util.Assert;
@@ -93,10 +95,24 @@
}
public static final String getUserSpecifiedDefaultEncodingPreference(String contentTypeID) {
- String enc = ContentBasedPreferenceGateway.getPreferencesString(contentTypeID, CommonEncodingPreferenceNames.INPUT_CODESET);
+ String enc = null;
+
+ // first try to get base's default encoding for content type
+ IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeID);
+ if (contentType != null) {
+ enc = contentType.getDefaultCharset();
+ }
+
+ // next try to get sse's default encoding for content type
+ if (enc == null || enc.trim().length() == 0) {
+ enc = ContentBasedPreferenceGateway.getPreferencesString(contentTypeID, CommonEncodingPreferenceNames.INPUT_CODESET);
+ }
+
+ // next, just try and use workbench encoding
if (enc == null || enc.trim().length() == 0) {
enc = getWorkbenchSpecifiedDefaultEncoding();
}
+
// return blank as null
if (enc != null && enc.trim().length() == 0) {
enc = null;
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/NonContentBasedEncodingRules.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/NonContentBasedEncodingRules.java
index ca4732d..892fdf0 100644
--- a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/NonContentBasedEncodingRules.java
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/NonContentBasedEncodingRules.java
@@ -15,6 +15,7 @@
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import sun.io.ByteToCharConverter;
@@ -47,12 +48,22 @@
public static String getUserSpecifiedDefaultForContentType(IFile iFile) {
- IContentType contentType = null;
String enc = null;
+
+ IContentType contentType = null;
try {
contentType = iFile.getContentDescription().getContentType();
+
+ // first try to get base's default encoding for content type
+ if (contentType != null) {
+ enc = contentType.getDefaultCharset();
+ }
- enc = ContentBasedPreferenceGateway.getPreferencesString(contentType, CommonEncodingPreferenceNames.INPUT_CODESET);
+ // next try to get sse's default encoding for content type
+ if (enc == null || enc.trim().length() == 0) {
+ enc = ContentBasedPreferenceGateway.getPreferencesString(contentType, CommonEncodingPreferenceNames.INPUT_CODESET);
+ }
+
// return blank as null
if (enc != null && enc.trim().length() == 0) {
enc = null;
@@ -65,7 +76,19 @@
}
public static String getUserSpecifiedDefaultForContentType(String contentTypeId) {
- String enc = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.INPUT_CODESET);
+ String enc = null;
+
+ // first try to get base's default encoding for content type
+ IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
+ if (contentType != null) {
+ enc = contentType.getDefaultCharset();
+ }
+
+ // next try to get sse's default encoding for content type
+ if (enc == null || enc.trim().length() == 0) {
+ enc = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.INPUT_CODESET);
+ }
+
// return blank as null
if (enc != null && enc.trim().length() == 0) {
enc = null;
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/AbstractCommand.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/AbstractCommand.java
new file mode 100644
index 0000000..fc9737e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/AbstractCommand.java
@@ -0,0 +1,249 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: AbstractCommand.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.Collection;
+import java.util.Collections;
+
+
+/**
+ * An abstract implementation of a basic command. Each derived class
+ * <bold>must</bold> implement {@link Command#execute} and
+ * {@link Command#redo}, <bold>must</bold> either implement {@link #undo} or
+ * implement {@link #canUndo} to return false, and <bold>must</bold> either
+ * override {@link #prepare} (this is the preferred approach) or can override
+ * {@link #canExecute} directly.
+ *
+ * <p>
+ * It is very convenient to use prepare, as it is guaranteed to be called only
+ * once just before canExecute is to be tested. It can be implemented to
+ * create any additional commands that need to be executed, and the result it
+ * yields becomes the permanent cached return value for canExecute.
+ *
+ */
+public abstract class AbstractCommand implements Command {
+ /**
+ * Keeps track of whether prepare needs to be called. It is tested in
+ * {@link #canExecute} so that {@link #prepare} is called exactly once to
+ * ready the command for execution.
+ */
+ protected boolean isPrepared;
+
+ /**
+ * Keeps track of whether the command is executable. It is set in
+ * {@link #canExecute} to the result of calling {@link #prepare}.
+ */
+ protected boolean isExecutable;
+
+ /**
+ * Holds a short textual description of the command as returned by
+ * {@link #getDescription} and set by {@link #setDescription}.
+ */
+ protected String description;
+
+ /**
+ * Holds the label of the command as returned by {@link #getLabel} and set
+ * by {@link #setLabel}.
+ */
+ protected String label;
+
+ /**
+ * Creates an empty instance.
+ */
+ protected AbstractCommand() {
+ }
+
+ /**
+ * Creates an instance with the given label.
+ *
+ * @param label
+ * the label.
+ */
+ protected AbstractCommand(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Creates and instance with the given label and description.
+ *
+ * @param label
+ * the label.
+ * @param description
+ * the description.
+ */
+ protected AbstractCommand(String label, String description) {
+ this.label = label;
+ this.description = description;
+ }
+
+ /**
+ * Called at most once in {@link #canExecute} to give the command an
+ * opportunity to ready itself for execution. The returned value is stored
+ * in {@link #canExecute}. In other words, you can override this method
+ * to initialize and to yield a cached value for the all subsequent calls
+ * to canExecute.
+ *
+ * @return whether the command is executable.
+ */
+ protected boolean prepare() {
+ return false;
+ }
+
+ /**
+ * Calls {@link #prepare}, caches the result in {@link #isExecutable},
+ * and sets {@link #isPrepared} to <code>true</code>; from then on, it
+ * will yield the value of isExecutable.
+ *
+ * @return whether the command can execute.
+ */
+ public boolean canExecute() {
+ if (!isPrepared) {
+ isExecutable = prepare();
+ isPrepared = true;
+ }
+
+ return isExecutable;
+ }
+
+ /**
+ * Returns <code>true</code> because most command should be undoable.
+ *
+ * @return <code>true</code>.
+ */
+ public boolean canUndo() {
+ return true;
+ }
+
+ /**
+ * Throws a runtime exception.
+ *
+ * @exception UnsupportedOperationException
+ * always.
+ */
+ public void undo() {
+ throw new RuntimeException("_EXC_Method_not_implemented");
+ }
+
+ /**
+ * Returns an empty list.
+ *
+ * @return an empty list.
+ */
+ public Collection getResult() {
+ return Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Returns an empty list.
+ *
+ * @return an empty list.
+ */
+ public Collection getAffectedObjects() {
+ return Collections.EMPTY_LIST;
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public String getLabel() {
+ return label == null ? "_UI_AbstractCommand_label" : label;
+ }
+
+ /**
+ * Sets the label after construction.
+ *
+ * @param label
+ * the new label.
+ */
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public String getDescription() {
+ return description == null ? "_UI_AbstractCommand_description" : description;
+ }
+
+ /**
+ * Sets the description after construction.
+ *
+ * @param description
+ * the new description.
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Creates a new compound command, containing this command and the given
+ * command, that delegates chain to {@link CompoundCommand#append}.
+ *
+ * @param command
+ * the command to chain with this one.
+ * @return a new chained compound command.
+ */
+ public Command chain(Command command) {
+ class ChainedCompoundCommand extends CompoundCommand {
+ public ChainedCompoundCommand() {
+ }
+
+ public Command chain(Command c) {
+ append(c);
+ return this;
+ }
+ }
+
+ CompoundCommand result = new ChainedCompoundCommand();
+ result.append(this);
+ result.append(command);
+ return result;
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public void dispose() {
+ }
+
+ /**
+ * Returns an abbreviated name using this object's own class' name,
+ * without package qualification, followed by a space separated list of
+ * <tt>field:value</tt> pairs.
+ *
+ * @return string representation.
+ */
+ public String toString() {
+ String className = getClass().getName();
+ int lastDotIndex = className.lastIndexOf('.');
+ StringBuffer result = new StringBuffer(lastDotIndex == -1 ? className : className.substring(lastDotIndex + 1));
+ result.append(" (label: " + label + ")");
+ result.append(" (description: " + description + ")");
+ result.append(" (isPrepared: " + isPrepared + ")");
+ result.append(" (isExecutable: " + isExecutable + ")");
+
+ return result.toString();
+ }
+
+ /**
+ * A marker interface implemented by commands that don't dirty the model.
+ */
+ public static interface NonDirtying {
+ }
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/BasicCommandStack.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/BasicCommandStack.java
new file mode 100644
index 0000000..c5a18d5
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/BasicCommandStack.java
@@ -0,0 +1,292 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: BasicCommandStack.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.wst.sse.core.internal.Logger;
+
+
+/**
+ * A basic and obvious implementation of an undoable stack of commands. See
+ * {@link Command} for more details about the command methods that this
+ * implementation uses.
+ */
+public class BasicCommandStack implements CommandStack {
+ /**
+ * The list of commands.
+ */
+ protected List commandList;
+
+ /**
+ * The current position within the list from which the next execute, undo,
+ * or redo, will be performed.
+ */
+ protected int top;
+
+ /**
+ * The command most recently executed, undone, or redone.
+ */
+ protected Command mostRecentCommand;
+
+ /**
+ * The {@link CommandStackListener}s.
+ */
+ protected Collection listeners;
+
+ /**
+ * The value of {@link #top} when {@link #saveIsDone} is called.
+ */
+ protected int saveIndex = -1;
+
+ /**
+ * Creates a new empty instance.
+ */
+ public BasicCommandStack() {
+ commandList = new ArrayList();
+ top = -1;
+ listeners = new ArrayList();
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public void execute(Command command) {
+ // If the command is executable, record and execute it.
+ //
+ if (command != null && command.canExecute()) {
+ // Clear the list past the top.
+ //
+ for (ListIterator commands = commandList.listIterator(top + 1); commands.hasNext(); commands.remove()) {
+ Command otherCommand = (Command) commands.next();
+ otherCommand.dispose();
+ }
+
+ try {
+ command.execute();
+ mostRecentCommand = command;
+ commandList.add(command);
+ ++top;
+ }
+ catch (RuntimeException exception) {
+ handleError(exception);
+
+ mostRecentCommand = null;
+ command.dispose();
+ }
+
+ // This is kind of tricky.
+ // If the saveIndex was in the redo part of the command list which
+ // has now been wiped out,
+ // then we can never reach a point where a save is not necessary,
+ // not even if we undo all the way back to the beginning.
+ //
+ if (saveIndex >= top) {
+ // This forces isSaveNeded to always be true.
+ //
+ saveIndex = -2;
+ }
+
+ notifyListeners();
+ }
+ else {
+ command.dispose();
+ }
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public boolean canUndo() {
+ return top != -1 && ((Command) commandList.get(top)).canUndo();
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public void undo() {
+ if (canUndo()) {
+ Command command = (Command) commandList.get(top--);
+ try {
+ command.undo();
+ mostRecentCommand = command;
+ }
+ catch (RuntimeException exception) {
+ handleError(exception);
+
+ mostRecentCommand = null;
+ flush();
+ }
+
+ notifyListeners();
+ }
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public boolean canRedo() {
+ return top < commandList.size() - 1;
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public void redo() {
+ if (canRedo()) {
+ Command command = (Command) commandList.get(++top);
+ try {
+ command.redo();
+ mostRecentCommand = command;
+ }
+ catch (RuntimeException exception) {
+ handleError(exception);
+
+ mostRecentCommand = null;
+
+ // Clear the list past the top.
+ //
+ for (ListIterator commands = commandList.listIterator(top--); commands.hasNext(); commands.remove()) {
+ Command otherCommand = (Command) commands.next();
+ otherCommand.dispose();
+ }
+ }
+
+ notifyListeners();
+ }
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public void flush() {
+ // Clear the list.
+ //
+ for (ListIterator commands = commandList.listIterator(); commands.hasNext(); commands.remove()) {
+ Command command = (Command) commands.next();
+ command.dispose();
+ }
+ commandList.clear();
+ top = -1;
+ saveIndex = -1;
+ notifyListeners();
+ mostRecentCommand = null;
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public Command getUndoCommand() {
+ return top == -1 || top == commandList.size() ? null : (Command) commandList.get(top);
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public Command getRedoCommand() {
+ return top + 1 >= commandList.size() ? null : (Command) commandList.get(top + 1);
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public Command getMostRecentCommand() {
+ return mostRecentCommand;
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public void addCommandStackListener(CommandStackListener listener) {
+ listeners.add(listener);
+ }
+
+ /*
+ * Javadoc copied from interface.
+ */
+ public void removeCommandStackListener(CommandStackListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * This is called to ensure that
+ * {@link CommandStackListener#commandStackChanged} is called for each
+ * listener.
+ */
+ protected void notifyListeners() {
+ for (Iterator i = listeners.iterator(); i.hasNext();) {
+ ((CommandStackListener) i.next()).commandStackChanged(new EventObject(this));
+ }
+ }
+
+ /**
+ * Handles an exception thrown during command execution by loging it with
+ * the plugin.
+ */
+ protected void handleError(Exception exception) {
+ Logger.logException("_UI_IgnoreException_exception", exception);
+ }
+
+ /**
+ * Called after a save has been successfully performed.
+ */
+ public void saveIsDone() {
+ // Remember where we are now.
+ //
+ saveIndex = top;
+ }
+
+ /**
+ * Returns whether the model has changes since {@link #saveIsDone} was
+ * call the last.
+ *
+ * @return whether the model has changes since <code>saveIsDone</code>
+ * was call the last.
+ */
+ public boolean isSaveNeeded() {
+ // Only if we are at the remembered index do we NOT need to save.
+ //
+ // return top != saveIndex;
+
+ if (saveIndex < -1) {
+ return true;
+ }
+
+ if (top > saveIndex) {
+ for (int i = top; i > saveIndex; --i) {
+ if (!(commandList.get(i) instanceof AbstractCommand.NonDirtying)) {
+ return true;
+ }
+ }
+ }
+ else {
+ for (int i = saveIndex; i > top; --i) {
+ if (!(commandList.get(i) instanceof AbstractCommand.NonDirtying)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/Command.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/Command.java
new file mode 100644
index 0000000..00af9b0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/Command.java
@@ -0,0 +1,138 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: Command.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.Collection;
+
+
+/**
+ * An interface that every command is expected to support.
+ * A command can be tested for executability,
+ * it can be executed,
+ * it can be tested for undoability,
+ * it can be undone,
+ * and can then be redone.
+ * A comand also provides access to a result collection, an affected-objects collection,
+ * a label, and a description.
+ *
+ * <p>
+ * There are important constraints on the valid order in which the various methods may be invoked,
+ * e.g., you cannot ask for the result before you've executed the command.
+ * These constraints are documented with the various methods.
+ */
+public interface Command
+{
+ /**
+ * Returns whether the comamad is valid to <code>execute</code>.
+ * The {@link UnexecutableCommand#INSTANCE}.<code>canExecute()</code> always returns <code>false</code>.
+ * This <b>must</b> be called before calling <code>execute</code>.
+ * @return whether the comamad is valid to <code>execute</code>.
+ */
+ boolean canExecute();
+
+ /**
+ * Performs the command activity required for the effect.
+ * The effect of calling <code>execute</code> when <code>canExecute</code> returns <code>false</code>,
+ * or when <code>canExecute</code> hasn't been called, is undefined.
+ */
+ void execute();
+
+ /**
+ * Returns whether the command can be undone.
+ * The result of calling this before <code>execute</code> is well defined,
+ * but the result of calling this before calling <code>canExecute</code> is undefined, i.e.,
+ * a command that returns <code>false</code> for <code>canExecute</code> may return <code>true</code> for canUndo,
+ * even though that is a contradiction.
+ * @return whether the command can be undone.
+ */
+ boolean canUndo();
+
+ /**
+ * Performs the command activity required to <code>undo</code> the effects of a preceding <code>execute</code> (or <code>redo</code>).
+ * The effect, if any, of calling <code>undo</code> before <code>execute</code> or <code>redo</code> have been called,
+ * or when canUndo returns <code>false</code>, is undefined.
+ */
+ void undo();
+
+ /**
+ * Performs the command activity required to <code>redo</code> the effect after undoing the effect.
+ * The effect, if any, of calling <code>redo</code> before <code>undo</code> is called is undefined.
+ * Note that if you implement <code>redo</code> to call <code>execute</code>
+ * then any derived class will be restricted by that decision also.
+ */
+ void redo();
+
+ /**
+ * Returns a collection of things which this command wishes to present as it's result.
+ * The result of calling this before an <code>execute</code> or <code>redo</code>, or after an <code>undo</code>, is undefined.
+ * @return a collection of things which this command wishes to present as it's result.
+ */
+ Collection getResult();
+
+ /**
+ * Returns the collection of things which this command wishes to present as the objects affected by the command.
+ * Typically should could be used as the selection that should be highlighted to best illustrate the effect of the command.
+ * The result of calling this before an <code>execute</code>, <code>redo</code>, or <code>undo</code> is undefined.
+ * The result may be different after an <code>undo</code> than it is after an <code>execute</code> or <code>redo</code>,
+ * but the result should be the same (equivalent) after either an <code>execute</code> or <code>redo</code>.
+ * @return the collection of things which this command wishes to present as the objects affected by the command.
+ */
+ Collection getAffectedObjects();
+
+ /**
+ * Returns a string suitable to represent the label that identifies this command.
+ * @return a string suitable to represent the label that identifies this command.
+ */
+ String getLabel();
+
+ /**
+ * Returns a string suitable to help describe the effect of this command.
+ * @return a string suitable to help describe the effect of this command.
+ */
+ String getDescription();
+
+ /**
+ * Called to indicate that the command will never be used again.
+ * Calling any other method after this one has undefined results.
+ */
+ void dispose();
+
+ /**
+ * Returns a command that represents the composition of this command with the given command.
+ * The resulting command may just be this, if this command is capabable of composition.
+ * Otherwise, it will be a new command created to compose the two.
+ * <p>
+ * Instead of the following pattern of usage
+ * <pre>
+ * Command result = x;
+ * if (condition) result = result.chain(y);
+ * </pre>
+ * you should consider using a {@link org.eclipse.emf.common.command.CompoundCommand}
+ * and using {@link org.eclipse.emf.common.command.CompoundCommand#unwrap()} to optimize the result:
+ * <pre>
+ * CompoundCommand subcommands = new CompoundCommand();
+ * subcommands.append(x);
+ * if (condition) subcommands.append(y);
+ * Command result = subcommands.unwrap();
+ * </pre>
+ * This gives you more control over how the compound command composes it's result and affected objects.
+ * @param command the command to chain.
+ * @return a command that represents the composition of this command with the given command.
+ */
+ Command chain(Command command);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandStack.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandStack.java
new file mode 100644
index 0000000..19567dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandStack.java
@@ -0,0 +1,90 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: CommandStack.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+
+/**
+ * A simple and obvious interface for an undoable stack of commands with a listener.
+ * See {@link Command} for more details about the command methods that this implementation uses
+ * and {@link CommandStackListener} for details about the listener.
+ */
+public interface CommandStack
+{
+ /**
+ * Clears any redoable commands not yet redone, adds the command, and then executes the command.
+ * @param command the command to execute.
+ */
+ void execute(Command command);
+
+ /**
+ * Returns whether the top command on the stack can be undone.
+ * @return whether the top command on the stack can be undone.
+ */
+ boolean canUndo();
+
+ /**
+ * Moves the top of the stack down, undoing what was formerly the top command.
+ */
+ void undo();
+
+ /**
+ * Returns whether there are commands past the top of the stack that can be redone.
+ * @return whether there are commands past the top of the stack that can be redone.
+ */
+ boolean canRedo();
+
+ /**
+ * Returns the command that will be undone if {@link #undo} is called.
+ * @return the command that will be undone if {@link #undo} is called.
+ */
+ public Command getUndoCommand();
+
+ /**
+ * Returns the command that will be redone if {@link #redo} is called.
+ * @return the command that will be redone if {@link #redo} is called.
+ */
+ public Command getRedoCommand();
+
+ /**
+ * Returns the command most recently executed, undone, or redone.
+ * @return the command most recently executed, undone, or redone.
+ */
+ public Command getMostRecentCommand();
+
+ /**
+ * Moves the top of the stack up, redoing the new top command.
+ */
+ void redo();
+
+ /**
+ * Disposes all the commands in the stack.
+ */
+ void flush();
+
+ /**
+ * Adds a listener to the command stack, which will be notified whenever a command has been processed on the stack.
+ * @param listener the listener to add.
+ */
+ void addCommandStackListener(CommandStackListener listener);
+
+ /**
+ * Removes a listener from the command stack.
+ * @param listener the listener to remove.
+ */
+ void removeCommandStackListener(CommandStackListener listener);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandStackListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandStackListener.java
new file mode 100644
index 0000000..3f81e93
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandStackListener.java
@@ -0,0 +1,33 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: CommandStackListener.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.EventObject;
+
+
+/**
+ * A listener to a {@link org.eclipse.emf.common.command.CommandStack}.
+ */
+public interface CommandStackListener
+{
+ /**
+ * Called when the {@link org.eclipse.emf.common.command.CommandStack}'s state has changed.
+ * @param event the event.
+ */
+ void commandStackChanged(EventObject event);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandWrapper.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandWrapper.java
new file mode 100644
index 0000000..1359390
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CommandWrapper.java
@@ -0,0 +1,267 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: CommandWrapper.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.Collection;
+import java.util.Collections;
+
+
+/**
+ * A command that wraps another command. All the {@link Command} methods are
+ * delegated to the wrapped command.
+ *
+ * <p>
+ * There are two typical usage patterns. One typical use for this command is
+ * to modify the behaviour of a command that you can't subclass, i.e., a
+ * decorator pattern:
+ *
+ * <pre>
+ * Command decoratedCommand = new CommandWrapper(someOtherCommand) {
+ * public void execute() {
+ * doSomethingBeforeExecution();
+ * super.execute();
+ * doSomethingAfterExecution();
+ * }
+ *
+ * public Collection getResult() {
+ * return someOtherResult();
+ * }
+ * };
+ * </pre>
+ *
+ * The other typical use is to act as a proxy for a command who's creation is
+ * delayed:
+ *
+ * <pre>
+ * Command proxyCommand = new CommandWrapper() {
+ * public Command createCommand() {
+ * return createACommandSomehow();
+ * }
+ * };
+ * </pre>
+ */
+public class CommandWrapper extends AbstractCommand {
+ /**
+ * The command for which this is a proxy or decorator.
+ */
+ protected Command command;
+
+ /**
+ * Creates a decorator instance for the given command.
+ *
+ * @param command
+ * the command to wrap.
+ */
+ public CommandWrapper(Command command) {
+ super(command.getLabel(), command.getDescription());
+ this.command = command;
+ }
+
+ /**
+ * Creates a decorator instance with the given label for the given
+ * command.
+ *
+ * @param label
+ * the label of the wrapper
+ * @param command
+ * the command to wrap.
+ */
+ protected CommandWrapper(String label, Command command) {
+ super(label, command.getDescription());
+ this.command = command;
+ }
+
+ /**
+ * Creates a decorator instance with the given label and description for
+ * the given command.
+ *
+ * @param label
+ * the label of the wrapper
+ * @param description
+ * the description of the wrapper
+ * @param command
+ * the command to wrap.
+ */
+ public CommandWrapper(String label, String description, Command command) {
+ super(label, description);
+ this.command = command;
+ }
+
+ /**
+ * Creates a commandless proxy instance. The wrapped command will be
+ * created by a {@link #createCommand} callback. Since a proxy command
+ * like this is pointless unless you override some method, this
+ * constructor is protected.
+ */
+ protected CommandWrapper() {
+ super();
+ }
+
+ /**
+ * Creates a commandless proxy instance, with the given label. The command
+ * will be created by a {@link #createCommand} callback. Since a proxy
+ * command like this is pointless unless you override some method, this
+ * constructor is protected.
+ *
+ * @param label
+ * the label of the wrapper
+ */
+ protected CommandWrapper(String label) {
+ super(label);
+ }
+
+ /**
+ * Creates a commandless proxy instance, with the given label and
+ * description. The command will be created by a {@link #createCommand}
+ * callback. Since a proxy command like this is pointless unless you
+ * override some method, this constructor is protected.
+ *
+ * @param label
+ * the label of the wrapper
+ * @param description
+ * the description of the wrapper
+ */
+ protected CommandWrapper(String label, String description) {
+ super(label, description);
+ }
+
+ /**
+ * Returns the command for which this is a proxy or decorator. This may be
+ * <code>null</code> before {@link #createCommand} is called.
+ *
+ * @return the command for which this is a proxy or decorator.
+ */
+ public Command getCommand() {
+ return command;
+ }
+
+ /**
+ * Create the command being proxied. This implementation just return
+ * <code>null</code>. It is called by {@link #prepare}.
+ *
+ * @return the command being proxied.
+ */
+ protected Command createCommand() {
+ return null;
+ }
+
+ /**
+ * Returns whether the command can execute. This implementation creates
+ * the command being proxied using {@link #createCommand}, if the command
+ * wasn't given in the constructor.
+ *
+ * @return whether the command can execute.
+ */
+ protected boolean prepare() {
+ if (command == null) {
+ command = createCommand();
+ }
+
+ boolean result = command.canExecute();
+ return result;
+ }
+
+ /**
+ * Delegates to the execute method of the command.
+ */
+ public void execute() {
+ if (command != null) {
+ command.execute();
+ }
+ }
+
+ /**
+ * Delegates to the canUndo method of the command.
+ */
+ public boolean canUndo() {
+ return command == null || command.canUndo();
+ }
+
+ /**
+ * Delegates to the undo method of the command.
+ */
+ public void undo() {
+ if (command != null) {
+ command.undo();
+ }
+ }
+
+ /**
+ * Delegates to the redo method of the command.
+ */
+ public void redo() {
+ if (command != null) {
+ command.redo();
+ }
+ }
+
+ /**
+ * Delegates to the getResult method of the command.
+ *
+ * @return the result.
+ */
+ public Collection getResult() {
+ return command == null ? Collections.EMPTY_LIST : command.getResult();
+ }
+
+ /**
+ * Delegates to the getAffectedObjects method of the command.
+ *
+ * @return the result.
+ */
+ public Collection getAffectedObjects() {
+ return command == null ? Collections.EMPTY_LIST : command.getAffectedObjects();
+ }
+
+ /**
+ * Delegates to the getLabel method of the command.
+ *
+ * @return the label.
+ */
+ public String getLabel() {
+ return label == null ? command == null ? "_UI_CommandWrapper_label" : command.getLabel() : label;
+ }
+
+ /**
+ * Delegates to the getDescription method of the command.
+ *
+ * @return the description.
+ */
+ public String getDescription() {
+ return description == null ? command == null ? "_UI_CommandWrapper_description" : command.getDescription() : description;
+ }
+
+ /**
+ * Delegates to the dispose method of the command.
+ */
+ public void dispose() {
+ if (command != null) {
+ command.dispose();
+ }
+ }
+
+ /*
+ * Javadoc copied from base class.
+ */
+ public String toString() {
+ StringBuffer result = new StringBuffer(super.toString());
+ result.append(" (command: " + command + ")");
+
+ return result.toString();
+ }
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CompoundCommand.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CompoundCommand.java
new file mode 100644
index 0000000..b70fbbb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/CompoundCommand.java
@@ -0,0 +1,718 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: CompoundCommand.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.wst.sse.core.internal.Logger;
+
+
+/**
+ * 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
+ * <code>false</code> to be returned.
+ *
+ * @return whether all the commands can execute.
+ */
+ protected boolean prepare() {
+ if (commandList.isEmpty()) {
+ return false;
+ }
+ else {
+ for (Iterator commands = commandList.listIterator(); commands.hasNext();) {
+ Command command = (Command) commands.next();
+ 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 = (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 = (Command) commands.previous();
+ if (command.canUndo()) {
+ command.undo();
+ }
+ else {
+ break;
+ }
+ }
+ }
+ catch (RuntimeException nestedException) {
+ Logger.logException("_UI_IgnoreException_exception", nestedException);
+ }
+
+ throw exception;
+ }
+ }
+ }
+
+ /**
+ * Returns <code>false</code> if any of the commands return
+ * <code>false</code> for {@link Command#canUndo}.
+ *
+ * @return <code>false</code> if any of the commands return
+ * <code>false</code> for <code>canUndo</code>.
+ */
+ public boolean canUndo() {
+ for (Iterator commands = commandList.listIterator(); commands.hasNext();) {
+ Command command = (Command) commands.next();
+ if (!command.canUndo()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Calls {@link Command#undo} for each command in the list, in reverse
+ * order.
+ */
+ public void undo() {
+ for (ListIterator commands = commandList.listIterator(commandList.size()); commands.hasPrevious();) {
+ try {
+ Command 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 = (Command) commands.next();
+ command.redo();
+ }
+ }
+ catch (RuntimeException nestedException) {
+ Logger.logException("_UI_IgnoreException_exception", exception);
+ }
+
+
+ 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 = (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 = (Command) commands.previous();
+ command.undo();
+ }
+ }
+ catch (RuntimeException nestedException) {
+ Logger.logException("_UI_IgnoreException_exception", nestedException);
+ }
+
+ 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.
+ */
+ public Collection getResult() {
+ if (commandList.isEmpty()) {
+ return Collections.EMPTY_LIST;
+ }
+ else if (resultIndex == LAST_COMMAND_ALL) {
+ return ((Command) commandList.get(commandList.size() - 1)).getResult();
+ }
+ else if (resultIndex == MERGE_COMMAND_ALL) {
+ return getMergedResultCollection();
+ }
+ else if (resultIndex < commandList.size()) {
+ return ((Command) 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 result = new ArrayList();
+
+ for (Iterator commands = commandList.iterator(); commands.hasNext();) {
+ Command command = (Command) commands.next();
+ result.addAll(command.getResult());
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Determines the affected objects by composing the affected objects of
+ * the commands in the list; this is affected by the setting of
+ * {@link #resultIndex}.
+ *
+ * @return the affected objects.
+ */
+ public Collection getAffectedObjects() {
+ if (commandList.isEmpty()) {
+ return Collections.EMPTY_LIST;
+ }
+ else if (resultIndex == LAST_COMMAND_ALL) {
+ return ((Command) commandList.get(commandList.size() - 1)).getAffectedObjects();
+ }
+ else if (resultIndex == MERGE_COMMAND_ALL) {
+ return getMergedAffectedObjectsCollection();
+ }
+ else if (resultIndex < commandList.size()) {
+ return ((Command) commandList.get(resultIndex)).getAffectedObjects();
+ }
+ else {
+ return Collections.EMPTY_LIST;
+ }
+ }
+
+ /**
+ * Returns the merged collection of all command affected objects.
+ *
+ * @return the merged collection of all command affected objects.
+ */
+ protected Collection getMergedAffectedObjectsCollection() {
+ Collection result = new ArrayList();
+
+ for (Iterator commands = commandList.iterator(); commands.hasNext();) {
+ Command command = (Command) commands.next();
+ result.addAll(command.getAffectedObjects());
+ }
+
+ return result;
+ }
+
+ /**
+ * Determines the label by composing the labels of the commands in the
+ * list; this is affected by the setting of {@link #resultIndex}.
+ *
+ * @return the label.
+ */
+ public String getLabel() {
+ if (label != null) {
+ return label;
+ }
+ else if (commandList.isEmpty()) {
+ return "_UI_CompoundCommand_label";
+ }
+ else if (resultIndex == LAST_COMMAND_ALL || resultIndex == MERGE_COMMAND_ALL) {
+ return ((Command) commandList.get(commandList.size() - 1)).getLabel();
+ }
+ else if (resultIndex < commandList.size()) {
+ return ((Command) commandList.get(resultIndex)).getLabel();
+ }
+ else {
+ return "_UI_CompoundCommand_label";
+ }
+ }
+
+ /**
+ * Determines the description by composing the descriptions of the
+ * commands in the list; this is affected by the setting of
+ * {@link #resultIndex}.
+ *
+ * @return the description.
+ */
+ public String getDescription() {
+ if (description != null) {
+ return description;
+ }
+ else if (commandList.isEmpty()) {
+ return "_UI_CompoundCommand_description";
+ }
+ else if (resultIndex == LAST_COMMAND_ALL || resultIndex == MERGE_COMMAND_ALL) {
+ return ((Command) commandList.get(commandList.size() - 1)).getDescription();
+ }
+ else if (resultIndex < commandList.size()) {
+ return ((Command) commandList.get(resultIndex)).getDescription();
+ }
+ else {
+ return "_UI_CompoundCommand_description";
+ }
+ }
+
+ /**
+ * Adds a command to this compound command's list of commands.
+ *
+ * @param command
+ * the command to append.
+ */
+ public void append(Command command) {
+ if (command != null) {
+ commandList.add(command);
+ }
+ }
+
+ /**
+ * Checks if the command can execute; if so, it is executed, appended to
+ * the list, and true is returned, if not, it is just disposed and false
+ * is returned. A typical use for this is to execute commands created
+ * during the execution of another command, e.g.,
+ *
+ * <pre>
+ * class MyCommand extends CommandBase {
+ * protected Command subcommand;
+ *
+ * //...
+ *
+ * public void execute()
+ * {
+ * // ...
+ * Compound subcommands = new CompoundCommand();
+ * subcommands.appendAndExecute(new AddCommand(...));
+ * if (condition) subcommands.appendAndExecute(new AddCommand(...));
+ * subcommand = subcommands.unwrap();
+ * } public void undo() {
+ * // ...
+ * subcommand.undo();
+ * }
+ *
+ * public void redo() {
+ * // ...
+ * subcommand.redo();
+ * }
+ *
+ * public void dispose() {
+ * // ...
+ * if (subcommand != null) {
+ * subcommand.dispose();
+ * }
+ * }
+ * }
+ *
+ * </pre>
+ *
+ * Another use is in an execute override of compound command itself:
+ *
+ * <pre>
+ * class MyCommand extends CompoundCommand {
+ * public void execute()
+ * {
+ * // ...
+ * appendAndExecute(new AddCommand(...));
+ * if (condition) appendAndExecute(new AddCommand(...));
+ * }}
+ *
+ * </pre>
+ *
+ * Note that appending commands will modify what getResult and
+ * getAffectedObjects return, so you may want to set the resultIndex flag.
+ *
+ * @param command
+ * the command.
+ * @return whether the command was successfully executed and appended.
+ */
+ public boolean appendAndExecute(Command command) {
+ if (command != null) {
+ if (!isPrepared) {
+ if (commandList.isEmpty()) {
+ isPrepared = true;
+ isExecutable = true;
+ }
+ else {
+ isExecutable = prepare();
+ isPrepared = true;
+ if (isExecutable) {
+ execute();
+ }
+ }
+ }
+
+ if (command.canExecute()) {
+ try {
+ command.execute();
+ commandList.add(command);
+ return true;
+ }
+ catch (RuntimeException exception) {
+ Logger.logException("_UI_IgnoreException_exception", exception);
+ }
+ }
+
+ command.dispose();
+ }
+
+ return false;
+ }
+
+ /**
+ * Adds a command to this compound command's the list of commands and
+ * returns <code>true</code>, if
+ * <code>command.{@link org.eclipse.emf.common.command.Command#canExecute() canExecute()}</code>
+ * returns true; otherwise, it simply calls
+ * <code>command.{@link org.eclipse.emf.common.command.Command#dispose() dispose()}</code>
+ * and returns <code>false</code>.
+ *
+ * @param command
+ * the command.
+ * @return whether the command was executed and appended.
+ */
+ public boolean appendIfCanExecute(Command command) {
+ if (command == null) {
+ return false;
+ }
+ else if (command.canExecute()) {
+ commandList.add(command);
+ return true;
+ }
+ else {
+ command.dispose();
+ return false;
+ }
+ }
+
+ /**
+ * Calls {@link Command#dispose} for each command in the list.
+ */
+ public void dispose() {
+ for (Iterator commands = commandList.listIterator(); commands.hasNext();) {
+ Command command = (Command) commands.next();
+ command.dispose();
+ }
+ }
+
+ /**
+ * Returns one of three things:
+ * {@link org.eclipse.emf.common.command.UnexecutableCommand#INSTANCE},
+ * if there are no commands, the one command, if there is exactly one
+ * command, or <code>this</code>, if there are multiple commands; this
+ * command is {@link #dispose}d in the first two cases. You should only
+ * unwrap a compound command if you created it for that purpose, e.g.,
+ *
+ * <pre>
+ * CompoundCommand subcommands = new CompoundCommand();
+ * subcommands.append(x);
+ * if (condition)
+ * subcommands.append(y);
+ * Command result = subcommands.unwrap();
+ * </pre>
+ *
+ * is a good way to create an efficient accumulated result.
+ *
+ * @return the unwapped command.
+ */
+ public Command unwrap() {
+ switch (commandList.size()) {
+ case 0 : {
+ dispose();
+ return UnexecutableCommand.INSTANCE;
+ }
+ case 1 : {
+ Command result = (Command) commandList.remove(0);
+ dispose();
+ return result;
+ }
+ default : {
+ return this;
+ }
+ }
+ }
+
+ /*
+ * Javadoc copied from base class.
+ */
+ public String toString() {
+ StringBuffer result = new StringBuffer(super.toString());
+ result.append(" (commandList: #" + commandList.size() + ")");
+ result.append(" (resultIndex: " + resultIndex + ")");
+
+ return result.toString();
+ }
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/IdentityCommand.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/IdentityCommand.java
new file mode 100644
index 0000000..43485bd
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/IdentityCommand.java
@@ -0,0 +1,212 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: IdentityCommand.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.Collection;
+import java.util.Collections;
+
+
+/**
+ * A command that always produces the same result.
+ */
+public class IdentityCommand extends AbstractCommand {
+ /**
+ * An empty instance of this object.
+ */
+ public static final IdentityCommand INSTANCE = new IdentityCommand();
+
+ /**
+ * Keeps track of the result returned from {@link #getResult}.
+ */
+ protected Collection result;
+
+ {
+ // This ensures that these useless state variables at least reflect
+ // the right value.
+ //
+ isPrepared = true;
+ isExecutable = true;
+ }
+
+ /**
+ * Creates an empty instance.
+ */
+ public IdentityCommand() {
+ super();
+ this.result = Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Creates an instance with a result collection containing the given
+ * result object.
+ *
+ * @param result
+ * the one object in the result collection.
+ */
+ public IdentityCommand(Object result) {
+ super();
+ this.result = Collections.singleton(result);
+ }
+
+ /**
+ * Creates an instance with the given result collection.
+ *
+ * @param result
+ * the result collection.
+ */
+ public IdentityCommand(Collection result) {
+ super();
+ this.result = result;
+ }
+
+ /**
+ * Creates an instance with the given label.
+ *
+ * @param label
+ * the label.
+ */
+ public IdentityCommand(String label) {
+ this.label = label;
+ this.result = Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Creates an instance with the given label and a result collection
+ * containing the given result object.
+ *
+ * @param label
+ * the label.
+ * @param result
+ * the one object in the result collection.
+ */
+ public IdentityCommand(String label, Object result) {
+ this.label = label;
+ this.result = Collections.singleton(result);
+ }
+
+ /**
+ * Creates an instance with the given label the result collection.
+ *
+ * @param label
+ * the label.
+ * @param result
+ * the result collection.
+ */
+ public IdentityCommand(String label, Collection result) {
+ this.label = label;
+ this.result = result;
+ }
+
+ /**
+ * Creates an instance with the given label and description.
+ *
+ * @param label
+ * the label.
+ * @param description
+ * the description.
+ */
+ public IdentityCommand(String label, String description) {
+ this.label = label;
+ this.description = description;
+ this.result = Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Creates an instance with the given label, description, and a result
+ * collection containing the given result object.
+ *
+ * @param label
+ * the label.
+ * @param description
+ * the description.
+ * @param result
+ * the one object in the result collection.
+ */
+ public IdentityCommand(String label, String description, Object result) {
+ this.label = label;
+ this.description = description;
+ this.result = Collections.singleton(result);
+ }
+
+ /**
+ * Creates an instance with the given label, description, result
+ * collection.
+ *
+ * @param label
+ * the label.
+ * @param description
+ * the description.
+ * @param result
+ * the result collection.
+ */
+ public IdentityCommand(String label, String description, Collection result) {
+ this.label = label;
+ this.description = description;
+ this.result = result;
+ }
+
+ /**
+ * Returns <code>true</code>.
+ *
+ * @return <code>true</code>.
+ */
+ public boolean canExecute() {
+ return true;
+ }
+
+ /**
+ * Do nothing.
+ */
+ public void execute() {
+ }
+
+ /**
+ * Do nothing.
+ */
+ public void undo() {
+ }
+
+ /**
+ * Do nothing.
+ */
+ public void redo() {
+ }
+
+ /*
+ * Javadoc copied from base class.
+ */
+ public String getLabel() {
+ return label == null ? "_UI_IdentityCommand_label" : label;
+ }
+
+ /*
+ * Javadoc copied from base class.
+ */
+ public String getDescription() {
+ return description == null ? "_UI_IdentityCommand_description" : description;
+ }
+
+ /**
+ * Return the identity result.
+ *
+ * @return the identity result.
+ */
+ public Collection getResult() {
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/StrictCompoundCommand.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/StrictCompoundCommand.java
new file mode 100644
index 0000000..3e852a7
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/StrictCompoundCommand.java
@@ -0,0 +1,426 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: StrictCompoundCommand.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.wst.sse.core.internal.Logger;
+
+
+/**
+ * A composite command which assumes that later commands in the list may
+ * depend on the results and side-effects of earlier commands in the list.
+ * Because of this, it must implement {@link Command#canExecute} more
+ * carefully, i.e., in order to determine canExecute for the composite, it
+ * doesn't simply test each command. It tests the first command to see if it
+ * can execute; then, if there is another command in the list, it checks if
+ * the first command can undo and then goes ahead and executes it! This
+ * process is repeated until the last command that is not followed by another,
+ * which then determines the final result. (For efficiency, when this
+ * processing gets to the last command, that command is tested for canUndo too
+ * and that result is cached.) All the commands that have been executed are
+ * then undone, if {@link #isPessimistic} is <code>true</code>; by default
+ * it's <code>false</code>.
+ *
+ * <p>
+ * It is important for all but the last command to have no visible
+ * side-effect! Multiple commands with visible side-effects must be composed
+ * into a single command using just a {@link CompoundCommand} and that
+ * composite could be the last command of a strict composite.
+ *
+ * <p>
+ * Here is an example of how this can be used in conjunction with a
+ * {@link CommandWrapper}.
+ *
+ * <pre>
+ *
+ *
+ * Command strictCompoundCommand = new StrictCompoundCommand();
+ * Command copyCommand = new CopyCommand(...);
+ * strictCompoundCommand.add(copyCommand);
+ *
+ * Command addCommand =
+ * new CommandWrapper()
+ * {
+ * public Command createCommand()
+ * {
+ * new AddCommand(parent, copyCommand.getResult());
+ * }
+ * };
+ * strictCompoundCommand.append(addCommand);
+ *
+ *
+ * </pre>
+ *
+ * Here the add command won't know which command to create until it has the
+ * result of the copy command. The proxy makes sure the creation of the add
+ * command is deferred and the strict composite ensures that execution
+ * dependencies are met.
+ */
+public class StrictCompoundCommand extends CompoundCommand {
+ /**
+ * The result for {@link Command#canUndo}.
+ */
+ protected boolean isUndoable;
+
+ /**
+ * Whether commands that have been tentatively executed need to be undone.
+ */
+ protected boolean isPessimistic;
+
+ /**
+ * Remember to call redo instead of execute for any command at or before
+ * this index in the list.
+ */
+ protected int rightMostExecutedCommandIndex = -1;
+
+ /**
+ * Creates an empty instance.
+ */
+ public StrictCompoundCommand() {
+ super();
+ resultIndex = LAST_COMMAND_ALL;
+ }
+
+ /**
+ * Creates an instance with the given label.
+ *
+ * @param label
+ * the label.
+ */
+ public StrictCompoundCommand(String label) {
+ super(label);
+ resultIndex = LAST_COMMAND_ALL;
+ }
+
+ /**
+ * Creates an instance with the given label and description.
+ *
+ * @param label
+ * the label.
+ * @param description
+ * the description.
+ */
+ public StrictCompoundCommand(String label, String description) {
+ super(label, description);
+ resultIndex = LAST_COMMAND_ALL;
+ }
+
+ /**
+ * Creates an instance with the given command list.
+ *
+ * @param commandList
+ * the list of commands.
+ */
+ public StrictCompoundCommand(List commandList) {
+ super(commandList);
+ resultIndex = LAST_COMMAND_ALL;
+ }
+
+ /**
+ * Creates an instance with the given label and command list.
+ *
+ * @param label
+ * the label.
+ * @param commandList
+ * the list of commands.
+ */
+ public StrictCompoundCommand(String label, List commandList) {
+ super(label, commandList);
+ resultIndex = LAST_COMMAND_ALL;
+ }
+
+ /**
+ * Creates an instance with the given label, description, and command
+ * list.
+ *
+ * @param label
+ * the label.
+ * @param description
+ * the description.
+ * @param commandList
+ * the list of commands.
+ */
+ public StrictCompoundCommand(String label, String description, List commandList) {
+ super(label, description, commandList);
+ resultIndex = LAST_COMMAND_ALL;
+ }
+
+ /**
+ * Returns <code>false</code> if any command on the list returns
+ * <code>false</code> for {@link Command#canExecute}, or if some
+ * command before the last one can't be undone and hence we can't test all
+ * the commands for executability.
+ *
+ * @return whether the command can execute.
+ */
+ protected boolean prepare() {
+ // Go through the commands of the list.
+ //
+ ListIterator commands = commandList.listIterator();
+
+ // If there are some...
+ //
+ if (commands.hasNext()) {
+ boolean result = true;
+
+ // The termination guard is in the body.
+ //
+ for (;;) {
+ Command command = (Command) commands.next();
+ if (command.canExecute()) {
+ if (commands.hasNext()) {
+ if (command.canUndo()) {
+ try {
+ if (commands.previousIndex() <= rightMostExecutedCommandIndex) {
+ command.redo();
+ }
+ else {
+ ++rightMostExecutedCommandIndex;
+ command.execute();
+ }
+ }
+ catch (RuntimeException exception) {
+ Logger.logException("_UI_IgnoreException_exception", exception);
+
+ result = false;
+ break;
+ }
+ }
+ else {
+ // We can't undo it, so we'd better give up.
+ //
+ result = false;
+ break;
+ }
+ }
+ else {
+ // Now is the best time to record isUndoable because
+ // later we would have to do all the executes again!
+ // This makes canUndo very simple!
+ //
+ isUndoable = command.canUndo();
+ break;
+ }
+ }
+ else {
+ // If we can't execute this one, we just can't do it at
+ // all.
+ //
+ result = false;
+ break;
+ }
+ }
+
+ // If we are pessimistic, then we need to undo all the commands
+ // that we have executed so far.
+ //
+ if (isPessimistic) {
+ // The most recently processed command will never have been
+ // executed.
+ //
+ commands.previous();
+
+ // We want to unroll all the effects of the previous commands.
+ //
+ while (commands.hasPrevious()) {
+ Command command = (Command) commands.previous();
+ command.undo();
+ }
+ }
+
+ return result;
+ }
+ else {
+ isUndoable = false;
+ return false;
+ }
+ }
+
+ /**
+ * Calls {@link Command#execute} for each command in the list, but makes
+ * sure to call redo for any commands that were previously executed to
+ * compute canExecute. In the case that {@link #isPessimistic} is false,
+ * only the last command will be executed since the others will have been
+ * executed but not undone during {@link #prepare}.
+ */
+ public void execute() {
+ if (isPessimistic) {
+ for (ListIterator commands = commandList.listIterator(); commands.hasNext();) {
+ try {
+ // Either execute or redo the command, as appropriate.
+ //
+ Command command = (Command) commands.next();
+ if (commands.previousIndex() <= rightMostExecutedCommandIndex) {
+ command.redo();
+ }
+ else {
+ command.execute();
+ }
+ }
+ catch (RuntimeException exception) {
+ // Skip over the command that threw the exception.
+ //
+ commands.previous();
+
+ // Iterate back over the executed commands to undo them.
+ //
+ while (commands.hasPrevious()) {
+ commands.previous();
+ Command command = (Command) commands.previous();
+ if (command.canUndo()) {
+ command.undo();
+ }
+ else {
+ break;
+ }
+ }
+
+ throw exception;
+ }
+ }
+ }
+ else if (!commandList.isEmpty()) {
+ Command command = (Command) commandList.get(commandList.size() - 1);
+ command.execute();
+ }
+ }
+
+ /**
+ * Calls {@link Command#undo} for each command in the list. In the case
+ * that {@link #isPessimistic} is false, only the last command will be
+ * undone since the others will have been executed and not undo during
+ * {@link #prepare}.
+ */
+ public void undo() {
+ if (isPessimistic) {
+ super.undo();
+ }
+ else if (!commandList.isEmpty()) {
+ Command command = (Command) commandList.get(commandList.size() - 1);
+ command.undo();
+ }
+ }
+
+ /**
+ * Calls {@link Command#redo} for each command in the list. In the case
+ * that {@link #isPessimistic} is false, only the last command will be
+ * redone since the others will have been executed and not undo during
+ * {@link #prepare}.
+ */
+ public void redo() {
+ if (isPessimistic) {
+ super.redo();
+ }
+ else if (!commandList.isEmpty()) {
+ Command command = (Command) commandList.get(commandList.size() - 1);
+ command.redo();
+ }
+ }
+
+ /**
+ * Checks if the command can execute; if so, it is executed, appended to
+ * the list, and <code>true</code> is returned, if not, it is just
+ * disposed and <code>false</code> is returned. A typical use for this
+ * is to execute commands created during the execution of another command,
+ * e.g.,
+ *
+ * <pre>
+ * class MyCommand extends AbstractCommand {
+ * protected Command subcommand;
+ *
+ * //...
+ *
+ * public void execute()
+ * {
+ * // ...
+ * StrictCompoundCommand subcommands = new StrictCompoundCommand();
+ * subcommands.appendAndExecute(new AddCommand(...));
+ * if (condition) subcommands.appendAndExecute(new AddCommand(...));
+ * subcommand = subcommands.unwrap();
+ * } public void undo() {
+ * // ...
+ * subcommand.undo();
+ * }
+ *
+ * public void redo() {
+ * // ...
+ * subcommand.redo();
+ * }
+ *
+ * public void dispose() {
+ * // ...
+ * if (subcommand != null) {
+ * subcommand.dispose();
+ * }
+ * }
+ * }
+ *
+ * </pre>
+ *
+ * @return whether the command was successfully executed and appended.
+ */
+ public boolean appendAndExecute(Command command) {
+ if (command != null) {
+ if (!isPrepared) {
+ if (commandList.isEmpty()) {
+ isPrepared = true;
+ isExecutable = true;
+ }
+ else {
+ isExecutable = prepare();
+ isPrepared = true;
+ isPessimistic = true;
+ if (isExecutable) {
+ execute();
+ }
+ }
+ }
+
+ if (command.canExecute()) {
+ try {
+ command.execute();
+ commandList.add(command);
+ ++rightMostExecutedCommandIndex;
+ isUndoable = command.canUndo();
+ return true;
+ }
+ catch (RuntimeException exception) {
+ Logger.logException("_UI_IgnoreException_exception", exception);
+ }
+ }
+
+ command.dispose();
+ }
+
+ return false;
+ }
+
+ /*
+ * Javadoc copied from base class.
+ */
+ public String toString() {
+ StringBuffer result = new StringBuffer(super.toString());
+ result.append(" (isUndoable: " + isUndoable + ")");
+ result.append(" (isPessimistic: " + isPessimistic + ")");
+ result.append(" (rightMostExecutedCommandIndex: " + rightMostExecutedCommandIndex + ")");
+
+ return result.toString();
+ }
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/UnexecutableCommand.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/UnexecutableCommand.java
new file mode 100644
index 0000000..bb5b2e0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/UnexecutableCommand.java
@@ -0,0 +1,74 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: UnexecutableCommand.java,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+package org.eclipse.emf.common.command;
+
+
+
+/**
+ * A singleton {@link UnexecutableCommand#INSTANCE} that cannot execute.
+ */
+public class UnexecutableCommand extends AbstractCommand {
+ /**
+ * The one instance of this object.
+ */
+ public static final UnexecutableCommand INSTANCE = new UnexecutableCommand();
+
+ /**
+ * Only one private instance is created.
+ */
+ private UnexecutableCommand() {
+ super("_UI_UnexecutableCommand_label", "_UI_UnexecutableCommand_description");
+ }
+
+ /**
+ * Returns <code>false</code>.
+ *
+ * @return <code>false</code>.
+ */
+ public boolean canExecute() {
+ return false;
+ }
+
+ /**
+ * Throws an exception if it should ever be called.
+ *
+ * @exception UnsupportedOperationException
+ * always.
+ */
+ public void execute() {
+ throw new RuntimeException("UnsupportedOperation");
+ }
+
+ /**
+ * Returns <code>false</code>.
+ *
+ * @return <code>false</code>.
+ */
+ public boolean canUndo() {
+ return false;
+ }
+
+ /**
+ * Throws an exception if it should ever be called.
+ *
+ * @exception UnsupportedOperationException
+ * always.
+ */
+ public void redo() {
+ throw new RuntimeException("UnsupportedOperation");
+ }
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/package.html b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/package.html
new file mode 100644
index 0000000..5e09942
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/emf/common/command/package.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta name="generator" content="HTML Tidy, see www.w3.org" />
+<meta http-equiv="Content-Type"
+content="text/html; charset=ISO-8859-1" /><!--
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2002-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: package.html,v 1.1 2005/04/15 23:31:25 david_williams Exp $
+ */
+-->
+<title></title>
+</head>
+<body>
+Provides a framework for implementing and composing commands.
+
+This was copied from the EMF common package as a temporary step
+as we transition to the new undo support in the base Eclipse.
+
+</body>
+</html>
+