package jnpf.flowable.service.dev; import jnpf.flowable.model.templatenode.nodejson.NodeModel; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; /** Checks saved values, including native child-table field paths. Never fabricates input. */ public final class DevApprovalValidation { private DevApprovalValidation() {} public static List missing(NodeModel node, Map values) { List problems = new ArrayList<>(); if (node.getFormOperates() == null) return problems; for (Map field : node.getFormOperates()) { if (!Boolean.TRUE.equals(field.get("required"))) continue; String id = String.valueOf(field.get("id")); String label = String.valueOf(field.getOrDefault("name", id)).replace('\n', ' '); int separator = id.indexOf('-'); if (separator < 0) { if (empty(values.get(id))) problems.add(label + "(" + id + ")"); } else { Object rows = values.get(id.substring(0, separator)); String column = id.substring(separator + 1); if (!(rows instanceof List) || ((List) rows).isEmpty()) { // No rows means there are no child field instances to validate. continue; } List list = (List) rows; for (int i = 0; i < list.size(); i++) { Object row = list.get(i); if (!(row instanceof Map) || empty(((Map) row).get(column))) { problems.add(label + "(第" + (i + 1) + "行," + id + ")"); } } } } return problems; } static boolean empty(Object value) { if (value == null) return true; if (value instanceof String) { String text = ((String) value).trim(); return text.isEmpty() || "[]".equals(text) || "null".equals(text); } if (value instanceof Collection) return ((Collection) value).isEmpty(); if (value instanceof Map) return ((Map) value).isEmpty(); return value.getClass().isArray() && Array.getLength(value) == 0; } }