/** * Copyright (c) 2002-2010 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 */ package org.eclipse.emf.edit.command; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; 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.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.edit.domain.EditingDomain; /** * This is a convenient base class for classes that implement {@link OverrideableCommand}. * Subclasses of AbstractOverrideableCommand should provide implementations of the doXxx methods * (e.g., doExecute) from OverrideableCommand instead of the base command methods (e.g., * execute), which have final implementations here. */ public abstract class AbstractOverrideableCommand extends AbstractCommand implements OverrideableCommand { /** * This is the editing domain in which this command operates. */ protected EditingDomain domain; /** * This is the command that overrides this command. */ protected Command overrideCommand; /** * This constructs an instance in this editing domain. */ protected AbstractOverrideableCommand(EditingDomain domain) { this(domain, null, null); } /** * This constructs an instance with the given label and in this editing domain. */ protected AbstractOverrideableCommand(EditingDomain domain, String label) { this(domain, label, null); } /** * This constructs an instance with the given label and description, in this editing domain. */ protected AbstractOverrideableCommand(EditingDomain domain, String label, String description) { super(label, description); this.domain = domain; } /** * This returns the editing domain that contains this. */ public EditingDomain getDomain() { return domain; } /** * This returns the command that overrides this command. */ public Command getOverride() { return overrideCommand; } /** * This sets the command that overrides this command. */ public void setOverride(Command overrideCommand) { this.overrideCommand = overrideCommand; } @Override public final boolean canExecute() { if (domain != null && !isPrepared) { Command newOverrideCommand = domain.createOverrideCommand(this); setOverride(newOverrideCommand); } boolean result = overrideCommand != null ? overrideCommand.canExecute() : doCanExecute(); return result; } public boolean doCanExecute() { return super.canExecute(); } public final void execute() { if (overrideCommand != null) { overrideCommand.execute(); } else { doExecute(); } } public abstract void doExecute(); @Override public final boolean canUndo() { boolean result = overrideCommand != null ? overrideCommand.canUndo() : doCanUndo(); return result; } public boolean doCanUndo() { return super.canUndo(); } @Override public final void undo() { if (overrideCommand != null) { overrideCommand.undo(); } else { doUndo(); } } public abstract void doUndo(); public final void redo() { if (overrideCommand != null) { overrideCommand.redo(); } else { doRedo(); } } public abstract void doRedo(); @Override public final Collection<?> getResult() { return overrideCommand != null ? overrideCommand.getResult() : doGetResult(); } public Collection<?> doGetResult() { return super.getResult(); } @Override public final Collection<?> getAffectedObjects() { return overrideCommand != null ? overrideCommand.getAffectedObjects() : doGetAffectedObjects(); } public Collection<?> doGetAffectedObjects() { return super.getAffectedObjects(); } @Override public final String getLabel() { return overrideCommand != null ? overrideCommand.getLabel() : doGetLabel(); } public String doGetLabel() { return super.getLabel(); } @Override public final String getDescription() { return overrideCommand != null ? overrideCommand.getDescription() : doGetDescription(); } public String doGetDescription() { return super.getDescription(); } @Override public final void dispose() { if (overrideCommand != null) { overrideCommand.dispose(); } else { doDispose(); } } public void doDispose() { super.dispose(); } public final Collection<?> getChildrenToCopy() { Collection<?> result = overrideCommand instanceof ChildrenToCopyProvider ? ((ChildrenToCopyProvider)overrideCommand).getChildrenToCopy() : doGetChildrenToCopy(); return result; } public Collection<?> doGetChildrenToCopy() { return Collections.EMPTY_LIST; } @SuppressWarnings("unchecked") public static EList<Object> getOwnerList(EObject owner, EStructuralFeature feature) { return owner.eClass().getEAllStructuralFeatures().contains(feature) && feature.isMany() ? (EList<Object>)owner.eGet(feature) : null; } /** * If the owner and the feature aren't null, * the feature is the key of a map entry class, * and the owner is contained in a EMap, * then the map is updated to properly reflect the change to the key's hash code. * @param owner the owner of the feature. * @param feature the feature that's been updated. */ protected void updateEMap(EObject owner, EStructuralFeature feature) { if (owner != null && feature != null && "key".equals(feature.getName()) && feature.getEContainingClass().getInstanceClass() == Map.Entry.class) { EObject container = owner.eContainer(); if (container != null) { EStructuralFeature containmentFeature = owner.eContainmentFeature(); @SuppressWarnings("unchecked") List<Object> list = (List<Object>)container.eGet(containmentFeature); list.set(list.indexOf(owner), owner); } } } /** * This gives 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. */ @Override public String toString() { StringBuffer result = new StringBuffer(super.toString()); result.append(" (domain: " + domain + ")"); result.append(" (overrideCommand: " + overrideCommand + ")"); return result.toString(); } }