Rekursion
Normalerweise wird ein Literal direkt nach seiner Verarbeitung an das nächste
command weitergeleitet. Es ist durch eine spezielle Syntax - ein führendes
@
im Namen - allerdings möglich, seine Werte bis zum Prozessierungsende des
Datensatzes im Cache zu halten:
<data source="eingabename" name="@loop"/>
<data source="@loop" name="ausgabename"/>
Bei der Verwendung dieser Syntax sind einige Dinge zu beachten:
Literale im Cache müssen bei jeder Wiederverwendung umbenannt werden, da sonst eine unendliche Schleife entsteht (aka ein
StackOverflowError
). Das heisst also, dass beispielsweise folgendes Konstrukt nicht möglich ist:<data source="eingabename" name="@loop"/> <data source="@loop"/> <!-- name-Attribut fehlt! -->
Ein literales
@
als erstes Zeichen eines Feldnamens ist möglich, wenn es durch einen vorangehenden\
seiner speziellen Bedeutung “beraubt” wird (\
erscheint anschliessend nicht mehr im Namen).\
ist nicht notwendig, wenn sich das betreffende Literal bzw. der betreffende collector innerhalb eines Eltern-collectors befindet (siehe dazu auch den nächsten Punkt).Literale bzw. collectors, welche innerhalb eines anderen collectors in die Rekursion geschickt werden, werden gleichzeitig immer auch literal weitergeleitet (also bspw. als
("@feldname": "feldwert")
). Da dieses Verhalten ist in der Regel nicht gewünscht, deshalb sollten Rekursionen grundsätzlich ausserhalb von Eltern-collectors definiert werden.
Durch Rekursion lassen sich verschiedene Probleme lösen, so:
- Eine initiale Verarbeitung eines Literals lässt sich zentral definieren, die Ausgabe lässt sich an verschiedenen Orten im Morph wiederverwenden (beispielsweise in einem collector)
- Das Ergebnis eines collector, der vor Ende des Datensatzes “geflusht” werden muss, soll in einem anderen collector genutzt werden
Allerdings gibt es auch Einschränkungen. Der gecachte Literal verhält sich aus Sicht der ihn aufrufen Morph-Definition wie ein Iterator: Jeder seiner Werte kann nur einmal wiederverwendet werden und geht dann verloren. Es ist zudem nicht möglich, einen gecachten Literal gestaffelt abzuarbeiten.
Eingabe
{ litA: wertAA, litA: wertAB, litB: wertBA, litB: wertBB }
Morph-Definitionen
<rules>
<data source="litA" name="@loop"/>
<entity name="entAB" flushWith="litB" reset="true">
<data source="@loop" name="litA"/>
<data source="litB" name="litB"/>
</entity>
</rules>
Ausgabe
{ entAB { litA: wertAA, litA: wertAB, litB: wertBA }, entAB { litB: wertBB } }