View | Details | Raw Unified | Return to bug 112531 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/gmf/runtime/emf/core/internal/notifications/MSLObjectListener.java (-58 lines)
Lines 19-27 Link Here
19
import org.eclipse.emf.common.notify.Notification;
19
import org.eclipse.emf.common.notify.Notification;
20
import org.eclipse.emf.ecore.EObject;
20
import org.eclipse.emf.ecore.EObject;
21
import org.eclipse.emf.ecore.EReference;
21
import org.eclipse.emf.ecore.EReference;
22
import org.eclipse.emf.ecore.EStructuralFeature;
23
import org.eclipse.emf.ecore.resource.Resource;
22
import org.eclipse.emf.ecore.resource.Resource;
24
25
import org.eclipse.gmf.runtime.emf.core.EventTypes;
23
import org.eclipse.gmf.runtime.emf.core.EventTypes;
26
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
24
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
27
import org.eclipse.gmf.runtime.emf.core.internal.resources.MResource;
25
import org.eclipse.gmf.runtime.emf.core.internal.resources.MResource;
Lines 59-85 Link Here
59
			
57
			
60
			if (!domain.getResouceListener().resourceFinishedLoading(resource))
58
			if (!domain.getResouceListener().resourceFinishedLoading(resource))
61
				return;
59
				return;
62
			// set resource dirty flag.
63
			switch (eventType) {
64
				case Notification.SET:
65
				case Notification.UNSET:
66
				case Notification.MOVE: {
67
					if (!notification.isTouch() && !resource.isModified()){
68
						if(!isTransient(notifier, feature))
69
							resource.setModified(true);
70
					}
71
					break;
72
				}
73
74
				case Notification.ADD:
75
				case Notification.REMOVE:
76
				case Notification.ADD_MANY:
77
				case Notification.REMOVE_MANY: {
78
					if (!resource.isModified() && !isTransient(notifier, feature))
79
						resource.setModified(true);
80
					break;
81
				}
82
			}
83
		}
60
		}
84
61
85
		Object newValue = notification.getNewValue();
62
		Object newValue = notification.getNewValue();
Lines 121-161 Link Here
121
	}
98
	}
122
99
123
	/**
100
	/**
124
	 * check if the feature or one of its containers is transient
125
	 * @param notifier
126
	 * @param feature
127
	 * @param transientChange
128
	 * @return
129
	 */
130
	private boolean isTransient(EObject notifier, Object feature) {
131
		if (feature instanceof EStructuralFeature) {
132
			if (((EStructuralFeature) feature).isTransient())
133
				return true;
134
			else
135
				// calling isTransient could be a lengthy operation  
136
				return isTransient(notifier);
137
		}
138
		return false;
139
	}
140
	
141
	/**
142
	 * Is object transient?
143
	 */
144
	private boolean isTransient(EObject eObject) {
145
		EStructuralFeature containmentFeature = eObject.eContainmentFeature();
146
		while (containmentFeature != null) {
147
			if (containmentFeature.isTransient())
148
				return true;
149
			eObject = eObject.eContainer();
150
			if (eObject != null)
151
				containmentFeature =  eObject.eContainmentFeature();
152
			else
153
				break;
154
		}
155
		return false;
156
	}
157
158
	/**
159
	 * Process references and update reference maps.
101
	 * Process references and update reference maps.
160
	 */
102
	 */
