GettingStarted With123
GettingStarted With123

Reputation: 427

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

Upvotes: 1

Views: 185

Answers (1)

Harshank Bansal
Harshank Bansal

Reputation: 3262

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)

Upvotes: 2

Related Questions