diff options
Diffstat (limited to 'cdo/bundles/org.eclipse.papyrus.cdo.ui/src/org/eclipse/papyrus/cdo/internal/ui/dnd/ResourceDropAdapter.java')
-rwxr-xr-x | cdo/bundles/org.eclipse.papyrus.cdo.ui/src/org/eclipse/papyrus/cdo/internal/ui/dnd/ResourceDropAdapter.java | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/cdo/bundles/org.eclipse.papyrus.cdo.ui/src/org/eclipse/papyrus/cdo/internal/ui/dnd/ResourceDropAdapter.java b/cdo/bundles/org.eclipse.papyrus.cdo.ui/src/org/eclipse/papyrus/cdo/internal/ui/dnd/ResourceDropAdapter.java new file mode 100755 index 00000000..26e9d6b9 --- /dev/null +++ b/cdo/bundles/org.eclipse.papyrus.cdo.ui/src/org/eclipse/papyrus/cdo/internal/ui/dnd/ResourceDropAdapter.java @@ -0,0 +1,394 @@ +/***************************************************************************** + * Copyright (c) 2013, 2017 CEA LIST and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * CEA LIST - Initial API and implementation + * Eike Stepper (CEA) - bug 466520 + *****************************************************************************/ +package org.eclipse.papyrus.cdo.internal.ui.dnd; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.eresource.CDOResourceFolder; +import org.eclipse.emf.cdo.eresource.CDOResourceNode; +import org.eclipse.emf.cdo.explorer.CDOExplorerUtil; +import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOURIUtil; +import org.eclipse.emf.cdo.view.CDOView; +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.ViewerDropAdapter; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.cdo.core.util.CDOFunctions; +import org.eclipse.papyrus.cdo.core.util.CDOPredicates; +import org.eclipse.papyrus.cdo.internal.ui.Activator; +import org.eclipse.papyrus.cdo.internal.ui.handlers.ImportModelsHandler; +import org.eclipse.papyrus.cdo.internal.ui.l10n.Messages; +import org.eclipse.papyrus.cdo.internal.ui.views.DIModel; +import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile; +import org.eclipse.papyrus.infra.onefile.model.PapyrusModelHelper; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.PluginTransfer; +import org.eclipse.ui.part.PluginTransferData; +import org.eclipse.ui.part.ResourceTransfer; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +/** + * This is the ResourceDropAdapter type. Enjoy. + */ +public class ResourceDropAdapter extends ViewerDropAdapter { + + private static final Transfer[] TRANSFERS = { ResourceTransfer.getInstance(), LocalSelectionTransfer.getTransfer(), PluginTransfer.getInstance() }; + + private final Predicate<Object> validDropTarget = Predicates.or(CDOPredicates.adaptsTo(CDOResourceFolder.class), CDOPredicates.adaptsTo(CDOCheckout.class)); + + private final Function<Object, CDOResourceNode> asNode = CDOFunctions.adapt(CDOResourceNode.class); + + protected ResourceDropAdapter(StructuredViewer viewer) { + super(viewer); + } + + public static ResourceDropAdapter install(StructuredViewer viewer) { + ResourceDropAdapter result = new ResourceDropAdapter(viewer); + + viewer.addDropSupport(DND.DROP_MOVE | /* DND.DROP_COPY | */DND.DROP_DEFAULT, TRANSFERS, result); + + return result; + } + + @Override + public boolean performDrop(Object data) { + boolean result = false; + + if (data instanceof IResource[]) { + data = new StructuredSelection((IResource[]) data); + } else if ((data instanceof PluginTransferData) && "org.eclipse.ui.navigator.PluginDropAction".equals(((PluginTransferData) data).getExtensionId())) { //$NON-NLS-1$ + String viewerID = new String(((PluginTransferData) data).getData()); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IViewPart view = page.findView(viewerID); + if (view != null) { + data = view.getSite().getSelectionProvider().getSelection(); + } + } + + CDOResourceNode dropTarget = adaptDropTarget(getCurrentTarget()); + if (dropTarget != null) { + Iterable<?> toMove = Collections.emptyList(); + + // handle resources to move within the repositories view + if (data instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection) data; + toMove = getResourceNodeAdaptables(selection); + } else if (data instanceof PluginTransferData) { + PluginTransferData ptData = (PluginTransferData) data; + if (ResourceDropActionDelegate.DROP_ACTION_ID.equals(ptData.getExtensionId())) { + CDOResourceURITransferData uris = CDOResourceURITransferData.deserialize(ptData.getData()); + toMove = getResourceNodeAdaptables(uris.getURIs()); + } + } + + if (!Iterables.isEmpty(toMove)) { + result = moveResourceNodes(dropTarget, toMove); + } else { + // handle resources to import from the workspace + if (data instanceof IStructuredSelection) { + Iterable<IFile> diFiles = getDIFiles((IStructuredSelection) data); + if (!Iterables.isEmpty(diFiles)) { + result = importModels(dropTarget, diFiles); + } + } + } + } + + return result; + } + + protected boolean moveResourceNodes(final CDOResourceNode dropTarget, final Iterable<?> resourceNodes) { + boolean result = false; + + // validate the move before we attempt to move anything + Iterable<? extends CDOResourceNode> nodes = Iterables.transform(resourceNodes, CDOFunctions.adapt(CDOResourceNode.class)); + for (CDOResourceNode next : nodes) { + result = true; + + if (contains(dropTarget, next)) { + result = false; + break; + } + } + + if (result) { + new Job(Messages.ResourceDropAdapter_1) { + + { + setUser(true); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + return doMove(dropTarget, resourceNodes); + } + }.schedule(); + } + + return result; + } + + protected boolean importModels(CDOResourceNode dropTarget, Iterable<IFile> diFiles) { + boolean result = false; + + IWorkbenchWindow window = null; + for (IWorkbenchWindow next : PlatformUI.getWorkbench().getWorkbenchWindows()) { + if (next.getShell() == getViewer().getControl().getShell()) { + window = next; + break; + } + } + + if (window != null) { + URI uri = dropTarget.getURI(); + CDOCheckout checkout = CDOExplorerUtil.getCheckout(uri); + if (checkout != null) { + List<IPapyrusFile> papyrusFiles = Lists.newArrayList(); + for (IFile next : diFiles) { + IPapyrusFile papyrusFile = PapyrusModelHelper.getPapyrusModelFactory().createIPapyrusFile(next); + if (papyrusFile != null) { + papyrusFiles.add(papyrusFile); + } + } + + if (!papyrusFiles.isEmpty()) { + result = true; + ImportModelsHandler.importModels(window, new StructuredSelection(papyrusFiles), checkout); + } + } + } + + return result; + } + + protected IStatus doMove(CDOResourceNode destination, Iterable<?> nodeAdaptables) { + IStatus result = Status.OK_STATUS; + CDOTransaction transaction = destination.cdoView().getSession().openTransaction(); + + try { + CDOResourceNode newParent = getCorrespondent(destination, transaction); + for (Object next : nodeAdaptables) { + if (next instanceof DIModel) { + for (CDOResourceNode component : getResourceNodes(Arrays.asList(((DIModel) next).getChildren()))) { + moveTo(newParent, getCorrespondent(component, transaction)); + } + } else { + moveTo(newParent, getCorrespondent(asNode.apply(next), transaction)); + } + } + + transaction.commit(); + } catch (CoreException e) { + result = e.getStatus(); + } catch (Exception e) { + result = error(Messages.ResourceDropAdapter_3, e); + } finally { + transaction.close(); + } + + return result; + } + + protected CDOResourceNode getCorrespondent(CDOResourceNode node, CDOView view) throws CoreException { + + CDOResourceNode result; + + try { + if (node == null) { + throw new CoreException(error(Messages.ResourceDropAdapter_2)); + } else if (node instanceof CDOResourceFolder) { + result = view.getResourceFolder(node.getPath()); + } else if (node instanceof CDOResource) { + result = view.getResource(node.getPath()); + } else { + throw new CoreException(error(NLS.bind(Messages.ResourceDropAdapter_4, node.getClass().getName()))); + } + } catch (CoreException e) { + throw e; + } catch (Exception e) { + throw new CoreException(error(e.getLocalizedMessage(), e)); + } + + return result; + } + + protected static IStatus error(String message) { + return error(message, null); + } + + protected static IStatus error(String message, Throwable exception) { + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, message, exception); + } + + protected void moveTo(CDOResourceNode newParent, CDOResourceNode node) throws CoreException { + String newPath = (node == null) ? null : new Path(newParent.getPath()).append(node.getName()).toString(); + + if (node == null) { + throw new CoreException(error(Messages.ResourceDropAdapter_0)); + } else if (newParent.cdoView().hasResource(newPath)) { + throw new CoreException(error(NLS.bind(Messages.ResourceDropAdapter_6, newPath))); + } else { + // just set the path. The node moves itself + node.setPath(newPath); + } + } + + @Override + public boolean validateDrop(Object target, int operation, TransferData transferType) { + boolean result = false; + + LocalSelectionTransfer local = LocalSelectionTransfer.getTransfer(); + if (local.isSupportedType(transferType) && (local.getSelection() instanceof IStructuredSelection) && isValidResourceContainer(target)) { + IStructuredSelection selection = (IStructuredSelection) local.getSelection(); + CDOResourceNode dropTarget = adaptDropTarget(target); + + // handle drag of files from the Project Explorer. If there's any + // DI file, that's good enough, because the import wizard handles + // mapping to repository paths + if ((dropTarget != null) && !Iterables.isEmpty(getDIFiles(selection))) { + result = true; + } + } else if (PluginTransfer.getInstance().isSupportedType(transferType) && isValidResourceContainer(target)) { + // assume that intra-repository drag of resource nodes will be OK + result = true; + } else if (ResourceTransfer.getInstance().isSupportedType(transferType) && isValidResourceContainer(target)) { + // assume that dragging resources will be OK + result = true; + } + + return result; + } + + protected boolean isValidResourceContainer(Object dropTarget) { + return validDropTarget.apply(dropTarget); + } + + protected CDOResourceNode adaptDropTarget(Object dropTarget) { + CDOResourceNode result = CDOFunctions.adapt(CDOResourceNode.class).apply(dropTarget); + + if (result == null) { + // must be a checkout + CDOView view = ((CDOCheckout) dropTarget).getView(); + if (view != null) { + result = view.getRootResource(); + } + } + + return result; + } + + protected boolean contains(CDOResourceNode parent, CDOResourceNode child) { + boolean result = false; + + if (parent instanceof CDOResourceFolder) { + CDOResourceFolder folder = (CDOResourceFolder) parent; + result = folder.getNodes().contains(child); + } else if (parent instanceof CDOResource) { + CDOResource resource = (CDOResource) parent; + if (resource.isRoot()) { + result = resource.getContents().contains(child); + } + } + + return result; + } + + protected Iterable<?> getResourceNodeAdaptables(IStructuredSelection selection) { + return Iterables.filter((List<?>) selection.toList(), CDOPredicates.adaptsTo(CDOResourceNode.class)); + } + + protected Iterable<?> getResourceNodeAdaptables(Iterable<URI> uris) { + List<Object> result = Lists.newArrayList(); + + for (URI next : uris) { + CDOCheckout checkout = CDOExplorerUtil.getCheckout(next); + if (checkout != null) { + CDOView view = checkout.getView(); + if (view != null) { // the repository could be disconnected by now + String path = CDOURIUtil.extractResourcePath(next); + try { + CDOResourceNode node = view.getResourceNode(path); + if (node instanceof CDOResource) { + DIModel diModel = DIModel.getInstance((CDOResource) node, false); + if (diModel != null) { + result.add(diModel); + } + } else if (node instanceof CDOResourceNode) { + result.add(node); + } + } catch (Exception e) { + // normal in the case that the resource or folder no longer exists + } + } + } + } + + return result; + } + + protected Iterable<? extends CDOResourceNode> getResourceNodes(IStructuredSelection selection) { + return getResourceNodes(selection.toList()); + } + + protected Iterable<? extends CDOResourceNode> getResourceNodes(Iterable<?> objects) { + return Iterables.filter(Iterables.transform(objects, asNode), Predicates.notNull()); + } + + protected Iterable<IFile> getDIFiles(IStructuredSelection selection) { + Iterable<IPapyrusFile> papyrusFiles = Iterables.filter(selection.toList(), IPapyrusFile.class); + Iterable<IFile> files = Iterables.filter(Iterables.filter(selection.toList(), IFile.class), new Predicate<IFile>() { + + @Override + public boolean apply(IFile input) { + return PapyrusModelHelper.getPapyrusModelFactory().isDi(input); + } + }); + + return Iterables.concat(files, Iterables.transform(papyrusFiles, new Function<IPapyrusFile, IFile>() { + + @Override + public IFile apply(IPapyrusFile input) { + return input.getMainFile(); + } + })); + } +} |