/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.ui.actions; 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.CoreException; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.dnd.FileTransfer; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.CopyProjectOperation; import org.eclipse.ui.actions.SelectionListenerAction; import org.eclipse.ui.part.ResourceTransfer; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.core.workspace.ModelWorkspaceException; import org.teiid.designer.core.workspace.ModelWorkspaceManager; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.common.UiConstants; import org.teiid.designer.ui.common.actions.AbstractAction; import org.teiid.designer.ui.common.actions.ActionService; import org.teiid.designer.ui.common.eventsupport.SelectionUtilities; import org.teiid.designer.ui.common.util.SystemClipboardUtilities; import org.teiid.designer.ui.common.util.UiUtil; import org.teiid.designer.ui.editors.ModelEditorManager; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * PasteInResourceAction * * @since 8.0 */ public class PasteInResourceAction extends ModelObjectAction implements UiConstants { /** Delegate for EObject and model paste. */ private AbstractAction eObjDelegateAction; /** Delegate for resource paste. */ private ResourcePasteAction resourceDelegateAction; /** * Constructs a <code>DeleteResourceAction</code>. */ public PasteInResourceAction() { super(UiPlugin.getDefault()); resourceDelegateAction = new ResourcePasteAction(); // get EObject paste action ActionService actionService = UiPlugin.getDefault().getActionService(UiUtil.getWorkbenchWindowOnlyIfUiThread().getActivePage()); try { eObjDelegateAction = (AbstractAction)actionService.getAction(PasteAction.class.getName()); setHoverImageDescriptor(eObjDelegateAction.getHoverImageDescriptor()); setImageDescriptor(eObjDelegateAction.getImageDescriptor()); setDisabledImageDescriptor(eObjDelegateAction.getDisabledImageDescriptor()); setText(eObjDelegateAction.getText()); setToolTipText(eObjDelegateAction.getToolTipText()); } catch (CoreException theException) { Util.log(theException); // create an always disabled action eObjDelegateAction = new AbstractAction(UiPlugin.getDefault()) { @Override protected void doRun() { } }; eObjDelegateAction.setEnabled(false); } } /** * @see org.teiid.designer.ui.common.actions.AbstractAction#doRun() */ @Override protected void doRun() { if (this.eObjDelegateAction.isEnabled()) { this.eObjDelegateAction.run(); } else if (this.resourceDelegateAction.isEnabled()) { this.resourceDelegateAction.run(); } setEnabledState(); } Shell getShell() { Shell shell = null; if( getPart() != null && getPart().getSite() != null ) { shell = getPart().getSite().getShell(); } else { shell = UiUtil.getWorkbenchShellOnlyIfUiThread(); } return shell; } /** * Check if resource already exists in workspace * * @param theResource * @return * @since 5.0 */ private boolean resourceAlreadyInWorkspace( IResource theResource ) { boolean result = false; try { result = ModelWorkspaceManager.getModelWorkspaceManager().findModelWorkspaceItem(theResource) != null; } catch (ModelWorkspaceException theException) { Util.log(theException); } return result; } private boolean isValidPasteResource( IResource theResource ) { boolean result = true; if (theResource.getProject().isOpen()) { if (theResource instanceof IFile) { if (!ModelUtilities.isModelFile(theResource) && !ModelUtilities.isVdbFile(theResource)) result = true; else if (ModelUtilities.isVdbFile(theResource)) { // Allow if in model project file container result = selectedIsInModelProject(); } } else if (theResource instanceof IContainer) { // make sure no models contained try { IResource[] members = ((IContainer)theResource).members(); if (members.length > 0) { for (int i = 0; i < members.length; i++) { result = isValidPasteResource(members[i]); if (!result) { break; } } } } catch (CoreException theException) { result = false; } } else { result = false; } } else { // can't paste into a closed project result = false; } return result; } /** * This method is called in the run() method of AbstractAction to give the actions a hook into canceling the run at the last * minute. This overrides the AbstractAction preRun() method. */ @Override protected boolean preRun() { boolean result = true; if (this.eObjDelegateAction.isEnabled()) { // result = super.preRun(); result = activateEditor(); } return result; } /** * @see org.teiid.designer.ui.actions.ModelObjectAction#requiresEditorForRun() */ @Override protected boolean requiresEditorForRun() { return true; } /** * @see org.teiid.designer.ui.common.actions.AbstractAction#selectionChanged(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) */ @Override public void selectionChanged( IWorkbenchPart thePart, ISelection theSelection ) { super.selectionChanged(thePart, theSelection); // make the delegate actions aware of the new selection and set enablement IStructuredSelection selection = null; if (theSelection instanceof IStructuredSelection) { selection = (IStructuredSelection)theSelection; } else { selection = StructuredSelection.EMPTY; } // pass selection to delegates. don't need to for the EObject actions since it was retrieved // from the action service which automatically hooks up the action to receive selection events // this.eObjDelegateAction.selectionChanged(thePart, selection); this.resourceDelegateAction.selectionChanged(selection); setEnabledState(); } /** * @see org.teiid.designer.ui.common.actions.AbstractAction#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ @Override public void selectionChanged( SelectionChangedEvent theEvent ) { super.selectionChanged(theEvent); // pass selection to delegates this.eObjDelegateAction.selectionChanged(theEvent); this.resourceDelegateAction.selectionChanged(theEvent); setEnabledState(); } private boolean selectedIsInModelProject() { boolean result = false; IResource targetResource = this.resourceDelegateAction.getContainer(); // targetResource is null if no valid target is selected or // selection is empty if (targetResource != null) result = ModelUtilities.isModelProjectResource(targetResource); return result; } private void setEnabledState() { boolean result = this.eObjDelegateAction.isEnabled(); if (!result && this.resourceDelegateAction.isEnabled()) { // make sure no models are being copied IResource[] resources = (IResource[])SystemClipboardUtilities.getContents(ResourceTransfer.getInstance()); if ((resources != null) && (resources.length > 0)) { result = true; for (int i = 0; i < resources.length; i++) { if (resourceAlreadyInWorkspace(resources[i]) || !isValidPasteResource(resources[i])) { result = false; break; } } } } setEnabled(result); } private boolean activateEditor() { if (requiresEditorForRun()) { List allSelectedEObjects = SelectionUtilities.getSelectedEObjects(getSelection()); if (allSelectedEObjects != null && !allSelectedEObjects.isEmpty()) { EObject eObject = (EObject)allSelectedEObjects.get(0); ModelResource mr = ModelUtilities.getModelResourceForModelObject(eObject); if (mr != null) { ModelEditorManager.activate(mr, true); } } else { // Check selection for resource if (SelectionUtilities.isSingleSelection(getSelection())) { Object selectedObject = SelectionUtilities.getSelectedObject(getSelection()); if (selectedObject instanceof IFile && ModelUtilities.isModelFile((IFile)selectedObject)) { ModelResource mr = null; try { mr = ModelUtil.getModelResource((IFile)selectedObject, false); } catch (ModelWorkspaceException err) { Util.log(err); } finally { if (mr != null) { ModelEditorManager.activate(mr, true); } } } } } } return true; } /** * Handles resource paste. Majority of code copied from org.eclipse.ui.views.navigator.PasteAction. */ private class ResourcePasteAction extends SelectionListenerAction { public ResourcePasteAction() { // text is not used since action is never installed in any menu super("not used"); //$NON-NLS-1$ } IContainer getContainer() { List selection = getSelectedResources(); // defect 16350 - prevent ArrayIndexOutOfBoundsExceptions if (selection == null || selection.isEmpty()) { return null; } // endif if (selection.get(0) instanceof IFile) { return ((IFile)selection.get(0)).getParent(); } return (IContainer)selection.get(0); } private IResource getTarget() { List selectedResources = getSelectedResources(); for (int i = 0; i < selectedResources.size(); i++) { IResource resource = (IResource)selectedResources.get(i); if (resource instanceof IProject && !((IProject)resource).isOpen()) return null; if (resource.getType() == IResource.FILE) resource = resource.getParent(); if (resource != null) return resource; } return null; } private boolean isLinked( IResource[] resources ) { if (resources != null) { for (int i = 0; i < resources.length; i++) { if (resources[i].isLinked()) { return true; } } } return false; } /** * @see org.eclipse.jface.action.Action#run() */ @Override public void run() { // try a resource transfer ResourceTransfer resTransfer = ResourceTransfer.getInstance(); IResource[] resourceData = (IResource[])SystemClipboardUtilities.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(getShell()); operation.copyProject((IProject)resourceData[i]); } } else { // enablement should ensure that we always have access to a container IContainer container = getContainer(); CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation(getShell()); operation.copyResources(resourceData, container); } return; } // try a file transfer FileTransfer fileTransfer = FileTransfer.getInstance(); String[] fileData = (String[])SystemClipboardUtilities.getContents(fileTransfer); if (fileData != null) { // enablement should ensure that we always have access to a container IContainer container = getContainer(); CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation(getShell()); operation.copyFiles(fileData, container); } } /** * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) */ @Override protected boolean updateSelection( IStructuredSelection selection ) { /* * Only update selection if we have a visible workbench window as only then will * the system clipboard be ready. */ IWorkbench workbench = PlatformUI.getWorkbench(); if (workbench == null) return false; IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow(); if (workbenchWindow == null) return false; if (workbenchWindow.getShell() == null || ! workbenchWindow.getShell().isVisible()) return false; /* * If selection is empty then bale out since the paste has nothing to * aim at anyway */ if (selection == null || selection.isEmpty()) return false; try { // clipboard must have resources or files ResourceTransfer resTransfer = ResourceTransfer.getInstance(); IResource[] resourceData = (IResource[])SystemClipboardUtilities.getContents(resTransfer); FileTransfer fileTransfer = FileTransfer.getInstance(); String[] fileData = (String[])SystemClipboardUtilities.getContents(fileTransfer); if (resourceData == null && fileData == null) return false; // can paste open projects regardless of selection boolean isProjectRes = resourceData != null && resourceData.length > 0 && resourceData[0].getType() == IResource.PROJECT; if (isProjectRes) { for (int i = 1; i < resourceData.length; i++) { // make sure all resource data are projects if (resourceData[i].getType() != IResource.PROJECT) return false; } return true; } // can paste files and folders to a single selection (project must be open) // or multiple file selection with the same parent if (getSelectedNonResources().size() > 0) return false; List selectedResources = getSelectedResources(); IResource targetResource = getTarget(); // targetResource is null if no valid target is selected or // selection is empty if (targetResource == null) return false; // linked resources can only be pasted into projects if (isLinked(resourceData) && targetResource.getType() != IResource.PROJECT) return false; if (selectedResources.size() > 1) { // if more than one resource is selected the selection has // to be all files with the same parent for (int i = 0; i < selectedResources.size(); i++) { IResource resource = (IResource)selectedResources.get(i); if (resource.getType() != IResource.FILE) return false; if (!targetResource.equals(resource.getParent())) return false; } } if (targetResource.getType() == IResource.FOLDER && resourceData != null) { // 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; } catch (Exception e) { Util.log(e); return false; } } } }