Macro Use Case: Recursive Operations

Here’s an example of a macro that deletes an sfdcDigest node. It also deletes the digest node and all other nodes that depend on that node.

This macro deletes the specified node and dynamically queries the JSON document to delete each dependency of those nodes.

Consider the simplified JSON below. To delete ‘node3’ and its dependencies, the result should delete: node3, node4, node5 (depends on node4), node6 (depends on node5), node7, node8, node9.

Example 

Example JSON

1{
2    "node1": { },
3    "node2": {
4        "dependsOn": "node1"
5    },
6    "node3": {
7        "dependsOn": "node2"
8    },
9    "node4": {
10        "dependsOn": "node3"
11    },
12    "node5": {
13        "dependsOn": "node4"
14    },
15    "node6": {
16        "dependsOn": "node5"
17    },
18    "node7": {
19        "dependsOn": "node3"
20    },
21    "node8": {
22        "dependsOn": "node3"
23    },
24    "node9": {
25        "dependsOn": "node3"
26    }
27}

Example 

Without Macro

Without using a macro (and associated enhancements), nodes would have to be deleted individually.

1{
2    "actions": [
3        {
4            "action": "delete",
5            "path": "$.node3"
6        },
7        {
8            "action": "delete",
9            "path": "$.node4"
10        },
11       {
12            "action": "delete",
13            "path": "$.node5"
14        },
15       {
16            "action": "delete",
17            "path": "$.node6"
18        },
19        {
20            "action": "delete",
21            "path": "$.node7"
22        },
23        {
24            "action": "delete",
25            "path": "$.node8"
26        },
27        {
28            "action": "delete",
29            "path": "$.node9"
30        }
31    ]
32}

This code is rigid and difficult to maintain because rules would need to be modified as node dependencies are added and removed from the JSON payload.

Example 

Macro Source

1{

2    "namespace": "macroRecursion",
3 
   "definitions": [

4        {

5            "name": "deleteNodeAndDependencies",
6 
           "description": "Delete a node and its dependencies.  Returns an array of json paths of all the nodes that were deleted.",
7 
           "parameters": [

8                "nodeName"

9            ],
10 
           "actions": [

11                {"action": "eval", "key": "fullNodePath",  "value": "$.${p.nodeName}" },
12 
               {"action": "eval", "key": "dependencies",  "value": "${macroRecursion:getDependents(p.nodeName)}"},
13 
               {

14                  "action": "eval",
15 
                 "value": "${array:forEach(Rules.Eval.dependencies, '${macroRecursion:deleteNodeAndDependencies(macroRecursion:deleteSingleNodeByFullJsonPath(var))}')}"

16                },
17 
                {

18                    "action": "eval",
19 
                   "value": "${macroRecursion:deleteSingleNodeByFullJsonPath(Rules.Eval.fullNodePath)}"

20                }

21            ]

22        },
23 
        {

24            "name": "deleteSingleNodeByFullJsonPath",
25 
           "description": "Deletes a node by full json path.",
26 
           "parameters": [

27                "fullJsonPath"

28            ],
29 
           "actions": [

30               {"action": "eval", "key": "pathSegments",
31  "value": "${string:match(p.fullJsonPath,'\\\\[\\'(.*?)\\'\\\\]')}"},
32 
              { "action": "delete",  "path": "${p.fullJsonPath}"}

33            ],
34 
           "returns": "${array:last(Rules.Eval.pathSegments)}"

35        },
36 
        {

37            "name": "getDependents",
38 
           "description": "Returns the full json path to search results",
39 
           "parameters": [

40                "nodeName"

41            ],
42 
           "actions": [

43               { "action": "eval", "key": "searchString", "value": "$.*[?(@.dependsOn=='${p.nodeName}')]"},
44 
              { "action": "eval", "key": "paths", "value": "${json:searchPaths(Rules.Eval.searchString)}"}

45            ],
46 
           "returns": "${Rules.Eval.paths}"

47        }

48    ]
}

Example 

Rule Calling the Macro

1{
2    "rules": [
3        {
4            "name": "Recursively delete node3 and dependencies",
5            "actions": [
6                {"action": "eval", "value": "${macroRecursion:deleteNodeAndDependencies('node3')}" }
7            ]
8        }
9    ]
10}