WeRun Consulting

In this Groovy scripting tutorial, we’ll explore how to manage UDAs in EPM Cloud for dynamic member updates.

Back to Home

Managing UDAs in EPM Cloud with Groovy: A Cheatsheet

Published: January 12, 2025 | By WeRun Consulting

User-Defined Attributes (UDAs) in EPM Cloud are custom tags assigned to members for reporting, calculations, or business logic. Groovy scripting lets you programmatically manage UDAs—adding, removing, replacing, or editing them—via the Dimension and Member classes. This cheatsheet provides detailed examples, building on our DataGrid Builders guide.

Adding UDAs to Members

Purpose: Assign a new UDA to a member to tag it for specific processes (e.g., marking regions as "HighPriority"). UDAs are managed through the member’s properties in a Map.

Key Methods:

Add "HighPriority" to Active Regions
Tag active regions with a "HighPriority" UDA for urgent forecasting.
Cube cube = operation.application.getCube("Plan1")
Dimension regionDim = operation.application.getDimension("Region", cube)
List activeRegions = ["East", "West"]
activeRegions.each { String regionName ->
    Member member = regionDim.getMember(regionName)
    if (member) {
        Map memberMap = member.toMap()
        String currentUda = memberMap.get("UDA") ?: ""
        List udaList = new ArrayList()
        if (currentUda) {
            udaList.addAll(currentUda.split(","))
        }
        if (!udaList.contains("HighPriority")) {
            udaList.add("HighPriority")
            memberMap.put("UDA", udaList.join(","))
            regionDim.saveMember(memberMap as Map)
            println "Added HighPriority to $regionName"
        } else {
            println "$regionName already has HighPriority UDA"
        }
    } else {
        println "Member $regionName not found"
    }
}
                
Logic: Iterates over regions, retrieves each Member, appends "HighPriority" to its UDA list if not present, and saves.
Tip: Check member existence to avoid null errors.
Use Case: Flag regions for priority reporting in dashboards.

Removing UDAs from Members

Purpose: Delete a UDA from a member when it’s no longer applicable (e.g., removing "Obsolete" from updated products).

Key Methods:

Remove "Obsolete" from Updated Products
Clear the "Obsolete" UDA from products after a refresh.
Cube cube = operation.application.getCube("Sales")
Dimension productDim = operation.application.getDimension("Product", cube)
List updatedProducts = ["ProdA", "ProdB"]
updatedProducts.each { String prodName ->
    Member member = productDim.getMember(prodName)
    if (member) {
        Map memberMap = member.toMap()
        String currentUda = memberMap.get("UDA") ?: ""
        List udaList = new ArrayList()
        if (currentUda) {
            udaList.addAll(currentUda.split(","))
        }
        if (udaList.contains("Obsolete")) {
            udaList.remove("Obsolete")
            memberMap.put("UDA", udaList.isEmpty() ? "" : udaList.join(","))
            productDim.saveMember(memberMap as Map)
            println "Removed Obsolete from $prodName"
        } else {
            println "$prodName does not have Obsolete UDA"
        }
    } else {
        println "Member $prodName not found"
    }
}
                
Logic: Checks if "Obsolete" exists in the member’s UDAs, removes it if present, and saves.
Tip: Handle empty UDA list with a conditional to avoid saving empty strings unnecessarily.
Use Case: Update product metadata post-revision.

Replacing UDAs on Members

Purpose: Swap all existing UDAs with a new set or replace specific UDAs conditionally.

Key Methods:

Replace UDAs with "Approved" Status
Update a scenario’s UDAs to reflect final approval, overwriting all existing UDAs.
Cube cube = operation.application.getCube("Plan1")
Dimension scenarioDim = operation.application.getDimension("Scenario", cube)
String scenarioName = "Q1Plan"
Member member = scenarioDim.getMember(scenarioName)
if (member) {
    Map memberMap = member.toMap()
    String currentUda = memberMap.get("UDA") ?: ""
    List udaList = new ArrayList()
    if (currentUda) {
        udaList.addAll(currentUda.split(","))
    }
    println "Old UDAs: $udaList"
    udaList.clear()
    udaList.add("Approved")
    memberMap.put("UDA", udaList.join(","))
    scenarioDim.saveMember(memberMap as Map)
    println "New UDAs: $udaList"
} else {
    println "Member $scenarioName not found"
}
                
