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:
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
}
}
-
Streamlined Steps:
- Each step of the logic (filtering products, sending the request, processing the response, and building the final result) is concise and isolated.
-
Functional Programming:
- Used functional programming constructs such as
Stream
,Collectors.toMap
, andOptional
for null-safety and concise mappings.
- Used functional programming constructs such as
-
Null-Safe Handling of API Responses:
- Used
Optional.ofNullable
to handle cases whereresponses
might benull
and defaulted to an empty stream if no responses are returned.
- Used
-
Simplified Mapping of Responses:
- Combined the mapping of
wknToRtFieldMap
and the final result generation into two compact and readable transformation pipelines.
- Combined the mapping of
-
Avoided Side Effects:
- All transformations are pure functions with no side effects, making the code easier to debug and test.
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"
.
We create a list of Query
objects, one for each wkn
, and send the payload to the API endpoint.
The API response is mapped to a Map<String, Double>
where:
- The key is the
wkn
(fromdataobject_id.id
). - The value is the
RT_FIELD_%
(fromdata
).
If the API returns null
, we handle it gracefully using Optional
and default to an empty map.
Finally, iterate over the wknToDlcIdMap
. For each wkn
, retrieve:
- The
RT_FIELD_%
value (defaulting to0.0
if missing). - The corresponding
dlcId
.
The result is a list of DlcCoeffImpl
objects.
-
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 } } ]
[
new DlcCoeffImpl(0.028561506832830933, "DLC_123"),
new DlcCoeffImpl(0.035, "DLC_456")
]
- 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.