blob: 8915d961f8c925669034b0f79ee45aa3ce75100d [file] [log] [blame]
/*
* Copyright (c) 2014 Eike Stepper (Berlin, Germany) 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:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.oomph.internal.ui;
import org.eclipse.oomph.base.util.BaseResourceFactoryImpl;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectInputStream;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectOutputStream;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.BasicInternalEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xml.namespace.XMLNamespacePackage;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.dnd.URLTransfer;
import org.xml.sax.InputSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.AbstractSequentialList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
/**
* @author Ed Merks
*/
public abstract class OomphTransferDelegate
{
private static final List<OomphTransferDelegate> MODIFIABLE_DELEGATES = new ArrayList<OomphTransferDelegate>();
public static final List<? extends OomphTransferDelegate> DELEGATES = Collections.unmodifiableList(MODIFIABLE_DELEGATES);
public static final List<? extends Transfer> TRANSFERS = asTransfers(MODIFIABLE_DELEGATES);
public static Transfer[] transfers()
{
return TRANSFERS.toArray(new Transfer[TRANSFERS.size()]);
}
public static List<? extends Transfer> asTransfers(final List<? extends OomphTransferDelegate> delegates)
{
return new AbstractSequentialList<Transfer>()
{
@Override
public ListIterator<Transfer> listIterator(final int index)
{
return new ListIterator<Transfer>()
{
ListIterator<? extends OomphTransferDelegate> delegate = delegates.listIterator(index);
public boolean hasNext()
{
return delegate.hasNext();
}
public Transfer next()
{
return delegate.next().getTransfer();
}
public boolean hasPrevious()
{
return delegate.hasPrevious();
}
public Transfer previous()
{
return delegate.previous().getTransfer();
}
public int nextIndex()
{
return delegate.nextIndex();
}
public int previousIndex()
{
return delegate.previousIndex();
}
public void remove()
{
throw new UnsupportedOperationException();
}
public void set(Transfer o)
{
throw new UnsupportedOperationException();
}
public void add(Transfer o)
{
throw new UnsupportedOperationException();
}
};
}
@Override
public int size()
{
return delegates.size();
}
};
}
private static void register(OomphTransferDelegate delegate, List<OomphTransferDelegate> delegates)
{
int priority = delegate.priority();
for (ListIterator<OomphTransferDelegate> it = delegates.listIterator(); it.hasNext();)
{
if (it.next().priority() > priority)
{
it.add(delegate);
return;
}
}
delegates.add(delegate);
}
public static void register(OomphTransferDelegate delegate)
{
register(delegate, MODIFIABLE_DELEGATES);
}
public static OomphTransferDelegate getDelegate(Transfer transfer, Collection<? extends OomphTransferDelegate> delegates)
{
for (OomphTransferDelegate delegate : delegates)
{
if (delegate.getTransfer() == transfer)
{
return delegate;
}
}
return null;
}
public static List<? extends OomphTransferDelegate> merge(Collection<? extends OomphTransferDelegate> delegates,
Collection<? extends OomphTransferDelegate> overridingDelegates)
{
return merge(delegates, overridingDelegates.toArray(new OomphTransferDelegate[overridingDelegates.size()]));
}
public static List<? extends OomphTransferDelegate> merge(Collection<? extends OomphTransferDelegate> delegates, OomphTransferDelegate... overridingDelegates)
{
List<OomphTransferDelegate> result = new ArrayList<OomphTransferDelegate>();
LOOP: for (OomphTransferDelegate delegate : delegates)
{
Transfer transfer = delegate.getTransfer();
for (OomphTransferDelegate overridingDelegate : overridingDelegates)
{
if (overridingDelegate.getTransfer() == transfer)
{
register(overridingDelegate, result);
continue LOOP;
}
}
register(delegate, result);
}
for (OomphTransferDelegate overridingDelegate : overridingDelegates)
{
if (!result.contains(overridingDelegate))
{
register(overridingDelegate, result);
}
}
return result;
}
public abstract Transfer getTransfer();
public boolean isSupportedType(TransferData transferData)
{
return getTransfer().isSupportedType(transferData);
}
public TransferData[] getSupportedTypes()
{
return getTransfer().getSupportedTypes();
}
public abstract Collection<?> getData(EditingDomain domain, TransferData transferData);
public abstract Collection<?> getValue(EditingDomain domain, Object data);
public abstract boolean setSelection(EditingDomain domain, ISelection selection);
public abstract Object getData();
public abstract void clear();
protected int priority()
{
return 0;
}
@Override
public String toString()
{
return super.toString() + " " + Arrays.asList(getTransfer().getSupportedTypes());
}
public abstract static class SelectionTransferDelegate extends OomphTransferDelegate
{
protected Collection<?> extractSelectedObjects(Object... objects)
{
List<Object> result = new ArrayList<Object>();
for (Object object : objects)
{
Object filteredObject = filter(object);
if (filteredObject != null)
{
result.add(filteredObject);
}
}
return result;
}
protected Object filter(Object object)
{
if (object instanceof Resource)
{
Resource resource = (Resource)object;
return resource.getURI();
}
else if (EMFPlugin.IS_RESOURCES_BUNDLE_AVAILABLE)
{
URI uri = EclipseHelper.getURI(object);
if (uri != null)
{
return uri;
}
}
return object;
}
}
public abstract static class ResourceSetTransferDelegate extends OomphTransferDelegate
{
protected static final Resource.Factory RESOURCE_FACTORY = new BaseResourceFactoryImpl();
protected ResourceSet createResourceSet(EditingDomain domain)
{
final ResourceSet resourceSet = domain.getResourceSet();
ResourceSet result = new ResourceSetImpl()
{
@Override
protected Resource delegatedGetResource(URI uri, boolean loadOnDemand)
{
Resource result = super.delegatedGetResource(uri, loadOnDemand);
if (result == null)
{
resourceSet.getResource(uri, false);
}
return result;
}
};
result.setURIConverter(resourceSet.getURIConverter());
result.setPackageRegistry(new EPackageRegistryImpl(resourceSet.getPackageRegistry()));
result.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", RESOURCE_FACTORY);
return result;
}
}
public static class LocalTransferDelegate extends SelectionTransferDelegate
{
protected final LocalTransfer localTransfer = LocalTransfer.getInstance();
protected ISelection selection;
@Override
public Transfer getTransfer()
{
return localTransfer;
}
@Override
public Collection<?> getData(EditingDomain domain, TransferData transferData)
{
return getValue(domain, localTransfer.nativeToJava(transferData));
}
@Override
public Collection<?> getValue(EditingDomain domain, Object data)
{
if (data instanceof IStructuredSelection)
{
IStructuredSelection selection = (IStructuredSelection)data;
return extractSelectedObjects(selection.toArray());
}
return Collections.emptyList();
}
@Override
public boolean setSelection(EditingDomain domain, ISelection selection)
{
if (!selection.isEmpty())
{
this.selection = selection;
return true;
}
return false;
}
@Override
public Object getData()
{
return selection;
}
@Override
public void clear()
{
selection = null;
}
}
static
{
register(new LocalTransferDelegate());
}
public static class LocalSelectionTransferDelegate extends SelectionTransferDelegate
{
protected final LocalSelectionTransfer localSelectionTransfer = LocalSelectionTransfer.getTransfer();
@Override
public Transfer getTransfer()
{
return localSelectionTransfer;
}
@Override
public Collection<?> getData(EditingDomain domain, TransferData transferData)
{
return getValue(domain, localSelectionTransfer.nativeToJava(transferData));
}
@Override
public Collection<?> getValue(EditingDomain domain, Object data)
{
if (data instanceof IStructuredSelection)
{
IStructuredSelection selection = (IStructuredSelection)data;
return extractSelectedObjects(selection.toArray());
}
return Collections.emptyList();
}
@Override
public boolean setSelection(EditingDomain domain, ISelection selection)
{
if (!selection.isEmpty())
{
localSelectionTransfer.setSelection(selection);
localSelectionTransfer.setSelectionSetTime(System.currentTimeMillis());
return true;
}
return false;
}
@Override
public Object getData()
{
return localSelectionTransfer.getSelection();
}
@Override
public void clear()
{
localSelectionTransfer.setSelection(null);
}
}
static
{
register(new LocalSelectionTransferDelegate());
}
public static class OomphBinaryTransferDelegate extends ResourceSetTransferDelegate
{
protected final OomphBinaryTransfer oomphBinaryTransfer = OomphBinaryTransfer.getInstance();
protected Set<EObject> eObjects;
protected byte[] data;
@Override
public Transfer getTransfer()
{
return oomphBinaryTransfer;
}
@Override
public Collection<?> getData(EditingDomain domain, TransferData transferData)
{
return getValue(domain, oomphBinaryTransfer.nativeToJava(transferData));
}
@Override
public Collection<?> getValue(EditingDomain domain, Object data)
{
if (data instanceof byte[])
{
byte[] bytes = (byte[])data;
try
{
final ResourceSet transferResourceSet = createResourceSet(domain);
// Create a stream to load the binary representation.
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
EObjectInputStream eObjectInputStream = new BinaryResourceImpl.EObjectInputStream(in, null)
{
{
resourceSet = transferResourceSet;
}
};
// Read all the packages first.
InternalEList<InternalEObject> ePackages = new BasicInternalEList<InternalEObject>(EPackage.class);
eObjectInputStream.loadEObjects(ePackages);
// Process the packages, putting each one in a resource in a resource set.
Registry packageRegistry = transferResourceSet.getPackageRegistry();
for (EPackage ePackage : ePackages.toArray(new EPackage[ePackages.size()]))
{
Resource resource = transferResourceSet.createResource(URI.createURI("*.ecore"));
resource.getContents().add(ePackage);
resource.setURI(ePackage.eResource().getURI());
// Check if there is a registered package available already.
String nsURI = ePackage.getNsURI();
EPackage registeredEPackage = packageRegistry.getEPackage(nsURI);
if (registeredEPackage == null)
{
// If not, register this dynamic package.
packageRegistry.put(nsURI, ePackage);
}
else
{
// If so, convert all the objects to proxies and so dynamic packages will extend the generated packages.
Map<EObject, String> fragments = new LinkedHashMap<EObject, String>();
for (Iterator<EObject> it = resource.getAllContents(); it.hasNext();)
{
EObject eObject = it.next();
fragments.put(eObject, resource.getURIFragment(eObject));
}
URI uri = URI.createURI(nsURI);
for (Map.Entry<EObject, String> entry : fragments.entrySet())
{
((InternalEObject)entry.getKey()).eSetProxyURI(uri.appendFragment(entry.getValue()));
}
}
}
// Read in all the objects, which will use the appropriate registered packages.
InternalEList<InternalEObject> eObjects = new BasicInternalEList<InternalEObject>(EObject.class);
eObjectInputStream.loadEObjects(eObjects);
Resource resource = transferResourceSet.createResource(URI.createURI("*.xmi"));
resource.getContents().addAll(eObjects);
return eObjects;
}
catch (IOException ex)
{
SWTException swtException = new SWTException(DND.ERROR_INVALID_DATA, ex.getMessage());
swtException.initCause(ex);
throw swtException;
}
}
return Collections.emptyList();
}
@Override
public boolean setSelection(EditingDomain domain, ISelection selection)
{
if (!selection.isEmpty() && selection instanceof IStructuredSelection)
{
eObjects = new LinkedHashSet<EObject>();
for (Object object : ((IStructuredSelection)selection).toArray())
{
gather(domain, object);
}
}
return !eObjects.isEmpty();
}
protected void gather(EditingDomain domain, Object object)
{
Object unwrappedObject = AdapterFactoryEditingDomain.unwrap(object);
if (unwrappedObject instanceof EObject)
{
EObject eObject = (EObject)unwrappedObject;
eObjects.add(eObject);
}
}
@Override
public Object getData()
{
if (!eObjects.isEmpty())
{
// Determine the packages of all the instances that will be copied.
EList<EPackage> ePackages = new UniqueEList<EPackage>();
for (Iterator<EObject> it = EcoreUtil.getAllContents(eObjects); it.hasNext();)
{
EObject eObject = it.next();
ePackages.add(eObject.eClass().getEPackage());
}
// Determine the closure of all packages.
for (int i = 0; i < ePackages.size(); ++i)
{
EPackage ePackage = ePackages.get(i);
for (Iterator<EObject> it = ePackage.eAllContents(); it.hasNext();)
{
EObject eObject = it.next();
for (EObject eCrossReference : eObject.eCrossReferences())
{
EObject rootContainer = EcoreUtil.getRootContainer(eCrossReference);
if (rootContainer instanceof EPackage)
{
ePackages.add((EPackage)rootContainer);
}
}
}
}
// Ignore the ubiquitously available packages.
ePackages.remove(EcorePackage.eINSTANCE);
ePackages.remove(XMLTypePackage.eINSTANCE);
ePackages.remove(XMLNamespacePackage.eINSTANCE);
// Create a specialized copier for copying the packages and the EObjects.
class Copier extends EcoreUtil.Copier
{
private static final long serialVersionUID = 1L;
Map<EObject, EObject> packageCopies;
public Copier()
{
super(true, true);
}
@Override
protected EClass getTarget(EClass eClass)
{
// Map to the copied package metadata.
if (packageCopies != null)
{
return (EClass)packageCopies.get(eClass);
}
return eClass;
}
@Override
protected EStructuralFeature getTarget(EStructuralFeature eStructuralFeature)
{
// Map to the copied package metadata.
if (packageCopies != null)
{
return (EStructuralFeature)packageCopies.get(eStructuralFeature);
}
return eStructuralFeature;
}
@Override
protected void copyAttribute(EAttribute eAttribute, EObject eObject, EObject copyEObject)
{
if (eAttribute.getEAttributeType().isSerializable())
{
super.copyAttribute(eAttribute, eObject, copyEObject);
}
}
@Override
protected void copyAttributeValue(EAttribute eAttribute, EObject eObject, Object value, Setting setting)
{
if (value != null)
{
// Do data conversion to a string representation.
EDataType eAttributeType = eAttribute.getEAttributeType();
EDataType eType = (EDataType)setting.getEStructuralFeature().getEType();
Class<?> instanceClass = eType.getInstanceClass();
Class<?> instanceClass2 = eAttributeType.getInstanceClass();
if (instanceClass != instanceClass2 || instanceClass == null)
{
if (eAttribute.isMany())
{
List<Object> values = new ArrayList<Object>();
for (Object element : (Collection<?>)value)
{
values.add(EcoreUtil.createFromString(eType, EcoreUtil.convertToString(eAttributeType, element)));
}
value = values;
}
else
{
value = EcoreUtil.createFromString(eType, EcoreUtil.convertToString(eAttributeType, value));
}
}
}
super.copyAttributeValue(eAttribute, eObject, value, setting);
}
public Collection<EPackage> copyEPackages(Collection<? extends EPackage> ePackages)
{
// Copy all the packages.
Collection<EPackage> result = new BasicInternalEList<EPackage>(EPackage.class, copyAll(ePackages));
copyReferences();
// Remember the state of the map at this time.
packageCopies = new HashMap<EObject, EObject>(this);
return result;
}
public Collection<EObject> copyEObjects(Collection<? extends EObject> eObjects)
{
// Don't use original references for the copied objects.
useOriginalReferences = false;
// Copy all the objects.
Collection<EObject> result = new BasicInternalEList<EObject>(InternalEObject.class, copyAll(eObjects));
// Remove the already-processed references from the map, before processing the references for the copied objects.
keySet().removeAll(packageCopies.keySet());
copyReferences();
return result;
}
}
Copier copier = new Copier();
// Copy all the packages.
Collection<EPackage> ePackageCopies = copier.copyEPackages(ePackages);
// Transform all the data types to be java.lang.String.
for (EPackage ePackage : ePackageCopies)
{
for (EClassifier eClassifier : ePackage.getEClassifiers())
{
String instanceClassName = eClassifier.getInstanceClassName();
if (instanceClassName != null)
{
if (eClassifier instanceof EDataType)
{
eClassifier.setInstanceClass(String.class);
}
else
{
eClassifier.setInstanceClassName(null);
eClassifier.setInstanceClass(null);
}
}
}
}
// Copy the objects to be instances of the dynamic packages.
Collection<EObject> eObjectCopies = copier.copyEObjects(eObjects);
try
{
// Create a stream for producing a binary representation.
ByteArrayOutputStream out = new ByteArrayOutputStream();
EObjectOutputStream eObjectOutputStream = new BinaryResourceImpl.EObjectOutputStream(out, null, BinaryResourceImpl.BinaryIO.Version.VERSION_1_1);
// Save all the packages.
@SuppressWarnings("unchecked")
InternalEList<? extends InternalEObject> internalEPackages = (InternalEList<? extends InternalEObject>)(InternalEList<?>)ePackageCopies;
eObjectOutputStream.saveEObjects(internalEPackages, BinaryResourceImpl.EObjectOutputStream.Check.CONTAINER);
// Save all the objects.
@SuppressWarnings("unchecked")
InternalEList<? extends InternalEObject> internalEObjects = (InternalEList<? extends InternalEObject>)(InternalEList<?>)eObjectCopies;
eObjectOutputStream.saveEObjects(internalEObjects, BinaryResourceImpl.EObjectOutputStream.Check.CONTAINER);
eObjectOutputStream.flush();
// Convert the bytes to a native representation.
return out.toByteArray();
}
catch (IOException ex)
{
SWTException swtException = new SWTException(DND.ERROR_INVALID_DATA, ex.getMessage());
swtException.initCause(ex);
throw swtException;
}
}
return null;
}
@Override
public void clear()
{
eObjects.clear();
}
}
static
{
register(new OomphBinaryTransferDelegate());
}
public static class FileTransferDelegate extends OomphTransferDelegate
{
protected final FileTransfer fileTransfer = FileTransfer.getInstance();
protected Set<String> files;
@Override
public Transfer getTransfer()
{
return fileTransfer;
}
@Override
public Collection<?> getData(EditingDomain domain, TransferData transferData)
{
return getValue(domain, fileTransfer.nativeToJava(transferData));
}
@Override
public Collection<?> getValue(EditingDomain domain, Object data)
{
if (data instanceof String[])
{
List<URI> result = new ArrayList<URI>();
for (String file : (String[])data)
{
result.add(URI.createFileURI(file));
}
return result;
}
return Collections.emptyList();
}
@Override
public boolean setSelection(EditingDomain domain, ISelection selection)
{
files = new LinkedHashSet<String>();
if (!selection.isEmpty() && selection instanceof IStructuredSelection)
{
for (Object object : ((IStructuredSelection)selection).toArray())
{
gather(domain, object);
}
}
return !files.isEmpty();
}
protected void gather(EditingDomain domain, Object object)
{
Object unwrappedObject = AdapterFactoryEditingDomain.unwrap(object);
if (unwrappedObject instanceof EObject)
{
EObject eObject = (EObject)unwrappedObject;
Resource resource = eObject.eResource();
if (resource != null)
{
gather(domain, resource.getURI());
}
}
else if (unwrappedObject instanceof Resource)
{
Resource resource = (Resource)unwrappedObject;
gather(domain, resource.getURI());
}
}
protected void gather(EditingDomain domain, URI uri)
{
URI normalizedURI = domain.getResourceSet().getURIConverter().normalize(uri);
URI resolvedURI = CommonPlugin.resolve(normalizedURI);
if (resolvedURI.isFile())
{
files.add(new File(resolvedURI.toFileString()).getAbsolutePath());
}
}
@Override
public Object getData()
{
return files.isEmpty() ? null : files.toArray(new String[files.size()]);
}
@Override
public void clear()
{
files = null;
}
}
static
{
register(new FileTransferDelegate());
}
public static class URLTransferDelegate extends OomphTransferDelegate
{
protected final URLTransfer urlTransfer = URLTransfer.getInstance();
protected String url;
@Override
public Transfer getTransfer()
{
return urlTransfer;
}
@Override
public Collection<?> getData(EditingDomain domain, TransferData transferData)
{
return getValue(domain, urlTransfer.nativeToJava(transferData));
}
@Override
public Collection<?> getValue(EditingDomain domain, Object data)
{
if (data instanceof String)
{
String value = data.toString().trim();
try
{
return Collections.singleton(URI.createURI(value));
}
catch (RuntimeException ex)
{
// Ignore.
}
}
return Collections.emptyList();
}
@Override
public boolean setSelection(EditingDomain domain, ISelection selection)
{
if (!selection.isEmpty() && selection instanceof IStructuredSelection)
{
for (Object object : ((IStructuredSelection)selection).toArray())
{
gather(domain, object);
if (url != null)
{
return true;
}
}
}
return false;
}
protected void gather(EditingDomain domain, Object object)
{
Object unwrappedObject = AdapterFactoryEditingDomain.unwrap(object);
if (unwrappedObject instanceof EObject)
{
EObject eObject = (EObject)unwrappedObject;
Resource resource = eObject.eResource();
if (resource != null)
{
gather(domain, resource.getURI());
}
}
else if (unwrappedObject instanceof Resource)
{
Resource resource = (Resource)unwrappedObject;
gather(domain, resource.getURI());
}
}
protected void gather(EditingDomain domain, URI uri)
{
URI normalizedURI = domain.getResourceSet().getURIConverter().normalize(uri);
URI resolvedURI = CommonPlugin.resolve(normalizedURI);
url = resolvedURI.toString();
}
@Override
public Object getData()
{
return url;
}
@Override
public void clear()
{
url = null;
}
}
static
{
register(new URLTransferDelegate());
}
public static class TextTransferDelegate extends ResourceSetTransferDelegate
{
protected final TextTransfer textTransfer = TextTransfer.getInstance();
protected Set<EObject> eObjects;
@Override
public Transfer getTransfer()
{
return textTransfer;
}
@Override
public Collection<?> getData(EditingDomain domain, TransferData transferData)
{
return getValue(domain, textTransfer.nativeToJava(transferData));
}
@Override
public Collection<?> getValue(EditingDomain domain, Object data)
{
if (data instanceof String)
{
Collection<? extends EObject> result = fromString(domain, data.toString());
if (result != null)
{
return result;
}
}
return Collections.emptyList();
}
/**
* Looks for a leading XML header tag and the trailing element end tag in a larger string value
* and calls {@link #fromXML(String) fromXML} for that substring.
* @param domain
*/
protected Collection<? extends EObject> fromString(EditingDomain domain, String value)
{
if (value != null)
{
int start = value.indexOf("<?xml");
if (start != -1)
{
int end = value.lastIndexOf('>');
if (end != -1)
{
Collection<? extends EObject> eObjects = fromXML(domain, value.substring(start, end + 1));
if (eObjects != null)
{
return eObjects;
}
}
}
}
return null;
}
protected Collection<? extends EObject> fromXML(EditingDomain domain, String xml)
{
ResourceSet resourceSet = createResourceSet(domain);
XMLResource resource = (XMLResource)resourceSet.createResource(URI.createURI("dummy:/*.xmi"));
try
{
resource.load(new InputSource(new StringReader(xml)), null);
return resource.getContents();
}
catch (IOException ex)
{
// Ignore.
}
return null;
}
@Override
public boolean setSelection(EditingDomain domain, ISelection selection)
{
eObjects = new LinkedHashSet<EObject>();
if (!selection.isEmpty() && selection instanceof IStructuredSelection)
{
for (Object object : ((IStructuredSelection)selection).toArray())
{
gather(domain, object);
}
}
return !eObjects.isEmpty();
}
protected void gather(EditingDomain domain, Object object)
{
Object unwrappedObject = AdapterFactoryEditingDomain.unwrap(object);
if (unwrappedObject instanceof EObject)
{
EObject eObject = (EObject)unwrappedObject;
eObjects.add(eObject);
}
}
@Override
public Object getData()
{
XMLResource resource = (XMLResource)RESOURCE_FACTORY.createResource(URI.createURI("dummy:/*.xmi"));
Copier copier = new EcoreUtil.Copier(true, false);
Collection<EObject> eObjectCopies = copier.copyAll(eObjects);
resource.getContents().addAll(eObjectCopies);
StringWriter writer = new StringWriter();
try
{
resource.save(writer, null);
writer.flush();
return writer.toString();
}
catch (IOException ex)
{
// Ignore.
}
return null;
}
@Override
public void clear()
{
eObjects = null;
}
}
static
{
register(new TextTransferDelegate());
}
private static class EclipseHelper
{
public static URI getURI(Object object)
{
if (object instanceof IResource)
{
IResource resource = (IResource)object;
return URI.createPlatformResourceURI(resource.getFullPath().toString(), true);
}
return null;
}
}
}