From deaec2a96cd6f01c51c876a6160fc782cd1293b5 Mon Sep 17 00:00:00 2001 From: Benoit Maggi Date: Wed, 30 Apr 2014 15:47:18 +0200 Subject: Bug 413802 – Cannot copy & paste model using Project Explorer Add copy/paste action for papyrus model in projectExplorer (Handler/Command don't seem to be able to override paste action) Change-Id: I5d2f5630d75c65e08fe8fb67cb3e383150591feb Signed-off-by: Benoit Maggi --- .../emf/resource/DependencyManagementHelper.java | 95 +- .../emf/resource/IURIReplacementStrategy.java | 28 + .../resource/MoveFileURIReplacementStrategy.java | 144 ++ .../infra/emf/resource/ReplacementImpl.java | 72 + .../emf/resource/RestoreDependencyHelper.java | 132 ++ .../papyrus/infra/emf/utils/ResourceUtils.java | 188 +- .../META-INF/MANIFEST.MF | 51 +- .../org.eclipse.papyrus.infra.onefile/plugin.xml | 596 +++--- .../action/CopyFilesAndFoldersOperation.java | 1959 ++++++++++++++++++++ .../PapyrusCopyFilesAndFoldersOperation.java | 190 ++ .../onefile/action/PapyrusModelPasteAction.java | 50 + .../papyrus/infra/onefile/action/PasteAction.java | 266 +++ .../onefile/providers/CopyToClipboardAction.java | 70 + .../providers/PapyrusEditActionProvider.java | 147 ++ .../providers/PapyrusModelActionProvider.java | 964 +++++----- .../onefile/testers/PapyrusClipboardTester.java | 77 + 16 files changed, 4083 insertions(+), 946 deletions(-) create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/IURIReplacementStrategy.java create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/MoveFileURIReplacementStrategy.java create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/ReplacementImpl.java create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/RestoreDependencyHelper.java create mode 100644 plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/CopyFilesAndFoldersOperation.java create mode 100644 plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusCopyFilesAndFoldersOperation.java create mode 100644 plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusModelPasteAction.java create mode 100644 plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PasteAction.java create mode 100644 plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/CopyToClipboardAction.java create mode 100644 plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusEditActionProvider.java create mode 100644 plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/testers/PapyrusClipboardTester.java diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/DependencyManagementHelper.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/DependencyManagementHelper.java index e97eb3d2477..65d9a2fe23f 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/DependencyManagementHelper.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/DependencyManagementHelper.java @@ -1,6 +1,6 @@ /***************************************************************************** * Copyright (c) 2013 CEA LIST. - * + * * 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 @@ -35,21 +35,21 @@ import org.eclipse.papyrus.infra.emf.utils.EMFHelper; /** * A Helper to edit dependencies (URIs) between EMF Resources - * + * * It replaces all references from a Resource A to a Resource B with references from A to B' - * + * * B and B' must be "equivalent" (e.g. B is a copy of B' with or without modifications). - * + * * @author Camille Letavernier - * + * */ public class DependencyManagementHelper { /** * Replaces all references (dependencies) in the "fromResources" to the "uriToReplace" URI, with the "targetURI" - * + * * Simplified pseudo code algorithm: fromResources.replaceAll(uriToReplace, targetURI) - * + * * @param uriToReplace * The URI of the resource which initially contains the referenced elements. May or may not exist. * Must not be null @@ -62,7 +62,7 @@ public class DependencyManagementHelper { * Must not be empty * @param editingDomain * The editing domain. May be null. - * + * * @return * The collection of replacements */ @@ -90,9 +90,9 @@ public class DependencyManagementHelper { /** * Replaces all references (dependencies) in the "fromResources" to the "uriToReplace" URI, with the "targetURI" - * + * * Simplified pseudo code algorithm: fromResources.replaceAll(uriToReplace, targetURI) - * + * * @param uriToReplace * The URI of the resource which initially contains the referenced elements. May or may not exist. * Must not be null @@ -197,7 +197,7 @@ public class DependencyManagementHelper { /** * Replaces the EObject (Which may be a proxy) by its equivalent in the given Resource's URI. * Returns null if the "currentValueToReplace" doesn't belong to the resource represented by "uriToReplace". - * + * * @param currentValueToReplace * The current value, to be replaced. May be a proxy * @param uriToReplace @@ -221,7 +221,7 @@ public class DependencyManagementHelper { /** * Replaces the EObject (Which may be a proxy) by its equivalent in the given Resource's URI. - * + * * @param currentValueToReplace * The current value, to be replaced. May be a proxy * @param targetURI @@ -255,9 +255,9 @@ public class DependencyManagementHelper { /** * Replaces all references (dependencies) in the "resourceSet" to the "uriToReplace" URI, with the "targetURI" - * + * * Simplified pseudo code algorithm: resourceSet.getResources().replaceAll(uriToReplace, targetURI) - * + * * @param uriToReplace * The URI of the resource which initially contains the referenced elements. May or may not exist. * Must not be null @@ -283,9 +283,9 @@ public class DependencyManagementHelper { /** * Replaces all references (dependencies) in the "fromResources" to the "uriToReplace" URI, with the "targetURI" - * + * * Simplified pseudo code algorithm: fromResources.replaceAll(uriToReplace, targetURI) - * + * * @param uriToReplace * The URI of the resource which initially contains the referenced elements. May or may not exist. * Must not be null @@ -305,9 +305,9 @@ public class DependencyManagementHelper { /** * Replaces all references (dependencies) in the "fromResource" to the "uriToReplace" URI, with the "targetURI" - * + * * Simplified pseudo code algorithm: fromResource.replaceAll(uriToReplace, targetURI) - * + * * @param uriToReplace * The URI of the resource which initially contains the referenced elements. May or may not exist. * Must not be null @@ -327,9 +327,9 @@ public class DependencyManagementHelper { /** * Replaces all references (dependencies) in the "resourceSet" to the "uriToReplace" URI, with the "targetURI" - * + * * Simplified pseudo code algorithm: resourceSet.getResources().replaceAll(uriToReplace, targetURI) - * + * * @param uriToReplace * The URI of the resource which initially contains the referenced elements. May or may not exist. * Must not be null @@ -347,59 +347,4 @@ public class DependencyManagementHelper { return updateDependencies(uriToReplace, targetURI, resourcesToEdit, null); } - private static class ReplacementImpl implements Replacement { - - private EObject parent; - - private EStructuralFeature property; - - private EObject oldValue; - - private EObject newValue; - - public ReplacementImpl(EObject parent, EStructuralFeature property, EObject oldValue, EObject newValue) { - this.parent = parent; - this.property = property; - this.oldValue = oldValue; - this.newValue = newValue; - } - - public EObject getEObject() { - return parent; - } - - public EStructuralFeature getEStructuralFeature() { - return property; - } - - public EObject get(boolean resolve) { - if(resolve && newValue != null && newValue.eIsProxy()) { - newValue = EcoreUtil.resolve(newValue, parent); - } - - return newValue; - } - - public void set(Object newValue) { - throw new UnsupportedOperationException(); - } - - public boolean isSet() { - return newValue != null; - } - - public void unset() { - throw new UnsupportedOperationException(); - } - - public EObject getOldValue() { - return oldValue; - } - - @Override - public String toString() { - return String.format("%s replaced with %s", EcoreUtil.getURI(oldValue), EcoreUtil.getURI(newValue)); - } - } - } diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/IURIReplacementStrategy.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/IURIReplacementStrategy.java new file mode 100644 index 00000000000..65e3d46d423 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/IURIReplacementStrategy.java @@ -0,0 +1,28 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.emf.resource; + +import org.eclipse.emf.common.util.URI; + + +/** + * Interface for different strategies to change URI of a Resource + * + */ +public interface IURIReplacementStrategy { + + URI getReplacementCandidate(URI resourceURI); + +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/MoveFileURIReplacementStrategy.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/MoveFileURIReplacementStrategy.java new file mode 100644 index 00000000000..81f59eb4a81 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/MoveFileURIReplacementStrategy.java @@ -0,0 +1,144 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + + +package org.eclipse.papyrus.infra.emf.resource; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.URIConverter; +import org.eclipse.papyrus.infra.core.resource.ModelSet; + + +/** + * The Class MoveFileURIReplacementStrategy. + */ +public class MoveFileURIReplacementStrategy implements IURIReplacementStrategy { + + + /** The replacement uri mapping. */ + protected Map replacementURIMapping; + + /** The source path. */ + protected IPath sourcePath; + + /** The target path. */ + protected IPath targetPath; + + /** + * Instantiates a new move file uri replacement strategy. + * + * @param replacementURIMapping + * the replacement uri mapping + * @param sourcePath + * the source path + * @param targetPath + * the target path + */ + public MoveFileURIReplacementStrategy(Map replacementURIMapping, IPath sourcePath, IPath targetPath) { + this.replacementURIMapping = replacementURIMapping; + this.sourcePath = sourcePath; + this.targetPath = targetPath; + } + + /** + * Instantiates a new move file uri replacement strategy. + * + * @param sourcePath + * the source path + * @param targetPath + * the target path + */ + public MoveFileURIReplacementStrategy(IPath sourcePath, IPath targetPath) { + this(new HashMap(), sourcePath, targetPath); + } + + + + /* + * (non-Javadoc) + * + * @see org.eclipse.papyrus.infra.emf.resource.IURIReplacementStrategy#getReplacementCandidate(org.eclipse.emf.common.util.URI) + */ + public URI getReplacementCandidate(URI resourceURI) { + if(replacementURIMapping.containsKey(resourceURI)) { + return replacementURIMapping.get(resourceURI); + } + URI calculateUri = calculateNewUri(resourceURI); + replacementURIMapping.put(resourceURI, calculateUri); + return calculateUri; + } + + + /** + * Calculate uri. + * + * @param resourceURI + * the resource uri + * @return the uri + */ + protected URI calculateNewUri(URI resourceURI) { + ModelSet modelSet = new ModelSet(); + URIConverter uriConverter = modelSet.getURIConverter(); + boolean exists = uriConverter.exists(resourceURI, Collections.EMPTY_MAP); + if(!exists) { + URI choseCorrectPath = trySourcePath(sourcePath, targetPath, resourceURI); + if(choseCorrectPath != null) { + return choseCorrectPath; + } + } + return resourceURI; + } + + + + + /** + * If the resource is not found in the target location then look in the source location + * + * @param sourcePath + * the source path + * @param targetPath + * the target path + * @param resourceURI + * the resource uri + * @return the uri + */ + protected URI trySourcePath(IPath sourcePath, IPath targetPath, URI resourceURI) { + String uriPlatformString = resourceURI.toPlatformString(true); + if(uriPlatformString != null) { + Path path = new Path(uriPlatformString); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IFile file = root.getFile(path); + if(!file.exists()) {// test file non existence from the target + // calculate a new path from source path + URI sourceURI = URI.createPlatformResourceURI(sourcePath.toString()+Path.SEPARATOR, true); + URI targetURI = URI.createPlatformResourceURI(targetPath.toString()+Path.SEPARATOR, true); + URI resourceDeresolved = resourceURI.deresolve(targetURI); + URI resourceResolved = resourceDeresolved.resolve(sourceURI); + return resourceResolved; + } + } + return null; + } + +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/ReplacementImpl.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/ReplacementImpl.java new file mode 100644 index 00000000000..6eafbfba7cc --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/ReplacementImpl.java @@ -0,0 +1,72 @@ +/***************************************************************************** + * Copyright (c) 2013 CEA LIST. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.infra.emf.resource; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.util.EcoreUtil; + + +public class ReplacementImpl implements Replacement { + + private EObject parent; + + private EStructuralFeature property; + + private EObject oldValue; + + private EObject newValue; + + public ReplacementImpl(EObject parent, EStructuralFeature property, EObject oldValue, EObject newValue) { + this.parent = parent; + this.property = property; + this.oldValue = oldValue; + this.newValue = newValue; + } + + public EObject getEObject() { + return parent; + } + + public EStructuralFeature getEStructuralFeature() { + return property; + } + + public EObject get(boolean resolve) { + if(resolve && newValue != null && newValue.eIsProxy()) { + newValue = EcoreUtil.resolve(newValue, parent); + } + + return newValue; + } + + public void set(Object newValue) { + throw new UnsupportedOperationException(); + } + + public boolean isSet() { + return newValue != null; + } + + public void unset() { + throw new UnsupportedOperationException(); + } + + public EObject getOldValue() { + return oldValue; + } + + @Override + public String toString() { + return String.format("%s replaced with %s", EcoreUtil.getURI(oldValue), EcoreUtil.getURI(newValue)); //$NON-NLS-1$ + } +} \ No newline at end of file diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/RestoreDependencyHelper.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/RestoreDependencyHelper.java new file mode 100644 index 00000000000..f018ddb9c5e --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/resource/RestoreDependencyHelper.java @@ -0,0 +1,132 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.emf.resource; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.infra.emf.Activator; + +/** + * The Class RestoreDependencyHelper is used to restore broken URI according to a replacement Strategy. + */ +public class RestoreDependencyHelper { + + + /** The uri replacement strategy. */ + protected IURIReplacementStrategy iURIReplacementStrategy; + + /** + * Instantiates a new restore dependency helper. + * + * @param iURIReplacementStrategy the chosen uriReplacementStrategy + */ + public RestoreDependencyHelper(IURIReplacementStrategy iURIReplacementStrategy) { + this.iURIReplacementStrategy = iURIReplacementStrategy; + } + + /** + * Restore dependencies, iterate on all contents to check and replace URIs. + * + * @param resource the resource + * @return the collection + */ + public Collection restoreDependencies(Resource resource) { + Iterator allContentsIterator = resource.getAllContents(); + Collection replacements = new LinkedList(); + while(allContentsIterator.hasNext()) { + EObject eObject = allContentsIterator.next(); + + for(EReference reference : eObject.eClass().getEAllReferences()) { + if(reference.isContainment()) { + continue; + } + + if(!reference.isChangeable()) { + continue; + } + + Object value = eObject.eGet(reference); + if(value instanceof EObject) { + EObject eObjectToReplace = (EObject)value; + EObject newEObject = checkAndReplace(eObjectToReplace); + if(newEObject == null) { + continue; + } + + try { + eObject.eSet(reference, newEObject); + replacements.add(new ReplacementImpl(eObject, reference, eObjectToReplace, newEObject)); + } catch (Exception ex) { + Activator.log.error(ex); + } + + } else if(value instanceof Collection) { + Map previousToNewValue = new HashMap(); + Collection collection = (Collection)value; + for(Object collectionElement : (Collection)value) { + if(collectionElement instanceof EObject) { + EObject eObjectToReplace = (EObject)collectionElement; + EObject newEObject = checkAndReplace(eObjectToReplace); + if(newEObject == null) { + continue; + } + previousToNewValue.put(eObjectToReplace, newEObject); + } + } + if(previousToNewValue.isEmpty()) { + continue; + } + if(collection instanceof EStructuralFeature.Setting) { + EStructuralFeature.Setting setting = (EStructuralFeature.Setting)collection; + for(Map.Entry entry : previousToNewValue.entrySet()) { + EcoreUtil.replace(setting, entry.getKey(), entry.getValue()); + replacements.add(new ReplacementImpl(eObject, reference, entry.getKey(), entry.getValue())); + } + } + } + } + } + return replacements; + } + + /** + * Check and replace. + * + * @param eObject the e object to replace + * @return the e object + */ + protected EObject checkAndReplace(EObject eObject) { + URI eObjectURIToReplace = EcoreUtil.getURI(eObject); + URI resourceURI = eObjectURIToReplace.trimFragment(); + if(!resourceURI.isEmpty()) { + URI targetURI = iURIReplacementStrategy.getReplacementCandidate(resourceURI); + if(targetURI != null && !targetURI.equals(resourceURI)) { + return DependencyManagementHelper.replace(eObject, targetURI); + } + } + return null; + } + +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/ResourceUtils.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/ResourceUtils.java index 225e5b57eae..26e1818e66b 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/ResourceUtils.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/ResourceUtils.java @@ -1,81 +1,107 @@ -/***************************************************************************** - * Copyright (c) 2012 CEA LIST. - * - * - * 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: - * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation - * - *****************************************************************************/ -package org.eclipse.papyrus.infra.emf.utils; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.Path; -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.xmi.XMIResource; - -/** - * - * This class provides methods for EMF Resource - * - */ -public class ResourceUtils { - - private ResourceUtils() { - //to prevent instanciation - } - - /** - * - * @param resource - * an EMF resource - * @return - * the IFile corresponding to this resource, or null if not found - */ - public static IFile getFile(final Resource resource) { - if(resource != null) { - URI uri = resource.getURI(); - uri = resource.getResourceSet().getURIConverter().normalize(uri); - if(uri.isPlatformResource()) { - String uriPlatformString = uri.toPlatformString(true) ; - return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uriPlatformString)); - } - } - return null; - } - - /** - * - * - * @param resource - * a resource - * @return - * a collection with all existing id in the resource - * - */ - public static Collection getAllResourceIds(final XMIResource resource) { - final Set ids = new HashSet(); - final Iterator iterator = resource.getAllContents(); - while(iterator.hasNext()) { - final EObject current = iterator.next(); - final String id = resource.getID(current); - Assert.isNotNull(id); - Assert.isTrue(!ids.contains(id)); - ids.add(id); - } - return ids; - } -} +/***************************************************************************** + * Copyright (c) 2012 CEA LIST. + * + * + * 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: + * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.emf.utils; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.Path; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.xmi.XMIResource; + +/** + * + * This class provides methods for EMF Resource + * + */ +public class ResourceUtils { + + private ResourceUtils() { + //to prevent instanciation + } + + /** + * + * @param resource + * an EMF resource + * @return + * the IFile corresponding to this resource, or null if not found + */ + public static IFile getFile(final Resource resource) { + if(resource != null) { + URI uri = resource.getURI(); + uri = resource.getResourceSet().getURIConverter().normalize(uri); + if(uri.isPlatformResource()) { + String uriPlatformString = uri.toPlatformString(true) ; + return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uriPlatformString)); + } + } + return null; + } + + /** + * + * + * @param resource + * a resource + * @return + * a collection with all existing id in the resource + * + */ + public static Collection getAllResourceIds(final XMIResource resource) { + final Set ids = new HashSet(); + final Iterator iterator = resource.getAllContents(); + while(iterator.hasNext()) { + final EObject current = iterator.next(); + final String id = resource.getID(current); + Assert.isNotNull(id); + Assert.isTrue(!ids.contains(id)); + ids.add(id); + } + return ids; + } + + + /** + * Default options to save emf files used in Papyrus + * @return + */ + public static Map getSaveOptions() { + Map saveOptions = new HashMap(); + + // default save options. + saveOptions.put(XMIResource.OPTION_DECLARE_XML, Boolean.TRUE); + saveOptions.put(XMIResource.OPTION_PROCESS_DANGLING_HREF, XMIResource.OPTION_PROCESS_DANGLING_HREF_DISCARD); + saveOptions.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); + saveOptions.put(XMIResource.OPTION_USE_XMI_TYPE, Boolean.TRUE); + saveOptions.put(XMIResource.OPTION_SAVE_TYPE_INFORMATION, Boolean.TRUE); + saveOptions.put(XMIResource.OPTION_SKIP_ESCAPE_URI, Boolean.FALSE); + saveOptions.put(XMIResource.OPTION_ENCODING, "UTF-8"); + + //see bug 397987: [Core][Save] The referenced plugin models are saved using relative path + saveOptions.put(XMIResource.OPTION_URI_HANDLER, new org.eclipse.emf.ecore.xmi.impl.URIHandlerImpl.PlatformSchemeAware()); + + return saveOptions; + } + +} diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/META-INF/MANIFEST.MF b/plugins/infra/org.eclipse.papyrus.infra.onefile/META-INF/MANIFEST.MF index 752e7a54773..e8af4ff0b31 100644 --- a/plugins/infra/org.eclipse.papyrus.infra.onefile/META-INF/MANIFEST.MF +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/META-INF/MANIFEST.MF @@ -1,24 +1,27 @@ -Manifest-Version: 1.0 -Export-Package: org.eclipse.papyrus.infra.onefile.model, - org.eclipse.papyrus.infra.onefile.utils -Require-Bundle: org.eclipse.papyrus.infra.core;bundle-version="1.0.0", - org.eclipse.ui.navigator, - org.eclipse.team.ui, - org.eclipse.ui.navigator.resources, - org.eclipse.core.resources;bundle-version="3.7.0", - org.eclipse.core.runtime;bundle-version="3.7.0", - org.eclipse.ui, - org.eclipse.ui.ide;bundle-version="3.8.0", - org.eclipse.papyrus.infra.core.log;bundle-version="1.0.0", - org.eclipse.ltk.core.refactoring;bundle-version="3.6.0", - org.eclipse.ltk.ui.refactoring;bundle-version="3.7.0" -Bundle-Vendor: %providerName -Bundle-ActivationPolicy: lazy -Bundle-Version: 1.0.0.qualifier -Bundle-Localization: plugin -Bundle-Name: %pluginName -Bundle-Activator: org.eclipse.papyrus.infra.onefile.Activator -Bundle-ManifestVersion: 2 -Bundle-SymbolicName: org.eclipse.papyrus.infra.onefile;singleton:=true -Bundle-RequiredExecutionEnvironment: J2SE-1.5 - +Manifest-Version: 1.0 +Export-Package: org.eclipse.papyrus.infra.onefile.model, + org.eclipse.papyrus.infra.onefile.utils +Require-Bundle: org.eclipse.papyrus.infra.core;bundle-version="1.0.0", + org.eclipse.ui.navigator, + org.eclipse.ui.navigator.resources, + org.eclipse.core.resources;bundle-version="3.7.0", + org.eclipse.core.runtime;bundle-version="3.7.0", + org.eclipse.ui, + org.eclipse.ui.ide;bundle-version="3.8.0", + org.eclipse.papyrus.infra.core.log;bundle-version="1.0.0", + org.eclipse.ltk.core.refactoring;bundle-version="3.6.0", + org.eclipse.ltk.ui.refactoring;bundle-version="3.7.0", + org.eclipse.core.filesystem;bundle-version="1.4.0", + org.eclipse.papyrus.infra.emf;bundle-version="1.0.0", + org.eclipse.core.expressions, + org.eclipse.emf.ecore +Bundle-Vendor: %providerName +Bundle-ActivationPolicy: lazy +Bundle-Version: 1.0.0.qualifier +Bundle-Localization: plugin +Bundle-Name: %pluginName +Bundle-Activator: org.eclipse.papyrus.infra.onefile.Activator +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: org.eclipse.papyrus.infra.onefile;singleton:=true +Bundle-RequiredExecutionEnvironment: J2SE-1.5 + diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/plugin.xml b/plugins/infra/org.eclipse.papyrus.infra.onefile/plugin.xml index 85297aee69e..4b89ad1cc3d 100644 --- a/plugins/infra/org.eclipse.papyrus.infra.onefile/plugin.xml +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/plugin.xml @@ -1,282 +1,316 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/CopyFilesAndFoldersOperation.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/CopyFilesAndFoldersOperation.java new file mode 100644 index 00000000000..86e0f9824e4 --- /dev/null +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/CopyFilesAndFoldersOperation.java @@ -0,0 +1,1959 @@ +/******************************************************************************* + * Copyright (c) 2000, 2013 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 + * Serge Beauchamp (Freescale Semiconductor) - [229633] Group Support + *******************************************************************************/ + +package org.eclipse.papyrus.infra.onefile.action; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.WorkspaceModifyOperation; +import org.eclipse.ui.dialogs.IOverwriteQuery; +import org.eclipse.ui.ide.dialogs.ImportTypeDialog; +import org.eclipse.ui.ide.undo.AbstractWorkspaceOperation; +import org.eclipse.ui.ide.undo.CopyResourcesOperation; +import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; +import org.eclipse.ui.internal.ide.IDEInternalPreferences; +import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; +import org.eclipse.ui.internal.ide.StatusUtil; +import org.eclipse.ui.internal.ide.dialogs.IDEResourceInfoUtils; +import org.eclipse.ui.statushandlers.StatusManager; +import org.eclipse.ui.wizards.datatransfer.FileStoreStructureProvider; +import org.eclipse.ui.wizards.datatransfer.ImportOperation; + + +/** + * Perform the copy of file and folder resources from the clipboard when paste + * action is invoked. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ * @noextend This class is not intended to be subclassed by clients. + */ +public class CopyFilesAndFoldersOperation { + + /** + * Status containing the errors detected when running the operation or + * null if no errors detected. + */ + private MultiStatus errorStatus; + + /** + * The parent shell used to show any dialogs. + */ + protected Shell messageShell; + + /** + * Whether or not the copy has been canceled by the user. + */ + private boolean canceled = false; + + /** + * Whether or not the operation creates virtual folders and links instead of folders + * and files. + */ + private boolean createVirtualFoldersAndLinks = false; + + /** + * Whether or not the operation creates links instead of folders and files. + */ + private boolean createLinks = false; + + private String relativeVariable = null; + /** + * Overwrite all flag. + */ + private boolean alwaysOverwrite = false; + + private String[] modelProviderIds; + + /** + * Returns a new name for a copy of the resource at the given path in the + * given workspace. This name is determined automatically. + * + * @param originalName + * the full path of the resource + * @param workspace + * the workspace + * @return the new full path for the copy + */ + static IPath getAutoNewNameFor(IPath originalName, IWorkspace workspace) { + int counter = 1; + String resourceName = originalName.lastSegment(); + IPath leadupSegment = originalName.removeLastSegments(1); + + while (true) { + String nameSegment; + + if (counter > 1) { + nameSegment = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyNameTwoArgs, + new Integer(counter), resourceName); + } else { + nameSegment = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyNameOneArg, + resourceName); + } + + IPath pathToTry = leadupSegment.append(nameSegment); + + if (!workspace.getRoot().exists(pathToTry)) { + return pathToTry; + } + + counter++; + } + } + + /** + * Creates a new operation initialized with a shell. + * + * @param shell + * parent shell for error dialogs + */ + public CopyFilesAndFoldersOperation(Shell shell) { + messageShell = shell; + } + + /** + * Returns whether this operation is able to perform on-the-fly + * auto-renaming of resources with name collisions. + * + * @return true if auto-rename is supported, and + * false otherwise + */ + protected boolean canPerformAutoRename() { + return true; + } + + /** + * Returns the message for querying deep copy/move of a linked resource. + * + * @param source + * resource the query is made for + * @return the deep query message + */ + protected String getDeepCheckQuestion(IResource source) { + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_deepCopyQuestion, + source.getFullPath().makeRelative()); + } + + /** + * Checks whether the infos exist. + * + * @param stores + * the file infos to test + * @return Multi status with one error message for each missing file. + */ + IStatus checkExist(IFileStore[] stores) { + MultiStatus multiStatus = new MultiStatus(PlatformUI.PLUGIN_ID, + IStatus.OK, getProblemsMessage(), null); + + for (int i = 0; i < stores.length; i++) { + if (stores[i].fetchInfo().exists() == false) { + String message = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted, + stores[i].getName()); + IStatus status = new Status(IStatus.ERROR, + PlatformUI.PLUGIN_ID, IStatus.OK, message, null); + multiStatus.add(status); + } + } + return multiStatus; + } + + /** + * Checks whether the resources with the given names exist. + * + * @param resources + * IResources to checl + * @return Multi status with one error message for each missing file. + */ + IStatus checkExist(IResource[] resources) { + MultiStatus multiStatus = new MultiStatus(PlatformUI.PLUGIN_ID, + IStatus.OK, getProblemsMessage(), null); + + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + if (resource != null && !resource.isVirtual()) { + URI location = resource.getLocationURI(); + String message = null; + if (location != null) { + IFileInfo info = IDEResourceInfoUtils.getFileInfo(location); + if (info == null || info.exists() == false) { + if (resource.isLinked()) { + message = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_missingLinkTarget, + resource.getName()); + } else { + message = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted, + resource.getName()); + } + } + } + if (message != null) { + IStatus status = new Status(IStatus.ERROR, + PlatformUI.PLUGIN_ID, IStatus.OK, message, null); + multiStatus.add(status); + } + } + } + return multiStatus; + } + + /** + * Check if the user wishes to overwrite the supplied resource or all + * resources. + * + * @param source + * the source resource + * @param destination + * the resource to be overwritten + * @return one of IDialogConstants.YES_ID, IDialogConstants.YES_TO_ALL_ID, + * IDialogConstants.NO_ID, IDialogConstants.CANCEL_ID indicating + * whether the current resource or all resources can be overwritten, + * or if the operation should be canceled. + */ + private int checkOverwrite(final IResource source, + final IResource destination) { + final int[] result = new int[1]; + + // Dialogs need to be created and opened in the UI thread + Runnable query = new Runnable() { + public void run() { + String message; + int resultId[] = { IDialogConstants.YES_ID, + IDialogConstants.YES_TO_ALL_ID, IDialogConstants.NO_ID, + IDialogConstants.CANCEL_ID }; + String labels[] = new String[] { IDialogConstants.YES_LABEL, + IDialogConstants.YES_TO_ALL_LABEL, + IDialogConstants.NO_LABEL, + IDialogConstants.CANCEL_LABEL }; + + if (destination.getType() == IResource.FOLDER) { + if (homogenousResources(source, destination)) { + message = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteMergeQuestion, + destination.getFullPath() + .makeRelative()); + } else { + if (destination.isLinked()) { + message = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteNoMergeLinkQuestion, + destination.getFullPath() + .makeRelative()); + } else { + message = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteNoMergeNoLinkQuestion, + destination.getFullPath() + .makeRelative()); + } + resultId = new int[] { IDialogConstants.YES_ID, + IDialogConstants.NO_ID, + IDialogConstants.CANCEL_ID }; + labels = new String[] { IDialogConstants.YES_LABEL, + IDialogConstants.NO_LABEL, + IDialogConstants.CANCEL_LABEL }; + } + } else { + String[] bindings = new String[] { + IDEResourceInfoUtils.getLocationText(destination), + IDEResourceInfoUtils + .getDateStringValue(destination), + IDEResourceInfoUtils.getLocationText(source), + IDEResourceInfoUtils.getDateStringValue(source) }; + message = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteWithDetailsQuestion, + bindings); + } + MessageDialog dialog = new MessageDialog( + messageShell, + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceExists, + null, message, MessageDialog.QUESTION, labels, 0) { + protected int getShellStyle() { + return super.getShellStyle() | SWT.SHEET; + } + }; + dialog.open(); + if (dialog.getReturnCode() == SWT.DEFAULT) { + // A window close returns SWT.DEFAULT, which has to be + // mapped to a cancel + result[0] = IDialogConstants.CANCEL_ID; + } else { + result[0] = resultId[dialog.getReturnCode()]; + } + } + }; + messageShell.getDisplay().syncExec(query); + return result[0]; + } + + /** + * Recursively collects existing files in the specified destination path. + * + * @param destinationPath + * destination path to check for existing files + * @param copyResources + * resources that may exist in the destination + * @param existing + * holds the collected existing files + */ + private void collectExistingReadonlyFiles(IPath destinationPath, + IResource[] copyResources, ArrayList existing) { + IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + + for (int i = 0; i < copyResources.length; i++) { + IResource source = copyResources[i]; + IPath newDestinationPath = destinationPath.append(source.getName()); + IResource newDestination = workspaceRoot + .findMember(newDestinationPath); + IFolder folder; + + if (newDestination == null) { + continue; + } + folder = getFolder(newDestination); + if (folder != null) { + IFolder sourceFolder = getFolder(source); + + if (sourceFolder != null) { + try { + collectExistingReadonlyFiles(newDestinationPath, + sourceFolder.members(), existing); + } catch (CoreException exception) { + recordError(exception); + } + } + } else { + IFile file = getFile(newDestination); + + if (file != null) { + if (file.isReadOnly()) { + existing.add(file); + } + if (getValidateConflictSource()) { + IFile sourceFile = getFile(source); + if (sourceFile != null) { + existing.add(sourceFile); + } + } + } + } + } + } + + /** + * Copies the resources to the given destination. This method is called + * recursively to merge folders during folder copy. + * + * @param resources + * the resources to copy + * @param destination + * destination to which resources will be copied + * @param subMonitor + * a progress monitor for showing progress and for cancelation + * + * @deprecated As of 3.3, the work is performed in the undoable operation + * created in + * {@link #getUndoableCopyOrMoveOperation(IResource[], IPath)} + */ + protected void copy(IResource[] resources, IPath destination, + IProgressMonitor subMonitor) throws CoreException { + + subMonitor + .beginTask( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_CopyResourcesTask, + resources.length); + + for (int i = 0; i < resources.length; i++) { + IResource source = resources[i]; + IPath destinationPath = destination.append(source.getName()); + IWorkspace workspace = source.getWorkspace(); + IWorkspaceRoot workspaceRoot = workspace.getRoot(); + IResource existing = workspaceRoot.findMember(destinationPath); + if (source.getType() == IResource.FOLDER && existing != null) { + // the resource is a folder and it exists in the destination, + // copy the + // children of the folder. + if (homogenousResources(source, existing)) { + IResource[] children = ((IContainer) source).members(); + copy(children, destinationPath, new SubProgressMonitor( + subMonitor, 1)); + } else { + // delete the destination folder, copying a linked folder + // over an unlinked one or vice versa. Fixes bug 28772. + delete(existing, new SubProgressMonitor(subMonitor, 0)); + source.copy(destinationPath, IResource.SHALLOW, + new SubProgressMonitor(subMonitor, 1)); + } + } else { + if (existing != null) { + if (homogenousResources(source, existing)) { + copyExisting(source, existing, new SubProgressMonitor( + subMonitor, 1)); + } else { + if (existing != null) { + // Copying a linked resource over unlinked or vice + // versa. + // Can't use setContents here. Fixes bug 28772. + delete(existing, new SubProgressMonitor(subMonitor, 0)); + } + + if ((createLinks || createVirtualFoldersAndLinks) + && (source.isLinked() == false) + && (source.isVirtual() == false)) { + if (source.getType() == IResource.FILE) { + IFile file = workspaceRoot.getFile(destinationPath); + file.createLink(createRelativePath(source.getLocationURI(), file), 0, + new SubProgressMonitor(subMonitor, 1)); + } else { + IFolder folder = workspaceRoot + .getFolder(destinationPath); + if (createVirtualFoldersAndLinks) { + folder.create(IResource.VIRTUAL, true, + new SubProgressMonitor(subMonitor, + 1)); + IResource[] members = ((IContainer) source) + .members(); + if (members.length > 0) + copy(members, destinationPath, + new SubProgressMonitor(subMonitor, + 1)); + } else + folder.createLink(createRelativePath(source.getLocationURI(), folder), 0, + new SubProgressMonitor(subMonitor, 1)); + } + } else + source.copy(destinationPath, IResource.SHALLOW, + new SubProgressMonitor(subMonitor, 1)); + } + + if (subMonitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + } + } + } + + /** + * Transform an absolute path URI to a relative path one (i.e. from + * "C:\foo\bar\file.txt" to "VAR\file.txt" granted that the relativeVariable + * is "VAR" and points to "C:\foo\bar\"). + * + * @param locationURI + * @return an URI that was made relative to a variable + */ + private URI createRelativePath(URI locationURI, IResource resource) { + if (relativeVariable == null) + return locationURI; + IPath location = URIUtil.toPath(locationURI); + IPath result; + try { + result = URIUtil.toPath(resource.getPathVariableManager().convertToRelative(URIUtil.toURI(location), true, relativeVariable)); + } catch (CoreException e) { + return locationURI; + } + return URIUtil.toURI(result); + } + + /** + * Sets the content of the existing file to the source file content. + * + * @param source + * source file to copy + * @param existing + * existing file to set the source content in + * @param subMonitor + * a progress monitor for showing progress and for cancelation + * @throws CoreException + * setContents failed + */ + private void copyExisting(IResource source, IResource existing, + IProgressMonitor subMonitor) throws CoreException { + IFile existingFile = getFile(existing); + + if (existingFile != null) { + IFile sourceFile = getFile(source); + + if (sourceFile != null) { + existingFile.setContents(sourceFile.getContents(), + IResource.KEEP_HISTORY, new SubProgressMonitor( + subMonitor, 0)); + } + } + } + + /** + * Copies the given resources to the destination. The current Thread is + * halted while the resources are copied using a WorkspaceModifyOperation. + * This method should be called from the UIThread. + * + * @param resources + * the resources to copy + * @param destination + * destination to which resources will be copied + * @return the resources which actually got copied + * @see WorkspaceModifyOperation + * @see Display#getThread() + * @see Thread#currentThread() + */ + public IResource[] copyResources(final IResource[] resources, + IContainer destination) { + return copyResources(resources, destination, true); + } + + /** + * Copies the given resources to the destination in the current Thread + * without forking a new Thread or blocking using a + * WorkspaceModifyOperation. It recommended that this method only be called + * from a {@link WorkspaceJob} to avoid possible deadlock. + * + * @param resources + * the resources to copy + * @param destination + * destination to which resources will be copied + * @param monitor + * the monitor that information will be sent to. + * @return IResource[] the resulting {@link IResource}[] + * @see WorkspaceModifyOperation + * @see WorkspaceJob + * @since 3.2 + */ + public IResource[] copyResourcesInCurrentThread( + final IResource[] resources, IContainer destination, + IProgressMonitor monitor) { + return copyResources(resources, destination, false); + } + + /** + * Copies the given resources to the destination. + * + * @param resources + * the resources to copy + * @param destination + * destination to which resources will be copied + * @return IResource[] the resulting {@link IResource}[] + */ + private IResource[] copyResources(final IResource[] resources, + IContainer destination, boolean fork) { + final IPath destinationPath = destination.getFullPath(); + final IResource[][] copiedResources = new IResource[1][0]; + + // test resources for existence separate from validate API. + // Validate is performance critical and resource exists + // check is potentially slow. Fixes bugs 16129/28602. + IStatus resourceStatus = checkExist(resources); + if (resourceStatus.getSeverity() != IStatus.OK) { + displayError(resourceStatus); + return copiedResources[0]; + } + String errorMsg = validateDestination(destination, resources); + if (errorMsg != null) { + displayError(errorMsg); + return copiedResources[0]; + } + + IRunnableWithProgress op = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) { + copyResources(resources, destinationPath, copiedResources, + monitor); + } + }; + + try { + PlatformUI.getWorkbench().getProgressService().run(fork, true, op); + } catch (InterruptedException e) { + return copiedResources[0]; + } catch (InvocationTargetException e) { + display(e); + } + + // If errors occurred, open an Error dialog + if (errorStatus != null) { + displayError(errorStatus); + errorStatus = null; + } + + return copiedResources[0]; + } + + /** + * Return whether the operation is a move or a copy + * + * @return whether the operation is a move or a copy + * @since 3.2 + */ + protected boolean isMove() { + return false; + } + + private void display(InvocationTargetException e) { + // CoreExceptions are collected above, but unexpected runtime + // exceptions and errors may still occur. + String format = "Exception in "+getClass().getName()+".performCopy(): "+e.getTargetException(); + + IDEWorkbenchPlugin.getDefault().getLog().log( + StatusUtil.newStatus(IStatus.ERROR, format, null)); + displayError(NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_internalError, + e.getTargetException().getMessage())); + } + + /** + * Copies the given URIS and folders to the destination. The current Thread + * is halted while the resources are copied using a + * WorkspaceModifyOperation. This method should be called from the UI + * Thread. + * + * @param uris + * the URIs to copy + * @param destination + * destination to which files will be copied + * @see WorkspaceModifyOperation + * @see Display#getThread() + * @see Thread#currentThread() + * @since 3.2 + */ + public void copyFiles(URI[] uris, IContainer destination) { + IFileStore[] stores = buildFileStores(uris); + if (stores == null) { + return; + } + + copyFileStores(destination, stores, true, null); + } + + /** + * Copies the given files and folders to the destination without forking a + * new Thread or blocking using a WorkspaceModifyOperation. It is + * recommended that this method only be called from a {@link WorkspaceJob} + * to avoid possible deadlock. + * + * @param uris + * the URIs to copy + * @param destination + * destination to which URIS will be copied + * @param monitor + * the monitor that information will be sent to. + * @see WorkspaceModifyOperation + * @see WorkspaceJob + * @since 3.2 + */ + public void copyFilesInCurrentThread(URI[] uris, IContainer destination, + IProgressMonitor monitor) { + IFileStore[] stores = buildFileStores(uris); + if (stores == null) { + return; + } + + copyFileStores(destination, stores, false, monitor); + } + + /** + * Build the collection of fileStores that map to fileNames. If any of them + * cannot be found then match then return null. + * + * @param uris + * @return IFileStore[] + */ + private IFileStore[] buildFileStores(URI[] uris) { + IFileStore[] stores = new IFileStore[uris.length]; + for (int i = 0; i < uris.length; i++) { + IFileStore store; + try { + store = EFS.getStore(uris[i]); + } catch (CoreException e) { + StatusManager.getManager().handle(e, IDEWorkbenchPlugin.IDE_WORKBENCH); + reportFileInfoNotFound(uris[i].toString()); + return null; + } + if (store == null) { + reportFileInfoNotFound(uris[i].toString()); + return null; + } + stores[i] = store; + } + return stores; + + } + + /** + * Depending on the 'Linked Resources' preferences it copies the given files and folders to the + * destination or creates links or shows a dialog that lets the user choose. The current thread + * is halted while the resources are copied using a {@link WorkspaceModifyOperation}. This + * method should be called from the UI Thread. + * + * @param fileNames names of the files to copy + * @param destination destination to which files will be copied + * @param dropOperation the drop operation ({@link DND#DROP_NONE}, {@link DND#DROP_MOVE} + * {@link DND#DROP_COPY}, {@link DND#DROP_LINK}, {@link DND#DROP_DEFAULT}) + * @see WorkspaceModifyOperation + * @see Display#getThread() + * @see Thread#currentThread() + * @since 3.6 + */ + public void copyOrLinkFiles(final String[] fileNames, IContainer destination, int dropOperation) { + IPreferenceStore store= IDEWorkbenchPlugin.getDefault().getPreferenceStore(); + boolean targetIsVirtual= destination.isVirtual(); + String dndPreference= store.getString(targetIsVirtual ? IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_VIRTUAL_FOLDER_MODE : IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE); + + int mode= ImportTypeDialog.IMPORT_NONE; + String variable= null; + + //check if resource linking is disabled + if (ResourcesPlugin.getPlugin().getPluginPreferences().getBoolean(ResourcesPlugin.PREF_DISABLE_LINKING)) + mode= ImportTypeDialog.IMPORT_COPY; + else { + if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_PROMPT)) { + ImportTypeDialog dialog= new ImportTypeDialog(messageShell, dropOperation, fileNames, destination); + dialog.setResource(destination); + if (dialog.open() == Window.OK) { + mode= dialog.getSelection(); + variable= dialog.getVariable(); + } + } else if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_MOVE_COPY)) { + mode= ImportTypeDialog.IMPORT_COPY; + } else if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_LINK)) { + mode= ImportTypeDialog.IMPORT_LINK; + } else if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_LINK_AND_VIRTUAL_FOLDER)) { + mode= ImportTypeDialog.IMPORT_VIRTUAL_FOLDERS_AND_LINKS; + } + } + + switch (mode) { + case ImportTypeDialog.IMPORT_COPY: + copyFiles(fileNames, destination); + break; + case ImportTypeDialog.IMPORT_VIRTUAL_FOLDERS_AND_LINKS: + if (variable != null) + setRelativeVariable(variable); + createVirtualFoldersAndLinks(fileNames, destination); + break; + case ImportTypeDialog.IMPORT_LINK: + if (variable != null) + setRelativeVariable(variable); + linkFiles(fileNames, destination); + break; + case ImportTypeDialog.IMPORT_NONE: + break; + } + + } + + /** + * Copies the given files and folders to the destination. The current Thread is halted while the + * resources are copied using a WorkspaceModifyOperation. This method should be called from the + * UI Thread. + * + * @param fileNames names of the files to copy + * @param destination destination to which files will be copied + * @see WorkspaceModifyOperation + * @see Display#getThread() + * @see Thread#currentThread() + * @since 3.2 + */ + public void copyFiles(final String[] fileNames, IContainer destination) { + IFileStore[] stores = buildFileStores(fileNames); + if (stores == null) { + return; + } + + copyFileStores(destination, stores, true, null); + } + + /** + * Copies the given files and folders to the destination without forking a + * new Thread or blocking using a WorkspaceModifyOperation. It is + * recommended that this method only be called from a {@link WorkspaceJob} + * to avoid possible deadlock. + * + * @param fileNames + * names of the files to copy + * @param destination + * destination to which files will be copied + * @param monitor + * the monitor that information will be sent to. + * @see WorkspaceModifyOperation + * @see WorkspaceJob + * @since 3.2 + */ + public void copyFilesInCurrentThread(final String[] fileNames, + IContainer destination, IProgressMonitor monitor) { + IFileStore[] stores = buildFileStores(fileNames); + if (stores == null) { + return; + } + + copyFileStores(destination, stores, false, monitor); + } + + /** + * Build the collection of fileStores that map to fileNames. If any of them + * cannot be found then match then return null. + * + * @param fileNames + * @return IFileStore[] + */ + private IFileStore[] buildFileStores(final String[] fileNames) { + IFileStore[] stores = new IFileStore[fileNames.length]; + for (int i = 0; i < fileNames.length; i++) { + IFileStore store = IDEResourceInfoUtils.getFileStore(fileNames[i]); + if (store == null) { + reportFileInfoNotFound(fileNames[i]); + return null; + } + stores[i] = store; + } + return stores; + } + + /** + * Report that a file info could not be found. + * + * @param fileName + */ + private void reportFileInfoNotFound(final String fileName) { + + messageShell.getDisplay().syncExec(new Runnable() { + public void run() { + ErrorDialog + .openError( + messageShell, + getProblemsTitle(), + NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_infoNotFound, + fileName), null); + } + }); + } + + /** + * Copies the given files and folders to the destination. + * + * @param stores + * the file stores to copy + * @param destination + * destination to which files will be copied + */ + private void copyFileStores(IContainer destination, + final IFileStore[] stores, boolean fork, IProgressMonitor monitor) { + // test files for existence separate from validate API + // because an external file may not exist until the copy actually + // takes place (e.g., WinZip contents). + IStatus fileStatus = checkExist(stores); + if (fileStatus.getSeverity() != IStatus.OK) { + displayError(fileStatus); + return; + } + String errorMsg = validateImportDestinationInternal(destination, stores); + if (errorMsg != null) { + displayError(errorMsg); + return; + } + final IPath destinationPath = destination.getFullPath(); + + if (fork) { + WorkspaceModifyOperation op = new WorkspaceModifyOperation() { + public void execute(IProgressMonitor monitor) { + copyFileStores(stores, destinationPath, monitor); + } + }; + try { + PlatformUI.getWorkbench().getProgressService().run(true, true, + op); + } catch (InterruptedException e) { + return; + } catch (InvocationTargetException exception) { + display(exception); + } + } else { + copyFileStores(stores, destinationPath, monitor); + } + + // If errors occurred, open an Error dialog + if (errorStatus != null) { + displayError(errorStatus); + errorStatus = null; + } + } + + /** + * Display the supplied status in an error dialog. + * + * @param status + * The status to display + */ + protected void displayError(final IStatus status) { + messageShell.getDisplay().syncExec(new Runnable() { + public void run() { + ErrorDialog.openError(messageShell, getProblemsTitle(), null, + status); + } + }); + } + + /** + * Creates a file or folder handle for the source resource as if it were to + * be created in the destination container. + * + * @param destination + * destination container + * @param source + * source resource + * @return IResource file or folder handle, depending on the source type. + */ + IResource createLinkedResourceHandle(IContainer destination, + IResource source) { + IWorkspace workspace = destination.getWorkspace(); + IWorkspaceRoot workspaceRoot = workspace.getRoot(); + IPath linkPath = destination.getFullPath().append(source.getName()); + IResource linkHandle; + + if (source.getType() == IResource.FOLDER) { + linkHandle = workspaceRoot.getFolder(linkPath); + } else { + linkHandle = workspaceRoot.getFile(linkPath); + } + return linkHandle; + } + + /** + * Removes the given resource from the workspace. + * + * @param resource + * resource to remove from the workspace + * @param monitor + * a progress monitor for showing progress and for cancelation + * @return true the resource was deleted successfully false the resource was + * not deleted because a CoreException occurred + */ + boolean delete(IResource resource, IProgressMonitor monitor) { + boolean force = false; // don't force deletion of out-of-sync resources + + if (resource.getType() == IResource.PROJECT) { + // if it's a project, ask whether content should be deleted too + IProject project = (IProject) resource; + try { + project.delete(true, force, monitor); + } catch (CoreException e) { + recordError(e); // log error + return false; + } + } else { + // if it's not a project, just delete it + int flags = IResource.KEEP_HISTORY; + if (force) { + flags = flags | IResource.FORCE; + } + try { + resource.delete(flags, monitor); + } catch (CoreException e) { + recordError(e); // log error + return false; + } + } + return true; + } + + /** + * Opens an error dialog to display the given message. + * + * @param message + * the error message to show + */ + protected void displayError(final String message) { + messageShell.getDisplay().syncExec(new Runnable() { + public void run() { + MessageDialog.openError(messageShell, getProblemsTitle(), + message); + } + }); + } + + /** + * Returns the resource either casted to or adapted to an IFile. + * + * @param resource + * resource to cast/adapt + * @return the resource either casted to or adapted to an IFile. + * null if the resource does not adapt to IFile + */ + protected IFile getFile(IResource resource) { + if (resource instanceof IFile) { + return (IFile) resource; + } + return (IFile) ((IAdaptable) resource).getAdapter(IFile.class); + } + + /** + * Returns java.io.File objects for the given file names. + * + * @param fileNames + * files to return File object for. + * @return java.io.File objects for the given file names. + * @deprecated As of 3.3, this method is no longer in use anywhere in this + * class and is only provided for backwards compatability with + * subclasses of the receiver. + */ + protected File[] getFiles(String[] fileNames) { + File[] files = new File[fileNames.length]; + + for (int i = 0; i < fileNames.length; i++) { + files[i] = new File(fileNames[i]); + } + return files; + } + + /** + * Returns the resource either casted to or adapted to an IFolder. + * + * @param resource + * resource to cast/adapt + * @return the resource either casted to or adapted to an IFolder. + * null if the resource does not adapt to IFolder + */ + protected IFolder getFolder(IResource resource) { + if (resource instanceof IFolder) { + return (IFolder) resource; + } + return (IFolder) ((IAdaptable) resource).getAdapter(IFolder.class); + } + + /** + * Returns a new name for a copy of the resource at the given path in the + * given workspace. + * + * @param originalName + * the full path of the resource + * @param workspace + * the workspace + * @return the new full path for the copy, or null if the + * resource should not be copied + */ + protected IPath getNewNameFor(final IPath originalName, + final IWorkspace workspace) { + final IResource resource = workspace.getRoot().findMember(originalName); + final IPath prefix = resource.getFullPath().removeLastSegments(1); + final String returnValue[] = { "" }; //$NON-NLS-1$ + + messageShell.getDisplay().syncExec(new Runnable() { + public void run() { + IInputValidator validator = new IInputValidator() { + public String isValid(String string) { + if (resource.getName().equals(string)) { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_nameMustBeDifferent; + } + IStatus status = workspace.validateName(string, + resource.getType()); + if (!status.isOK()) { + return status.getMessage(); + } + if (workspace.getRoot().exists(prefix.append(string))) { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_nameExists; + } + return null; + } + }; + + InputDialog dialog = new InputDialog( + messageShell, + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_inputDialogTitle, + NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_inputDialogMessage, + resource.getName()), getAutoNewNameFor( + originalName, workspace).lastSegment() + .toString(), validator); + dialog.setBlockOnOpen(true); + dialog.open(); + if (dialog.getReturnCode() == Window.CANCEL) { + returnValue[0] = null; + } else { + returnValue[0] = dialog.getValue(); + } + } + }); + if (returnValue[0] == null) { + throw new OperationCanceledException(); + } + return prefix.append(returnValue[0]); + } + + /** + * Returns the task title for this operation's progress dialog. + * + * @return the task title + */ + protected String getOperationTitle() { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_operationTitle; + } + + /** + * Returns the message for this operation's problems dialog. + * + * @return the problems message + */ + protected String getProblemsMessage() { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_problemMessage; + } + + /** + * Returns the title for this operation's problems dialog. + * + * @return the problems dialog title + */ + protected String getProblemsTitle() { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyFailedTitle; + } + + /** + * Returns whether the source file in a destination collision will be + * validateEdited together with the collision itself. Returns false. Should + * return true if the source file is to be deleted after the operation. + * + * @return boolean true if the source file in a destination + * collision should be validateEdited. false if only + * the destination should be validated. + */ + protected boolean getValidateConflictSource() { + return false; + } + + /** + * Returns whether the given resources are either both linked or both + * unlinked. + * + * @param source + * source resource + * @param destination + * destination resource + * @return boolean true if both resources are either linked + * or unlinked. false otherwise. + */ + protected boolean homogenousResources(IResource source, + IResource destination) { + boolean isSourceLinked = source.isLinked(); + boolean isDestinationLinked = destination.isLinked(); + + return (isSourceLinked && isDestinationLinked || isSourceLinked == false + && isDestinationLinked == false); + } + + /** + * Returns whether the given resource is accessible. Files and folders are + * always considered accessible and a project is accessible if it is open. + * + * @param resource + * the resource + * @return true if the resource is accessible, and + * false if it is not + */ + private boolean isAccessible(IResource resource) { + switch (resource.getType()) { + case IResource.FILE: + return true; + case IResource.FOLDER: + return true; + case IResource.PROJECT: + return ((IProject) resource).isOpen(); + default: + return false; + } + } + + /** + * Returns whether any of the given source resources are being recopied to + * their current container. + * + * @param sourceResources + * the source resources + * @param destination + * the destination container + * @return true if at least one of the given source + * resource's parent container is the same as the destination + */ + boolean isDestinationSameAsSource(IResource[] sourceResources, + IContainer destination) { + IPath destinationLocation = destination.getLocation(); + + for (int i = 0; i < sourceResources.length; i++) { + IResource sourceResource = sourceResources[i]; + if (sourceResource.getParent().equals(destination)) { + return true; + } else if (destinationLocation != null) { + // do thorough check to catch linked resources. Fixes bug 29913. + IPath sourceLocation = sourceResource.getLocation(); + IPath destinationResource = destinationLocation + .append(sourceResource.getName()); + if (sourceLocation != null + && sourceLocation.isPrefixOf(destinationResource)) { + return true; + } + } + } + return false; + } + + /** + * Copies the given resources to the destination container with the given + * name. + *

+ * Note: the destination container may need to be created prior to copying + * the resources. + *

+ * + * @param resources + * the resources to copy + * @param destination + * the path of the destination container + * @param monitor + * a progress monitor for showing progress and for cancelation + * @return true if the copy operation completed without + * errors + */ + protected boolean performCopy(IResource[] resources, IPath destination, + IProgressMonitor monitor) { + try { + AbstractWorkspaceOperation op = getUndoableCopyOrMoveOperation( + resources, destination); + op.setModelProviderIds(getModelProviderIds()); + if (op instanceof CopyResourcesOperation) { + CopyResourcesOperation copyMoveOp = (CopyResourcesOperation) op; + copyMoveOp.setCreateVirtualFolders(createVirtualFoldersAndLinks); + copyMoveOp.setCreateLinks(createLinks); + copyMoveOp.setRelativeVariable(relativeVariable); + } + PlatformUI.getWorkbench().getOperationSupport() + .getOperationHistory().execute(op, monitor, + WorkspaceUndoUtil.getUIInfoAdapter(messageShell)); + } catch (ExecutionException e) { + if (e.getCause() instanceof CoreException) { + recordError((CoreException) e.getCause()); + } else { + IDEWorkbenchPlugin.log(e.getMessage(), e); + displayError(e.getMessage()); + } + return false; + } + return true; + } + + /** + * Individually copies the given resources to the specified destination + * container checking for name collisions. If a collision is detected, it is + * saved with a new name. + *

+ * Note: the destination container may need to be created prior to copying + * the resources. + *

+ * + * @param resources + * the resources to copy + * @param destination + * the path of the destination container + * @return true if the copy operation completed without + * errors. + */ + protected boolean performCopyWithAutoRename(IResource[] resources, + IPath destination, IProgressMonitor monitor) { + IWorkspace workspace = resources[0].getWorkspace(); + IPath[] destinationPaths = new IPath[resources.length]; + try { + for (int i = 0; i < resources.length; i++) { + IResource source = resources[i]; + destinationPaths[i] = destination.append(source.getName()); + + if (workspace.getRoot().exists(destinationPaths[i])) { + destinationPaths[i] = getNewNameFor(destinationPaths[i], + workspace); + } + } + CopyResourcesOperation op = new CopyResourcesOperation(resources, + destinationPaths, + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyTitle); + op.setModelProviderIds(getModelProviderIds()); + PlatformUI.getWorkbench().getOperationSupport() + .getOperationHistory().execute(op, monitor, + WorkspaceUndoUtil.getUIInfoAdapter(messageShell)); + } catch (ExecutionException e) { + if (e.getCause() instanceof CoreException) { + recordError((CoreException) e.getCause()); + } else { + IDEWorkbenchPlugin.log(e.getMessage(), e); + displayError(e.getMessage()); + } + return false; + } + return true; + } + + /** + * Performs an import of the given stores into the provided container. + * Returns a status indicating if the import was successful. + * + * @param stores + * stores that are to be imported + * @param target + * container to which the import will be done + * @param monitor + * a progress monitor for showing progress and for cancelation + */ + private void performFileImport(IFileStore[] stores, IContainer target, + IProgressMonitor monitor) { + IOverwriteQuery query = new IOverwriteQuery() { + public String queryOverwrite(String pathString) { + if (alwaysOverwrite) { + return ALL; + } + + final String returnCode[] = { CANCEL }; + final String msg = NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteQuestion, + pathString); + final String[] options = { IDialogConstants.YES_LABEL, + IDialogConstants.YES_TO_ALL_LABEL, + IDialogConstants.NO_LABEL, + IDialogConstants.CANCEL_LABEL }; + messageShell.getDisplay().syncExec(new Runnable() { + public void run() { + MessageDialog dialog = new MessageDialog( + messageShell, + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_question, + null, msg, MessageDialog.QUESTION, options, 0) { + protected int getShellStyle() { + return super.getShellStyle() | SWT.SHEET; + } + }; + dialog.open(); + int returnVal = dialog.getReturnCode(); + String[] returnCodes = { YES, ALL, NO, CANCEL }; + returnCode[0] = returnVal == -1 ? CANCEL + : returnCodes[returnVal]; + } + }); + if (returnCode[0] == ALL) { + alwaysOverwrite = true; + } else if (returnCode[0] == CANCEL) { + canceled = true; + } + return returnCode[0]; + } + }; + + ImportOperation op = new ImportOperation(target.getFullPath(), + stores[0].getParent(), FileStoreStructureProvider.INSTANCE, + query, Arrays.asList(stores)); + op.setContext(messageShell); + op.setCreateContainerStructure(false); + op.setVirtualFolders(createVirtualFoldersAndLinks); + op.setCreateLinks(createLinks); + op.setRelativeVariable(relativeVariable); + try { + op.run(monitor); + } catch (InterruptedException e) { + return; + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof CoreException) { + displayError(((CoreException) e.getTargetException()) + .getStatus()); + } else { + display(e); + } + return; + } + // Special case since ImportOperation doesn't throw a CoreException on + // failure. + IStatus status = op.getStatus(); + if (!status.isOK()) { + if (errorStatus == null) { + errorStatus = new MultiStatus(PlatformUI.PLUGIN_ID, + IStatus.ERROR, getProblemsMessage(), null); + } + errorStatus.merge(status); + } + } + + /** + * Records the core exception to be displayed to the user once the action is + * finished. + * + * @param error + * a CoreException + */ + protected void recordError(CoreException error) { + if (errorStatus == null) { + errorStatus = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.ERROR, + getProblemsMessage(), error); + } + + errorStatus.merge(error.getStatus()); + } + + /** + * Checks whether the destination is valid for copying the source resources. + *

+ * Note this method is for internal use only. It is not API. + *

+ * + * @param destination + * the destination container + * @param sourceResources + * the source resources + * @return an error message, or null if the path is valid + */ + public String validateDestination(IContainer destination, + IResource[] sourceResources) { + if (!isAccessible(destination)) { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationAccessError; + } + IContainer firstParent = null; + URI destinationLocation = destination.getLocationURI(); + for (int i = 0; i < sourceResources.length; i++) { + IResource sourceResource = sourceResources[i]; + if (firstParent == null) { + firstParent = sourceResource.getParent(); + } else if (firstParent.equals(sourceResource.getParent()) == false) { + // Resources must have common parent. Fixes bug 33398. + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_parentNotEqual; + } + + // verify that if the destination is a virtual folder, the resource must be + // either a link or another virtual folder + if (destination.isVirtual()) { + if (!sourceResource.isLinked() && !sourceResource.isVirtual() + && !createLinks && !createVirtualFoldersAndLinks) { + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_sourceCannotBeCopiedIntoAVirtualFolder, + sourceResource.getName()); + } + } + URI sourceLocation = sourceResource.getLocationURI(); + if (sourceLocation == null) { + if (sourceResource.isLinked()) { + // Don't allow copying linked resources with undefined path + // variables. See bug 28754. + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_missingPathVariable, + sourceResource.getName()); + } + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted, + sourceResource.getName()); + + } + if (!destination.isVirtual()) { + if (sourceLocation.equals(destinationLocation)) { + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_sameSourceAndDest, + sourceResource.getName()); + } + // is the source a parent of the destination? + if (new Path(sourceLocation.toString()).isPrefixOf(new Path( + destinationLocation.toString()))) { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationDescendentError; + } + } + + String linkedResourceMessage = validateLinkedResource(destination, + sourceResource); + if (linkedResourceMessage != null) { + return linkedResourceMessage; + } + } + return null; + } + + /** + * Validates that the given source resources can be copied to the + * destination as decided by the VCM provider. + * + * @param destination + * copy destination + * @param sourceResources + * source resources + * @return true all files passed validation or there were no + * files to validate. false one or more files did not + * pass validation. + */ + private boolean validateEdit(IContainer destination, + IResource[] sourceResources) { + ArrayList copyFiles = new ArrayList(); + + collectExistingReadonlyFiles(destination.getFullPath(), + sourceResources, copyFiles); + if (copyFiles.size() > 0) { + IFile[] files = (IFile[]) copyFiles.toArray(new IFile[copyFiles + .size()]); + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IStatus status = workspace.validateEdit(files, messageShell); + + canceled = status.isOK() == false; + return status.isOK(); + } + return true; + } + + /** + * Checks whether the destination is valid for copying the source files. + *

+ * Note this method is for internal use only. It is not API. + *

+ * + * @param destination + * the destination container + * @param sourceNames + * the source file names + * @return an error message, or null if the path is valid + */ + public String validateImportDestination(IContainer destination, + String[] sourceNames) { + + IFileStore[] stores = new IFileStore[sourceNames.length]; + for (int i = 0; i < sourceNames.length; i++) { + IFileStore store = IDEResourceInfoUtils + .getFileStore(sourceNames[i]); + if (store == null) { + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_infoNotFound, + sourceNames[i]); + } + stores[i] = store; + } + return validateImportDestinationInternal(destination, stores); + + } + + /** + * Checks whether the destination is valid for copying the source file + * stores. + *

+ * Note this method is for internal use only. It is not API. + *

+ *

+ * TODO Bug 117804. This method has been renamed to avoid a bug in the + * Eclipse compiler with regards to visibility and type resolution when + * linking. + *

+ * + * @param destination + * the destination container + * @param sourceStores + * the source IFileStore + * @return an error message, or null if the path is valid + */ + private String validateImportDestinationInternal(IContainer destination, + IFileStore[] sourceStores) { + if (!isAccessible(destination)) + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationAccessError; + + if (!destination.isVirtual()) { + IFileStore destinationStore; + try { + destinationStore = EFS.getStore(destination.getLocationURI()); + } catch (CoreException exception) { + IDEWorkbenchPlugin.log(exception.getLocalizedMessage(), exception); + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_internalError, + exception.getLocalizedMessage()); + } + for (int i = 0; i < sourceStores.length; i++) { + IFileStore sourceStore = sourceStores[i]; + IFileStore sourceParentStore = sourceStore.getParent(); + + if (sourceStore != null) { + if (destinationStore.equals(sourceStore) + || (sourceParentStore != null && destinationStore + .equals(sourceParentStore))) { + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_importSameSourceAndDest, + sourceStore.getName()); + } + // work around bug 16202. replacement for + // sourcePath.isPrefixOf(destinationPath) + if (sourceStore.isParentOf(destinationStore)) { + return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationDescendentError; + } + } + } + } + return null; + } + + /** + * Check if the destination is valid for the given source resource. + * + * @param destination + * destination container of the operation + * @param source + * source resource + * @return String error message or null if the destination is valid + */ + private String validateLinkedResource(IContainer destination, + IResource source) { + if ((source.isLinked() == false) || source.isVirtual()) { + return null; + } + IWorkspace workspace = destination.getWorkspace(); + IResource linkHandle = createLinkedResourceHandle(destination, source); + IStatus locationStatus = workspace.validateLinkLocationURI(linkHandle, + source.getRawLocationURI()); + + if (locationStatus.getSeverity() == IStatus.ERROR) { + return locationStatus.getMessage(); + } + IPath sourceLocation = source.getLocation(); + if (source.getProject().equals(destination.getProject()) == false + && source.getType() == IResource.FOLDER + && sourceLocation != null) { + // prevent merging linked folders that point to the same + // file system folder + try { + IResource[] members = destination.members(); + for (int j = 0; j < members.length; j++) { + if (sourceLocation.equals(members[j].getLocation()) + && source.getName().equals(members[j].getName())) { + return NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_sameSourceAndDest, + source.getName()); + } + } + } catch (CoreException exception) { + displayError(NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_internalError, + exception.getMessage())); + } + } + return null; + } + + /** + * Returns whether moving all of the given source resources to the given + * destination container could be done without causing name collisions. + * + * @param destination + * the destination container + * @param sourceResources + * the list of resources + * @return true if there would be no name collisions, and + * false if there would + */ + private IResource[] validateNoNameCollisions(IContainer destination, + IResource[] sourceResources) { + List copyItems = new ArrayList(); + IWorkspaceRoot workspaceRoot = destination.getWorkspace().getRoot(); + int overwrite = IDialogConstants.NO_ID; + + // Check to see if we would be overwriting a parent folder. + // Cancel entire copy operation if we do. + for (int i = 0; i < sourceResources.length; i++) { + final IResource sourceResource = sourceResources[i]; + final IPath destinationPath = destination.getFullPath().append( + sourceResource.getName()); + final IPath sourcePath = sourceResource.getFullPath(); + + IResource newResource = workspaceRoot.findMember(destinationPath); + if (newResource != null && destinationPath.isPrefixOf(sourcePath)) { + displayError(NLS + .bind( + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteProblem, + destinationPath, sourcePath)); + + canceled = true; + return null; + } + } + // Check for overwrite conflicts + for (int i = 0; i < sourceResources.length; i++) { + final IResource source = sourceResources[i]; + final IPath destinationPath = destination.getFullPath().append( + source.getName()); + + IResource newResource = workspaceRoot.findMember(destinationPath); + if (newResource != null) { + if (overwrite != IDialogConstants.YES_TO_ALL_ID + || (newResource.getType() == IResource.FOLDER && homogenousResources( + source, destination) == false)) { + overwrite = checkOverwrite(source, newResource); + } + if (overwrite == IDialogConstants.YES_ID + || overwrite == IDialogConstants.YES_TO_ALL_ID) { + copyItems.add(source); + } else if (overwrite == IDialogConstants.CANCEL_ID) { + canceled = true; + return null; + } + } else { + copyItems.add(source); + } + } + return (IResource[]) copyItems.toArray(new IResource[copyItems.size()]); + } + + private void copyResources(final IResource[] resources, + final IPath destinationPath, final IResource[][] copiedResources, + IProgressMonitor monitor) { + IResource[] copyResources = resources; + + // Fix for bug 31116. Do not provide a task name when + // creating the task. + monitor.beginTask("", 100); //$NON-NLS-1$ + monitor.setTaskName(getOperationTitle()); + monitor.worked(10); // show some initial progress + + // Checks only required if this is an exisiting container path. + boolean copyWithAutoRename = false; + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + if (root.exists(destinationPath)) { + IContainer container = (IContainer) root + .findMember(destinationPath); + // If we're copying to the source container then perform + // auto-renames on all resources to avoid name collisions. + if (isDestinationSameAsSource(copyResources, container) + && canPerformAutoRename()) { + copyWithAutoRename = true; + } else { + // If no auto-renaming will be happening, check for + // potential name collisions at the target resource + copyResources = validateNoNameCollisions(container, + copyResources); + if (copyResources == null) { + if (canceled) { + return; + } + displayError(IDEWorkbenchMessages.CopyFilesAndFoldersOperation_nameCollision); + return; + } + if (validateEdit(container, copyResources) == false) { + return; + } + } + } + + errorStatus = null; + if (copyResources.length > 0) { + if (copyWithAutoRename) { + performCopyWithAutoRename(copyResources, destinationPath, + new SubProgressMonitor(monitor, 90)); + } else { + performCopy(copyResources, destinationPath, new SubProgressMonitor(monitor, 90)); + } + } + monitor.done(); + copiedResources[0] = copyResources; + } + + private void copyFileStores(final IFileStore[] stores, + final IPath destinationPath, IProgressMonitor monitor) { + // Checks only required if this is an exisiting container path. + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + if (root.exists(destinationPath)) { + IContainer container = (IContainer) root + .findMember(destinationPath); + + performFileImport(stores, container, monitor); + } + } + + /** + * Returns the model provider ids that are known to the client that + * instantiated this operation. + * + * @return the model provider ids that are known to the client that + * instantiated this operation. + * @since 3.2 + */ + public String[] getModelProviderIds() { + return modelProviderIds; + } + + /** + * Sets the model provider ids that are known to the client that + * instantiated this operation. Any potential side effects reported by these + * models during validation will be ignored. + * + * @param modelProviderIds + * the model providers known to the client who is using this + * operation. + * @since 3.2 + */ + public void setModelProviderIds(String[] modelProviderIds) { + this.modelProviderIds = modelProviderIds; + } + + /** + * Create virtual folders and links of the given files and folders to the + * destination. The current Thread is halted while the resources are copied + * using a WorkspaceModifyOperation. This method should be called from the + * UI Thread. + * + * @param fileNames + * names of the files to copy + * @param destination + * destination to which files will be copied + * @see WorkspaceModifyOperation + * @see Display#getThread() + * @see Thread#currentThread() + * @since 3.6 + */ + public void createVirtualFoldersAndLinks(final String[] fileNames, + IContainer destination) { + IFileStore[] stores = buildFileStores(fileNames); + if (stores == null) { + return; + } + + createVirtualFoldersAndLinks = true; + copyFileStores(destination, stores, true, null); + } + + /** + * Create links of the given files and folders to the destination. The + * current Thread is halted while the resources are copied using a + * WorkspaceModifyOperation. This method should be called from the UI + * Thread. + * + * @param fileNames + * names of the files to copy + * @param destination + * destination to which files will be copied + * @see WorkspaceModifyOperation + * @see Display#getThread() + * @see Thread#currentThread() + * @since 3.6 + */ + public void linkFiles(final String[] fileNames, IContainer destination) { + IFileStore[] stores = buildFileStores(fileNames); + if (stores == null) { + return; + } + + createLinks = true; + copyFileStores(destination, stores, true, null); + } + + /** + * Set whether or not virtual folders and links will be created under the destination + * container. + * + * @param value + * @since 3.6 + */ + public void setVirtualFolders(boolean value) { + createVirtualFoldersAndLinks = value; + } + + /** + * Set whether or not links will be created under the destination container. + * + * @param value + * @since 3.6 + */ + public void setCreateLinks(boolean value) { + createLinks = value; + } + + /** + * Set a variable relative to which the links are created + * + * @param variable + * @since 3.6 + */ + public void setRelativeVariable(String variable) { + relativeVariable = variable; + } + + /** + * Returns an AbstractWorkspaceOperation suitable for performing the move or + * copy operation that will move or copy the given resources to the given + * destination path. + * + * @param resources + * the resources to be moved or copied + * @param destinationPath + * the destination path to which the resources should be moved + * @return the operation that should be used to perform the move or cop + * @since 3.3 + */ + protected AbstractWorkspaceOperation getUndoableCopyOrMoveOperation( + IResource[] resources, IPath destinationPath) { + return new CopyResourcesOperation(resources, destinationPath, + IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyTitle); + + } +} diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusCopyFilesAndFoldersOperation.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusCopyFilesAndFoldersOperation.java new file mode 100644 index 00000000000..2706699f612 --- /dev/null +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusCopyFilesAndFoldersOperation.java @@ -0,0 +1,190 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.onefile.action; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.papyrus.infra.core.resource.ModelSet; +import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel; +import org.eclipse.papyrus.infra.emf.resource.DependencyManagementHelper; +import org.eclipse.papyrus.infra.emf.resource.MoveFileURIReplacementStrategy; +import org.eclipse.papyrus.infra.emf.resource.RestoreDependencyHelper; +import org.eclipse.papyrus.infra.emf.utils.ResourceUtils; +import org.eclipse.papyrus.infra.onefile.Activator; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.undo.CopyResourcesOperation; +import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; +import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; + + + +/** + * Implementation of Papyrus paste for model + */ +public class PapyrusCopyFilesAndFoldersOperation extends CopyFilesAndFoldersOperation { + + protected Map renameMapping = new HashMap(); + + protected IPath[] destinationPaths = null; + + public PapyrusCopyFilesAndFoldersOperation(Shell shell) { + super(shell); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.papyrus.infra.onefile.action.CopyFilesAndFoldersOperation#performCopyWithAutoRename(org.eclipse.core.resources.IResource[], + * org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + // perform rename only for .di + protected boolean performCopyWithAutoRename(IResource[] resources, IPath destination, IProgressMonitor monitor) { + IWorkspace workspace = resources[0].getWorkspace(); + destinationPaths = new IPath[resources.length]; + try { + String oldName = ""; //$NON-NLS-1$ + String newName = ""; //$NON-NLS-1$ + for(int i = 0; i < resources.length; i++) { + IResource source = resources[i]; + destinationPaths[i] = destination.append(source.getName()); + IPath relativSourcePath = source.getFullPath(); + String sourceFileName = relativSourcePath.removeFileExtension().lastSegment(); + if(sourceFileName.equals(oldName)) { + String fileExtension = relativSourcePath.getFileExtension(); + destinationPaths[i] = relativSourcePath.removeLastSegments(1).append(newName).addFileExtension(fileExtension); + } else { + oldName = sourceFileName; + if(workspace.getRoot().exists(destinationPaths[i]) && destinationPaths[i].getFileExtension().equals(DiModel.MODEL_FILE_EXTENSION)) { + destinationPaths[i] = getNewNameFor(destinationPaths[i], workspace); + newName = destinationPaths[i].removeFileExtension().lastSegment(); + } + renameMapping.put(oldName, newName); + } + + } + CopyResourcesOperation op = new CopyResourcesOperation(resources, destinationPaths, IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyTitle); + op.setModelProviderIds(getModelProviderIds()); + PlatformUI.getWorkbench().getOperationSupport().getOperationHistory().execute(op, monitor, WorkspaceUndoUtil.getUIInfoAdapter(messageShell)); + } catch (ExecutionException e) { + if(e.getCause() instanceof CoreException) { + recordError((CoreException)e.getCause()); + } else { + IDEWorkbenchPlugin.log(e.getMessage(), e); + displayError(e.getMessage()); + } + return false; + } + return true; + } + + + /* + * (non-Javadoc) + * + * @see org.eclipse.papyrus.infra.onefile.action.CopyFilesAndFoldersOperation#performCopy(org.eclipse.core.resources.IResource[], + * org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + // store path of created files + protected boolean performCopy(IResource[] resources, IPath destination, IProgressMonitor monitor) { + boolean performCopy = super.performCopy(resources, destination, monitor); + if(performCopy) { + destinationPaths = new IPath[resources.length]; + for(int i = 0; i < resources.length; i++) { + String name = resources[i].getName(); + destinationPaths[i] = destination.append(name); + } + } + return performCopy; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.papyrus.infra.onefile.action.CopyFilesAndFoldersOperation#copyResources(org.eclipse.core.resources.IResource[], + * org.eclipse.core.resources.IContainer) + */ + @Override + // restore internal and external link coherence + public IResource[] copyResources(IResource[] resources, IContainer destination) { + IResource[] copyResources = super.copyResources(resources, destination); + try { + ModelSet modelSet = new ModelSet(); + restoreInternalLinks(modelSet, resources, copyResources); + restoreExternalLinks(modelSet, resources, copyResources); + } catch (IOException e) { + Activator.log.error("It was not possible to restore broken links", e); //$NON-NLS-1$ + } + return copyResources; + } + + + /** + * Restore referenced URI following the pattern ; + * - if there is an accessible Resource use it + * - else search the resource in the source location of the copy + * @param resources + * @param copyResources + * @throws IOException + */ + protected void restoreExternalLinks(ModelSet modelSet, IResource[] resources, IResource[] copyResources) throws IOException { + for(int i = 0; i < destinationPaths.length; i++) { + IPath iPath = destinationPaths[i]; + URI uri = URI.createPlatformResourceURI(iPath.toString(), Boolean.TRUE); + Resource resource = modelSet.getResource(uri, Boolean.TRUE); + for(int j = 0; j < copyResources.length; j++) { + IPath targetPath = destinationPaths[j]; + IResource sourceResource = copyResources[j]; + URI targetURI = URI.createPlatformResourceURI(targetPath.toString(), true); + URI sourceURI = URI.createPlatformResourceURI(sourceResource.getFullPath().toString(), true); + DependencyManagementHelper.updateDependencies(sourceURI, targetURI, resource); + } + resource.save(ResourceUtils.getSaveOptions()); + } + } + + /** + * Restore links to maintain coherence in the 3 files: uml-notation-di + * @param resources + * @param copyResources + * @throws IOException + */ + protected void restoreInternalLinks(ModelSet modelSet, IResource[] resources, IResource[] copyResources) throws IOException { + for(int i = 0; i < destinationPaths.length; i++) { + IPath iPath = destinationPaths[i]; + MoveFileURIReplacementStrategy iURIReplacementStrategy = new MoveFileURIReplacementStrategy(new HashMap(), resources[i].getFullPath().removeLastSegments(1), iPath.removeLastSegments(1)); + RestoreDependencyHelper restoreDependencyHelper = new RestoreDependencyHelper(iURIReplacementStrategy); + URI uri = URI.createPlatformResourceURI(iPath.toString(), Boolean.TRUE); + Resource resource = modelSet.getResource(uri, Boolean.TRUE); + restoreDependencyHelper.restoreDependencies(resource); + resource.save(ResourceUtils.getSaveOptions()); + } + } + +} diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusModelPasteAction.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusModelPasteAction.java new file mode 100644 index 00000000000..9c78949bd58 --- /dev/null +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PapyrusModelPasteAction.java @@ -0,0 +1,50 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.onefile.action; + +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.widgets.Shell; + + +/** + * Action for pasting IPapyrusfiles + * + */ +public class PapyrusModelPasteAction extends PasteAction { + + + /** + * Action for pasting IPapyrusfiles + * + * @param shell + * @param clipboard + */ + public PapyrusModelPasteAction(Shell shell, Clipboard clipboard) { + super(shell, clipboard); + + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.papyrus.infra.onefile.action.PasteAction#createCopyFilesAndFolderOperation(org.eclipse.swt.widgets.Shell) + */ + @Override + protected CopyFilesAndFoldersOperation createCopyFilesAndFolderOperation(Shell shell) { + return new PapyrusCopyFilesAndFoldersOperation(shell); + } + + +} diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PasteAction.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PasteAction.java new file mode 100644 index 00000000000..c1676574755 --- /dev/null +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/action/PasteAction.java @@ -0,0 +1,266 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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.papyrus.infra.onefile.action; + + +import java.util.List; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.CopyProjectOperation; +import org.eclipse.ui.actions.SelectionListenerAction; +import org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorMessages; +import org.eclipse.ui.part.ResourceTransfer; + +/** + * Standard action for pasting resources on the clipboard to the selected resource's location. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ * + * @since 2.0 + */ +/*package*/class PasteAction extends SelectionListenerAction { + + /** + * The id of this action. + */ + public static final String ID = PlatformUI.PLUGIN_ID + ".PasteAction";//$NON-NLS-1$ + + /** + * The shell in which to show any dialogs. + */ + protected Shell shell; + + /** + * System clipboard + */ + protected Clipboard clipboard; + + /** + * Creates a new action. + * + * @param shell the shell for any dialogs + * @param clipboard the clipboard + */ + public PasteAction(Shell shell, Clipboard clipboard) { + super(WorkbenchNavigatorMessages.PasteAction_Past_); + Assert.isNotNull(shell); + Assert.isNotNull(clipboard); + this.shell = shell; + this.clipboard = clipboard; + setToolTipText(WorkbenchNavigatorMessages.PasteAction_Paste_selected_resource_s_); + setId(PasteAction.ID); + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, "HelpId"); //$NON-NLS-1$ + // TODO INavigatorHelpContextIds.PASTE_ACTION); + } + + /** + * Returns the actual target of the paste action. Returns null + * if no valid target is selected. + * + * @return the actual target of the paste action + */ + private IResource getTarget() { + List selectedResources = getSelectedResources(); + + for (IResource resource : selectedResources) { + if (resource instanceof IProject && !((IProject) resource).isOpen()) { + return null; + } + if (resource.getType() == IResource.FILE) { + resource = resource.getParent(); + } + if (resource != null) { + return resource; + } + } + return null; + } + + /** + * Returns whether any of the given resources are linked resources. + * + * @param resources resource to check for linked type. may be null + * @return true=one or more resources are linked. false=none of the + * resources are linked + */ + private boolean isLinked(IResource[] resources) { + for (int i = 0; i < resources.length; i++) { + if (resources[i].isLinked()) { + return true; + } + } + return false; + } + + /** + * Implementation of method defined on IAction. + */ + public void run() { + // try a resource transfer + ResourceTransfer resTransfer = ResourceTransfer.getInstance(); + IResource[] resourceData = (IResource[]) clipboard + .getContents(resTransfer); + + if (resourceData != null && resourceData.length > 0) { + if (resourceData[0].getType() == IResource.PROJECT) { + // enablement checks for all projects + for (int i = 0; i < resourceData.length; i++) { + CopyProjectOperation operation = new CopyProjectOperation( + this.shell); + operation.copyProject((IProject) resourceData[i]); + } + } else { + // enablement should ensure that we always have access to a container + IContainer container = getContainer(); + + CopyFilesAndFoldersOperation operation = createCopyFilesAndFolderOperation(this.shell); + operation.copyResources(resourceData, container); + } + return; + } + + // try a file transfer + FileTransfer fileTransfer = FileTransfer.getInstance(); + String[] fileData = (String[]) clipboard.getContents(fileTransfer); + + if (fileData != null) { + // enablement should ensure that we always have access to a container + IContainer container = getContainer(); + + CopyFilesAndFoldersOperation operation = createCopyFilesAndFolderOperation(this.shell); + operation.copyFiles(fileData, container); + } + } + + protected CopyFilesAndFoldersOperation createCopyFilesAndFolderOperation(Shell shell) { + return new CopyFilesAndFoldersOperation(shell); + } + + + + + /** + * Returns the container to hold the pasted resources. + */ + protected IContainer getContainer() { + List selectedResources = getSelectedResources(); + List selection = selectedResources; + if (selection.get(0) instanceof IFile) { + return ((IFile) selection.get(0)).getParent(); + } + return (IContainer) selection.get(0); + } + + /** + * The PasteAction implementation of this + * SelectionListenerAction method enables this action if + * a resource compatible with what is on the clipboard is selected. + * + * -Clipboard must have IResource or java.io.File + * -Projects can always be pasted if they are open + * -Workspace folder may not be copied into itself + * -Files and folders may be pasted to a single selected folder in open + * project or multiple selected files in the same folder + */ + protected boolean updateSelection(IStructuredSelection selection) { + if (!super.updateSelection(selection)) { + return false; + } + + final IResource[][] clipboardData = new IResource[1][]; + shell.getDisplay().syncExec(new Runnable() { + public void run() { + // clipboard must have resources or files + ResourceTransfer resTransfer = ResourceTransfer.getInstance(); + clipboardData[0] = (IResource[]) clipboard + .getContents(resTransfer); + } + }); + IResource[] resourceData = clipboardData[0]; + boolean isProjectRes = resourceData != null && resourceData.length > 0 + && resourceData[0].getType() == IResource.PROJECT; + + if (isProjectRes) { + for (int i = 0; i < resourceData.length; i++) { + // make sure all resource data are open projects + // can paste open projects regardless of selection + if (resourceData[i].getType() != IResource.PROJECT + || ((IProject) resourceData[i]).isOpen() == false) { + return false; + } + } + return true; + } + + if (getSelectedNonResources().size() > 0) { + return false; + } + + IResource targetResource = getTarget(); + // targetResource is null if no valid target is selected (e.g., open project) + // or selection is empty + if (targetResource == null) { + return false; + } + + // can paste files and folders to a single selection (file, folder, + // open project) or multiple file selection with the same parent + List selectedResources = getSelectedResources(); + if (selectedResources.size() > 1) { + for (IResource resource : selectedResources) { + if (resource.getType() != IResource.FILE) { + return false; + } + if (!targetResource.equals(resource.getParent())) { + return false; + } + } + } + if (resourceData != null) { + // linked resources can only be pasted into projects + if (isLinked(resourceData) + && targetResource.getType() != IResource.PROJECT + && targetResource.getType() != IResource.FOLDER) { + return false; + } + + if (targetResource.getType() == IResource.FOLDER) { + // don't try to copy folder to self + for (int i = 0; i < resourceData.length; i++) { + if (targetResource.equals(resourceData[i])) { + return false; + } + } + } + return true; + } + TransferData[] transfers = clipboard.getAvailableTypes(); + FileTransfer fileTransfer = FileTransfer.getInstance(); + for (int i = 0; i < transfers.length; i++) { + if (fileTransfer.isSupportedType(transfers[i])) { + return true; + } + } + return false; + } +} + diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/CopyToClipboardAction.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/CopyToClipboardAction.java new file mode 100644 index 00000000000..4aa834fe59d --- /dev/null +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/CopyToClipboardAction.java @@ -0,0 +1,70 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.onefile.providers; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.actions.CopyResourceAction; +import org.eclipse.ui.part.ResourceTransfer; + +/** + * Copy to the clipboard the payrus model as 3 IResource + * + */ +public class CopyToClipboardAction extends CopyResourceAction { + + protected Clipboard fClipboard; + + public CopyToClipboardAction(IShellProvider shellProvider) { + super(shellProvider); + } + + @Override + public void run() { + Display display = shellProvider.getShell().getDisplay(); + fClipboard= new Clipboard(display); + IStructuredSelection structuredSelection = getStructuredSelection(); + try { + copytoClipboardStructuredSelection(structuredSelection); + } finally { + fClipboard.dispose(); + } + } + + + /** + * Copy in the clipboard the selection + * @param selection + */ + public void copytoClipboardStructuredSelection(IStructuredSelection selection) { + Display display = Display.getCurrent(); + Clipboard clipboard = new Clipboard(display); + Object[] array = selection.toArray(); + IResource[] associatedResources = new IResource[array.length]; + for(int i = 0; i < associatedResources.length; i++) { + Object object = array[i]; + if (object instanceof IResource){ + associatedResources[i]= (IResource) object; + } + } + clipboard.setContents(new Object[] { associatedResources }, + new Transfer[] { ResourceTransfer.getInstance() }); + clipboard.dispose(); + } +} diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusEditActionProvider.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusEditActionProvider.java new file mode 100644 index 00000000000..adfd7f500f8 --- /dev/null +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusEditActionProvider.java @@ -0,0 +1,147 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.onefile.providers; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.papyrus.infra.onefile.action.PapyrusModelPasteAction; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchCommandConstants; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.ActionContext; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.navigator.CommonActionProvider; +import org.eclipse.ui.navigator.ICommonActionExtensionSite; +import org.eclipse.ui.navigator.ICommonMenuConstants; +import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite; + +/** + * Action provider for paste Papyrus models + */ +public class PapyrusEditActionProvider extends CommonActionProvider { + + private boolean fInViewPart = false; + + private ICommonViewerWorkbenchSite workbenchSite; + + private Action pasteAction; + + public PapyrusEditActionProvider() { + } + + @Override + public void fillActionBars(IActionBars actionBars) { + if(fInViewPart) { + actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction); + } + super.fillActionBars(actionBars); + } + + @Override + public void fillContextMenu(IMenuManager menu) { + super.fillContextMenu(menu); + appendToGroup(menu, pasteAction, ICommonMenuConstants.GROUP_EDIT); + } + + private void appendToGroup(IMenuManager menu, IAction action, String id) { + if(action != null && action.isEnabled()) { + menu.appendToGroup(id, action); + } + } + + @Override + public void init(ICommonActionExtensionSite site) { + if(site.getViewSite() instanceof ICommonViewerWorkbenchSite) { + workbenchSite = (ICommonViewerWorkbenchSite)site.getViewSite(); + } + if(workbenchSite != null) { + if(workbenchSite.getPart() != null && workbenchSite.getPart() instanceof IViewPart) { + fInViewPart = true; + } + makeActions(); + } + } + + private void makeActions() { + final IWorkbenchPartSite provider = workbenchSite.getSite(); + + Shell shell = provider.getShell(); + Clipboard clipboard = new Clipboard(shell.getDisplay()); + pasteAction = new PapyrusModelPasteAction(shell, clipboard) { + + //the helper is filtering Ipapyrus files + + @Override + protected List getSelectedResources() { + ActionContext context = getContext(); + List selectedResources = getSelectedResources(context); + return selectedResources; + } + + protected List getSelectedResources(ActionContext context) { + ISelection selec = context.getSelection(); + List resources = new ArrayList(); + + if(selec instanceof TreeSelection) { + TreeSelection tree = (TreeSelection)selec; + Object firstElement = tree.getFirstElement(); + if(firstElement instanceof IResource) { + resources.add((IResource)firstElement); + } + } + return resources; + } + }; + + makeAction(pasteAction, IWorkbenchCommandConstants.EDIT_PASTE, ISharedImages.IMG_TOOL_PASTE, ISharedImages.IMG_TOOL_PASTE_DISABLED); + } + + /** + * Create an action + * + * @param action + * @param id + * @param imgTool + * @param imgToolDisabled + */ + protected void makeAction(Action action, String id, String imgTool, String imgToolDisabled) { + if(action != null) { + ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); + if(id != null) { + action.setId(id); + action.setActionDefinitionId(id); + } + if(imgTool != null) { + action.setImageDescriptor(images.getImageDescriptor(imgTool)); + } + if(imgToolDisabled != null) { + action.setDisabledImageDescriptor(images.getImageDescriptor(imgToolDisabled)); + } + } + } + +} diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusModelActionProvider.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusModelActionProvider.java index 300d3957fcd..dcad5bf2550 100644 --- a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusModelActionProvider.java +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/providers/PapyrusModelActionProvider.java @@ -1,485 +1,479 @@ -/***************************************************************************** - * Copyright (c) 2011 Atos Origin Integration - CEA LIST. - * - * 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: - * Tristan Faure (Atos Origin Integration) tristan.faure@atosorigin.com - Initial API and implementation - * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - *****************************************************************************/ -package org.eclipse.papyrus.infra.onefile.providers; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.wizard.IWizardPage; -import org.eclipse.ltk.core.refactoring.RefactoringStatus; -import org.eclipse.ltk.internal.core.refactoring.resource.RenameResourceProcessor; -import org.eclipse.ltk.internal.ui.refactoring.RefactoringUIMessages; -import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; -import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; -import org.eclipse.ltk.ui.refactoring.resource.RenameResourceWizard; -import org.eclipse.papyrus.infra.onefile.Activator; -import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile; -import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IWorkbenchCommandConstants; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPartSite; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.WorkbenchException; -import org.eclipse.ui.actions.ActionContext; -import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.actions.DeleteResourceAction; -import org.eclipse.ui.actions.MoveResourceAction; -import org.eclipse.ui.actions.RefreshAction; -import org.eclipse.ui.actions.RenameResourceAction; -import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; -import org.eclipse.ui.navigator.CommonActionProvider; -import org.eclipse.ui.navigator.ICommonActionConstants; -import org.eclipse.ui.navigator.ICommonActionExtensionSite; -import org.eclipse.ui.navigator.ICommonMenuConstants; -import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite; -import org.eclipse.ui.part.FileEditorInput; - -/** - * Actions available through an {@link IPapyrusFile} - * - * @author tfaure - * - */ -@SuppressWarnings({ "restriction", "rawtypes" }) -public class PapyrusModelActionProvider extends CommonActionProvider { - - private boolean fInViewPart = false; - - private ICommonViewerWorkbenchSite workbenchSite; - - private Action openAction; - - private Action deleteAction; - - //Disabled. The CopyResourceAction may create inconsistent changes (i.e. it renames files without editing the links). - //We need to use a CopyToClipboard action instead - //@unused - private Action copyAction; - - private Action renameAction; - - private Action refreshAction; - - private Action moveAction; - - public PapyrusModelActionProvider() { - - } - - @Override - protected boolean filterAction(IAction action) { - return super.filterAction(action); - } - - @Override - public void fillActionBars(IActionBars actionBars) { - if(fInViewPart) { - actionBars.setGlobalActionHandler(ICommonActionConstants.OPEN, openAction); - actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction); - actionBars.setGlobalActionHandler(ActionFactory.RENAME.getId(), renameAction); - actionBars.setGlobalActionHandler(ActionFactory.MOVE.getId(), moveAction); - // actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction); - actionBars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction); - - } - super.fillActionBars(actionBars); - } - - @Override - public void fillContextMenu(IMenuManager menu) { - super.fillContextMenu(menu); - appendToGroup(menu, openAction, ICommonMenuConstants.GROUP_OPEN); - appendToGroup(menu, deleteAction, ICommonMenuConstants.GROUP_EDIT); - appendToGroup(menu, moveAction, ICommonMenuConstants.GROUP_EDIT); - // appendToGroup(menu, copyAction, ICommonMenuConstants.GROUP_EDIT); - appendToGroup(menu, renameAction, ICommonMenuConstants.GROUP_EDIT); - appendToGroup(menu, refreshAction, ICommonMenuConstants.GROUP_EDIT); - } - - private void appendToGroup(IMenuManager menu, IAction action, String id) { - if(action != null && action.isEnabled()) { - menu.appendToGroup(id, action); - } - } - - @Override - public void init(ICommonActionExtensionSite site) { - if(site.getViewSite() instanceof ICommonViewerWorkbenchSite) { - workbenchSite = (ICommonViewerWorkbenchSite)site.getViewSite(); - } - if(workbenchSite != null) { - if(workbenchSite.getPart() != null && workbenchSite.getPart() instanceof IViewPart) { - fInViewPart = true; - } - makeActions(); - } - } - - private void makeActions() { - final IWorkbenchPartSite provider = workbenchSite.getSite(); - final ActionHelper helper = new ActionHelper(); - openAction = new Action() { - - @Override - public void run() { - if(getIFile() != null) { - try { - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - page.openEditor(new FileEditorInput(getIFile()), "org.eclipse.papyrus.infra.core.papyrusEditor", true, IWorkbenchPage.MATCH_ID | IWorkbenchPage.MATCH_INPUT); - } catch (WorkbenchException e) { - Activator.log.error(e); - } - } - } - - public IFile getIFile() { - return helper.getIFile(getContext()); - } - - @Override - public boolean isEnabled() { - return getIFile() != null; - } - - @Override - public String getText() { - return IDEWorkbenchMessages.OpenFileAction_text; - } - }; - - deleteAction = new DeleteResourceAction(provider) { - - @Override - public boolean isEnabled() { - return getSelectedResources() != null && getSelectedResources().size() > 0 && OneFileUtils.isDi((IResource)getSelectedResources().get(0)); - - } - - @Override - public IStructuredSelection getStructuredSelection() { - return helper.getStructuredSelection(getContext()); - } - - @Override - protected List getSelectedResources() { - return helper.getSelectedResources(getContext()); - } - }; - - moveAction = new MoveResourceAction(provider) { - - @Override - public IStructuredSelection getStructuredSelection() { - return helper.getStructuredSelection(getContext()); - } - - @Override - protected List getSelectedResources() { - return helper.getSelectedResources(getContext()); - } - }; - - - //FIXME: The CopyResourceAction is actually a copy + paste - //It fails when the target folder is the same as the source folder (Because it needs to rename the copied files) - //Replace this action with a Copy to Clipboard action - // copyAction = new CopyResourceAction(provider) { - // - // @Override - // public IStructuredSelection getStructuredSelection() { - // return helper.getStructuredSelection(getContext()); - // } - // - // @Override - // protected List getSelectedResources() { - // return helper.getSelectedResources(getContext()); - // } - // }; - - renameAction = new OneFileRenameAction(provider); - - refreshAction = new RefreshAction(provider) { - - @Override - public void run() { - super.run(); - } - - }; - - makeAction(openAction, ICommonActionConstants.OPEN, ISharedImages.IMG_TOOL_COPY, ISharedImages.IMG_TOOL_COPY_DISABLED); - makeAction(deleteAction, IWorkbenchCommandConstants.EDIT_DELETE, ISharedImages.IMG_TOOL_DELETE, ISharedImages.IMG_TOOL_DELETE_DISABLED); - makeAction(moveAction, ActionFactory.MOVE.getId(), null, null); - // makeAction(copyAction, IWorkbenchCommandConstants.EDIT_CUT, ISharedImages.IMG_TOOL_CUT, ISharedImages.IMG_TOOL_CUT_DISABLED); - // makeAction(copyAction, IWorkbenchCommandConstants.EDIT_COPY, ISharedImages.IMG_TOOL_COPY, ISharedImages.IMG_TOOL_COPY_DISABLED); - makeAction(refreshAction, ActionFactory.REFRESH.getCommandId(), null, null); - } - - /** - * A Rename action applying to an IPapyrusFile - * The action will rename only the *.di file - * (Refactoring from infra.ui.resources will rename related files and fix URIs) - * - * The user won't be asked for a file extension (*.di will be kept) - * - * @author Camille Letavernier - */ - public class OneFileRenameAction extends RenameResourceAction { - - final ActionHelper helper = new ActionHelper(); - - private IWorkbenchPartSite partSiteProvider; - - public OneFileRenameAction(IWorkbenchPartSite provider) { - super(provider); - this.partSiteProvider = provider; - } - - private Shell getShell() { - return partSiteProvider.getShell(); - } - - @Override - public void run() { - - ISelection selection = partSiteProvider.getSelectionProvider().getSelection(); - - if(selection instanceof IStructuredSelection) { - IStructuredSelection structuredSelection = (IStructuredSelection)selection; - if(structuredSelection.size() != 1) { - return; - } - - Object selectedElement = structuredSelection.getFirstElement(); - if(selectedElement instanceof IPapyrusFile) { - IPapyrusFile modelToRename = (IPapyrusFile)selectedElement; - - RenamePapyrusModelWizard refactoringWizard = new RenamePapyrusModelWizard(modelToRename); - RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(refactoringWizard); - try { - op.run(getShell(), RefactoringUIMessages.RenameResourceHandler_title); - } catch (InterruptedException e) { - // do nothing - } - } - } - } - } - - private static class RenamePapyrusModelWizard extends RenameResourceWizard { - - private IPapyrusFile papyrusFile; - - public RenamePapyrusModelWizard(IPapyrusFile papyrusFile) { - super(papyrusFile.getMainFile()); - this.papyrusFile = papyrusFile; - } - - @Override - protected void addUserInputPages() { - RenameResourceProcessor processor = (RenameResourceProcessor)getRefactoring().getAdapter(RenameResourceProcessor.class); - addPage(new RenamePapyrusModelPage(processor)); - } - - private class RenamePapyrusModelPage extends UserInputWizardPage { - - private final RenameResourceProcessor fRefactoringProcessor; - - private Text fNameField; - - public RenamePapyrusModelPage(RenameResourceProcessor processor) { - super("RenamePapyrusModelRefactoringInputPage"); //$NON-NLS-1$ - fRefactoringProcessor = processor; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) - */ - public void createControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - composite.setFont(parent.getFont()); - - Label label = new Label(composite, SWT.NONE); - label.setText(RefactoringUIMessages.RenameResourceWizard_name_field_label); - label.setLayoutData(new GridData()); - - fNameField = new Text(composite, SWT.BORDER); - fNameField.setText(papyrusFile.getMainFile().getFullPath().removeFileExtension().lastSegment()); - fNameField.setFont(composite.getFont()); - fNameField.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false)); - fNameField.addModifyListener(new ModifyListener() { - - public void modifyText(ModifyEvent e) { - validatePage(); - } - }); - - fNameField.selectAll(); - setPageComplete(false); - setControl(composite); - } - - @Override - public void setVisible(boolean visible) { - if(visible) { - fNameField.setFocus(); - } - super.setVisible(visible); - } - - protected final void validatePage() { - String text = fNameField.getText() + ".di"; - RefactoringStatus status = fRefactoringProcessor.validateNewElementName(text); - setPageComplete(status); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ltk.ui.refactoring.UserInputWizardPage#performFinish() - */ - @Override - protected boolean performFinish() { - initializeRefactoring(); - storeSettings(); - return super.performFinish(); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ltk.ui.refactoring.UserInputWizardPage#getNextPage() - */ - @Override - public IWizardPage getNextPage() { - initializeRefactoring(); - storeSettings(); - return super.getNextPage(); - } - - private void storeSettings() { - } - - private void initializeRefactoring() { - fRefactoringProcessor.setNewResourceName(fNameField.getText() + ".di"); - } - } - } - - protected void makeAction(Action action, String id, String imgTool, String imgToolDisabled) { - if(action != null) { - ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); - if(id != null) { - action.setId(id); - action.setActionDefinitionId(id); - } - if(imgTool != null) { - action.setImageDescriptor(images.getImageDescriptor(imgTool)); - } - if(imgToolDisabled != null) { - action.setDisabledImageDescriptor(images.getImageDescriptor(imgToolDisabled)); - } - } - } - - public static class ActionHelper { - - public IStructuredSelection getStructuredSelection(ActionContext context) { - return new StructuredSelection(getSelectedResources(context)); - } - - public List getOneSelectedResources(ActionContext context) { - List selectedResources = getSelectedResources(context); - if(selectedResources.size() > 0) { - for(Iterator i = selectedResources.iterator(); i.hasNext();) { - Object o = i.next(); - if(o instanceof IFile) { - IFile file = (IFile)o; - if(!OneFileUtils.isDi(file)) { - i.remove(); - } - } - } - return selectedResources; - } - return Collections.EMPTY_LIST; - } - - public IStructuredSelection getOneStructuredSelection(ActionContext context) { - List selectedResources = getOneSelectedResources(context); - if(selectedResources.size() > 0) { - return new StructuredSelection(selectedResources); - } - return null; - } - - protected List getSelectedResources(ActionContext context) { - ISelection selec = context.getSelection(); - List resources = new ArrayList(); - if(selec instanceof IStructuredSelection) { - IStructuredSelection struc = (IStructuredSelection)selec; - for(Iterator i = struc.iterator(); i.hasNext();) { - Object o = i.next(); - if(o instanceof IPapyrusFile) { - IPapyrusFile papy = (IPapyrusFile)o; - resources.addAll(Arrays.asList(papy.getAssociatedResources())); - } - } - } - return resources; - } - - public IFile getIFile(ActionContext context) { - ISelection selec = context.getSelection(); - if(selec instanceof IStructuredSelection) { - IStructuredSelection struc = (IStructuredSelection)selec; - Object firstElement = struc.getFirstElement(); - if(firstElement instanceof IFile) { - IFile file = (IFile)firstElement; - return file; - } else if(firstElement instanceof IPapyrusFile) { - return ((IPapyrusFile)firstElement).getMainFile(); - } - } - return null; - } - } - -} +/***************************************************************************** + * Copyright (c) 2011 Atos Origin Integration - CEA LIST. + * + * 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: + * Tristan Faure (Atos Origin Integration) tristan.faure@atosorigin.com - Initial API and implementation + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr + * Benoit Maggi (CEA LIST) benoit.maggi@cea.fr - Add copy Action + *****************************************************************************/ +package org.eclipse.papyrus.infra.onefile.providers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.internal.core.refactoring.resource.RenameResourceProcessor; +import org.eclipse.ltk.internal.ui.refactoring.RefactoringUIMessages; +import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; +import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; +import org.eclipse.ltk.ui.refactoring.resource.RenameResourceWizard; +import org.eclipse.papyrus.infra.onefile.Activator; +import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile; +import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchCommandConstants; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.actions.ActionContext; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.actions.DeleteResourceAction; +import org.eclipse.ui.actions.MoveResourceAction; +import org.eclipse.ui.actions.RefreshAction; +import org.eclipse.ui.actions.RenameResourceAction; +import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; +import org.eclipse.ui.navigator.CommonActionProvider; +import org.eclipse.ui.navigator.ICommonActionConstants; +import org.eclipse.ui.navigator.ICommonActionExtensionSite; +import org.eclipse.ui.navigator.ICommonMenuConstants; +import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite; +import org.eclipse.ui.part.FileEditorInput; + +/** + * Actions available through an {@link IPapyrusFile} + * + * @author tfaure + * + */ +@SuppressWarnings({ "restriction", "rawtypes" }) +public class PapyrusModelActionProvider extends CommonActionProvider { + + private boolean fInViewPart = false; + + private ICommonViewerWorkbenchSite workbenchSite; + + private Action openAction; + + private Action deleteAction; + + private Action copyAction; + + private Action renameAction; + + private Action refreshAction; + + private Action moveAction; + + public PapyrusModelActionProvider() { + + } + + @Override + protected boolean filterAction(IAction action) { + return super.filterAction(action); + } + + @Override + public void fillActionBars(IActionBars actionBars) { + if(fInViewPart) { + actionBars.setGlobalActionHandler(ICommonActionConstants.OPEN, openAction); + actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction); + actionBars.setGlobalActionHandler(ActionFactory.RENAME.getId(), renameAction); + actionBars.setGlobalActionHandler(ActionFactory.MOVE.getId(), moveAction); + actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction); + actionBars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction); + } + super.fillActionBars(actionBars); + } + + @Override + public void fillContextMenu(IMenuManager menu) { + super.fillContextMenu(menu); + appendToGroup(menu, openAction, ICommonMenuConstants.GROUP_OPEN); + appendToGroup(menu, deleteAction, ICommonMenuConstants.GROUP_EDIT); + appendToGroup(menu, moveAction, ICommonMenuConstants.GROUP_EDIT); + appendToGroup(menu, copyAction, ICommonMenuConstants.GROUP_EDIT); + appendToGroup(menu, renameAction, ICommonMenuConstants.GROUP_EDIT); + appendToGroup(menu, refreshAction, ICommonMenuConstants.GROUP_EDIT); + } + + private void appendToGroup(IMenuManager menu, IAction action, String id) { + if(action != null && action.isEnabled()) { + menu.appendToGroup(id, action); + } + } + + @Override + public void init(ICommonActionExtensionSite site) { + if(site.getViewSite() instanceof ICommonViewerWorkbenchSite) { + workbenchSite = (ICommonViewerWorkbenchSite)site.getViewSite(); + } + if(workbenchSite != null) { + if(workbenchSite.getPart() != null && workbenchSite.getPart() instanceof IViewPart) { + fInViewPart = true; + } + makeActions(); + } + } + + private void makeActions() { + final IWorkbenchPartSite provider = workbenchSite.getSite(); + final ActionHelper helper = new ActionHelper(); + openAction = new Action() { + + @Override + public void run() { + if(getIFile() != null) { + try { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + page.openEditor(new FileEditorInput(getIFile()), "org.eclipse.papyrus.infra.core.papyrusEditor", true, IWorkbenchPage.MATCH_ID | IWorkbenchPage.MATCH_INPUT); + } catch (WorkbenchException e) { + Activator.log.error(e); + } + } + } + + public IFile getIFile() { + return helper.getIFile(getContext()); + } + + @Override + public boolean isEnabled() { + return getIFile() != null; + } + + @Override + public String getText() { + return IDEWorkbenchMessages.OpenFileAction_text; + } + }; + + deleteAction = new DeleteResourceAction(provider) { + + @Override + public boolean isEnabled() { + return getSelectedResources() != null && getSelectedResources().size() > 0 && OneFileUtils.isDi((IResource)getSelectedResources().get(0)); + + } + + @Override + public IStructuredSelection getStructuredSelection() { + return helper.getStructuredSelection(getContext()); + } + + @Override + protected List getSelectedResources() { + return helper.getSelectedResources(getContext()); + } + }; + + moveAction = new MoveResourceAction(provider) { + + @Override + public IStructuredSelection getStructuredSelection() { + return helper.getStructuredSelection(getContext()); + } + + @Override + protected List getSelectedResources() { + return helper.getSelectedResources(getContext()); + } + }; + + copyAction = new CopyToClipboardAction(provider){ + + @Override + public IStructuredSelection getStructuredSelection() { + return helper.getStructuredSelection(getContext()); + } + + @Override + protected List getSelectedResources() { + return helper.getSelectedResources(getContext()); + } + + }; + + renameAction = new OneFileRenameAction(provider); + + refreshAction = new RefreshAction(provider) { + + @Override + public void run() { + super.run(); + } + + }; + + makeAction(openAction, ICommonActionConstants.OPEN, ISharedImages.IMG_TOOL_COPY, ISharedImages.IMG_TOOL_COPY_DISABLED); + makeAction(deleteAction, IWorkbenchCommandConstants.EDIT_DELETE, ISharedImages.IMG_TOOL_DELETE, ISharedImages.IMG_TOOL_DELETE_DISABLED); + makeAction(moveAction, ActionFactory.MOVE.getId(), null, null); + makeAction(copyAction, IWorkbenchCommandConstants.EDIT_CUT, ISharedImages.IMG_TOOL_CUT, ISharedImages.IMG_TOOL_CUT_DISABLED); + makeAction(copyAction, IWorkbenchCommandConstants.EDIT_COPY, ISharedImages.IMG_TOOL_COPY, ISharedImages.IMG_TOOL_COPY_DISABLED); + makeAction(refreshAction, ActionFactory.REFRESH.getCommandId(), null, null); + } + + /** + * A Rename action applying to an IPapyrusFile + * The action will rename only the *.di file + * (Refactoring from infra.ui.resources will rename related files and fix URIs) + * + * The user won't be asked for a file extension (*.di will be kept) + * + * @author Camille Letavernier + */ + public class OneFileRenameAction extends RenameResourceAction { + + final ActionHelper helper = new ActionHelper(); + + private IWorkbenchPartSite partSiteProvider; + + public OneFileRenameAction(IWorkbenchPartSite provider) { + super(provider); + this.partSiteProvider = provider; + } + + private Shell getShell() { + return partSiteProvider.getShell(); + } + + @Override + public void run() { + + ISelection selection = partSiteProvider.getSelectionProvider().getSelection(); + + if(selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = (IStructuredSelection)selection; + if(structuredSelection.size() != 1) { + return; + } + + Object selectedElement = structuredSelection.getFirstElement(); + if(selectedElement instanceof IPapyrusFile) { + IPapyrusFile modelToRename = (IPapyrusFile)selectedElement; + + RenamePapyrusModelWizard refactoringWizard = new RenamePapyrusModelWizard(modelToRename); + RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(refactoringWizard); + try { + op.run(getShell(), RefactoringUIMessages.RenameResourceHandler_title); + } catch (InterruptedException e) { + // do nothing + } + } + } + } + } + + private static class RenamePapyrusModelWizard extends RenameResourceWizard { + + private IPapyrusFile papyrusFile; + + public RenamePapyrusModelWizard(IPapyrusFile papyrusFile) { + super(papyrusFile.getMainFile()); + this.papyrusFile = papyrusFile; + } + + @Override + protected void addUserInputPages() { + RenameResourceProcessor processor = (RenameResourceProcessor)getRefactoring().getAdapter(RenameResourceProcessor.class); + addPage(new RenamePapyrusModelPage(processor)); + } + + private class RenamePapyrusModelPage extends UserInputWizardPage { + + private final RenameResourceProcessor fRefactoringProcessor; + + private Text fNameField; + + public RenamePapyrusModelPage(RenameResourceProcessor processor) { + super("RenamePapyrusModelRefactoringInputPage"); //$NON-NLS-1$ + fRefactoringProcessor = processor; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + composite.setFont(parent.getFont()); + + Label label = new Label(composite, SWT.NONE); + label.setText(RefactoringUIMessages.RenameResourceWizard_name_field_label); + label.setLayoutData(new GridData()); + + fNameField = new Text(composite, SWT.BORDER); + fNameField.setText(papyrusFile.getMainFile().getFullPath().removeFileExtension().lastSegment()); + fNameField.setFont(composite.getFont()); + fNameField.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false)); + fNameField.addModifyListener(new ModifyListener() { + + public void modifyText(ModifyEvent e) { + validatePage(); + } + }); + + fNameField.selectAll(); + setPageComplete(false); + setControl(composite); + } + + @Override + public void setVisible(boolean visible) { + if(visible) { + fNameField.setFocus(); + } + super.setVisible(visible); + } + + protected final void validatePage() { + String text = fNameField.getText() + ".di"; + RefactoringStatus status = fRefactoringProcessor.validateNewElementName(text); + setPageComplete(status); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ltk.ui.refactoring.UserInputWizardPage#performFinish() + */ + @Override + protected boolean performFinish() { + initializeRefactoring(); + storeSettings(); + return super.performFinish(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ltk.ui.refactoring.UserInputWizardPage#getNextPage() + */ + @Override + public IWizardPage getNextPage() { + initializeRefactoring(); + storeSettings(); + return super.getNextPage(); + } + + private void storeSettings() { + } + + private void initializeRefactoring() { + fRefactoringProcessor.setNewResourceName(fNameField.getText() + ".di"); + } + } + } + + protected void makeAction(Action action, String id, String imgTool, String imgToolDisabled) { + if(action != null) { + ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); + if(id != null) { + action.setId(id); + action.setActionDefinitionId(id); + } + if(imgTool != null) { + action.setImageDescriptor(images.getImageDescriptor(imgTool)); + } + if(imgToolDisabled != null) { + action.setDisabledImageDescriptor(images.getImageDescriptor(imgToolDisabled)); + } + } + } + + public static class ActionHelper { + + public IStructuredSelection getStructuredSelection(ActionContext context) { + return new StructuredSelection(getSelectedResources(context)); + } + + public List getOneSelectedResources(ActionContext context) { + List selectedResources = getSelectedResources(context); + if(selectedResources.size() > 0) { + for(Iterator i = selectedResources.iterator(); i.hasNext();) { + Object o = i.next(); + if(o instanceof IFile) { + IFile file = (IFile)o; + if(!OneFileUtils.isDi(file)) { + i.remove(); + } + } + } + return selectedResources; + } + return Collections.EMPTY_LIST; + } + + public IStructuredSelection getOneStructuredSelection(ActionContext context) { + List selectedResources = getOneSelectedResources(context); + if(selectedResources.size() > 0) { + return new StructuredSelection(selectedResources); + } + return null; + } + + protected List getSelectedResources(ActionContext context) { + ISelection selec = context.getSelection(); + List resources = new ArrayList(); + if(selec instanceof IStructuredSelection) { + IStructuredSelection struc = (IStructuredSelection)selec; + for(Iterator i = struc.iterator(); i.hasNext();) { + Object o = i.next(); + if(o instanceof IPapyrusFile) { + IPapyrusFile papy = (IPapyrusFile)o; + resources.addAll(Arrays.asList(papy.getAssociatedResources())); + } + } + } + return resources; + } + + public IFile getIFile(ActionContext context) { + ISelection selec = context.getSelection(); + if(selec instanceof IStructuredSelection) { + IStructuredSelection struc = (IStructuredSelection)selec; + Object firstElement = struc.getFirstElement(); + if(firstElement instanceof IFile) { + IFile file = (IFile)firstElement; + return file; + } else if(firstElement instanceof IPapyrusFile) { + return ((IPapyrusFile)firstElement).getMainFile(); + } + } + return null; + } + } + +} diff --git a/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/testers/PapyrusClipboardTester.java b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/testers/PapyrusClipboardTester.java new file mode 100644 index 00000000000..fd78671c97d --- /dev/null +++ b/plugins/infra/org.eclipse.papyrus.infra.onefile/src/org/eclipse/papyrus/infra/onefile/testers/PapyrusClipboardTester.java @@ -0,0 +1,77 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * + * 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: + * Benoit Maggi benoit.maggi@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.onefile.testers; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.resources.IResource; +import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.part.ResourceTransfer; + +/** + * Papyrus tester on clipboard contents + * containsPapyrusModel : test if there is a papyrus model + */ +public class PapyrusClipboardTester extends PropertyTester { + + public static final String CLIPBOARD_CONTAINS_PAPYRUS_MODEL = "containsPapyrusModel"; //$NON-NLS-1$ + + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { + if(receiver instanceof org.eclipse.swt.widgets.Shell) { + Clipboard clipboard = new Clipboard(Display.getDefault()); + if(CLIPBOARD_CONTAINS_PAPYRUS_MODEL.equals(property)) { + boolean answer = containsPapyrusModel(clipboard); + return new Boolean(answer).equals(expectedValue); + } + } + return false; + } + + + /** + * Test if the clipboard contains some Papyrus model (that is with a di extension) + * @param clipboard + * @return + */ + protected boolean containsPapyrusModel(Clipboard clipboard) { + if (clipboard != null) { + String[] filePaths =(String[]) clipboard.getContents(FileTransfer.getInstance()); + if (filePaths != null){ + if (filePaths.length >0 ) { + for(int i = 0; i < filePaths.length; i++) { + if (filePaths[i].endsWith("."+DiModel.MODEL_FILE_EXTENSION)){ //$NON-NLS-1$ + return true; + } + } + } + } else { + IResource[] resources = (IResource[]) clipboard.getContents(ResourceTransfer.getInstance()); + if (resources != null){ + if (resources.length >0 ) { + for(int i = 0; i < resources.length; i++) { + if (DiModel.MODEL_FILE_EXTENSION.equals(resources[i].getFileExtension())){ + return true; + } + } + } + } + } + } + return false; + } + +} -- cgit v1.2.3