/** * 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 */ package org.eclipse.emf.mapping.command; import java.util.Collection; import java.util.Iterator; import org.eclipse.emf.common.command.AbstractCommand; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.edit.command.RemoveCommand; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.mapping.MappedObjectState; import org.eclipse.emf.mapping.Mapping; import org.eclipse.emf.mapping.MappingPackage; import org.eclipse.emf.mapping.MappingRoot; import org.eclipse.emf.mapping.domain.MappingDomain; /** * This command overrides the SetCommand to additionally unmap the removed object and map the new object. */ public class SetOverrideCommand extends AbstractCommand { /** * This keeps track of the mapping domain in which the command operates. */ protected MappingDomain mappingDomain; /** * This keeps track of the SetCommand we're overriding */ protected SetCommand setCommand; /** * This keeps track of the set mapping command(s) used to implement this command. */ protected Command mapCommand; /** * This creates a command instance that removes, unmaps the removed object and then adds and maps the new object. */ public SetOverrideCommand(MappingDomain domain, SetCommand setCommand) { super(setCommand.doGetLabel(), setCommand.doGetDescription()); this.mappingDomain = domain; this.setCommand = setCommand; } @Override protected boolean prepare() { return setCommand.doCanExecute(); } public void execute() { setCommand.doExecute(); MappingRoot mappingRoot = mappingDomain.getMappingRoot(); CompoundCommand subcommands = new CompoundCommand(); if (setCommand.getOldValue() != null) { Object oldValue = setCommand.getOldValue(); for (Iterator<?> objects = mappingDomain.treeIterator(oldValue); objects.hasNext(); ) { Object object = objects.next(); for (Mapping mapping : mappingRoot.getMappings(object)) { Collection<?> outputs = mapping.getOutputs(); if (outputs.size() == 1 && outputs.iterator().next() == object) { subcommands.append(RemoveMappingCommand.create(mappingDomain, mapping)); } else { subcommands.append( //(RemoveCommand.create(mappingDomain, mapping, mapping.ePackageMapping().getMapping_Outputs(), object))); (RemoveCommand.create(mappingDomain, mapping, MappingPackage.eINSTANCE.getMapping_Outputs(), object))); } } } } if (setCommand.getValue() != null) { Object value = setCommand.getValue(); for (Iterator<?> objects = mappingDomain.treeIterator(value); objects.hasNext(); ) { Object object = objects.next(); MappedObjectState mappedObjectState = mappingRoot.getMappedObjectState(object); Object originatingInput = mappedObjectState.getOriginatingInput(); // This is tricky and is done for each object here rather than once for the owner of the addCommnd. // We want to make sure the object is really part of the conceptual tree induced by the domain. // if (originatingInput == null) { mappedObjectState.setOutput(); } else if (mappingRoot.isAttachedObject(object)) { subcommands.append(CreateMappingCommand.create(mappingDomain, originatingInput, object)); } } } mapCommand = subcommands.unwrap(); if (mapCommand.canExecute()) { mapCommand.execute(); } else { mapCommand.dispose(); mapCommand = null; } } @Override public void undo() { if (mapCommand != null) { mapCommand.undo(); } setCommand.doUndo(); } public void redo() { setCommand.doRedo(); if (mapCommand != null) { mapCommand.redo(); } } @Override public void dispose() { if (mapCommand != null) { mapCommand.dispose(); } setCommand.doDispose(); } @Override public Collection<?> getResult() { return setCommand.doGetResult(); } @Override public Collection<?> getAffectedObjects() { return setCommand.doGetAffectedObjects(); } /** * 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(" (mappingDomain: " + mappingDomain + ")"); result.append(" (mapCommand: " + mapCommand + ")"); return result.toString(); } }