161
	private void processReferences(EObject notifier, int eventType,
103
	private void processReferences(EObject notifier, int eventType,
(-)src/org/eclipse/gmf/runtime/emf/core/internal/resources/LogicalResourceUnit.java (-1 / +1 lines)
Lines 525-531 Link Here
525
	public void setModified(boolean isModified) {
525
	public void setModified(boolean isModified) {
526
		super.setModified(isModified);
526
		super.setModified(isModified);
527
		
527
		
528
		if (isModified) {
528
		if (isModified && getLogicalResource().isTrackingModification()) {
529
			// propagate modified state to the root
529
			// propagate modified state to the root
530
			getLogicalResource().setModified(isModified);
530
			getLogicalResource().setModified(isModified);
531
		}
531
		}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/resources/MSLResource.java (-1 / +66 lines)
Lines 11-18 Link Here
11
11
12
package org.eclipse.gmf.runtime.emf.core.internal.resources;
12
package org.eclipse.gmf.runtime.emf.core.internal.resources;
13
13
14
import org.eclipse.emf.common.notify.Adapter;
15
import org.eclipse.emf.common.notify.Notification;
14
import org.eclipse.emf.common.util.URI;
16
import org.eclipse.emf.common.util.URI;
15
import org.eclipse.emf.ecore.EObject;
17
import org.eclipse.emf.ecore.EObject;
18
import org.eclipse.emf.ecore.EStructuralFeature;
16
19
17
import org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain;
20
import org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain;
18
import org.eclipse.gmf.runtime.emf.core.internal.util.MSLConstants;
21
import org.eclipse.gmf.runtime.emf.core.internal.util.MSLConstants;
Lines 26-38 Link Here
26
	extends LogicalResource {
29
	extends LogicalResource {
27
30
28
	private boolean useIDAttributes = false;
31
	private boolean useIDAttributes = false;
29
32
	
30
	/**
33
	/**
31
	 * Constructor.
34
	 * Constructor.
32
	 */
35
	 */
33
	public MSLResource(URI uri) {
36
	public MSLResource(URI uri) {
34
37
35
		super(MEditingDomain.INSTANCE.convertURI(uri));
38
		super(MEditingDomain.INSTANCE.convertURI(uri));
39
		
40
		setTrackingModification(true);
36
	}
41
	}
37
42
38
	protected LogicalResourceUnit createUnit(URI unitUri) {
43
	protected LogicalResourceUnit createUnit(URI unitUri) {
Lines 98-101 Link Here
98
103
99
		super.setURI(uri);
104
		super.setURI(uri);
100
	}
105
	}
106
	
107
	/**
108
	 * The inherited implementation creates an adapter that <em>always</em> sets
109
	 * the modified state.  We prefer to check, first, whether the resource
110
	 * is already modified so that we don't generate redundant notifications.
111
	 * Moreover, we additionally set modified state only for changes that are
112
	 * in non-transient features of objects contained (recursively) by
113
	 * non-transient references.
114
	 */
115
	protected Adapter createModificationTrackingAdapter() {
116
		return new ModificationTrackingAdapter() {
117
			public void notifyChanged(Notification notification) {
118
				if (!isModified() && !isTransient(
119
						notification.getNotifier(), notification.getFeature())) {
120
					
121
					super.notifyChanged(notification);
122
				}
123
			}
124
125
			/**
126
			 * Check if the feature or one of the notifier's containers is
127
			 * transient.
128
			 * 
129
			 * @param notifier a notifier
130
			 * @param feature the feature that changed
131
			 * 
132
			 * @return <code>true</code> if the feature is transient or if the
133
			 *    notifier or any of its ancestors is contained by a transient
134
			 *    reference; <code>false</code>, otherwise
135
			 */
136
			private boolean isTransient(Object notifier, Object feature) {
137
				if (feature instanceof EStructuralFeature) {
138
					if (((EStructuralFeature) feature).isTransient())
139
						return true;
140
					else
141
						// calling isTransient could be a lengthy operation.
142
						//   It is safe to cast because the adapter is only
143
						//   attached to EObjects, not to the resource
144
						return isTransient((EObject) notifier);
145
				}
146
				return false;
147
			}
148
			
149
			/**
150
			 * Is object transient?
151
			 */
152
			private boolean isTransient(EObject eObject) {
153
				EStructuralFeature containmentFeature = eObject.eContainmentFeature();
154
				while (containmentFeature != null) {
155
					if (containmentFeature.isTransient())
156
						return true;
157
					eObject = eObject.eContainer();
158
					if (eObject != null)
159
						containmentFeature =  eObject.eContainmentFeature();
160
					else
161
						break;
162
				}
163
				return false;
164
			}};
165
	}
101
}
166
}
(-)src/org/eclipse/gmf/tests/runtime/emf/core/RegressionTestCase.java (+58 lines)
Lines 15-20 Link Here
15
import junit.framework.Test;
15
import junit.framework.Test;
16
import junit.framework.TestSuite;
16
import junit.framework.TestSuite;
17
17
18
import org.eclipse.emf.common.notify.Notification;
19
import org.eclipse.emf.common.notify.impl.AdapterImpl;
18
import org.eclipse.emf.common.util.BasicEList;
20
import org.eclipse.emf.common.util.BasicEList;
19
import org.eclipse.emf.common.util.EList;
21
import org.eclipse.emf.common.util.EList;
20
import org.eclipse.emf.ecore.resource.Resource;
22
import org.eclipse.emf.ecore.resource.Resource;
Lines 303-306 Link Here
303
		// check that MSLUtil made the correct change
305
		// check that MSLUtil made the correct change
304
		assertEquals(expected, list);
306
		assertEquals(expected, list);
305
	}
307
	}
308
	
309
	/**
310
	 * Tests consistency of the <code>isTrackingModification()</code> method
311
	 * with the actual tracking of modification provided by the
312
	 * <code>MSLObjectListener</code>.
313
	 */
314
	public void test_modificationTracking_112531() {
315
		class TestAdapter extends AdapterImpl {
316
			boolean modified;
317
			
318
			public void notifyChanged(Notification msg) {
319
				if (msg.getFeatureID(null) == Resource.RESOURCE__IS_MODIFIED) {
320
					modified = msg.getNewBooleanValue();
321
				}
322
			}
323
			
324
			void reset() {
325
				modified = false;
326
			}
327
		}
328
		
329
		if (writing()) {
330
			// MSL resources initially track modification
331
			assertTrue(testResource.isTrackingModification());
332
			
333
			TestAdapter adapter = new TestAdapter();
334
			testResource.eAdapters().add(adapter);
335
			
336
			assertFalse(adapter.modified);
337
			
338
			// make a change
339
			Library lib = EXTLibraryFactory.eINSTANCE.createLibrary();
340
			lib.setName("NewlyAdded"); //$NON-NLS-1$
341
			root.getBranches().add(lib);
342
			
343
			assertTrue(adapter.modified);
344
			adapter.reset();
345
			
346
			// disable modification tracking
347
			testResource.setModified(false);
348
			testResource.setTrackingModification(false);
349
			
350
			// make a change
351
			root.getBranches().remove(lib);
352
			
353
			assertFalse(adapter.modified);
354
			
355
			// re-enable tracking
356
			testResource.setTrackingModification(true);
357
			
358
			// make a change
359
			root.getBranches().add(lib);
360
			
361
			assertTrue(adapter.modified);
362
		}
363
	}
306
}
364
}

Return to bug 112531