Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandra Buzila2016-02-12 17:02:31 +0000
committerJonas Helming2016-03-29 16:31:24 +0000
commitc2f3d33e6f34013650a63fa401e7f5d9c0b89b76 (patch)
tree2e87ced8cb6ff1e20e133bac8c8467af2737f721
parentba81c58c3341210b58a45dd084ab8dbe5aaad430 (diff)
downloadeclipse.platform.ui-c2f3d33e6f34013650a63fa401e7f5d9c0b89b76.tar.gz
eclipse.platform.ui-c2f3d33e6f34013650a63fa401e7f5d9c0b89b76.tar.xz
eclipse.platform.ui-c2f3d33e6f34013650a63fa401e7f5d9c0b89b76.zip
Bug 480610 - Add Tests for ModelAssembler
Refactored ModelAssembler and added tests Change-Id: Iaa809d9165f877f89a14fa5b68eb1246eed6c366 Signed-off-by: Alexandra Buzila <abuzila@eclipsesource.com>
-rw-r--r--bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java220
-rw-r--r--tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_null.xml10
-rw-r--r--tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_wrongProcessorClass.xml11
-rw-r--r--tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml22
-rw-r--r--tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml22
-rw-r--r--tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java2
-rw-r--r--tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java488
-rw-r--r--tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePostProcessor.java22
-rw-r--r--tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePreProcessor.java21
-rw-r--r--tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimpleProcessor.java35
10 files changed, 776 insertions, 77 deletions
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
index effd0c2ca83..9fa1418f83f 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2015 BestSolution.at and others.
+ * Copyright (c) 2010, 2016 BestSolution.at 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
@@ -10,6 +10,7 @@
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 430075, 430080, 431464, 433336, 472654
* René Brandstetter - Bug 419749
* Brian de Alwis (MTI) - Bug 433053
+ * Alexandra Buzila - Refactoring
******************************************************************************/
package org.eclipse.e4.ui.internal.workbench;
@@ -49,7 +50,9 @@ import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
- *
+ * The ModelAssembler is responsible for adding {@link MModelFragment fragments}
+ * and {@link MApplicationElement} imports to the application model and running
+ * pre- and post-processors on the model.
*/
public class ModelAssembler {
@Inject
@@ -66,12 +69,21 @@ public class ModelAssembler {
final private static String extensionPointID = "org.eclipse.e4.workbench.model"; //$NON-NLS-1$
- // private static final String ALWAYS = "always"; //$NON-NLS-1$
+ // private static final String ALWAYS = "always"; //$NON-NLS-1$
private static final String INITIAL = "initial"; //$NON-NLS-1$
private static final String NOTEXISTS = "notexists"; //$NON-NLS-1$
/**
- * Process the model
+ * Processes the model. This will run pre-processors, process the fragments,
+ * run post-processors and resolve imports, in this order. <br>
+ * The <strong>org.eclipse.e4.workbench.model</strong> extension point will
+ * be used to retrieve the contributed fragments (with imports) and
+ * processors.<br>
+ * Extension points will be sorted based on the dependencies of their
+ * contributors.
+ *
+ * @param initial
+ * <code>true</code> if running from a non-persisted state
*/
public void processModel(boolean initial) {
IExtensionPoint extPoint = registry.getExtensionPoint(extensionPointID);
@@ -85,32 +97,75 @@ public class ModelAssembler {
processFragments(extensions, imports, addedElements, initial);
// run processors which are marked to run after fragments
runProcessors(extensions, initial, true);
-
resolveImports(imports, addedElements);
}
/**
+ * Adds the {@link MApplicationElement model elements} contributed by the
+ * {@link IExtension extensions} to the {@link MApplication application
+ * model}.
+ *
* @param extensions
+ * the list of {@link IExtension} extension elements
* @param imports
+ * list that will be populated in place with the
+ * {@link MApplicationElement MApplicationElements} imported by
+ * the fragments
* @param addedElements
+ * list that will be populated in place with the
+ * {@link MApplicationElement MApplicationElements} contributed
+ * by the fragments to the application model
+ * @param initial
+ * <code>true</code> if running from a non-persisted state
*/
private void processFragments(IExtension[] extensions, List<MApplicationElement> imports,
List<MApplicationElement> addedElements, boolean initial) {
-
for (IExtension extension : extensions) {
IConfigurationElement[] ces = extension.getConfigurationElements();
for (IConfigurationElement ce : ces) {
- if ("fragment".equals(ce.getName())) { //$NON-NLS-1$
- if (initial || !INITIAL.equals(ce.getAttribute("apply"))) { //$NON-NLS-1$
- processFragment(ce, imports, addedElements, initial);
- }
+ if ("fragment".equals(ce.getName()) && (initial || !INITIAL.equals(ce.getAttribute("apply")))) { //$NON-NLS-1$ //$NON-NLS-2$
+ boolean checkExist = !initial && NOTEXISTS.equals(ce.getAttribute("apply")); //$NON-NLS-1$
+ processFragmentConfigurationElement(ce, checkExist, imports, addedElements);
}
}
}
}
- private void processFragment(IConfigurationElement ce, List<MApplicationElement> imports,
- List<MApplicationElement> addedElements, boolean initial) {
+ private void processFragmentConfigurationElement(IConfigurationElement ce, boolean checkExist,
+ List<MApplicationElement> imports,
+ List<MApplicationElement> addedElements) {
+ MModelFragments fragmentsContainer = getFragmentsContainer(ce);
+ if (fragmentsContainer == null) {
+ return;
+ }
+ String contributorURI = URIHelper.constructPlatformURI(ce.getContributor());
+ boolean evalImports = false;
+ for (MModelFragment fragment : fragmentsContainer.getFragments()) {
+ Diagnostic validationResult = Diagnostician.INSTANCE.validate((EObject) fragment);
+ int severity = validationResult.getSeverity();
+ if (severity == Diagnostic.ERROR) {
+ logger.error("Fragment from \"" + "uri.toString()" + "\" of \"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ + ce.getContributor().getName() + "\" could not be validated and was not merged \"{0}\"", //$NON-NLS-1$
+ fragment.toString());
+
+ continue;
+ }
+
+ List<MApplicationElement> merged = processModelFragment(fragment, contributorURI, checkExist);
+ if (merged.size() > 0) {
+ evalImports = true;
+ addedElements.addAll(merged);
+ } else {
+ logger.debug("Nothing to merge for fragment \"{0}\" of \"{1}\"", ce.getAttribute("uri"), //$NON-NLS-1$ //$NON-NLS-2$
+ ce.getContributor().getName());
+ }
+ }
+ if (evalImports) {
+ imports.addAll(fragmentsContainer.getImports());
+ }
+ }
+
+ private MModelFragments getFragmentsContainer(IConfigurationElement ce) {
E4XMIResource applicationResource = (E4XMIResource) ((EObject) application).eResource();
ResourceSet resourceSet = applicationResource.getResourceSet();
IContributor contributor = ce.getContributor();
@@ -118,7 +173,7 @@ public class ModelAssembler {
String bundleName = contributor.getName();
if (attrURI == null) {
logger.warn("Unable to find location for the model extension \"{0}\"", bundleName); //$NON-NLS-1$
- return;
+ return null;
}
URI uri;
@@ -132,96 +187,99 @@ public class ModelAssembler {
}
} catch (RuntimeException e) {
logger.warn(e, "Invalid location \"" + attrURI + "\" of model extension \"" + bundleName + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- return;
+ return null;
}
- String contributorURI = URIHelper.constructPlatformURI(contributor);
Resource resource;
try {
resource = resourceSet.getResource(uri, true);
} catch (RuntimeException e) {
- logger.warn(e, "Unable to read model extension from \"" + uri.toString() +"\" of \"" + bundleName + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- return;
+ logger.warn(e, "Unable to read model extension from \"" + uri.toString() + "\" of \"" + bundleName + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return null;
}
EList<?> contents = resource.getContents();
if (contents.isEmpty()) {
- return;
+ return null;
}
Object extensionRoot = contents.get(0);
if (!(extensionRoot instanceof MModelFragments)) {
logger.warn("Unable to create model extension \"{0}\"", bundleName); //$NON-NLS-1$
- return;
+ return null;
}
- boolean checkExist = !initial && NOTEXISTS.equals(ce.getAttribute("apply")); //$NON-NLS-1$
-
- MModelFragments fragmentsContainer = (MModelFragments) extensionRoot;
- List<MModelFragment> fragments = fragmentsContainer.getFragments();
- boolean evalImports = false;
- for (MModelFragment fragment : fragments) {
- Diagnostic validationResult = Diagnostician.INSTANCE.validate((EObject) fragment);
- int severity = validationResult.getSeverity();
- if (severity == Diagnostic.ERROR) {
- logger.error("Fragment from \"" + uri.toString() + "\" of \"" + bundleName // $NON-NLS-1$ //$NON-NLS-1$ //$NON-NLS-2$
- // //$NON-NLS-2$
- + "\" could not be validated and will not be merged \"{0}\"", fragment); // $NON-NLS-1$ //$NON-NLS-1$
- continue;
- }
- List<MApplicationElement> elements = fragment.getElements();
- if (elements.size() == 0) {
- continue;
- }
+ return (MModelFragments) extensionRoot;
+ }
- for (MApplicationElement el : elements) {
- EObject o = (EObject) el;
+ /**
+ * Contributes the given {@link MModelFragment} to the application model.
+ *
+ * @param fragment
+ * the fragment to add to the application model
+ * @param contributorURI
+ * the URI of the element that contributes this fragment
+ * @param checkExist
+ * specifies whether we should check that the application model
+ * doesn't already contain the elements contributed by the
+ * fragment before merging them
+ * @return a list of the {@link MApplicationElement} elements that were
+ * merged into the application model by the fragment
+ */
+ public List<MApplicationElement> processModelFragment(MModelFragment fragment, String contributorURI,
+ boolean checkExist) {
- E4XMIResource r = (E4XMIResource) o.eResource();
+ E4XMIResource applicationResource = (E4XMIResource) ((EObject) application).eResource();
- if (checkExist && applicationResource.getIDToEObjectMap().containsKey(r.getID(o))) {
- continue;
- }
+ List<MApplicationElement> elements = fragment.getElements();
+ if (elements.size() == 0) {
+ return new ArrayList<>();
+ }
- applicationResource.setID(o, r.getID(o));
+ for (MApplicationElement el : elements) {
+ EObject o = (EObject) el;
- if (contributorURI != null)
- el.setContributorURI(contributorURI);
+ E4XMIResource r = (E4XMIResource) o.eResource();
- // Remember IDs of subitems
- TreeIterator<EObject> treeIt = EcoreUtil.getAllContents(o, true);
- while (treeIt.hasNext()) {
- EObject eObj = treeIt.next();
- r = (E4XMIResource) eObj.eResource();
- if (contributorURI != null && (eObj instanceof MApplicationElement))
- ((MApplicationElement) eObj).setContributorURI(contributorURI);
- applicationResource.setID(eObj, r.getInternalId(eObj));
- }
+ if (checkExist && applicationResource.getIDToEObjectMap().containsKey(r.getID(o))) {
+ continue;
}
- List<MApplicationElement> merged = fragment.merge(application);
+ applicationResource.setID(o, r.getID(o));
- if (merged.size() > 0) {
- evalImports = true;
- addedElements.addAll(merged);
- } else {
- logger.debug("Nothing to merge for \"{0}\"", uri); //$NON-NLS-1$
- }
- }
+ if (contributorURI != null)
+ el.setContributorURI(contributorURI);
- if (evalImports) {
- List<MApplicationElement> localImports = fragmentsContainer.getImports();
- if (localImports != null) {
- imports.addAll(localImports);
+ // Remember IDs of subitems
+ TreeIterator<EObject> treeIt = EcoreUtil.getAllContents(o, true);
+ while (treeIt.hasNext()) {
+ EObject eObj = treeIt.next();
+ r = (E4XMIResource) eObj.eResource();
+ if (contributorURI != null && (eObj instanceof MApplicationElement))
+ ((MApplicationElement) eObj).setContributorURI(contributorURI);
+ applicationResource.setID(eObj, r.getInternalId(eObj));
}
}
+
+ return fragment.merge(application);
}
/**
+ * Executes the processors as declared in provided {@link IExtension
+ * extensions} array.
+ *
* @param extensions
+ * the array of {@link IExtension} extensions containing the
+ * processors
+ * @param initial
+ * <code>true</code> if the application is running from a
+ * non-persisted state
* @param afterFragments
+ * <code>true</code> if the processors that should be run before
+ * model fragments are merged are to be executed,
+ * <code>false</code> otherwise
*/
- private void runProcessors(IExtension[] extensions, boolean initial, boolean afterFragments) {
+ public void runProcessors(IExtension[] extensions, boolean initial, boolean afterFragments) {
for (IExtension extension : extensions) {
IConfigurationElement[] ces = extension.getConfigurationElements();
for (IConfigurationElement ce : ces) {
@@ -260,11 +318,11 @@ public class ModelAssembler {
}
try {
- Object o = factory
- .create("bundleclass://" + ce.getContributor().getName() + "/" + ce.getAttribute("class"), //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
- context, localContext);
+ Object o = factory.create("bundleclass://" + ce.getContributor().getName() + "/" + ce.getAttribute("class"), //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+ context, localContext);
if (o == null) {
- logger.warn("Unable to create processor " + ce.getAttribute("class") + " from " + ce.getContributor().getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ logger.warn("Unable to create processor " + ce.getAttribute("class") + " from " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ + ce.getContributor().getName());
} else {
ContextInjectionFactory.invoke(o, Execute.class, context, localContext);
}
@@ -273,19 +331,27 @@ public class ModelAssembler {
}
}
- private void resolveImports(List<MApplicationElement> imports,
- List<MApplicationElement> addedElements) {
+ /**
+ * Resolves the given list of imports used by the specified
+ * <code>addedElements</code> in the application model.
+ *
+ * @param imports
+ * the list of elements that were imported by fragments and
+ * should be resolved in the application model
+ * @param addedElements
+ * the list of elements contributed by the fragments to the
+ * application model
+ */
+ public void resolveImports(List<MApplicationElement> imports, List<MApplicationElement> addedElements) {
if (imports.isEmpty())
return;
// now that we have all components loaded, resolve imports
Map<MApplicationElement, MApplicationElement> importMaps = new HashMap<>();
for (MApplicationElement importedElement : imports) {
- MApplicationElement realElement = ModelUtils.findElementById(application,
- importedElement.getElementId());
+ MApplicationElement realElement = ModelUtils.findElementById(application, importedElement.getElementId());
if (realElement == null) {
logger.warn("Could not resolve an import element for '" + realElement + "'"); //$NON-NLS-1$ //$NON-NLS-2$
}
-
importMaps.put(importedElement, realElement);
}
diff --git a/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_null.xml b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_null.xml
new file mode 100644
index 00000000000..66e84d4d21a
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_null.xml
@@ -0,0 +1,10 @@
+<plugin>
+ <extension
+ id="id1"
+ point="org.eclipse.e4.workbench.model">
+ <processor
+ apply="always"
+ beforefragment="true">
+ </processor>
+ </extension>
+</plugin> \ No newline at end of file
diff --git a/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_wrongProcessorClass.xml b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_wrongProcessorClass.xml
new file mode 100644
index 00000000000..2d2ee362c81
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processor_wrongProcessorClass.xml
@@ -0,0 +1,11 @@
+<plugin>
+ <extension
+ id="id1"
+ point="org.eclipse.e4.workbench.model">
+ <processor
+ apply="always"
+ beforefragment="true"
+ class="org.eclipse.e4.ui.tests.workbench.SimplePreProcessor_NotFound">
+ </processor>
+ </extension>
+</plugin> \ No newline at end of file
diff --git a/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml
new file mode 100644
index 00000000000..c285436065a
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml
@@ -0,0 +1,22 @@
+<plugin>
+ <extension
+ id="id1"
+ point="org.eclipse.e4.workbench.model">
+ <processor
+ apply="always"
+ beforefragment="true"
+ class="org.eclipse.e4.ui.tests.workbench.SimplePreProcessor">
+ <element
+ id="org.eclipse.e4.ui.tests.modelassembler.app">
+ </element>
+ </processor>
+ <processor
+ apply="always"
+ beforefragment="false"
+ class="org.eclipse.e4.ui.tests.workbench.SimplePostProcessor">
+ <element
+ id="org.eclipse.e4.ui.tests.modelassembler.app">
+ </element>
+ </processor>
+ </extension>
+</plugin> \ No newline at end of file
diff --git a/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml
new file mode 100644
index 00000000000..8bca5ed4f1b
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml
@@ -0,0 +1,22 @@
+<plugin>
+ <extension
+ id="id1"
+ point="org.eclipse.e4.workbench.model">
+ <processor
+ apply="initial"
+ beforefragment="true"
+ class="org.eclipse.e4.ui.tests.workbench.SimplePreProcessor">
+ <element
+ id="org.eclipse.e4.ui.tests.modelassembler.app">
+ </element>
+ </processor>
+ <processor
+ apply="initial"
+ beforefragment="false"
+ class="org.eclipse.e4.ui.tests.workbench.SimplePostProcessor">
+ <element
+ id="org.eclipse.e4.ui.tests.modelassembler.app">
+ </element>
+ </processor>
+ </extension>
+</plugin> \ No newline at end of file
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java
index 9fb15d0a0ea..fedcc897e5a 100644
--- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/UIAllTests.java
@@ -34,6 +34,7 @@ import org.eclipse.e4.ui.tests.workbench.MSashTest;
import org.eclipse.e4.ui.tests.workbench.MSaveablePartTest;
import org.eclipse.e4.ui.tests.workbench.MToolItemTest;
import org.eclipse.e4.ui.tests.workbench.MWindowTest;
+import org.eclipse.e4.ui.tests.workbench.ModelAssemblerTests;
import org.eclipse.e4.ui.tests.workbench.PartFocusTest;
import org.eclipse.e4.ui.tests.workbench.PartRenderingEngineTests;
import org.eclipse.e4.ui.tests.workbench.SashRendererTest;
@@ -80,6 +81,7 @@ import org.junit.runners.Suite;
TopoSortTests.class,
ExtensionsSortTests.class,
HandlerActivationTest.class,
+ ModelAssemblerTests.class
// SWTPartRendererTest.class,
})
public class UIAllTests {
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
new file mode 100644
index 00000000000..5b356dcaf61
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
@@ -0,0 +1,488 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EclipseSource Muenchen GmbH 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:
+ * Alexandra Buzila - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.tests.workbench;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.internal.registry.ExtensionRegistry;
+import org.eclipse.core.runtime.ContributorFactorySimple;
+import org.eclipse.core.runtime.IContributor;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.RegistryFactory;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.E4XMIResource;
+import org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory;
+import org.eclipse.e4.ui.internal.workbench.ExtensionsSort;
+import org.eclipse.e4.ui.internal.workbench.ModelAssembler;
+import org.eclipse.e4.ui.internal.workbench.swt.E4Application;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.impl.ApplicationFactoryImpl;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MAdvancedFactory;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MBasicFactory;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+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.e4.ui.workbench.Selector;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+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.URIConverter;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@SuppressWarnings("nls")
+public class ModelAssemblerTests {
+ final private static String EXTENSION_POINT_ID = "org.eclipse.e4.workbench.model";
+ final private static String BUNDLE_SYMBOLIC_NAME = "org.eclipse.e4.ui.tests";
+ final private static String APPLICATION_ID = "org.eclipse.e4.ui.tests.modelassembler.app";
+ private IEclipseContext appContext;
+ private MApplication application;
+ private E4XMIResourceFactory factory;
+ private ResourceSetImpl resourceSet;
+ private E4XMIResource appResource;
+ private ModelAssembler assembler;
+ private Logger logger;
+
+ @Before
+ public void setup() {
+ appContext = E4Application.createDefaultContext();
+ application = ApplicationFactoryImpl.eINSTANCE.createApplication();
+ application.setElementId(APPLICATION_ID);
+ application.setContext(appContext);
+
+ logger = mock(Logger.class);
+
+ appContext.set(Logger.class, logger);
+ appContext.set(MApplication.class, application);
+
+ factory = new E4XMIResourceFactory();
+ appResource = (E4XMIResource) factory.createResource(URI.createURI("virtualuri"));
+ resourceSet = new ResourceSetImpl();
+ resourceSet.getResources().add(appResource);
+ appResource.getContents().add((EObject) application);
+ assembler = new ModelAssembler();
+ ContextInjectionFactory.inject(assembler, appContext);
+ }
+
+ /**
+ * Test the handling of a fragment contribution with no elements to merge.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFragments_emptyFragment() throws Exception {
+ MModelFragment fragment = MFragmentFactory.INSTANCE.createStringModelFragment();
+ final String contributorURI = "testFragments_emptyFragment_contribURI";
+
+ List<MApplicationElement> elements = assembler.processModelFragment(fragment, contributorURI, true);
+ assertTrue(elements.isEmpty());
+
+ EModelService modelService = application.getContext().get(EModelService.class);
+ List<MApplicationElement> modelElements = modelService.findElements(application, MApplicationElement.class,
+ EModelService.ANYWHERE, new Selector() {
+ @Override
+ public boolean select(MApplicationElement element) {
+ return element.getContributorURI() != null
+ && element.getContributorURI().equals(contributorURI);
+ }
+ });
+ assertTrue(modelElements.isEmpty());
+
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests that fragments are correctly contributed to the application model.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFragments_workingFragment() throws Exception {
+ // the contributed element
+ MWindow window = MBasicFactory.INSTANCE.createWindow();
+ final String contributedElementId = "testFragments_workingFragment-contributedWindow";
+ window.setElementId(contributedElementId);
+
+ // create fragment
+ MStringModelFragment fragment = MFragmentFactory.INSTANCE.createStringModelFragment();
+ fragment.setFeaturename("children");
+ final String fragmentParentId = "org.eclipse.e4.ui.tests.modelassembler.app";
+ fragment.setParentElementId(fragmentParentId);
+ fragment.getElements().add(window);
+ // add fragment to resource
+ Resource fragmentResource = factory.createResource(URI.createURI("fragmentvirtualuri"));
+ resourceSet.getResources().add(fragmentResource);
+ fragmentResource.getContents().add((EObject) fragment);
+
+ EModelService modelService = application.getContext().get(EModelService.class);
+ assertEquals(null, modelService.find(contributedElementId, application));
+
+ final String contributorURI = "testFragments_emptyFragment_contribURI";
+ List<MApplicationElement> elements = assembler.processModelFragment(fragment, contributorURI, false);
+
+ assertEquals(window, modelService.find(contributedElementId, application));
+ assertEquals(1, elements.size());
+ assertEquals(contributorURI, elements.get(0).getContributorURI());
+ assertTrue(elements.contains(window));
+ MUIElement found = modelService.find(contributedElementId, application);
+ assertEquals(window, found);
+ assertEquals(fragmentParentId, found.getParent().getElementId());
+
+ verifyZeroInteractions(logger);
+
+
+ }
+
+ @Test
+ @Ignore // currently ignored due to bug 487748
+ public void testFragments_existingXMIID_checkExists() throws Exception {
+ // create fragment
+ MStringModelFragment fragment = MFragmentFactory.INSTANCE.createStringModelFragment();
+ fragment.setFeaturename("children");
+ fragment.setParentElementId("org.eclipse.e4.ui.tests.modelassembler.app");
+ // create fragment resource
+ E4XMIResource fragmentResource = (E4XMIResource) factory.createResource(URI.createURI("fragmentvirtualuri"));
+ resourceSet.getResources().add(fragmentResource);
+ fragmentResource.getContents().add((EObject) fragment);
+
+ final String contributedElementId = "testFragments_existingElementID-contributedWindow";
+ MWindow window1 = MBasicFactory.INSTANCE.createWindow();
+ window1.setElementId(contributedElementId);
+ MWindow window2 = MBasicFactory.INSTANCE.createWindow();
+ window2.setElementId(contributedElementId);
+
+ // add window1 to app and window2 to fragment
+ application.getChildren().add(window1);
+ fragment.getElements().add(window2);
+
+ // set the same resource xmi id to window1 and window2
+ final String xmiId = "testFragments_existingXMIID_XMIID";
+ appResource.setID((EObject) window1, xmiId);
+ fragmentResource.setID((EObject) window2, xmiId);
+ final String contributorURI = "testFragments_existingElementID_contribURI";
+ window1.setContributorURI(contributorURI);
+ window2.setContributorURI(contributorURI);
+ List<MApplicationElement> elements = assembler.processModelFragment(fragment,
+ contributorURI, true);
+
+ // fragment wasn't merged as the contributed element was already part of
+ // the application model
+ assertEquals(0, elements.size());
+ EModelService modelService = application.getContext().get(EModelService.class);
+ MUIElement found = modelService.find(contributedElementId, application);
+ assertEquals(window1, found);
+
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests that fragments configured to be always merged are correctly
+ * contributed to the application model, even if the model already contains
+ * the contributed element.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFragments_existingXMIID_ignoreExists() throws Exception {
+ // create fragment
+ MStringModelFragment fragment = MFragmentFactory.INSTANCE.createStringModelFragment();
+ fragment.setFeaturename("children");
+ fragment.setParentElementId("org.eclipse.e4.ui.tests.modelassembler.app");
+ // create fragment resource
+ E4XMIResource fragmentResource = (E4XMIResource) factory.createResource(URI.createURI("fragmentvirtualuri"));
+ resourceSet.getResources().add(fragmentResource);
+ fragmentResource.getContents().add((EObject) fragment);
+
+ final String contributedElementId = "testFragments_existingElementID-contributedWindow";
+ MWindow window1 = MBasicFactory.INSTANCE.createWindow();
+ window1.setElementId(contributedElementId);
+ MWindow window2 = MBasicFactory.INSTANCE.createWindow();
+ window2.setElementId(contributedElementId);
+
+ // add window1 to app and window2 to fragment
+ application.getChildren().add(window1);
+ fragment.getElements().add(window2);
+
+ // set the same resource xmi id to window1 and window2
+ final String xmiId = "testFragments_existingXMIID_XMIID";
+ appResource.setID((EObject) window1, xmiId);
+ fragmentResource.setID((EObject) window2, xmiId);
+
+ final String contributorID = "testFragments_existingElementID_contribURI";
+ List<MApplicationElement> elements = assembler.processModelFragment(fragment, contributorID, false);
+
+ assertEquals(elements.size(), 1);
+ EModelService modelService = application.getContext().get(EModelService.class);
+ MUIElement found = modelService.find(contributedElementId, application);
+ assertEquals(found, window2);
+ assertEquals(contributorID, found.getContributorURI());
+
+ verifyZeroInteractions(logger);
+ }
+
+ /** Tests that correctly configured imports are correctly handled. */
+ @Test
+ public void testImports() {
+ List<MApplicationElement> imports = new ArrayList<MApplicationElement>();
+ List<MApplicationElement> addedElements = new ArrayList<MApplicationElement>();
+
+ final String windowElementId = "testImports_emptyList_window1";
+ MTrimmedWindow importWindow1 = MBasicFactory.INSTANCE.createTrimmedWindow();
+ importWindow1.setElementId(windowElementId);
+ MModelFragments fragment = MFragmentFactory.INSTANCE.createModelFragments();
+ fragment.getImports().add(importWindow1);
+ imports.add(importWindow1);
+
+ MTrimmedWindow realWindow1 = MBasicFactory.INSTANCE.createTrimmedWindow();
+ realWindow1.setElementId(windowElementId);
+ application.getChildren().add(realWindow1);
+
+ MPlaceholder placeholder = MAdvancedFactory.INSTANCE.createPlaceholder();
+ placeholder.setRef(importWindow1);
+ addedElements.add(placeholder);
+
+ assembler.resolveImports(imports, addedElements);
+ assertEquals(realWindow1, placeholder.getRef());
+ verifyZeroInteractions(logger);
+ }
+
+ /** Tests the processing of an import with a null/incorrect element id. */
+ @Test
+ public void testImports_noImportElementId() {
+ List<MApplicationElement> imports = new ArrayList<MApplicationElement>();
+ List<MApplicationElement> addedElements = new ArrayList<MApplicationElement>();
+
+ MTrimmedWindow importWindow1 = MBasicFactory.INSTANCE.createTrimmedWindow();
+ importWindow1.setElementId(null);
+ MModelFragments fragment = MFragmentFactory.INSTANCE.createModelFragments();
+ fragment.getImports().add(importWindow1);
+ imports.add(importWindow1);
+ MTrimmedWindow realWindow1 = MBasicFactory.INSTANCE.createTrimmedWindow();
+ realWindow1.setElementId("testImports_emptyList_window1");
+ application.getChildren().add(realWindow1);
+
+ MPlaceholder placeholder = MAdvancedFactory.INSTANCE.createPlaceholder();
+ placeholder.setRef(importWindow1);
+ addedElements.add(placeholder);
+
+ assembler.resolveImports(imports, addedElements);
+ assertEquals(null, placeholder.getRef());
+ verify(logger).warn("Could not resolve an import element for 'null'");
+ verify(logger).warn("Could not resolve import for null");
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests that pre-processors running from a non-persisted state that are
+ * marked as "always" are executed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPreProcessor_nonPersistedState_always() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", true, false);
+ assertEquals(1, application.getDescriptors().size());
+ assertEquals("simpleprocessor.pre", application.getDescriptors().get(0).getElementId());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests that pre-processors running from a persisted state that are marked
+ * as "always" are executed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPreProcessor_persistedState_always() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", false, false);
+ assertEquals(1, application.getDescriptors().size());
+ assertEquals("simpleprocessor.pre", application.getDescriptors().get(0).getElementId());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests that pre-processors running from a non-persisted state and marked
+ * as "initial" are executed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPreProcessor_nonPersistedState_initial() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", true, false);
+ assertEquals(1, application.getDescriptors().size());
+ assertEquals("simpleprocessor.pre", application.getDescriptors().get(0).getElementId());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests that pre-processors running from a persisted state and marked as
+ * "initial" are not executed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPreProcessor_persistedState_initial() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", false, false);
+ assertEquals(0, application.getDescriptors().size());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests the execution of post-processors that should always be applied,
+ * running from a persisted state.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPostProcessor_persistedState_always() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", false, true);
+ assertEquals(1, application.getDescriptors().size());
+ assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests the execution of post-processors that should always be applied,
+ * running from a non-persisted state.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPostProcessor_nonPersistedState_always() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", true, true);
+ assertEquals(1, application.getDescriptors().size());
+ assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests the execution of post-processors running from a non-persisted state
+ * declared to be applied as "initial".
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPostProcessor_NonPersistedState_initial() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", true, true);
+ assertEquals(1, application.getDescriptors().size());
+ assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Processors running from a persisted state declared to be applied as
+ * "initial" should not be run.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPostProcessor_persistedState_initial() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", false, true);
+ assertEquals(0, application.getDescriptors().size());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Test handling of processor contribution without any processor class. A
+ * warning should be logged in such cases.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testProcessor_noProcessor() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processor_null.xml", true, false);
+ verify(logger).warn("Unable to create processor null from org.eclipse.e4.ui.tests");
+ assertEquals(0, application.getDescriptors().size());
+ verifyZeroInteractions(logger);
+ }
+
+ /**
+ * Tests a contribution containing an nonexistent processor class. A warning
+ * should be logged in such cases.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testProcessor_processorNotFound() throws Exception {
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processor_wrongProcessorClass.xml", true, false);
+ verify(logger).warn(
+ "Unable to create processor org.eclipse.e4.ui.tests.workbench.SimplePreProcessor_NotFound from org.eclipse.e4.ui.tests");
+ assertEquals(0, application.getDescriptors().size());
+ verifyZeroInteractions(logger);
+ }
+
+
+ /**
+ * Tests a processor contribution that adds to the context an element with
+ * an id that does not exist in the application model. A warning should be
+ * logged, but the processors should still be executed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testProcessor_wrongAppId() throws Exception {
+ application.setElementId("newID");
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", true, true);
+ verify(logger).warn("Could not find element with id 'org.eclipse.e4.ui.tests.modelassembler.app'");
+ verifyZeroInteractions(logger);
+ assertEquals(1, application.getDescriptors().size());
+ assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
+ }
+
+ private void testProcessor(String filePath, boolean initial, boolean afterFragments) throws Exception {
+ IContributor contributor = ContributorFactorySimple.createContributor(BUNDLE_SYMBOLIC_NAME);
+ IExtensionRegistry registry = createTestExtensionRegistry();
+ assertEquals(0, registry.getConfigurationElementsFor(EXTENSION_POINT_ID).length);
+ registry.addContribution(getContentsAsInputStream(filePath), contributor, false, null, null, null);
+ IExtensionPoint extPoint = registry.getExtensionPoint(EXTENSION_POINT_ID);
+ IExtension[] extensions = new ExtensionsSort().sort(extPoint.getExtensions());
+ assertEquals(0, application.getDescriptors().size());
+ assembler.runProcessors(extensions, initial, afterFragments);
+ }
+
+ private IExtensionRegistry createTestExtensionRegistry() {
+ IExtensionRegistry defaultRegistry = RegistryFactory.getRegistry();
+ IExtensionPoint extensionPoint = defaultRegistry.getExtensionPoint(EXTENSION_POINT_ID);
+ ExtensionRegistry registry = (ExtensionRegistry) RegistryFactory.createRegistry(null, null, null);
+ registry.addExtensionPoint(extensionPoint.getUniqueIdentifier(), extensionPoint.getContributor(), false,
+ extensionPoint.getLabel(), extensionPoint.getSchemaReference(), null);
+ appContext.set(IExtensionRegistry.class, registry);
+ return registry;
+ }
+
+ private InputStream getContentsAsInputStream(String filePath) throws IOException {
+ URI uri = URI.createPlatformPluginURI(filePath, true);
+ return URIConverter.INSTANCE.createInputStream(uri);
+ }
+}
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePostProcessor.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePostProcessor.java
new file mode 100644
index 00000000000..e6fae0c5b2c
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePostProcessor.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EclipseSource Muenchen GmbH 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:
+ * Alexandra Buzila - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.tests.workbench;
+
+class SimplePostProcessor extends SimpleProcessor {
+
+ @Override
+ public String getDescriptorId() {
+ return "simpleprocessor.post";
+ }
+
+}
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePreProcessor.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePreProcessor.java
new file mode 100644
index 00000000000..790f5cfff4f
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimplePreProcessor.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EclipseSource Muenchen GmbH 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:
+ * Alexandra Buzila - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.tests.workbench;
+
+class SimplePreProcessor extends SimpleProcessor {
+ @Override
+ public String getDescriptorId() {
+ return "simpleprocessor.pre";
+ }
+
+}
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimpleProcessor.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimpleProcessor.java
new file mode 100644
index 00000000000..601ce062717
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/SimpleProcessor.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EclipseSource Muenchen GmbH 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:
+ * Alexandra Buzila - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.tests.workbench;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MBasicFactory;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+
+abstract class SimpleProcessor {
+ @Inject
+ private MApplication application;
+
+ @Execute
+ public void run() {
+ if (application != null) {
+ MPartDescriptor descriptor = MBasicFactory.INSTANCE.createPartDescriptor();
+ descriptor.setElementId(getDescriptorId());
+ application.getDescriptors().add(descriptor);
+ }
+ }
+
+ public abstract String getDescriptorId();
+}

Back to the top