/**
* 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.ArrayList;
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.AddCommand;
import org.eclipse.emf.mapping.MappedObjectState;
import org.eclipse.emf.mapping.MappingRoot;
import org.eclipse.emf.mapping.domain.MappingDomain;
/**
* This command overrides the AddCommand to additionally map the added object(s) to corresponding inputs.
*/
public class AddOverrideCommand extends AbstractCommand
{
/**
* This keeps track of the mapping domain in which the command operates.
*/
protected MappingDomain mappingDomain;
/**
* This keeps track of the AddCommand we're overriding
*/
protected AddCommand addCommand;
/**
* This keeps track of the create mapping command(s) used to implement this command.
*/
protected Command mapCommand;
/**
* This creates a command instance that adds and then maps the added object(s).
*/
public AddOverrideCommand(MappingDomain domain, AddCommand addCommand)
{
super(addCommand.doGetLabel(), addCommand.doGetDescription());
this.mappingDomain = domain;
this.addCommand = addCommand;
}
@Override
protected boolean prepare()
{
return addCommand.doCanExecute();
}
public void execute()
{
addCommand.doExecute();
MappingRoot mappingRoot = mappingDomain.getMappingRoot();
CompoundCommand subcommands = new CompoundCommand();
for (Object addition : addCommand.getCollection())
{
for (Iterator<?> objects = mappingDomain.treeIterator(addition); 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))
{
mapOutputObject(object, originatingInput, subcommands);
}
}
}
mapCommand = !subcommands.isEmpty() ? subcommands.unwrap() : null;
}
protected void mapOutputObject(Object outputObject, Object originatingInput, CompoundCommand subcommands)
{
subcommands.appendAndExecute(CreateMappingCommand.create(mappingDomain, originatingInput, outputObject));
}
@Override
public void undo()
{
if (mapCommand != null)
{
mapCommand.undo();
}
addCommand.doUndo();
}
public void redo()
{
addCommand.doRedo();
if (mapCommand != null)
{
mapCommand.redo();
}
}
@Override
public void dispose()
{
if (mapCommand != null)
{
mapCommand.dispose();
}
addCommand.doDispose();
}
@Override
public Collection<?> getResult()
{
Collection<Object> result = new ArrayList<Object>();
result.addAll(addCommand.doGetResult());
if (mapCommand != null)
{
result.addAll(mapCommand.getResult());
}
return result;
}
@Override
public Collection<?> getAffectedObjects()
{
Collection<Object> result = new ArrayList<Object>();
result.addAll(addCommand.doGetAffectedObjects());
if (mapCommand != null)
{
result.addAll(mapCommand.getAffectedObjects());
}
return result;
}
/**
* 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();
}
}