Repository navigation
handlebarshelpers
The following provides documentation on the helpers that are provided with the uml4net.HandleBars project. A helper adds logic to a Handlebars.Net template: it answers a question about a model element, returns a collection to iterate over, or writes text.
This page covers the helpers that can be used in any template. The helpers that write code that is specific to uml4net itself, such as its XMI readers and writers, are documented in Generating uml4net.
Each group of helpers is registered with an extension method on IHandlebars. Register the groups that a template uses before the template is compiled.
var handlebars = Handlebars.Create();
HandlebarsHelpers.Register(handlebars);
handlebars.RegisterStringHelper();
handlebars.RegisterClassHelper();
handlebars.RegisterPropertyHelper();
HandlebarsHelpers.Register comes from the Handlebars.Net.Helpers package. The generators of uml4net call it, and it determines how the name of a helper can be written in a template, see the leading #.
| Group | Registration method | Helpers | Works on |
|---|---|---|---|
| Boolean | RegisterBooleanHelper |
1 | bool |
| Class | RegisterClassHelper |
15 | IClass |
| Classifier | RegisterClassifierHelper |
1 | IClassifier |
| Documentation | RegisterDocumentationHelper |
3 |
IElement, IOperation
|
| Enum | RegisterEnumHelper |
1 | any C# enum value |
| IEnumerable | RegisterEnumerableHelper |
1 | any collection |
| NamedElement | RegisterNamedElementHelper |
1 | INamedElement |
| Parameter | RegisterParameterHelper |
1 | IParameter |
| Property | RegisterPropertyHelper |
29 | IProperty |
| String | RegisterStringHelper |
3 | string |
| TypeName | RegisterTypeNameHelper |
1 | IProperty |
| ValueSpecification | RegisterValueSpecificationHelper |
1 | IValueSpecification |
RegisterClassHelper and RegisterPropertyHelper also register the uml4net specific helpers of their group. RegisterDecoratorHelper, RegisterGeneralizationHelper and RegisterOperationHelper only register uml4net specific helpers, see Generating uml4net.
The Input of a helper states where it takes its value from. This matters, a helper that is given its value in the wrong way throws an exception or returns the wrong result.
Argument: the helper works on the value that follows its name.
{{ String.LowerCaseFirstLetter class.Name }}
Context: the helper works on the current context of the template, which is this, or the current item inside an {{#each}} block. The templates of uml4net write the element after the name of the helper for readability, as in the example below. The helper does not read that argument, so make sure that the current context is the element that is meant.
{{ #each (Class.QueryAllProperties this) as | property | }}
{{ #Documentation property }}
{{ /each }}
Block: the helper wraps a part of the template and renders it when a condition is met.
{{#Property.IsEnumerable property}}
// only rendered for a property with an upper bound larger than 1
{{/Property.IsEnumerable}}
A helper that returns a value, a bool or a collection, is used as a sub-expression between parentheses inside {{#if}}, {{#unless}} or {{#each}}:
{{#if (Property.QueryIsEnum property)}} ... {{/if}}
{{#each (Class.QueryAllOperations this) as | operation |}} ... {{/each}}
The name of a helper can be written with a leading #, as in {{ #RawDocumentation property }}, or without it, as in {{Property.WriteTypeName property}}. Both forms are used in the templates of uml4net.
The form with the # always works. The form without the # only works when HandlebarsHelpers.Register(handlebars) has been called. Without that call, a name that contains a . and that is written without the # is read as a path into the model instead of as a helper: nothing is written, and a sub-expression such as (Property.QueryIsEnum property) fails to compile with the message Sub-expression does not contain a converted MethodCall expression.
It is recommended to always write the leading
#in front of a helper of uml4net. That form works in every setup, while a helper that is written without it can silently write nothing.
| Summary | writes the value of a Boolean to lower case |
| Writes | string representation of a boolean value in lower case |
| Input | Argument |
| Parameters | |
| bool | Boolean value to convert |
{{ Boolean.ToLowerCase True }}
{{ Boolean.ToLowerCase False }}
true
false
The following helpers return a collection and are used in an {{#each}} block. The input of each of them is the Context, which is to be an IClass; an ArgumentException is thrown when it is not. "All properties" are the properties that the class implements directly, through its superclasses, or through the interfaces that the class or its superclasses realize. The results are ordered by name unless stated otherwise.
| Helper | Returns |
|---|---|
Class.QueryOwnedAttributeOrdered |
the owned attributes of the class itself |
Class.QueryAllProperties |
all properties |
Class.QueryAllContainedProperties |
all properties that are a containment (composite) |
Class.QueryAllContainedNonDerivedProperties |
all containment properties that are not derived |
Class.QueryAllContainedNonDerivedNonRedefinedProperties |
all containment properties that are not derived and that are not redefined by another property in the result |
Class.QueryAllNonDerivedProperties |
all properties that are not derived |
Class.QueryAllNonDerivedNonReadOnlyProperties |
all properties that are not derived, not a derived union and not read-only |
Class.QueryAllNonDerivedNonReadOnlyPropertiesInCanonicalOrder |
the same properties as Class.QueryAllNonDerivedNonReadOnlyProperties, in the order of Canonical XMI (XMI 2.5.1 Annex B.5.2) instead of ordered by name |
Class.QueryAllNonDerivedNonReadOnlyNonContainedReferenceEnumerableProperties |
all properties that are not derived, not a derived union, not read-only and not a containment, that are a reference type and that have an upper bound larger than 1 |
Class.QueryAllNonDerivedNonReadOnlyNonContainedNonRedefinedReferenceEnumerableProperties |
the same properties as the previous helper, without those that are redefined by another property in the result |
Class.QueryAllSpecializations |
the classes that are an immediate subclass of the class |
Class.QueryAllConstraints |
the constraints of the class and of its generalizations |
Class.QueryAllOperations |
the operations of the class, of its generalizations and of the interfaces that are realized. Not ordered by name |
For the Activity class of the UML 2.5.1 model:
{{#each (#Class.QueryOwnedAttributeOrdered this) as | property |}}{{ property.Name }};{{/each}}
edge;group;isReadOnly;isSingleExecution;node;partition;structuredNode;variable;
| Summary | renders the block for a class that has an inheritance diagram |
| Writes | the block, in which this is the diagram of the class. Nothing is written when the dictionary has no diagram for the class, or when the arguments are missing or are of another type |
| Input | Block, 2 arguments |
| Parameters | |
| class | the IClass for which the diagram is rendered |
| diagrams | an IDictionary<string, string> that holds the diagram, such as an SVG, by the XmiId of the class |
{{#Class.RenderInheritanceDiagram class diagrams}}<div>{{{this}}}</div>{{/Class.RenderInheritanceDiagram}}
When diagrams holds <svg>test-diagram</svg> for the class:
<div><svg>test-diagram</svg></div>
Renders the block for a class that has an association diagram. The parameters and the behavior are the same as those of Class.RenderInheritanceDiagram, the dictionary that is passed holds the association diagrams.
{{#Class.RenderAssociationDiagram class @root.ClassAssociationDiagrams}}
{{{this}}}
{{/Class.RenderAssociationDiagram}}
| Summary | queries the classifiers that contain the classifier |
| Returns | the IClassifiers that have an owned property that is a composite of the classifier, ordered by name |
| Input | Context, an IClassifier. An ArgumentException is thrown when it is not |
{{#each (Classifier.QueryContainers this) as | container |}}{{ container.Name }};{{/each}}
| Summary | writes the documentation of an element as a C# XML documentation summary |
| Writes | a /// <summary> block with one /// line for each line of documentation, followed by a new line |
| Input | Context, an IElement. An ArgumentException is thrown when it is not |
For a class with an owned comment that has the body Short description.:
{{ #Documentation this }}
/// <summary>
/// Short description.
/// </summary>
| Summary | writes the documentation of an element as plain text |
| Writes | the documentation on a single line, stripped from HTML tags; the owned comments are separated by a space. No Documentation Provided is written when the element has no documentation |
| Input | Context, an IElement. An ArgumentException is thrown when it is not |
{{ #RawDocumentation this }}
Short description.
| Summary | writes the documentation of the parameters of an operation as C# XML documentation |
| Writes | a /// <param name="..."> block for each parameter that is not the return parameter, and a /// <returns> block when the return parameter has a type. The name of the parameter is written with a lower case first letter. A parameter without documentation gets the text No documentation provided, a return parameter without documentation gets a reference to its type |
| Input | Argument |
| Parameters | |
| operation | the IOperation of which the parameters are documented. An ArgumentException is thrown when it is not an IOperation
|
{{ #ParameterDocumentation this }}
| Summary | writes the name of an enumeration value |
| Writes | the name of the value in lower case |
| Input | Argument |
| Parameters | |
| enum | the C# enum value. A HandlebarsException is thrown when it is not an enum, or when more than one argument is given |
{{ Enum.ToString this.Visibility }}
For DayOfWeek.Monday:
monday
| Summary | queries whether a collection is empty |
| Returns |
true when the collection has no items. false when it has items, and also when the value is not a collection of objects |
| Input | Argument |
| Parameters | |
| collection | the collection to check |
{{#if (IEnumerable.IsEmpty list)}}empty{{else}}not-empty{{/if}}
empty
| Summary | writes the namespace of a named element |
| Writes | the qualified name of the element without its first segment (the root package) and without its last segment (the name of the element), with the remaining segments separated by a .
|
| Input | Context, an INamedElement. An ArgumentException is thrown when it is not |
For the class root::sub::MyClass:
{{ #NamedElement.WriteNameSpace this }}
sub
| Summary | writes the direction, type, name and multiplicity of a parameter as HTML |
| Writes | the direction, followed by a link to the type (<a href=#{XmiId}>), the name and the multiplicity. The name is left out for a return parameter. void is written instead when the parameter has no type |
| Input | Argument |
| Parameters | |
| parameter | the IParameter to write. An ArgumentException is thrown when it is not an IParameter
|
| Remarks | writes HTML, the helper is meant for reports and not for code generation |
{{ #Parameter.WriteTypeAndName parameter }}
For an In parameter count and a Return parameter, both of type Integer:
In <a href=#Integer>Integer</a> count [1..1]
Return <a href=#Integer>Integer</a> [1..1]
The following helpers return a bool and are used in an {{#if}} or {{#unless}} block.
The input is an Argument, the IProperty to check. A HandlebarsException is thrown when the number of arguments is not 1.
| Helper | Returns true when |
|---|---|
Property.QueryIsEnumerable |
the upper bound is larger than 1 |
Property.QueryIsNullable |
the lower bound is 0 |
Property.QueryIsScalar |
both the lower bound and the upper bound are 1 |
Property.QueryIsReferenceProperty |
the type is not a DataType. A property without a type is a reference property |
Property.QueryIsEnum |
the type is an Enumeration
|
Property.QueryIsBool |
the type is a primitive type that maps to bool (UML Boolean) |
Property.QueryIsString |
the type is a primitive type that maps to string
|
Property.QueryIsNumeric |
the type is a primitive type that maps to an integer, floating point or decimal C# type (UML Integer and Real) |
Property.QueryIsInteger |
the type is a primitive type that maps to an integer C# type such as int or long (UML Integer) |
Property.QueryIsFloat |
the type is a primitive type that maps to float
|
Property.QueryIsDouble |
the type is a primitive type that maps to double (UML Real) |
Property.QueryIsDateTime |
the type is a primitive type that maps to a date or time C# type such as DateTime
|
Property.QueryHasDefaultValue |
the property has a default value |
Property.QueryIsDerivedOrDerivedUnionOrReadOnly |
the property is derived, a derived union or read-only |
Property.QueryIsMemberOfManyToMany |
the property takes part in a many-to-many relationship: both ends of its association have an upper bound larger than 1, or it is a reference property with an upper bound larger than 1 that is not part of an association |
The mapping of primitive types to C# types is described in Primitive Types Mapping.
{{#if (Property.QueryHasDefaultValue this)}}default{{else}}none{{/if}}
The input is the Context, which is to be an IProperty; an ArgumentException is thrown when it is not.
| Helper | Returns true when |
|---|---|
Property.IsComposite |
the property is a containment: it is composite, or it is an end of an association of which an owned end is composite |
Property.IsRedefinition |
the property redefines one or more other properties |
Property.QueryIsSubsetted |
the property subsets one or more other properties |
Known issue:
Property.QueryIsSubsettedcurrently returnstruefor every property, also for a property that does not subset another property.
{{#if (#Property.IsComposite property) }} ... {{/if}}
| Helper | Arguments | Returns |
|---|---|---|
Property.IsRedefined |
the IProperty and the IClass in which context it is checked |
true when the property is redefined by another property in the context of the class |
Property.QueryRedefinedByProperty |
the IProperty and the IClass in which context it is queried |
a list with the one property that redefines the property, for use in {{#each}}. An ArgumentException is thrown when the property is not redefined, check with Property.IsRedefined first |
Property.XmiIdEquals |
the IProperty and a string
|
true when the XmiId of the property is equal to the string |
Property.QueryStructuralFeatureNameEqualsEnclosingType |
the IProperty and the IClass that contains it |
true when the name of the property is equal to the name of the class, ignoring case. C# does not allow a member that has the name of its enclosing type |
Known issue:
Property.QueryStructuralFeatureNameEqualsEnclosingTyperequires two arguments and then reads them as if there is one. It throws an exception when it is called.
{{#if (#Property.IsRedefined property class)}}
{{#each (#Property.QueryRedefinedByProperty property class) as | redefinition |}}
{{ redefinition.Name }}
{{/each}}
{{/if}}
{{#if (Property.XmiIdEquals property "Element-ownedElement") }} ... {{/if}}
| Summary | renders the block for a property that has an upper bound larger than 1 |
| Writes | the block, with the current context |
| Input | Block, 1 argument |
| Parameters | |
| property | the IProperty to check |
{{#Property.IsEnumerable property}}
// rendered when the upper bound is larger than 1
{{/Property.IsEnumerable}}
Renders the block for a property that has the same name as the class that contains it. The arguments are the IProperty and the IClass.
Known issue: the helper checks that it is given exactly one argument and then reads a second argument. It throws an exception when it is called.
| Summary | writes the name of the type of a property |
| Writes | the name of the type as it is in the model. Nothing is written for a property without a type |
| Input | Context, an IProperty. An ArgumentException is thrown when it is not |
{{Property.WriteTypeName property}}
| Summary | writes the upper bound of a property |
| Writes | the upper bound as a number. 2147483647 (int.MaxValue) is written for an unlimited upper bound (*), 1 for a property without an upper value |
| Input | Context, an IProperty. An ArgumentException is thrown when it is not |
| Summary | writes the multiplicity of a property |
| Writes | the multiplicity in bracket notation, such as [0..1] or [1..*]
|
| Input | Context, an IProperty. An ArgumentException is thrown when it is not |
{{#Property.WriteFormattedMultiplicity property }}
| Summary | writes the default value of a property |
| Writes | the string representation of the default value. null is written when the property has no default value |
| Input | Context, an IProperty. An ArgumentException is thrown when it is not |
{{ #Property.WriteDefaultValueAsString property }}
| Summary | writes a marker for a property that takes part in a many-to-many relationship |
| Writes |
{many-to-many:Type.name}, with the type and name of the opposite property, when both ends of the association have an upper bound larger than 1. {many-to-many} when the property has an upper bound larger than 1 and no opposite. Nothing in any other case, and nothing for a property that is typed by a DataType
|
| Input | Context, an IProperty. A HandlebarsException is thrown when it is not |
{{ #Property.WriteManyToManyAndOpposite property }}
Each of the String helpers takes one Argument, a string. A HandlebarsException is thrown when the number of arguments is not 1.
| Helper | Writes |
|---|---|
String.CapitalizeFirstLetter |
the string with an upper case first letter |
String.LowerCaseFirstLetter |
the string with a lower case first letter |
String.Length |
the number of characters of the string |
With starion as context for the first line and Starion for the other two:
{{ #String.CapitalizeFirstLetter this }}
{{ #String.LowerCaseFirstLetter this }}
{{ #String.Length this }}
Starion
starion
7
| Summary | writes the C# type of a property for a POCO class |
| Writes | the C# type name of the property, see the table below |
| Input | Context, an IProperty. An ArgumentException is thrown when it is not |
| Remarks | the owner of the property is to be an IClass
|
| The property | Is written as | Example |
|---|---|---|
| is a value type with an upper bound larger than 1 | List<T> |
List<int> |
is a value type, not a string, with a lower bound of 0 |
T? |
int? |
| is any other value type | T |
int, string
|
| is a reference type with an upper bound larger than 1 | List<T> |
List<Bar> |
| is any other reference type | T |
Bar |
| has no type | object |
object |
The name of a reference type is prefixed with an I, such as IFoo, when the class that owns the property is abstract.
{{#POCO.TypeName this}}
| Summary | writes the language and body of a value specification |
| Writes | the language and body pairs of an OpaqueExpression. An empty string is written for any other value specification |
| Input | Context, an IValueSpecification. An ArgumentException is thrown when it is not |
For an OpaqueExpression with the language OCL and the body self.size() > 0:
{{ #ValueSpecification.WriteLanguageAndBody this }}
OCL: self.size() > 0
copyright @ Starion Group S.A.
- Home
- uml4net Tools
- Code Generation Tutorial
- Primitive Types Mapping
- Profiles and StereoTypes
- Code Generation Conventions
- UML Handlebars Helpers
- Generating uml4net
- Developers Experience
- SBOM
- Design Decisions