Search code examples
muledataweavemule4

Derive parent-child hierarchy from an array using DataWeave


I am using Mule 4.3 and Dataweave 2.x From database am getting following records example:

    [
  {
    "gp": "G1",
    "parent": "P1",
    "child": "C1"
  },
  {
    "gp": "G1",
    "parent": "P1",
    "child": "C2"
  },
  {
    "gp": "G2",
    "parent": "P1",
    "child": "C3"
  },
  {
    "gp": "G1",
    "parent": "G1",
    "child": "C4"
  }
]

Each element in array represents a row of data and each row has hierarchical data (Grandparent , Parent and Child data)

I need to generate the output in XML as below:

    <list>
 <genealogy>
        <code>G1</code>
        <hierarchy>
           <!-- here parent is not included in hierarchy as it has same value of grandparent -->
            <genealogy>
                <code>C4</code>
                <hierarchy/>
            </genealogy>
            <!-- here 2 instances of P1 have become One value -- >
            <genealogy>
                <code>P1</code>
                <hierarchy>
                    <genealogy>
                        <code>C1</code>
                        <hierarchy/>
                    </genealogy>
                    <genealogy>
                        <code>C2</code>
                        <hierarchy/>
                    </genealogy>
                </hierarchy>
            </genealogy>            
        </hierarchy>
    </genealogy>
    <genealogy>
        <code>G2</code>
        <hierarchy>
            <genealogy>
                <code>P1</code>
                <hierarchy>
                    <genealogy>
                        <code>C3</code>
                        <hierarchy/>
                    </genealogy>
                </hierarchy>
            </genealogy>            
        </hierarchy>
    </genealogy>
</list>

Here couple of challenges are:

  1. Its a 3 level Hierarchy where Grandparent needs to be the first element , within which we have the Parent(s) and within Parent Child(ren)
  2. If the parent ( Ex : G1 last object in input array ) has same value of grandparent then parent should be dropped in hierarchy ( Grandparent and then directly Child )

I am stumped how to do the needful in Dataweave and have tried things like groupBy , pluck etc but am not able to get desired result


Solution

  • I have built a solution. Somehow, making this generic was more easier then make it specifically for 3 levels.

    It is a bit complicated, I have explained the logic in comments within the script

    %dw 2.0
    output application/xml
    // hierarchy's structure. If, lets say you add a "grand child" it should work. (haven't tested this though)
    var hierarchy = {
        gp: {
            parent: {
                child: null
            }
        }
    }
    fun getDirectGeanologies(records, hierarchyStructure) = do {
        var topLevel = keysOf(hierarchyStructure)[0] as String
        var secondLevel = keysOf(hierarchyStructure[topLevel])[0]
        ---
        (records groupBy $[topLevel])
            mapObject ((level1Childs, code) -> 
                genealogy: {
                    code: code,
                    hierarchy:
                        if(secondLevel != null) // If there are no more childs, do nothing.
                            (level1Childs groupBy ((item) -> item[secondLevel] ~= code) // This is to handle when parent = gp
                                mapObject ((value, hasSameParent) -> 
                                    // If parent = gp, we want to skip parent and link directly to child
                                    if(hasSameParent as Boolean) getDirectGeanologies(value, hierarchyStructure[topLevel][secondLevel]) 
                                    // recurrsively call the function with child records and going down the hierarchyStructure by one
                                    else getDirectGeanologies(value, hierarchyStructure[topLevel]) 
                            ))
                        else {}
                }
            )
    }
    ---
    list: getDirectGeanologies(payload,hierarchy)