### Eclipse Workspace Patch 1.0
#P org.eclipse.gmf.runtime.emf.core
Index: src/org/eclipse/gmf/runtime/emf/core/internal/notifications/MSLObjectListener.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.gmf/plugins/org.eclipse.gmf.runtime.emf.core/src/org/eclipse/gmf/runtime/emf/core/internal/notifications/MSLObjectListener.java,v
retrieving revision 1.2
diff -u -r1.2 MSLObjectListener.java
--- src/org/eclipse/gmf/runtime/emf/core/internal/notifications/MSLObjectListener.java 12 Sep 2005 21:25:11 -0000 1.2
+++ src/org/eclipse/gmf/runtime/emf/core/internal/notifications/MSLObjectListener.java 15 Dec 2005 15:41:37 -0000
@@ -19,9 +19,7 @@
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
-
import org.eclipse.gmf.runtime.emf.core.EventTypes;
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
import org.eclipse.gmf.runtime.emf.core.internal.resources.MResource;
@@ -59,27 +57,6 @@
if (!domain.getResouceListener().resourceFinishedLoading(resource))
return;
- // set resource dirty flag.
- switch (eventType) {
- case Notification.SET:
- case Notification.UNSET:
- case Notification.MOVE: {
- if (!notification.isTouch() && !resource.isModified()){
- if(!isTransient(notifier, feature))
- resource.setModified(true);
- }
- break;
- }
-
- case Notification.ADD:
- case Notification.REMOVE:
- case Notification.ADD_MANY:
- case Notification.REMOVE_MANY: {
- if (!resource.isModified() && !isTransient(notifier, feature))
- resource.setModified(true);
- break;
- }
- }
}
Object newValue = notification.getNewValue();
@@ -121,41 +98,6 @@
}
/**
- * check if the feature or one of its containers is transient
- * @param notifier
- * @param feature
- * @param transientChange
- * @return
- */
- private boolean isTransient(EObject notifier, Object feature) {
- if (feature instanceof EStructuralFeature) {
- if (((EStructuralFeature) feature).isTransient())
- return true;
- else
- // calling isTransient could be a lengthy operation
- return isTransient(notifier);
- }
- return false;
- }
-
- /**
- * Is object transient?
- */
- private boolean isTransient(EObject eObject) {
- EStructuralFeature containmentFeature = eObject.eContainmentFeature();
- while (containmentFeature != null) {
- if (containmentFeature.isTransient())
- return true;
- eObject = eObject.eContainer();
- if (eObject != null)
- containmentFeature = eObject.eContainmentFeature();
- else
- break;
- }
- return false;
- }
-
- /**
* Process references and update reference maps.
*/
private void processReferences(EObject notifier, int eventType,
Index: src/org/eclipse/gmf/runtime/emf/core/internal/resources/LogicalResourceUnit.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.gmf/plugins/org.eclipse.gmf.runtime.emf.core/src/org/eclipse/gmf/runtime/emf/core/internal/resources/LogicalResourceUnit.java,v
retrieving revision 1.2
diff -u -r1.2 LogicalResourceUnit.java
--- src/org/eclipse/gmf/runtime/emf/core/internal/resources/LogicalResourceUnit.java 12 Sep 2005 21:25:12 -0000 1.2
+++ src/org/eclipse/gmf/runtime/emf/core/internal/resources/LogicalResourceUnit.java 15 Dec 2005 15:41:37 -0000
@@ -525,7 +525,7 @@
public void setModified(boolean isModified) {
super.setModified(isModified);
- if (isModified) {
+ if (isModified && getLogicalResource().isTrackingModification()) {
// propagate modified state to the root
getLogicalResource().setModified(isModified);
}
Index: src/org/eclipse/gmf/runtime/emf/core/internal/resources/MSLResource.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.gmf/plugins/org.eclipse.gmf.runtime.emf.core/src/org/eclipse/gmf/runtime/emf/core/internal/resources/MSLResource.java,v
retrieving revision 1.2
diff -u -r1.2 MSLResource.java
--- src/org/eclipse/gmf/runtime/emf/core/internal/resources/MSLResource.java 12 Sep 2005 21:25:12 -0000 1.2
+++ src/org/eclipse/gmf/runtime/emf/core/internal/resources/MSLResource.java 15 Dec 2005 15:41:37 -0000
@@ -11,8 +11,11 @@
package org.eclipse.gmf.runtime.emf.core.internal.resources;
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain;
import org.eclipse.gmf.runtime.emf.core.internal.util.MSLConstants;
@@ -26,13 +29,15 @@
extends LogicalResource {
private boolean useIDAttributes = false;
-
+
/**
* Constructor.
*/
public MSLResource(URI uri) {
super(MEditingDomain.INSTANCE.convertURI(uri));
+
+ setTrackingModification(true);
}
protected LogicalResourceUnit createUnit(URI unitUri) {
@@ -98,4 +103,64 @@
super.setURI(uri);
}
+
+ /**
+ * The inherited implementation creates an adapter that always sets
+ * the modified state. We prefer to check, first, whether the resource
+ * is already modified so that we don't generate redundant notifications.
+ * Moreover, we additionally set modified state only for changes that are
+ * in non-transient features of objects contained (recursively) by
+ * non-transient references.
+ */
+ protected Adapter createModificationTrackingAdapter() {
+ return new ModificationTrackingAdapter() {
+ public void notifyChanged(Notification notification) {
+ if (!isModified() && !isTransient(
+ notification.getNotifier(), notification.getFeature())) {
+
+ super.notifyChanged(notification);
+ }
+ }
+
+ /**
+ * Check if the feature or one of the notifier's containers is
+ * transient.
+ *
+ * @param notifier a notifier
+ * @param feature the feature that changed
+ *
+ * @return true
if the feature is transient or if the
+ * notifier or any of its ancestors is contained by a transient
+ * reference; false
, otherwise
+ */
+ private boolean isTransient(Object notifier, Object feature) {
+ if (feature instanceof EStructuralFeature) {
+ if (((EStructuralFeature) feature).isTransient())
+ return true;
+ else
+ // calling isTransient could be a lengthy operation.
+ // It is safe to cast because the adapter is only
+ // attached to EObjects, not to the resource
+ return isTransient((EObject) notifier);
+ }
+ return false;
+ }
+
+ /**
+ * Is object transient?
+ */
+ private boolean isTransient(EObject eObject) {
+ EStructuralFeature containmentFeature = eObject.eContainmentFeature();
+ while (containmentFeature != null) {
+ if (containmentFeature.isTransient())
+ return true;
+ eObject = eObject.eContainer();
+ if (eObject != null)
+ containmentFeature = eObject.eContainmentFeature();
+ else
+ break;
+ }
+ return false;
+ }};
+ }
}
\ No newline at end of file
#P org.eclipse.gmf.tests.runtime.emf.core
Index: src/org/eclipse/gmf/tests/runtime/emf/core/RegressionTestCase.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.gmf/tests/org.eclipse.gmf.tests.runtime.emf.core/src/org/eclipse/gmf/tests/runtime/emf/core/RegressionTestCase.java,v
retrieving revision 1.4
diff -u -r1.4 RegressionTestCase.java
--- src/org/eclipse/gmf/tests/runtime/emf/core/RegressionTestCase.java 20 Oct 2005 21:34:21 -0000 1.4
+++ src/org/eclipse/gmf/tests/runtime/emf/core/RegressionTestCase.java 15 Dec 2005 15:41:38 -0000
@@ -15,6 +15,8 @@
import junit.framework.Test;
import junit.framework.TestSuite;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.resource.Resource;
@@ -303,4 +305,60 @@
// check that MSLUtil made the correct change
assertEquals(expected, list);
}
+
+ /**
+ * Tests consistency of the isTrackingModification()
method
+ * with the actual tracking of modification provided by the
+ * MSLObjectListener
.
+ */
+ public void test_modificationTracking_112531() {
+ class TestAdapter extends AdapterImpl {
+ boolean modified;
+
+ public void notifyChanged(Notification msg) {
+ if (msg.getFeatureID(null) == Resource.RESOURCE__IS_MODIFIED) {
+ modified = msg.getNewBooleanValue();
+ }
+ }
+
+ void reset() {
+ modified = false;
+ }
+ }
+
+ if (writing()) {
+ // MSL resources initially track modification
+ assertTrue(testResource.isTrackingModification());
+
+ TestAdapter adapter = new TestAdapter();
+ testResource.eAdapters().add(adapter);
+
+ assertFalse(adapter.modified);
+
+ // make a change
+ Library lib = EXTLibraryFactory.eINSTANCE.createLibrary();
+ lib.setName("NewlyAdded"); //$NON-NLS-1$
+ root.getBranches().add(lib);
+
+ assertTrue(adapter.modified);
+ adapter.reset();
+
+ // disable modification tracking
+ testResource.setModified(false);
+ testResource.setTrackingModification(false);
+
+ // make a change
+ root.getBranches().remove(lib);
+
+ assertFalse(adapter.modified);
+
+ // re-enable tracking
+ testResource.setTrackingModification(true);
+
+ // make a change
+ root.getBranches().add(lib);
+
+ assertTrue(adapter.modified);
+ }
+ }
}