Template syntax
General Structure and Interpretation rules
An Active Code Template definition consists of a <template> XML element, which in turn contains a <body> element, forming the body of the template (the text and markup elements), and one or more <define> elements, representing named parts of a body (more on <define> element below).
Alternatively, the <template> element can contain a <j-code> element, containing arbitrary J language code.
In the first case, the body of the template, together with defines referenced from the body, is compiled into J code, which is then interpreted to add the resulting text to the predefined string variable res.
In the second case, it is assumed that the J code provided by the template author in the <j-code> section is ready for execution, and the results are concatenated to the same string variable res.
The <body> element can contain any arbitrary text, with markup elements of the kinds described below.
The text nodes are copied to the resulting text string almost as is, with the following exceptions:
· ASCII TAB symbols are removed (to inject an ASCII TAB into resulting text, the <tab/> element described below is used).
· ASCII CR & LF symbols are removed (the <newline/> or <br/> elements described below are used instead).
· All other characters, including spaces, are copied as is.
The markup elements inside <body> elements are interpreted according to their semantics (see the description for each element). Typically, an element is either replaced by a string that is dynamically generated using data extracted from the UML model and/or the environment, or controls the interpretation of its adjacent or contained elements (both text nodes and other markup elements).
For example, the <foreach> element controls repetitious interpretation of the text/markup nodes it contains, according to the specified loop conditions.
The following is a short example of a template with a body, containing text and ACT markup.
<template
id=”ClassDef”>
<body>
class <?subst
this.makeCxxName()?><br/>
{
<indent><br/>
<foreach
expr=”this.PartAttribute”>
<include tpl=”AttrDef”/>
</foreach>
</indent><br/>
}
</body>
<define id=”name”>
<?subst this.makeCxxName()?>
</define>
</template>
As previously discussed, the <template> element is the "root" element of a template definition. It contains the following attributes:
· id – contains a string identifier of the template, which should be unique within a template library (can be overridden in a different library) and which is used when referencing the template from other templates, product definition files, and so on.
<define> elements and their use
A <define> element is very similar to the <body> element described above in that it can contain any arbitrary text and markup that is allowed in the <body> element. However, a template can contain more than one named <define> element, and the content of a <define> element is not automatically included in the resulting text, unless it is referenced in the <body> in the form of $define-id.
If a define is referenced in the body, the respective J code is injected into the J code generated for the body, in the respective position. Thus, when interpreting the template, the resulting text of the define element is combined into the resulting text of the template body.
The following example is a fragment of the template used in the previous example, utilizing the define element to achieve the same effect, but in a more readable form.
Note: The readability issue is important as long as the ACT templates are designed directly in the form of XML documents. However, the syntax of the ACT templates was designed to be easily representable in much more readable form using an advanced GUI. For example, most of the markup like <br/>,<indent> and so on can be represented by graphical symbols, while the <includes> of other templates can be represented as "hyperlinks" and the <defines> can be represented as expandable text regions, …. This can dramatically improve readability and clarity, allowing instant understanding of what kind of resulting text is produced by a template.
<template id=”ClassDef”>
<body>
class
$name<br/>
{
…
</body>
<define
id=”name”>
<?subst
this.makeCxxName()?>
</define>
</template>
The use of defines helps keep the template body clear and readable, by hiding complex template expressions behind self-describing symbols.
The <subst> element is replaced by the results of the interpretation of the enclosed J expression of string type. It supports two alternative syntaxes:
· arbitrary XML element, with attribute expr containing a J expression. For example: <subst expr=”this.Name”/>.
· freeform XML element, with a J expression as contents. For example: <?subst this.name?>.
The <tab> element is replaced by the ASCII TAB character. Typically used in the following compact form: <tab/>).
The <newline> element is replaced by the ASCII CR [+LF] sequence (depending on the platform). Typically used in the following compact form: <newline/>.
The <br> element is replaced by the ASCII CR [+LF] sequence (depending on the platform), plus a number of whitespace indentation characters (typically ASCII TAB symbols). The number of indentation symbols is determined by current indentation level, which is controlled by <indent>, <doindent> and <unindent> elements, described below.
<indent>, <doindent> and <unindent> elements
The <indent> and <unindent> elements increase and decrease the current indentation level respectively, without adding anything to the result string.
Two different usage styles are supported:
· compact style, for example, <indent/> or <unindent/>. Replaced by empty string and increasing/descreasing the indent level.
· expanded style, for example, <indent> some template code block </indent>. This changes the indentation level at the beginning, interprets the enclosed template block, then restores the indentation level to its previous form.
The <doindent> element is replaced with a number of indentation symbols, according to the current indentation level. The <newline/><doindent/> sequence is equivalent to <br/>.
The <if> element is used to control whether or not the resulting text for the enclosed template block should be added to the result, depending on the J expression of Boolean type. The element contains the following attributes:
· expr - J expression of Boolean type, used as a condition to include or not include the enclosed block in the resulting text.
Example: <if expr=”this.IsClass”>static </if>
The <foreach> element is used to repeatedly add the resulting text for the enclosed template block to the result, once for each object in a set, determined by a given J expression. The element contains the following attributes:
· expr – J expression of Set type, which returns a set of J objects, over which to iterate.
Besides other markup elements allowed in arbitrary template blocks, a few more specialized elements are allowed inside <foreach> elements:
· <header>: The contents of this element are inserted only once before any iterated contents are added, and only if the number of iterations is greater than zero.
· <footer>. The contents of this element are inserted only once after all iterated contents are added, and only if the number of iterations is greater than zero.
· <separator>. The contents of this element are inserted between the iterated blocks, but not before or after them (for example, a comma "," separating parameters in a function parameter list).
Example:
<foreach expr=”this.PartAttribute”>
<header>Attributes:<br/></header>
<footer>;</footer>
<separator>, </separator>
<?subst this.Name?>
</foreach>
For a class with two attributes, attr1 and attr2, this should produce:
Attributes: attr1, attr2;
The <include> element is replaced with the resulting text of another template, identified by the "tpl" attribute of the element.
Example:
<include
tpl=”CxxModifiableNoteContent”/>
The <with> element does not add anything to the resulting text, but rather changes the J "context" to the J object returned by an expression, contained in the attribute "expr".
Example:
<with expr=”this.getParent()”>
<?subst this.Name?>
</with>
is compiled into:
this.getParent()
{
res.strcat(this.Name);
}
The <inject> element is used to inject arbitrary J code (contained in the <j-code> element inside the <inject> element) into the compiled template code.
Example:
<with expr=”this.getParent()”>
<inject><j-code>ModelElement
x;</jcode></inject>
</with>
Is compiled into:
this.getParent()
{
ModelElement
x;
}