package jnpf.dmsService; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import jnpf.exception.DataException; import java.util.*; /** Native organizeSelect values; deliberately rejects users, positions and unresolved dynamic parameters. */ public final class DmsApprovedDepartmentScope { private static final ObjectMapper JSON = new ObjectMapper(); public record Department(String id, String scope) {} private DmsApprovedDepartmentScope() {} public static List parse(String value) { if (value == null || value.isBlank()) return List.of(); try { JsonNode array = JSON.readTree(value); // Native empty selections can be SQL NULL or serialized JSON null. if (array == null || array.isNull()) return List.of(); if (!array.isArray()) throw new DataException("查阅授权部门必须为数组"); Map departments = new TreeMap<>(); for (JsonNode node : array) { if (!node.isTextual()) throw new DataException("查阅授权部门必须为ID字符串"); String token = node.textValue().trim(); String id = token, scope = "SELF"; int separator = token.indexOf("--"); if (separator >= 0) { id = token.substring(0, separator); scope = switch (token.substring(separator + 2)) { case "org" -> "SELF"; case "subOrg" -> "CHILDREN"; case "progenyOrg" -> "DESCENDANTS"; default -> throw new DataException("查阅授权仅支持部门及部门下级范围"); }; } if (id.isBlank() || id.length() > 100 || id.startsWith("@") || !id.equals(id.trim()) || id.chars().anyMatch(Character::isWhitespace)) throw new DataException("查阅授权部门ID无效"); Department candidate = new Department(id, scope); Department old = departments.get(id); if (old == null || rank(candidate.scope()) > rank(old.scope())) departments.put(id, candidate); } return List.copyOf(departments.values()); } catch (DataException ex) { throw ex; } catch (Exception ex) { throw new DataException("查阅授权部门格式无效"); } } public static String normalize(String value) { List departments = parse(value); try { return JSON.writeValueAsString(departments.stream().map(d -> d.id() + switch (d.scope()) { case "CHILDREN" -> "--subOrg"; case "DESCENDANTS" -> "--progenyOrg"; default -> ""; }).toList()); } catch (Exception ex) { throw new DataException("无法保存查阅授权部门快照"); } } private static int rank(String scope) { return switch (scope) { case "CHILDREN" -> 1; case "DESCENDANTS" -> 2; default -> 0; }; } }