blob: 27d92a0666d1d9639494ac0058515acc50e9a65b [file] [log] [blame]
/*
* Copyright (c) 2005, 2013 IBM Corporation, CEA, 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
* Kenn Hussey - 286329
* Christian W. Damus (CEA) - 326915, 286444
*
*/
package org.eclipse.uml2.uml.editor.actions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.IdentityCommand;
import org.eclipse.emf.common.command.UnexecutableCommand;
import org.eclipse.emf.common.ui.dialogs.ResourceDialog;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ContentHandler;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.ui.EMFEditUIPlugin;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
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.uml2.uml.Element;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.editor.UMLEditorPlugin;
import org.eclipse.uml2.uml.editor.dialogs.AbstractChoicesDialogDelegate;
import org.eclipse.uml2.uml.editor.dialogs.ChoicesDialog;
import org.eclipse.uml2.uml.util.UMLUtil.StereotypeApplicationHelper;
public class ApplyStereotypeAction
extends UMLCommandAction {
public ApplyStereotypeAction() {
super();
}
@Override
protected Command createActionCommand(EditingDomain editingDomain,
Collection<?> collection) {
if (collection.size() == 1
&& collection.iterator().next() instanceof Element) {
return IdentityCommand.INSTANCE;
}
return UnexecutableCommand.INSTANCE;
}
@Override
public void run(IAction action) {
if (command != UnexecutableCommand.INSTANCE) {
final Element element = (Element) collection.iterator().next();
final List<Stereotype> choiceOfValues = new ArrayList<Stereotype>();
for (Stereotype applicableStereotype : element
.getApplicableStereotypes()) {
if (!element.isStereotypeApplied(applicableStereotype)) {
choiceOfValues.add(applicableStereotype);
}
}
Collections.<Stereotype> sort(choiceOfValues,
new TextComparator<Stereotype>());
String label = UMLEditorPlugin.INSTANCE
.getString("_UI_ApplyStereotypeActionCommand_label"); //$NON-NLS-1$
final ChoicesDelegate chooserDelegate = new ChoicesDelegate(
element, choiceOfValues);
final ChoicesDialog<Stereotype> dialog = new ChoicesDialog<Stereotype>(
workbenchPart.getSite().getShell(), element, label,
chooserDelegate);
dialog.open();
if ((dialog.getReturnCode() == Window.OK)
&& !dialog.getResult().isEmpty()) {
editingDomain.getCommandStack().execute(
new RefreshingChangeCommand(editingDomain, new Runnable() {
public void run() {
final StereotypeApplicationHelper helper = chooserDelegate
.getSelectedResource() == null
? null
: new StereotypeApplicationHelper() {
@Override
protected EList<EObject> getContainmentList(
Element element, EClass definition) {
return chooserDelegate
.getSelectedResource()
.getContents();
}
};
for (Stereotype result : dialog.getResult()) {
EObject newApplication = element
.applyStereotype(result);
if (helper != null) {
helper.addToContainmentList(element,
newApplication);
}
}
}
}, label));
}
}
}
//
// Nested types
//
private final class ChoicesDelegate
extends AbstractChoicesDialogDelegate<Stereotype> {
private ComboViewer resourceCombo;
private EList<Object> resourcesList;
private final Element element;
private final Collection<Stereotype> applicableStereotypes;
private Resource selectedResource;
ChoicesDelegate(Element element,
Collection<Stereotype> applicableStereotypes) {
super(Stereotype.class);
this.element = element;
this.applicableStereotypes = applicableStereotypes;
}
public Resource getSelectedResource() {
Resource result = selectedResource;
// don't return the default resource, so that we won't mess with new
// stereotype applications
if (result == element.eResource()) {
result = null;
}
return result;
}
@Override
public String getChoicesLabelText() {
return UMLEditorPlugin.INSTANCE
.getString("_UI_ApplicableStereotypes_label"); //$NON-NLS-1$
}
@Override
public String getValuesLabelText() {
return UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesToApply_label"); //$NON-NLS-1$
}
@Override
public String getAddButtonText() {
return UMLEditorPlugin.INSTANCE.getString("_UI_Apply_label"); //$NON-NLS-1$
}
@Override
public String getRemoveButtonText() {
return UMLEditorPlugin.INSTANCE.getString("_UI_Unapply_label"); //$NON-NLS-1$
}
public ILabelProvider getLabelProvider() {
return ApplyStereotypeAction.this.getLabelProvider();
}
public Collection<Stereotype> getChoiceOfValues() {
return applicableStereotypes;
}
@Override
public void createAdditionalControls(Composite parent) {
Composite contents = new Composite(parent, SWT.NONE);
contents.setLayout(new GridLayout(2, false));
new Label(contents, SWT.NONE).setText(UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_label")); //$NON-NLS-1$
resourceCombo = new ComboViewer(contents, SWT.DROP_DOWN
| SWT.READ_ONLY);
resourceCombo.getControl().setLayoutData(
new GridData(GridData.FILL_HORIZONTAL));
resourceCombo.setLabelProvider(getLabelProvider());
resourceCombo.setContentProvider(new ArrayContentProvider());
final Resource defaultResource = computeDefaultResource();
final ResourceSet rset = defaultResource.getResourceSet();
resourcesList = new BasicEList<Object>(
rset.getResources().size() + 1);
for (Resource next : rset.getResources()) {
if (!editingDomain.isReadOnly(next)) {
resourcesList.add(next);
}
}
resourcesList.move(0, defaultResource);
// add actions for loading an existing or creating a new resource
resourcesList.add(createLoadExistingResourceAction());
resourcesList.add(createCreateNewResourceAction());
resourceCombo.setInput(resourcesList);
resourceCombo
.setSelection(new StructuredSelection(defaultResource));
selectedResource = defaultResource;
resourceCombo
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
if (event.getSelection().isEmpty()) {
selectedResource = defaultResource;
} else {
Object selected = ((IStructuredSelection) event
.getSelection()).getFirstElement();
if (selected instanceof Resource) {
selectedResource = (Resource) selected;
} else {
// clicked on "Existing..." or "Create new..."
((IAction) selected).run();
}
}
}
});
}
private Resource computeDefaultResource() {
Resource result = null;
// if all of the current stereotype applications are in some other
// resource, then let that be the default on the assumption that the
// user will want to continue this pattern
for (EObject next : element.getStereotypeApplications()) {
Resource res = next.eResource();
if (result == null) {
result = res;
} else if (res != result) {
// forget it, we'll use the element's containing resource as
// the default
result = null;
break;
}
}
if (result == null) {
result = element.eResource();
}
return result;
}
private IAction createLoadExistingResourceAction() {
return new LoadOtherResourceAction(
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_existing_label")) { //$NON-NLS-1$
@Override
protected Resource openDialog(Shell parentShell,
final ResourceSet rset, URI contextURI) {
ResourceDialog dlg = new ResourceDialog(
resourceCombo.getControl().getShell(),
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_existingDialog_label"), //$NON-NLS-1$
SWT.OPEN | SWT.SINGLE, contextURI) {
@Override
protected boolean processResources() {
Resource resource = null;
try {
if (getURIs().isEmpty()) {
return true; // just let it go
}
URI selectedURI = getURIs().get(0);
if (!rset.getURIConverter().exists(selectedURI,
null)) {
MessageDialog
.openError(
getShell(),
EMFEditUIPlugin.INSTANCE
.getString("_UI_InvalidURI_label"), //$NON-NLS-1$
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_notExists_message")); //$NON-NLS-1$
return false;
}
resource = rset.getResource(selectedURI, true);
} catch (Exception e) {
MessageDialog
.openError(
getShell(),
EMFEditUIPlugin.INSTANCE
.getString("_UI_InvalidURI_label"), //$NON-NLS-1$
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_loadFailed_message")); //$NON-NLS-1$
UMLEditorPlugin.INSTANCE.log(e);
return false;
}
if (editingDomain.isReadOnly(resource)) {
MessageDialog.openError(getShell(),
EMFEditUIPlugin.INSTANCE
.getString("_UI_InvalidURI_label"), //$NON-NLS-1$
EMFEditUIPlugin.INSTANCE
.getString("_WARN_ReadOnlyResource")); //$NON-NLS-1$
return false;
}
return resource != null;
}
};
Resource result = null;
if ((dlg.open() == Window.OK) && !dlg.getURIs().isEmpty()) {
URI newURI = dlg.getURIs().get(0);
result = rset.getResource(newURI, true);
}
return result;
}
// the label provider will use this to get a label
@Override
public String toString() {
return getText();
}
};
}
private IAction createCreateNewResourceAction() {
return new LoadOtherResourceAction(
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_new_label")) { //$NON-NLS-1$
@Override
protected Resource openDialog(Shell parentShell,
final ResourceSet rset, URI contextURI) {
ResourceDialog dlg = new ResourceDialog(
resourceCombo.getControl().getShell(),
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_newDialog_label"), //$NON-NLS-1$
SWT.SAVE | SWT.SINGLE, contextURI) {
@Override
protected boolean processResources() {
Resource resource = null;
try {
if (getURIs().isEmpty()) {
return true; // just let it go
}
URI selectedURI = getURIs().get(0);
if (rset.getURIConverter().exists(selectedURI,
null)) {
MessageDialog
.openError(
getShell(),
EMFEditUIPlugin.INSTANCE
.getString("_UI_InvalidURI_label"), //$NON-NLS-1$
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_exists_message")); //$NON-NLS-1$
return false;
} else {
resource = rset
.createResource(
selectedURI,
ContentHandler.UNSPECIFIED_CONTENT_TYPE);
if (resource != null) {
// poke the new resource to mark it as
// loaded so that we won't attempt to
// load it from non-existent storage
resource.getContents().clear();
}
}
} catch (Exception e) {
MessageDialog
.openError(
getShell(),
EMFEditUIPlugin.INSTANCE
.getString("_UI_InvalidURI_label"), //$NON-NLS-1$
UMLEditorPlugin.INSTANCE
.getString("_UI_StereotypesResource_createFailed_message")); //$NON-NLS-1$
UMLEditorPlugin.INSTANCE.log(e);
return false;
}
return resource != null;
}
};
Resource result = null;
if ((dlg.open() == Window.OK) && !dlg.getURIs().isEmpty()) {
URI newURI = dlg.getURIs().get(0);
result = rset.getResource(newURI, true);
}
return result;
}
// the label provider will use this to get a label
@Override
public String toString() {
return getText();
}
};
}
private abstract class LoadOtherResourceAction
extends Action {
LoadOtherResourceAction(String label) {
super(label);
}
@Override
public void run() {
// if we've gotten this far, we know this element is in a
// resource set
final ResourceSet rset = element.eResource().getResourceSet();
URI contextURI = null;
if ((selectedResource != null)
&& selectedResource.getURI().isPlatformResource()) {
contextURI = selectedResource.getURI();
}
Resource newResource = null;
try {
newResource = openDialog(resourceCombo.getControl()
.getShell(), rset, contextURI);
} catch (Exception e) {
UMLEditorPlugin.INSTANCE.log(e);
}
if (newResource != null) {
// add it after the default
resourcesList.add(1, newResource);
resourceCombo.refresh();
} else {
// revert to the current selection, then
newResource = selectedResource;
}
// select the new resource
resourceCombo
.setSelection(new StructuredSelection(newResource));
selectedResource = newResource;
// the loading of a new resource may have
// brought in new stereotype applications
applicableStereotypes
.removeAll(element.getAppliedStereotypes());
getDialog().updateChoiceOfValues();
}
protected abstract Resource openDialog(Shell parentShell,
ResourceSet rset, URI contextURI);
// the label provider will use this to get a label
@Override
public String toString() {
return getText();
}
}
}
}