Executing commands programmatically

Executing commands (e.g. from a SWT listener) is a pretty handy thing. You don’t have to care about, where the handler is registered, you simply execute the command via the ICommandService, the delegation is provided by the framework.


...
ICommandService commandService = (ICommandService)getViewSite().getService(ICommandService.class);
try {
commandService.getCommand("com.foo.the.command").executeWithChecks(new ExecutionEvent());
}
catch (Exception exception) {
logger.error(exception.getMessage(), exception);
}
...

There is just one thing about the snippet above that is bad: The way the ExecutionEvent is created. Using the default constructor results in hard time for a handler, as the HandlerUtil class cannot be used due to the missing context information. A better way is to pass on some parameters to the ExecutionEvent to be created. The most important one is the last parameter, the application context object. It can be obtained via the IEvaluationService.


...
ICommandService commandService = (ICommandService)getViewSite().getService(ICommandService.class);
IEvaluationService evaluationService = (IEvaluationService)getViewSite().getService(IEvaluationService.class);
try {
Command theCommand = commandService.getCommand("com.foo.the.command");
theCommand.executeWithChecks(new ExecutionEvent(theCommand, new HashMap(), control, evaluationService.getCurrentState()));
}
catch (Exception exception) {
logger.error(exception.getMessage(), exception);
}
...

This command invokation can be processed by any handler using the HandlerUtil class.

Tuning Xpand Templates

Our current project is model driven, using MWE, Xpand & Xtend. Right at the beginning, our templates were really fast and the round trip time was fairly acceptable. By now, our model contains quite a lot of elements and a generator run takes far more time than before. So I had a look what can be done to tune our templates a little.
When studying the Xpand docs, I found something interesting: The cached keyword for Xtend functions. A return value of cached functions is stored for the given parameter(s) and this turns out to be very useful. We have a lot of typeSelect() operations to do something on specific model types, for example on all our Services, in both Xpand templates and Xtend functions.
... eRootContainer.eAllContents.typeSelect(Service) ...
This statement results in scanning the whole model for elements of the desired type. Usually you expect the result to be the same each time (at least you should hope). This piece of code is a perfect example for a cached Xtend function that replaces all occurrences of the upper statement.

cached List[Service] services(EObject eRootContainer):
eRootContainer.eAllContents.typeSelect(Service);

So the model is scanned only once, as the eRootContainer is always the same object. This saves a lot of time. If you provide such a function for each type you need, your templates will be processed much faster. I know, caching is a little dangerous, but well dosed it can be quite useful and reduces the required time for a round trip.