View | Details | Raw Unified | Return to bug 113892
Collapse All | Expand All

(-)src/org/eclipse/gmf/tests/runtime/emf/core/EditingDomainExtensibilityTests.java (-2 / +2 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2005 IBM Corporation and others.
2
 * Copyright (c) 2005, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 653-659 Link Here
653
					projectName);
653
					projectName);
654
				
654
				
655
				if (proj != null) {
655
				if (proj != null) {
656
					result = (MyResourceSet) getResourceSet(proj);
656
					result = getResourceSet(proj);
657
				}
657
				}
658
			}
658
			}
659
			
659
			
(-)src/org/eclipse/gmf/tests/runtime/emf/core/AllTests.java (-1 / +2 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2002, 2005 IBM Corporation and others.
2
 * Copyright (c) 2002-2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 88-93 Link Here
88
		suite.addTestSuite(MSLEditingDomainTestCase.class);
88
		suite.addTestSuite(MSLEditingDomainTestCase.class);
89
		suite.addTestSuite(MFilterTests.class);
89
		suite.addTestSuite(MFilterTests.class);
90
		suite.addTestSuite(MListenerTest.class);
90
		suite.addTestSuite(MListenerTest.class);
91
		suite.addTestSuite(CrossReferenceAdapterTests.class);
91
92
92
		return suite;
93
		return suite;
93
	}
94
	}
(-)src/org/eclipse/gmf/tests/runtime/emf/core/CrossReferenceAdapterTests.java (+809 lines)
Added Link Here
1
/******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
10
 ****************************************************************************/
11
12
package org.eclipse.gmf.tests.runtime.emf.core;
13
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Iterator;
17
import java.util.List;
18
19
import org.eclipse.emf.common.notify.Notifier;
20
import org.eclipse.emf.common.util.TreeIterator;
21
import org.eclipse.emf.ecore.EObject;
22
import org.eclipse.emf.ecore.EReference;
23
import org.eclipse.emf.ecore.resource.Resource;
24
import org.eclipse.emf.ecore.resource.ResourceSet;
25
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
26
import org.eclipse.emf.examples.extlibrary.Book;
27
import org.eclipse.emf.examples.extlibrary.EXTLibraryFactory;
28
import org.eclipse.emf.examples.extlibrary.EXTLibraryPackage;
29
import org.eclipse.emf.examples.extlibrary.Employee;
30
import org.eclipse.emf.examples.extlibrary.Library;
31
import org.eclipse.emf.examples.extlibrary.Writer;
32
import org.eclipse.gmf.runtime.emf.core.edit.MRunnable;
33
import org.eclipse.gmf.runtime.emf.core.edit.MUndoInterval;
34
import org.eclipse.gmf.runtime.emf.core.exceptions.MSLActionAbandonedException;
35
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
36
import org.eclipse.gmf.runtime.emf.core.internal.index.MSLCrossReferenceAdapter;
37
import org.eclipse.gmf.runtime.emf.core.util.EObjectUtil;
38
import org.eclipse.gmf.runtime.emf.core.util.ResourceUtil;
39
40
/**
41
 * Test cases for the MSLCrossReferenceAdapter.
42
 * 
43
 * @author Christian Vogt (cvogt)
44
 */
