/*******************************************************************************
* Copyright (c) 2010-2015 Henshin developers. 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:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
package de.tub.tfs.muvitor.actions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.ui.actions.Clipboard;
import org.eclipse.gef.ui.actions.SelectionAction;
import org.eclipse.gmf.runtime.emf.clipboard.core.BasePasteOperation;
import org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil;
import org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport;
import org.eclipse.gmf.runtime.emf.clipboard.core.PasteTarget;
import org.eclipse.gmf.runtime.emf.clipboard.core.internal.DefaultClipboardSupport;
import org.eclipse.gmf.runtime.emf.clipboard.core.internal.PasteOperation;
import org.eclipse.gmf.runtime.emf.clipboard.core.internal.SerializationEMFResource;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.IPage;
import de.tub.tfs.muvitor.ui.MultiDimensionalPage;
import de.tub.tfs.muvitor.ui.MuvitorPage;
import de.tub.tfs.muvitor.ui.MuvitorPageBookView;
import de.tub.tfs.muvitor.ui.MuvitorTreeEditor;
/**
* This action pastes the clipboard into the current edit part if allowed
*
* @author Tony Modica
*/
public class GenericPasteAction extends SelectionAction {
public static interface IPasteRule {
public void afterPaste(EObject element, EObject target);
public boolean isValidPaste(EObject element, EObject target);
}
public static class PasteCommand extends Command {
private final String clipString;
private Collection<EObject> pasted;
private Collection<EObject> failedPasted;
private final EObject target;
/**
* @param target
* @param clipString
*/
public PasteCommand(final EObject target, final String clipString) {
super();
setLabel("paste into " + target.eClass().getName());
if (target instanceof ENamedElement) {
setLabel(getLabel() + " '" + ((ENamedElement) target).getName() + "'");
}
this.target = target;
this.clipString = clipString;
}
@SuppressWarnings("unchecked")
@Override
public void execute() {
//pasted = ClipboardUtil.pasteElementsFromString(getClipString(), target, null,
// );
NullProgressMonitor monitor = new NullProgressMonitor();
monitor.beginTask(BasePasteOperation.PASTE,
PasteOperation.TOTAL_WORK);
IClipboardSupport helper = ClipboardUtil.createClipboardSupport((EObject)target);
PasteOperation pasteProcess;
Set result;
try {
pasteProcess = new PasteOperation(
monitor, helper, this.clipString, new PasteTarget(target),
SerializationEMFResource.LOAD_OPTIONS, Collections.EMPTY_MAP);
pasteProcess.paste();
result = pasteProcess.getPastedElementSet();
helper.performPostPasteProcessing(result);
pasted = result;
failedPasted = pasteProcess.getPasteFailuresObjectSet();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// get edit part map of current viewer we are pasting into
final IWorkbenchPart activePart = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().getActivePart();
EditPartViewer viewer = null;
if (activePart instanceof MuvitorTreeEditor) {
viewer = ((MuvitorTreeEditor) activePart).getTreeViewer();
} else if (activePart instanceof MuvitorPageBookView) {
final IPage page = ((MuvitorPageBookView) activePart).getCurrentPage();
if (page instanceof MuvitorPage)
viewer = ((MuvitorPage) page).getCurrentViewer();
else
viewer = ((MultiDimensionalPage<?>) page).getCurrentViewer();
} else {
return;
}
// -------------------------------------------
final ArrayList<EditPart> newEditParts = new ArrayList<EditPart>();
for (final EObject copy : pasted) {
if (viewer != null && viewer.getEditPartRegistry() != null && viewer.getEditPartRegistry().get(copy) != null)
newEditParts.add((EditPart) viewer.getEditPartRegistry().get(copy));
}
for (final EObject copy : failedPasted) {
final LinkedList<EClass> copySuperTypes = new LinkedList<EClass>( copy.eClass().getEAllSuperTypes());
copySuperTypes.add(EcorePackage.Literals.EOBJECT);
copySuperTypes.add(copy.eClass());
for (final Entry<EClass, IPasteRule> entry : pasteRules.entrySet()) {
if (copySuperTypes.contains(entry.getKey())) {
entry.getValue().afterPaste(copy, target);
}
}
// ----------------------
//newEditParts.add((EditPart) viewer.getEditPartRegistry().get(copy));
}
final StructuredSelection newSelection = new StructuredSelection(newEditParts);
viewer.setSelection(newSelection);
}
@Override
public void undo() {
final ArrayList<EObject> pastedElements = new ArrayList<EObject>(pasted);
Collections.reverse(pastedElements);
for (final EObject pastedElement : pastedElements) {
EcoreUtil.remove(pastedElement);
}
}
public Collection<EObject> getPastedElements() {
return pasted;
}
public String getClipString() {
return clipString;
}
public Collection<EObject> getFailedPastedElements() {
return failedPasted;
}
}
public static class PasteRuleAdapter implements IPasteRule {
@Override
public void afterPaste(final EObject element, final EObject target) {
}
@Override
public boolean isValidPaste(final EObject element, final EObject target) {
return true;
}
}
public final static Map<EClass, IPasteRule> pasteRules = new HashMap<EClass, IPasteRule>();
protected Command command = null;
protected EObject targetModel;
public GenericPasteAction(final IWorkbenchPart part) {
super(part);
setId(ActionFactory.PASTE.getId());
super.setText("Paste");
super.setDescription("Paste from clipboard");
super.setToolTipText("Pastes the copied parts from the clipboard");
// // TEST Ist das notwendig???: default rule for all EObjects: clear the set of eAdapter that has been copied
// registerPasteRule(EcorePackage.Literals.EOBJECT,
// new GenericPasteAction.PasteRuleAdapter() {
// @Override
// public void afterPaste(final EObject newElement, final EObject target) {
// newElement.eAdapters().clear();
// }
// });
// default rule for named elements
registerPasteRule(EcorePackage.Literals.ENAMED_ELEMENT,
new GenericPasteAction.PasteRuleAdapter() {
@Override
public void afterPaste(final EObject newElement, final EObject target) {
final ENamedElement namedElement = (ENamedElement) newElement;
final String name = namedElement.getName();
// remove the annoying "Copy_x_"
if (name.startsWith("Copy_")) {
final String[] split = name.split("_");
namedElement.setName(split[2]);
}
}
});
}
@Override
public boolean calculateEnabled() {
if (!(getSelection() instanceof IStructuredSelection)) {
return false;
}
final IStructuredSelection selection = (IStructuredSelection) getSelection();
if (selection == null || selection.size() != 1) {
return false;
}
final Object selectionElement = selection.getFirstElement();
if (!(selectionElement instanceof EditPart)) {
return false;
}
final Object model = ((EditPart) selectionElement).getModel();
if (!(model instanceof EObject)) {
return false;
}
targetModel = (EObject) model;
// is targetModel of appropriate type?
if (!GenericCopyAction.allowedPasteTargetEClasses.contains(targetModel.eClass())) {
/*
* for convenience: if parent is of appropriate type try pasting
* into parent
*/
final EObject container = targetModel.eContainer();
if (container != null
&& GenericCopyAction.allowedPasteTargetEClasses.contains(container.eClass())) {
targetModel = container;
} else {
return false;
}
}
final Object clipboardContents = Clipboard.getDefault().getContents();
// ensure a collection of EObjects
if (!(clipboardContents instanceof Collection<?>)) {
return false;
}
for (final Object copy : (Collection<?>) clipboardContents) {
if (!(copy instanceof EObject)) {
return false;
}
}
@SuppressWarnings("unchecked")
final Collection<EObject> copies = (Collection<EObject>) clipboardContents;
for (final EObject copy : copies) {
final EList<EClass> copySuperTypes = copy.eClass().getEAllSuperTypes();
for (final Entry<EClass, IPasteRule> entry : pasteRules.entrySet()) {
if (copySuperTypes.contains(entry.getKey())
&& !entry.getValue().isValidPaste(copy, targetModel)) {
return false;
}
}
}
final String clipString = ClipboardUtil.copyElementsToString(copies, null,
new NullProgressMonitor());
command = new PasteCommand(targetModel, clipString);
return true;
}
public void registerPasteRule(final EClass eClass, final IPasteRule validator) {
pasteRules.put(eClass, validator);
}
@Override
public void run() {
execute(command);
}
}