/**
* Copyright (c) 2006-2012 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 - Initial API and implementation
*/
package org.eclipse.emf.edit.ui.action;
import java.util.Collection;
import java.util.List;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandWrapper;
import org.eclipse.emf.common.ui.dialogs.ResourceDialog;
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.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.ui.EMFEditUIPlugin;
/**
* A control action moves a contained object into a new resource or restores it to its containers' resource.
* It is implemented by creating a {@link AddCommand} or {@link RemoveCommand}.
* @since 2.2.0
*/
public class ControlAction extends CommandActionHandler
{
protected IStructuredSelection selection = null;
protected EObject eObject = null;
public ControlAction(EditingDomain domain)
{
super(domain, EMFEditUIPlugin.INSTANCE.getString("_UI_Control_menu_item"));
}
public ControlAction()
{
this(null);
}
// We can create the RemoveCommand for an uncontrol, but we must defer creating an AddCommand
// to control until run(), when the user specifies a target resource.
//
@Override
public boolean updateSelection(IStructuredSelection selection)
{
this.selection = selection;
if (selection.size() != 1) return false;
Object object = AdapterFactoryEditingDomain.unwrap(selection.getFirstElement());
boolean result = domain.isControllable(object);
eObject = result ? (EObject)object : null;
if (!AdapterFactoryEditingDomain.isControlled(object))
{
setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Control_menu_item"));
setDescription("_UI_Control_menu_item_description");
command = null;
}
else
{
setText(EMFEditUIPlugin.INSTANCE.getString("_UI_Uncontrol_menu_item"));
setDescription("_UI_Uncontrol_menu_item_description");
if (result)
{
command = new RemoveCommand(domain, eObject.eResource().getContents(), eObject);
command = new SelfAffectingCommand(EMFEditUIPlugin.INSTANCE.getString("_UI_UncontrolCommand_label"), command);
result = command.canExecute();
}
}
return result;
}
protected class SelfAffectingCommand extends CommandWrapper
{
SelfAffectingCommand(String label, Command command)
{
super(label, command);
}
@Override
public Collection<?> getResult()
{
return selection.toList();
}
@Override
public Collection<?> getAffectedObjects()
{
return selection.toList();
}
}
// For the control case, we need a dialog to ask for the URI and obtain the resource, then we create the command.
//
@Override
public void run()
{
if (command == null)
{
if (eObject == null) return;
Resource resource = getResource();
if (resource == null) return;
command = new AddCommand(domain, resource.getContents(), eObject);
command = new SelfAffectingCommand(EMFEditUIPlugin.INSTANCE.getString("_UI_ControlCommand_label"), command);
}
// Ensure that all proxies are resolved so that references into the controlled object will be saved to reference the new resource.
//
EcoreUtil.resolveAll(domain.getResourceSet());
super.run();
}
protected Resource getResource()
{
ControlResourceDialog dialog = new ControlResourceDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), domain, eObject.eResource());
dialog.open();
return dialog.getResource();
}
public void setActiveWorkbenchPart(IWorkbenchPart workbenchPart)
{
if (workbenchPart instanceof IEditingDomainProvider)
{
domain = ((IEditingDomainProvider)workbenchPart).getEditingDomain();
}
}
/**
* A save-type {@link ResourceDialog resource dialog} that attempts to create the specified resource and
* load it, if it already exists.
*/
protected static class ControlResourceDialog extends ResourceDialog
{
protected EditingDomain domain;
protected Resource resource;
protected Resource currentResource;
public ControlResourceDialog(Shell parent, EditingDomain domain, Resource currentResource)
{
super(parent, EMFEditUIPlugin.INSTANCE.getString("_UI_ControlDialog_title"), SWT.SAVE, getContextURI(domain));
this.domain = domain;
this.currentResource = currentResource;
}
private static URI getContextURI(EditingDomain domain)
{
if (domain != null)
{
List<Resource> resources = domain.getResourceSet().getResources();
if (!resources.isEmpty())
{
return resources.get(0).getURI();
}
}
return null;
}
/**
* Creates and, if it already exists, loads the specified resource. This implementation verifies that a
* resource can be opened for that URI, that the resource is not the object's current container, and that
* it is not read-only in the editing domain. If there is an existing resource with that URI, it prompts
* before overriding or adding to it.
*/
@Override
protected boolean processResources()
{
List<URI> uris = getURIs();
if (uris.isEmpty()) return false;
URI uri = uris.get(0);
ResourceSet resourceSet = domain.getResourceSet();
Resource resource = resourceSet.getResource(uri, false);
boolean resourceInSet = resource != null;
if (resource == currentResource)
{
MessageDialog.openError(getShell(), EMFEditUIPlugin.INSTANCE.getString("_UI_InvalidURI_label"), EMFEditUIPlugin.INSTANCE.getString("_WARN_AlreadyInResource"));
return false;
}
if (resource != null && domain.isReadOnly(resource))
{
MessageDialog.openError(getShell(), EMFEditUIPlugin.INSTANCE.getString("_UI_InvalidURI_label"), EMFEditUIPlugin.INSTANCE.getString("_WARN_ReadOnlyResource"));
return false;
}
boolean resourceExists = resourceSet.getURIConverter().exists(uri, null);
boolean resourceBad = false;
if (!resourceInSet)
{
resource = resourceSet.createResource(uri);
if (resource == null)
{
MessageDialog.openError(getShell(), EMFEditUIPlugin.INSTANCE.getString("_UI_InvalidURI_label"), EMFEditUIPlugin.INSTANCE.getString("_WARN_CannotCreateResource"));
return false;
}
if (resourceExists)
{
try
{
resource = resourceSet.getResource(uri, true);
}
catch (RuntimeException exception)
{
EMFEditUIPlugin.INSTANCE.log(exception);
resourceBad = resource.getContents().isEmpty();
}
}
}
boolean result = true;
if (resourceBad)
{
result = MessageDialog.openQuestion(getShell(), EMFEditUIPlugin.INSTANCE.getString("_UI_ExistingResource_label"), EMFEditUIPlugin.INSTANCE.getString("_WARN_ReplaceResource"));
}
else if (resourceExists)
{
result = MessageDialog.openQuestion(getShell(), EMFEditUIPlugin.INSTANCE.getString("_UI_ExistingResource_label"), EMFEditUIPlugin.INSTANCE.getString("_WARN_AddToResource"));
}
if (!result && !resourceInSet && resource != null)
{
resource.unload();
resourceSet.getResources().remove(resource);
}
else
{
this.resource = resource;
}
return result;
}
public Resource getResource()
{
return resource;
}
}
}