Features

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:

Creating a Feature

And give it a decent name:

Feature Form

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} 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:

Creating an ExpanderFeature

Then select the target Expander (with the ... button):

ExpanderFeature form

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

References