Logic: Logs current UDAs, clears them, adds "Approved", and saves, overwriting all previous UDAs.
Tip: Use logging to verify changes before and after.
Use Case: Finalize a planning scenario’s status.
Replace "Temporary" with "Permanent" UDA
Swap "Temporary" for "Permanent" in a member’s UDAs while preserving others, using a Map approach.
Cube cube = operation.application.getCube("Plan1")
Dimension entityDim = operation.application.getDimension("Entity", cube)
String entityName = "Branch101"
Member member = entityDim.getMember(entityName)
def memberUDA = "Temporary"
def memberMap = member.toMap()
String currUDA = memberMap["UDA"]
if (currUDA?.contains(memberUDA)) {
    List UDAs = ((String)memberMap["UDA"])?.split(",")*.trim() as List
    UDAs -= ["Temporary"]
    UDAs += ["Permanent"]
    memberMap["UDA"] = UDAs.join(", ")
    Member updatedMember = entityDim.saveMember(memberMap, DynamicChildStrategy.DYNAMIC_IF_AVAILABLE)
    println "Updated UDAs for $entityName: ${updatedMember.getUdas()}"
}
                
Logic: Converts the member to a Map, checks for "Temporary" in the UDA string, splits it into a List, removes "Temporary," adds "Permanent," joins back to a string, and saves with DYNAMIC_IF_AVAILABLE.
Tip: Use ?. to safely handle null UDAs.
Use Case: Update branch status from temporary to permanent.

Editing UDAs (Conditional Add/Remove)

Purpose: Modify UDAs based on conditions (e.g., toggle "Active" to "Inactive" for customers).

Key Methods:

Toggle Customer Activity Status
Switch customer UDAs between "Active" and "Inactive" based on sales data.
Cube cube = operation.application.getCube("Revenue")
Dimension customerDim = operation.application.getDimension("Customer", cube)
String customerName = "Cust123"
Member member = customerDim.getMember(customerName)
if (member) {
    Map memberMap = member.toMap()
    String currentUda = memberMap.get("UDA") ?: ""
    List udaList = new ArrayList()
    if (currentUda) {
        udaList.addAll(currentUda.split(","))
    }
    boolean hasSales = true // Replace with actual sales check logic
    if (hasSales && udaList.contains("Inactive")) {
        udaList.remove("Inactive")
        udaList.add("Active")
        memberMap.put("UDA", udaList.join(","))
        customerDim.saveMember(memberMap as Map)
        println "$customerName set to Active"
    } else if (!hasSales && udaList.contains("Active")) {
        udaList.remove("Active")
        udaList.add("Inactive")
        memberMap.put("UDA", udaList.join(","))
        customerDim.saveMember(memberMap as Map)
        println "$customerName set to Inactive"
    }
} else {
    println "Member $customerName not found"
}
                
Logic: Checks current UDAs and a condition (e.g., sales). Swaps "Inactive" to "Active" or vice versa as needed.
Tip: Integrate with DataGridBuilder for dynamic sales checks.
Use Case: Maintain customer status based on activity.

Key Considerations

- Permissions: Ensure your Groovy rule has metadata update rights in EPM Cloud.
- Validation: UDAs must be alphanumeric, no spaces.
- Performance: Batch saves with dimension.saveMembers(members) for multiple updates.

Tips and Tricks

Check Before Save
Verify changes to avoid unnecessary commits.
Member member = dimension.getMember("Test")
Map memberMap = member.toMap()
String currentUda = memberMap.get("UDA") ?: ""
List udaList = new ArrayList()
if (currentUda) {
    udaList.addAll(currentUda.split(","))
}
if (!udaList.contains("NewUDA")) {
    udaList.add("NewUDA")
    memberMap.put("UDA", udaList.join(","))
    dimension.saveMember(memberMap as Map)
}
                
Log Changes
Track UDA updates for debugging.
Member member = dimension.getMember("Test")
Map memberMap = member.toMap()
String currentUda = memberMap.get("UDA") ?: ""
List udaList = new ArrayList()
if (currentUda) {
    udaList.addAll(currentUda.split(","))
}
println "Before: $udaList"
udaList.add("Test")
memberMap.put("UDA", udaList.join(","))
dimension.saveMember(memberMap as Map)
println "After: $udaList"
                

Disclaimer

This blog reflects my personal insights, written independently of my employer or Oracle. EPM Cloud features evolve, so verify with Oracle’s official documentation for the latest details.

Comments