Functions
Table of Contents
- Overview
- Function Space
- Function types
- Built-in functions
- Built-in functions on Any
- Built-in functions on Any List
- Built-in functions on Resource
- Built-in functions on List of Resource
- Built-in functions on Literal
- Built-in functions on IntegerLiteral
- Built-in functions on IntegerLiteralList
- Built-in functions on BooleanLiteral
- Built-in functions on List of Character
- Built-in functions on List of Letter
- Built-in functions on TextLiteral
- Built-in functions on StringLiteral
- Built-in functions on Word
- Built-in functions on Guid
- Built-in functions on Build
- Built-in functions on LinkSelector
- Built-in functions on File
- Accessing the model from within Java function
Overview
Actifsource functions might be called from templates (see ChapterTemplate Editor), from other functions, or from selector relations (see Chapter 4.4.7 SelectorRelation). There are different supported types of functions (see Chapter 9.3 Function types).
Function Space
The function space is the resource where functions are living. We know two different types of functions spaces, both derived from AbstractFunctionSpace.
FunctionSpace is the place where you can place any function. Template is a code template where you can place functions in the scope of the template.
Functions are grouped by a FunctionContext. By the typeRef, the FunctionContext is bound to a Class or an Enum. Functions in the function context are applicable on instances of types referenced by typeRef.
Note that Actifsource prohibits more than one function context with the same typeRef in the same function space.
Function Parameters
A function might define a set of parameters. If calling a function from a template, Actifsource automatically tries to match with the context path (see Chapter 8.3.17).
Function parameters are defined in the model of the specific function type (see Chapter 9.3 Function types).
Using function parameters in a template function (see Chapter 9.3.6 TemplateFunction) leads to the corresponding super contexts (see Chapter 8.3.5 SuperContext).
Using function parameters in a java function (see Chapter 9.3.3 SelectorFunction)
Selector functions allow you to navigate the model by using the selector syntax. Starting from a Class defined by FunctionContext.typeRef you may navigate via the resource properties.
Selectors might be used in Templates to select a context. But selectors might also be called from within selectors – even recursively.
-
Forward navigation Consider the following meta-model.
We like to define a selector function named getSubChild on Parent which returns all sub-children in all children of the parent. The return type when navigating along a property is given by the range of the property, i.e, in our example the expected return type is a list of elements of type SubChild To navigate from Parent via child to subChild just assemble a selector Parent.child.subChild Make sure to use content assist (Ctrl+Space) when writing selector functions.
This is what a selector function could look like.
- Backward navigation Consider the following meta-model.
To get the Parent instance for a SubChild instance we have to navigate backwards via the subChild and child relation. The selector allows backward navigation via the minus relation.
- List operators Actifsource provides you with the following operators which are defined on lists (where the lists are given by Selector expressions):\
Operator | Description |
---|---|
A union B |
The result is the concatenation of the two lists A and B. For example, [a1,a2] union [a3,a1] is equal to [a1,a2,a3,a1]. |
A intersect B |
Only elements found in A and in B where duplicates are preserved and the resulting order is given by A. For example, [a1,a1,a2,a2] intersect [a2,a1,a1] is equal to [a1,a1,a2]. |
A except B |
For all elements b in B, the first occurrence of b in A is removed from A. For example, [a2,a1,a3,a2,a1] except [a1,a2,a1] is equal to [a3,a2] |
A else B |
All elements in A if a is empty, otherwise all elements in B. For example, [a1, a2] else [b1,b2] is equal to [a1,a2] and [] else [b1,b2] is equal to [b1,b2]. |
A then B |
All element in B if A is not empty else empty list (i.e (A then B else C)). |
A excludefilter A.c |
All elements from the set A with the exception of the elements for which A.c is evaluated to empty or boolean true . |
A includefilter A.c |
where the expression A.c must be evaluated as not empty or Boolean true . |
A getindex i |
Selects the element at position i ($i \in \mathbb{Z}_{0}^{+}$) from the list of elements of A. For example [a2,a1,a3,a2,a1] getindex 2 selects a3. |
Note that you can use brackets to control precedence (i.e. (A.x union A.y) intersect A.z). The result type of the union, intersect and else operator is the most concrete supertype of the type of the two operands (e.g. if A is of type NamedResource and B is of type Resource, then A intersect B A union B and A else B are all of type Resource). After brackets you can continue the selector (i.e (A.x union A.y).typeOf).
If you only like to get Leaf components from the Client, just use the type cast operator (colon).
-
Up Cast It is always possible to use an upcast to a base class (i.e. Resource or NamedResource) if needed.
-
Self Cast If your selector has to return the typeRef instance itself, use the self-cast. Consider the following selector function for Component returning the component instance itself.
- Recursive navigation The diagram below shows a composite pattern as presented in the book Design Patterns from Erich Gamma et al. The composite pattern allows you to recursively instantiate Composite instances, which might aggregate other components of type Leaf or again – of type Composite.
There is an easy way to find the Client of this recursive model using selectors. First, we collect all components including the own component and all parent components.
For that reason we write a selector function for Component which returns the component itself and also all parent components which are reachable by going backwards via the component relation.
To get the Client which is parent of all component just collect all component first by using the above selector functions. From all this components in the collected set there is only one instance aggregated by Client. Let’s write a selector function for that.
Please take extra care because there are two relations named component. One is Composite.component the other one is Client.component Make sure to use Composite.component in allComponent and Client.component in getClient
- Calling selectors with parameters
[TBD]
JavaFunction
leads to the corresponding java function arguments.
Polymorphic calls
Function calls are polymorphic if a function has the same name, the same parameters and a typeRef to a sub class.
In the following example, the function identify is defined for MyClass and MySubClass. There will be a polymorphic call to MyClass.identify dependent on the type of the instance.
Non-Polymorphic calls
There are situations where polymorphic calls are not desired. You have to disable polymorphic calls on every caller. Use the context menu Change to non-virtual call on the function.
A small arrow indicates the non-polymorphic call.
Extends
Polymorphic calls are supported in the same function space by default. Extending another function space enables polymorphic calls over functions spaces.
Function types
Actifsource supports different types of functions.
Abstract Function
Abstract functions shall only be defined on types with an abstract modifier (see Chapter 4.6.1 ch.actifsource.core.Class
).
For an abstract function, there must be non-abstract function for any non-abstract subclass in the same function space or in a function space that extends it.
SelectorFunction
Selector functions allow you to navigate the model by using the selector syntax. Starting from a Class defined by FunctionContext.typeRef you may navigate via the resource properties.
Selectors might be used in Templates to select a context. But selectors might also be called from within selectors – even recursively.
We like to define a selector function named getSubChild on Parent which returns all sub-children in all children of the parent. The return type when navigating along a property is given by the range of the property, i.e, in our example the expected return type is a list of elements of type SubChild
To navigate from Parent via child to subChild just assemble a selector Parent.child.subChild Make sure to use content assist (Ctrl+Space) when writing selector functions.
This is what a selector function could look like.
- Backward navigation Consider the following meta-model.
To get the Parent instance for a SubChild instance we have to navigate backwards via the subChild and child relation. The selector allows backward navigation via the minus relation.
- List operators Actifsource provides you with the following operators which are defined on lists (where the lists are given by Selector expressions):
Operator | Description |
---|---|
A union B | The result is the concatenation of the two lists A and B. For example, [a1,a2] union [a3,a1] is equal to [a1,a2,a3,a1]. |
A intersect B | Only elements found in A and in B where duplicates are preserved and the resulting order is given by A. For example, [a1,a1,a2,a2] intersect [a2,a1,a1] is equal to [a1,a1,a2]. |
A except B | For all elements b in B, the first occurrence of b in A is removed from A. For example, [a2,a1,a3,a2,a1] except [a1,a2,a1] is equal to [a3,a2] |
A else B | All elements in A if a is not empty, otherwise all elements in B. For example, [a1, a2] else [b1,b2] is equal to [a1,a2] and [] else [b1,b2] is equal to [b1,b2]. |
A then B | All element in B if A is not empty else empty list (i.e (A then B else C)). |
Note that you can use brackets to control precedence (i.e. (A.x union A.y) intersect A.z). The result type of the union, intersect and else operator is the most concrete supertype of the type of the two operands (e.g. if A is of type NamedResource and B is of type Resource, then A intersect B A union B and A else B are all of type Resource).
- Down Cast Consider the following meta-model.
If you only like to get Leaf components from the Client, just use the type cast operator (colon).
-
Up Cast It is always possible to use an upcast to a base class (i.e. Resource or NamedResource) if needed.
-
Self Cast If your selector has to return the typeRef instance itself, use the self-cast. Consider the following selector function for Component returning the component instance itself.
- Recursive navigation The diagram below shows a composite pattern as presented in the book Design Patterns from Erich Gamma et al. The composite pattern allows you to recursively instantiate Composite instances, which might aggregate other components of type Leaf or again – of type Composite.
There is an easy way to find the Client of this recursive model using selectors. First, we collect all components including the own component and all parent components.
For that reason we write a selector function for Component which returns the component itself and also all parent components which are reachable by going backwards via the component relation. $
To get the Client which is parent of all component just collect all component first by using the above selector functions. From all this components in the collected set there is only one instance aggregate by Client. Let’s write a selector function for that.
Please take extra care because there are two relations named component. One is Composite.component the other one is Client.component Make sure to use Composite.component in allComponent and Client.component in getClient
- Calling selectors with parameters
[TBD]
JavaFunction
Actifsource supports user-implemented Java functions that make use of the very powerful Javamodel to access the Actifsource models from Java code (see also Section 9.5).
When you declare a Java function, Actifsource automatically generates a function skeleton in a file with the same name as your function space found in the folder src-gen
.
You should only modify generated files within protected regions (see Chapter 2.12.5 Protected Regions). Take extra care that import statements are placed within the protected regions – especially if inserted automatically by the Java content assist.
As function arguments, an instance of type FunctionContext.typeRef and all parameters are passed. Use the Java content assist (Ctrl+Space) to display available functions. To access properties choose myClass.selectMyProperty(). For more information on how to access the Javamodel see Chapter 9.5.
A Java function has a return type which is either a Type or a TypeReference.
A Type is either a SimpleType or a ListType. A SimpleType can, in particular, be a ClassType, which references any Class, or a LiteralType, which references any Literal. For a LiteralType the return type of the generated Java function is the Java class given by the return value of the method getValueType()
of the ILiteralAspect (e.g. in the example above the LiteralAspect of StringLiterals (ch.actifsource.core.model.aspects.impl.String.StringLiteralAspect
) defines that java.lang.String represents StringLiterals and, therefore, the the return type of identify is java.lang.String). A ListType references either a Class or a Literal (more precisely, it actually references an AbstractType). The return type of the generated Java function is then a java.util.List<Class>
, where Class is the Java class that corresponds to the Literal or the Class. Note that in the latter case the Java class is the wrapper Java class that corresponds to the Actifsource Class and is provided by the Javamodel (see also Chapter 2 and Section 9.5).
A TypeReference is either a GenericContextType or a GenericContextListType. In the first case, the return type of the generated Java function is <T extends C
T
where C is the Java class corresponding to the type of the element the function is called on (the this-instance). In the second case, the return type of the generated Java function is a <T extends C>
java.util.List<T>
where T
is defined as before (see examples below).
Note that function with a return type of GenericContextType or a GenericContextListType can be applied to elements of any sub-type of the type given by typeRef of the FunctionContext, i.e., the this-parameter of the generated Java function is <T extends Class>
T where Class is the Java wrapper class corresponding to the typeRef of the FunctionContext.
JavaListFunction
Java list functions can be applied to a list of elements defined by a Selector expression, e.g. in the Selector expression Parent.child.myFunction@ChildFunctionSpace
the function myFunction is called on the list of all Children reachable from Parent via the relation child (see example in Section 9.3.2). The this-parameter of the generated Java function is then of type java.util.List<\>
where C
is the Java class corresponding to the typeRef of the FunctionContext (respectively java.util.List<T extends C>
if the returnType of the Java list function is GenericContext(List)Type). Consider the following example that is based on the meta-model from Section 9.3.5:
The return types of JavaListFunctions are determined in the same way as for JavaFunctions (see Section 9.3.3). A list of built-in (Java) list functions is presented in Section Fehler! Verweisquelle konnte nicht gefunden werden..
Consider an extended meta-model where Parent can be referenced by a ParentContainer via a relation parent:
In this case, the selector ParentContainer.parent.child.myFunction@MyFunctionSpace constructs for each Parent the list of Children reachable from this Parent and then applies the function myFunction to each of these lists. If the function should be applied to the list of Children reachable indirectly via parent we can write a (Selector)Function that returns a list of all these Children e.g. ParentContainer.getAllChildren@MyFunctionSpace where getAllChildren is a SelectorFunction with the selector ParentContainer.parent.child In the selector ParentContainer.getAllChildren@MyFunctionSpace.myFunction@MyFunctionSpace the function myFunction is only called once on the list of all Children reachable from ParentContainer.
JavaAspectFunction
[TBD]
TemplateFunction
A template function behaves in the same way as a template, but there are no files generated from a template function. Just think of a template function as a sub template which can be expanded in a template or in another template function (also recursively).
Consider the following meta-model:
Let us now write a template function for a component which writes the name and type of the component and, if the given component is a composite, also does the same recursively for all subcomponents.
First of all we have to define the template function in the model.
To open the template function with the template editor, just double click in the Project Explorer. Use the Link with Editor tool (see Chapter 2.10.1 Link with Editor) to easily locate the template function in the project explorer.
In line 1 we write out the component name and its type name. In line 2 we iterate over all aggregated components, but only if the component is of type Composite (type cast). In this context we call the template function asText recursively for all aggregated component.
Note the indention of two spaces on line 2. Actifsource takes care of the indentions so that the whole content of the template function is indented.
We can now call our template function from a template. If there is a call to a function from another function space, the function space is explicitly stated using the notation myFunction@MyFunctionSpace.
Next, we create an instance of type Client containing composites and leaves. The output from the above template might look as follows.
Note that the indention is applied recursively.
TemplateLineFunction
The template line function behaves like a template but without the possibility to set contexts (see Chapter 8.3.9 Line Context, Column Context, Protected Context). The template line allows you to create simple single line texts as for name aspects (see Chapter 4.6.1 ch.actifsource.core.Class).
Consider a resource Person with two string literals firstName and LastName
Write a template function for person, which prints out the person's last name and first name.
Simply use the template line function as name aspect in the class Person.
Please not that it is also possible that the selector of the name aspect can be used directly as template line.
Note that Person is only a Resource but not a NamedResource. The attributes firstName and lastName are therefore just normal properties.
Defining the name aspect as seen above synthesizes the name.
Built-in functions
Actifsource provides lots of useful built-in functions.
Built-in functions on Any
Actifsource provides the following built-in functions on Any.
Function | Return type | Description |
---|---|---|
guid | Literal | Gets the unique identifier of any Resource or Literal. (For Resources it is a GUID, for Literals it is the Literal itself.) |
Built-in functions on Any List
Actifsource provides the following built-in functions on List of Any.
Function | Return type | Description |
---|---|---|
count | IntegerLiteral | Counts the number of elements in the list |
isEmpty | BooleanLiteral | Returns true if and only if the list is empty. |
isSet | BooleanLiteral | Returns true if and only if the list contains no duplicates. |
first | T | Returns the first element in the list. |
last | T | Returns the last element in the list. |
count | IntegerLiteral | Counts the number of elements in the list. |
reverse | List of T | Reverses the elements in the list. |
distinct | List of T | Remove duplicates from a list, first to last. |
Built-in functions on Resource
Actifsource provides the following built-in functions on Resource.
Function | Return type | Description |
---|---|---|
package | String | Returns the package of the resource as string. |
guid | String | Returns the GUID of the resource as string. |
simpleName | String | Returns the Resource’s name as defined by its NameAspect. If the resource extends NamedResource, the NameAspect returns the value of the name attribute. If no NameAspect is defined, the GUID of the resource is returned. |
Built-in functions on List of Resource
Actifsource provides the following built-in functions on List of Resource.
Function | Return type | Description |
---|---|---|
sortByGuid | List of T | Sorts the list of resources by their GUIDs. |
sortBySimpleName | List of T | Sorts the list of resources by their names. |
Built-in functions on Literal
Actifsource provides the following built-in functions on Literal.
Function | Return type | Description |
---|---|---|
guid | T | Gets the identifier of the Literal value. |
Built-in functions on IntegerLiteral
Actifsource provides the following built-in functions on IntegerLiteral.
Function | Return type | Description |
---|---|---|
increment | Integer | Increments an integer number. |
decrement | Integer | Decrements an integer number. |
notZero | Integer | Returns the number unless it is zero. |
Built-in functions on IntegerLiteralList
Actifsource provides the following built-in functions on List of IntegerLiteral.
Function | Return type | Description |
---|---|---|
sum | Integer | Calculates the sum of a list of integer numbers. |
minimum | Integer | Returns the minimum integer in a list. |
maximum | Integer | Returns the maximum integer in a list. |
Built-in functions on BooleanLiteral
Actifsource provides the following built-in functions on BooleanLiteral.
Function | Return type | Description |
---|---|---|
isFalse | Boolean | Returns true if the Boolean value is false. |
Built-in functions on List of Character
Actifsource provides the following built-in functions on List of Character.
Function | Return type | Description |
---|---|---|
string | Boolean | Builds a string from characters. |
Built-in functions on List of Letter
Actifsource provides the following built-in functions on List of Letter.
Function | Return type | Description |
---|---|---|
string | Word | Builds a word from letters. |
Built-in functions on TextLiteral
Actifsource provides the following built-in functions on TextLiteral.
Function | Return type | Description |
---|---|---|
suppressIndent | Text | Sets the current intent mode to ‘suppress indent’: All lines after the first line start at the very beginning of the line. If applied in a template function, the setting of the outer template is not affected. The return value is the text itself. |
indent | Text | Sets the indent mode to ‘indent’ (=default). All lines will start at the same position as the first line. (The preceding characters in the first line are copied, non-whitespace characters replaced by whitespaces.) If applied in a template function, the setting of the outer template is not affected. The return value is the text itself. |
prefix | Text | Sets the indent mode to ‘prefix’. All lines will repeat the preceding characters in of the first line. If applied in a template function, the setting of the outer template is not affected. The return value is the text itself. |
splitLines | List<String> | Splits text at line breaks into a list of strings. |
split80 | List<String> | Splits text into a list of strings of maximum 80 characters. Words are considered atomic, if possible. |
split100 | List<String> | Splits text into a list of strings of maximum 100 characters. Words are considered atomic, if possible. |
escapedString | String | Escapes the text such that it can be embedded into C, C++ or Java source code. Escaping for C/C++ only works for ASCII characters. |
notEmpty | Text | Returns the text unless it is empty. |
Built-in functions on StringLiteral
Actifsource provides the following built-in functions on StringLiteral.
Function | Return type | Description |
---|---|---|
character | List of Character | Gets the characters in the string. |
length | Integer Gets the number of characters in the string. | |
toFirstUpper | String | Gets the same string with capital first letter. |
toFirstLower | String | Gets the same string with small first letter. |
toAllUpper | String | Gets the string in all capital letters. |
toAllLower | String | Gets the string in all small letters. |
camelcapToUnderscore | String | Inserts an underscore before every uppercase letter unless it is the first letter in the string. |
whitespaceToCamelcap | String | Replaces letters behind one or many whitespace characters by their uppercase counterparts, replacing those whitespace |
characters. | ||
whitespaceToUnderscore | String | Replaces all whitespace characters by underscore characters. |
split80 | List of String | Splits the string into a list of strings of maximally 80 characters. |
split100 | List of String | Splits the string into a list of strings of maximally 100 characters. |
packageToDirectory | String | Replaces '.' by '/'. |
isNotEmpty | Boolean | Returns true if and only if the string is not an empty string. |
escapedString | String | Escapes the string such that it can be embedded into C, C++ or Java source code. Escaping for C/C++ only works for ASCII characters. |
part | List of Literal | Parses the string into words, natural numbers and special characters, removing whitespaces. |
Built-in functions on Word
Actifsource provides the following built-in functions on Build.
Function | Return type | Description |
---|---|---|
character | Letter | Gets the letters in the word. |
Built-in functions on Guid
Actifsource provides the following built-in functions on Build.
Function | Return type | Description |
---|---|---|
timestamp | Long | Returns the GUID's timestamp in nanoseconds starting from Oct 15, 1582. |
time | Time | Returns the GUID's time. |
identify | Resource | Returns the Resource identified by the GUID. |
Built-in functions on Build
Actifsource provides the following built-in functions on Build.
Function | Return type | Description |
---|---|---|
once | Build | Used in the selector of the template. Build.once means a template is not based on a resource but only built once. |
Built-in functions on LinkSelector
Actifsource provides the following built-in functions on LinkSelector.
Function | Return type | Description |
---|---|---|
selectorText | String | Converts a selector to simple text string. |
selectorResultType | AbstractType | Calculates a selectors result type. |
Built-in functions on File
Actifsource provides the following built-in functions on File.
Function | Return type | Description |
---|---|---|
contents | Text | Returns a file's contents. |
Accessing the model from within Java function
It is possible to access the model, other functions (see chapter 9.3 Function types), or even built-in functions (see chapter Fehler! Verweisquelle konnte nicht gefunden werden. Fehler! Verweisquelle konnte nicht gefunden werden.) from within Java functions.
Consider the following meta-model for the subsequent examples:
Model forward access
Let’s write a Java Function for Parent which returns only instances of type Child with names beginning with “A”.
Start by declaring a Java Function named filterChild as seen in Chapter 9.3.3.
For the model forward access use the selectProperty() function on the given resource where property is the property to select.
The subsequent filter function iterates over the relation Parent.child in the for-Statement via parent.selectChild(). Then we check if Child.name starts with “A” via child.selectName(). If the condition is fulfilled we add the filtered child to the child list. At the end we return the child list with the filtered children.
You might use the filter function in the selector of a template or in any other function. The following template only prints children with names starting with “A”.
Model backward access
Using the selector syntax accessing the model backwards is quite easy (see chapter 9.3.2 SelectorFunction) by the minus sign. Accessing the model backwards is also possible in the Java code.
For the model backward access use the static function selectToMeProperty() on the class which defines the relation.
Since we want to access the relation Parent.child backwards we have to choose the static method Parent.selectToMeChild() providing the actual child as parameter. As a result we get the parent of the given child.
Function access
Use the extension mechanism to access any of your functions from within Java Code.
Note that the extension mechanism also supports polymorphic calls (see chapter Fehler! Verweisquelle konnte nicht gefunden werden. Fehler! Verweisquelle konnte nicht gefunden werden.).
Let’s assume that we have a function filterChild as shown in chapter 9.5.1 Model forward access. Let’s write a Java function filterChildReverse which returns a reverse list of the filtered children based on filterChild.
For the function access use the extension() function on the given resource with FunctionSpace.ITypeRefFunctions.class as parameter. FunctionSpace is the function space where your function is defined. TypeRef is FunctionContext.typeRef. The static property .class is given from Java and represents a class as an object.
Built-in function access
Use the extension mechanism to access built-in functions on resources (see chapter 9.4.1 Built-in functions on Any
Actifsource provides the following built-in functions on Any.
Function | Return type | Description |
---|---|---|
guid | Literal | Gets the unique identifier of any Resource or Literal. (For Resources it is a GUID, for Literals it is the Literal itself.) |
Built-in functions on Any List
Actifsource provides the following built-in functions on List of Any.
Function | Return type | Description |
---|---|---|
count | IntegerLiteral | Counts the number of elements in the list. |
isEmpty | BooleanLiteral | Returns true if and only if the list is empty. |
isSet | BooleanLiteral | Returns true if and only if the list contains no duplicates. |
first | T | Returns the first element in the list. |
last | T | Returns the last element in the list. |
count | IntegerLiteral | Counts the number of elements in the list. |
reverse | List of T | Reverses the elements in the list. |
distinct | List of T | Remove duplicates from a list, first to last. |
Built-in functions on Resource) from within Java Code. Accessing built-in functions is done the same way as seen in the above chapter 9.5.3 Function access.
To write a function which returns the package and the simpleName of a child we can reuse the built-in functions package() and simpleName() For the built-in function access use the extension() function on the given resource with BuiltinResourceFunctions.class as parameter.
Note that you cannot access built-in functions for literals via the extension mechanism.