diff options
| author | Alexandra Buzila | 2016-02-12 17:02:31 +0000 |
|---|---|---|
| committer | Jonas Helming | 2016-03-29 16:31:24 +0000 |
| commit | c2f3d33e6f34013650a63fa401e7f5d9c0b89b76 (patch) | |
| tree | 2e87ced8cb6ff1e20e133bac8c8467af2737f721 | |
| parent | ba81c58c3341210b58a45dd084ab8dbe5aaad430 (diff) | |
| download | eclipse.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>
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(); +} |
