Features for Cross Cutting Concerns
Features are additions to the expandersExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact. which aim to add pieces of code to multiple expandersExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact.. A feature can then be enabled with some option or another condition to add logic to multiple artifactsArtifactA build or deployment result, such as a Docker container image or Java archive, produced by a software project. at once.
That way, crosscutting concerns can be extracted from the expandersExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact. 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.
Feature vs. Expander Feature
First, a Feature is defined. Then, for each ExpanderExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact. that will be modified by the Feature, an ExpanderFeature should be created.
Feature Files
- a
{Feature}.xmlfile containing a condition, which is similar to the isApplicable of the ExpanderExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact. and a type, which can be custom (each insertion is different for each artifactArtifactA build or deployment result, such as a Docker container image or Java archive, produced by a software project.) or uniform (each artifactArtifactA build or deployment result, such as a Docker container image or Java archive, produced by a software project. has the same insertion) - a
{Feature}.mdfile which contains a description of the feature - a
{Feature}Test.javafile which contains the units tests
Expander Feature Files
The ExpanderFeature provides the mapping and templates for the inserted code.
- a
{Feature}.{Expander}Mapping.xmlfile to provide additional mappings for the insertion - a
{Feature}.{Expander}.stgfile to provide a template - a
{Feature}{Expander}Test.javafile for the units tests - a
{Feature}{Expander}Test.stgfile 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 anchorAnchorA marker within generated source code reserved for adding custom logic during re-expansion. in the original expanderExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact. template.
You can add these feature anchorsAnchorA marker within generated source code reserved for adding custom logic during re-expansion. to your own ExpandersExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact. to allow for them to be extended.
When expanding, the insertion will be injected into the artifactArtifactA build or deployment result, such as a Docker container image or Java archive, produced by a software project. at the place of the feature anchorAnchorA marker within generated source code reserved for adding custom logic during re-expansion. as follows:
// @anchor:methods:start
public <F> SearchResult<CityDetails> findAllDetails(ParameterContext<F> parameter) {
...
}
// @anchor:methods:end
A more elaborate guide on how to set up features using the intelliJ plugin can be found in the developer hub: Features