1 /*******************************************************************************
2  * Copyright (c) 2009, 2014 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  *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 431667, 440893
14  *     Thibault Le Ouay <thibaultleouay@gmail.com> - Bug 450209
15  ******************************************************************************/
16 package org.eclipse.e4.core.commands.tests;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertTrue;
22 
23 import java.util.Collections;
24 
25 import javax.inject.Named;
26 
27 import org.eclipse.core.commands.Category;
28 import org.eclipse.core.commands.IParameter;
29 import org.eclipse.core.commands.IParameterValues;
30 import org.eclipse.core.commands.ParameterValuesException;
31 import org.eclipse.core.commands.ParameterizedCommand;
32 import org.eclipse.e4.core.commands.CommandServiceAddon;
33 import org.eclipse.e4.core.commands.ECommandService;
34 import org.eclipse.e4.core.commands.EHandlerService;
35 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
36 import org.eclipse.e4.core.contexts.EclipseContextFactory;
37 import org.eclipse.e4.core.contexts.IEclipseContext;
38 import org.eclipse.e4.core.di.annotations.CanExecute;
39 import org.eclipse.e4.core.di.annotations.Execute;
40 import org.eclipse.e4.core.di.annotations.Optional;
41 import org.junit.After;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.osgi.framework.FrameworkUtil;
45 
46 public class HandlerTest {
47 
48 	private static final String ACTIVE_INFO_ID = "activeInfo";
49 	private static final String TEST_ID3 = "test.id3";
50 	private static final String TEST_ID2 = "test.id2";
51 	private static final String TEST_ID1 = "test.id1";
52 	private static final String TEST_CAT1 = "test.cat1";
53 
54 	private IEclipseContext workbenchContext;
55 
56 	@Before
setUp()57 	public void setUp() {
58 		IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(FrameworkUtil.getBundle(this.getClass()).getBundleContext());
59 		IEclipseContext globalContext = serviceContext.createChild();
60 		workbenchContext = globalContext.createChild("workbenchContext");
61 		ContextInjectionFactory.make(CommandServiceAddon.class, workbenchContext);
62 		defineCommands(workbenchContext);
63 	}
64 
65 	@After
tearDown()66 	public void tearDown() {
67 		workbenchContext.dispose();
68 	}
69 
70 	@Test
testCallHandler()71 	public void testCallHandler() throws Exception {
72 		EHandlerService hs = workbenchContext.get(EHandlerService.class);
73 		CallHandler handler = new CallHandler();
74 		hs.activateHandler(TEST_ID1, handler);
75 		assertFalse(handler.q1);
76 		assertFalse(handler.q2);
77 		ECommandService cs = workbenchContext.get(ECommandService.class);
78 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
79 		assertTrue(hs.canExecute(cmd));
80 		assertFalse(handler.q2);
81 		assertEquals(Boolean.TRUE, hs.executeHandler(cmd));
82 		assertTrue(handler.q1);
83 		assertTrue(handler.q2);
84 	}
85 
86 	@Test
testDeactivateHandler()87 	public void testDeactivateHandler() throws Exception {
88 		EHandlerService hs = workbenchContext.get(EHandlerService.class);
89 		CallHandler handler = new CallHandler();
90 		hs.activateHandler(TEST_ID1, handler);
91 		assertFalse(handler.q1);
92 		assertFalse(handler.q2);
93 		ECommandService cs = workbenchContext.get(ECommandService.class);
94 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
95 		assertTrue(hs.canExecute(cmd));
96 		assertFalse(handler.q2);
97 		hs.deactivateHandler(TEST_ID1, handler);
98 		assertNull(hs.executeHandler(cmd));
99 		assertTrue(handler.q1);
100 		assertFalse(handler.q2);
101 	}
102 
103 	@Test
testActiveHandlerExecuteWorkbench()104 	public void testActiveHandlerExecuteWorkbench() throws Exception {
105 		IEclipseContext c1 = workbenchContext.createChild("c1");
106 		c1.activate();
107 		EHandlerService h1 = c1.get(EHandlerService.class);
108 		CallHandler handler1 = new CallHandler();
109 		h1.activateHandler(TEST_ID1, handler1);
110 		ECommandService cs = c1.get(ECommandService.class);
111 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
112 		assertTrue(h1.canExecute(cmd));
113 		EHandlerService wHS = workbenchContext.get(EHandlerService.class);
114 		assertTrue(wHS.canExecute(cmd));
115 	}
116 
117 	@Test
testQueryTwoHandlers()118 	public void testQueryTwoHandlers() throws Exception {
119 		ECommandService cs = workbenchContext.get(ECommandService.class);
120 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
121 		EHandlerService wHS = workbenchContext.get(EHandlerService.class);
122 
123 		IEclipseContext c1 = workbenchContext.createChild("c1");
124 		c1.activate();
125 		EHandlerService h1 = c1.get(EHandlerService.class);
126 		CallHandler handler1 = new CallHandler();
127 		h1.activateHandler(TEST_ID1, handler1);
128 
129 		IEclipseContext c2 = workbenchContext.createChild("c2");
130 		EHandlerService h2 = c2.get(EHandlerService.class);
131 		CallHandler handler2 = new CallHandler();
132 		h2.activateHandler(TEST_ID1, handler2);
133 
134 		assertFalse(handler1.q1);
135 		assertFalse(handler2.q1);
136 		assertEquals(Boolean.TRUE, wHS.executeHandler(cmd));
137 		assertTrue(handler1.q1);
138 		assertTrue(handler1.q2);
139 		assertFalse(handler2.q1);
140 		assertFalse(handler2.q2);
141 	}
142 
143 	@Test
testExecuteTwoActiveHandlers()144 	public void testExecuteTwoActiveHandlers() throws Exception {
145 		ECommandService cs = workbenchContext.get(ECommandService.class);
146 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
147 		EHandlerService wHS = workbenchContext.get(EHandlerService.class);
148 
149 		IEclipseContext c1 = workbenchContext.createChild("c1");
150 		c1.activate();
151 		EHandlerService h1 = c1.get(EHandlerService.class);
152 		CallHandler handler1 = new CallHandler();
153 		h1.activateHandler(TEST_ID1, handler1);
154 
155 		IEclipseContext c2 = workbenchContext.createChild("c2");
156 		EHandlerService h2 = c2.get(EHandlerService.class);
157 		CallHandler handler2 = new CallHandler();
158 		h2.activateHandler(TEST_ID1, handler2);
159 
160 		assertTrue(h1.canExecute(cmd));
161 		assertTrue(handler1.q1);
162 
163 		assertFalse(handler2.q1);
164 		assertTrue(h2.canExecute(cmd));
165 		assertTrue(handler2.q1);
166 
167 		assertFalse(handler1.q2);
168 		assertFalse(handler2.q2);
169 		assertEquals(Boolean.TRUE, wHS.executeHandler(cmd));
170 		assertTrue(handler1.q2);
171 		assertFalse(handler2.q2);
172 	}
173 
174 	@Test
testSwitchActivationTwoHandlers()175 	public void testSwitchActivationTwoHandlers() throws Exception {
176 		ECommandService cs = workbenchContext.get(ECommandService.class);
177 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
178 		EHandlerService wHS = workbenchContext.get(EHandlerService.class);
179 
180 		IEclipseContext c1 = workbenchContext.createChild("c1");
181 		c1.activate();
182 		EHandlerService h1 = c1.get(EHandlerService.class);
183 		CallHandler handler1 = new CallHandler();
184 		h1.activateHandler(TEST_ID1, handler1);
185 
186 		IEclipseContext c2 = workbenchContext.createChild("c2");
187 		EHandlerService h2 = c2.get(EHandlerService.class);
188 		CallHandler handler2 = new CallHandler();
189 		h2.activateHandler(TEST_ID1, handler2);
190 
191 		assertFalse(handler1.q1);
192 		assertFalse(handler2.q1);
193 		assertEquals(Boolean.TRUE, wHS.executeHandler(cmd));
194 		assertTrue(handler1.q1);
195 		assertTrue(handler1.q2);
196 		assertFalse(handler2.q1);
197 		assertFalse(handler2.q2);
198 
199 		handler1.q1 = false;
200 		handler1.q2 = false;
201 		c2.activate();
202 		assertEquals(Boolean.TRUE, wHS.executeHandler(cmd));
203 		assertTrue(handler2.q1);
204 		assertTrue(handler2.q2);
205 		assertFalse(handler1.q1);
206 		assertFalse(handler1.q2);
207 	}
208 
209 	static class HandlerWithInfo {
210 		@CanExecute
canExecute(Info h)211 		public boolean canExecute(Info h) {
212 			return h.name.equals("Hello");
213 		}
214 
215 		@Execute
execute(Info h)216 		public Object execute(Info h) {
217 			return h.name.equals("Hello") ? h : null;
218 		}
219 	}
220 
221 	static class HandlerWithAnnotations {
222 		@CanExecute
canExecute(@amedACTIVE_INFO_ID) Info h)223 		public boolean canExecute(@Named(ACTIVE_INFO_ID) Info h) {
224 			return h.name.equals("Hello");
225 		}
226 
227 		@Execute
execute(@amedACTIVE_INFO_ID) Info h)228 		public Object execute(@Named(ACTIVE_INFO_ID) Info h) {
229 			return h.name.equals("Hello") ? h : null;
230 		}
231 	}
232 
233 	static class HandlerWithParams {
234 		@CanExecute
canExecute(@ptional @amedACTIVE_INFO_ID) String param)235 		public boolean canExecute(@Optional @Named(ACTIVE_INFO_ID) String param) {
236 			return true;
237 		}
238 
239 		@Execute
execute(@ptional @amedACTIVE_INFO_ID) String param)240 		public Object execute(@Optional @Named(ACTIVE_INFO_ID) String param) {
241 			return param;
242 		}
243 	}
244 
245 	static class Info {
246 		public String name;
247 
Info(String name)248 		public Info(String name) {
249 			this.name = name;
250 		}
251 	}
252 
253 	@Test
testMethodInfo()254 	public void testMethodInfo() throws Exception {
255 		Info helloInfo = new Info("Hello");
256 		workbenchContext.set(Info.class, helloInfo);
257 		ECommandService cs = workbenchContext.get(ECommandService.class);
258 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
259 		EHandlerService wHS = workbenchContext.get(EHandlerService.class);
260 		HandlerWithInfo handler = new HandlerWithInfo();
261 		wHS.activateHandler(TEST_ID1, handler);
262 
263 		assertEquals(helloInfo, wHS.executeHandler(cmd));
264 	}
265 
266 	@Test
testMethodWithAnnocation()267 	public void testMethodWithAnnocation() throws Exception {
268 		Info helloInfo = new Info("Hello");
269 		ECommandService cs = workbenchContext.get(ECommandService.class);
270 		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
271 		EHandlerService wHS = workbenchContext.get(EHandlerService.class);
272 		HandlerWithAnnotations handler = new HandlerWithAnnotations();
273 		wHS.activateHandler(TEST_ID1, handler);
274 
275 		workbenchContext.set(Info.class, helloInfo);
276 		assertNull(wHS.executeHandler(cmd));
277 
278 		workbenchContext.remove(Info.class);
279 		assertNull(wHS.executeHandler(cmd));
280 
281 		workbenchContext.set(ACTIVE_INFO_ID, helloInfo);
282 		assertEquals(helloInfo, wHS.executeHandler(cmd));
283 
284 		workbenchContext.remove(ACTIVE_INFO_ID);
285 		assertNull(wHS.executeHandler(cmd));
286 	}
287 
288 	@Test
testBug314847()289 	public void testBug314847() {
290 		ECommandService cs = workbenchContext.get(ECommandService.class);
291 		EHandlerService wHS = workbenchContext.get(EHandlerService.class);
292 
293 		ParameterizedCommand nonparameterizedCmd = cs.createCommand(TEST_ID3, null);
294 		ParameterizedCommand parameterizedCmd = cs.createCommand(TEST_ID3,
295 				Collections.singletonMap(ACTIVE_INFO_ID, (Object) "param"));
296 
297 		HandlerWithParams handler = new HandlerWithParams();
298 		wHS.activateHandler(TEST_ID3, handler);
299 
300 		assertEquals(true, wHS.canExecute(parameterizedCmd));
301 
302 		assertEquals("param", wHS.executeHandler(parameterizedCmd));
303 
304 		assertEquals(true, wHS.canExecute(nonparameterizedCmd));
305 
306 		assertEquals(null, wHS.executeHandler(nonparameterizedCmd));
307 	}
308 
defineCommands(IEclipseContext context)309 	private void defineCommands(IEclipseContext context) {
310 		ECommandService cs = workbenchContext.get(ECommandService.class);
311 		Category category = cs.defineCategory(TEST_CAT1, "CAT1", null);
312 		cs.defineCommand(TEST_ID1, "ID1", null, category, null);
313 		cs.defineCommand(TEST_ID2, "ID2", null, category, null);
314 		cs.defineCommand(TEST_ID3, "ID3", null, category, new IParameter[] { new IParameter() {
315 
316 			@Override
317 			public boolean isOptional() {
318 				return true;
319 			}
320 
321 			@Override
322 			public IParameterValues getValues() throws ParameterValuesException {
323 				return () -> Collections.emptyMap();
324 			}
325 
326 			@Override
327 			public String getName() {
328 				return ACTIVE_INFO_ID;
329 			}
330 
331 			@Override
332 			public String getId() {
333 				return ACTIVE_INFO_ID;
334 			}
335 		} });
336 	}
337 
338 	static class CallHandler {
339 		public boolean q1;
340 		public boolean q2;
341 
342 		@CanExecute
canExecute()343 		public boolean canExecute() {
344 			q1 = true;
345 			return true;
346 		}
347 
348 		@Execute
execute()349 		public Object execute() {
350 			q2 = true;
351 			if (q1) {
352 				return Boolean.TRUE;
353 			}
354 			return Boolean.FALSE;
355 		}
356 	}
357 }
358