blob: 34a7ffcb1841364f14435effdcaab5493f4a3416 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2005 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 Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.j2ee.internal.webservice.command;
import java.util.Collection;
import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
public class CommandAddElement extends AbstractCommand {
private EObject parent_;
private EStructuralFeature childFeature_;
private Object newChild_;
private Object oldChild_;
private boolean oldChildSet_;
public CommandAddElement(String label, String description, EObject parent, EStructuralFeature childFeature, Object newChild) {
super(label, description);
parent_ = parent;
childFeature_ = childFeature;
newChild_ = newChild;
oldChild_ = null;
oldChildSet_ = true;
}
public CommandAddElement(String label, String description, EObject parent, EClass childEClass, EStructuralFeature childFeature, EStructuralFeature[] childProperties, Object[] propertyValues) {
super(label, description);
parent_ = parent;
childFeature_ = childFeature;
newChild_ = createNewChild(childEClass, (childProperties != null) ? childProperties : new EStructuralFeature[0], (propertyValues != null) ? propertyValues : new Object[0]);
oldChild_ = null;
oldChildSet_ = true;
}
private Object createNewChild(EClass childEClass, EStructuralFeature[] childProperties, Object[] propertyValues) {
EFactory eFactory = childEClass.getEPackage().getEFactoryInstance();
EObject newChild = eFactory.create(childEClass);
if (newChild != null)
for (int i = 0; i < childProperties.length; i++)
newChild.eSet(childProperties[i], propertyValues[i]);
return newChild;
}
/**
* 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 true;
}
/**
* 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>.
*/
public boolean canExecute() {
return super.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.
*/
public void execute() {
if (childFeature_.isMany()) {
if (newChild_ != null)
((EList) parent_.eGet(childFeature_)).add(newChild_);
} else {
oldChild_ = parent_.eGet(childFeature_);
oldChildSet_ = parent_.eIsSet(childFeature_);
parent_.eSet(childFeature_, newChild_);
}
}
/**
* Returns <code>true</code> because most command should be undoable.
*
* @return <code>true</code>.
*/
public boolean canUndo() {
return true;
}
/**
* 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.
*/
public void undo() {
if (childFeature_.isMany()) {
if (newChild_ != null)
((EList) parent_.eGet(childFeature_)).remove(newChild_);
} else {
if (oldChildSet_)
parent_.eSet(childFeature_, oldChild_);
else
parent_.eUnset(childFeature_);
}
}
/**
* 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.
*/
public void redo() {
execute();
}
/**
* 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.
*/
public Collection getResult() {
return super.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.
*/
public Collection getAffectedObjects() {
return super.getAffectedObjects();
}
/**
* Called to indicate that the command will never be used again. Calling any other method after
* this one has undefined results.
*/
public void dispose() {
//Do nothing
}
/**
* 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.
*/
public Command chain(Command command) {
return super.chain(command);
}
public Object getAddedObject() {
return newChild_;
}
}