Bug 465144 - [e4 Tools] Extract into fragment wizard does not handle
handlers without commands
https://bugs.eclipse.org/bugs/show_bug.cgi?id=465144
Change-Id: I8be302baf0816e25a5ad6c2f878ff54b4c83d2ff
Signed-off-by: jonas <jonas.helming@googlemail.com>
diff --git a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/Messages.java b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/Messages.java
index 1c484b1..c43d83c 100644
--- a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/Messages.java
+++ b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/Messages.java
@@ -34,6 +34,7 @@
public static String BaseApplicationModelWizard_AddExtractedNode;
public static String BaseApplicationModelWizard_Error;
public static String BaseApplicationModelWizard_FileExists;
+ public static String BaseApplicationModelWizard_ModelRootMustNotBeNull;
public static String BaseApplicationModelWizard_TheFileAlreadyExists;
public static String NewAddonClassWizard_NewAddon;
public static String NewAddonClassWizard_NewAddonClass;
@@ -104,6 +105,7 @@
public static String E4NewProjectWizard_Quit;
public static String E4NewProjectWizard_SamplePart;
public static String E4NewProjectWizard_Save;
+ public static String ExtractContributionModelWizard_ExistingFragmentIsCorrupted;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/messages.properties b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/messages.properties
index 8a4f5dd..f3131ab 100644
--- a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/messages.properties
+++ b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/messages.properties
@@ -13,6 +13,7 @@
BaseApplicationModelWizard_AddExtractedNode=Would you like to add the extracted node to this file?
BaseApplicationModelWizard_Error=Error
BaseApplicationModelWizard_FileExists=File exists
+BaseApplicationModelWizard_ModelRootMustNotBeNull=Model root object much not be null
BaseApplicationModelWizard_TheFileAlreadyExists=The file already exists.
E4NewProjectWizard_About=About
E4NewProjectWizard_File=File
@@ -24,6 +25,7 @@
E4NewProjectWizard_Quit=Quit
E4NewProjectWizard_SamplePart=Sample Part
E4NewProjectWizard_Save=Save
+ExtractContributionModelWizard_ExistingFragmentIsCorrupted=Existing Fragment file is corrupted
NewAddonClassWizard_NewAddon=New Addon
NewAddonClassWizard_NewAddonClass=Create a new addon class
NewApplicationModelWizard_IncludeDefaultAddons=Include default addons
diff --git a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/BaseApplicationModelWizard.java b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/BaseApplicationModelWizard.java
index 9e093e7..55b6a0e 100644
--- a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/BaseApplicationModelWizard.java
+++ b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/BaseApplicationModelWizard.java
@@ -12,9 +12,7 @@
******************************************************************************/
package org.eclipse.e4.internal.tools.wizards.model;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
@@ -29,19 +27,11 @@
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.internal.tools.Messages;
-import org.eclipse.e4.ui.model.application.MApplicationElement;
-import org.eclipse.e4.ui.model.application.commands.MCommand;
-import org.eclipse.e4.ui.model.application.commands.MHandler;
-import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
-import org.eclipse.e4.ui.model.fragment.MModelFragment;
-import org.eclipse.e4.ui.model.fragment.MModelFragments;
-import org.eclipse.emf.common.util.TreeIterator;
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.resource.impl.ResourceSetImpl;
-import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
@@ -110,17 +100,16 @@
final IFile modelFile = getModelFile();
if (modelFile.exists()) {
- if (!MessageDialog.openQuestion(getShell(), Messages.BaseApplicationModelWizard_FileExists,
- Messages.BaseApplicationModelWizard_TheFileAlreadyExists
- + Messages.BaseApplicationModelWizard_AddExtractedNode)) {
- return false;
+ final boolean continueWithExistingFile = handleFileExist();
+ if (!continueWithExistingFile) {
+ return true;
}
+
}
// Do the work within an operation.
//
- final WorkspaceModifyOperation operation =
- new WorkspaceModifyOperation() {
+ final WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor progressMonitor) {
try {
@@ -136,80 +125,22 @@
//
final Resource resource = resourceSet.createResource(fileURI);
+ final EObject rootObject = createInitialModel();
+
+ if (rootObject == null) {
+ throw new IllegalArgumentException(Messages.BaseApplicationModelWizard_ModelRootMustNotBeNull);
+ }
+
// If target file already exists, load its content
//
if (modelFile.exists()) {
resource.load(null);
- }
- // Add the initial model object to the contents.
- //
- final EObject rootObject = createInitialModel();
- if (rootObject != null) {
- if (resource.getContents().size() == 0) {
- // If target model is empty (file just created) => add as is
- resource.getContents().add(rootObject);
- } else {
- // Otherwise (file already exists) => take the roots of source and target models
- // and copy multiple attributes 'imports' and 'fragments' objects from source to
- // target
- final MModelFragments sourceFragments = (MModelFragments) rootObject;
- final MModelFragments targetFragments = (MModelFragments) resource.getContents()
- .get(0);
-
- final List<MCommand> listOfAllImportsFromElements = new ArrayList<MCommand>();
- for (final MModelFragment fragment : sourceFragments.getFragments()) {
- final List<MCommand> commandsToImport = new ArrayList<MCommand>();
- final EObject eObject = (EObject) fragment;
- final TreeIterator<EObject> eAllContents = eObject.eAllContents();
- while (eAllContents.hasNext()) {
- final EObject next = eAllContents.next();
- final MApplicationElement mApplicationElement = (MApplicationElement) next;
- if (mApplicationElement instanceof MHandler) {
- final MHandler mHandler = (MHandler) mApplicationElement;
- final MCommand command = mHandler.getCommand();
- commandsToImport.add(command);
- final MApplicationElement copy = (MApplicationElement) EcoreUtil
- .copy((EObject) command);
- targetFragments.getImports().add(copy);
- mHandler.setCommand((MCommand) copy);
- }
- else if (mApplicationElement instanceof MHandledItem) {
- final MHandledItem mHandledItem = (MHandledItem) mApplicationElement;
- final MCommand command = mHandledItem.getCommand();
- commandsToImport.add(command);
- final MApplicationElement copy = (MApplicationElement) EcoreUtil
- .copy((EObject) command);
- targetFragments.getImports().add(copy);
- mHandledItem.setCommand((MCommand) copy);
- }
-
- }
- listOfAllImportsFromElements.addAll(commandsToImport);
- targetFragments.getFragments().add(
- (MModelFragment) EcoreUtil.copy((EObject) fragment));
-
- }
- for (final MApplicationElement element : sourceFragments.getImports()) {
- boolean isAlreadyImport = true;
- for (final MCommand mCommand : listOfAllImportsFromElements) {
-
- if (!mCommand.getElementId().equals(element.getElementId())) {
-
- isAlreadyImport = false;
- break;
- }
- if (!isAlreadyImport) {
-
- targetFragments.getImports().add(
- (MApplicationElement) EcoreUtil.copy((EObject) element));
- }
-
- }
-
- }
-
- }
+ mergeWithExistingFile(resource, rootObject);
+ } else {
+ // If target model is empty (file just created)
+ // => add as is
+ resource.getContents().add(rootObject);
}
// Save the contents of the resource to the file system.
@@ -218,11 +149,9 @@
resource.save(options);
adjustBuildPropertiesFile(modelFile);
adjustDependencies(modelFile);
- }
- catch (final Exception exception) {
+ } catch (final Exception exception) {
throw new RuntimeException(exception);
- }
- finally {
+ } finally {
progressMonitor.done();
}
}
@@ -237,20 +166,18 @@
final IWorkbenchPart activePart = page.getActivePart();
if (activePart instanceof ISetSelectionTarget) {
final ISelection targetSelection = new StructuredSelection(modelFile);
- getShell().getDisplay().asyncExec
- (new Runnable() {
- @Override
+ getShell().getDisplay().asyncExec(new Runnable() {
+ @Override
public void run() {
- ((ISetSelectionTarget) activePart).selectReveal(targetSelection);
- }
- });
+ ((ISetSelectionTarget) activePart).selectReveal(targetSelection);
+ }
+ });
}
// Open an editor on the new file.
//
try {
- page.openEditor
- (new FileEditorInput(modelFile),
+ page.openEditor(new FileEditorInput(modelFile),
workbench.getEditorRegistry().getDefaultEditor(modelFile.getFullPath().toString()).getId());
} catch (final PartInitException exception) {
MessageDialog.openError(workbenchWindow.getShell(), "Could not init editor", exception.getMessage()); //$NON-NLS-1$
@@ -265,6 +192,21 @@
}
}
+ /**
+ * @return if the wizard should continue in case the file already exists
+ */
+ protected boolean handleFileExist() {
+ MessageDialog.openInformation(getShell(), Messages.BaseApplicationModelWizard_FileExists,
+ Messages.BaseApplicationModelWizard_TheFileAlreadyExists);
+
+ return false;
+ }
+
+ /**
+ * Creates the rootObject of the new model file. Must not be null.
+ *
+ * @return The root {@link EObject}
+ */
protected abstract EObject createInitialModel();
protected IFile getModelFile() throws CoreException {
@@ -274,14 +216,15 @@
final IResource resource = root.findMember(new Path(containerName));
if (!resource.exists() || !(resource instanceof IContainer)) {
throwCoreException("Container \"" + containerName //$NON-NLS-1$
- + "\" does not exist."); //$NON-NLS-1$
+ + "\" does not exist."); //$NON-NLS-1$
}
final IContainer container = (IContainer) resource;
return container.getFile(new Path(fileName));
}
private void throwCoreException(String message) throws CoreException {
- final IStatus status = new Status(IStatus.ERROR, "org.eclipse.e4.tools.emf.editor3x", IStatus.OK, message, null); //$NON-NLS-1$
+ final IStatus status = new Status(IStatus.ERROR, "org.eclipse.e4.tools.emf.editor3x", IStatus.OK, message, //$NON-NLS-1$
+ null);
throw new CoreException(status);
}
@@ -300,8 +243,7 @@
/**
* Adds other file to the build.properties file.
*/
- private void adjustBuildPropertiesFile(IFile file)
- throws CoreException {
+ private void adjustBuildPropertiesFile(IFile file) throws CoreException {
final IProject project = file.getProject();
final IFile buildPropertiesFile = PDEProject.getBuildProperties(project);
if (buildPropertiesFile.exists()) {
@@ -335,8 +277,7 @@
final IFile pluginXml = PDEProject.getPluginXml(project);
final IFile manifest = PDEProject.getManifest(project);
- final WorkspaceBundlePluginModel fModel = new WorkspaceBundlePluginModel(
- manifest, pluginXml);
+ final WorkspaceBundlePluginModel fModel = new WorkspaceBundlePluginModel(manifest, pluginXml);
try {
addWorkbenchDependencyIfRequired(fModel);
registerWithExtensionPointIfRequired(project, fModel, file);
@@ -346,8 +287,7 @@
}
}
- private void addWorkbenchDependencyIfRequired(
- WorkspaceBundlePluginModel fModel) throws CoreException {
+ private void addWorkbenchDependencyIfRequired(WorkspaceBundlePluginModel fModel) throws CoreException {
final IPluginImport[] imports = fModel.getPluginBase().getImports();
final String WORKBENCH_IMPORT_ID = "org.eclipse.e4.ui.model.workbench"; //$NON-NLS-1$
@@ -359,19 +299,15 @@
}
String version = ""; //$NON-NLS-1$
- final IPluginModelBase findModel = PluginRegistry
- .findModel(WORKBENCH_IMPORT_ID);
+ final IPluginModelBase findModel = PluginRegistry.findModel(WORKBENCH_IMPORT_ID);
if (findModel != null) {
- final BundleDescription bundleDescription = findModel
- .getBundleDescription();
+ final BundleDescription bundleDescription = findModel.getBundleDescription();
if (bundleDescription != null) {
- version = bundleDescription.getVersion().toString()
- .replaceFirst("\\.qualifier$", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ version = bundleDescription.getVersion().toString().replaceFirst("\\.qualifier$", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
}
- final IPluginImport workbenchImport = fModel.getPluginFactory()
- .createImport();
+ final IPluginImport workbenchImport = fModel.getPluginFactory().createImport();
workbenchImport.setId(WORKBENCH_IMPORT_ID);
workbenchImport.setVersion(version);
workbenchImport.setMatch(IMatchRules.GREATER_OR_EQUAL);
@@ -383,17 +319,20 @@
* Register the fragment.e4xmi with the org.eclipse.e4.workbench.model
* extension point, if there is not already a fragment registered.
*/
- private void registerWithExtensionPointIfRequired(IProject project,
- WorkspaceBundlePluginModel fModel, IFile file) throws CoreException {
+ private void registerWithExtensionPointIfRequired(IProject project, WorkspaceBundlePluginModel fModel, IFile file)
+ throws CoreException {
final String WORKBENCH_MODEL_EP_ID = "org.eclipse.e4.workbench.model"; //$NON-NLS-1$
final String FRAGMENT = "fragment"; //$NON-NLS-1$
- // Fix bug #436836 : the received fModel is an empty plugin model without extension.
+ // Fix bug #436836 : the received fModel is an empty plugin model
+ // without extension.
// We must copy extensions found in registry plugin model into it
- // The registry plugin model is read only and must be copied inside the new extension value..
+ // The registry plugin model is read only and must be copied inside the
+ // new extension value..
final BundlePluginModel registryModel = (BundlePluginModel) PluginRegistry.findModel(project.getName());
- // The registry Model is not modifiable and may be contains some existing extensions.
+ // The registry Model is not modifiable and may be contains some
+ // existing extensions.
// Must copy them in the new created fModel
for (final IPluginExtension e : registryModel.getPluginBase().getExtensions()) {
final IPluginExtension clonedExtens = copyExtension(fModel.getFactory(), e);
@@ -403,8 +342,7 @@
// Can now check if we must add this extension (may be already inside).
final IPluginExtension[] extensions = fModel.getPluginBase().getExtensions();
for (final IPluginExtension iPluginExtension : extensions) {
- if (WORKBENCH_MODEL_EP_ID
- .equalsIgnoreCase(iPluginExtension.getPoint())) {
+ if (WORKBENCH_MODEL_EP_ID.equalsIgnoreCase(iPluginExtension.getPoint())) {
final IPluginObject[] children = iPluginExtension.getChildren();
for (final IPluginObject child : children) {
if (FRAGMENT.equalsIgnoreCase(child.getName())) {
@@ -414,10 +352,9 @@
}
}
- final IPluginExtension extPointFragmentRegister = fModel.getPluginFactory()
- .createExtension();
- final IPluginElement element = extPointFragmentRegister.getModel()
- .getFactory().createElement(extPointFragmentRegister);
+ final IPluginExtension extPointFragmentRegister = fModel.getPluginFactory().createExtension();
+ final IPluginElement element = extPointFragmentRegister.getModel().getFactory()
+ .createElement(extPointFragmentRegister);
element.setName(FRAGMENT);
element.setAttribute("uri", file.getName()); //$NON-NLS-1$
extPointFragmentRegister.setId(project.getName() + "." + FRAGMENT); //$NON-NLS-1$
@@ -429,8 +366,7 @@
// Used to Fix bug #436836
private IPluginExtension copyExtension(IExtensionsModelFactory factory, final IPluginExtension ext) {
- try
- {
+ try {
final IPluginExtension clonedExt = factory.createExtension();
clonedExt.setPoint(ext.getPoint());
final IPluginObject[] _children = ext.getChildren();
@@ -451,9 +387,8 @@
// Used to Fix bug #436836
private IPluginElement copyExtensionElement(IExtensionsModelFactory factory, final IPluginElement elt,
- final IPluginObject parent) {
- try
- {
+ final IPluginObject parent) {
+ try {
final IPluginElement clonedElt = factory.createElement(parent);
clonedElt.setName(elt.getName());
for (final IPluginAttribute a : elt.getAttributes()) {
@@ -474,4 +409,13 @@
}
+ /**
+ * @param resource
+ * @param rootObject
+ */
+ protected void mergeWithExistingFile(Resource resource, EObject rootObject) {
+ // do nothing
+
+ }
+
}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/ExtractContributionModelWizard.java b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/ExtractContributionModelWizard.java
index bbbc1b1..4ac77e5 100644
--- a/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/ExtractContributionModelWizard.java
+++ b/bundles/org.eclipse.e4.tools/src/org/eclipse/e4/internal/tools/wizards/model/ExtractContributionModelWizard.java
@@ -12,21 +12,27 @@
package org.eclipse.e4.internal.tools.wizards.model;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
+import org.eclipse.e4.internal.tools.Messages;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.e4.ui.model.application.commands.MHandler;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
import org.eclipse.e4.ui.model.fragment.MFragmentFactory;
+import org.eclipse.e4.ui.model.fragment.MModelFragment;
import org.eclipse.e4.ui.model.fragment.MModelFragments;
import org.eclipse.e4.ui.model.fragment.MStringModelFragment;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature.Setting;
+import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.PlatformUI;
@@ -60,6 +66,9 @@
final MHandler mhandler = (MHandler) moe;
final MCommand command = ((MHandler) moe).getCommand();
+ if (command == null) {
+ return;
+ }
final MCommand existImportCommand = importCommands.get(command.getElementId());
if (existImportCommand == null) {
final MApplicationElement copy = (MApplicationElement) EcoreUtil.copy((EObject) command);
@@ -72,6 +81,9 @@
} else if (moe instanceof MHandledItem) {
final MHandledItem mh = (MHandledItem) moe;
final MCommand command = mh.getCommand();
+ if (command == null) {
+ return;
+ }
final MCommand existImportCommand = importCommands.get(command.getElementId());
if (existImportCommand == null) {
final MApplicationElement copy = (MApplicationElement) EcoreUtil.copy((EObject) command);
@@ -100,11 +112,11 @@
hasNext = eAllContents.hasNext();
}
final MStringModelFragment createStringModelFragment = MFragmentFactory.INSTANCE
- .createStringModelFragment();
+ .createStringModelFragment();
final MApplicationElement e = (MApplicationElement) EcoreUtil.copy((EObject) moe);
final String featurename = ((EObject) moe).eContainmentFeature().getName();
- createStringModelFragment.setParentElementId(((MApplicationElement) ((EObject) moe).eContainer())
- .getElementId());
+ createStringModelFragment
+ .setParentElementId(((MApplicationElement) ((EObject) moe).eContainer()).getElementId());
createStringModelFragment.getElements().add(e);
createStringModelFragment.setFeaturename(featurename);
@@ -127,4 +139,79 @@
super.adjustFragmentDependencies(file);
}
-}
\ No newline at end of file
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.e4.internal.tools.wizards.model.BaseApplicationModelWizard#handleFileExist()
+ */
+ @Override
+ protected boolean handleFileExist() {
+ return MessageDialog.openQuestion(getShell(), Messages.BaseApplicationModelWizard_FileExists,
+ Messages.BaseApplicationModelWizard_TheFileAlreadyExists
+ + Messages.BaseApplicationModelWizard_AddExtractedNode);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.e4.internal.tools.wizards.model.BaseApplicationModelWizard#mergeWithExistingFile(org.eclipse.emf.ecore.resource.Resource)
+ */
+ @Override
+ protected void mergeWithExistingFile(Resource resource, EObject rootObject) {
+
+ final EObject existingRootObject = resource.getContents().get(0);
+ if (!(existingRootObject instanceof MModelFragments)) {
+ throw new IllegalStateException(Messages.ExtractContributionModelWizard_ExistingFragmentIsCorrupted);
+ }
+
+ final MModelFragments sourceFragments = (MModelFragments) rootObject;
+ final MModelFragments targetFragments = (MModelFragments) existingRootObject;
+
+ targetFragments.getFragments().addAll(sourceFragments.getFragments());
+ final List<MApplicationElement> sourceImports = new ArrayList<MApplicationElement>();
+ sourceImports.addAll(sourceFragments.getImports());
+ for (final MApplicationElement source : sourceImports) {
+
+ boolean doImport = true;
+ for (final MApplicationElement target : targetFragments.getImports()) {
+ if (target.getElementId() == null || source.getElementId() == null) {
+ continue;
+ }
+ if (target.getElementId().equals(source.getElementId())) {
+ doImport = false;
+ connectToExistingImport(targetFragments.getFragments(), target, source);
+ break;
+ }
+
+ }
+ if (doImport) {
+ targetFragments.getImports().add(source);
+ }
+
+ }
+
+ }
+
+ /**
+ * @param fragments
+ * @param existingImport
+ * @param source
+ */
+ private void connectToExistingImport(List<MModelFragment> fragments, MApplicationElement target,
+ MApplicationElement source) {
+ final Collection<Setting> settings = EcoreUtil.UsageCrossReferencer.find((EObject) source, fragments);
+ for (final Setting setting : settings) {
+ if (setting.getEStructuralFeature().isMany()) {
+ @SuppressWarnings("unchecked")
+ final List<MApplicationElement> list = (List<MApplicationElement>) setting.getEObject()
+ .eGet(setting.getEStructuralFeature());
+ list.remove(source);
+ list.add(target);
+ } else {
+ setting.getEObject().eSet(setting.getEStructuralFeature(), target);
+ }
+ }
+
+ }
+}