/*
 * 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;
    }
  }
}
