package jnpf.dmsPermission; import jnpf.dmsEntity.permission.model.DmsSubjectSet; import jnpf.permission.OrganizeApi; import jnpf.permission.PositionApi; import jnpf.permission.entity.OrganizeEntity; import jnpf.permission.entity.PositionEntity; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @Component @RequiredArgsConstructor public class DmsSubjectHierarchyResolver { private static final String ROOT_PARENT_ID = "-1"; private static final String LEGACY_ROOT_PARENT_ID = "0"; private final OrganizeApi organizeApi; private final PositionApi positionApi; public void resolve(Collection subjects) { resolve(subjects, false); } public void resolveStrict(Collection subjects) { resolve(subjects, true); } private void resolve(Collection subjects, boolean strict) { if (subjects == null || subjects.isEmpty()) { return; } resolvePositions(subjects, strict); resolveOrganizations(subjects, strict); } private void resolveOrganizations(Collection subjects, boolean strict) { Set directIds = collectDirectIds(subjects, true); if (directIds.isEmpty()) { return; } for (DmsSubjectSet subject : subjects) { if (subject != null) { subject.getAncestorOrgIds().addAll(subject.getDirectOrgIds()); } } Map entitiesById = new LinkedHashMap<>(); List entities = organizeApi.getListByIds(new ArrayList<>(directIds)); if (entities != null) { for (OrganizeEntity entity : entities) { String id = entity == null ? null : normalizeId(entity.getId()); if (id != null && directIds.contains(id)) { entitiesById.putIfAbsent(id, entity); } } } rejectMissing(directIds, entitiesById.keySet(), "直属组织", strict); for (DmsSubjectSet subject : subjects) { if (subject == null) { continue; } for (String directId : subject.getDirectOrgIds()) { OrganizeEntity entity = entitiesById.get(directId); if (entity == null) { continue; } List hierarchy = parseHierarchy(entity.getOrganizeIdTree(), directId); subject.getAncestorOrgIds().addAll(hierarchy); addImmediateParent(subject.getImmediateParentOrgIds(), subject.getAncestorOrgIds(), entity.getParentId(), hierarchy, directId); } } } private void resolvePositions(Collection subjects, boolean strict) { Set directIds = collectDirectIds(subjects, false); if (directIds.isEmpty()) { return; } for (DmsSubjectSet subject : subjects) { if (subject != null) { subject.getAncestorPositionIds().addAll(subject.getPositionIds()); } } Map entitiesById = new LinkedHashMap<>(); List entities = positionApi.getListByIds(new ArrayList<>(directIds)); if (entities != null) { for (PositionEntity entity : entities) { String id = entity == null ? null : normalizeId(entity.getId()); if (id != null && directIds.contains(id)) { entitiesById.putIfAbsent(id, entity); } } } rejectMissing(directIds, entitiesById.keySet(), "直属岗位", strict); for (DmsSubjectSet subject : subjects) { if (subject == null) { continue; } for (String directId : subject.getPositionIds()) { PositionEntity entity = entitiesById.get(directId); if (entity == null) { continue; } String organizationId = normalizeId(entity.getOrganizeId()); if (organizationId != null) { subject.getDirectOrgIds().add(organizationId); } List hierarchy = parseHierarchy(entity.getPositionIdTree(), directId); subject.getAncestorPositionIds().addAll(hierarchy); addImmediateParent(subject.getImmediateParentPositionIds(), subject.getAncestorPositionIds(), entity.getParentId(), hierarchy, directId); } } } private Set collectDirectIds(Collection subjects, boolean organization) { Set directIds = new LinkedHashSet<>(); for (DmsSubjectSet subject : subjects) { if (subject == null) { continue; } Set source = organization ? subject.getDirectOrgIds() : subject.getPositionIds(); Set normalized = new LinkedHashSet<>(); if (source != null) { for (String id : source) { String value = normalizeId(id); if (value != null) { normalized.add(value); } } source.clear(); source.addAll(normalized); } directIds.addAll(normalized); } return directIds; } private List parseHierarchy(String idTree, String directId) { Set hierarchy = new LinkedHashSet<>(); if (idTree != null) { for (String id : idTree.split(",")) { String value = normalizeId(id); if (value != null) { hierarchy.add(value); } } } hierarchy.add(directId); return new ArrayList<>(hierarchy); } private void addImmediateParent(Set parentIds, Set ancestorIds, String entityParentId, List hierarchy, String directId) { String parentId = normalizeId(entityParentId); if (parentId == null) { int directIndex = hierarchy.indexOf(directId); if (directIndex > 0) { parentId = hierarchy.get(directIndex - 1); } } if (parentId != null && !parentId.equals(directId)) { parentIds.add(parentId); ancestorIds.add(parentId); } } private void rejectMissing(Set requestedIds, Set foundIds, String subjectType, boolean strict) { Set missingIds = new LinkedHashSet<>(requestedIds); missingIds.removeAll(foundIds); if (strict && !missingIds.isEmpty()) { throw DmsPermissionException.of(DmsPermissionError.PRINCIPAL_NOT_FOUND, subjectType + "主体不存在或主体服务不可用: " + missingIds); } } private String normalizeId(String id) { if (id == null) { return null; } String value = id.trim(); return value.isEmpty() || ROOT_PARENT_ID.equals(value) || LEGACY_ROOT_PARENT_ID.equals(value) ? null : value; } }