Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2014-06-11 20:21:34 +0000
committerChristian W. Damus2014-07-21 14:58:30 +0000
commit5ab06e3232056fdea6708b153e2c22d4b99eaa14 (patch)
treeb60e5e91a8d531f81b62bcdf538afb98ca906fbe
parent029e4b677bf9ad7a919565c55d1c4ed3128e5cb4 (diff)
downloadorg.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
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java9
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareProxyModificationTrackingAdapter.java64
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractBaseModel.java5
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/EMFLogicalModel.java8
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java33
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ProxyModificationTrackingAdapter.java29
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/additional/AdditionalResourcesModel.java12
-rw-r--r--tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java137
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.infra.core.tests/test/org/eclipse/papyrus/infra/core/resource/ModelSetTest.java1150
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF1
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/ModelUtils.java50
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/EcoreModel.java74
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/resources/WorkspaceModificationAssertion.java128
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();
+ }
+ }
+}

Back to the top