blob: 179cee534c976802c9f414a3ca0e4cf1387e8841 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2005, 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 Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.emf.clipboard.core;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardPlugin;
import org.eclipse.gmf.runtime.emf.clipboard.core.internal.ClipboardSupportManager;
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;
/**
* Utility for the creation of
* {@link org.eclipse.gmf.runtime.emf.clipboard.core.IClipboardSupport} instances for
* specific EMF metamodels, and for copy/paste operations to and from a String
* form for use on the system clipboard.
*
* @author Christian W. Damus (cdamus)
*/
public class ClipboardUtil {
/**
* Hint to perform "weak" merges when resolving paste collisions by merging.
* Weak merges will merge the content of multiplicity-many features but
* will not replace existing values in scalar features.
* <p>
* This hint is specified on a per-object basis.
* </p>
*
* @see #MERGE_HINT_STRONG
*/
public final static String MERGE_HINT_WEAK = "*merge=weak"; //$NON-NLS-1$
/**
* Hint to perform "strong" merges when resolving paste collisions by merging.
* Strong merges will merge the content of multiplicity-many features and
* will also replace existing values in scalar features. This is the
* default merge behaviour.
* <p>
* This hint is specified on a per-object basis.
* </p>
*
* @see #MERGE_HINT_WEAK
*/
public final static String MERGE_HINT_STRONG = "*merge=strong"; //$NON-NLS-1$
/**
* Hint to retain the original element's ID when pasting it. Normally used
* only when implementing a "move" operation, rather than a "copy".
* <p>
* This hint is specified on a per-object basis.
* </p>
*/
public final static String RECYCLE_HINT_ID = "*recycle=id"; //$NON-NLS-1$
/**
* Hint to ignore the recycle hint when pasting objects that were copied
* with the recycle hint. This essentially forces IDs to be regenerated
* even when the copier asked for them to be reused. This would be
* appropriate, for example, on the second and subsequent paste of elements
* that had been cut and already pasted once.
* <p>
* This hint applies to all objects: use it as a key in the hint map with
* a boolean value to indicate whether it is enabled.
* </p>
*/
public final static String IGNORE_RECYCLE_HINT_ID = "*ignore_recycle=id"; //$NON-NLS-1$
/**
* Hint to attempt to paste into the parent of target element if target
* element doesn't accept the copied element.
* <p>
* This hint is specified on a per-object basis.
* </p>
*/
public final static String PASTE_TO_TARGET_PARENT = "*paste=parent"; //$NON-NLS-1$
/**
* Hint indicating that the elements to be pasted were harvested, rather
* than just copied.
* <p>
* This hint is specified on a per-object basis.
* </p>
*/
public final static String HARVESTED_ELEMENT = "*paste=harvest"; //$NON-NLS-1$
private static final String PASTE_SELECTION_FROM_STRING = "pasteElementsFromString"; //$NON-NLS-1$
private static final String COPY_SELECTION_TO_STRING = "copyElementsToString"; //$NON-NLS-1$
/**
* Not instantiable by clients.
*/
private ClipboardUtil() {
super();
}
/**
* Serializes elements to a string suitable for putting on the system
* clipboard.
*
* @param eObjects a collection of {@link EObject}s to be serialized
* @param hints a mapping of hints (defined as constants on this class), or
* <code>null</code> to provide no hints
* @param monitor a progress monitor to track progress, or
* <code>null</code> if no progress feedback is required
*
* @return the serial form of the <code>eObjects</code>
*/
public static String copyElementsToString(Collection eObjects, Map hints,
IProgressMonitor monitor) {
try {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(CopyOperation.COPY,
CopyOperation.TOTAL_WORK);
// as long as we do not support heterogeneous copy, we need to
// look at the first object in the client's original collection
// in case they try to force a certain clipboard support by
// ordering a particular element to the front (bug 136975)
EObject first = eObjects.isEmpty()? null : (EObject) eObjects.iterator().next();
eObjects = ClipboardSupportUtil.getCopyElements(eObjects);
if (eObjects.isEmpty() == false) {
if (hints == null) {
hints = new HashMap();
}
CopyOperation copyOperation = new CopyOperation(
monitor,
createClipboardSupport(first),
eObjects, hints);
return copyOperation.copy();
}
} catch (Exception ex) {
handleException(ex, COPY_SELECTION_TO_STRING);
} finally {
monitor.done();
}
return null;
}
/**
* Deerializes elements from a string (obtained from the system clipboard)
* and pastes them into the specified target element.
*
* @param string the string containing the elements to be pasted
* @param targetElement the element into which the new elements are to be
* pasted
* @param hints a mapping of hints (defined as constants on this class), or
* <code>null</code> to provide no hints
* @param monitor a progress monitor to track progress, or
* <code>null</code> if no progress feedback is required
*
* @return the newly pasted {@link EObject}s
*/
public static Collection pasteElementsFromString(String string,
EObject targetElement, final Map hints, IProgressMonitor monitor) {
return pasteElementsFromStringDelagate(string, new PasteTarget(targetElement), hints, monitor);
}
/**
* Deerializes elements from a string (obtained from the system clipboard)
* and pastes them into the specified target element.
*
* @param string the string containing the elements to be pasted
* @param targetElement the element into which the new elements are to be
* pasted
* @param hints a mapping of hints (defined as constants on this class), or
* <code>null</code> to provide no hints
* @param monitor a progress monitor to track progress, or
* <code>null</code> if no progress feedback is required
*
* @return the newly pasted {@link EObject}s
*/
public static Collection pasteElementsFromString(String string,
Resource targetElement, final Map hints, IProgressMonitor monitor) {
return pasteElementsFromStringDelagate(string, new PasteTarget(targetElement), hints, monitor);
}
/**
* Deerializes elements from a string (obtained from the system clipboard)
* and pastes them into the specified target element.
*
* @param string the string containing the elements to be pasted
* @param targetElement the element into which the new elements are to be
* pasted
* @param hints a mapping of hints (defined as constants on this class), or
* <code>null</code> to provide no hints
* @param monitor a progress monitor to track progress, or
* <code>null</code> if no progress feedback is required
*
* @return the newly pasted {@link EObject}s
*/
private static Collection pasteElementsFromStringDelagate(String string,
PasteTarget targetElement, final Map hints, IProgressMonitor monitor) {
Set result = null;
try {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(BasePasteOperation.PASTE,
PasteOperation.TOTAL_WORK);
IClipboardSupport helper = targetElement.isResource()
? DefaultClipboardSupport.getInstance()
: createClipboardSupport(((EObject)targetElement.getObject()));
if (string.length() == 0) {
return Collections.EMPTY_SET;
}
PasteOperation pasteProcess = new PasteOperation(
monitor, helper, string, targetElement,
SerializationEMFResource.LOAD_OPTIONS, hints);
pasteProcess.paste();
result = pasteProcess.getPastedElementSet();
helper.performPostPasteProcessing(result);
} catch (Exception ex) {
handleException(ex, PASTE_SELECTION_FROM_STRING);
} finally {
monitor.done();
}
return result;
}
/**
* handles the exception, does tracing ...etc.
*
* @param ex
* the exception to hanlde
* @param methodname
* the calling method
*/
private static void handleException(Exception ex, String methodname) {
if (ex instanceof OperationCanceledException) {
ClipboardPlugin.catching(ClipboardUtil.class,
methodname, ex);
} else {
ClipboardPlugin.throwing(ClipboardUtil.class,
methodname, ex);
throw (ex instanceof RuntimeException) ? (RuntimeException) ex
: new RuntimeException("Copy-Paste General Error", ex);//$NON-NLS-1$
}
}
/**
* Obtains the clipboard copy/paste support utility, if any, for the
* specified <code>eClass</code>'s metamodel. If the metamodel does not
* have a dedicated clipboard support implementation, then a default
* implementation is provided that implements semantics similar to the
* {@link org.eclipse.emf.ecore.util.EcoreUtil.Copier} class.
* <p>
* <b>WARNING: DO NOT USE.</b> Calling this method does not support the full
* extensibility capabilities of the ClipboardSupport extension point. Use
* the method {@link #createClipboardSupport(EObject)} instead.
*
* @param eClass a metaclass
* @return the <code>eClass</code>'s metamodel's clipboard support
* utility, or a null implementation if none is registered for it
* (not actually <code>null</code>)
*/
public static IClipboardSupport createClipboardSupport(EClass eClass) {
IClipboardSupport result = DefaultClipboardSupport.getInstance();
EPackage ePackage = eClass.getEPackage();
IClipboardSupportFactory factory = ClipboardSupportManager.lookup(ePackage);
if (factory != null) {
result = factory.newClipboardSupport(ePackage);
}
return result;
}
/**
* Obtains the clipboard copy/paste support utility, if any, for the
* specified <code>eObject</code>. If there is not clipboard support
* implementation provided for this EObject, then a default implementation
* is provided that implements semantics similar to the
* {@link org.eclipse.emf.ecore.util.EcoreUtil.Copier} class.
*
* @param eObject
* an EObject
* @return the <code>eObject</code>'s clipboard support utility, or a null
* implementation if none is registered for it (not actually
* <code>null</code>)
* @since 1.3
*/
public static IClipboardSupport createClipboardSupport(EObject eObject) {
IClipboardSupport result = DefaultClipboardSupport.getInstance();
IClipboardSupportFactory factory = ClipboardSupportManager.lookup(eObject);
if (factory != null) {
result = factory.newClipboardSupport(eObject.eClass().getEPackage());
}
return result;
}
}