Structure Map composer - FML Notation

en

TL;TR

 Click here to view
  1. Find target objects.
  2. Flatmap target fields that have input connection.
    given:
    Model:
    # AModel (target)
      - field-1
      - field-2
      - field-3
    
    Rules:
      Rule.x -> field-1
      Rule.y -> field-3   
    
    Expected output:
    [[AModel, field-1], [AModel, field-3]]
    
  3. Iterate target fields.
  4. Create sub FML for each field.
  5. Sort objects (topological sorting) result into the list.
  6. Select the first and last element in the list, and begin “moving inwards”.
  7. Every iteration is a FML rule.
  8. Every iteration MUST have source and target objects
    1. Create source and target objects
    2. Find rules in between.
  9. Nest iteration rules. Not the in between rules, but 7. rules

Preparation

The first step is to find all the target objects, since the primary goal of FML transformations is to correctly fill the fields of the target objects with the transformed values

For each target object, we find the fields to which connections are drawn, whether through direct copying, sub-object creation, or connections from a rule’s output. It’s important to note that not all fields of the target object necessarily have input connections from other objects.

For each such field, a sub-FML is created, containing only the objects, rules, and connections necessary to populate the corresponding field of the target object. There are no unnecessary objects or rules in the sub-FML. It describes all the connections and objects required to compose the result and set it in the target object field.

 View sub-FML visualization

Next, with the sub-FML in hand, topological sorting is performed. Topological sorting builds a correct sequence of actions, taking into account the dependencies between them.

After sorting, two lists are produced:

  • List A, consisting of source/element objects, where the first element is source, forming a chain of objects from left to right.
  • List B, consisting of target/object objects, where the first element is target, forming a chain of objects from right to left.

In this way, we determine the order and the number of levels that need to be created/visited as a result of the algorithm’s operation. The maximum depth corresponds to the greater of the two lists’ lengths (max(A.length, B.length)), and it equals the maximum number of iterations required to traverse all levels.

Composing the FML

With two lists and indices i and j that indicate positions in lists A and B respectively, we can start traversing and composing FML rules. Before each iteration, both indices are incremented. If there’s no element at the index in the list for which this index is used, the index decrements to the previous value. This ensures that while going through all levels, we always have the left/source and right/target values.

In this example, with each subsequent iteration, the source object remains A. Simultaneously, with an increase in the index j, the target object becomes the next object in list B.

Objects

Each iteration to the next level, in the context of FML, means the creation of a new FML rule. Every FML rule requires source and target objects. As mentioned earlier, at each iteration, either a new element is selected, or the previous one is used.

If a new element is selected, in the FML context, we must either choose a sub-element (ctx.field as f1) or create a new resource (create('Resource') as r1) to which values will be assigned later.

Rules

Once the source and target objects have been created/selected, and we know which objects we are in the context of, we can find all the rules that can be created within this context.

At the moment we have two types of rules:

  • Direct - copying a value from the source object to the target object.
  • Regular - a square with the type rule in the FML editor, from which a connection is drawn to the field of the target object.

Because there are two types of rules, they are created differently. Creating FML rules for direct copying is relatively straightforward. In the current context, all connections between the source and target objects are found, and the corresponding FML copy rule is created.

For the other type of rule, a recursive search is run for each target object field, and a chain of rules is created that lead to the creation or assignment of a value to that field. When the chain is found, a rule handler is selected for each rule within the chain.

There are quite a few rule handlers; there is a basic one, but if it is necessary to handle a rule in another way, for example append, to combine several source objects into one value, then a separate handler for append rule is created.

Example of different rule types

As a result, we get a list of all rules between objects in the current iterated context, that are added as a sub-rule to the main FML rule.


Page last modified: Oct 30 2023 at 03:27 PM.