Skip to main content

Conditional Mapping with Branches

Use branches to apply different mappings based on conditions:
val mapping = Platymap.flow("customer")
    .to("processedCustomer")
    .branch()
        .when { source -> (source as? Map<*, *>)?.get("age") as? Int ?: 0 >= 18 }
        .then()
            .map("name").to("adultName")
            .map("status").transform { "adult" }.to("customerType")
        .endBranch()
        .otherwise()
            .map("name").to("minorName")
            .map("status").transform { "minor" }.to("customerType")
        .endBranch()
    .end()
    .build()

Collection Processing with ForEach

Process collections with the forEach feature:
val mapping = Platymap.flow("order")
    .to("processedOrder")
    .map("orderId").to("id")
    .forEach("items")
        .`as`("item")
        .create("processedItems")
            .map("$item.name").to("productName")
            .map("$item.quantity").to("qty")
            .map("$item.price").to("unitPrice")
        .end()
    .end()
    .build()
Note: In Kotlin, as is a reserved keyword for type casting. To use it as a method name, we need to surround it with backticks: `as`.

Bulk Mapping

Map multiple fields at once with pattern matching:
val mapping = Platymap.flow("customer")
    .to("user")
    .mapAll("personal.*")
        .to("profile")
        .end()
    .build()
This maps all fields under “personal” to the “profile” object in the target. For example, “personal.firstName” becomes “profile.firstName”. You can exclude specific fields:
val mapping = Platymap.flow("customer")
    .to("user")
    .mapAll("personal.*")
        .excluding("personal.ssn", "personal.password")
        .to("profile")
        .end()
    .build()
Or include only specific fields:
val mapping = Platymap.flow("customer")
    .to("user")
    .mapAll("personal.*")
        .including("personal.firstName", "personal.lastName")
        .to("profile")
        .end()
    .build()

Nesting Flat Fields

The nest operation transforms flat fields into nested structures:
val mapping = Platymap.flow("flatCustomer")
    .to("nestedCustomer")
    .nest("address.*")
        .asObject("address")
        .to("contact")
    .build()
This transforms:
{
    "address.street": "123 Main St",
    "address.city": "Anytown",
    "address.zip": "12345"
}
Into:
{
    "contact": {
        "address": {
            "street": "123 Main St",
            "city": "Anytown",
            "zip": "12345"
        }
    }
}
You can also create a collection of objects:
val mapping = Platymap.flow("flatCustomer")
    .to("nestedCustomer")
    .nest("phones.*")
        .asCollection("phoneNumbers")
        .to("contact")
    .build()
This transforms:
{
    "phones.home": "555-1234",
    "phones.work": "555-5678",
    "phones.mobile": "555-9012"
}
Into:
{
    "contact": {
        "phoneNumbers": [
            { "name": "home", "value": "555-1234" },
            { "name": "work", "value": "555-5678" },
            { "name": "mobile", "value": "555-9012" }
        ]
    }
}

Flattening Nested Structures

The flatten operation does the opposite of nesting, transforming nested structures into flat fields:
val mapping = Platymap.flow("nestedCustomer")
    .to("flatCustomer")
    .flatten("contact.address")
        .withPrefix("address_")
        .to("")
        .end()
    .build()
This transforms:
{
    "contact": {
        "address": {
            "street": "123 Main St",
            "city": "Anytown",
            "zip": "12345"
        }
    }
}
Into:
{
    "address_street": "123 Main St",
    "address_city": "Anytown",
    "address_zip": "12345"
}

Custom Functions

You can define and use custom functions for more complex transformations:
// Register a custom function
FunctionRegistry.register(
    MapFunction("formatPhoneNumber", listOf("phone")) { args ->
        val phone = args[0]?.toString() ?: ""
        if (phone.length == 10) {
            "(${phone.substring(0, 3)}) ${phone.substring(3, 6)}-${phone.substring(6)}"
        } else {
            phone
        }
    }
)

// Use the function in a mapping
val mapping = Platymap.flow("customer")
    .to("user")
    .map("phone").transform { phone ->
        FunctionRegistry.call("formatPhoneNumber", phone)
    }.to("formattedPhone")
    .build()

Type-Safe Mappings for Java Beans

For Java beans, you can use type-safe mappings:
data class Customer(val id: Long, val name: String, val email: String)
data class UserDTO(var userId: Long = 0, var fullName: String = "", var contactEmail: String = "")

val mapping = Platymap
    .flow(Customer::class.java)
    .to(UserDTO::class.java)
    .map { it.id }.to { dto, value -> dto.userId = value }
    .map { it.name }.to { dto, value -> dto.fullName = value }
    .map { it.email }.to { dto, value -> dto.contactEmail = value }
    .build()

val customer = Customer(1, "John Doe", "[email protected]")
val userDTO = mapping.execute(customer)