removed warnings

This commit is contained in:
Andreas Isler
2026-06-12 10:58:35 +02:00
parent 1d07485746
commit 2fd873741b
7 changed files with 115 additions and 158 deletions
@@ -44,7 +44,7 @@ public class JsonUtils {
}
public Map<String, Object> convertJsonNodeToMap(JsonNode jsonNode) {
return objectMapper.convertValue(jsonNode, new TypeReference<Map<String, Object>>() {});
return objectMapper.convertValue(jsonNode, new TypeReference<>() {});
}
public Map<String, Object> flatten(Object payload) {
@@ -57,7 +57,7 @@ public class JsonUtils {
public Map<String, Object> unflatten(Map<String, Object> flatVars) {
try {
return objectMapper.readValue(JsonUnflattener.unflatten(flatVars), Map.class);
return objectMapper.readValue(JsonUnflattener.unflatten(flatVars), new TypeReference<>() {});
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
@@ -73,7 +73,7 @@ public class JsonUtils {
}
public Map<String, Object> convertObjectNodeToMap(ObjectNode objectNode) {
return objectMapper.convertValue(objectNode, new TypeReference<Map<String, Object>>() {});
return objectMapper.convertValue(objectNode, new TypeReference<>() {});
}
public ObjectNode getEmptyObjectNode() {
@@ -2,48 +2,5 @@ package com.customer.work.model;
import java.util.List;
public class EmailDto {
private String subject;
private List<String> receiverList;
private String content;
private Object contentRaw;
public EmailDto(String subject, List<String> receiverList, String content, Object contentRaw) {
this.subject = subject;
this.receiverList = receiverList;
this.content = content;
this.contentRaw = contentRaw;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public List<String> getReceiverList() {
return receiverList;
}
public void setReceiverList(List<String> receiverList) {
this.receiverList = receiverList;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Object getContentRaw() {
return contentRaw;
}
public void setContentRaw(Object contentRaw) {
this.contentRaw = contentRaw;
}
public record EmailDto(String subject, List<String> receiverList, String content, Object contentRaw) {
}
@@ -1,6 +1,5 @@
package com.customer.work.model;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -95,25 +94,23 @@ public class FlowableExcelMapper {
}
protected Object parseCellValue(String type, String cellValue) {
switch (cellValue) {
case "__NULL": return null;
case "__N_A": return "__N_A";
}
switch (type) {
case "String":
switch (cellValue) {
case "__EMPTY": return "";
case "__BLANK": return " ";
default: return cellValue;
}
case "Boolean": return Boolean.parseBoolean(cellValue);
case "Integer": return Integer.parseInt(cellValue);
case "Long": return Long.parseLong(cellValue);
case "Double": return Double.parseDouble(cellValue);
case "Date": return parseDate(cellValue);
default:
throw new IllegalArgumentException("Variable type not supported: " + type);
}
return switch (cellValue) {
case "__NULL" -> null;
case "__N_A" -> "__N_A";
default -> switch (type) {
case "String" -> switch (cellValue) {
case "__EMPTY" -> "";
case "__BLANK" -> " ";
default -> cellValue;
};
case "Boolean" -> Boolean.parseBoolean(cellValue);
case "Integer" -> Integer.parseInt(cellValue);
case "Long" -> Long.parseLong(cellValue);
case "Double" -> Double.parseDouble(cellValue);
case "Date" -> parseDate(cellValue);
default -> throw new IllegalArgumentException("Variable type not supported: " + type);
};
};
}
protected Instant parseDate(String cellValue) {
@@ -1,6 +1,5 @@
package com.customer.work.model;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -9,16 +8,18 @@ import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Converts plain Java test data (maps, lists, scalars) into the variable types
* used by Flowable models. Maps and lists become JsonNodes by default; an inner
* map of the form {"__TYPE": "...", "__VALUE": ...} requests an explicit type.
*/
@Component
public class FlowableJsonParser {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final JavaTimeModule javaTimeModule = new JavaTimeModule();
public static final String BOOLEAN = "Boolean";
public static final String STRING = "String";
public static final String INTEGER = "Integer";
@@ -30,28 +31,36 @@ public class FlowableJsonParser {
public static final String MAP = "Map";
public static final String ARRAY_LIST = "ArrayList";
protected final ObjectMapper objectMapper = new ObjectMapper();
public FlowableJsonParser() {
objectMapper.registerModule(javaTimeModule);
// Enable ObjectMapper for handling Instant as string
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
public Map<String, Object> parseMap(Object map) throws JsonProcessingException, ClassCastException {
return (Map<String, Object>) parseObject(map);
public Map<String, Object> parseMap(Object map) {
Object parsed = parseObject(map);
if (!(parsed instanceof Map)) {
throw new IllegalArgumentException("Not a map: " + map);
}
@SuppressWarnings("unchecked")
Map<String, Object> result = (Map<String, Object>) parsed;
return result;
}
public Object parseObject(Object object) throws JsonProcessingException, ClassCastException {
if (object instanceof Map) {
Map<String, Object> resultMap = new LinkedHashMap<>(Map.of());
for (Map.Entry<String, Object> mapEntry : ((Map<String, Object>) object).entrySet()) {
String key = mapEntry.getKey();
public Object parseObject(Object object) {
if (object instanceof Map<?, ?> map) {
Map<String, Object> resultMap = new LinkedHashMap<>();
for (Map.Entry<?, ?> mapEntry : map.entrySet()) {
String key = String.valueOf(mapEntry.getKey());
resultMap.put(key, parseMapEntry(key, mapEntry.getValue()));
}
return resultMap;
}
if (object instanceof ArrayList) {
ArrayList<Object> resultList = new ArrayList<>();
for (Object arrayEntry : (ArrayList<Object>) object) {
if (object instanceof List<?> list) {
List<Object> resultList = new ArrayList<>();
for (Object arrayEntry : list) {
resultList.add(parseArrayEntry(arrayEntry));
}
return resultList;
@@ -59,52 +68,51 @@ public class FlowableJsonParser {
return null;
}
private Object parseMapEntry(String key, Object value) throws JsonProcessingException {
if (value instanceof Map) {
Map<String, Object> valueMap = (Map<String, Object>) value;
if (valueMap.containsKey("__TYPE") && valueMap.containsKey("__VALUE") && valueMap.size() == 2) {
private Object parseMapEntry(String key, Object value) {
if (value instanceof Map<?, ?> valueMap) {
if (valueMap.size() == 2 && valueMap.containsKey("__TYPE") && valueMap.containsKey("__VALUE")) {
// if Map in Map, check if inner Map has explicit type (__TYPE and __VALUE)
return convertObjectExplicit(valueMap.get("__VALUE"), (String) valueMap.get("__TYPE"));
return convertObjectExplicit(valueMap.get("__VALUE"), String.valueOf(valueMap.get("__TYPE")));
}
if (Arrays.asList("__IN", "__OUT").contains(key)) {
if (FlowableModelTestUtils.IN_PARAM.equals(key) || FlowableModelTestUtils.OUT_PARAM.equals(key)) {
// convert __IN and __OUT maps as Map
return parseObject(value);
}
// convert Map to JsonObjectNode (default in models)
return convertObjectExplicit(value, JSON_OBJECT_NODE);
}
if (value instanceof ArrayList) {
// convert ArrayList to JsonArrayNode (default in models)
if (value instanceof List) {
// convert List to JsonArrayNode (default in models)
return convertObjectExplicit(value, JSON_ARRAY_NODE);
}
// take json supported type (Boolean, String, Integer, Double)
return value;
}
private Object parseArrayEntry(Object value) throws JsonProcessingException {
private Object parseArrayEntry(Object value) {
if (value instanceof Map) {
// convert Map to JsonObjectNode (default in models)
return convertObjectExplicit(value, JSON_OBJECT_NODE);
}
if (value instanceof ArrayList) {
// convert ArrayList to JsonArrayNode (default in models)
if (value instanceof List) {
// convert List to JsonArrayNode (default in models)
return convertObjectExplicit(value, JSON_ARRAY_NODE);
}
// take json supported type (Boolean, String, Integer, Double)
return value;
}
private Object convertObjectExplicit(Object value, String explicitType) throws JsonProcessingException {
switch (explicitType) {
case BOOLEAN: return Boolean.parseBoolean(value.toString());
case STRING: return value.toString();
case INTEGER: return Integer.parseInt(value.toString());
case DOUBLE: return Double.parseDouble(value.toString());
case LONG: return Long.parseLong(value.toString());
case INSTANT: return Instant.parse(value.toString());
case MAP: case ARRAY_LIST: return parseObject(value);
case JSON_OBJECT_NODE: case JSON_ARRAY_NODE: return objectMapper.convertValue(parseObject(value), JsonNode.class);
default: return value;
}
private Object convertObjectExplicit(Object value, String explicitType) {
return switch (explicitType) {
case BOOLEAN -> Boolean.parseBoolean(value.toString());
case STRING -> value.toString();
case INTEGER -> Integer.parseInt(value.toString());
case DOUBLE -> Double.parseDouble(value.toString());
case LONG -> Long.parseLong(value.toString());
case INSTANT -> Instant.parse(value.toString());
case MAP, ARRAY_LIST -> parseObject(value);
case JSON_OBJECT_NODE, JSON_ARRAY_NODE -> objectMapper.convertValue(parseObject(value), JsonNode.class);
default -> value;
};
}
}
@@ -122,8 +122,8 @@ public class FlowableModelTestUtils {
Assertions.assertThat(emails.size()).as("%s: invalid email number %s", hint, emailNumber).isGreaterThanOrEqualTo(emailNumber);
EmailDto email = emails.get(emailNumber - 1);
Assertions.assertThat(email.getSubject()).as("%s: invalid subject %s", hint, email.getSubject()).endsWith(subject);
Assertions.assertThat(email.getReceiverList()).as("%s: invalid email receivers", hint)
Assertions.assertThat(email.subject()).as("%s: invalid subject %s", hint, email.subject()).endsWith(subject);
Assertions.assertThat(email.receiverList()).as("%s: invalid email receivers", hint)
.containsExactlyInAnyOrder(receivers.split("[,\\s]+"));
}
@@ -227,14 +227,11 @@ public class FlowableModelTestUtils {
return true;
}
// If test is an object node, check if all fields in test exist in root
if (test.isObject()){
for (Iterator<String> iterator = test.fieldNames(); iterator.hasNext(); ) {
String fieldName = iterator.next();
JsonNode testValue = test.get(fieldName);
JsonNode rootValue = null;
if (root != null) {
rootValue = root.get(fieldName);
}
if (test.isObject()) {
for (Map.Entry<String, JsonNode> testField : test.properties()) {
String fieldName = testField.getKey();
JsonNode testValue = testField.getValue();
JsonNode rootValue = root != null ? root.get(fieldName) : null;
if (testValue.isTextual() && "__N_A".equals(testValue.asText())) {
if (root != null && root.has(fieldName)) {
return false;
@@ -276,12 +273,8 @@ public class FlowableModelTestUtils {
ObjectNode vars = jsonUtils.getEmptyObjectNode();
JsonNode rootParam = row.get("root");
if (rootParam != null) {
Iterator<Map.Entry<String, JsonNode>> rootVars = rootParam.fields();
while (rootVars.hasNext()) {
Map.Entry<String, JsonNode> rootVar = rootVars.next();
String key = rootVar.getKey();
JsonNode value = rootVar.getValue();
vars.set(key, value);
for (Map.Entry<String, JsonNode> rootVar : rootParam.properties()) {
vars.set(rootVar.getKey(), rootVar.getValue());
}
}
JsonNode inParam = row.get("in");
@@ -335,20 +328,20 @@ public class FlowableModelTestUtils {
public Map<String, Object> testObjExcelRow(String path, Map<String, Object> row) {
Map<String, Object> vars = new LinkedHashMap<>();
Map<String, Object> rootParam = (Map<String, Object>) row.get("root");
Map<String, Object> rootParam = getMapParam(row, "root", path);
if (rootParam != null) {
vars.putAll(rootParam);
}
Map<String, Object> inParam = (Map<String, Object>) row.get("in");
Map<String, Object> inParam = getMapParam(row, "in", path);
if (inParam != null) {
vars.put(IN_PARAM, inParam);
}
Map<String, Object> outParam = (Map<String, Object>) row.get("out");
Map<String, Object> outParam = getMapParam(row, "out", path);
if (outParam != null) {
vars.put(OUT_PARAM, outParam);
}
String idParam = (String) row.get("id");
Map<String, Object> test =(Map<String, Object>) row.get("test");
Map<String, Object> test = getMapParam(row, "test", path);
int timerCount = 0;
Object timerNode = row.get("timer");
if (timerNode != null) timerCount = (Integer) timerNode;
@@ -388,6 +381,16 @@ public class FlowableModelTestUtils {
return result;
}
@SuppressWarnings("unchecked")
protected Map<String, Object> getMapParam(Map<String, Object> row, String key, String path) {
Object value = row.get(key);
if (value == null) {
return null;
}
Assertions.assertThat(value).as("Parameter '%s' in %s must be an object", key, path).isInstanceOf(Map.class);
return (Map<String, Object>) value;
}
public void exportApp(String rootUrl, String workspaceKey, String appModelKey, String username, String password) {
RestClient restClient = RestClient.builder()
.baseUrl(rootUrl)
@@ -416,7 +419,9 @@ public class FlowableModelTestUtils {
public ObjectNode loadObjectNodeFromResources(String path) {
if (path == null || path.isEmpty()) return jsonUtils.getEmptyObjectNode();
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path)) {
Assertions.assertThat(inputStream).as("Resource not found: %s", path).isNotNull();
if (inputStream == null) {
throw new IllegalArgumentException("Resource not found: " + path);
}
JsonNode jsonNode = jsonUtils.convertJsonStringToJsonNode(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
Assertions.assertThat(jsonNode).as("Resource %s is not a JSON object", path).isInstanceOf(ObjectNode.class);
return (ObjectNode) jsonNode;
@@ -433,26 +438,20 @@ public class FlowableModelTestUtils {
public Map<String, Object> loadTestVarsFromResources(String path) {
ObjectNode node = loadObjectNodeFromResources(path);
Map<String, Object> vars = new LinkedHashMap<>();
for (Iterator<Map.Entry<String, JsonNode>> fields = node.fields(); fields.hasNext(); ) {
Map.Entry<String, JsonNode> field = fields.next();
for (Map.Entry<String, JsonNode> field : node.properties()) {
String key = field.getKey();
switch (key) {
case ROOT_PARAM:
case ROOT_PARAM -> {
Assertions.assertThat(field.getValue().isObject())
.as("%s in %s must be a JSON object", ROOT_PARAM, path).isTrue();
for (Iterator<String> rootKeys = field.getValue().fieldNames(); rootKeys.hasNext(); ) {
String rootKey = rootKeys.next();
Assertions.assertThat(rootKey.startsWith("__"))
.as("Root parameter '%s' in %s must not start with '__'", rootKey, path).isFalse();
for (Map.Entry<String, JsonNode> rootVar : field.getValue().properties()) {
Assertions.assertThat(rootVar.getKey().startsWith("__"))
.as("Root parameter '%s' in %s must not start with '__'", rootVar.getKey(), path).isFalse();
}
vars.putAll(jsonUtils.convertJsonNodeToMap(field.getValue()));
break;
case IN_PARAM:
case OUT_PARAM:
vars.put(key, jsonUtils.convertJsonNodeToMap(field.getValue()));
break;
default:
throw new IllegalArgumentException("Implicit parameter '" + key + "' in " + path
}
case IN_PARAM, OUT_PARAM -> vars.put(key, jsonUtils.convertJsonNodeToMap(field.getValue()));
default -> throw new IllegalArgumentException("Implicit parameter '" + key + "' in " + path
+ ": parameters must be declared explicitly inside " + ROOT_PARAM + ", " + IN_PARAM + " or " + OUT_PARAM);
}
}
@@ -505,8 +504,8 @@ public class FlowableModelTestUtils {
public void completeTask(String taskId, Map<String, Object> completionVariables, String outcome) {
CompleteFormRepresentation form = new CompleteFormRepresentation();
for (String key : completionVariables.keySet()) {
form.setValues(key, completionVariables.get(key));
for (Map.Entry<String, Object> entry : completionVariables.entrySet()) {
form.setValues(entry.getKey(), entry.getValue());
}
form.setOutcome(outcome);
platformTaskService.completeTaskForm(taskId, form);
@@ -526,8 +525,8 @@ public class FlowableModelTestUtils {
return convertHistVariableListToMap(historicVariableInstanceList);
}
private HashMap<String, Object> convertHistVariableListToMap(List<HistoricVariableInstance> historicVariableInstanceList) {
HashMap<String, Object> variableMap = new HashMap<>();
private Map<String, Object> convertHistVariableListToMap(List<HistoricVariableInstance> historicVariableInstanceList) {
Map<String, Object> variableMap = new HashMap<>();
for (HistoricVariableInstance historicVariableInstance : historicVariableInstanceList) {
variableMap.put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue());
}
@@ -584,11 +583,9 @@ public class FlowableModelTestUtils {
CallActivity callActivity = new CallActivity();
callActivity.setId(testKey);
callActivity.setCalledElement(testKey);
JsonNode inNode = variables.get(IN_PARAM);
if (inNode instanceof ObjectNode) {
Map<String, Object> inMap = jsonUtils.convertObjectNodeToMap((ObjectNode) inNode);
ArrayList<IOParameter> inParameters = new ArrayList<>();
for (Map.Entry<String, Object> entry : inMap.entrySet()) {
if (variables.get(IN_PARAM) instanceof ObjectNode inNode) {
List<IOParameter> inParameters = new ArrayList<>();
for (Map.Entry<String, JsonNode> entry : inNode.properties()) {
IOParameter ioParameter = new IOParameter();
ioParameter.setSourceExpression("${" + IN_PARAM + "." + entry.getKey() + "}");
ioParameter.setTarget(entry.getKey());
@@ -596,14 +593,12 @@ public class FlowableModelTestUtils {
}
callActivity.setInParameters(inParameters);
}
JsonNode outNode = variables.get(OUT_PARAM);
if (outNode instanceof ObjectNode) {
Map<String, String> outMap = (Map) jsonUtils.convertJsonNodeToMap(variables).get(OUT_PARAM);
ArrayList<IOParameter> outParameters = new ArrayList<>();
for (Map.Entry<String, String> entry : outMap.entrySet()) {
if (variables.get(OUT_PARAM) instanceof ObjectNode outNode) {
List<IOParameter> outParameters = new ArrayList<>();
for (Map.Entry<String, JsonNode> entry : outNode.properties()) {
IOParameter ioParameter = new IOParameter();
ioParameter.setSource(entry.getKey());
ioParameter.setTarget(entry.getValue());
ioParameter.setTarget(entry.getValue().asText());
outParameters.add(ioParameter);
}
callActivity.setOutParameters(outParameters);
@@ -7,7 +7,7 @@ flowable.async-executor-activate=false
flowable.async-history-executor-activate=false
flowable.indexing.enabled=false
management.health.elasticsearch.enabled=false
management.metrics.export.elastic.enabled=false
management.elastic.metrics.export.enabled=false
# Set debug level in tests
logging.level.com.flowable=INFO