1 /*******************************************************************************
2  * Copyright (c) 2009, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  ******************************************************************************/
14 package org.eclipse.e4.ui.tests.application;
15 
16 import static org.junit.Assert.assertEquals;
17 import static org.junit.Assert.assertNull;
18 import static org.junit.Assert.assertTrue;
19 
20 import javax.inject.Inject;
21 import javax.inject.Named;
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.Status;
25 import org.eclipse.core.runtime.jobs.Job;
26 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
27 import org.eclipse.e4.core.contexts.IEclipseContext;
28 import org.eclipse.e4.core.contexts.RunAndTrack;
29 import org.eclipse.e4.core.di.annotations.Execute;
30 import org.eclipse.e4.core.di.annotations.Optional;
31 import org.eclipse.e4.ui.di.UISynchronize;
32 import org.eclipse.e4.ui.internal.workbench.UIEventPublisher;
33 import org.eclipse.e4.ui.model.application.MApplication;
34 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
35 import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
36 import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
37 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
38 import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
39 import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
40 import org.eclipse.e4.ui.services.IServiceConstants;
41 import org.eclipse.e4.ui.workbench.modeling.EPartService;
42 import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
43 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
44 import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
45 import org.eclipse.emf.common.notify.Notifier;
46 import org.junit.Test;
47 
48 public class ESelectionServiceTest extends UITest {
49 
50 	@Test
testGetSelection()51 	public void testGetSelection() {
52 		MWindow window = ems.createModelElement(MWindow.class);
53 		application.getChildren().add(window);
54 		application.setSelectedElement(window);
55 
56 		MPart partA = ems.createModelElement(MPart.class);
57 		partA.setElementId("partA"); //$NON-NLS-1$
58 		window.getChildren().add(partA);
59 		window.setSelectedElement(partA);
60 
61 		MPart partB = ems.createModelElement(MPart.class);
62 		partB.setElementId("partB"); //$NON-NLS-1$
63 		window.getChildren().add(partB);
64 
65 		initialize();
66 		getEngine().createGui(window);
67 
68 		IEclipseContext contextA = partA.getContext();
69 		IEclipseContext contextB = partB.getContext();
70 		IEclipseContext windowContext = window.getContext();
71 
72 		ESelectionService serviceA = contextA.get(ESelectionService.class);
73 		ESelectionService serviceB = contextB.get(ESelectionService.class);
74 		ESelectionService windowService = windowContext.get(ESelectionService.class);
75 		EPartService partService = windowContext.get(EPartService.class);
76 
77 		Object selection1 = new Object();
78 		Object selection2 = new Object();
79 
80 		serviceA.setSelection(selection1);
81 
82 		assertEquals(selection1, windowService.getSelection());
83 		assertEquals(selection1, serviceA.getSelection());
84 		assertEquals(selection1, serviceB.getSelection());
85 
86 		serviceB.setSelection(selection2);
87 
88 		assertEquals(selection1, windowService.getSelection());
89 		assertEquals(selection1, serviceA.getSelection());
90 		assertEquals(selection1, serviceB.getSelection());
91 
92 		partService.activate(partB);
93 
94 		assertEquals(selection2, windowService.getSelection());
95 		assertEquals(selection2, serviceA.getSelection());
96 		assertEquals(selection2, serviceB.getSelection());
97 	}
98 
99 	@Test
testGetSelection_Id()100 	public void testGetSelection_Id() {
101 		MWindow window = ems.createModelElement(MWindow.class);
102 		application.getChildren().add(window);
103 		application.setSelectedElement(window);
104 
105 		MPart partA = ems.createModelElement(MPart.class);
106 		partA.setElementId("partA"); //$NON-NLS-1$
107 		window.getChildren().add(partA);
108 		window.setSelectedElement(partA);
109 
110 		MPart partB = ems.createModelElement(MPart.class);
111 		partB.setElementId("partB"); //$NON-NLS-1$
112 		window.getChildren().add(partB);
113 
114 		initialize();
115 		getEngine().createGui(window);
116 
117 		IEclipseContext contextA = partA.getContext();
118 		IEclipseContext contextB = partB.getContext();
119 		IEclipseContext windowContext = window.getContext();
120 
121 		ESelectionService serviceA = contextA.get(ESelectionService.class);
122 		ESelectionService serviceB = contextB.get(ESelectionService.class);
123 		ESelectionService windowService = windowContext.get(ESelectionService.class);
124 
125 		Object selection1 = new Object();
126 		Object selection2 = new Object();
127 
128 		serviceA.setSelection(selection1);
129 
130 		assertEquals(selection1, windowService.getSelection("partA")); //$NON-NLS-1$
131 		assertEquals(selection1, serviceA.getSelection("partA")); //$NON-NLS-1$
132 		assertEquals(selection1, serviceB.getSelection("partA")); //$NON-NLS-1$
133 		assertNull(windowService.getSelection("partB")); //$NON-NLS-1$
134 		assertNull(serviceA.getSelection("partB")); //$NON-NLS-1$
135 		assertNull(serviceB.getSelection("partB")); //$NON-NLS-1$
136 
137 		serviceB.setSelection(selection2);
138 
139 		assertEquals(selection1, windowService.getSelection("partA")); //$NON-NLS-1$
140 		assertEquals(selection1, serviceA.getSelection("partA")); //$NON-NLS-1$
141 		assertEquals(selection1, serviceB.getSelection("partA")); //$NON-NLS-1$
142 		assertEquals(selection2, windowService.getSelection("partB")); //$NON-NLS-1$
143 		assertEquals(selection2, serviceA.getSelection("partB")); //$NON-NLS-1$
144 		assertEquals(selection2, serviceB.getSelection("partB")); //$NON-NLS-1$
145 	}
146 
147 	@Test
testSelectionListener()148 	public void testSelectionListener() {
149 		MWindow window = ems.createModelElement(MWindow.class);
150 		application.getChildren().add(window);
151 		application.setSelectedElement(window);
152 
153 		MPart partA = ems.createModelElement(MPart.class);
154 		partA.setElementId("partA"); //$NON-NLS-1$
155 		window.getChildren().add(partA);
156 		window.setSelectedElement(partA);
157 
158 		MPart partB = ems.createModelElement(MPart.class);
159 		partB.setElementId("partB"); //$NON-NLS-1$
160 		window.getChildren().add(partB);
161 
162 		initialize();
163 		getEngine().createGui(window);
164 
165 		IEclipseContext contextB = partB.getContext();
166 		IEclipseContext windowContext = window.getContext();
167 
168 		ESelectionService serviceB = contextB.get(ESelectionService.class);
169 		ESelectionService windowService = windowContext.get(ESelectionService.class);
170 		EPartService partService = windowContext.get(EPartService.class);
171 
172 		Object selection = new Object();
173 
174 		SelectionListener listener = new SelectionListener();
175 		windowService.addSelectionListener(listener);
176 
177 		serviceB.setSelection(selection);
178 
179 		listener.reset();
180 		partService.activate(partB);
181 
182 		assertEquals(partB, listener.getPart());
183 		assertEquals(selection, listener.getSelection());
184 
185 		windowService.removeSelectionListener(listener);
186 
187 		listener.reset();
188 		partService.activate(partA);
189 
190 		assertNull(listener.getPart());
191 		assertNull(listener.getSelection());
192 
193 		listener.reset();
194 		partService.activate(partB);
195 
196 		assertNull(listener.getPart());
197 		assertNull(listener.getSelection());
198 	}
199 
200 	@Test
testSelectionListener2()201 	public void testSelectionListener2() {
202 		MWindow window = ems.createModelElement(MWindow.class);
203 		application.getChildren().add(window);
204 		application.setSelectedElement(window);
205 
206 		MPart partA = ems.createModelElement(MPart.class);
207 		partA.setElementId("partA"); //$NON-NLS-1$
208 		window.getChildren().add(partA);
209 		window.setSelectedElement(partA);
210 
211 		MPart partB = ems.createModelElement(MPart.class);
212 		partB.setElementId("partB"); //$NON-NLS-1$
213 		window.getChildren().add(partB);
214 
215 		initialize();
216 		getEngine().createGui(window);
217 
218 		IEclipseContext contextA = partA.getContext();
219 		IEclipseContext contextB = partB.getContext();
220 		IEclipseContext windowContext = window.getContext();
221 
222 		ESelectionService serviceA = contextA.get(ESelectionService.class);
223 		ESelectionService serviceB = contextB.get(ESelectionService.class);
224 		ESelectionService windowService = windowContext.get(ESelectionService.class);
225 		EPartService partService = windowContext.get(EPartService.class);
226 
227 		Object selectionA = new Object();
228 		Object selectionB = new Object();
229 
230 		SelectionListener listener = new SelectionListener();
231 		windowService.addSelectionListener(listener);
232 
233 		serviceA.setSelection(selectionA);
234 
235 		assertEquals(partA, listener.getPart());
236 		assertEquals(selectionA, listener.getSelection());
237 
238 		listener.reset();
239 		serviceA.setSelection(selectionA);
240 
241 		assertNull(listener.getPart());
242 		assertNull(listener.getSelection());
243 
244 		listener.reset();
245 		serviceB.setSelection(selectionB);
246 
247 		assertNull(listener.getPart());
248 		assertNull(listener.getSelection());
249 
250 		listener.reset();
251 		partService.activate(partB);
252 
253 		assertEquals(partB, listener.getPart());
254 		assertEquals(selectionB, listener.getSelection());
255 
256 		windowService.removeSelectionListener(listener);
257 
258 		listener.reset();
259 		partService.activate(partA);
260 
261 		assertNull(listener.getPart());
262 		assertNull(listener.getSelection());
263 
264 		listener.reset();
265 		partService.activate(partB);
266 
267 		assertNull(listener.getPart());
268 		assertNull(listener.getSelection());
269 	}
270 
271 	@Test
testSelectionListener3()272 	public void testSelectionListener3() {
273 		MWindow window = ems.createModelElement(MWindow.class);
274 		application.getChildren().add(window);
275 		application.setSelectedElement(window);
276 
277 		MPart partA = ems.createModelElement(MPart.class);
278 		partA.setElementId("partA"); //$NON-NLS-1$
279 		window.getChildren().add(partA);
280 		window.setSelectedElement(partA);
281 
282 		MPart partB = ems.createModelElement(MPart.class);
283 		partB.setElementId("partB"); //$NON-NLS-1$
284 		window.getChildren().add(partB);
285 
286 		initialize();
287 		getEngine().createGui(window);
288 
289 		IEclipseContext contextA = partA.getContext();
290 		IEclipseContext windowContext = window.getContext();
291 
292 		ESelectionService serviceA = contextA.get(ESelectionService.class);
293 		ESelectionService windowService = windowContext.get(ESelectionService.class);
294 		EPartService partService = windowContext.get(EPartService.class);
295 
296 		Object selectionA = new Object();
297 		Object selectionB = new Object();
298 
299 		SelectionListener listener = new SelectionListener();
300 		windowService.addSelectionListener(listener);
301 
302 		serviceA.setSelection(selectionA);
303 
304 		assertEquals(partA, listener.getPart());
305 		assertEquals(selectionA, listener.getSelection());
306 
307 		listener.reset();
308 		serviceA.setSelection(selectionA);
309 
310 		assertNull(listener.getPart());
311 		assertNull(listener.getSelection());
312 
313 		listener.reset();
314 		partService.activate(partB);
315 
316 		assertNull(listener.getPart());
317 		assertNull(listener.getSelection());
318 
319 		listener.reset();
320 		serviceA.setSelection(selectionB);
321 
322 		assertNull(listener.getPart());
323 		assertNull(listener.getSelection());
324 	}
325 
326 	@Test
testBug314538()327 	public void testBug314538() {
328 		MWindow window = ems.createModelElement(MWindow.class);
329 		application.getChildren().add(window);
330 		application.setSelectedElement(window);
331 
332 		initialize();
333 		getEngine().createGui(window);
334 
335 		IEclipseContext windowContext = window.getContext();
336 		ESelectionService windowService = windowContext.get(ESelectionService.class);
337 		EPartService partService = windowContext.get(EPartService.class);
338 
339 		SelectionListener listener = new SelectionListener();
340 		windowService.addSelectionListener(listener);
341 
342 		MPerspectiveStack perspectiveStack = ems.createModelElement(MPerspectiveStack.class);
343 		window.getChildren().add(perspectiveStack);
344 		window.setSelectedElement(perspectiveStack);
345 
346 		MPerspective perspective = ems.createModelElement(MPerspective.class);
347 		perspectiveStack.getChildren().add(perspective);
348 		perspectiveStack.setSelectedElement(perspective);
349 
350 		MPart partA = ems.createModelElement(MPart.class);
351 		partA.setElementId("partA"); //$NON-NLS-1$
352 		perspective.getChildren().add(partA);
353 		perspective.setSelectedElement(partA);
354 
355 		MPart partB = ems.createModelElement(MPart.class);
356 		partB.setElementId("partB"); //$NON-NLS-1$
357 		perspective.getChildren().add(partB);
358 
359 		IEclipseContext contextB = partB.getContext();
360 
361 		ESelectionService serviceB = contextB.get(ESelectionService.class);
362 
363 		Object selection = new Object();
364 
365 		serviceB.setSelection(selection);
366 
367 		listener.reset();
368 		partService.activate(partB);
369 
370 		assertEquals(partB, listener.getPart());
371 		assertEquals(selection, listener.getSelection());
372 
373 		windowService.removeSelectionListener(listener);
374 
375 		listener.reset();
376 		partService.activate(partA);
377 
378 		assertNull(listener.getPart());
379 		assertNull(listener.getSelection());
380 
381 		listener.reset();
382 		partService.activate(partB);
383 
384 		assertNull(listener.getPart());
385 		assertNull(listener.getSelection());
386 	}
387 
388 	@Test
testSelectionListener_Id()389 	public void testSelectionListener_Id() {
390 		MWindow window = ems.createModelElement(MWindow.class);
391 		application.getChildren().add(window);
392 		application.setSelectedElement(window);
393 
394 		MPart partA = ems.createModelElement(MPart.class);
395 		partA.setElementId("partA"); //$NON-NLS-1$
396 		window.getChildren().add(partA);
397 		window.setSelectedElement(partA);
398 
399 		MPart partB = ems.createModelElement(MPart.class);
400 		partB.setElementId("partB"); //$NON-NLS-1$
401 		window.getChildren().add(partB);
402 
403 		initialize();
404 		getEngine().createGui(window);
405 
406 		IEclipseContext contextA = partA.getContext();
407 		IEclipseContext contextB = partB.getContext();
408 		IEclipseContext windowContext = window.getContext();
409 
410 		ESelectionService serviceA = contextA.get(ESelectionService.class);
411 		ESelectionService serviceB = contextB.get(ESelectionService.class);
412 		ESelectionService windowService = windowContext.get(ESelectionService.class);
413 		EPartService partService = windowContext.get(EPartService.class);
414 
415 		Object selectionA = new Object();
416 		Object selectionB = new Object();
417 
418 		SelectionListener listener = new SelectionListener();
419 		windowService.addSelectionListener("partB", listener); //$NON-NLS-1$
420 
421 		serviceA.setSelection(selectionA);
422 
423 		assertNull(listener.getPart());
424 		assertNull(listener.getSelection());
425 
426 		listener.reset();
427 		partService.activate(partB);
428 
429 		assertNull(listener.getPart());
430 		assertNull(listener.getSelection());
431 
432 		listener.reset();
433 		serviceB.setSelection(selectionB);
434 
435 		assertEquals(partB, listener.getPart());
436 		assertEquals(selectionB, listener.getSelection());
437 
438 		listener.reset();
439 		serviceA.setSelection(selectionB);
440 
441 		assertNull(listener.getPart());
442 		assertNull(listener.getSelection());
443 
444 		listener.reset();
445 		windowService.removeSelectionListener("partB", listener); //$NON-NLS-1$
446 		serviceB.setSelection(selectionA);
447 
448 		assertNull(listener.getPart());
449 		assertNull(listener.getSelection());
450 	}
451 
452 	@Test
testSelectionListener_Id2()453 	public void testSelectionListener_Id2() {
454 		MWindow window = ems.createModelElement(MWindow.class);
455 		application.getChildren().add(window);
456 		application.setSelectedElement(window);
457 
458 		MPart partA = ems.createModelElement(MPart.class);
459 		partA.setElementId("partA"); //$NON-NLS-1$
460 		window.getChildren().add(partA);
461 		window.setSelectedElement(partA);
462 
463 		MPart partB = ems.createModelElement(MPart.class);
464 		partB.setElementId("partB"); //$NON-NLS-1$
465 		window.getChildren().add(partB);
466 
467 		initialize();
468 		getEngine().createGui(window);
469 
470 		IEclipseContext contextB = partB.getContext();
471 		IEclipseContext windowContext = window.getContext();
472 
473 		ESelectionService serviceB = contextB.get(ESelectionService.class);
474 		ESelectionService windowService = windowContext.get(ESelectionService.class);
475 		EPartService partService = windowContext.get(EPartService.class);
476 
477 		Object selectionB = new Object();
478 
479 		SelectionListener listener = new SelectionListener();
480 		windowService.addSelectionListener("partB", listener); //$NON-NLS-1$
481 
482 		partService.activate(partA);
483 
484 		assertNull(listener.getPart());
485 		assertNull(listener.getSelection());
486 
487 		listener.reset();
488 		serviceB.setSelection(selectionB);
489 
490 		assertEquals(partB, listener.getPart());
491 		assertEquals(selectionB, listener.getSelection());
492 	}
493 
494 	@Test
testSelectionListener_Id3()495 	public void testSelectionListener_Id3() {
496 		MWindow window = ems.createModelElement(MWindow.class);
497 		application.getChildren().add(window);
498 		application.setSelectedElement(window);
499 
500 		MPart partA = ems.createModelElement(MPart.class);
501 		partA.setElementId("partA"); //$NON-NLS-1$
502 		window.getChildren().add(partA);
503 		window.setSelectedElement(partA);
504 
505 		MPartStack partStack = ems.createModelElement(MPartStack.class);
506 		MPart partB = ems.createModelElement(MPart.class);
507 		partB.setElementId("partB"); //$NON-NLS-1$
508 		partStack.getChildren().add(partB);
509 		MPart partC = ems.createModelElement(MPart.class);
510 		partC.setElementId("partC"); //$NON-NLS-1$
511 		partStack.getChildren().add(partC);
512 		partStack.setSelectedElement(partB);
513 		window.getChildren().add(partStack);
514 
515 		initialize();
516 		getEngine().createGui(window);
517 
518 		IEclipseContext windowContext = window.getContext();
519 
520 		ESelectionService windowService = windowContext.get(ESelectionService.class);
521 		EPartService partService = windowContext.get(EPartService.class);
522 
523 		Object selection = new Object();
524 
525 		SelectionListener listener = new SelectionListener();
526 		windowService.addSelectionListener("partC", listener); //$NON-NLS-1$
527 
528 		partService.showPart("partC", PartState.CREATE); //$NON-NLS-1$
529 
530 		assertNull(listener.getPart());
531 		assertNull(listener.getSelection());
532 
533 		IEclipseContext contextC = partC.getContext();
534 		ESelectionService serviceC = contextC.get(ESelectionService.class);
535 
536 		listener.reset();
537 		serviceC.setSelection(selection);
538 
539 		assertEquals(partC, listener.getPart());
540 		assertEquals(selection, listener.getSelection());
541 	}
542 
543 	static class ConsumerPart {
544 		public Object input;
545 
546 		@Inject
547 		@Optional
setInput(@amedIServiceConstants.ACTIVE_SELECTION) Object current)548 		public void setInput(@Named(IServiceConstants.ACTIVE_SELECTION) Object current) {
549 			input = current;
550 		}
551 	}
552 
553 	static class ProviderPart extends ConsumerPart {
554 		private ESelectionService selectionService;
555 
556 		@Inject
setSelectionService(ESelectionService s)557 		public void setSelectionService(ESelectionService s) {
558 			selectionService = s;
559 		}
560 
setSelection(Object selection)561 		public void setSelection(Object selection) {
562 			selectionService.setSelection(selection);
563 		}
564 	}
565 
566 	static class TrackingProviderPart extends ProviderPart {
567 		public Object otherSelection;
568 
setOtherSelection(Object selection)569 		public void setOtherSelection(Object selection) {
570 			otherSelection = selection;
571 		}
572 	}
573 
574 	static class UseSelectionHandler {
575 		public Object selection;
576 
577 		@Execute
execute(@ptional @amedIServiceConstants.ACTIVE_SELECTION) Object s)578 		public void execute(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) Object s) {
579 			selection = s;
580 		}
581 	}
582 
583 	@Test
testOnePartSelection()584 	public void testOnePartSelection() throws Exception {
585 		MWindow window = ems.createModelElement(MWindow.class);
586 		application.getChildren().add(window);
587 		application.setSelectedElement(window);
588 
589 		MPart part = ems.createModelElement(MPart.class);
590 		window.getChildren().add(part);
591 		window.setSelectedElement(part);
592 
593 		initialize();
594 		getEngine().createGui(window);
595 
596 		ProviderPart p = new ProviderPart();
597 		ContextInjectionFactory.inject(p, part.getContext());
598 
599 		assertNull(p.input);
600 
601 		Object selection = new Object();
602 
603 		p.setSelection(selection);
604 		assertEquals(selection, p.input);
605 		p.setSelection(null);
606 		assertNull(p.input);
607 	}
608 
609 	@Test
testTwoPartHandlerExecute()610 	public void testTwoPartHandlerExecute() throws Exception {
611 		MWindow window = ems.createModelElement(MWindow.class);
612 		application.getChildren().add(window);
613 		application.setSelectedElement(window);
614 
615 		MPart partA = ems.createModelElement(MPart.class);
616 		window.getChildren().add(partA);
617 		MPart partB = ems.createModelElement(MPart.class);
618 		window.getChildren().add(partB);
619 		window.setSelectedElement(partA);
620 
621 		initialize();
622 		getEngine().createGui(window);
623 
624 		IEclipseContext windowContext = window.getContext();
625 
626 		IEclipseContext partContextA = partA.getContext();
627 		IEclipseContext partContextB = partB.getContext();
628 
629 		ProviderPart partOneImpl = new ProviderPart();
630 		ContextInjectionFactory.inject(partOneImpl, partContextA);
631 
632 		ConsumerPart partTwoImpl = new ConsumerPart();
633 		ContextInjectionFactory.inject(partTwoImpl, partContextB);
634 
635 		Object selection = new Object();
636 
637 		partOneImpl.setSelection(selection);
638 
639 		UseSelectionHandler handler = new UseSelectionHandler();
640 		assertNull(handler.selection);
641 
642 		ContextInjectionFactory.invoke(handler, Execute.class, applicationContext, null);
643 		assertEquals(selection, handler.selection);
644 		handler.selection = null;
645 
646 		ContextInjectionFactory.invoke(handler, Execute.class, windowContext, null);
647 		assertEquals(selection, handler.selection);
648 		handler.selection = null;
649 
650 		ContextInjectionFactory.invoke(handler, Execute.class, partContextA, null);
651 		assertEquals(selection, handler.selection);
652 		handler.selection = null;
653 
654 		ContextInjectionFactory.invoke(handler, Execute.class, partContextB, null);
655 		// assertNull(handler.selection); // incorrect: should be the window
656 		// selection
657 
658 		EPartService partService = windowContext.get(EPartService.class);
659 		partService.activate(partB);
660 
661 		ContextInjectionFactory.invoke(handler, Execute.class, applicationContext, null);
662 		// assertNull(handler.selection); // partB does not post a selection
663 		handler.selection = null;
664 
665 		ContextInjectionFactory.invoke(handler, Execute.class, windowContext, null);
666 		// assertNull(handler.selection); // partB does not post a selection
667 		handler.selection = null;
668 
669 		ContextInjectionFactory.invoke(handler, Execute.class, partContextA, null);
670 		// assertEquals(selection, handler.selection); // incorrect;
671 		// selection is at window level and active part did not change
672 		handler.selection = null;
673 
674 		ContextInjectionFactory.invoke(handler, Execute.class, partContextB, null);
675 		// assertNull(handler.selection); // incorrect; should be selection
676 	}
677 
678 	@Test
testThreePartSelection()679 	public void testThreePartSelection() throws Exception {
680 		MWindow window = ems.createModelElement(MWindow.class);
681 		application.getChildren().add(window);
682 		application.setSelectedElement(window);
683 
684 		MPart partA = ems.createModelElement(MPart.class);
685 		window.getChildren().add(partA);
686 		MPart partB = ems.createModelElement(MPart.class);
687 		window.getChildren().add(partB);
688 		MPart partC = ems.createModelElement(MPart.class);
689 		window.getChildren().add(partC);
690 		window.setSelectedElement(partA);
691 
692 		initialize();
693 		getEngine().createGui(window);
694 
695 		IEclipseContext windowContext = window.getContext();
696 		IEclipseContext partContextA = partA.getContext();
697 		IEclipseContext partContextB = partB.getContext();
698 		IEclipseContext partContextC = partC.getContext();
699 
700 		ProviderPart partOneImpl = new ProviderPart();
701 		ContextInjectionFactory.inject(partOneImpl, partContextA);
702 
703 		ConsumerPart partTwoImpl = new ConsumerPart();
704 		ContextInjectionFactory.inject(partTwoImpl, partContextB);
705 
706 		ProviderPart partThreeImpl = new ProviderPart();
707 		ContextInjectionFactory.inject(partThreeImpl, partContextC);
708 
709 		ESelectionService windowService = windowContext.get(ESelectionService.class);
710 		EPartService partService = windowContext.get(EPartService.class);
711 
712 		Object selection = new Object();
713 		Object selection2 = new Object();
714 
715 		assertNull(windowService.getSelection());
716 		assertNull(partOneImpl.input);
717 		assertNull(partTwoImpl.input);
718 		assertNull(partThreeImpl.input);
719 
720 		partOneImpl.setSelection(selection);
721 		assertEquals(selection, windowService.getSelection());
722 		assertEquals(selection, partOneImpl.input);
723 		// assertNull(partTwoImpl.input); // incorrect
724 		// assertNull(partThreeImpl.input); // incorrect
725 
726 		partThreeImpl.setSelection(selection2);
727 		assertEquals(selection, windowService.getSelection());
728 		assertEquals(selection, partOneImpl.input);
729 		// assertNull(partTwoImpl.input); // incorrect
730 		// assertEquals(selection2, partThreeImpl.input); // incorrect, it is
731 		// not active
732 
733 		partService.activate(partB);
734 		// assertNull(windowService.getSelection()); // partB does not post
735 		// a selection
736 		// assertEquals(selection, partOneImpl.input); // incorrect
737 		// assertNull(partTwoImpl.input);// partB does not post a selection
738 		// assertEquals(selection2, partThreeImpl.input); // incorrect
739 
740 		partService.activate(partC);
741 		assertEquals(selection2, windowService.getSelection());
742 		// assertEquals(selection, partOneImpl.input); // incorrect
743 		// assertNull(partTwoImpl.input); // incorrect
744 		assertEquals(selection2, partThreeImpl.input);
745 	}
746 
747 	@Test
testPartOneTracksPartThree()748 	public void testPartOneTracksPartThree() throws Exception {
749 		MWindow window = ems.createModelElement(MWindow.class);
750 		application.getChildren().add(window);
751 		application.setSelectedElement(window);
752 
753 		MPart partA = ems.createModelElement(MPart.class);
754 		window.getChildren().add(partA);
755 		MPart partB = ems.createModelElement(MPart.class);
756 		window.getChildren().add(partB);
757 		MPart partC = ems.createModelElement(MPart.class);
758 		partC.setElementId("partC");
759 		window.getChildren().add(partC);
760 		window.setSelectedElement(partA);
761 
762 		initialize();
763 		getEngine().createGui(window);
764 
765 		final IEclipseContext partContextA = partA.getContext();
766 		IEclipseContext partContextB = partB.getContext();
767 		final IEclipseContext partContextC = partC.getContext();
768 
769 		final TrackingProviderPart partOneImpl = new TrackingProviderPart();
770 		ContextInjectionFactory.inject(partOneImpl, partContextA);
771 
772 		ConsumerPart partTwoImpl = new ConsumerPart();
773 		ContextInjectionFactory.inject(partTwoImpl, partContextB);
774 
775 		ProviderPart partThreeImpl = new ProviderPart();
776 		ContextInjectionFactory.inject(partThreeImpl, partContextC);
777 
778 		Object selection = new Object();
779 		Object selection2 = new Object();
780 
781 		partOneImpl.setSelection(selection);
782 		partThreeImpl.setSelection(selection2);
783 		assertEquals(selection, partOneImpl.input);
784 		assertNull(partOneImpl.otherSelection);
785 		// assertNull(partTwoImpl.input); // incorrect
786 		// assertEquals(selection2, partThreeImpl.input); // incorrect
787 
788 		// part one tracks down part three. this could just as easily be
789 		// fronted by the mediator.addSelectionListener(*)
790 		partContextC.runAndTrack(new RunAndTrack() {
791 			@Override
792 			public boolean changed(IEclipseContext context) {
793 				ESelectionService s = partContextA.get(ESelectionService.class);
794 				partOneImpl.setOtherSelection(s.getSelection("partC"));
795 				return true;
796 			}
797 		});
798 
799 		assertEquals(selection, partOneImpl.input);
800 		assertEquals(selection2, partOneImpl.otherSelection);
801 		// assertNull(partTwoImpl.input); // incorrect
802 		// assertEquals(selection2, partThreeImpl.input); // incorrect
803 
804 		partThreeImpl.setSelection(selection);
805 		assertEquals(selection, partOneImpl.input);
806 		assertEquals(selection, partOneImpl.otherSelection);
807 		// assertNull(partTwoImpl.input); // incorrect
808 		// assertEquals(selection, partThreeImpl.input); // incorrect
809 
810 		partThreeImpl.setSelection(null);
811 		assertEquals(selection, partOneImpl.input);
812 		assertNull(partOneImpl.otherSelection);
813 		// assertNull(partTwoImpl.input); // incorrect
814 		// assertNull(partThreeImpl.input); // incorrect
815 	}
816 
817 	@Test
testPartOneTracksPartThree2()818 	public void testPartOneTracksPartThree2() throws Exception {
819 		MWindow window = ems.createModelElement(MWindow.class);
820 		application.getChildren().add(window);
821 		application.setSelectedElement(window);
822 
823 		MPart partA = ems.createModelElement(MPart.class);
824 		window.getChildren().add(partA);
825 		MPart partB = ems.createModelElement(MPart.class);
826 		window.getChildren().add(partB);
827 		MPart partC = ems.createModelElement(MPart.class);
828 		partC.setElementId("partC");
829 		window.getChildren().add(partC);
830 		window.setSelectedElement(partA);
831 
832 		initialize();
833 		getEngine().createGui(window);
834 
835 		final IEclipseContext partContextA = partA.getContext();
836 		IEclipseContext partContextB = partB.getContext();
837 		final IEclipseContext partContextC = partC.getContext();
838 
839 		final TrackingProviderPart partOneImpl = new TrackingProviderPart();
840 		ContextInjectionFactory.inject(partOneImpl, partContextA);
841 
842 		ConsumerPart partTwoImpl = new ConsumerPart();
843 		ContextInjectionFactory.inject(partTwoImpl, partContextB);
844 
845 		ProviderPart partThreeImpl = new ProviderPart();
846 		ContextInjectionFactory.inject(partThreeImpl, partContextC);
847 
848 		Object selection = new Object();
849 		Object selection2 = new Object();
850 		Object selection3 = new Object();
851 
852 		partOneImpl.setSelection(selection);
853 		partThreeImpl.setSelection(selection2);
854 		assertEquals(selection, partOneImpl.input);
855 		assertNull(partOneImpl.otherSelection);
856 		// assertNull(partTwoImpl.input); // incorrect
857 		// assertEquals(selection2, partThreeImpl.input); // incorrect
858 
859 		ESelectionService selectionService = partContextA.get(ESelectionService.class);
860 		selectionService.addSelectionListener(partC.getElementId(), (part, selection1) -> partOneImpl.setOtherSelection(selection1));
861 
862 		partThreeImpl.setSelection(selection3);
863 
864 		assertEquals(selection, partOneImpl.input);
865 		assertEquals(selection3, partOneImpl.otherSelection);
866 		// assertNull(partTwoImpl.input); // incorrect
867 		// assertEquals(selection3, partThreeImpl.input); // incorrect
868 
869 		partThreeImpl.setSelection(selection);
870 		assertEquals(selection, partOneImpl.input);
871 		assertEquals(selection, partOneImpl.otherSelection);
872 		// assertNull(partTwoImpl.input); // incorrect
873 		// assertEquals(selection, partThreeImpl.input); // incorrect
874 
875 		partThreeImpl.setSelection(null);
876 		assertEquals(selection, partOneImpl.input);
877 		assertNull(partOneImpl.otherSelection);
878 		// assertNull(partTwoImpl.input); // incorrect
879 		// assertNull(partThreeImpl.input); // incorrect
880 	}
881 
882 	static class Target {
Target(String s)883 		Target(String s) {
884 
885 		}
886 	}
887 
888 	static class InjectPart {
889 
890 		Object selection;
891 
892 		@Inject
setSelection(@ptional @amedIServiceConstants.ACTIVE_SELECTION) Target selection)893 		void setSelection(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) Target selection) {
894 			this.selection = selection;
895 		}
896 	}
897 
898 	@Test
testInjection()899 	public void testInjection() {
900 		MWindow window = ems.createModelElement(MWindow.class);
901 		application.getChildren().add(window);
902 		application.setSelectedElement(window);
903 
904 		MPart partA = ems.createModelElement(MPart.class);
905 		window.getChildren().add(partA);
906 		MPart partB = ems.createModelElement(MPart.class);
907 		window.getChildren().add(partB);
908 		window.setSelectedElement(partA);
909 
910 		initialize();
911 		getEngine().createGui(window);
912 
913 		IEclipseContext windowContext = window.getContext();
914 		IEclipseContext partContextA = partA.getContext();
915 		IEclipseContext partContextB = partB.getContext();
916 
917 		EPartService partService = windowContext.get(EPartService.class);
918 		partService.activate(partA);
919 		ESelectionService selectionServiceA = partContextA.get(ESelectionService.class);
920 		ESelectionService selectionServiceB = partContextB.get(ESelectionService.class);
921 
922 		InjectPart injectPart = ContextInjectionFactory.make(InjectPart.class, partContextA);
923 		assertNull(injectPart.selection);
924 
925 		Object o = new Target("");
926 		selectionServiceA.setSelection(o);
927 
928 		assertEquals(o, injectPart.selection);
929 
930 		partService.activate(partB);
931 		assertEquals("Part B doesn't post a selection, no change", o, injectPart.selection);
932 
933 		partService.activate(partA);
934 		assertEquals(o, injectPart.selection);
935 
936 		Object o2 = new Target("");
937 		selectionServiceB.setSelection(o2);
938 
939 		assertEquals(o, injectPart.selection);
940 
941 		partService.activate(partB);
942 		assertEquals(o2, injectPart.selection);
943 
944 		partService.activate(partA);
945 		assertEquals(o, injectPart.selection);
946 	}
947 
948 	@Test
testBug343003()949 	public void testBug343003() {
950 		MWindow window = ems.createModelElement(MWindow.class);
951 		application.getChildren().add(window);
952 		application.setSelectedElement(window);
953 
954 		MPerspectiveStack perspectiveStack = ems.createModelElement(MPerspectiveStack.class);
955 		window.getChildren().add(perspectiveStack);
956 		window.setSelectedElement(perspectiveStack);
957 
958 		MPerspective perspective = ems.createModelElement(MPerspective.class);
959 		perspectiveStack.getChildren().add(perspective);
960 		perspectiveStack.setSelectedElement(perspective);
961 
962 		MPart partA = ems.createModelElement(MPart.class);
963 		perspective.getChildren().add(partA);
964 		perspective.setSelectedElement(partA);
965 
966 		initialize();
967 		getEngine().createGui(window);
968 
969 		window.getContext().get(EPartService.class).activate(partA);
970 
971 		ESelectionService selectionServiceA = partA.getContext().get(ESelectionService.class);
972 		SelectionListener listener = new SelectionListener();
973 		selectionServiceA.addSelectionListener("partB", listener); //$NON-NLS-1$
974 
975 		MPart partB = ems.createModelElement(MPart.class);
976 		partB.setElementId("partB");
977 		window.getSharedElements().add(partB);
978 
979 		MPlaceholder placeholder = ems.createModelElement(MPlaceholder.class);
980 		placeholder.setRef(partB);
981 		partB.setCurSharedRef(placeholder);
982 		perspective.getChildren().add(placeholder);
983 
984 		Object o = new Object();
985 		ESelectionService selectionServiceB = partB.getContext().get(ESelectionService.class);
986 		selectionServiceB.setSelection(o);
987 
988 		assertEquals(partB, listener.getPart());
989 		assertEquals(o, listener.getSelection());
990 	}
991 
992 	@Test
testBug343984()993 	public void testBug343984() throws Exception {
994 		MWindow window = ems.createModelElement(MWindow.class);
995 		application.getChildren().add(window);
996 		application.setSelectedElement(window);
997 
998 		MPart part = ems.createModelElement(MPart.class);
999 		window.getChildren().add(part);
1000 		window.setSelectedElement(part);
1001 
1002 		initialize();
1003 		applicationContext.set(UISynchronize.class, new JobUISynchronizeImpl());
1004 		getEngine().createGui(window);
1005 
1006 		IEclipseContext context = part.getContext();
1007 		Bug343984Listener listener = new Bug343984Listener();
1008 		listener.context = context;
1009 		ESelectionService selectionService = context.get(ESelectionService.class);
1010 		selectionService.addSelectionListener(listener);
1011 
1012 		selectionService.setSelection(new Object());
1013 		Thread.sleep(1000);
1014 		assertTrue(listener.success);
1015 
1016 		listener.reset();
1017 		selectionService.setSelection(new Object());
1018 		Thread.sleep(1000);
1019 		assertTrue(listener.success);
1020 	}
1021 
1022 	@Test
testBug393137()1023 	public void testBug393137() {
1024 		MWindow window = ems.createModelElement(MWindow.class);
1025 		application.getChildren().add(window);
1026 		application.setSelectedElement(window);
1027 
1028 		MPart partA = ems.createModelElement(MPart.class);
1029 		window.getChildren().add(partA);
1030 		MPart partB = ems.createModelElement(MPart.class);
1031 		window.getChildren().add(partB);
1032 		window.setSelectedElement(partA);
1033 
1034 		initialize();
1035 		getEngine().createGui(window);
1036 
1037 		IEclipseContext windowContext = window.getContext();
1038 		IEclipseContext partContextB = partB.getContext();
1039 
1040 		EPartService partService = windowContext.get(EPartService.class);
1041 		partService.activate(partA);
1042 		ESelectionService selectionServiceB = partContextB.get(ESelectionService.class);
1043 
1044 		Object o = new Target("");
1045 		selectionServiceB.setSelection(o);
1046 		selectionServiceB.setPostSelection(o);
1047 
1048 		SelectionListener listener = new SelectionListener();
1049 		SelectionListener postListener = new SelectionListener();
1050 		selectionServiceB.addSelectionListener(listener);
1051 		selectionServiceB.addPostSelectionListener(postListener);
1052 		partService.activate(partB);
1053 		assertEquals(1, listener.count);
1054 		assertEquals(1, postListener.count);
1055 	}
1056 
initialize()1057 	private void initialize() {
1058 		applicationContext.set(MApplication.class, application);
1059 		applicationContext.set(UISynchronize.class, new UISynchronize() {
1060 			@Override
1061 			public void syncExec(Runnable runnable) {
1062 				runnable.run();
1063 			}
1064 
1065 			@Override
1066 			public void asyncExec(final Runnable runnable) {
1067 				runnable.run();
1068 			}
1069 		});
1070 		application.setContext(applicationContext);
1071 		final UIEventPublisher ep = new UIEventPublisher(applicationContext);
1072 		((Notifier) application).eAdapters().add(ep);
1073 		applicationContext.set(UIEventPublisher.class, ep);
1074 	}
1075 
1076 	static class SelectionListener implements ISelectionListener {
1077 
1078 		private MPart part;
1079 		private Object selection;
1080 		private int count;
1081 
reset()1082 		public void reset() {
1083 			part = null;
1084 			selection = null;
1085 			count = 0;
1086 		}
1087 
1088 		@Override
selectionChanged(MPart part, Object selection)1089 		public void selectionChanged(MPart part, Object selection) {
1090 			this.part = part;
1091 			this.selection = selection;
1092 			this.count++;
1093 		}
1094 
getPart()1095 		public MPart getPart() {
1096 			return part;
1097 		}
1098 
getSelection()1099 		public Object getSelection() {
1100 			return selection;
1101 		}
1102 
getCount()1103 		public int getCount() {
1104 			return count;
1105 		}
1106 	}
1107 
1108 	static class Bug343984Listener implements ISelectionListener {
1109 
1110 		IEclipseContext context;
1111 		int count = 0;
1112 		boolean success = false;
1113 
reset()1114 		public void reset() {
1115 			count = 0;
1116 			success = false;
1117 		}
1118 
1119 		@Override
selectionChanged(MPart part, Object selection)1120 		public void selectionChanged(MPart part, Object selection) {
1121 			if (count > 0) {
1122 				success = false;
1123 				return;
1124 			}
1125 
1126 			success = true;
1127 			count++;
1128 
1129 			context.get("a");
1130 			context.set("a", new Object());
1131 
1132 			context.get("b");
1133 			context.set("b", new Object());
1134 		}
1135 
1136 	}
1137 
1138 	static class JobUISynchronizeImpl extends UISynchronize {
1139 		@Override
syncExec(Runnable runnable)1140 		public void syncExec(Runnable runnable) {
1141 			runnable.run();
1142 		}
1143 
1144 		@Override
asyncExec(final Runnable runnable)1145 		public void asyncExec(final Runnable runnable) {
1146 			Job job = new Job("") {
1147 				@Override
1148 				protected IStatus run(IProgressMonitor monitor) {
1149 					runnable.run();
1150 					return Status.OK_STATUS;
1151 				}
1152 			};
1153 			job.setPriority(Job.INTERACTIVE);
1154 			job.schedule();
1155 		}
1156 	}
1157 }
1158