Skip to content

handlebarshelpers

samatstarion edited this page Oct 11, 2026 · 3 revisions

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.

Registering the helpers

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.

How the helpers are called

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 leading

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.

Boolean Helpers

Boolean.ToLowerCase

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

Example

Usage

{{ Boolean.ToLowerCase True }}
{{ Boolean.ToLowerCase False }}

Returns

true
false

Class Helpers

Class queries

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

Example

Usage

For the Activity class of the UML 2.5.1 model:

{{#each (#Class.QueryOwnedAttributeOrdered this) as | property |}}{{ property.Name }};{{/each}}

Returns

edge;group;isReadOnly;isSingleExecution;node;partition;structuredNode;variable;

Class.RenderInheritanceDiagram

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

Example

Usage

{{#Class.RenderInheritanceDiagram class diagrams}}<div>{{{this}}}</div>{{/Class.RenderInheritanceDiagram}}

Returns

When diagrams holds <svg>test-diagram</svg> for the class:

<div><svg>test-diagram</svg></div>

Class.RenderAssociationDiagram

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

Classifier Helpers

Classifier.QueryContainers

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

Example

Usage

{{#each (Classifier.QueryContainers this) as | container |}}{{ container.Name }};{{/each}}

Documentation Helpers

Documentation

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

Example

Usage

For a class with an owned comment that has the body Short description.:

{{ #Documentation this }}

Returns

/// <summary>
/// Short description.
/// </summary>

RawDocumentation

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

Example

Usage

{{ #RawDocumentation this }}

Returns

Short description.

ParameterDocumentation

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

Example

Usage

{{ #ParameterDocumentation this }}

Enum Helpers

Enum.ToString

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

Example

Usage

{{ Enum.ToString this.Visibility }}

Returns

For DayOfWeek.Monday:

monday

IEnumerable Helpers

IEnumerable.IsEmpty

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

Example

Usage

{{#if (IEnumerable.IsEmpty list)}}empty{{else}}not-empty{{/if}}

Returns

empty

NamedElement Helpers

NamedElement.WriteNameSpace

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

Example

Usage

For the class root::sub::MyClass:

{{ #NamedElement.WriteNameSpace this }}

Returns

sub

Parameter Helpers

Parameter.WriteTypeAndName

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

Example

Usage

{{ #Parameter.WriteTypeAndName parameter }}

Returns

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]

Property Helpers

Property checks

The following helpers return a bool and are used in an {{#if}} or {{#unless}} block.

Checks with one argument

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.

Example

{{#if (Property.QueryHasDefaultValue this)}}default{{else}}none{{/if}}

Checks on the context

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.QueryIsSubsetted currently returns true for every property, also for a property that does not subset another property.

Example

{{#if (#Property.IsComposite property) }} ... {{/if}}

Checks with two arguments

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.QueryStructuralFeatureNameEqualsEnclosingType requires two arguments and then reads them as if there is one. It throws an exception when it is called.

Example

{{#if (#Property.IsRedefined property class)}}
    {{#each (#Property.QueryRedefinedByProperty property class) as | redefinition |}}
        {{ redefinition.Name }}
    {{/each}}
{{/if}}

{{#if (Property.XmiIdEquals property "Element-ownedElement") }} ... {{/if}}

Property.IsEnumerable

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

Example

Usage

{{#Property.IsEnumerable property}}
    // rendered when the upper bound is larger than 1
{{/Property.IsEnumerable}}

Property.NameEqualsEnclosingType

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.

Property.WriteTypeName

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

Example

Usage

{{Property.WriteTypeName property}}

Property.WriteUpperValue

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

Property.WriteFormattedMultiplicity

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

Example

Usage

{{#Property.WriteFormattedMultiplicity property }}

Property.WriteDefaultValueAsString

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

Example

Usage

{{ #Property.WriteDefaultValueAsString property }}

Property.WriteManyToManyAndOpposite

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

Example

Usage

{{ #Property.WriteManyToManyAndOpposite property }}

String Helpers

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

Example

Usage

With starion as context for the first line and Starion for the other two:

{{ #String.CapitalizeFirstLetter this }}
{{ #String.LowerCaseFirstLetter this }}
{{ #String.Length this }}

Returns

Starion
starion
7

TypeName Helpers

POCO.TypeName

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.

Example

Usage

{{#POCO.TypeName this}}

ValueSpecification Helpers

ValueSpecification.WriteLanguageAndBody

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

Example

Usage

For an OpaqueExpression with the language OCL and the body self.size() > 0:

{{ #ValueSpecification.WriteLanguageAndBody this }}

Returns

OCL: self.size() > 0

Clone this wiki locally