b4A Expressions
Mit den b4A Expressions wird ein Ersetzungsalgorithmus zur Verfügung gestellt. mit dem einfache Wertersetzungen durchgeführt oder erweiterte Funktionen zur Ersetzung genutzt werden können.
Einfache Ersetzungen
Mit diesen können zuvor definierte Variablen in Zeichenketten ersetzt werden. Zusätzlich können die Werte der Variablen vor der Ersetzung mit Listen von regulären Ausdrücken verändert werden. Welche Variablen definiert sind hängt von dem Modul ab, das b4A Expressions unterstützt. Daher sind die Variablenlisten in der Dokumentation der Module zu finden.
Um eine Variable zu ersetzen müssen in der Zeichenkette bestimmte Marker definiert sein wie in dem folgenden Beispiel.
Dies ist das Objekt %(object_name) vom Typ %(object_type)
Sind die Variablen object_name und object_type definiert, werden die Werte der Variablen in dem Text eingefügt. Um die Werte vor der Ersetzung zu verändern, können in den Markern Ersetzungsregeln angegeben werden.
Der Objekt-Titel wird auf %(object_name/_/ /§§/./ /§§/[A-Z]+/CAPITALIZE/) gesetzt
Die Ersetzungsregeln werden als semikolon-separierte Liste im Marker definiert. Jede Regel besteht aus zwei Teilen. Einem regulären Ausdruck, der den zu ersetzenden Teil definiert und die Zeichenkette, mit der der Teil ersetzt werden soll. Das Format ist wie folgt definiert:
/<regulärer Ausdruck>/<Ersetzungstext>/
Für den <Ersetzungstext> gibt es drei besondere Werte, die nicht direkt als Ersetzung genutzt werden, sondern Funktionen sind, die auf den Wert der Variable angewendet werden.
UPPERCASE: ersetzt den Teil mit Großbuchstaben.
LOWERCASE: ersetzt den Teil mit Kleinbuchstaben.
CAPITALIZE: ersetzt den Teil durch ein Wort mit dem ersten Buchstaben als Großbuchstaben und den Rest in Kleinbuchstaben.
Wenn in dem Ersetzungstext oder dem regulären Ausdruck Schrägstriche enthalten sein sollen muss diesen ein Backslash (\) vorangestellt werden.
%(package_dependencies/ *§§ */<\/br>/)
%(folder/.*\///)
Funktionen
Eine weitere Variante der b4A Expressions sind Funktionen. Diese können verschiedene Aufgaben auf dem zu ersetzenden Text ausführen. Funktionen werden wie folgt definiert:
%{<Funktionsname>[,<Option>[,<Option>...]]:<Parameter>:<Ersetzungstext>}
Die Optionen einer Funktion werden als eine Komma-separierte Liste angegeben. Eine Option wird in folgendem Format angegeben:
<Name>=<Wert>
Um boolesche Optionen auf den Wert true zu setzen reicht es nur den Namen anzugeben.
<Name>
IF
Mit der Funktion IF kann eine bedingte Textausgabe definiert werden. Dabei wird der Wert eines Attributes verglichen. Nur wenn die Bedingung erfüllt ist, wird der Ersetzungstext in die Dokumentation übernommen.
%{IF[,<Option>[,<Option>...]]:<Vergleich>:<Ersetzungstext>}
Optionen:
ignore_case[=(true|false)]: Ist die Option gesetzt, wird bei Vergleichen nicht auf die Groß- und Kleinschreibung geachtet.
Als Operatoren für den Vergleich stehen folgende zur Verfügung:
==: Prüft ob der Wert eines Attributs gleich einem gegebenen Wert ist
!=: Prüft ob der Wert eines Attributs ungleich einem gegebenen Wert ist
~=: Prüft ob der Wert eines Attributs einen gegebenen Wert enthält
>: Prüft ob der Wert eines Attribut größer ist als ein gegebenen Wert (Zahlen)
<: Prüft ob der Wert eines Attribut größer ist als ein gegebenen Wert (Zahlen)
!: Prüft ob der Wert eines Attributes leer ist (Liste oder Zeichenkette)
?: Prüft ob der Wert eines Attributes nicht leer ist (Liste oder Zeichenkette)
Einige der Operatoren können nur auf bestimmte Typen von Attributen angewendet werden. Dies ist in der obigen Liste entsprechend angegeben. Diese Bedingungen können mit den booleschen Operatoren & (und) und | (oder) verknüpft werden. Die Bedingungen werden dabei von links nach rechts bis zur letzten Bedingung ausgewertet.
Wenn das Attribut leer ist, dann wird der Text angezeigt.
%{IF:!sync_list:
Die Sync-Liste ist leer
}
Wenn das Attribut nicht leer ist, dann wird der Text angezeigt.
%{IF:?sync_list:
||Sync object||Start action||Abend action||End action||Else||
%{LOOP_LIST:sync_list:|%(sync_object)|%(start)|%(abend)|%(end)|%(else)|}
}
Wenn das Attribut dem Wert true entspricht.
%{IF:runtime==true:
Laufzeitwerte sind gesetzt
}
Wenn das Attribut runtime den Wert true hat und die Liste sync_list nicht leer ist wird der Text ausgegeben.
%{IF:runtime==true&?sync_list:
Laufzeitwerte sind gesetzt und Sync-Liste ist nicht leer
}
LOOP_LIST
Mit der Funktion LOOP_LIST kann über Listen von Attributen iteriert werden. Der Ersetzungstext wird für jedes Element der Liste eingefügt.
%{LOOP_LIST[,<Option>[,<Option>...]]:<Attribut>:<Ersetzungstext>}
Optionen:
separator=<separator>: Ist die Option gesetzt, dann werden keine Zeilenumbrüche nach den einzelnen Einträgen eingefügt, sondern die angegebenen Zeichen.
Das angegebene <Attribut> muss eine Liste enthalten. Jedes Element der Liste ist wieder eine Sammlung von Attributen, die in dem <Ersetzungstext> ersetzt werden.
COUNT_LIST
Mit der Funktion COUNT_LIST können die Elemente einer Liste gezählt werden. Das Ergebnis steht als Attribut zur Verfügung und kann im Ersetzungstext verwendet werden.
%{COUNT_LIST:<Attribut>:<Ersetzungstext>}
Im folgenden Beispiel wird die Anzahl der Objekte in dem Package ausgegeben.
%{COUNT_LIST:objects:<p>Number of objects: %(count)</p>}
JOIN
Die Funktion JOIN erlaubt es ein Feld je Element einer Liste in ein eine Zeichenkette zusammenzusetzen. Dabei kann das Trennzeichen zwischen den Elementen konfiguriert werden.
%{JOIN:<Liste>,<Feld>:<Trennzeichen>}
Um die Namen der Sync-Objekte eines Jobs auszugeben kann folgender Ausdruck genutzt werden.
%{JOIN:sync_list,sync_object:, }
Die Liste der Sync-Objekte wird mit einem Komma (,) als Trennzeichen ausgegeben
LOOP_XY
Die Funktion LOOP_XY ist speziell für die Darstellung von Attributen der RA-Objekte. Hier werden Listen nicht als Datenstruktur zur Verfügung gestellt, sondern durch einzelne Attribute, die in ihren Namen eine Strukturkodierung enthalten.
query_0_0 = query1
query_0_1 = param1
query_1_0 = query1
query_1_1 = param1
Die Nummern in den Attributnamen geben die Zeile soviel die Spalte innerhalb der Listenstruktur an. Somit bilden alle Attribute dieser Liste, die mit query_0_ beginnen, die Elemente des ersten Listenelements. Um solche Attribute ähnlich zu einer Liste wie mit LOOP_LIST darstellen zu können gibt es die Funktion LOOP_XY.
%{LOOP_XY:<Attributmuster>:<Ersetzungstext>}
Im <Attributmuster> wird durch die Kennzeichner $x (Spalte) und $y (Zeile) angegeben, wie die Attribute der Liste aufgebaut sind. In dem Ersetzungstext kann auf die Elemente einer solchen Liste mittels virtueller Attribute zugegriffen werden, die nach der Nummer der Spalte benannt sind (z.B. %(1), %(2)).
%{LOOP_XY:query_$y_$x:<tr><td><i>%(1)</i></td><td>%(2)</td></tr>}
LOOP_Y
Die Funktion LOOP_Y ist ähnlich wie die Funktion LOOP_XY. Hier geht es um Attribute, die die Zeile der Listenelemente im Namen kodieren, die Spalte wird allerdings durch einen sprechenden Namen definiert.
response_part_0_script_0_code_0 = store.bla
response_part_0_script_0_queryType = JSONPath
response_part_0_script_0_resourceName = &jsonvar#
response_part_0_script_0_saveTo = variable
response_part_0_script_0_useArray = true
response_part_0_script_1_code_0 = if ( store.fasel.equals( "hello world" ) )
Die Verwendung der Funktion LOOP_Y ist der Funktion LOOP_XY gleich. Im Attributmuster muss nur die Zeile ($y) angegeben werden, da die Spalte durch das Ende des Attributsnamen definiert wird.
%{LOOP_Y:<Attributmuster>:<Ersetzungstext>}
In dem Ersetzungstext können Attribute verwendet werden, die den Endungen der Originalattribute entsprechen. Alles hinter dem angegebenen Attributmuster entspricht dem Namen der virtuellen Attribute.
%{LOOP_Y:response_part_0_script_$y_:<tr><td>%(queryType)</td><td>%(saveTo)</td><td>%(resourceName)</td><td><div class="code">%(code_0)</div></td><td>%(useArray)</td></tr>}
LOOP_LINES
Mit der Funktion LOOP_LINES kann über die einzelnen Zeilen eines mehrzeiligen Attributes iteriert werden.
%{LOOP_LINES[,<Option>[,<Option>…]]:<Attribut>[,<regulärer Ausdruck>]:<Ersetzungstext>}
Optionen:
ignore_case[=(true|false)]: Ist die Option gesetzt, wird bei der Filterung mit dem regulären Ausdruck nicht auf die Groß- und Kleinschreibung geachtet.
Mit dem regulären Ausdruck können die Zeilen gefiltert werden, die in der Schleife berücksichtigt werden. Um den Inhalt einer Zeile in dem Ersetzungstext einzufügen kann das Attribut line verwendet werden. Zusätzlich steht auch noch das Attribut number zur Verfügung, das die Zeilennummer enthält.
%{LOOP_LINES,ignore_case:process,“^:.*activate_uc_object.*“:<tr><td>%(number)</td><td><p class=“code“>%(line)</p></td></tr>}
COUNT_LINES
Mit der Funktion COUNT_LINES können die Zeilen in einer mehrzeiligen Zeichenkette gezählt werden. Genauso wie bei LOOP_LINES können die Zeilen basierend auf einem regulären Ausdruck gefiltert werden.
%{COUNT_LINES[,<Option>[,<Option>...]]:<Attribut>[,<regulärer Ausdruck>]:<Ersetzungstext>}
Optionen:
ignore_case[=(true|false)]: Ist die Option gesetzt, wird bei der Filterung mit dem regulären Ausdruck nicht auf die Groß- und Kleinschreibung geachtet.
Für den Ersetzungstext steht das Attribut count zur Verfügung, um die Anzahl der Zeilen auszugeben.
%{COUNT_LINES,ignore_case:process,"^\:.*activate_uc_object.*":<p>Found %(count) object activations</p>}
DEFINE
Mit der Funktion DEFINE können Ersetzungen für Werte von Attributen definiert werden. Dies kann beispielsweise dafür genutzt werden, um Werte an das Ausgabeformat anzupassen. Die Definitionen müssen definiert werden, bevor Ersetzungen genutzt werden. Es empfiehlt sich die #HEADER- und #HEADER_RUNNABLE-Vorlagen zu nutzen.
%{DEFINE:<Wert>:<Ersetzungstext>}
Der <Wert> kann auch als regulärer Ausdruck angegeben werden. Die Ersetzung wird dann auf alle Werte angewendet, die auf den Ausdruck zutreffen. Daher sollten die Ausdrücke so genau wie möglich definiert werden, um eine Doppeldeutigkeit auszuschließen.
In dem Ersetzungstext kann der eigentliche Wert auch wieder eingefügt werden. Dafür kann wie bei der normalen Attributersetzung das Attribut value eingesetzt werden. Im Folgenden gibt es dazu einige Beispiele.
Um die bool’schen Werte true und false automatisch für die HTML-Ausgabe in eine Checkbox umzuwandeln können folgende Kommandos verwendet werden:
%{DEFINE:true:<input type="checkbox" name="" value="" checked disabled>}
%{DEFINE:false:<input type="checkbox" name="" value="" disabled>}
Hierbei wird der eigentliche Wert nicht benötigt. Um Zahlenwerte rechtsbündig anzuzeigen kann folgende Definition genutzt werden:
%{DEFINE:[0-9]+:<div style="text-align: right">%(value)</div>}
Mit dem Ausdruck %(value) wird hier der ursprüngliche Wert verwendet. Um bei Zeitstempeln die Zahlen kursiv darzustellen kann folgende Definition genutzt werden:
%{DEFINE:[0-9]{2}\:[0-9]{2}\:[0-9]{2}:<div style="text-align: right"><i>%(value/:.*//)</i>:<i>%(value/[^:]*://§§/:[^:]*//)</i>:<i>%(value/.*://)</i></div>}
CONST_ATTR
Die Funktion CONST_ATTR erlaubt es, Konstanten in dem aktuellen Kontext zu erstellen. Kontext ist hier als Gültigkeitsbereich zu verstehen, der sich auf die Bearbeitung einer Vorlage bezieht. Dabei können die Werte der Attribute auch auf andere existierende Attribute referenzieren.
%{CONST_ATTR:<Attributname>:<Wert>}
Im folgenden Beispiel werden die neuen Attribute width und height definiert und mit dem Wert einer Zahl belegt.
%{CONST_ATTR:width:330.0}
%{CONST_ATTR:height:150.0}
Ist ein anderes Attribut Teil des Wertes, dann werden die Attribute wie folgt nach der bekannten Syntax referenziert.
%{CONST_ATTR:my_x: My x is %(x)}
%{CONST_ATTR:my_y:My y is %(y)}
Wie in den Beispielen zu sehen ist, können Konstanten von verschiedenen Datentypen definiert werden.
SET_ATTR
Die Funktion SET_ATTR kann genutzt werden um neue Attribute hinzuzufügen oder existierende Attribute zu ändern. Die Arbeitsweise ähnelt der Funktion CONST_ATTR. Allerdings können Attribute, die mit dieser Funktion erstellt werden, auch in den Parametern anderer Funktionen genutzt werden wie in dem folgenden Beispiel zu sehen ist. Zusätzlich sind sie nur in dem jeweiligen Kontext gültig. Beispielsweise innerhalb einer LOOP_LIST-Funktion definierte Attribute können nicht außerhalb genutzt werden.
Attribute, die auf diese Art erzeugt werden, sind vom Typ eine Zeichenkette. Dies kann mit der Option TYPE beeinflusst werden. Es stehen folgende Typen zur Verfügung:
STRING
BOOLEAN
INTEGER
DOUBLE
%{SET_ATTR:subfolder:%(folder/.*\///)}
%{IF:subfolder==CONFIG:
<p>%(name) is a configuration object</p>
}
%{SET_ATTR,TYPE=DOUBLE:a_number:%{EVAL:js:3.14 * 42}}
EVAL
Die Funktion EVAL bietet die Möglichkeit auf andere Programmiersprachen zurückzugreifen und dabei auf die definierten Attribute zuzugreifen.
%{EVAL:<Interpreter>:<Statement>}
Als <Interpreter> wird aktuell js (Javascript) unterstützt. Damit können beliebige Javascript-Statements ausgewertet werden. Das Ergebnis wird in dem Ergebnistext anstelle des Aufrufs stehen. In dem folgenden Beispiel wird von dem Wert des Attribute x eins abgezogen. Das Ergebnis der Rechnung steht anschließend im Text.
%{EVAL:js:%(x)-1}
Es können auch beliebige andere Javascript-Statements gewählt werden. Beispielsweise eine Manipulation der Zeichenketten.
%{EVAL:js:"%(alias_or_name)".substring( 4 )}
%{EVAL:js:
var a = "%(alias_or_name)"
if ( a.startsWith( "PCK." ) )
a.substring( 4 )
else
a
}
SCRIPT
Die Funktion SCRIPT kann genutzt werden um mittels anderer Programmiersprachen Textsegmente für die zu Dokumentation zu erzeugen. Dabei stehen in dem Script alle Attribute, Konstanten und Definitionen zur Verfügung. Über eine zuvor definierte Variable kann das Textsegment definiert werden. Der Aufruf sieht wie folgt aus:
%{SCRIPT:<Sprache>:<Script>}
Als <Sprache> wird aktuell groovy (Groovy) unterstützt. Damit können beliebige Groovy-Scripte ausgeführt werden. In dem Script stehen folgende Variablen zur Verfügung:
$attributes
: In dieser Variable stehen alle Attribute zur Verfügung
$constants
: In dieser Variable sind alle Konstanten, die mit der Funktion CONST_ATTR definiert wurden
$defines
: In dieser Variable sind alle Definitionen für Wertersetzungen enthalten, die mit der Funktion DEFINE erzeugt wurden
$output
: Diese Variable enthält ein Objekt vom Typ StringBuilder. Mit Funktionen wie append kann die Ausgabe des Scriptes erweitert werden
Die folgenden Beispiele beziehen sich auf den Index und nutzen Attribute, die dort verfügbar sind. Im ersten Besipiel wird in die Ausgabedatei eine Liste der Objekte mit ihren Ordnern geschrieben.
%{SCRIPT:groovy:
for( object in $attributes.objects ) {
$output.append( "$object.name im Ordner $object.folder\n" );
}
}
Es können die in Groovy verfügbaren mehrzeiligen Zeichenketten genutzt werden, um auf einmal mehrere Zeilen in die Ausgabe zu hängen. Die Attribute können dabei direkt in der Zeichenkette aufgelöst werden.
%{SCRIPT:groovy:
$output.append( """\
### b4A Package $attributes.package_name
* A
* list
* of
* items
""" );
Konstanten, die in einem Block definiert wurden, können in anderen SCRIPT-Blöcke genutzt werden. Somit können Daten zwischen Blöcken ausgetauscht werden.
%{SCRIPT:groovy:
$constants.DEMO = "welcome to b4A"
}
%{SCRIPT:groovy:
$output.append( $constants.DEMO )
}
DATE
Die Funktion DATE ermöglicht es ein Datum im Text einzutragen. Dabei kann ausgehend von dem aktuellen Datum eine Abweichung definiert werden. Diese kann in Jahren, Monaten und Tagen angegeben werden. Die Datumsangaben werden immer im Format YYYY-MM-DD ausgegeben.
Um den aktuellen Tag auszugeben kann folgender Ausdruck genutzt werden.
%{DATE::}
Für den Tag vorher ist folgender Ausdruck zu nutzen.
%{DATE:-1d:}
Und für den Tag vor 13 Monaten und 5 Tagen kann folgender Ausdruck genutzt werden.
%{DATE:-1y-1m-5d:}
TIME
Die Funktion TIME funktioniert genauso wie die Funktion DATE, nur, dass diese sich auf einen Zeitpunkt bezieht, der im Format HH:MM:SS ausgegeben wird.
%{TIME::}
Für den Zeitpunkt, der in 3 Stunden, 5 Minuten und 46 Sekunden sein wird kann folgende Angabe genutzt werden.
%{TIME:3h5m46s:}
XML2ATTR
Bemerkung
Diese Funktion steht aktuell nur für die Module pm.DocBuilder und util.Mail zur Verfügung
Die Funktion XML2ATTR übersetzt den Inhalt von XML-Variablen in best4Automic Expression Attribute. Dabei werden die Elemente der XML-Dokumente in einzelne Attribute umgesetzt.
Das folgende XML-Dokument wird in ein Javascript-Objekt umgewandelt welches direkt in den b4A Expressions genutzt werden kann.
<?xml version="1.0" encoding="UTF-8"?>
<best4Automic version="4.4.0alpha1">
<pm>
<compliance>
<tests>
<test key="agent">
<title>Überprüfe Agenten</title>
<result>Succeeded</result>
<details>Die Agenten aller Objekte sind gültig</details>
</test>
<test key="folders">
<title>Überprüfe die Ordnerstruktur</title>
<result>Succeeded</result>
<details>Alle notwendigen Ordner existieren</details>
</test>
</tests>
</compliance>
</pm>
</best4Automic>
Aus dem Dokument wird folgendes Objekt erzeugt.
{
"best4Automic": {
"version": "4.4.0alpha1",
"pm": {
"compliance": {
"tests": {
"test": [
{
"result": "Succeeded",
"details": "Die Agenten aller Objekte sind gültig",
"title": "Überprüfe Agenten",
"key": "agent"
},
{
"result": "Succeeded",
"details": "Alle notwendigen Ordner existieren",
"title": "Überprüfe die Ordnerstruktur",
"key": "folders"
}
]
}
}
}
}
}
Um beispielsweise auf das Feld der Version zuzugreifen kann das Attribut best4Automic.version genutzt werden. Um die Ergebnisse der Tests auszuwerten kann die Funktion LOOP_LIST genutzt werden.
%{LOOP_LIST:best4automic.pm.compliance.tests.test:
The result of test %(key) is %(result)
}
Die Funktion unterstützt zwei Optionen. Mit der Option KEY kann der Key der XML-Variable ausgewählt werden aus dem das XML-Dokument ausgelesen wird. Wird der Key nicht angegeben, dann wird jeder Key der Variable gelesen und alle Dokumente als Attribute abgebildet. Dafür wird jedes der Dokumente in ein Objekt gekapselt, dass den Namen des Keys trägt.
Optional kann der Funktion die Option PREFIX mitgegeben werden. Diese Option definiert ein Attribut in dem das Ergebnis eingebettet wird.
%{XML2ATTR,PREFIX=xml,KEY=test:VARA.XML)}
Das Objekt sieht dann wie folgt aus.
{
"xml": {
"test": {
"best4Automic": {
"version": "4.4.0alpha1",
"pm": {
"compliance": {
"tests": {
"test": [
{
"result": "Succeeded",
"details": "Die Agenten aller Objekte sind gültig",
"title": "Überprüfe Agenten",
"key": "agent"
},
{
"result": "Succeeded",
"details": "Alle notwendigen Ordner existieren",
"title": "Überprüfe die Ordnerstruktur",
"key": "folders"
}
]
}
}
}
}
}
}
}