Adding Features for Crosscutting Concerns
Features are additions to the expanders which aim to add pieces of code to multiple expanders. A feature can then be enabled with some option or another condition to add logic to multiple artifacts at once.
That way, crosscutting concerns can be extracted from the expanders to provide further decoupling.
Here is an example to paint a clearer image. Let's say we want to expose a new method of the dataElement-bean:
public <F> SearchResult<CityDetails> findAllDetails(ParameterContext<F> parameter) {
...
}
This method also needs to be added to the Remote interface:
<F> SearchResult<CityDetails> findAllDetails(ParameterContext<F> parameter);
And some more to the Local, Proxy and Agent.
Creating a Feature
Create a new feature through the idea:
And give it a decent name:
This will generate:
- a
{Feature}.xml
file containing a condition, which is similar to the isApplicable of the Expander and a type, which can be custom (each insertion is different for each artifact) or uniform (each artifact has the same insertion) - a
{Feature}.md
file which contains a description of the feature - a
{Feature}Test.java
file which contains the units tests
Implementing a Feature with type custom
For each Expander that will be modified by the Feature, an ExpanderFeature should be created. The ExpanderFeature provides the mapping and templates for the inserted code.
Select the Feature you wish to extend and select new > Expander Feature:
Then select the target Expander (with the ...
button):
This will add the ExpanderFeature to {Feature}.xml
and generate:
- a
{Feature}.{Expander}Mapping.xml
file to provide additional mappings for the insertion - a
{Feature}.{Expander}.stg
file to provide a template - a
{Feature}{Expander}Test.java
file for the units tests - a
{Feature}{Expander}Test.stg
file to provide the test templates
The content of the {Feature}.{Expander}.stg
file should contain hooks with the insertions:
base() ::= <<
@hook:methods:start
public \<F\> SearchResult\<<dataelement>Details\> findAllDetails(ParameterContext\<F\> parameter) {
...
}
@hook:methods:end
>>
The @hook:methods
refers to an @anchor:methods
feature anchor in the original expander template.
You can add these feature anchors to your own Expanders to allow for them to be extended.
When expanding, the insertion will be injected into the artifact at the place of the feature anchor as follows:
// @anchor:methods:start
public <F> SearchResult<CityDetails> findAllDetails(ParameterContext<F> parameter) {
...
}
// @anchor:methods:end