diff options
author | Christian W. Damus | 2014-06-11 20:21:34 +0000 |
---|---|---|
committer | Christian W. Damus | 2014-07-21 14:58:30 +0000 |
commit | 5ab06e3232056fdea6708b153e2c22d4b99eaa14 (patch) | |
tree | b60e5e91a8d531f81b62bcdf538afb98ca906fbe | |
parent | 029e4b677bf9ad7a919565c55d1c4ed3128e5cb4 (diff) | |
download | org.eclipse.papyrus-5ab06e3232056fdea6708b153e2c22d4b99eaa14.tar.gz org.eclipse.papyrus-5ab06e3232056fdea6708b153e2c22d4b99eaa14.tar.xz org.eclipse.papyrus-5ab06e3232056fdea6708b153e2c22d4b99eaa14.zip |
437052: [CDO] Support resource modification tracking for non-CDO
resources
https://bugs.eclipse.org/bugs/show_bug.cgi?id=437052
Restore the resource modification-tracking-based strategy in the
ModelSet's save logic. IModel implementations delegate the question of
whether a resource needs to be saved to the ModelSet via a new
"shouldSave(Resource) : boolean" API.
The ModelSet, in turn, delegates the question of whether a resource
needs to be saved to its ProxyModificationTrackingAdapter, which latter
is now specialized by the CDOAwareModelSet to take into account the save
semantics of CDOResources. For a ModelSet that is not tracking resource
modifications, and therefore does not have this adapter, it simply
assumes that any resource that can be saved needs to be saved.
Change-Id: Ia651b38f09d7dade435a8738b8a4a7f25e50af1b
13 files changed, 1172 insertions, 528 deletions
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java index bee114137cd..cfc43f96173 100644 --- a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java +++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java @@ -10,6 +10,7 @@ * CEA LIST - Initial API and implementation * Christian W. Damus (CEA) - bug 429242 * Christian W. Damus (CEA) - bug 422257 + * Christian W. Damus (CEA) - bug 437052 * *****************************************************************************/ package org.eclipse.papyrus.cdo.core.resource; @@ -77,13 +78,15 @@ public class CDOAwareModelSet extends OnDemandLoadingModelSet { super(); this.resources = new SafeResourceList(); - - setTrackingModification(false); - this.repositoryManager = repositoryManager; } @Override + protected Adapter createModificationTrackingAdapter() { + return new CDOAwareProxyModificationTrackingAdapter(); + } + + @Override public EObject getEObject(URI uri, boolean loadOnDemand) { return CDOUtils.isCDOURI(uri) ? getCDOObject(uri, loadOnDemand) : super.getEObject(uri, loadOnDemand); } diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareProxyModificationTrackingAdapter.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareProxyModificationTrackingAdapter.java new file mode 100644 index 00000000000..2f449b3403b --- /dev/null +++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareProxyModificationTrackingAdapter.java @@ -0,0 +1,64 @@ +/***************************************************************************** + * Copyright (c) 2014 CEA LIST. + * + * 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: + * CEA LIST - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.cdo.core.resource; + +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.view.CDOView; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.papyrus.infra.core.resource.ProxyModificationTrackingAdapter; + + +/** + * A specialization of the {@link ProxyModificationTrackingAdapter} that knows how to deal with + * CDO resources. In particular, that their dirty/save semantics is completely different from + * that of workspace resources. + */ +public class CDOAwareProxyModificationTrackingAdapter extends ProxyModificationTrackingAdapter { + + public CDOAwareProxyModificationTrackingAdapter() { + super(); + } + + @Override + public boolean shouldSave(Resource resource) { + boolean result; + + if(resource instanceof CDOResource) { + CDOView view = ((CDOResource)resource).cdoView(); + if(view instanceof CDOTransaction) { + // Saving CDO resources is done by committing the transaction + result = ((CDOTransaction)view).isDirty(); + } else { + // If there's no view or it's not a transaction, then saving is a non-starter + result = false; + } + } else { + result = super.shouldSave(resource); + } + + return result; + } + + @Override + public void notifyChanged(Notification msg) { + Object notifier = msg.getNotifier(); + + // Only for non-CDO resources do we care if the URI has changed or contents been added, because + // references within the repository use OIDs and are, therefore, not susceptible to URI changes + if(!(notifier instanceof CDOResource)) { + super.notifyChanged(msg); + } + } + +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractBaseModel.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractBaseModel.java index af63fc6987a..0e06f9ecb90 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractBaseModel.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractBaseModel.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2013 CEA LIST and others. + * Copyright (c) 2010, 2014 CEA LIST and others. * * * All rights reserved. This program and the accompanying materials @@ -10,6 +10,7 @@ * Contributors: * CEA LIST - Initial API and implementation * Christian W. Damus (CEA) - manage models by URI, not IFile (CDO) + * Christian W. Damus (CEA) - bug 437052 * *****************************************************************************/ package org.eclipse.papyrus.infra.core.resource; @@ -223,7 +224,7 @@ public abstract class AbstractBaseModel extends AbstractModel implements IVersio */ @Override public void saveModel() throws IOException { - if(!getModelManager().getTransactionalEditingDomain().isReadOnly(resource) && !ModelUtils.resourceFailedOnLoad(resource)) { + if(getModelManager().shouldSave(resource)) { resource.save(null); } } diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/EMFLogicalModel.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/EMFLogicalModel.java index 9c96ac90e00..e24f0730d94 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/EMFLogicalModel.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/EMFLogicalModel.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437052
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.core.resource;
@@ -52,8 +54,10 @@ public abstract class EMFLogicalModel extends AbstractBaseModel implements IEMFM @Override
public void saveModel() throws IOException {
+ final ModelSet set = getModelManager();
+
for(Resource resource : getResources()) {
- if(!getModelManager().getTransactionalEditingDomain().isReadOnly(resource) && !ModelUtils.resourceFailedOnLoad(resource)) {
+ if(set.shouldSave(resource)) {
try {
resource.save(null);
} catch (IOException ex) {
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java index e0c17b97958..098e048e8e8 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java @@ -16,6 +16,7 @@ * Christian W. Damus (CEA LIST) - Controlled resources in CDO repositories * Christian W. Damus (CEA) - bug 429826 * Christian W. Damus (CEA) - bug 432813 + * Christian W. Damus (CEA) - bug 437052 * *****************************************************************************/ package org.eclipse.papyrus.infra.core.resource; @@ -255,6 +256,36 @@ public class ModelSet extends ResourceSetImpl { } /** + * Queries whether a {@code resource} managed by me is either known to be or assumed to be needing to be saved. + * Generally this is true for resources that have been modified since the last save and that are saveable + * (not read-only and correctly and completely loaded in the first place). + * + * @param resource + * a resource that I manage + * + * @return whether the {@code resource} currently needs to be saved + */ + public boolean shouldSave(Resource resource) { + boolean result; + + if(getTransactionalEditingDomain().isReadOnly(resource) || ModelUtils.resourceFailedOnLoad(resource)) { + result = false; + } else if(!getURIConverter().exists(resource.getURI(), null)) { + // If the resource needs to be created, it needs to be saved + result = true; + } else if(modificationTrackingAdapter instanceof ProxyModificationTrackingAdapter) { + result = ((ProxyModificationTrackingAdapter)modificationTrackingAdapter).shouldSave(resource); + } else if(modificationTrackingAdapter != null) { + result = !resource.isTrackingModification() || resource.isModified(); + } else { + // Assume that the resource is modified since the last save + result = true; + } + + return result; + } + + /** * @deprecated please use {@link #getAssociatedResource(EObject, String, boolean)} instead * * @param modelElement @@ -938,7 +969,7 @@ public class ModelSet extends ResourceSetImpl { if(packageRegistry != null) { packageRegistry.clear(); } - + // Dispose Editing Domain if(transactionalEditingDomain != null) { transactionalEditingDomain.dispose(); diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ProxyModificationTrackingAdapter.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ProxyModificationTrackingAdapter.java index 58bbd3278bb..41e18ac7255 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ProxyModificationTrackingAdapter.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ProxyModificationTrackingAdapter.java @@ -9,12 +9,13 @@ * Contributors: * Mathieu Velten (Atos) mathieu.velten@atos.net - Initial API and implementation * Christian W. Damus (CEA) - bug 432753 + * Christian W. Damus (CEA) - bug 437052 * *****************************************************************************/ package org.eclipse.papyrus.infra.core.resource; -import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import org.eclipse.emf.common.notify.Notification; @@ -25,7 +26,6 @@ import org.eclipse.emf.ecore.EStructuralFeature.Setting; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.papyrus.infra.core.utils.EMFHelper; /** * This adapter handles "modified" flag of resources for tricky cases : @@ -44,6 +44,20 @@ import org.eclipse.papyrus.infra.core.utils.EMFHelper; */ public class ProxyModificationTrackingAdapter extends EContentAdapter { + /** + * Queries whether a {@code resource} tracked by me is either known to be or assumed to be needing to be saved. + * Generally this is true for resources that have been modified since the last save and that are saveable + * (not read-only and correctly and completely loaded in the first place). + * + * @param resource + * a resource that I track + * + * @return whether the {@code resource} should be saved + */ + public boolean shouldSave(Resource resource) { + return !resource.isTrackingModification() || resource.isModified(); + } + @Override protected void setTarget(Resource target) { basicSetTarget(target); @@ -81,7 +95,7 @@ public class ProxyModificationTrackingAdapter extends EContentAdapter { } } else { - List objects = new ArrayList(); + List<?> objects; switch(n.getEventType()) { case Notification.ADD_MANY: @@ -91,10 +105,13 @@ public class ProxyModificationTrackingAdapter extends EContentAdapter { objects = (List<?>)n.getOldValue(); break; case Notification.ADD: - objects.add(n.getNewValue()); + objects = Collections.singletonList(n.getNewValue()); break; case Notification.REMOVE: - objects.add(n.getOldValue()); + objects = Collections.singletonList(n.getOldValue()); + break; + default: + objects = Collections.emptyList(); break; } @@ -122,7 +139,7 @@ public class ProxyModificationTrackingAdapter extends EContentAdapter { } protected void setReferencingResourcesAsModified(EObject eObj) { - Collection<Setting> references = EMFHelper.getUsages(eObj); + Collection<Setting> references = org.eclipse.papyrus.infra.core.utils.EMFHelper.getUsages(eObj); for (Setting setting : references) { EStructuralFeature f = setting.getEStructuralFeature(); if(setting.getEObject() != null && !f.isDerived() && !f.isTransient()) { diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/additional/AdditionalResourcesModel.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/additional/AdditionalResourcesModel.java index d21339d6c7a..b09dc5c9411 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/additional/AdditionalResourcesModel.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/additional/AdditionalResourcesModel.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2013 Atos Origin, CEA LIST, and others. + * Copyright (c) 2010, 2014 Atos Origin, CEA LIST, and others. * * * All rights reserved. This program and the accompanying materials @@ -11,6 +11,7 @@ * Emilien Perico emilien.perico@atosorigin.com - manage loading strategies * Christian W. Damus (CEA) - manage models by URI, not IFile (CDO) * Christian W. Damus (CEA LIST) - support control mode in CDO resources + * Christian W. Damus (CEA) - bug 437052 * *****************************************************************************/ package org.eclipse.papyrus.infra.core.resource.additional; @@ -29,7 +30,6 @@ import org.eclipse.emf.ecore.xmi.impl.URIHandlerImpl; import org.eclipse.papyrus.infra.core.resource.AbstractModel; import org.eclipse.papyrus.infra.core.resource.IModel; import org.eclipse.papyrus.infra.core.resource.ModelSet; -import org.eclipse.papyrus.infra.core.resource.ModelUtils; public class AdditionalResourcesModel extends AbstractModel implements IModel { @@ -80,10 +80,10 @@ public class AdditionalResourcesModel extends AbstractModel implements IModel { if(isAdditionalResource(getModelManager(), r.getURI())) { // only save referenced models not // read-only and either platform or file - if(!modelSet.getTransactionalEditingDomain().isReadOnly(r) && modelSet.isUserModelResource(r.getURI()) && !ModelUtils.resourceFailedOnLoad(r)) { - if(r instanceof XMIResource){ + if(modelSet.shouldSave(r) && modelSet.isUserModelResource(r.getURI())) { + if(r instanceof XMIResource) { r.save(Collections.singletonMap(XMLResource.OPTION_URI_HANDLER, new URIHandlerImpl.PlatformSchemeAware())); - }else { + } else { r.save(Collections.EMPTY_MAP); } @@ -136,7 +136,7 @@ public class AdditionalResourcesModel extends AbstractModel implements IModel { Set<URI> res = new HashSet<URI>(); for(Resource r : modelSet.getResources()) { if(isAdditionalResource(getModelManager(), r.getURI())) { - if (!r.isTrackingModification() || r.isModified()) { + if(!r.isTrackingModification() || r.isModified()) { res.add(r.getURI()); } } diff --git a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java index 925a496df09..0199366a4f3 100644 --- a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java +++ b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java @@ -27,18 +27,27 @@ import static org.junit.Assume.assumeThat; import java.util.Collections; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.net4j.util.lifecycle.LifecycleException; import org.eclipse.papyrus.cdo.core.resource.CDOAwareModelSet; import org.eclipse.papyrus.cdo.core.resource.CDOAwareTransactionalEditingDomain; import org.eclipse.papyrus.cdo.core.resource.PapyrusCDOResourceFactory; import org.eclipse.papyrus.cdo.core.tests.AbstractPapyrusCDOTest; +import org.eclipse.papyrus.cdo.internal.core.PapyrusRepositoryManager; import org.eclipse.papyrus.infra.core.Activator; import org.eclipse.papyrus.infra.core.resource.ModelSet; import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis; @@ -46,6 +55,10 @@ import org.eclipse.papyrus.infra.core.services.ExtensionServicesRegistry; import org.eclipse.papyrus.infra.core.services.ServiceMultiException; import org.eclipse.papyrus.infra.core.services.ServiceNotFoundException; import org.eclipse.papyrus.infra.core.services.ServicesRegistry; +import org.eclipse.papyrus.infra.core.utils.TransactionHelper; +import org.eclipse.papyrus.junit.utils.ModelUtils; +import org.eclipse.papyrus.junit.utils.resources.EcoreModel; +import org.eclipse.papyrus.junit.utils.resources.WorkspaceModificationAssertion; import org.eclipse.uml2.uml.Model; import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.UMLFactory; @@ -165,6 +178,126 @@ public class CDOAwareModelSetTest extends AbstractPapyrusCDOTest { assertThat(imported.getName(), equalTo("model1")); } + /** + * Tests that only modified workspace resources are saved, where we have only one model (no referenced libraries). + */ + @Test + public void testSave_onlyModifiedWorkspaceResources1() throws Exception { + final TransactionalEditingDomain domain = fixture.getTransactionalEditingDomain(); + + EcoreModel model = new EcoreModel(); + + fixture.registerModel(model); + + IProject p = houseKeeper.createProject(houseKeeper.getTestName()); + + final IFile modelFile = p.getFile("ecore1." + model.getModelFileExtension()); + final URI modelURI = URI.createPlatformResourceURI(modelFile.getFullPath().toString(), true); + + final WorkspaceModificationAssertion mods = new WorkspaceModificationAssertion(houseKeeper); + + fixture.createModels(modelURI); + mods.save(fixture); + + assertThat("workspace resource not created", modelFile.exists(), is(true)); + + assertThat("EMF resource is null", model.getResource(), notNullValue()); + assertThat("EMF resource not created", model.getResource().getContents().isEmpty(), is(false)); + + EPackage ePackage = model.getRoot(); + domain.getCommandStack().execute(SetCommand.create(domain, ePackage, EcorePackage.Literals.ENAMED_ELEMENT__NAME, "newname")); + + mods.requireChange(modelURI); + mods.save(fixture); + + // Saving again should have no effect on the workspace + mods.requireNoChange(modelURI); + mods.save(fixture); + } + + /** + * Tests that only modified workspace resources are saved, where we have multiple models (referenced libraries). + */ + @Test + public void testSave_onlyModifiedWorkspaceResources2() throws Exception { + final TransactionalEditingDomain domain = fixture.getTransactionalEditingDomain(); + + final EcoreModel model = new EcoreModel(); + + fixture.registerModel(model); + + IProject p = houseKeeper.createProject(houseKeeper.getTestName()); + + final IFile modelFile1 = p.getFile("ecore1." + model.getModelFileExtension()); + final URI modelURI1 = URI.createPlatformResourceURI(modelFile1.getFullPath().toString(), true); + + final IFile modelFile2 = p.getFile("ecore2." + model.getModelFileExtension()); + final URI modelURI2 = URI.createPlatformResourceURI(modelFile2.getFullPath().toString(), true); + + final WorkspaceModificationAssertion mods = new WorkspaceModificationAssertion(houseKeeper); + + fixture.createModels(modelURI1); + + // Set up a second model and a dependency from the first + final Resource res2 = fixture.createResource(modelURI2, EcorePackage.eCONTENT_TYPE); + TransactionHelper.run(domain, new Runnable() { + + @Override + public void run() { + EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage(); + ePackage.setName("library"); + ePackage.setNsPrefix("lib"); + ePackage.setNsURI("http://www.eclipse.org/papyrus/test/fakemodel/ecore/library"); + res2.getContents().add(ePackage); + + // A class in the library model + EClass foo = EcoreFactory.eINSTANCE.createEClass(); + foo.setName("Foo"); + ePackage.getEClassifiers().add(foo); + + // A class in the main model + EClass thing = EcoreFactory.eINSTANCE.createEClass(); + thing.setName("Thing"); + model.getRoot().getEClassifiers().add(thing); + + EReference reference = EcoreFactory.eINSTANCE.createEReference(); + reference.setName("foo"); + reference.setEType(foo); + thing.getEStructuralFeatures().add(reference); + } + }); + + // We need this referenced model to be writable in order to save it + ModelUtils.makeReferencedModelsWritable(fixture, modelURI2); + mods.save(fixture); + + assertThat("workspace resource not created", modelFile1.exists(), is(true)); + assertThat("workspace resource not created", modelFile2.exists(), is(true)); + + assertThat("EMF resource is null", model.getResource(), notNullValue()); + assertThat("EMF resource not created", model.getResource().getContents().isEmpty(), is(false)); + assertThat("EMF resource not created", res2.getContents().isEmpty(), is(false)); + + // Change the referenced resource's URI. This should make the resource and its dependents dirty + final URI modelURI2New = modelURI2.trimSegments(1).appendSegment("library1").appendFileExtension(model.getModelFileExtension()); + res2.setURI(modelURI2New); + + ModelUtils.makeReferencedModelsWritable(fixture, modelURI2New); + mods.requireChange(modelURI1); // Thanks to the ProxyModificationTrackingAdapter + mods.requireChange(modelURI2New); + mods.requireNoChange(modelURI2); // No longer an interesting URI + mods.save(fixture); + + EPackage ePackage = model.getRoot(); + domain.getCommandStack().execute(SetCommand.create(domain, ePackage, EcorePackage.Literals.ENAMED_ELEMENT__NAME, "newname")); + + // Saving this should have no effect on the second resource + mods.requireChange(modelURI1); + mods.requireNoChange(modelURI2New); + mods.requireNoChange(modelURI2); + mods.save(fixture); + } + // // Test framework // @@ -174,6 +307,9 @@ public class CDOAwareModelSetTest extends AbstractPapyrusCDOTest { services = new ExtensionServicesRegistry(Activator.PLUGIN_ID); try { + // Ensure that the CDOAwareModelSet is the ModelSet service implementation + services.add(ModelSet.class, Integer.MAX_VALUE, new CDOAwareModelSet(PapyrusRepositoryManager.INSTANCE)); + // start the ModelSet and its dependencies services.startServicesByClassKeys(ModelSet.class, TransactionalEditingDomain.class); } catch (ServiceMultiException e) { @@ -183,6 +319,7 @@ public class CDOAwareModelSetTest extends AbstractPapyrusCDOTest { } fixture = services.getService(ModelSet.class); + assertThat(fixture, instanceOf(CDOAwareModelSet.class)); // pre-emptively get the editing domain to avoid lock contention later services.getService(TransactionalEditingDomain.class); diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/resource/ModelSetTest.java b/tests/junit/plugins/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/resource/ModelSetTest.java index 2e6f943d9a9..bdd8c2be593 100644 --- a/tests/junit/plugins/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/resource/ModelSetTest.java +++ b/tests/junit/plugins/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/resource/ModelSetTest.java @@ -1,507 +1,643 @@ -/*****************************************************************************
- * Copyright (c) 2010, 2014 LIFL, CEA, and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * LIFL - Initial API and implementation
- * Christian W. Damus (CEA) - bug 422257
- * Christian W. Damus (CEA) - bug 436047
- *
- *****************************************************************************/
-package org.eclipse.papyrus.infra.core.resource;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EcoreFactory;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.papyrus.junit.utils.rules.HouseKeeper;
-import org.eclipse.papyrus.junit.utils.tests.AbstractPapyrusTest;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-/**
- * Test for {@link ModelSet}. <br>
- * Run as "JUnit Plugin-Test"
- *
- * @author cedric dumoulin
- *
- */
-public class ModelSetTest extends AbstractPapyrusTest {
-
- /**
- * Name of the plugin that is created.
- */
- final protected String PLUGIN_PROJECT_NAME = "org.eclipse.papyrus.infra.core";
-
- @Rule
- public final HouseKeeper houseKeeper = new HouseKeeper();
-
- /**
- *
- * @throws Exception
- */
- @Before
- public void setUp() throws Exception {
- }
-
- /**
- *
- * @throws Exception
- */
- @After
- public void tearDown() throws Exception {
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet.registerModel(IModel)} .
- */
- @Test
- public void testRegisterModel() {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- FakeModel model1 = new FakeModel("model1");
-
- mngr.registerModel(model1);
-
- assertNotNull("mngr is set", model1.getModelManager());
- assertNotNull("model is registered", mngr.getModel("model1"));
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#getModel(String)} .
- */
- @Test
- public void testGetModel() {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- FakeModel model1 = new FakeModel("model1");
- FakeModel model2 = new FakeModel("model2");
-
- mngr.registerModel(model1);
- mngr.registerModel(model2);
-
- assertNotNull("model is registered", mngr.getModel("model1"));
- assertNotNull("model is registered", mngr.getModel("model2"));
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#getTransactionalEditingDomain()} .
- */
- @Test
- public void testGetTransactionalEditingDomain() {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- assertNotNull("editing domain created", mngr.getTransactionalEditingDomain());
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#createsModels(IFile)} .
- */
- @Test
- public void testCreatesModels() throws IOException, CoreException {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- String model1Key = "ecore";
- String model2Key = "genmodel";
-
- FakeModel model1 = new FakeModel(model1Key);
- FakeModel model2 = new FakeModel(model2Key);
-
- mngr.registerModel(model1);
- mngr.registerModel(model2);
-
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
-
- IFile model1File = p.getFile("tmp/model1." + model1Key);
-
- // Do create
- mngr.createsModels(model1File);
-
- assertNotNull("resource created", model1.getResource());
- assertNotNull("resource created", model2.getResource());
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#loadModels(IFile)} .
- *
- * @throws ModelMultiException
- */
- @Test
- public void testLoadModels() throws IOException, CoreException, ModelMultiException {
-
- // Create models so they exists
- testSave();
-
- // Now do load
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- String model1Key = "ecore";
- String model2Key = "genmodel";
-
- FakeModel model1 = new FakeModel(model1Key);
- FakeModel model2 = new FakeModel(model2Key);
-
- mngr.registerModel(model1);
- mngr.registerModel(model2);
-
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
-
- IFile model1File = p.getFile("tmp/model1." + model1Key);
- IFile model2File = p.getFile("tmp/model1." + model2Key);
-
- assertTrue("modelFile exist", model1File.exists());
- assertTrue("modelFile exist", model2File.exists());
-
- // Try to load
- mngr.loadModels(model1File);
-
- assertNotNull("resource created", model1.getResource());
- assertNotNull("resource created", model2.getResource());
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#save(IProgressMonitor)} .
- */
- @Test
- public void testSave() throws CoreException, IOException {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- String model1Key = "ecore";
- String model2Key = "genmodel";
-
- FakeModel model1 = new FakeModel(model1Key);
- FakeModel model2 = new FakeModel(model2Key);
-
- mngr.registerModel(model1);
- mngr.registerModel(model2);
-
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
- if(!p.exists()) {
- p.create(new NullProgressMonitor());
- }
- p.open(new NullProgressMonitor());
-
- IFile model1File = p.getFile("tmp/model1." + model1Key);
- IFile model2File = p.getFile("tmp/model1." + model2Key);
-
- // Do create and save
- mngr.createsModels(model1File);
- mngr.save(new NullProgressMonitor());
- //
- assertTrue("resource created", model1File.exists());
- assertTrue("resource created", model2File.exists());
- //
- assertNotNull("resource created", model1.getResource());
- assertNotNull("resource created", model2.getResource());
- }
-
- /**
- * Create some Resources for other test. This method should be called explicitly.
- *
- * @throws CoreException
- * @throws IOException
- */
- protected void createResources(String... filenames) throws CoreException, IOException {
-
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(PLUGIN_PROJECT_NAME);
- if(!p.exists()) {
- p.create(new NullProgressMonitor());
- }
- p.open(new NullProgressMonitor());
-
- ResourceSet resourceSet = houseKeeper.createResourceSet();
-
- for(String filename : filenames) {
- createResource(p, resourceSet, filename);
- }
-
- // Save created resources
- for(Resource resource : resourceSet.getResources()) {
- resource.save(null);
- }
- }
-
-
- /**
- * Create a resource.
- *
- * @param p
- * @param resourceSet
- * @param filename
- */
- private void createResource(IProject p, ResourceSet resourceSet, String filename) {
-
- // Build a valid file
- IFile file = p.getFile(filename);
-
-
- URI uri = URI.createPlatformResourceURI(file.getFullPath().toOSString(), true);
- resourceSet.createResource(uri);
-
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#saveAs(IPath)} .
- */
- @Test
- public void testSaveAs() throws CoreException, IOException {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- String model1Key = "ecore";
- String model2Key = "genmodel";
-
- FakeModel model1 = new FakeModel(model1Key);
- FakeModel model2 = new FakeModel(model2Key);
-
- mngr.registerModel(model1);
- mngr.registerModel(model2);
-
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
- if(!p.exists()) {
- p.create(new NullProgressMonitor());
- }
- p.open(new NullProgressMonitor());
-
- IFile model1File = p.getFile("tmp/model1." + model1Key);
-
- // Do create and save
- mngr.createsModels(model1File);
- mngr.save(new NullProgressMonitor());
-
- // Change the name
- IFile newModel1File = p.getFile("tmp/model2." + model1Key);
- IFile newModel2File = p.getFile("tmp/model2." + model2Key);
- IPath newPath = newModel1File.getFullPath();
-
- mngr.saveAs(newPath);
- // check creation
-
- assertTrue("resource created", newModel2File.exists());
- assertTrue("resource created", newModel2File.exists());
- //
- assertNotNull("resource created", model1.getResource());
- assertNotNull("resource created", model2.getResource());
-
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#unload()} .
- */
- @Test
- public void testUnload() {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- String model1Key = "ecore";
- String model2Key = "genmodel";
-
- FakeModel model1 = new FakeModel(model1Key);
- FakeModel model2 = new FakeModel(model2Key);
-
- mngr.registerModel(model1);
- mngr.registerModel(model2);
-
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
-
- IFile model1File = p.getFile("tmp/model1." + model1Key);
-
- // Do create and then unload
- mngr.createsModels(model1File);
- mngr.unload();
-
- assertNull("resource unloaded", model1.getResource());
- assertNull("resource unloaded", model2.getResource());
- }
-
- /**
- * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#addModelSetSnippet(IModelManagerSnippet)} .
- */
- @Test
- public void testAddModelSetSnippet() {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- // Add snippets
- TestTrace trace = new TestTrace();
- mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet1"));
- mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet2"));
-
- // Do create
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
- IFile model1File = p.getFile("tmp/model1.ecore");
- mngr.createsModels(model1File);
-
- // Check calls
- assertTrue("snippet1 called", trace.contains("snippet1", "start"));
- assertTrue("snippet2 called", trace.contains("snippet2", "start"));
-
- }
-
- /**
- * Test that snippets are called after a call to createsModels()
- */
- @Test
- public void testSnippetCalledAfterCreateModels() {
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- // Add snippets
- TestTrace trace = new TestTrace();
- mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet1"));
- mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet2"));
-
- // Do create
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
- IFile model1File = p.getFile("tmp/model1.ecore");
- mngr.createsModels(model1File);
-
- // Check calls
- assertTrue("snippet1 called", trace.contains("snippet1", "start"));
- assertTrue("snippet2 called", trace.contains("snippet2", "start"));
-
- // dispose
- mngr.unload();
- // Check calls
- assertTrue("snippet1 called", trace.contains("snippet1", "dispose"));
- assertTrue("snippet2 called", trace.contains("snippet2", "dispose"));
-
- }
-
- /**
- * Test that snippets are called after a call to loadModels()
- *
- * @throws ModelMultiException
- */
- @Test
- public void testSnippetCalledAfterLoadModels() throws ModelMultiException {
-
- // force model creation
- testSnippetCalledAfterCreateModels();
-
- // now do load.
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- // Add snippets
- TestTrace trace = new TestTrace();
- mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet1"));
- mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet2"));
-
- // Do create
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core");
- IFile model1File = p.getFile("tmp/model1.ecore");
- mngr.loadModels(model1File);
-
- // Check calls
- assertTrue("snippet1 called", trace.contains("snippet1", "start"));
- assertTrue("snippet2 called", trace.contains("snippet2", "start"));
-
- // dispose
- mngr.unload();
- // Check calls
- assertTrue("snippet1 called", trace.contains("snippet1", "dispose"));
- assertTrue("snippet2 called", trace.contains("snippet2", "dispose"));
-
- }
-
- /**
- * Test {@link #createResources(String...)}. This is a test methods :-)
- *
- * @throws ModelMultiException
- */
- @Test
- public void testCreateResource() throws IOException, CoreException, ModelMultiException {
-
- String model1Key = "ecore";
- String model2Key = "genmodel";
- String model3Key = "uml";
-
- // Create models
- createResources("tmp/model1." + model1Key, "tmp/model1." + model2Key, "tmp/model1." + model3Key);
-
- // Check model creation
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(PLUGIN_PROJECT_NAME);
-
- IFile model1File = p.getFile("tmp/model1." + model1Key);
- IFile model2File = p.getFile("tmp/model1." + model2Key);
- IFile model3File = p.getFile("tmp/model1." + model3Key);
-
- assertTrue("modelFile exist", model1File.exists());
- assertTrue("modelFile exist", model2File.exists());
- assertTrue("modelFile exist", model3File.exists());
- }
-
- /**
- * Test {@link ModelSet#importModels(ModelIdentifiers, IFile)} called after {@link ModelSet#createsModels(IFile)} .
- *
- * @throws ModelException
- */
- @Test
- public void testImportAfterCreate() throws IOException, CoreException, ModelException {
-
- String model1Key = "ecore";
- String model2Key = "genmodel";
- String model3Key = "uml";
-
- // Create models
- createResources("tmp/model1." + model1Key, "tmp/model1." + model2Key, "tmp/model1." + model3Key);
-
- // Now do registration
- ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet());
-
- FakeModel model1 = new FakeModel(model1Key);
- FakeModel model2 = new FakeModel(model2Key);
- FakeModel model3 = new FakeModel(model3Key);
-
- mngr.registerModel(model1);
- mngr.registerModel(model2);
- mngr.registerModel(model3);
-
-
- // Get an handle on one of the files
- IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(PLUGIN_PROJECT_NAME);
- IFile createdFile = p.getFile("tmp/model2." + model1Key);
-
-
- // Try to create all models
- mngr.createsModels(createdFile);
-
- assertNotNull("resource created", model1.getResource());
- assertNotNull("resource created", model2.getResource());
- assertNotNull("resource created", model3.getResource());
-
- // Add something in the model
- model1.getResource().getContents().add(EcoreFactory.eINSTANCE.createEPackage());
- assertEquals("model1 has changed", 1, model1.getResource().getContents().size());
-
- // Try to import
- IFile importFile = p.getFile("tmp/model1." + model1Key);
- mngr.importModels(new ModelIdentifiers(model1Key, model2Key), importFile);
-
- assertNotNull("resource exist", model1.getResource());
- assertNotNull("resource exist", model2.getResource());
- assertNotNull("resource exist", model3.getResource());
-
- assertEquals("model1 has changed", 0, model1.getResource().getContents().size());
-
-
- }
-
-
-}
+/***************************************************************************** + * Copyright (c) 2010, 2014 LIFL, CEA, and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * LIFL - Initial API and implementation + * Christian W. Damus (CEA) - bug 422257 + * Christian W. Damus (CEA) - bug 436047 + * Christian W. Damus (CEA) - bug 437052 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.core.resource; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.edit.command.SetCommand; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.papyrus.infra.core.resource.additional.AdditionalResourcesModel; +import org.eclipse.papyrus.infra.core.utils.TransactionHelper; +import org.eclipse.papyrus.junit.utils.ModelUtils; +import org.eclipse.papyrus.junit.utils.resources.EcoreModel; +import org.eclipse.papyrus.junit.utils.resources.WorkspaceModificationAssertion; +import org.eclipse.papyrus.junit.utils.rules.HouseKeeper; +import org.eclipse.papyrus.junit.utils.tests.AbstractPapyrusTest; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +/** + * Test for {@link ModelSet}. <br> + * Run as "JUnit Plugin-Test" + * + * @author cedric dumoulin + * + */ +public class ModelSetTest extends AbstractPapyrusTest { + + /** + * Name of the plugin that is created. + */ + final protected String PLUGIN_PROJECT_NAME = "org.eclipse.papyrus.infra.core"; + + @Rule + public final HouseKeeper houseKeeper = new HouseKeeper(); + + /** + * + * @throws Exception + */ + @Before + public void setUp() throws Exception { + } + + /** + * + * @throws Exception + */ + @After + public void tearDown() throws Exception { + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet.registerModel(IModel)} . + */ + @Test + public void testRegisterModel() { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + FakeModel model1 = new FakeModel("model1"); + + mngr.registerModel(model1); + + assertNotNull("mngr is set", model1.getModelManager()); + assertNotNull("model is registered", mngr.getModel("model1")); + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#getModel(String)} . + */ + @Test + public void testGetModel() { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + FakeModel model1 = new FakeModel("model1"); + FakeModel model2 = new FakeModel("model2"); + + mngr.registerModel(model1); + mngr.registerModel(model2); + + assertNotNull("model is registered", mngr.getModel("model1")); + assertNotNull("model is registered", mngr.getModel("model2")); + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#getTransactionalEditingDomain()} . + */ + @Test + public void testGetTransactionalEditingDomain() { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + assertNotNull("editing domain created", mngr.getTransactionalEditingDomain()); + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#createsModels(IFile)} . + */ + @Test + public void testCreatesModels() throws IOException, CoreException { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + String model1Key = "ecore"; + String model2Key = "genmodel"; + + FakeModel model1 = new FakeModel(model1Key); + FakeModel model2 = new FakeModel(model2Key); + + mngr.registerModel(model1); + mngr.registerModel(model2); + + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + + IFile model1File = p.getFile("tmp/model1." + model1Key); + + // Do create + mngr.createsModels(model1File); + + assertNotNull("resource created", model1.getResource()); + assertNotNull("resource created", model2.getResource()); + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#loadModels(IFile)} . + * + * @throws ModelMultiException + */ + @Test + public void testLoadModels() throws IOException, CoreException, ModelMultiException { + + // Create models so they exists + testSave(); + + // Now do load + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + String model1Key = "ecore"; + String model2Key = "genmodel"; + + FakeModel model1 = new FakeModel(model1Key); + FakeModel model2 = new FakeModel(model2Key); + + mngr.registerModel(model1); + mngr.registerModel(model2); + + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + + IFile model1File = p.getFile("tmp/model1." + model1Key); + IFile model2File = p.getFile("tmp/model1." + model2Key); + + assertTrue("modelFile exist", model1File.exists()); + assertTrue("modelFile exist", model2File.exists()); + + // Try to load + mngr.loadModels(model1File); + + assertNotNull("resource created", model1.getResource()); + assertNotNull("resource created", model2.getResource()); + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#save(IProgressMonitor)} . + */ + @Test + public void testSave() throws CoreException, IOException { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + String model1Key = "ecore"; + String model2Key = "genmodel"; + + FakeModel model1 = new FakeModel(model1Key); + FakeModel model2 = new FakeModel(model2Key); + + mngr.registerModel(model1); + mngr.registerModel(model2); + + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + if(!p.exists()) { + p.create(new NullProgressMonitor()); + } + p.open(new NullProgressMonitor()); + + IFile model1File = p.getFile("tmp/model1." + model1Key); + IFile model2File = p.getFile("tmp/model1." + model2Key); + + // Do create and save + mngr.createsModels(model1File); + mngr.save(new NullProgressMonitor()); + // + assertTrue("resource created", model1File.exists()); + assertTrue("resource created", model2File.exists()); + // + assertNotNull("resource created", model1.getResource()); + assertNotNull("resource created", model2.getResource()); + } + + /** + * Tests that only modified resources are saved, where we have only one model (no referenced libraries). + */ + @Test + public void testSave_onlyModifiedResources1() throws Exception { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + TransactionalEditingDomain domain = houseKeeper.cleanUpLater(mngr.getTransactionalEditingDomain()); + + EcoreModel model = new EcoreModel(); + + mngr.registerModel(model); + mngr.registerModel(new AdditionalResourcesModel()); + + IProject p = houseKeeper.createProject(houseKeeper.getTestName()); + + final IFile modelFile = p.getFile("model1." + model.getModelFileExtension()); + final URI modelURI = URI.createPlatformResourceURI(modelFile.getFullPath().toString(), true); + + final WorkspaceModificationAssertion mods = new WorkspaceModificationAssertion(houseKeeper); + + mngr.createModels(modelURI); + mods.save(mngr); + + assertThat("workspace resource not created", modelFile.exists(), is(true)); + + assertThat("EMF resource is null", model.getResource(), notNullValue()); + assertThat("EMF resource not created", model.getResource().getContents().isEmpty(), is(false)); + + EPackage ePackage = model.getRoot(); + domain.getCommandStack().execute(SetCommand.create(domain, ePackage, EcorePackage.Literals.ENAMED_ELEMENT__NAME, "newname")); + + mods.requireChange(modelURI); + mods.save(mngr); + + // Saving again should have no effect on the workspace + mods.requireNoChange(modelURI); + mods.save(mngr); + } + + /** + * Tests that only modified resources are saved, where we have multiple models (referenced libraries). + */ + @Test + public void testSave_onlyModifiedResources2() throws Exception { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + TransactionalEditingDomain domain = houseKeeper.cleanUpLater(mngr.getTransactionalEditingDomain()); + + final EcoreModel model = new EcoreModel(); + + mngr.registerModel(model); + mngr.registerModel(new AdditionalResourcesModel()); + + IProject p = houseKeeper.createProject(houseKeeper.getTestName()); + + final IFile modelFile1 = p.getFile("model1." + model.getModelFileExtension()); + final URI modelURI1 = URI.createPlatformResourceURI(modelFile1.getFullPath().toString(), true); + + final IFile modelFile2 = p.getFile("model2." + model.getModelFileExtension()); + final URI modelURI2 = URI.createPlatformResourceURI(modelFile2.getFullPath().toString(), true); + + final WorkspaceModificationAssertion mods = new WorkspaceModificationAssertion(houseKeeper); + + mngr.createModels(modelURI1); + + // Set up a second model and a dependency from the first + final Resource res2 = mngr.createResource(modelURI2, EcorePackage.eCONTENT_TYPE); + TransactionHelper.run(domain, new Runnable() { + + public void run() { + EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage(); + ePackage.setName("library"); + ePackage.setNsPrefix("lib"); + ePackage.setNsURI("http://www.eclipse.org/papyrus/test/fakemodel/ecore/library"); + res2.getContents().add(ePackage); + + // A class in the library model + EClass foo = EcoreFactory.eINSTANCE.createEClass(); + foo.setName("Foo"); + ePackage.getEClassifiers().add(foo); + + // A class in the main model + EClass thing = EcoreFactory.eINSTANCE.createEClass(); + thing.setName("Thing"); + model.getRoot().getEClassifiers().add(thing); + + EReference reference = EcoreFactory.eINSTANCE.createEReference(); + reference.setName("foo"); + reference.setEType(foo); + thing.getEStructuralFeatures().add(reference); + } + }); + + // We need this referenced model to be writable in order to save it + ModelUtils.makeReferencedModelsWritable(mngr, modelURI2 ); + mods.save(mngr); + + assertThat("workspace resource not created", modelFile1.exists(), is(true)); + assertThat("workspace resource not created", modelFile2.exists(), is(true)); + + assertThat("EMF resource is null", model.getResource(), notNullValue()); + assertThat("EMF resource not created", model.getResource().getContents().isEmpty(), is(false)); + assertThat("EMF resource not created", res2.getContents().isEmpty(), is(false)); + + // Change the referenced resource's URI. This should make the resource and its dependents dirty + final URI modelURI2New = modelURI2.trimSegments(1).appendSegment("library1").appendFileExtension(model.getModelFileExtension()); + res2.setURI(modelURI2New); + + ModelUtils.makeReferencedModelsWritable(mngr, modelURI2New); + mods.requireChange(modelURI1); // Thanks to the ProxyModificationTrackingAdapter + mods.requireChange(modelURI2New); + mods.requireNoChange(modelURI2); // No longer an interesting URI + mods.save(mngr); + + EPackage ePackage = model.getRoot(); + domain.getCommandStack().execute(SetCommand.create(domain, ePackage, EcorePackage.Literals.ENAMED_ELEMENT__NAME, "newname")); + + // Saving this should have no effect on the second resource + mods.requireChange(modelURI1); + mods.requireNoChange(modelURI2New); + mods.requireNoChange(modelURI2); + mods.save(mngr); + } + + /** + * Create some Resources for other test. This method should be called explicitly. + * + * @throws CoreException + * @throws IOException + */ + protected void createResources(String... filenames) throws CoreException, IOException { + + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(PLUGIN_PROJECT_NAME); + if(!p.exists()) { + p.create(new NullProgressMonitor()); + } + p.open(new NullProgressMonitor()); + + ResourceSet resourceSet = houseKeeper.createResourceSet(); + + for(String filename : filenames) { + createResource(p, resourceSet, filename); + } + + // Save created resources + for(Resource resource : resourceSet.getResources()) { + resource.save(null); + } + } + + + /** + * Create a resource. + * + * @param p + * @param resourceSet + * @param filename + */ + private void createResource(IProject p, ResourceSet resourceSet, String filename) { + + // Build a valid file + IFile file = p.getFile(filename); + + + URI uri = URI.createPlatformResourceURI(file.getFullPath().toOSString(), true); + resourceSet.createResource(uri); + + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#saveAs(IPath)} . + */ + @Test + public void testSaveAs() throws CoreException, IOException { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + String model1Key = "ecore"; + String model2Key = "genmodel"; + + FakeModel model1 = new FakeModel(model1Key); + FakeModel model2 = new FakeModel(model2Key); + + mngr.registerModel(model1); + mngr.registerModel(model2); + + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + if(!p.exists()) { + p.create(new NullProgressMonitor()); + } + p.open(new NullProgressMonitor()); + + IFile model1File = p.getFile("tmp/model1." + model1Key); + + // Do create and save + mngr.createsModels(model1File); + mngr.save(new NullProgressMonitor()); + + // Change the name + IFile newModel1File = p.getFile("tmp/model2." + model1Key); + IFile newModel2File = p.getFile("tmp/model2." + model2Key); + IPath newPath = newModel1File.getFullPath(); + + mngr.saveAs(newPath); + // check creation + + assertTrue("resource created", newModel2File.exists()); + assertTrue("resource created", newModel2File.exists()); + // + assertNotNull("resource created", model1.getResource()); + assertNotNull("resource created", model2.getResource()); + + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#unload()} . + */ + @Test + public void testUnload() { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + String model1Key = "ecore"; + String model2Key = "genmodel"; + + FakeModel model1 = new FakeModel(model1Key); + FakeModel model2 = new FakeModel(model2Key); + + mngr.registerModel(model1); + mngr.registerModel(model2); + + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + + IFile model1File = p.getFile("tmp/model1." + model1Key); + + // Do create and then unload + mngr.createsModels(model1File); + mngr.unload(); + + assertNull("resource unloaded", model1.getResource()); + assertNull("resource unloaded", model2.getResource()); + } + + /** + * Test method for {@link org.eclipse.papyrus.infra.core.resource.ModelSet#addModelSetSnippet(IModelManagerSnippet)} . + */ + @Test + public void testAddModelSetSnippet() { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + // Add snippets + TestTrace trace = new TestTrace(); + mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet1")); + mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet2")); + + // Do create + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + IFile model1File = p.getFile("tmp/model1.ecore"); + mngr.createsModels(model1File); + + // Check calls + assertTrue("snippet1 called", trace.contains("snippet1", "start")); + assertTrue("snippet2 called", trace.contains("snippet2", "start")); + + } + + /** + * Test that snippets are called after a call to createsModels() + */ + @Test + public void testSnippetCalledAfterCreateModels() { + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + // Add snippets + TestTrace trace = new TestTrace(); + mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet1")); + mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet2")); + + // Do create + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + IFile model1File = p.getFile("tmp/model1.ecore"); + mngr.createsModels(model1File); + + // Check calls + assertTrue("snippet1 called", trace.contains("snippet1", "start")); + assertTrue("snippet2 called", trace.contains("snippet2", "start")); + + // dispose + mngr.unload(); + // Check calls + assertTrue("snippet1 called", trace.contains("snippet1", "dispose")); + assertTrue("snippet2 called", trace.contains("snippet2", "dispose")); + + } + + /** + * Test that snippets are called after a call to loadModels() + * + * @throws ModelMultiException + */ + @Test + public void testSnippetCalledAfterLoadModels() throws ModelMultiException { + + // force model creation + testSnippetCalledAfterCreateModels(); + + // now do load. + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + // Add snippets + TestTrace trace = new TestTrace(); + mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet1")); + mngr.addModelSetSnippet(new FakeModelManagerSnippet(trace, "snippet2")); + + // Do create + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject("org.eclipse.papyrus.infra.core"); + IFile model1File = p.getFile("tmp/model1.ecore"); + mngr.loadModels(model1File); + + // Check calls + assertTrue("snippet1 called", trace.contains("snippet1", "start")); + assertTrue("snippet2 called", trace.contains("snippet2", "start")); + + // dispose + mngr.unload(); + // Check calls + assertTrue("snippet1 called", trace.contains("snippet1", "dispose")); + assertTrue("snippet2 called", trace.contains("snippet2", "dispose")); + + } + + /** + * Test {@link #createResources(String...)}. This is a test methods :-) + * + * @throws ModelMultiException + */ + @Test + public void testCreateResource() throws IOException, CoreException, ModelMultiException { + + String model1Key = "ecore"; + String model2Key = "genmodel"; + String model3Key = "uml"; + + // Create models + createResources("tmp/model1." + model1Key, "tmp/model1." + model2Key, "tmp/model1." + model3Key); + + // Check model creation + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(PLUGIN_PROJECT_NAME); + + IFile model1File = p.getFile("tmp/model1." + model1Key); + IFile model2File = p.getFile("tmp/model1." + model2Key); + IFile model3File = p.getFile("tmp/model1." + model3Key); + + assertTrue("modelFile exist", model1File.exists()); + assertTrue("modelFile exist", model2File.exists()); + assertTrue("modelFile exist", model3File.exists()); + } + + /** + * Test {@link ModelSet#importModels(ModelIdentifiers, IFile)} called after {@link ModelSet#createsModels(IFile)} . + * + * @throws ModelException + */ + @Test + public void testImportAfterCreate() throws IOException, CoreException, ModelException { + + String model1Key = "ecore"; + String model2Key = "genmodel"; + String model3Key = "uml"; + + // Create models + createResources("tmp/model1." + model1Key, "tmp/model1." + model2Key, "tmp/model1." + model3Key); + + // Now do registration + ModelSet mngr = houseKeeper.cleanUpLater(new ModelSet()); + + FakeModel model1 = new FakeModel(model1Key); + FakeModel model2 = new FakeModel(model2Key); + FakeModel model3 = new FakeModel(model3Key); + + mngr.registerModel(model1); + mngr.registerModel(model2); + mngr.registerModel(model3); + + + // Get an handle on one of the files + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(PLUGIN_PROJECT_NAME); + IFile createdFile = p.getFile("tmp/model2." + model1Key); + + + // Try to create all models + mngr.createsModels(createdFile); + + assertNotNull("resource created", model1.getResource()); + assertNotNull("resource created", model2.getResource()); + assertNotNull("resource created", model3.getResource()); + + // Add something in the model + model1.getResource().getContents().add(EcoreFactory.eINSTANCE.createEPackage()); + assertEquals("model1 has changed", 1, model1.getResource().getContents().size()); + + // Try to import + IFile importFile = p.getFile("tmp/model1." + model1Key); + mngr.importModels(new ModelIdentifiers(model1Key, model2Key), importFile); + + assertNotNull("resource exist", model1.getResource()); + assertNotNull("resource exist", model2.getResource()); + assertNotNull("resource exist", model3.getResource()); + + assertEquals("model1 has changed", 0, model1.getResource().getContents().size()); + + + } +} diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF index 2c7238f294c..ae8017b314c 100644 --- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF +++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF @@ -21,6 +21,7 @@ Require-Bundle: org.eclipse.ui, org.eclipse.papyrus.infra.nattable.model;bundle-version="1.0.0" Export-Package: org.eclipse.papyrus.junit.utils, org.eclipse.papyrus.junit.utils.classification, + org.eclipse.papyrus.junit.utils.resources, org.eclipse.papyrus.junit.utils.rules, org.eclipse.papyrus.junit.utils.tests Bundle-Vendor: %Bundle-Vendor diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/ModelUtils.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/ModelUtils.java index ac7bb43356d..8bd0b967e89 100644 --- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/ModelUtils.java +++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/ModelUtils.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,15 +8,25 @@ *
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437052
+ *
*****************************************************************************/
package org.eclipse.papyrus.junit.utils;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
import org.eclipse.core.runtime.IPath;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import org.eclipse.papyrus.infra.core.resource.ModelMultiException;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.core.utils.DiResourceSet;
/**
@@ -59,4 +69,42 @@ public class ModelUtils { return TransactionalEditingDomain.Factory.INSTANCE.getEditingDomain(modelSet);
}
+ /**
+ * Attempts to set the specified resource URIs as writable according to the referenced-model handler.
+ *
+ * @param modelSet
+ * a model set
+ * @param uri
+ * referenced-model resource URIs to make writable
+ */
+ public static void makeReferencedModelsWritable(ModelSet modelSet, URI... uris) {
+ IReadOnlyHandler2 handler = modelSet.getReadOnlyHandler();
+ if(handler != null) {
+ try {
+ // It will have this field if it's a ReadOnlyManager
+ Field orderedHandlersByAxisField = handler.getClass().getDeclaredField("orderedHandlersByAxis"); //$NON-NLS-1$
+ orderedHandlersByAxisField.setAccessible(true);
+
+ // Find the referenced-model handler and make it non-interactive so that we don't attempt to pop up a user dialog
+ @SuppressWarnings("unchecked")
+ Map<ReadOnlyAxis, IReadOnlyHandler2[]> orderedHandlersByAxis = (Map<ReadOnlyAxis, IReadOnlyHandler2[]>)orderedHandlersByAxisField.get(handler);
+ for(IReadOnlyHandler2 next : orderedHandlersByAxis.get(ReadOnlyAxis.DISCRETION)) {
+ // If this handler supports user interaction, try to suppress it
+ Duck nextHandler = new Duck(next);
+ if(nextHandler.understands("setInteractive", false)) {
+ nextHandler.quack("setInteractive", false);
+ }
+
+ // And make the resources writable in this handler
+ if(next.canMakeWritable(ReadOnlyAxis.discretionAxes(), uris).or(false)) {
+ next.makeWritable(ReadOnlyAxis.discretionAxes(), uris);
+ }
+ }
+ } catch (Exception e) {
+ // OK, didn't work. Fine. It's expected for non-ReadOnlyManager
+ }
+
+ assertThat("Could not make referenced models writable: " + uris, handler.anyReadOnly(ReadOnlyAxis.discretionAxes(), uris).or(true), is(false));
+ }
+ }
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/EcoreModel.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/EcoreModel.java new file mode 100644 index 00000000000..49461a32162 --- /dev/null +++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/EcoreModel.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.junit.utils.resources; + +import static org.junit.Assert.fail; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.infra.core.resource.EMFLogicalModel; +import org.eclipse.papyrus.infra.core.resource.IModel; +import org.eclipse.papyrus.infra.core.resource.ModelSet; +import org.eclipse.papyrus.infra.core.utils.TransactionHelper; + + +/** + * An {@link IModel} implementation for Ecore models that test cases may add to their {@link ModelSet}s for cases where it is expedient to + * work with models that are not UML. + */ +public class EcoreModel extends EMFLogicalModel { + + public EcoreModel() { + super(); + } + + @Override + public String getIdentifier() { + return "test.ecore"; + } + + @Override + public String getModelFileExtension() { + return "ecore"; + } + + public EPackage getRoot() { + return (EPackage)EcoreUtil.getObjectByType(getResource().getContents(), EcorePackage.Literals.EPACKAGE); + } + + @Override + public void createModel(URI uri) { + resourceURI = uri.appendFileExtension(getModelFileExtension()); + resource = getResourceSet().createResource(resourceURI, EcorePackage.eCONTENT_TYPE); + + final EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage(); + ePackage.setName("package1"); + ePackage.setNsPrefix("pkg1"); + ePackage.setNsURI("http://www.eclipse.org/papyrus/test/fakemodel/ecore/package1"); + + try { + TransactionHelper.run(getModelManager().getTransactionalEditingDomain(), new Runnable() { + + public void run() { + resource.getContents().add(ePackage); + } + }); + } catch (Exception e) { + e.printStackTrace(); + fail("Creation of Ecore model failed: " + e.getLocalizedMessage()); + } + } +} diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/WorkspaceModificationAssertion.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/WorkspaceModificationAssertion.java new file mode 100644 index 00000000000..7bc8e6257e7 --- /dev/null +++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/WorkspaceModificationAssertion.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014 CEA and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.junit.utils.resources; + +import static org.hamcrest.CoreMatchers.anything; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.IOException; +import java.util.Set; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.common.util.URI; +import org.eclipse.papyrus.infra.core.resource.ModelSet; +import org.eclipse.papyrus.junit.utils.rules.AbstractHouseKeeperRule; +import org.hamcrest.CoreMatchers; + +import com.google.common.collect.Sets; + +/** + * A simple fixture for making assertions on the workspace resource changes made (or not) by {@link ModelSet}s upon saving. + */ +public class WorkspaceModificationAssertion implements IResourceChangeListener { + + private final IWorkspace ws = ResourcesPlugin.getWorkspace(); + + private final Set<URI> requireChange = Sets.newHashSet(); + + private final Set<URI> requireNoChange = Sets.newHashSet(); + + private final Set<URI> changed = Sets.newHashSet(); + + private CoreException exception; + + public WorkspaceModificationAssertion(AbstractHouseKeeperRule houseKeeper) { + ws.addResourceChangeListener(this); + houseKeeper.cleanUpLater(this); + } + + public void dispose() { + ws.removeResourceChangeListener(this); + reset(); + } + + public void requireChange(URI uri) { + assertThat("conflicting change requirement for " + uri, requireNoChange, not(hasItem(uri))); + requireChange.add(uri); + } + + public void requireNoChange(URI uri) { + assertThat("conflicting change requirement for " + uri, requireChange, not(hasItem(uri))); + requireNoChange.add(uri); + } + + public void resourceChanged(IResourceChangeEvent event) { + try { + event.getDelta().accept(new IResourceDeltaVisitor() { + + public boolean visit(IResourceDelta delta) throws CoreException { + if(delta.getResource().getType() == IResource.FILE) { + changed.add(URI.createPlatformResourceURI(delta.getFullPath().toString(), true)); + } + return true; + } + }); + } catch (CoreException e) { + e.printStackTrace(); + exception = e; + } + } + + public void reset() { + requireChange.clear(); + requireNoChange.clear(); + changed.clear(); + exception = null; + } + + public void save(final ModelSet modelSet) { + try { + try { + ws.run(new IWorkspaceRunnable() { + + public void run(IProgressMonitor monitor) throws CoreException { + try { + modelSet.save(monitor); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, "org.eclipse.papyrus.junit.utils", "Save failed.", e)); + } + } + }, new NullProgressMonitor()); + } catch (CoreException e) { + e.printStackTrace(); + exception = e; + } + + assertThat("Resource(s) saved that should not have been", Sets.intersection(requireNoChange, changed), not(CoreMatchers.<URI> hasItem(anything()))); + assertThat("Resource(s) not saved that should have been", Sets.difference(requireChange, changed), not(CoreMatchers.<URI> hasItem(anything()))); + assertThat("Save assertion failed with an exception", exception, nullValue()); + } finally { + reset(); + } + } +} |