Skip to content

English documentation

Álex Cortiñas edited this page Sep 15, 2022 · 1 revision

First steps

The first thing to do is to follow the steps in Install from github of the readme. Apart from the installation instructions, it is also explained how to launch the tests (in some Windows installations the tests fail due to the line breaks of the templates), and also the details about one of the examples of the project, a web calculator product line (examples/MyCalculator). The same example is used in this documet to see the default folder and file structure:

  • code folder: annotated source code.
  • config.json: configuration file to define the delimiters used for the annotations depending on the file extension of the annotated file. You can also set some folders to be ignored by the engine.
  • extra.js: this optional file can be used to define JavaScript functions and variables that can be used within the annotations.
  • model.[json|xml]: the feature model. It supports Feature IDE XMl format, but also an internal JSON format used by the tool.
  • product.json: the specification or configuration for the product we want to generate. It includes the feature selection and a JSON object that can be used and referenced withing the annotations.

In addition to the examples, the implemented tests can be checked to understand how the engine works regarding the variability management or any other detail, as there are tests for all the functionalities (TDD is followed in its development).

Annotation types

The derivation engine supports three types of annotations. As an example, let us assume we have a product with features A, B and C (we assume it is a correct feature selection), and some data specification, as seen next:

{
  features: [ A, B, C ],
  data: {
    forms: [ { name: "formA" }, { name: "formB" }, { name: "formC" } ]
    applicationTitle: "Example application"
  }
}

Basic annotation

Basic annotations are mostly used to delimit the source code for each feature, but they may include any kind of JavaScript code. An example of a basic annotation is shown below. Let us assume the code shown is java, and the delimiters used are /*% %*/.

/*% if (feature.A) { %*/
code to include in the product if feature A is selected
/*% } 
    if (feature.X) { %*/
code to include in the product if feature X is selected
/*% } %*/

The resulting code with the example product specification would be:

code to include in the product if feature A is selected

Interpolation annotation

These annotations are used to include values from the product specification straight to the generated source code. An example is shown below as HTML code, using the delimiters <!--% %-->. As we can see, the interpolation annotations are indicated with the character = after the starting annotation delmiter:

<head>
  <title><!--%= data.applicationTitle %--></title>
</head>

The resulting code with the example product specification would be:

<head>
  <title>Example application</title>
</head>

File generation annotations

File generation annotations are used to generate new files from the product specification. They are necessary, for example, to create the Java classes of each entity based on a data model. In the example shown below, we will create a file for each form defined in the product specification, in the property data.forms. They work in a different way from the rest, as they always have to be at the beginning of the annotated file, and they have to contain the implementation of a function that receives the specification (data and feature), and returns an array of objects with two properties: fileName and context. We indicate such annotations with the @ character following the starting annotation delimiter. The next example is also in HTML language (delimiters are <!--% %-->).

<!--%@ return data.forms.map(function(form) {
    return {
        fileName: normalize(form.name) + '.html',
        context: form 
    };
})%-->
<head>
  <title><!--%= context.name %--></title>
</head>

The result would be three files, one for each element in the data.forms property, which is an array, with names formA.html, formB.html and formC.html. The name of the file uses the normalize function which is explained further down in this document. For each generated file, the content can be annotated and has access to a context variable defined in the file generation annotation. In this case, the context variable for each file is each element belonging the array data.forms. In the rest of the annotated file the developer can use annotations of any type (you can even chain file generation annotations). The result of the above template with the example product specification would be the following three files:

  • formA.html:
<head>
  <title>formA</title>
</head>
  • formB.html:
<head>
  <title>formB</title>
</head>
  • formC.html:
<head>
  <title>formC</title>
</head>

Extra information

normalize function

The normalize(str, upper) function is defined in the engine code itself. It can be used in any annotation. It serves to normalize texts, removing spaces and strange characters from a string. The first parameter is the string itself (or the variable with the string). The second parameter is used to indicate whether the result should start with an upper or lower case letter.

normalize('Alex Cortiñas');         // alexCortinas
normalize('Alex Cortiñas', true);   // AlexCortinas
normalize('Alex _ Cortiñas', true); // AlexCortinas
Clone this wiki locally