45
public class CrossReferenceAdapterTests extends BaseCoreTests {
46
47
	private Resource otherRes;
48
	private Library otherRoot;
49
	private Book otherBook;
50
	private Writer otherWriter;
51
	private Employee otherEmp;
52
53
	/**
54
	 * Tests to ensure that every object in the resource has
55
	 * an attached CrossReferenceAdapter
56
	 */
57
	public void test_hasCrossReferenceAdapter() {
58
		checkHasCrossReferenceAdapter(testResource);
59
	}
60
	
61
	/**
62
	 * Helper method to check that the notifier and all its contents
63
	 * have an attached CrossReferenceAdapter.
64
	 * 
65
	 * @param notifier
66
	 */
67
	private void checkHasCrossReferenceAdapter(Notifier notifier) {
68
		boolean result = hasCrossRefenenceAdapter(notifier);
69
		if (result) {
70
			TreeIterator iter = null;
71
			if (notifier instanceof ResourceSet) {
72
				iter = ((ResourceSet)notifier).getAllContents();
73
			} else if (notifier instanceof Resource) {
74
				iter = ((Resource)notifier).getAllContents();
75
			} else if (notifier instanceof EObject) {
76
				iter = ((EObject)notifier).eAllContents();
77
			} else {
78
				fail("Invalid Object Type"); //$NON-NLS-1$
79
			}
80
			
81
			while (iter.hasNext()) {
82
				if (!hasCrossRefenenceAdapter((Notifier)iter.next())) {
83
					result = false;
84
					break;
85
				}
86
			}
87
		}
88
		if (!result) {
89
			fail("CrossReferenceAdapter is missing."); //$NON-NLS-1$
90
		}
91
	}
92
	
93
	/**
94
	 * Returns true if the notifier has an attached CrossReferenceAdapter.
95
	 * 
96
	 * @param notifier the notifier to check
97
	 * @return
98
	 */
99
	private boolean hasCrossRefenenceAdapter(Notifier notifier) {
100
		boolean result = false;
101
		for (Iterator i = notifier.eAdapters().iterator(); i.hasNext(); ) {
102
			if (i.next() instanceof MSLCrossReferenceAdapter) {
103
				result = true;
104
			}
105
		}
106
		return result;
107
	}
108
109
	/**
110
	 * Tests that resource import and exports information is properly
111
	 * maintained when many cross references are added and removed.
112
	 */
113
	public void test_importsExportsAddRemoveMany() {
114
		Book rootBook = (Book)root.getBooks().get(0);
115
		Book level1Book = (Book)((Library)root.getBranches().get(0)).getBooks().get(0);
116
		final List books = new ArrayList();
117
		books.add(rootBook);
118
		books.add(level1Book);
119
		
120
		MUndoInterval undo = domain.runInUndoInterval(new Runnable() {
121
			public void run() {
122
				try {
123
					domain.runAsWrite(new MRunnable() {
124
					
125
						public Object run() {
126
							otherWriter.getBooks().addAll(books);
127
							
128
							return null;
129
						}});
130
				} catch (MSLActionAbandonedException e) {
131
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
132
				}
133
			}});
134
135
		Collection imports = domain.getImports(otherRes);
136
		assertTrue(imports.contains(testResource));
137
		
138
		imports = domain.getAllImports(otherRes);
139
		assertTrue(imports.contains(testResource));
140
		
141
		Collection exports = domain.getExports(testResource);
142
		assertTrue(exports.contains(otherRes));
143
		
144
		exports = domain.getAllExports(testResource);
145
		assertTrue(exports.contains(otherRes));
146
147
		// remove books by undo
148
		undo.undo();
149
		
150
		imports = domain.getImports(otherRes);
151
		assertFalse(imports.contains(testResource));
152
		
153
		imports = domain.getAllImports(otherRes);
154
		assertFalse(imports.contains(testResource));
155
156
		exports = domain.getExports(testResource);
157
		assertFalse(exports.contains(otherRes));
158
		
159
		exports = domain.getAllExports(testResource);
160
		assertFalse(exports.contains(otherRes));
161
	}
162
163
	/**
164
	 * Tests that resource import and exports information is properly
165
	 * maintained when many cross references are added and removed
166
	 * one at a time.
167
	 */
168
	public void test_importsExportsAddManyRemoveOneAtATime() {
169
		final Book rootBook = (Book)root.getBooks().get(0);
170
		final Book level1Book = (Book)((Library)root.getBranches().get(0)).getBooks().get(0);
171
		final List books = new ArrayList();
172
		books.add(rootBook);
173
		books.add(level1Book);
174
		
175
		domain.runInUndoInterval(new Runnable() {
176
			public void run() {
177
				try {
178
					domain.runAsWrite(new MRunnable() {
179
					
180
						public Object run() {
181
							otherWriter.getBooks().addAll(books);
182
							
183
							return null;
184
						}});
185
				} catch (MSLActionAbandonedException e) {
186
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
187
				}
188
			}});
189
		
190
		Collection imports = domain.getImports(otherRes);
191
		assertTrue(imports.contains(testResource));
192
		
193
		imports = domain.getAllImports(otherRes);
194
		assertTrue(imports.contains(testResource));
195
		
196
		Collection exports = domain.getExports(testResource);
197
		assertTrue(exports.contains(otherRes));
198
		
199
		exports = domain.getAllExports(testResource);
200
		assertTrue(exports.contains(otherRes));
201
202
		domain.runInUndoInterval(new Runnable() {
203
			public void run() {
204
				try {
205
					domain.runAsWrite(new MRunnable() {
206
					
207
						public Object run() {
208
							otherWriter.getBooks().remove(rootBook);
209
							
210
							return null;
211
						}});
212
				} catch (MSLActionAbandonedException e) {
213
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
214
				}
215
			}});
216
		
217
		imports = domain.getImports(otherRes);
218
		assertTrue(imports.contains(testResource));
219
		
220
		imports = domain.getAllImports(otherRes);
221
		assertTrue(imports.contains(testResource));
222
		
223
		exports = domain.getExports(testResource);
224
		assertTrue(exports.contains(otherRes));
225
		
226
		exports = domain.getAllExports(testResource);
227
		assertTrue(exports.contains(otherRes));
228
		
229
		domain.runUnvalidated(new MRunnable() {
230
			public Object run() {
231
				return domain.runInUndoInterval(new Runnable() {
232
					public void run() {
233
						try {
234
							domain.runAsWrite(new MRunnable() {
235
							
236
								public Object run() {
237
									otherWriter.getBooks().remove(level1Book);
238
									
239
									return null;
240
								}});
241
						} catch (MSLActionAbandonedException e) {
242
							fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
243
						}
244
					}
245
				});
246
			}
247
		});
248
		
249
		imports = domain.getImports(otherRes);
250
		assertFalse(imports.contains(testResource));
251
		
252
		imports = domain.getAllImports(otherRes);
253
		assertFalse(imports.contains(testResource));
254
255
		exports = domain.getExports(testResource);
256
		assertFalse(exports.contains(otherRes));
257
		
258
		exports = domain.getAllExports(testResource);
259
		assertFalse(exports.contains(otherRes));
260
	}
261
262
	/**
263
	 * Tests that resource import and exports information is properly
264
	 * maintained when a cross reference is set and unset.
265
	 */
266
	public void test_importsExportsSetUnset() {
267
		final Writer rootWriter = (Writer)root.getWriters().get(0);
268
269
		
270
		MUndoInterval undo = domain.runInUndoInterval(new Runnable() {
271
			public void run() {
272
				try {
273
					domain.runAsWrite(new MRunnable() {
274
					
275
						public Object run() {
276
							otherBook.setAuthor(rootWriter);
277
							
278
							return null;
279
						}});
280
				} catch (MSLActionAbandonedException e) {
281
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
282
				}
283
			}});
284
285
		Collection imports = domain.getImports(otherRes);
286
		assertTrue(imports.contains(testResource));
287
		
288
		imports = domain.getAllImports(otherRes);
289
		assertTrue(imports.contains(testResource));
290
		
291
		Collection exports = domain.getExports(testResource);
292
		assertTrue(exports.contains(otherRes));
293
		
294
		exports = domain.getAllExports(testResource);
295
		assertTrue(exports.contains(otherRes));
296
297
		// unset author by undo
298
		undo.undo();
299
		
300
		imports = domain.getImports(otherRes);
301
		assertFalse(imports.contains(testResource));
302
		
303
		imports = domain.getAllImports(otherRes);
304
		assertFalse(imports.contains(testResource));
305
306
		exports = domain.getExports(testResource);
307
		assertFalse(exports.contains(otherRes));
308
		
309
		exports = domain.getAllExports(testResource);
310
		assertFalse(exports.contains(otherRes));
311
	}
312
	
313
	/**
314
	 * Tests that resource import and exports information is properly
315
	 * maintained when a cross reference is added and removed.
316
	 */
317
	public void test_importsExportsAddRemove() {
318
		final Book rootBook = (Book)root.getBooks().get(0);
319
320
		MUndoInterval undo = domain.runInUndoInterval(new Runnable() {
321
			public void run() {
322
				try {
323
					domain.runAsWrite(new MRunnable() {
324
					
325
						public Object run() {
326
							otherWriter.getBooks().add(rootBook);
327
							
328
							return null;
329
						}});
330
				} catch (MSLActionAbandonedException e) {
331
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
332
				}
333
			}});
334
335
		Collection imports = domain.getImports(otherRes);
336
		assertTrue(imports.contains(testResource));
337
		
338
		imports = domain.getAllImports(otherRes);
339
		assertTrue(imports.contains(testResource));
340
		
341
		Collection exports = domain.getExports(testResource);
342
		assertTrue(exports.contains(otherRes));
343
		
344
		exports = domain.getAllExports(testResource);
345
		assertTrue(exports.contains(otherRes));
346
347
		// remove book by undo
348
		undo.undo();
349
		
350
		imports = domain.getImports(otherRes);
351
		assertFalse(imports.contains(testResource));
352
		
353
		imports = domain.getAllImports(otherRes);
354
		assertFalse(imports.contains(testResource));
355
356
		exports = domain.getExports(testResource);
357
		assertFalse(exports.contains(otherRes));
358
		
359
		exports = domain.getAllExports(testResource);
360
		assertFalse(exports.contains(otherRes));
361
	}
362
363
	/**
364
	 * Tests that when a resource containing a cross reference is unload,
365
	 * the cross reference information is maintained and not accessible.
366
	 */
367
	public void test_unloadedCrossReference() {
368
		final Employee boss = EXTLibraryFactory.eINSTANCE.createEmployee();
369
370
		domain.runInUndoInterval(new Runnable() {
371
			public void run() {
372
				try {
373
					domain.runAsWrite(new MRunnable() {
374
					
375
						public Object run() {
376
							root.getEmployees().add(boss);
377
							otherEmp.setManager(boss);
378
379
							return null;
380
						}});
381
				} catch (MSLActionAbandonedException e) {
382
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
383
				}
384
			}});
385
		
386
		Collection xrefs = EObjectUtil.getReferencers(
387
				boss,
388
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
389
			
390
		assertTrue(xrefs.contains(otherEmp));
391
392
		// unload the resource containing the employee
393
		otherRes.unload();
394
		
395
		xrefs = EObjectUtil.getReferencers(
396
				boss,
397
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
398
			
399
		// cannot find references because resource was unloaded and are not returned
400
		assertTrue(xrefs.isEmpty());
401
	}
402
	
403
	/**
404
	 * Tests when a resource containing a cross reference and the referencer
405
	 * is destroyed, that the cross reference information is updated.
406
	 */
407
	public void test_destroyReferencer() {
408
		final Employee boss = EXTLibraryFactory.eINSTANCE.createEmployee();
409
410
		domain.runInUndoInterval(new Runnable() {
411
			public void run() {
412
				try {
413
					domain.runAsWrite(new MRunnable() {
414
					
415
						public Object run() {
416
							root.getEmployees().add(boss);
417
							domain.getResourceSet().eAdapters().add(new ECrossReferenceAdapter());
418
							otherEmp.setManager(boss);
419
							return null;
420
						}});
421
				} catch (MSLActionAbandonedException e) {
422
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
423
				}
424
			}});
425
426
		Collection xrefs = EObjectUtil.getReferencers(
427
				boss,
428
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
429
430
		assertTrue(xrefs.contains(otherEmp));
431
432
		domain.runInUndoInterval(new Runnable() {
433
			public void run() {
434
				try {
435
					domain.runAsWrite(new MRunnable() {
436
					
437
						public Object run() {
438
							EObjectUtil.destroy(otherEmp);
439
							return null;
440
						}});
441
				} catch (MSLActionAbandonedException e) {
442
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
443
				}
444
			}});
445
		xrefs = EObjectUtil.getReferencers(
446
				boss,
447
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
448
			
449
		assertTrue(xrefs.isEmpty());
450
	}
451
452
	/**
453
	 * Tests when a resource containing a cross reference and the referencer
454
	 * is detached, that the cross reference information is maintained.
455
	 */
456
	public void test_detachReferencer() {
457
		final Employee boss = EXTLibraryFactory.eINSTANCE.createEmployee();
458
459
		domain.runInUndoInterval(new Runnable() {
460
			public void run() {
461
				try {
462
					domain.runAsWrite(new MRunnable() {
463
					
464
						public Object run() {
465
							root.getEmployees().add(boss);
466
							otherEmp.setManager(boss);
467
							return null;
468
						}});
469
				} catch (MSLActionAbandonedException e) {
470
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
471
				}
472
			}});
473
474
		Collection xrefs = EObjectUtil.getReferencers(
475
				boss,
476
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
477
478
		assertTrue(xrefs.contains(otherEmp));
479
480
		domain.runInUndoInterval(new Runnable() {
481
			public void run() {
482
				try {
483
					domain.runAsWrite(new MRunnable() {
484
					
485
						public Object run() {
486
							otherRoot.getEmployees().remove(otherEmp);
487
							return null;
488
						}});
489
				} catch (MSLActionAbandonedException e) {
490
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
491
				}
492
			}});
493
		xrefs = EObjectUtil.getReferencers(
494
				boss,
495
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
496
			
497
		assertTrue(xrefs.contains(otherEmp));
498
	}
499
500
	/**
501
	 * Tests when a resource containing a cross reference and the referenced object
502
	 * is detached, that the cross reference information is maintained.
503
	 */
504
	public void test_detachReferenced() {
505
		final Employee boss = EXTLibraryFactory.eINSTANCE.createEmployee();
506
507
		domain.runInUndoInterval(new Runnable() {
508
			public void run() {
509
				try {
510
					domain.runAsWrite(new MRunnable() {
511
					
512
						public Object run() {
513
							root.getEmployees().add(boss);
514
							otherEmp.setManager(boss);
515
							return null;
516
						}});
517
				} catch (MSLActionAbandonedException e) {
518
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
519
				}
520
			}});
521
522
		Collection xrefs = EObjectUtil.getReferencers(
523
				boss,
524
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
525
526
		assertTrue(xrefs.contains(otherEmp));
527
528
		domain.runInUndoInterval(new Runnable() {
529
			public void run() {
530
				try {
531
					domain.runAsWrite(new MRunnable() {
532
					
533
						public Object run() {
534
							root.getEmployees().remove(boss);
535
							return null;
536
						}});
537
				} catch (MSLActionAbandonedException e) {
538
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
539
				}
540
			}});
541
		xrefs = EObjectUtil.getReferencers(
542
				boss,
543
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
544
			
545
		assertTrue(xrefs.contains(otherEmp));
546
	}
547
548
	/**
549
	 * Tests when a resource containing a bi-directional cross reference
550
	 * to an object and the reference is destroyed, that the cross
551
	 * reference information is updated correctly
552
	 */
553
	public void test_biDirectionalReference() {
554
		final Book rootBook = (Book)root.getBooks().get(0);
555
556
		domain.runInUndoInterval(new Runnable() {
557
			public void run() {
558
				try {
559
					domain.runAsWrite(new MRunnable() {
560
					
561
						public Object run() {
562
							otherWriter.getBooks().add(rootBook);
563
							return null;
564
						}});
565
				} catch (MSLActionAbandonedException e) {
566
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
567
				}
568
			}});
569
570
		Collection xrefs = EObjectUtil.getReferencers(
571
				rootBook,
572
				new EReference[] {EXTLibraryPackage.eINSTANCE.getWriter_Books()});
573
			
574
		assertTrue(xrefs.contains(otherWriter));
575
576
		domain.runUnvalidated(new MRunnable() {
577
			public Object run() {
578
				return domain.runInUndoInterval(new Runnable() {
579
					public void run() {
580
						try {
581
							domain.runAsWrite(new MRunnable() {
582
							
583
								public Object run() {
584
									EObjectUtil.destroy(otherWriter);
585
									otherWriter = null;
586
									return null;
587
								}});
588
						} catch (MSLActionAbandonedException e) {
589
							fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
590
						}
591
					}
592
				});
593
			}
594
		});
595
596
		xrefs = EObjectUtil.getReferencers(
597
				rootBook,
598
				new EReference[] {EXTLibraryPackage.eINSTANCE.getWriter_Books()});
599
			
600
		assertTrue(xrefs.isEmpty());
601
	}
602
603
	/**
604
	 * Tests when a resource containing a uni-directional cross reference
605
	 * to an object in another resource and the reference is destroyed,
606
	 * that the cross reference information is updated correctly
607
	 */
608
	public void test_uniDirectionalReference() {
609
		final Employee boss = EXTLibraryFactory.eINSTANCE.createEmployee();
610
611
		domain.runInUndoInterval(new Runnable() {
612
			public void run() {
613
				try {
614
					domain.runAsWrite(new MRunnable() {
615
					
616
						public Object run() {
617
							root.getEmployees().add(boss);
618
							otherEmp.setManager(boss);
619
							return null;
620
						}});
621
				} catch (MSLActionAbandonedException e) {
622
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
623
				}
624
			}});
625
626
		Collection xrefs = EObjectUtil.getReferencers(
627
				boss,
628
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
629
			
630
		assertTrue(xrefs.contains(otherEmp));
631
632
		domain.runInUndoInterval(new Runnable() {
633
			public void run() {
634
				try {
635
					domain.runAsWrite(new MRunnable() {
636
					
637
						public Object run() {
638
							EObjectUtil.destroy(otherEmp);
639
							otherEmp = null;
640
							return null;
641
						}});
642
				} catch (MSLActionAbandonedException e) {
643
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
644
				}
645
			}});
646
647
		xrefs = EObjectUtil.getReferencers(
648
				boss,
649
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
650
			
651
		assertTrue(xrefs.isEmpty());
652
	}
653
654
	/**
655
	 * Tests retrieving referencers of a specific type.
656
	 */
657
	public void test_getReferencersOfType() {
658
		final Employee boss = EXTLibraryFactory.eINSTANCE.createEmployee();
659
660
		domain.runInUndoInterval(new Runnable() {
661
			public void run() {
662
				try {
663
					domain.runAsWrite(new MRunnable() {
664
					
665
						public Object run() {
666
							root.getEmployees().add(boss);
667
							otherEmp.setManager(boss);
668
							return null;
669
						}});
670
				} catch (MSLActionAbandonedException e) {
671
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
672
				}
673
			}});
674
675
		MSLCrossReferenceAdapter crossReferenceAdapter =
676
			MSLCrossReferenceAdapter.getCrossReferenceAdapter(boss);
677
		
678
		// tests valid type
679
		Collection xrefs = crossReferenceAdapter.getInverseReferencers(boss,
680
				EXTLibraryPackage.eINSTANCE.getEmployee_Manager(),
681
				EXTLibraryPackage.eINSTANCE.getEmployee());
682
			
683
		assertTrue(xrefs.contains(otherEmp));
684
		
685
		// tests valid type
686
		xrefs = crossReferenceAdapter.getInverseReferencers(boss,
687
				null,
688
				EXTLibraryPackage.eINSTANCE.getEmployee());
689
			
690
		assertTrue(xrefs.contains(otherEmp));
691
		
692
		// tests invalid type
693
		xrefs = crossReferenceAdapter.getInverseReferencers(boss,
694
				EXTLibraryPackage.eINSTANCE.getEmployee_Manager(),
695
				EXTLibraryPackage.eINSTANCE.getLibrary());
696
			
697
		assertTrue(xrefs.isEmpty());
698
		
699
		// tests invalid type
700
		xrefs = crossReferenceAdapter.getInverseReferencers(boss,
701
				null,
702
				EXTLibraryPackage.eINSTANCE.getLibrary());
703
		
704
		assertTrue(xrefs.isEmpty());
705
	}
706
707
	/**
708
	 * Tests retrieving referencers when the cross reference adapter
709
	 * is not added to the ResourceSet when the domain is created, but rather
710
	 * added at a later point in time.
711
	 */
712
	public void test_addLateCrossReferenceAdapter() {
713
		MSLEditingDomain mslDomain = (MSLEditingDomain)domain;
714
		
715
		// remove the cross reference adapter from the ResourceSet
716
		mslDomain.getResourceSet().eAdapters().remove(mslDomain.getCrossReferenceAdapter());
717
		
718
		final Employee boss = EXTLibraryFactory.eINSTANCE.createEmployee();
719
720
		domain.runInUndoInterval(new Runnable() {
721
			public void run() {
722
				try {
723
					domain.runAsWrite(new MRunnable() {
724
					
725
						public Object run() {
726
							root.getEmployees().add(boss);
727
							otherEmp.setManager(boss);
728
							return null;
729
						}});
730
				} catch (MSLActionAbandonedException e) {
731
					fail("Failed to update model: " + e.getLocalizedMessage()); //$NON-NLS-1$
732
				}
733
			}});
734
735
		Collection xrefs = EObjectUtil.getReferencers(
736
				boss,
737
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
738
			
739
		assertTrue(xrefs.isEmpty());
740
741
		// add the cross reference adapter back to the ResourceSet
742
		mslDomain.getResourceSet().eAdapters().add(mslDomain.getCrossReferenceAdapter());
743
744
		// check that all children of the ResourceSet have a cross reference adapter
745
		checkHasCrossReferenceAdapter(mslDomain.getResourceSet());
746
		
747
		xrefs = EObjectUtil.getReferencers(
748
				boss,
749
				new EReference[] {EXTLibraryPackage.eINSTANCE.getEmployee_Manager()});
750
			
751
		assertTrue(xrefs.contains(otherEmp));
752
	}
753
754
	/* 
755
	 * Sets up a library test model:
756
	 * 
757
	 * Library     (otherRoot)
758
	 *  - Book     (otherBook)
759
	 *  - Writer   (otherWiter)
760
	 *  - Employee (otherEmp)
761
	 */
762
	protected void setUp() throws Exception {
763
764
		super.setUp();
765
766
		otherRes = ResourceUtil.create("/tmp/otherLibrary.extLibrary", //$NON-NLS-1$
767
				EXTLibraryPackage.eINSTANCE.getLibrary());
768
	
769
		domain.getResourceSet().getResources().add(otherRes);
770
771
		otherRoot = (Library)otherRes.getContents().get(0);
772
		otherBook = EXTLibraryFactory.eINSTANCE.createBook();
773
		otherWriter = EXTLibraryFactory.eINSTANCE.createWriter();
774
		otherEmp = EXTLibraryFactory.eINSTANCE.createEmployee();
775
776
		domain.runInUndoInterval(new Runnable() {
777
			public void run() {
778
				try {
779
					domain.runAsWrite(new MRunnable() {
780
					
781
						public Object run() {
782
							
783
							otherRoot.getBooks().add(otherBook);
784
							otherRoot.getWriters().add(otherWriter);
785
							otherRoot.getEmployees().add(otherEmp);
786
							
787
							return null;
788
						}});
789
				} catch (MSLActionAbandonedException e) {
790
					fail("Failed to setup test model: " + e.getLocalizedMessage()); //$NON-NLS-1$
791
				}
792
			}});
793
	}
794
795
	protected void tearDown() throws Exception {
796
797
		try {
798
			if (otherRes != null) {
799
				if (otherRes.isLoaded()) {
800
					otherRes.unload();
801
				}
802
803
				otherRes.getResourceSet().getResources().remove(otherRes);
804
			}
805
		} finally {
806
			super.tearDown();
807
		}
808
	}
809
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/notifications/MSLResourceListener.java (-4 / +1 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2002, 2003 IBM Corporation and others.
2
 * Copyright (c) 2002-2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 182-190 Link Here
182
182
183
						loadedResources.remove(notifier);
183
						loadedResources.remove(notifier);
184
184
185
						domain.getResourceIndexer().deregisterReferences(
186
							notifier);
187
188
						domain.getUndoStack().flushAll();
185
						domain.getUndoStack().flushAll();
189
186
190
						EObject root = null;
187
						EObject root = null;
(-)src/org/eclipse/gmf/runtime/emf/core/internal/notifications/MSLObjectListener.java (-78 / +1 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2002, 2004 IBM Corporation and others.
2
 * Copyright (c) 2002-2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-28 Link Here
11
11
12
package org.eclipse.gmf.runtime.emf.core.internal.notifications;
12
package org.eclipse.gmf.runtime.emf.core.internal.notifications;
13
13
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Iterator;
17
import java.util.List;
18
19
import org.eclipse.emf.common.notify.Notification;
14
import org.eclipse.emf.common.notify.Notification;
20
import org.eclipse.emf.ecore.EObject;
15
import org.eclipse.emf.ecore.EObject;
21
import org.eclipse.emf.ecore.EReference;
22
import org.eclipse.emf.ecore.resource.Resource;
16
import org.eclipse.emf.ecore.resource.Resource;
23
import org.eclipse.gmf.runtime.emf.core.EventTypes;
17
import org.eclipse.gmf.runtime.emf.core.EventTypes;
24
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
18
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
25
import org.eclipse.gmf.runtime.emf.core.internal.resources.MResource;
26
import org.eclipse.gmf.runtime.emf.core.internal.util.MSLUtil;
19
import org.eclipse.gmf.runtime.emf.core.internal.util.MSLUtil;
27
20
28
/**
21
/**
Lines 51-58 Link Here
51
44
52
		int eventType = notification.getEventType();
45
		int eventType = notification.getEventType();
53
46
54
		Object feature = notification.getFeature();
55
56
		if (resource != null) {
47
		if (resource != null) {
57
48
58
			if (!domain.getResouceListener().resourceFinishedLoading(resource))
49
			if (!domain.getResouceListener().resourceFinishedLoading(resource))
Lines 96-170 Link Here
96
		// populate undo stack.
87
		// populate undo stack.
97
		domain.getCommandGenerator().generateCommand(notification);
88
		domain.getCommandGenerator().generateCommand(notification);
98
89
99
		// process references.
100
		processReferences(notifier, eventType, newValue, oldValue, feature,
101
				resource);
102
103
		// forward event to broker.
90
		// forward event to broker.
104
		domain.getEventBroker().addEvent(notification);
91
		domain.getEventBroker().addEvent(notification);
105
	}
92
	}
106
107
	/**
108
	 * Process references and update reference maps.
109
	 */
110
	private void processReferences(EObject notifier, int eventType,
111
			Object newValue, Object oldValue, Object feature, Resource resource) {
112
113
		if (feature instanceof EReference) {
114
115
			// maintain the reverese reference map.
116
			EReference reference = (EReference) feature;
117
118
			List newObjects = new ArrayList();
119
			List oldObjects = new ArrayList();
120
121
			if ((eventType == Notification.SET)
122
					|| (eventType == Notification.UNSET)
123
					|| (eventType == Notification.ADD)
124
					|| (eventType == Notification.REMOVE)
125
					|| (eventType == Notification.ADD_MANY)
126
					|| (eventType == Notification.REMOVE_MANY)
127
					|| (eventType == Notification.RESOLVE)) {
128
129
				if (newValue instanceof EObject)
130
					newObjects.add(newValue);
131
132
				else if (newValue instanceof Collection) {
133
134
					Iterator i = ((Collection) newValue).iterator();
135
136
					while (i.hasNext()) {
137
138
						Object newObject = i.next();
139
140
						if (newObject instanceof EObject)
141
							newObjects.add(newObject);
142
					}
143
				}
144
145
				if (oldValue instanceof EObject)
146
					oldObjects.add(oldValue);
147
148
				else if (oldValue instanceof Collection) {
149
150
					Iterator i = ((Collection) oldValue).iterator();
151
152
					while (i.hasNext()) {
153
154
						Object oldObject = i.next();
155
156
						if (oldObject instanceof EObject)
157
							oldObjects.add(oldObject);
158
					}
159
				}
160
			}
161
162
			if (resource instanceof MResource)
163
				((MResource) resource).getHelper().registerReferences(domain,
164
						notifier, reference, newObjects, oldObjects);
165
			else
166
				MSLUtil.registerReferences(domain, notifier, reference,
167
						newObjects, oldObjects);
168
		}
169
	}
170
}
93
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/index/MSLReferenceVisitor.java (-41 / +73 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
2
 * Copyright (c) 2004-2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-23 Link Here
11
11
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
13
13
14
import java.lang.ref.WeakReference;
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Collections;
17
import java.util.HashMap;
18
import java.util.Iterator;
15
import java.util.List;
19
import java.util.List;
16
import java.util.Map;
20
import java.util.Map;
21
import java.util.Set;
17
22
18
import org.eclipse.emf.ecore.EObject;
23
import org.eclipse.emf.ecore.EObject;
19
import org.eclipse.emf.ecore.EReference;
24
import org.eclipse.emf.ecore.EReference;
20
25
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
21
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
26
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
22
27
23
/**
28
/**
Lines 32-64 Link Here
32
37
33
	protected EObject referencedObject = null;
38
	protected EObject referencedObject = null;
34
39
35
	private boolean resolve = true;
36
37
	/**
40
	/**
38
	 * Constructor.
41
	 * Constructor.
39
	 */
42
	 */
40
	public MSLReferenceVisitor(MSLEditingDomain domain, EObject eObject) {
43
	public MSLReferenceVisitor(MSLEditingDomain domain, EObject eObject) {
41
		this(domain, eObject, true);
42
	}
43
44
	/**
45
	 * Constructor.
46
	 */
47
	public MSLReferenceVisitor(MSLEditingDomain domain, EObject eObject,
48
			boolean resolve) {
49
50
		this.domain = domain;
44
		this.domain = domain;
51
		this.referencedObject = eObject;
45
		this.referencedObject = eObject;
52
		this.resolve = resolve;
53
	}
46
	}
54
47
48
55
	/**
49
	/**
56
	 * Visit all the referencers.
50
	 * Visit all the referencers.
57
	 */
51
	 */
58
	public void visitReferencers() {
52
	public void visitReferencers() {
59
53
60
		Map featureMap = domain.getObjectIndexer().getGroupedReferencers(
54
		Map featureMap = getGroupedReferencers(referencedObject);
61
			referencedObject, resolve);
62
55
63
		// operate on a clone to prevent concurrent access exceptions.
56
		// operate on a clone to prevent concurrent access exceptions.
64
		Object[] references = featureMap.keySet().toArray();
57
		Object[] references = featureMap.keySet().toArray();
Lines 67-112 Link Here
67
60
68
			EReference reference = (EReference) references[i];
61
			EReference reference = (EReference) references[i];
69
62
70
			Object value = featureMap.get(reference);
63
			List referencerList = (List)featureMap.get(reference);
71
64
72
			if (value instanceof List) {
65
			// operate on a clone to prevent concurrent access exceptions.
66
			Object[] referencers = referencerList.toArray();
73
67
74
				List referencerList = (List) value;
68
			for (int j = 0; j < referencers.length; j++) {
69
				EObject referencer = (EObject) referencerList.get(j);
75
70
76
				// operate on a clone to prevent concurrent access exceptions.
71
				visitedReferencer(reference, referencer);
77
				Object[] referencers = referencerList.toArray();
72
			}
73
		}
74
	}
78
75
79
				for (int j = 0; j < referencers.length; j++) {
76
	/**
77
	 * Override to implement processing the visit.
78
	 */
79
	protected abstract void visitedReferencer(EReference reference,
80
			EObject referencer);
80
81
81
					WeakReference r = (WeakReference) referencerList.get(j);
82
	/**
83
	 * For the given referenced EObject, returns a Map whose keys are EReferences
84
	 * and values are EObjects that reference the referenced EObject with the key
85
	 * EReference.
86
	 * 
87
	 * @param referenced the referenced EObject
88
	 * @return a Map of referencers
89
	 */
90
	private Map getGroupedReferencers(EObject referenced) {
82
91
83
					if (r != null) {
92
		Map newMap = new HashMap();
84
93
85
						EObject referencer = (EObject) r.get();
94
		MSLCrossReferenceAdapter crossReferenceAdapter = domain.getCrossReferenceAdapter();
86
95
87
						if (referencer != null)
96
		// first group all the inverse referencers
88
							visitedReferencer(reference, referencer);
97
		Collection nonNavigableInverseReferences = 
89
					}
98
			crossReferenceAdapter.getNonNavigableInverseReferences(referenced);
99
100
		if (nonNavigableInverseReferences != null &&
101
				!nonNavigableInverseReferences.isEmpty()) {
102
			for (Iterator iter = nonNavigableInverseReferences.iterator(); iter
103
					.hasNext();) {
104
				Setting setting = (Setting) iter.next();
105
				List list = (List)newMap.get(setting.getEStructuralFeature());
106
				if (list == null) {
107
					list = new ArrayList();
108
					list.add(setting.getEObject());
109
					newMap.put(setting.getEStructuralFeature(), list);
110
				} else {
111
					list.add(setting.getEObject());
90
				}
112
				}
113
			}
114
		}
115
116
		// next loop through all the EReferences to find referencers
117
		// for those EReferences with opposites
118
		List features = referenced.eClass().getEAllReferences();
119
120
		for (Iterator i = features.iterator(); i.hasNext();) {
121
122
			EReference reference = (EReference) i.next();
91
123
92
			} else if (value instanceof WeakReference) {
124
			EReference opposite = reference.getEOpposite();
93
125
94
				WeakReference r = (WeakReference) value;
126
			if (opposite != null && reference.isChangeable()
127
					&& !reference.isContainer() && !reference.isContainment()) {
95
128
96
				if (r != null) {
129
				Set referencers = crossReferenceAdapter.getInverseReferencers(referenced, opposite, null);
97
130
98
					EObject referencer = (EObject) r.get();
131
				if (!referencers.isEmpty()) {
99
132
100
					if (referencer != null)
133
					newMap.put(opposite, new ArrayList(referencers));
101
						visitedReferencer(reference, referencer);
102
				}
134
				}
103
			}
135
			}
104
		}
136
		}
105
	}
106
137
107
	/**
138
		if (newMap != null) {
108
	 * Override to implement processing the visit.
139
			return Collections.unmodifiableMap(newMap);
109
	 */
140
		} else {
110
	protected abstract void visitedReferencer(EReference reference,
141
			return Collections.EMPTY_MAP;
111
			EObject referencer);
142
		}
143
	}
112
}
144
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/index/MSLObjectIndexer.java (-905 lines)
Removed Link Here
1
/******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
10
 ****************************************************************************/
11
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
13
14
import java.lang.ref.WeakReference;
15
import java.util.ArrayList;
16
import java.util.Collections;
17
import java.util.HashMap;
18
import java.util.HashSet;
19
import java.util.Iterator;
20
import java.util.List;
21
import java.util.Map;
22
import java.util.Set;
23
24
import org.eclipse.emf.common.notify.Adapter;
25
import org.eclipse.emf.common.util.EList;
26
import org.eclipse.emf.common.util.URI;
27
import org.eclipse.emf.ecore.EObject;
28
import org.eclipse.emf.ecore.EReference;
29
import org.eclipse.emf.ecore.resource.Resource;
30
import org.eclipse.emf.ecore.util.EcoreUtil;
31
import org.eclipse.emf.ecore.util.InternalEList;
32
33
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
34
import org.eclipse.gmf.runtime.emf.core.internal.resources.MResourceFactory;
35
import org.eclipse.gmf.runtime.emf.core.internal.util.MSLUtil;
36
import org.eclipse.gmf.runtime.emf.core.util.EObjectUtil;
37
38
/**
39
 * This class manages the reverse reference map feature at the object level.
40
 * When resources are loaded the reverse map gets updated without causing more
41
 * resources to be loaded.
42
 * 
43
 * @author rafikj
44
 */
45
public class MSLObjectIndexer {
46
47
	private MSLEditingDomain domain = null;
48
49
	/**
50
	 * Constructor.
51
	 */
52
	public MSLObjectIndexer(MSLEditingDomain domain) {
53
54
		super();
55
56
		this.domain = domain;
57
	}
58
59
	/**
60
	 * Registers a reference in the reverse reference map.
61
	 */
62
	public boolean registerReference(EObject referencer, EObject referenced,
63
			EReference reference) {
64
65
		// ignore non changeable and container/containment features.
66
		if ((!reference.isChangeable()) || (reference.isContainer())
67
			|| (reference.isContainment()))
68
			return false;
69
70
		if (referencer.eIsProxy())
71
			return false;
72
73
		// register resource reference.
74
		Resource referencerResource = referencer.eResource();
75
76
		Resource referencedResource = MSLUtil.getResource(domain, referenced);
77
78
		if (referenced.eIsProxy()) {
79
80
			URI uri = EcoreUtil.getURI(referenced);
81
82
			Resource.Factory factory = Resource.Factory.Registry.INSTANCE
83
				.getFactory(uri);
84
85
			if (!(factory instanceof MResourceFactory)) {
86
87
				if ((referencerResource == referencedResource)
88
					|| ((referencedResource != null) && (referencedResource
89
						.isLoaded())))
90
					referenced = EcoreUtil.resolve(referenced, domain
91
						.getResourceSet());
92
			}
93
		}
94
95
		domain.getResourceIndexer().registerReference(referencerResource,
96
			referencedResource);
97
98
		return doRegisterReference(referencer, referenced, reference);
99
	}
100
101
	/**
102
	 * Registers a reference in the reverse reference map.
103
	 */
104
	private boolean doRegisterReference(EObject referencer, EObject referenced,
105
			EReference reference) {
106
107
		// ignore features that have opposites.
108
		if (reference.getEOpposite() != null)
109
			return false;
110
111
		// objects must be resolved.
112
		if (referenced.eIsProxy())
113
			return false;
114
115
		Map featureMap = getFeatureMap(referenced);
116
117
		if (featureMap == null)
118
			featureMap = createFeatureMap(referenced);
119
120
		WeakReference ref = new WeakReference(referencer);
121
122
		Object value = featureMap.get(reference);
123
124
		// value is a list.
125
		if (value instanceof List) {
126
127
			int index = -1;
128
129
			List referencerList = (List) value;
130
131
			for (int i = 0, count = referencerList.size(); i < count; i++) {
132
133
				WeakReference r = (WeakReference) referencerList.get(i);
134
135
				if (r == null) {
136
137
					// found empty slot.
138
					if (index == -1)
139
						index = i;
140
141
				} else {
142
143
					Object current = r.get();
144
145
					// object already there.
146
					if (current == referencer)
147
						ref = null;
148
149
					else if (current == null) {
150
151
						referencerList.set(i, null);
152
153
						// found empty slot.
154
						if (index == -1)
155
							index = i;
156
					}
157
				}
158
			}
159
160
			// if not already there add.
161
			if (ref != null) {
162
163
				// resuse slot if any.
164
				if (index != -1)
165
					referencerList.set(index, ref);
166
				else
167
					referencerList.add(ref);
168
			}
169
170
		} else if (value instanceof WeakReference) {
171
172
			// value is a weak reference.
173
			WeakReference r = (WeakReference) value;
174
175
			Object current = r.get();
176
177
			if (current == referencer) {
178
179
				// already there.
180
				ref = null;
181
182
			} else if (current == null) {
183
184
				// put in empty slot.
185
				featureMap.put(reference, ref);
186
187
			} else {
188
189
				// create a new list if more than one.
190
				List referencerList = new ArrayList(2);
191
192
				referencerList.add(r);
193
				referencerList.add(ref);
194
195
				featureMap.put(reference, referencerList);
196
			}
197
198
		} else if (value == null) {
199
200
			// found empty slot.
201
			featureMap.put(reference, ref);
202
		}
203
204
		return true;
205
	}
206
207
	/**
208
	 * Deregisters a reference in the reverse reference map.
209
	 */
210
	public void deregisterReference(EObject referencer, EObject referenced,
211
			EReference reference) {
212
213
		// ignore non changeable and container/containment features.
214
		if ((!reference.isChangeable()) || (reference.isContainer())
215
			|| (reference.isContainment()))
216
			return;
217
218
		if (referencer.eIsProxy())
219
			return;
220
221
		// deregister resource reference.
222
		Resource referencerResource = referencer.eResource();
223
224
		Resource referencedResource = MSLUtil.getResource(domain, referenced);
225
226
		domain.getResourceIndexer().deregisterReference(referencerResource,
227
			referencedResource);
228
229
		doDeregisterReference(referencer, referenced, reference);
230
	}
231
232
	/**
233
	 * Deregisters a reference in the reverse reference map.
234
	 */
235
	private void doDeregisterReference(EObject referencer, EObject referenced,
236
			EReference reference) {
237
238
		Map featureMap = getFeatureMap(referenced);
239
240
		if (featureMap == null)
241
			return;
242
243
		Object value = featureMap.get(reference);
244
245
		if (value instanceof List) {
246
247
			// value is a list.
248
			List referencerList = (List) value;
249
250
			boolean empty = true;
251
252
			for (int i = 0, count = referencerList.size(); i < count; i++) {
253
254
				WeakReference r = (WeakReference) referencerList.get(i);
255
256
				if (r != null) {
257
258
					Object current = r.get();
259
260
					if (current == referencer)
261
						referencerList.set(i, null);
262
263
					else if (current == null)
264
						referencerList.set(i, null);
265
266
					else if (empty)
267
						empty = false;
268
				}
269
			}
270
271
			if (empty)
272
				featureMap.remove(reference);
273
274
		} else if (value instanceof WeakReference) {
275
276
			// value is a weak reference.
277
			WeakReference r = (WeakReference) value;
278
279
			if (r.get() == referencer)
280
				featureMap.remove(reference);
281
282
		} else
283
			return;
284
285
		if (featureMap.isEmpty())
286
			removeFeatureMap(referenced);
287
	}
288
289
	/**
290
	 * Registers references by traversing the referencer object. Referencer is a
291
	 * non proxy object.
292
	 */
293
	public void registerReferences(EObject container, EObject eObject) {
294
295
		if (eObject.eIsProxy())
296
			return;
297
298
		EList features = eObject.eClass().getEAllReferences();
299
300
		Iterator i = features.iterator();
301
302
		while (i.hasNext()) {
303
304
			EReference reference = (EReference) i.next();
305
306
			if ((reference.isChangeable()) && (!reference.isContainer())
307
				&& (eObject.eIsSet(reference))) {
308
309
				if (reference.isMany()) {
310
311
					if (reference.isContainment()) {
312
313
						EList objects = (EList) eObject.eGet(reference);
314
315
						for (Iterator j = objects.iterator(); j.hasNext();) {
316
317
							EObject contained = (EObject) j.next();
318
319
							if (contained != null)
320
								registerReferences(container, contained);
321
						}
322
323
					} else {
324
325
						EList objects = (EList) eObject.eGet(reference, false);
326
327
						// ensure references are not resolved.
328
						boolean resolve = true;
329
330
						for (Iterator j = ((InternalEList) objects)
331
							.basicIterator(); j.hasNext();) {
332
333
							EObject referenced = (EObject) j.next();
334
335
							if (referenced != null) {
336
337
								if (!registerReference(eObject, referenced,
338
									reference))
339
									resolve = false;
340
							}
341
						}
342
343
						// if all references were resolveable resolve the whole
344
						// list.
345
						if (resolve) {
346
347
							for (Iterator k = objects.iterator(); k.hasNext();)
348
								k.next();
349
						}
350
					}
351
352
				} else {
353
354
					if (reference.isContainment()) {
355
356
						EObject contained = (EObject) eObject.eGet(reference);
357
358
						if (contained != null)
359
							registerReferences(container, contained);
360
361
					} else {
362
363
						// ensure reference is not resolved.
364
						EObject referenced = (EObject) eObject.eGet(reference,
365
							false);
366
367
						if (referenced != null) {
368
369
							boolean resolve = registerReference(eObject,
370
								referenced, reference);
371
372
							// if reference was resolveable resolve it.
373
							if (resolve)
374
								eObject.eGet(reference);
375
						}
376
					}
377
				}
378
			}
379
		}
380
381
		// register referencer resources.
382
		final Resource containerResource = container.eResource();
383
384
		MSLReferenceVisitor visitor = new MSLReferenceVisitor(domain, eObject,
385
			false) {
386
387
			protected void visitedReferencer(EReference reference,
388
					EObject referencer) {
389
390
				Resource referencerResource = referencer.eResource();
391
392
				domain.getResourceIndexer().registerReference(
393
					referencerResource, containerResource);
394
			}
395
		};
396
397
		visitor.visitReferencers();
398
	}
399
400
	/**
401
	 * Deregisters references by traversing the referencer object.
402
	 */
403
	public void deregisterReferences(EObject container, EObject eObject) {
404
		deregisterReferences(container, eObject, eObject);
405
	}
406
407
	/**
408
	 * Deregisters references by traversing the referencer object.
409
	 */
410
	public void deregisterReferences(EObject container, final EObject detached,
411
			EObject eObject) {
412
413
		if (eObject.eIsProxy())
414
			return;
415
416
		final Resource containerResource = container.eResource();
417
418
		EList features = eObject.eClass().getEAllReferences();
419
420
		Iterator i = features.iterator();
421
422
		while (i.hasNext()) {
423
424
			EReference reference = (EReference) i.next();
425
426
			if ((reference.isChangeable()) && (!reference.isContainer())
427
				&& (eObject.eIsSet(reference))) {
428
429
				if (reference.isMany()) {
430
431
					if (reference.isContainment()) {
432
433
						EList objects = (EList) eObject.eGet(reference);
434
435
						for (Iterator j = objects.iterator(); j.hasNext();) {
436
437
							EObject contained = (EObject) j.next();
438
439
							if (contained != null)
440
								deregisterReferences(container, detached,
441
									contained);
442
						}
443
444
					} else {
445
446
						EList objects = (EList) eObject.eGet(reference, false);
447
448
						// ensure references are not resolved.
449
						for (Iterator j = ((InternalEList) objects)
450
							.basicIterator(); j.hasNext();) {
451
452
							EObject referenced = (EObject) j.next();
453
454
							if ((referenced != null)
455
								&& (!EObjectUtil.contains(detached, referenced))) {
456
457
								Resource referencedResource = MSLUtil
458
									.getResource(domain, referenced);
459
460
								domain.getResourceIndexer()
461
									.deregisterReference(containerResource,
462
										referencedResource);
463
							}
464
						}
465
					}
466
467
				} else {
468
469
					if (reference.isContainment()) {
470
471
						EObject contained = (EObject) eObject.eGet(reference);
472
473
						if (contained != null)
474
							deregisterReferences(container, detached, contained);
475
476
					} else {
477
478
						// ensure reference is not resolved.
479
						EObject referenced = (EObject) eObject.eGet(reference,
480
							false);
481
482
						if ((referenced != null)
483
							&& (!EObjectUtil.contains(detached, referenced))) {
484
485
							Resource referencedResource = MSLUtil.getResource(
486
								domain, referenced);
487
488
							domain.getResourceIndexer().deregisterReference(
489
								containerResource, referencedResource);
490
						}
491
					}
492
				}
493
			}
494
		}
495
496
		// deregister referencer resources.
497
		MSLReferenceVisitor visitor = new MSLReferenceVisitor(domain, eObject) {
498
499
			protected void visitedReferencer(EReference reference,
500
					EObject referencer) {
501
502
				if (!EObjectUtil.contains(detached, referencer)) {
503
504
					Resource referencerResource = referencer.eResource();
505
506
					domain.getResourceIndexer().deregisterReference(
507
						referencerResource, containerResource);
508
				}
509
			}
510
		};
511
512
		visitor.visitReferencers();
513
	}
514
515
	/**
516
	 * Resolves references by traversing the referencer object. Referencer is a
517
	 * non proxy object.
518
	 */
519
	public void resolveReferences(EObject container, EObject eObject) {
520
521
		if (eObject.eIsProxy())
522
			return;
523
524
		EList features = eObject.eClass().getEAllReferences();
525
526
		Iterator i = features.iterator();
527
528
		while (i.hasNext()) {
529
530
			EReference reference = (EReference) i.next();
531
532
			if ((reference.isChangeable()) && (!reference.isContainer())
533
				&& (eObject.eIsSet(reference))) {
534
535
				if (reference.isMany()) {
536
537
					if (reference.isContainment()) {
538
539
						EList objects = (EList) eObject.eGet(reference);
540
541
						for (Iterator j = objects.iterator(); j.hasNext();) {
542
543
							EObject contained = (EObject) j.next();
544
545
							if (contained != null)
546
								resolveReferences(container, contained);
547
						}
548
549
					} else {
550
551
						EList objects = (EList) eObject.eGet(reference, false);
552
553
						// ensure references are not resolved.
554
						boolean resolve = true;
555
556
						for (Iterator j = ((InternalEList) objects)
557
							.basicIterator(); j.hasNext();) {
558
559
							EObject referenced = (EObject) j.next();
560
561
							if (referenced != null) {
562
563
								if (!resolveReference(eObject, referenced,
564
									reference))
565
									resolve = false;
566
							}
567
						}
568
569
						// if all references were resolveable resolve the whole
570
						// list.
571
						if (resolve) {
572
573
							for (Iterator k = objects.iterator(); k.hasNext();)
574
								k.next();
575
						}
576
					}
577
578
				} else {
579
580
					if (reference.isContainment()) {
581
582
						EObject contained = (EObject) eObject.eGet(reference);
583
584
						if (contained != null)
585
							resolveReferences(container, contained);
586
587
					} else {
588
589
						// ensure reference is not resolved.
590
						EObject referenced = (EObject) eObject.eGet(reference,
591
							false);
592
593
						if (referenced != null) {
594
595
							boolean resolve = resolveReference(eObject,
596
								referenced, reference);
597
598
							// if reference was resolveable resolve it.
599
							if (resolve)
600
								eObject.eGet(reference);
601
						}
602
					}
603
				}
604
			}
605
		}
606
	}
607
608
	/**
609
	 * Resolves a reference.
610
	 */
611
	public boolean resolveReference(EObject referencer, EObject referenced,
612
			EReference reference) {
613
614
		// ignore non changeable and container/containment features.
615
		if ((!reference.isChangeable()) || (reference.isContainer())
616
			|| (reference.isContainment()))
617
			return false;
618
619
		if (referencer.eIsProxy())
620
			return false;
621
622
		if (referenced.eIsProxy()) {
623
624
			// register resource reference.
625
			Resource referencerResource = referencer.eResource();
626
627
			Resource referencedResource = MSLUtil.getResource(domain,
628
				referenced);
629
630
			URI uri = EcoreUtil.getURI(referenced);
631
632
			Resource.Factory factory = Resource.Factory.Registry.INSTANCE
633
				.getFactory(uri);
634
635
			if (!(factory instanceof MResourceFactory)) {
636
637
				if ((referencerResource == referencedResource)
638
					|| ((referencedResource != null) && (referencedResource
639
						.isLoaded())))
640
					referenced = EcoreUtil.resolve(referenced, domain
641
						.getResourceSet());
642
			}
643
644
			if (referenced.eIsProxy())
645
				return false;
646
			else
647
				doRegisterReference(referencer, referenced, reference);
648
		}
649
650
		return true;
651
	}
652
653
	/**
654
	 * Retrieves reverse references.
655
	 */
656
	public Map getGroupedReferencers(EObject referenced) {
657
		return getGroupedReferencers(referenced, true);
658
	}
659
660
	/**
661
	 * Retrieves reverse references.
662
	 */
663
	public Map getGroupedReferencers(EObject referenced, boolean resolve) {
664
665
		Map map = getFeatureMap(referenced);
666
667
		Map newMap = null;
668
669
		List features = referenced.eClass().getEAllReferences();
670
671
		for (Iterator i = features.iterator(); i.hasNext();) {
672
673
			EReference reference = (EReference) i.next();
674
675
			EReference opposite = reference.getEOpposite();
676
677
			if (opposite != null) {
678
679
				Set referencers = getReferencers(referenced, opposite, resolve);
680
681
				if (!referencers.isEmpty()) {
682
683
					if (newMap == null)
684
						newMap = (map == null) ? (new HashMap())
685
							: (new HashMap(map));
686
687
					List newReferencers = new ArrayList(referencers.size());
688
689
					for (Iterator j = referencers.iterator(); j.hasNext();)
690
						newReferencers.add(new WeakReference(j.next()));
691
692
					newMap.put(opposite, newReferencers);
693
				}
694
			}
695
		}
696
697
		if (newMap != null)
698
			return Collections.unmodifiableMap(newMap);
699
700
		else if (map != null)
701
			return Collections.unmodifiableMap(map);
702
703
		else
704
			return Collections.EMPTY_MAP;
705
	}
706
707
	/**
708
	 * Retrieves reverse references.
709
	 */
710
	public Set getAllReferencers(EObject referenced) {
711
		return getAllReferencers(referenced, true);
712
	}
713
714
	/**
715
	 * Retrieves reverse references.
716
	 */
717
	public Set getAllReferencers(EObject referenced, boolean resolve) {
718
719
		if (referenced.eIsProxy())
720
			return Collections.EMPTY_SET;
721
722
		final Set set = new HashSet();
723
724
		MSLReferenceVisitor visitor = new MSLReferenceVisitor(domain,
725
			referenced, resolve) {
726
727
			protected void visitedReferencer(EReference reference,
728
					EObject referencer) {
729
730
				if (!referencer.eIsProxy())
731
					set.add(referencer);
732
			}
733
		};
734
735
		visitor.visitReferencers();
736
737
		return Collections.unmodifiableSet(set);
738
	}
739
740
	/**
741
	 * Retrieves reverse references.
742
	 */
743
	public Set getReferencers(EObject referenced, EReference reference) {
744
		return getReferencers(referenced, reference, true);
745
	}
746
747
	/**
748
	 * Retrieves reverse references.
749
	 */
750
	public Set getReferencers(EObject referenced, EReference reference,
751
			boolean resolve) {
752
753
		if (referenced.eIsProxy())
754
			return Collections.EMPTY_SET;
755
756
		if ((reference.isChangeable()) && (!reference.isContainer())
757
			&& (!reference.isContainment())) {
758
759
			EReference opposite = reference.getEOpposite();
760
761
			if (opposite == null) {
762
763
				Map featureMap = getFeatureMap(referenced);
764
765
				if (featureMap != null) {
766
767
					Object value = featureMap.get(reference);
768
769
					if (value instanceof List) {
770
771
						// value is a list.
772
						List referencerList = (List) value;
773
774
						Set set = new HashSet();
775
776
						for (int i = 0, count = referencerList.size(); i < count; i++) {
777
778
							WeakReference r = (WeakReference) referencerList
779
								.get(i);
780
781
							if (r != null) {
782
783
								EObject referencer = (EObject) r.get();
784
785
								if ((referencer != null)
786
									&& (!referencer.eIsProxy()))
787
									set.add(referencer);
788
							}
789
						}
790
791
						return Collections.unmodifiableSet(set);
792
793
					} else if (value instanceof WeakReference) {
794
795
						// value is a weak reference.
796
						WeakReference r = (WeakReference) value;
797
798
						EObject referencer = (EObject) r.get();
799
800
						if (referencer != null)
801
							return Collections.singleton(referencer);
802
					}
803
				}
804
805
			} else {
806
807
				if ((opposite.isChangeable()) && (!opposite.isContainer())
808
					&& (!opposite.isContainment())
809
					&& (referenced.eIsSet(opposite))) {
810
811
					if (opposite.isMany()) {
812
813
						List referencers = (List) referenced.eGet(opposite,
814
							resolve);
815
816
						if (!referencers.isEmpty()) {
817
818
							// try not to resolve if asked to.
819
							if (resolve)
820
								return Collections.unmodifiableSet(new HashSet(
821
									referencers));
822
							else {
823
824
								Set nonProxyReferencers = new HashSet();
825
826
								for (Iterator j = ((InternalEList) referencers)
827
									.basicIterator(); j.hasNext();) {
828
829
									EObject referencer = (EObject) j.next();
830
831
									if ((referencer != null)
832
										&& (!referencer.eIsProxy()))
833
										nonProxyReferencers.add(referencer);
834
								}
835
836
								return Collections
837
									.unmodifiableSet(nonProxyReferencers);
838
							}
839
						}
840
841
					} else {
842
843
						// try not to resolve if asked to.
844
						EObject referencer = (EObject) referenced.eGet(
845
							opposite, resolve);
846
847
						if ((referencer != null) && (!referencer.eIsProxy()))
848
							return Collections.singleton(referencer);
849
					}
850
				}
851
			}
852
		}
853
854
		return Collections.EMPTY_SET;
855
	}
856
857
	/**
858
	 * Gets feature map of a given object.
859
	 */
860
	private Map getFeatureMap(EObject referenced) {
861
862
		for (int i = 0, count = referenced.eAdapters().size(); i < count; i++) {
863
864
			Adapter adapter = (Adapter) referenced.eAdapters().get(i);
865
866
			if (adapter instanceof MSLReferenceAdapter)
867
				return (Map) adapter;
868
		}
869
870
		return null;
871
	}
872
873
	/**
874
	 * Creates feature map of a given object.
875
	 */
876
	private Map createFeatureMap(EObject referenced) {
877
878
		Map map = new MSLReferenceAdapter();
879
880
		referenced.eAdapters().add(map);
881
882
		return map;
883
	}
884
885
	/**
886
	 * Removes feature map of a given object.
887
	 */
888
	private Map removeFeatureMap(EObject referenced) {
889
890
		for (int i = 0, count = referenced.eAdapters().size(); i < count; i++) {
891
892
			Adapter adapter = (Adapter) referenced.eAdapters().get(i);
893
894
			if (adapter instanceof MSLReferenceAdapter) {
895
896
				referenced.eAdapters().remove(i);
897
898
				return (Map) adapter;
899
			}
900
		}
901
902
		return null;
903
	}
904
}
905
(-)src/org/eclipse/gmf/runtime/emf/core/internal/index/MSLExportsAdapter.java (-66 lines)
Removed Link Here
1
/******************************************************************************
2
 * Copyright (c) 2002, 2003 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
10
 ****************************************************************************/
11
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
13
14
import java.util.HashMap;
15
16
import org.eclipse.emf.common.notify.Adapter;
17
import org.eclipse.emf.common.notify.Notification;
18
import org.eclipse.emf.common.notify.Notifier;
19
20
/**
21
 * This class defines the reference adapter that will hold the exports for a
22
 * given resource.
23
 * 
24
 * @author rafikj
25
 */
26
public class MSLExportsAdapter
27
	extends HashMap
28
	implements Adapter {
29
30
	private static final long serialVersionUID = -9110312883845863489L;
31
32
	/**
33
	 * Constructor.
34
	 */
35
	public MSLExportsAdapter() {
36
		super(2);
37
	}
38
39
	/**
40
	 * @see org.eclipse.emf.common.notify.Adapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
41
	 */
42
	public void notifyChanged(Notification notification) {
43
		// do nothing.
44
	}
45
46
	/**
47
	 * @see org.eclipse.emf.common.notify.Adapter#getTarget()
48
	 */
49
	public Notifier getTarget() {
50
		return null;
51
	}
52
53
	/**
54
	 * @see org.eclipse.emf.common.notify.Adapter#setTarget(org.eclipse.emf.common.notify.Notifier)
55
	 */
56
	public void setTarget(Notifier newTarget) {
57
		// do nothing.
58
	}
59
60
	/**
61
	 * @see org.eclipse.emf.common.notify.Adapter#isAdapterForType(java.lang.Object)
62
	 */
63
	public boolean isAdapterForType(Object type) {
64
		return false;
65
	}
66
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/index/MSLResourceIndexer.java (-388 lines)
Removed Link Here
1
/******************************************************************************
2
 * Copyright (c) 2002, 2003 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
10
 ****************************************************************************/
11
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
13
14
import java.util.Collections;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
20
import org.eclipse.emf.common.notify.Adapter;
21
import org.eclipse.emf.common.notify.impl.NotificationImpl;
22
import org.eclipse.emf.ecore.EObject;
23
import org.eclipse.emf.ecore.resource.Resource;
24
25
import org.eclipse.gmf.runtime.emf.core.EventTypes;
26
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
27
28
/**
29
 * This class manages the reverse reference map feature at the resource level.
30
 * When resources are loaded the reverse map gets updated without causing more
31
 * resources to be loaded.
32
 * 
33
 * @author rafikj
34
 */
35
public class MSLResourceIndexer {
36
37
	private MSLEditingDomain domain = null;
38
39
	/**
40
	 * Constructor.
41
	 */
42
	public MSLResourceIndexer(MSLEditingDomain domain) {
43
44
		super();
45
46
		this.domain = domain;
47
	}
48
49
	/**
50
	 * Registers a reference in the imports and exports maps.
51
	 */
52
	public void registerReference(final Resource referencer,
53
			final Resource referenced) {
54
55
		if ((referencer != null) && (referenced != null)
56
			&& (referencer != referenced)) {
57
58
			Map importsMap = getImportsMap(referencer);
59
60
			if (importsMap == null)
61
				importsMap = createImportsMap(referencer);
62
63
			Integer importsCount = (Integer) importsMap.get(referenced);
64
65
			if (importsCount == null) {
66
67
				domain.sendNotification(new NotificationImpl(
68
					EventTypes.IMPORT, (Object) null, referenced, -1) {
69
70
					public Object getNotifier() {
71
						return referencer;
72
					}
73
				});
74
75
				importsCount = new Integer(1);
76
77
			} else
78
				importsCount = new Integer(importsCount.intValue() + 1);
79
80
			importsMap.put(referenced, importsCount);
81
82
			Map exportsMap = getExportsMap(referenced);
83
84
			if (exportsMap == null)
85
				exportsMap = createExportsMap(referenced);
86
87
			Integer exportsCount = (Integer) exportsMap.get(referencer);
88
89
			if (exportsCount == null) {
90
91
				domain.sendNotification(new NotificationImpl(
92
					EventTypes.EXPORT, (Object) null, referencer, -1) {
93
94
					public Object getNotifier() {
95
						return referenced;
96
					}
97
				});
98
99
				exportsCount = new Integer(1);
100
101
			} else
102
				exportsCount = new Integer(exportsCount.intValue() + 1);
103
104
			exportsMap.put(referencer, exportsCount);
105
		}
106
	}
107
108
	/**
109
	 * Dregisters a reference in the imports and exports maps.
110
	 */
111
	public void deregisterReference(final Resource referencer,
112
			final Resource referenced) {
113
114
		if ((referencer != null) && (referenced != null)
115
			&& (referencer != referenced)) {
116
117
			Map importsMap = getImportsMap(referencer);
118
119
			if (importsMap != null) {
120
121
				Integer importsCount = (Integer) importsMap.get(referenced);
122
123
				if (importsCount != null) {
124
125
					if (importsCount.intValue() < 2) {
126
127
						importsMap.remove(referenced);
128
129
						domain.sendNotification(new NotificationImpl(
130
							EventTypes.IMPORT, referenced, (Object) null, -1) {
131
132
							public Object getNotifier() {
133
								return referencer;
134
							}
135
						});
136
					} else
137
						importsMap.put(referenced, new Integer(importsCount
138
							.intValue() - 1));
139
				}
140
141
				if (importsMap.isEmpty())
142
					removeImportsMap(referencer);
143
			}
144
145
			Map exportsMap = getExportsMap(referenced);
146
147
			if (exportsMap != null) {
148
149
				Integer exportsCount = (Integer) exportsMap.get(referencer);
150
151
				if (exportsCount != null) {
152
153
					if (exportsCount.intValue() < 2) {
154
155
						exportsMap.remove(referencer);
156
157
						domain.sendNotification(new NotificationImpl(
158
							EventTypes.EXPORT, referencer, (Object) null, -1) {
159
160
							public Object getNotifier() {
161
								return referenced;
162
							}
163
						});
164
					} else
165
						exportsMap.put(referencer, new Integer(exportsCount
166
							.intValue() - 1));
167
				}
168
169
				if (exportsMap.isEmpty())
170
					removeExportsMap(referenced);
171
			}
172
		}
173
	}
174
175
	/**
176
	 * Registers references by traversing the referencer resource.
177
	 */
178
	public void registerReferences(Resource referencer) {
179
180
		List referencerContents = referencer.getContents();
181
182
		if (referencerContents == null)
183
			return;
184
185
		for (Iterator i = referencerContents.iterator(); i.hasNext();) {
186
187
			EObject referencerRoot = (EObject) i.next();
188
189
			if (referencerRoot != null) {
190
191
				domain.getObjectIndexer().registerReferences(referencerRoot,
192
					referencerRoot);
193
194
				Object[] exports = getExports(referencer).toArray();
195
196
				for (int j = 0; j < exports.length; j++) {
197
198
					Resource resource = (Resource) exports[j];
199
200
					List resourceContents = resource.getContents();
201
202
					if (resourceContents == null)
203
						continue;
204
205
					for (Iterator k = resourceContents.iterator(); k.hasNext();) {
206
207
						EObject resourceRoot = (EObject) k.next();
208
209
						if (resourceRoot != null)
210
							domain.getObjectIndexer().resolveReferences(
211
								resourceRoot, resourceRoot);
212
					}
213
				}
214
			}
215
		}
216
	}
217
218
	/**
219
	 * Cleans reference maps.
220
	 */
221
	public void deregisterReferences(final Resource referencer) {
222
223
		Object[] imports = getImports(referencer).toArray();
224
225
		for (int i = 0; i < imports.length; i++) {
226
227
			final Resource referenced = (Resource) imports[i];
228
229
			Map importsMap = getImportsMap(referencer);
230
231
			if (importsMap != null) {
232
233
				importsMap.remove(referenced);
234
235
				domain.sendNotification(new NotificationImpl(
236
					EventTypes.IMPORT, referenced, (Object) null, -1) {
237
238
					public Object getNotifier() {
239
						return referencer;
240
					}
241
				});
242
243
				if (importsMap.isEmpty())
244
					removeImportsMap(referencer);
245
			}
246
247
			Map exportsMap = getExportsMap(referenced);
248
249
			if (exportsMap != null) {
250
251
				exportsMap.remove(referencer);
252
253
				domain.sendNotification(new NotificationImpl(
254
					EventTypes.EXPORT, referencer, (Object) null, -1) {
255
256
					public Object getNotifier() {
257
						return referenced;
258
					}
259
				});
260
261
				if (exportsMap.isEmpty())
262
					removeExportsMap(referenced);
263
			}
264
		}
265
	}
266
267
	/**
268
	 * Gets the imports of a resource.
269
	 */
270
	public Set getImports(Resource referencer) {
271
272
		Map importsMap = getImportsMap(referencer);
273
274
		if (importsMap != null)
275
			return Collections.unmodifiableSet(importsMap.keySet());
276
		else
277
			return Collections.EMPTY_SET;
278
	}
279
280
	/**
281
	 * Gets the exports of a resource.
282
	 */
283
	public Set getExports(Resource referenced) {
284
285
		Map exportsMap = getExportsMap(referenced);
286
287
		if (exportsMap != null)
288
			return Collections.unmodifiableSet(exportsMap.keySet());
289
		else
290
			return Collections.EMPTY_SET;
291
	}
292
293
	/**
294
	 * Gets imports map of a given resource.
295
	 */
296
	private Map getImportsMap(Resource referencer) {
297
298
		for (int i = 0, count = referencer.eAdapters().size(); i < count; i++) {
299
300
			Adapter adapter = (Adapter) referencer.eAdapters().get(i);
301
302
			if (adapter instanceof MSLImportsAdapter)
303
				return (Map) adapter;
304
		}
305
306
		return null;
307
	}
308
309
	/**
310
	 * Creates imports map of a given resource.
311
	 */
312
	private Map createImportsMap(Resource referencer) {
313
314
		Map map = new MSLImportsAdapter();
315
316
		referencer.eAdapters().add(map);
317
318
		return map;
319
	}
320
321
	/**
322
	 * Removes imports map of a given resource.
323
	 */
324
	private Map removeImportsMap(Resource referencer) {
325
326
		for (int i = 0, count = referencer.eAdapters().size(); i < count; i++) {
327
328
			Adapter adapter = (Adapter) referencer.eAdapters().get(i);
329
330
			if (adapter instanceof MSLImportsAdapter) {
331
332
				referencer.eAdapters().remove(i);
333
334
				return (Map) adapter;
335
			}
336
		}
337
338
		return null;
339
	}
340
341
	/**
342
	 * Gets exports map of a given resource.
343
	 */
344
	private Map getExportsMap(Resource referenced) {
345
346
		for (int i = 0, count = referenced.eAdapters().size(); i < count; i++) {
347
348
			Adapter adapter = (Adapter) referenced.eAdapters().get(i);
349
350
			if (adapter instanceof MSLExportsAdapter)
351
				return (Map) adapter;
352
		}
353
354
		return null;
355
	}
356
357
	/**
358
	 * Creates exports map of a given resource.
359
	 */
360
	private Map createExportsMap(Resource referenced) {
361
362
		Map map = new MSLExportsAdapter();
363
364
		referenced.eAdapters().add(map);
365
366
		return map;
367
	}
368
369
	/**
370
	 * Removes exports map of a given resource.
371
	 */
372
	private Map removeExportsMap(Resource referenced) {
373
374
		for (int i = 0, count = referenced.eAdapters().size(); i < count; i++) {
375
376
			Adapter adapter = (Adapter) referenced.eAdapters().get(i);
377
378
			if (adapter instanceof MSLExportsAdapter) {
379
380
				referenced.eAdapters().remove(i);
381
382
				return (Map) adapter;
383
			}
384
		}
385
386
		return null;
387
	}
388
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/index/MSLReferenceAdapter.java (-66 lines)
Removed Link Here
1
/******************************************************************************
2
 * Copyright (c) 2002, 2003 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
10
 ****************************************************************************/
11
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
13
14
import java.util.HashMap;
15
16
import org.eclipse.emf.common.notify.Adapter;
17
import org.eclipse.emf.common.notify.Notification;
18
import org.eclipse.emf.common.notify.Notifier;
19
20
/**
21
 * This class defines the reference adapter that will hold the reverse map for a
22
 * given EObject.
23
 * 
24
 * @author rafikj
25
 */
26
public class MSLReferenceAdapter
27
	extends HashMap
28
	implements Adapter {
29
30
	private static final long serialVersionUID = 1989964645244552123L;
31
32
	/**
33
	 * Constructor.
34
	 */
35
	public MSLReferenceAdapter() {
36
		super(2);
37
	}
38
39
	/**
40
	 * @see org.eclipse.emf.common.notify.Adapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
41
	 */
42
	public void notifyChanged(Notification notification) {
43
		// do nothing.
44
	}
45
46
	/**
47
	 * @see org.eclipse.emf.common.notify.Adapter#getTarget()
48
	 */
49
	public Notifier getTarget() {
50
		return null;
51
	}
52
53
	/**
54
	 * @see org.eclipse.emf.common.notify.Adapter#setTarget(org.eclipse.emf.common.notify.Notifier)
55
	 */
56
	public void setTarget(Notifier newTarget) {
57
		// do nothing.
58
	}
59
60
	/**
61
	 * @see org.eclipse.emf.common.notify.Adapter#isAdapterForType(java.lang.Object)
62
	 */
63
	public boolean isAdapterForType(Object type) {
64
		return false;
65
	}
66
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/index/MSLImportsAdapter.java (-66 lines)
Removed Link Here
1
/******************************************************************************
2
 * Copyright (c) 2002, 2003 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
10
 ****************************************************************************/
11
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
13
14
import java.util.HashMap;
15
16
import org.eclipse.emf.common.notify.Adapter;
17
import org.eclipse.emf.common.notify.Notification;
18
import org.eclipse.emf.common.notify.Notifier;
19
20
/**
21
 * This class defines the reference adapter that will hold the imports for a
22
 * given resource.
23
 * 
24
 * @author rafikj
25
 */
26
public class MSLImportsAdapter
27
	extends HashMap
28
	implements Adapter {
29
30
	private static final long serialVersionUID = 7770242431763053066L;
31
32
	/**
33
	 * Constructor.
34
	 */
35
	public MSLImportsAdapter() {
36
		super(2);
37
	}
38
39
	/**
40
	 * @see org.eclipse.emf.common.notify.Adapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
41
	 */
42
	public void notifyChanged(Notification notification) {
43
		// do nothing.
44
	}
45
46
	/**
47
	 * @see org.eclipse.emf.common.notify.Adapter#getTarget()
48
	 */
49
	public Notifier getTarget() {
50
		return null;
51
	}
52
53
	/**
54
	 * @see org.eclipse.emf.common.notify.Adapter#setTarget(org.eclipse.emf.common.notify.Notifier)
55
	 */
56
	public void setTarget(Notifier newTarget) {
57
		// do nothing.
58
	}
59
60
	/**
61
	 * @see org.eclipse.emf.common.notify.Adapter#isAdapterForType(java.lang.Object)
62
	 */
63
	public boolean isAdapterForType(Object type) {
64
		return false;
65
	}
66
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/domain/MSLEditingDomain.java (-21 / +17 lines)
Lines 70-77 Link Here
70
import org.eclipse.gmf.runtime.emf.core.exceptions.MSLRuntimeException;
70
import org.eclipse.gmf.runtime.emf.core.exceptions.MSLRuntimeException;
71
import org.eclipse.gmf.runtime.emf.core.internal.commands.MSLCommandGenerator;
71
import org.eclipse.gmf.runtime.emf.core.internal.commands.MSLCommandGenerator;
72
import org.eclipse.gmf.runtime.emf.core.internal.commands.MSLUndoStack;
72
import org.eclipse.gmf.runtime.emf.core.internal.commands.MSLUndoStack;
73
import org.eclipse.gmf.runtime.emf.core.internal.index.MSLObjectIndexer;
73
import org.eclipse.gmf.runtime.emf.core.internal.index.MSLCrossReferenceAdapter;
74
import org.eclipse.gmf.runtime.emf.core.internal.index.MSLResourceIndexer;
75
import org.eclipse.gmf.runtime.emf.core.internal.l10n.EMFCoreMessages;
74
import org.eclipse.gmf.runtime.emf.core.internal.l10n.EMFCoreMessages;
76
import org.eclipse.gmf.runtime.emf.core.internal.notifications.MSLContentAdapter;
75
import org.eclipse.gmf.runtime.emf.core.internal.notifications.MSLContentAdapter;
77
import org.eclipse.gmf.runtime.emf.core.internal.notifications.MSLEventBroker;
76
import org.eclipse.gmf.runtime.emf.core.internal.notifications.MSLEventBroker;
Lines 130-138 Link Here
130
129
131
	private MSLPathmap pathmap = null;
130
	private MSLPathmap pathmap = null;
132
131
133
	private MSLObjectIndexer objectIndexer = null;
132
	private MSLCrossReferenceAdapter crossReferenceAdapter = null;
134
135
	private MSLResourceIndexer resourceIndexer = null;
136
133
137
	private static Map resourceSets = new WeakHashMap();
134
	private static Map resourceSets = new WeakHashMap();
138
135
Lines 187-198 Link Here
187
184
188
		pathmap = new MSLPathmap(this);
185
		pathmap = new MSLPathmap(this);
189
186
190
		objectIndexer = new MSLObjectIndexer(this);
187
		crossReferenceAdapter = new MSLCrossReferenceAdapter(this);
191
192
		resourceIndexer = new MSLResourceIndexer(this);
193
188
194
		ResourceSet resourceSet = getResourceSet();
189
		ResourceSet resourceSet = getResourceSet();
195
190
191
		resourceSet.eAdapters().add(crossReferenceAdapter);
192
		
196
		extendedMetaData = new MSLExtendedMetaData();
193
		extendedMetaData = new MSLExtendedMetaData();
197
194
198
		contentAdapter.listenToModifications(resourceSet);
195
		contentAdapter.listenToModifications(resourceSet);
Lines 268-284 Link Here
268
	}
265
	}
269
266
270
	/**
267
	/**
271
	 * Returns the object indexer.
268
	 * Returns the cross reference adapter.
272
	 */
269
	 */
273
	public MSLObjectIndexer getObjectIndexer() {
270
	public MSLCrossReferenceAdapter getCrossReferenceAdapter() {
274
		return objectIndexer;
271
		return crossReferenceAdapter;
275
	}
276
277
	/**
278
	 * Returns the resource indexer.
279
	 */
280
	public MSLResourceIndexer getResourceIndexer() {
281
		return resourceIndexer;
282
	}
272
	}
283
273
284
	/**
274
	/**
Lines 1672-1685 Link Here
1672
	 * @see org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain#getImports(org.eclipse.emf.ecore.resource.Resource)
1662
	 * @see org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain#getImports(org.eclipse.emf.ecore.resource.Resource)
1673
	 */
1663
	 */
1674
	public Collection getImports(Resource resource) {
1664
	public Collection getImports(Resource resource) {
1675
		return resourceIndexer.getImports(resource);
1665
		return crossReferenceAdapter.getImports(resource);
1676
	}
1666
	}
1677
1667
1678
	/**
1668
	/**
1679
	 * @see org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain#getExports(org.eclipse.emf.ecore.resource.Resource)
1669
	 * @see org.eclipse.gmf.runtime.emf.core.edit.MEditingDomain#getExports(org.eclipse.emf.ecore.resource.Resource)
1680
	 */
1670
	 */
1681
	public Collection getExports(Resource resource) {
1671
	public Collection getExports(Resource resource) {
1682
		return resourceIndexer.getExports(resource);
1672
		return crossReferenceAdapter.getExports(resource);
1683
	}
1673
	}
1684
	
1674
	
1685
	/**
1675
	/**
Lines 1789-1795 Link Here
1789
1779
1790
			if (!exports.contains(directExport)) {
1780
			if (!exports.contains(directExport)) {
1791
1781
1792
				directExports.add(directExport);
1782
				exports.add(directExport);
1793
1783
1794
				getAllExports(directExport, exports, unload);
1784
				getAllExports(directExport, exports, unload);
1795
			}
1785
			}
Lines 1830-1835 Link Here
1830
			if (currentDomain instanceof MSLEditingDomain) {
1820
			if (currentDomain instanceof MSLEditingDomain) {
1831
				// remove current content adapter
1821
				// remove current content adapter
1832
				rset.eAdapters().remove(((MSLEditingDomain) currentDomain).getContentAdapter());
1822
				rset.eAdapters().remove(((MSLEditingDomain) currentDomain).getContentAdapter());
1823
				
1824
				// remove cross reference adapter
1825
				rset.eAdapters().remove(((MSLEditingDomain) currentDomain).getCrossReferenceAdapter());
1833
			}
1826
			}
1834
			
1827
			
1835
			if (domain instanceof MSLEditingDomain) {
1828
			if (domain instanceof MSLEditingDomain) {
Lines 1838-1843 Link Here
1838
				// attach new content adapter
1831
				// attach new content adapter
1839
				rset.eAdapters().add(newDomain.getContentAdapter());
1832
				rset.eAdapters().add(newDomain.getContentAdapter());
1840
				
1833
				
1834
				// attach new cross reference adapter
1835
				rset.eAdapters().add(newDomain.getCrossReferenceAdapter());
1836
				
1841
				// for each resource that is loaded, ensure that the new domain
1837
				// for each resource that is loaded, ensure that the new domain
1842
				//   know that it has finished loading
1838
				//   know that it has finished loading
1843
				for (Iterator iter = rset.getResources().iterator(); iter.hasNext();) {
1839
				for (Iterator iter = rset.getResources().iterator(); iter.hasNext();) {
(-)src/org/eclipse/gmf/runtime/emf/core/internal/util/MSLUtil.java (-74 / +4 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2002, 2004 IBM Corporation and others.
2
 * Copyright (c) 2002-2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 44-51 Link Here
44
import org.eclipse.emf.ecore.resource.ResourceSet;
44
import org.eclipse.emf.ecore.resource.ResourceSet;
45
import org.eclipse.emf.ecore.util.EcoreUtil;
45
import org.eclipse.emf.ecore.util.EcoreUtil;
46
import org.eclipse.emf.ecore.xmi.XMLResource;
46
import org.eclipse.emf.ecore.xmi.XMLResource;
47
import org.osgi.framework.Bundle;
48
49
import org.eclipse.gmf.runtime.common.core.util.Trace;
47
import org.eclipse.gmf.runtime.common.core.util.Trace;
50
import org.eclipse.gmf.runtime.emf.core.EventTypes;
48
import org.eclipse.gmf.runtime.emf.core.EventTypes;
51
import org.eclipse.gmf.runtime.emf.core.IValidationStatus;
49
import org.eclipse.gmf.runtime.emf.core.IValidationStatus;
Lines 65-70 Link Here
65
import org.eclipse.gmf.runtime.emf.core.services.metamodel.IMetamodelSupport;
63
import org.eclipse.gmf.runtime.emf.core.services.metamodel.IMetamodelSupport;
66
import org.eclipse.gmf.runtime.emf.core.util.EObjectUtil;
64
import org.eclipse.gmf.runtime.emf.core.util.EObjectUtil;
67
import org.eclipse.gmf.runtime.emf.core.util.MetaModelUtil;
65
import org.eclipse.gmf.runtime.emf.core.util.MetaModelUtil;
66
import org.osgi.framework.Bundle;
68
67
69
import com.ibm.icu.util.StringTokenizer;
68
import com.ibm.icu.util.StringTokenizer;
70
69
Lines 154-159 Link Here
154
			eClass);
153
			eClass);
155
154
156
		domain.getContentAdapter().listenToModifications(eObject);
155
		domain.getContentAdapter().listenToModifications(eObject);
156
		
157
		eObject.eAdapters().add(domain.getCrossReferenceAdapter());
157
158
158
		if (sendEvents)
159
		if (sendEvents)
159
			sendCreateEvent(domain, eObject);
160
			sendCreateEvent(domain, eObject);
Lines 724-732 Link Here
724
							}
725
							}
725
						}
726
						}
726
727
727
						domain.getResourceIndexer()
728
							.registerReferences(resource);
729
730
						return null;
728
						return null;
731
					}
729
					}
732
				});
730
				});
Lines 735-808 Link Here
735
	}
733
	}
736
734
737
	/**
735
	/**
738
	 * Process references and update reference maps.
739
	 */
740
	public static void registerReferences(MSLEditingDomain domain,
741
			EObject eObject, EReference reference, List newObjects,
742
			List oldObjects) {
743
744
		if (reference.isContainment()) {
745
746
			if (!newObjects.isEmpty()) {
747
748
				Iterator i = newObjects.iterator();
749
750
				while (i.hasNext()) {
751
752
					EObject newObject = (EObject) i.next();
753
754
					domain.getObjectIndexer().registerReferences(eObject,
755
						newObject);
756
				}
757
			}
758
759
			if (!oldObjects.isEmpty()) {
760
761
				Iterator i = oldObjects.iterator();
762
763
				while (i.hasNext()) {
764
765
					EObject oldObject = (EObject) i.next();
766
767
					domain.getObjectIndexer().deregisterReferences(eObject,
768
						oldObject);
769
				}
770
			}
771
772
		} else {
773
774
			if (!newObjects.isEmpty()) {
775
776
				Iterator i = newObjects.iterator();
777
778
				while (i.hasNext()) {
779
780
					EObject newObject = (EObject) i.next();
781
782
					// registers reference in reverse reference map.
783
					domain.getObjectIndexer().registerReference(eObject,
784
						newObject, reference);
785
				}
786
			}
787
788
			if (!oldObjects.isEmpty()) {
789
790
				Iterator i = oldObjects.iterator();
791
792
				while (i.hasNext()) {
793
794
					EObject oldObject = (EObject) i.next();
795
796
					// deregisters reference in reverse reference
797
					// map.
798
					domain.getObjectIndexer().deregisterReference(eObject,
799
						oldObject, reference);
800
				}
801
			}
802
		}
803
	}
804
805
	/**
806
	 * Returns all of the children of the validation <code>status</code> that
736
	 * Returns all of the children of the validation <code>status</code> that
807
	 * indicate violated constraints (i.e., problems). These will be some
737
	 * indicate violated constraints (i.e., problems). These will be some
808
	 * combination of errors, warnings, and informational messages. No reports
738
	 * combination of errors, warnings, and informational messages. No reports
(-)src/org/eclipse/gmf/runtime/emf/core/util/EObjectUtil.java (-5 / +15 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
2
 * Copyright (c) 2004-2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 13-18 Link Here
13
13
14
import java.util.ArrayList;
14
import java.util.ArrayList;
15
import java.util.Collection;
15
import java.util.Collection;
16
import java.util.Collections;
16
import java.util.Iterator;
17
import java.util.Iterator;
17
import java.util.List;
18
import java.util.List;
18
import java.util.Map;
19
import java.util.Map;
Lines 30-35 Link Here
30
import org.eclipse.emf.ecore.EStructuralFeature;
31
import org.eclipse.emf.ecore.EStructuralFeature;
31
import org.eclipse.emf.ecore.EcorePackage;
32
import org.eclipse.emf.ecore.EcorePackage;
32
import org.eclipse.emf.ecore.resource.Resource;
33
import org.eclipse.emf.ecore.resource.Resource;
34
import org.eclipse.emf.ecore.resource.ResourceSet;
33
import org.eclipse.emf.ecore.util.EcoreUtil;
35
import org.eclipse.emf.ecore.util.EcoreUtil;
34
import org.eclipse.gmf.runtime.common.core.util.Trace;
36
import org.eclipse.gmf.runtime.common.core.util.Trace;
35
import org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil;
37
import org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil;
Lines 39-44 Link Here
39
import org.eclipse.gmf.runtime.emf.core.edit.MRunnable;
41
import org.eclipse.gmf.runtime.emf.core.edit.MRunnable;
40
import org.eclipse.gmf.runtime.emf.core.exceptions.MSLRuntimeException;
42
import org.eclipse.gmf.runtime.emf.core.exceptions.MSLRuntimeException;
41
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
43
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
44
import org.eclipse.gmf.runtime.emf.core.internal.index.MSLCrossReferenceAdapter;
42
import org.eclipse.gmf.runtime.emf.core.internal.index.MSLReferenceVisitor;
45
import org.eclipse.gmf.runtime.emf.core.internal.index.MSLReferenceVisitor;
43
import org.eclipse.gmf.runtime.emf.core.internal.plugin.MSLDebugOptions;
46
import org.eclipse.gmf.runtime.emf.core.internal.plugin.MSLDebugOptions;
44
import org.eclipse.gmf.runtime.emf.core.internal.plugin.MSLPlugin;
47
import org.eclipse.gmf.runtime.emf.core.internal.plugin.MSLPlugin;
Lines 563-569 Link Here
563
566
564
						for (int j = 0; j < list.length; j++) {
567
						for (int j = 0; j < list.length; j++) {
565
568
566
							Object object = (EObject) list[j];
569
							Object object = list[j];
567
570
568
							newList.add(object);
571
							newList.add(object);
569
						}
572
						}
Lines 636-641 Link Here
636
		if (domain == null)
639
		if (domain == null)
637
			domain = (MSLEditingDomain) MEditingDomain.INSTANCE;
640
			domain = (MSLEditingDomain) MEditingDomain.INSTANCE;
638
641
642
		MSLCrossReferenceAdapter crossReferenceAdapter =
643
				MSLCrossReferenceAdapter.getCrossReferenceAdapter(eObject);
644
645
		if (crossReferenceAdapter == null) {
646
			return Collections.EMPTY_LIST;
647
		}
648
639
		if ((features != null) && (features.length != 0)) {
649
		if ((features != null) && (features.length != 0)) {
640
650
641
			Collection referencers = new ArrayList();
651
			Collection referencers = new ArrayList();
Lines 644-651 Link Here
644
654
645
				EReference feature = features[i];
655
				EReference feature = features[i];
646
656
647
				Iterator j = domain.getObjectIndexer().getReferencers(eObject,
657
				Iterator j = crossReferenceAdapter.getInverseReferencers(eObject,
648
					feature).iterator();
658
						feature, null).iterator();
649
659
650
				while (j.hasNext()) {
660
				while (j.hasNext()) {
651
661
Lines 658-664 Link Here
658
			return referencers;
668
			return referencers;
659
669
660
		} else
670
		} else
661
			return domain.getObjectIndexer().getAllReferencers(eObject);
671
			return crossReferenceAdapter.getInverseReferencers(eObject, null, null);
662
	}
672
	}
663
673
664
	/**
674
	/**
(-)src/org/eclipse/gmf/runtime/emf/core/internal/resources/MResource.java (-3 / +6 lines)
Lines 1-5 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
2
 * Copyright (c) 2004-2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 76-85 Link Here
76
		}
76
		}
77
77
78
		// Override to alter the behavior of reference registration.
78
		// Override to alter the behavior of reference registration.
79
		/**
80
		 * @deprecated No longer necessary to register references. The cross
81
		 * reference adapter takes care of this. 
82
		 */
79
		public void registerReferences(MEditingDomain domain, EObject eObject,
83
		public void registerReferences(MEditingDomain domain, EObject eObject,
80
				EReference reference, List newObjects, List oldObjects) {
84
				EReference reference, List newObjects, List oldObjects) {
81
			MSLUtil.registerReferences((MSLEditingDomain) domain, eObject,
85
			// empty
82
				reference, newObjects, oldObjects);
83
		}
86
		}
84
	}
87
	}
85
}
88
}
(-)src/org/eclipse/gmf/runtime/emf/core/internal/index/MSLCrossReferenceAdapter.java (+564 lines)
Added Link Here
1
/******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
10
 ****************************************************************************/
11
12
package org.eclipse.gmf.runtime.emf.core.internal.index;
13
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Collections;
17
import java.util.HashMap;
18
import java.util.HashSet;
19
import java.util.Iterator;
20
import java.util.List;
21
import java.util.Map;
22
import java.util.Set;
23
24
import org.eclipse.emf.common.notify.Adapter;
25
import org.eclipse.emf.common.notify.Notification;
26
import org.eclipse.emf.common.notify.Notifier;
27
import org.eclipse.emf.common.notify.impl.NotificationImpl;
28
import org.eclipse.emf.common.util.TreeIterator;
29
import org.eclipse.emf.ecore.EClass;
30
import org.eclipse.emf.ecore.EObject;
31
import org.eclipse.emf.ecore.EReference;
32
import org.eclipse.emf.ecore.InternalEObject;
33
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
34
import org.eclipse.emf.ecore.resource.Resource;
35
import org.eclipse.emf.ecore.resource.ResourceSet;
36
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
37
import org.eclipse.gmf.runtime.emf.core.EventTypes;
38
import org.eclipse.gmf.runtime.emf.core.internal.domain.MSLEditingDomain;
39
40
/**
41
 * An adapter that maintains itself as an adapter for all contained objects.
42
 * It can be installed for an {@link EObject}, a {@link Resource}, or a {@link ResourceSet}.
43
 * <p>
44
 * This adapter maintain information on inverse references, resource imports, and resource
45
 * exports.
46
 * 
47
 * @author Christian Vogt (cvogt)
48
 */
49
public class MSLCrossReferenceAdapter extends ECrossReferenceAdapter {
50
51
	private MSLEditingDomain domain;
52
53
	private Map imports = new HashMap();
54
55
	private Map exports = new HashMap();
56
57
	/**
58
	 * Constructor.
59
	 * 
60
	 * @param domain a (@link MSLEditingDomain}
61
	 */
62
	public MSLCrossReferenceAdapter(MSLEditingDomain domain) {
63
		super();
64
		this.domain = domain;
65
	}
66
67
	/**
68
	 * Updates imports and exports maps.
69
	 * 
70
	 * @param notification the event notification
71
	 */
72
	public void selfAdapt(Notification notification) {
73
		super.selfAdapt(notification);
74
		Object notifier = notification.getNotifier();
75
		Object feature = notification.getFeature();
76
77
		// update import / export information when a resource
78
		// is unloaded
79
		if (notifier instanceof Resource) {
80
			if (notification.getFeatureID(Resource.class) == Resource.RESOURCE__IS_LOADED
81
					&& !notification.getNewBooleanValue()) {
82
				deregisterReferences((Resource)notifier);
83
			}
84
			return;
85
		}
86
87
		// interested in maintaining import / export information
88
		// when the notifier is an EObject and the feature is a
89
		// non-containment EReference
90
		if (!(notifier instanceof EObject)
91
				|| !(feature instanceof EReference)) {
92
			return;
93
		}
94
95
		EReference reference = (EReference)feature;
96
		if (reference.isContainment()) {
97
			return;
98
		}
99
100
		switch (notification.getEventType()) {
101
			case Notification.RESOLVE: 
102
			case Notification.SET:
103
			case Notification.UNSET: {
104
				EObject oldValue = (EObject) notification.getOldValue();
105
				if (oldValue != null) {
106
					deregisterReference(
107
							((EObject)notification.getNotifier()).eResource(),
108
							oldValue.eResource());
109
				}
110
				EObject newValue = (EObject) notification.getNewValue();
111
				if (newValue != null) {
112
					registerReference(
113
							((EObject)notification.getNotifier()).eResource(),
114
							newValue.eResource());
115
				}
116
				break;
117
			}
118
			case Notification.ADD: {
119
				EObject newValue = (EObject) notification.getNewValue();
120
				if (newValue != null) {
121
					registerReference(
122
							((EObject)notification.getNotifier()).eResource(),
123
							newValue.eResource());
124
				}
125
				break;
126
			}
127
			case Notification.ADD_MANY: {
128
				Collection newValues = (Collection) notification.getNewValue();
129
				for (Iterator i = newValues.iterator(); i.hasNext();) {
130
					EObject newValue = (EObject) i.next();
131
					registerReference(
132
							((EObject)notification.getNotifier()).eResource(),
133
							newValue.eResource());
134
				}
135
				break;
136
			}
137
			case Notification.REMOVE: {
138
				EObject oldValue = (EObject) notification.getOldValue();
139
				if (oldValue != null) {
140
					deregisterReference(
141
							((EObject)notification.getNotifier()).eResource(),
142
							oldValue.eResource());
143
				}
144
				break;
145
			}
146
			case Notification.REMOVE_MANY: {
147
				Collection oldValues = (Collection) notification.getOldValue();
148
				for (Iterator i = oldValues.iterator(); i.hasNext();) {
149
					EObject oldValue = (EObject) i.next();
150
					deregisterReference(
151
							((EObject)notification.getNotifier()).eResource(),
152
							oldValue.eResource());
153
				}
154
				break;
155
			}
156
		}
157
	}
158
	
159
	/**
160
	 * @see org.eclipse.emf.ecore.util.ECrossReferenceAdapter#setTarget(org.eclipse.emf.common.notify.Notifier)
161
	 */
162
	public void setTarget(Notifier target) {
163
		super.setTarget(target);
164
		if (target instanceof Resource) {
165
			Resource resource = (Resource)target;
166
			for (TreeIterator conents = resource.getAllContents(); conents.hasNext(); ) {
167
				EObject eObject = (EObject)conents.next();
168
				List allRefs = eObject.eClass().getEAllReferences();
169
				for (int i = 0; i < allRefs.size(); ++i) {
170
					EReference eReference = (EReference)allRefs.get(i);
171
					if (!eReference.isContainer() && !eReference.isContainment() && eObject.eIsSet(eReference)) {
172
						if (eReference.isMany()) {
173
							for (Iterator iter = ((Collection)eObject.eGet(eReference)).iterator(); iter.hasNext(); ) {
174
								registerReference(resource, ((EObject)iter.next()).eResource());
175
							}
176
						} else {
177
							registerReference(resource, ((EObject)eObject.eGet(eReference)).eResource());
178
						}
179
					}
180
				}
181
			}
182
	    }
183
	}
184
185
	/**
186
	 * @see org.eclipse.emf.ecore.util.ECrossReferenceAdapter#unsetTarget(org.eclipse.emf.common.notify.Notifier)
187
	 */
188
	public void unsetTarget(Notifier target) {
189
		super.unsetTarget(target);
190
		if (target instanceof Resource) {
191
			deregisterReferences((Resource)target);
192
	    }
193
	}
194
195
	/**
196
	 * @see org.eclipse.emf.ecore.util.ECrossReferenceAdapter#isIncluded(org.eclipse.emf.ecore.EReference)
197
	 */
198
	protected boolean isIncluded(EReference eReference) {
199
		return super.isIncluded(eReference) && eReference.isChangeable()
200
			&& !eReference.isContainer() && !eReference.isContainment();
201
	}
202
203
	/**
204
	 * @see org.eclipse.emf.ecore.util.ECrossReferenceAdapter#getInverseReferences(org.eclipse.emf.ecore.EObject)
205
	 */
206
	public Collection getInverseReferences(EObject eObject) {
207
		Collection result = new ArrayList();
208
209
		// removed the addition of eContainer from default behavior
210
		
211
		Collection nonNavigableInverseReferences = (Collection)inverseCrossReferencer.get(eObject);
212
		if (nonNavigableInverseReferences != null) {
213
			result.addAll(nonNavigableInverseReferences);
214
		}
215
		
216
		for (Iterator i = eObject.eClass().getEAllReferences().iterator(); i.hasNext(); ) {
217
			EReference eReference = (EReference)i.next();
218
			EReference eOpposite = eReference.getEOpposite();
219
			// added eReference.isChangeable() from default behavior
220
			if (eOpposite != null && eReference.isChangeable() && !eReference.isContainer() && !eReference.isContainment() && eObject.eIsSet(eReference)) {
221
				if (eReference.isMany()) {
222
					for (Iterator j = ((Collection)eObject.eGet(eReference)).iterator(); j.hasNext(); ) {
223
						InternalEObject referencingEObject = (InternalEObject)j.next();
224
						result.add(referencingEObject.eSetting(eOpposite));
225
					}
226
				} else {
227
					result.add(((InternalEObject)eObject.eGet(eReference)).eSetting(eOpposite));
228
				}
229
			}
230
		}
231
		
232
		return result;
233
	}
234
235
	/**
236
	 * Gets the imports of a resource.
237
	 * 
238
	 * @param referencer the resource to retrieve imports for
239
	 * @return a Set of resource imports
240
	 */
241
	public Set getImports(Resource referencer) {
242
243
		Map importsMap = getImportsMap(referencer);
244
245
		if (importsMap != null) {
246
			return Collections.unmodifiableSet(importsMap.keySet());
247
		} else {
248
			return Collections.EMPTY_SET;
249
		}
250
	}
251
252
	/**
253
	 * Gets the exports of a resource.
254
	 * 
255
	 * @param referenced the resource to retrieve exports for
256
	 * @return a Set of resource exports
257
	 */
258
	public Set getExports(Resource referenced) {
259
260
		Map exportsMap = getExportsMap(referenced);
261
262
		if (exportsMap != null) {
263
			return Collections.unmodifiableSet(exportsMap.keySet());
264
		} else {
265
			return Collections.EMPTY_SET;
266
		}
267
	}
268
269
	/**
270
	 * Returns the imports map of the given resource.
271
	 * 
272
	 * @param resource
273
	 * @return imports map of the given resource
274
	 */
275
	private Map getImportsMap(Resource resource) {
276
		return (Map) imports.get(resource);
277
	}
278
279
	/**
280
	 * Returns the exports map of the given resource.
281
	 * 
282
	 * @param resource
283
	 * @return exports map of the given resource
284
	 */
285
	private Map getExportsMap(Resource resource) {
286
		return (Map) exports.get(resource);
287
	}
288
289
	/**
290
	 * Registers a reference updating the imports and exports maps
291
	 * accordingly.
292
	 *
293
	 * @param referencer the referencing resource
294
	 * @param referenced the referenced resouce
295
	 */
296
	private void registerReference(final Resource referencer,
297
			final Resource referenced) {
298
299
		if ((referencer != null) && (referenced != null)
300
			&& (referencer != referenced)) {
301
302
			Map importsMap = getImportsMap(referencer);
303
304
			if (importsMap == null) {
305
				importsMap = new HashMap();
306
				imports.put(referencer, importsMap);
307
			}
308
309
			Integer importsCount = (Integer) importsMap.get(referenced);
310
311
			if (importsCount == null) {
312
313
				domain.sendNotification(new NotificationImpl(
314
					EventTypes.IMPORT, (Object) null, referenced, -1) {
315
316
					public Object getNotifier() {
317
						return referencer;
318
					}
319
				});
320
321
				importsCount = new Integer(1);
322
323
			} else {
324
				importsCount = new Integer(importsCount.intValue() + 1);
325
			}
326
327
			importsMap.put(referenced, importsCount);
328
329
			Map exportsMap = getExportsMap(referenced);
330
331
			if (exportsMap == null) {
332
				exportsMap = new HashMap();
333
				exports.put(referenced, exportsMap);
334
			}
335
336
			Integer exportsCount = (Integer) exportsMap.get(referencer);
337
338
			if (exportsCount == null) {
339
340
				domain.sendNotification(new NotificationImpl(
341
					EventTypes.EXPORT, (Object) null, referencer, -1) {
342
343
					public Object getNotifier() {
344
						return referenced;
345
					}
346
				});
347
348
				exportsCount = new Integer(1);
349
350
			} else {
351
				exportsCount = new Integer(exportsCount.intValue() + 1);
352
			}
353
354
			exportsMap.put(referencer, exportsCount);
355
		}
356
	}
357
358
	/**
359
	 * Deregisters a reference updating the imports and exports maps
360
	 * accordingly.
361
	 * 
362
	 * @param referencer the referencing resource
363
	 * @param referenced the referenced resource
364
	 */
365
	private void deregisterReference(final Resource referencer,
366
			final Resource referenced) {
367
368
		if ((referencer != null) && (referenced != null)
369
			&& (referencer != referenced)) {
370
371
			Map importsMap = getImportsMap(referencer);
372
373
			if (importsMap != null) {
374
375
				Integer importsCount = (Integer) importsMap.get(referenced);
376
377
				if (importsCount != null) {
378
379
					if (importsCount.intValue() < 2) {
380
381
						importsMap.remove(referenced);
382
383
						domain.sendNotification(new NotificationImpl(
384
							EventTypes.IMPORT, referenced, (Object) null, -1) {
385
386
							public Object getNotifier() {
387
								return referencer;
388
							}
389
						});
390
					} else {
391
						importsMap.put(referenced, new Integer(importsCount
392
							.intValue() - 1));
393
					}
394
				}
395
396
				if (importsMap.isEmpty()) {
397
					imports.remove(referencer);
398
				}
399
			}
400
401
			Map exportsMap = getExportsMap(referenced);
402
403
			if (exportsMap != null) {
404
405
				Integer exportsCount = (Integer) exportsMap.get(referencer);
406
407
				if (exportsCount != null) {
408
409
					if (exportsCount.intValue() < 2) {
410
411
						exportsMap.remove(referencer);
412
413
						domain.sendNotification(new NotificationImpl(
414
							EventTypes.EXPORT, referencer, (Object) null, -1) {
415
416
							public Object getNotifier() {
417
								return referenced;
418
							}
419
						});
420
					} else {
421
						exportsMap.put(referencer, new Integer(exportsCount
422
							.intValue() - 1));
423
					}
424
				}
425
426
				if (exportsMap.isEmpty()) {
427
					exports.remove(referenced);
428
				}
429
			}
430
		}
431
	}
432
433
	/**
434
	 * Cleans up a resource from the imports and exports maps.
435
	 * 
436
	 * @param referencer the referencing resource
437
	 */
438
	private void deregisterReferences(final Resource referencer) {
439
440
		Object[] resImports = getImports(referencer).toArray();
441
442
		for (int i = 0; i < resImports.length; i++) {
443
444
			final Resource referenced = (Resource) resImports[i];
445
446
			Map importsMap = getImportsMap(referencer);
447
448
			if (importsMap != null) {
449
450
				importsMap.remove(referenced);
451
452
				domain.sendNotification(new NotificationImpl(
453
					EventTypes.IMPORT, referenced, (Object) null, -1) {
454
455
					public Object getNotifier() {
456
						return referencer;
457
					}
458
				});
459
460
				if (importsMap.isEmpty()) {
461
					imports.remove(referencer);
462
				}
463
			}
464
465
			Map exportsMap = getExportsMap(referenced);
466
467
			if (exportsMap != null) {
468
469
				exportsMap.remove(referencer);
470
471
				domain.sendNotification(new NotificationImpl(
472
					EventTypes.EXPORT, referencer, (Object) null, -1) {
473
474
					public Object getNotifier() {
475
						return referenced;
476
					}
477
				});
478
479
				if (exportsMap.isEmpty()) {
480
					exports.remove(referenced);
481
				}
482
			}
483
		}
484
	}
485
	
486
487
	/**
488
	 * Returns a Set of EObjects that reference the given EObject.
489
	 * If an EReference is specified, the scope of the search is limited
490
	 * only to that EReference. To include all references specify a value of null.
491
	 * If an EClass type is specified, the returned Set will only include those
492
	 * referencers that match the given type. To include all types specify a value of null.
493
	 * 
494
	 * @param referenced the referenced EObject
495
	 * @param reference the reference to find referencers on, null for any reference
496
	 * @param type the type of the referencers, use null for any type
497
	 * @return a Set of referencers
498
	 */
499
	public Set getInverseReferencers(EObject referenced, EReference reference, EClass type) {
500
		return getReferencers(getInverseReferences(referenced), reference, type);
501
	}
502
503
	/**
504
	 * Returns a Set of EObjects that reference the given EObject through a uni
505
	 * directional EReferences. If an EReference is specified, the scope of the
506
	 * search is limited only to that EReference. To include all references specify
507
	 * a value of null. If an EClass type is specified, the returned Set will only
508
	 * include those referencers that match the given type. To include all types
509
	 * specify a value of null.
510
	 * 
511
	 * @param referenced the referenced EObject
512
	 * @param reference the reference to find referencers on, null for any reference
513
	 * @param type the type of the referencers, use null for any type
514
	 * @return a Set of referencers
515
	 */
516
	public Set getNonNavigableInverseReferencers(EObject referenced, EReference reference, EClass type) {
517
		return getReferencers(getNonNavigableInverseReferences(referenced), reference, type);
518
	}
519
520
	/**
521
	 * Extracts the EObjects from the EStructuralFeature.Setting references
522
	 * and returns a filtered Set based on the given reference and type.
523
	 * 
524
	 * @param references a collection of EStructuralFeature.Setting
525
	 * @param reference the reference to find referencers on, null for any reference
526
	 * @param type the type of the referencers, use null for any type
527
	 * @return a Set of referencers
528
	 */
529
	private Set getReferencers(Collection references, EReference reference, EClass type) {
530
		Set set = new HashSet();
531
		if (!references.isEmpty()) {
532
			for (Iterator iter = references.iterator(); iter.hasNext(); ) {
533
				Setting setting = (Setting) iter.next();
534
				if (reference == null || reference == setting.getEStructuralFeature()) {
535
					EObject referencer = setting.getEObject();
536
					if (referencer != null && (type == null || type.isInstance(referencer))) {
537
						set.add(referencer);
538
					}
539
				}
540
			}
541
		}
542
		return set;
543
	}
544
545
	/**
546
	 * Searches the adapter list of the given Notifier for an MSLCrossReferenceAdapter.
547
	 * If not found, returns null.
548
	 * 
549
	 * @param notifier the notifier to search
550
	 * @return MSLCrossReferenceAdapter if found, otherwise null
551
	 */
552
	public static MSLCrossReferenceAdapter getCrossReferenceAdapter(Notifier notifier) {
553
		List adapters = notifier.eAdapters();
554
		
555
		for (int i = 0, size = adapters.size(); i < size; ++i) {
556
			Adapter adapter = (Adapter)adapters.get(i);
557
			if (adapter instanceof MSLCrossReferenceAdapter) {
558
				return (MSLCrossReferenceAdapter)adapter;
559
			}
560
		}
561
		return null;
562
	}
563
564
}

Return to bug 113892