20250101 ‐ manipulating result mapping from payload - cywongg/2025 GitHub Wiki

Chrome Certainly! A clean code approach with functional programming in Java can simplify the logic and make the code more intuitive. Here’s how you can achieve the same functionality in a simpler, more readable way:


Simplified Code with Clean Code and Functional Programming

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Value;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

public class Example {

    private final RestTemplate restTemplate = new RestTemplate();

    public Collection<DlcCoeffImpl> getDlcCoeff() {
        // Step 1: Filter products and map to `wkn` and `dlcId`
        Map<String, String> wknToDlcIdMap = productService.getProducts().values().stream()
            .filter(product -> "SGX".equals(product.getExchangeId())) // Ensure `ExchangeId` is SGX
            .filter(product -> !product.isCompetitor())              // Filter out competitors
            .collect(Collectors.toMap(
                Product::getIcomWKN, // Key: `wkn`
                Product::getid  // Value: `dlcId`
            ));

        // Step 2: Create and send JSON payload
        String url = "http://your-api-endpoint/read/get_data_objects";
        List<Query> queries = wknToDlcIdMap.keySet().stream()
            .map(wkn -> new Query("EXTERNAL_RIC", wkn))
            .toList();

        Response[] responses = restTemplate.postForObject(url, queries, Response[].class);

        // Step 3: Map API responses to `wkn -> RT_FIELD_%`
        Map<String, Double> wknToRtFieldMap = Optional.ofNullable(responses)
            .map(Arrays::stream)
            .orElseGet(Stream::empty)
            .collect(Collectors.toMap(
                response -> response.getDataObjectId().getId(),    // Key: `wkn` from API response
                response -> response.getData().getRtFieldPercent() // Value: `RT_FIELD_%`
            ));

        // Step 4: Build the final result
        return wknToDlcIdMap.entrySet().stream()
            .map(entry -> new DlcCoeffImpl(
                wknToRtFieldMap.getOrDefault(entry.getKey(), 0.0), // Map `wkn` to `RT_FIELD_%`
                entry.getValue()                                      // `dlcId`
            ))
            .toList();
    }

    @Value
    @AllArgsConstructor
    @NoArgsConstructor
    private static class Query {
        @JsonProperty("datatype_id")
        String datatypeId;

        @JsonProperty("id")
        String id;
    }

    @Value
    @AllArgsConstructor
    @NoArgsConstructor
    private static class Response {
        @JsonProperty("dataobject_id")
        DataObjectId dataObjectId;

        @JsonProperty("data")
        Data data;
    }

    @Value
    @AllArgsConstructor
    @NoArgsConstructor
    private static class DataObjectId {
        @JsonProperty("datatype_id")
        String datatypeId;

        @JsonProperty("id")
        String id; // The `wkn` (identifier)
    }

    @Value
    @AllArgsConstructor
    @NoArgsConstructor
    private static class Data {
        @JsonProperty("RT_FIELD_%")
        double rtFieldPercent; // The field we're interested in
    }

    @Value
    @AllArgsConstructor
    @NoArgsConstructor
    private static class DlcCoeffImpl {
        @JsonProperty("RT_YIELD_S")
        private double rtYieldS;

        private String dlcId; // Maps to the `dlcId` of the product
    }
}

Key Improvements for Clean Code

  1. Streamlined Steps:

    • Each step of the logic (filtering products, sending the request, processing the response, and building the final result) is concise and isolated.
  2. Functional Programming:

    • Used functional programming constructs such as Stream, Collectors.toMap, and Optional for null-safety and concise mappings.
  3. Null-Safe Handling of API Responses:

    • Used Optional.ofNullable to handle cases where responses might be null and defaulted to an empty stream if no responses are returned.
  4. Simplified Mapping of Responses:

    • Combined the mapping of wknToRtFieldMap and the final result generation into two compact and readable transformation pipelines.
  5. Avoided Side Effects:

    • All transformations are pure functions with no side effects, making the code easier to debug and test.

Explanation of Steps

Step 1: Map wkn to dlcId

Here, we build a mapping of wkn (retrieved from product.getIcomWKN()) to dlcId (retrieved from product.getid()), filtering out competitors and ensuring the ExchangeId is "SGX".

Step 2: Create and Send Queries

We create a list of Query objects, one for each wkn, and send the payload to the API endpoint.

Step 3: Map API Responses

The API response is mapped to a Map<String, Double> where:

  • The key is the wkn (from dataobject_id.id).
  • The value is the RT_FIELD_% (from data).

If the API returns null, we handle it gracefully using Optional and default to an empty map.

Step 4: Build Final Result

Finally, iterate over the wknToDlcIdMap. For each wkn, retrieve:

  • The RT_FIELD_% value (defaulting to 0.0 if missing).
  • The corresponding dlcId.

The result is a list of DlcCoeffImpl objects.


Example Input and Output

Input:

  • Products:

    [
        new Product("EXMAPLE", "SGX", "DLC_123", false), // wkn = EXMAPLE, dlcId = DLC_123
        new Product("XSES_95DW_240322", "SGX", "DLC_456", false)  // wkn = XSES_95DW_240322, dlcId = DLC_456
    ]
  • API Response:

    [
        {
            "dataobject_id": {
                "datatype_id": "EXTERNAL_RIC",
                "id": "EXMAPLE"
            },
            "data": {
                "RT_FIELD_%": 0.028561506832830933
            }
        },
        {
            "dataobject_id": {
                "datatype_id": "EXTERNAL_RIC",
                "id": "XSES_95DW_240322"
            },
            "data": {
                "RT_FIELD_%": 0.035
            }
        }
    ]

Output:

[
    new DlcCoeffImpl(0.028561506832830933, "DLC_123"),
    new DlcCoeffImpl(0.035, "DLC_456")
]

Advantages of This Approach

  • Readability: Each step is a self-contained transformation, making the code easier to follow.
  • Null Safety: Handled potential null responses from the API gracefully.
  • Maintainability: The code is concise and modular, making it easier to refactor or extend.
  • Functional Programming: Avoided imperative constructs like loops and mutable variables, increasing clarity and reducing potential bugs.

This functional approach strikes a balance between simplicity, performance, and maintainability.

⚠️ **GitHub.com Fallback** ⚠️