package jnpf.dmsPermission; import jnpf.dmsEntity.permission.entity.DmsDocumentEntity; import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity; import jnpf.dmsEntity.permission.entity.DmsPermissionResourceEntity; import jnpf.dmsEntity.permission.enums.DmsResourceType; import jnpf.dmsEntity.permission.form.PermissionDecisionForm; import jnpf.dmsEntity.permission.model.DmsFolderAncestorRow; import jnpf.dmsEntity.permission.model.DmsResourcePath; import jnpf.dmsMapper.DmsDocumentMapper; import jnpf.dmsMapper.DmsFileVersionMapper; import jnpf.dmsMapper.DmsFolderMapper; import jnpf.dmsMapper.DmsPermissionResourceMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; @Component @RequiredArgsConstructor public class DmsResourceResolver { private final DmsPermissionResourceMapper resourceMapper; private final DmsFolderMapper folderMapper; private final DmsDocumentMapper documentMapper; private final DmsFileVersionMapper fileVersionMapper; public DmsResourcePath resolve(String tenantId, DmsResourceType type, UUID id) { PermissionDecisionForm request = new PermissionDecisionForm(); request.setResourceType(type); request.setResourceId(id); return resolveAll(tenantId, Collections.singletonList(request)).get(id); } public Map resolveAll(String tenantId, List requests) { Set allIds = requests.stream().map(PermissionDecisionForm::getResourceId) .collect(Collectors.toCollection(LinkedHashSet::new)); Map registry = byId( resourceMapper.selectByTenantAndIds(tenantId, new ArrayList<>(allIds)), DmsPermissionResourceEntity::getId); Map> idsByType = new EnumMap<>(DmsResourceType.class); for (PermissionDecisionForm request : requests) { DmsPermissionResourceEntity registered = registry.get(request.getResourceId()); if (registered == null || !request.getResourceType().name().equals(registered.getResourceType())) { throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND, "权限资源不存在或类型不一致: " + request.getResourceId()); } idsByType.computeIfAbsent(request.getResourceType(), key -> new ArrayList<>()) .add(request.getResourceId()); } Map versions = byId(loadVersions(tenantId, idsByType.get(DmsResourceType.FILE_VERSION)), DmsFileVersionEntity::getId); Set documentIds = new LinkedHashSet<>(); documentIds.addAll(orEmpty(idsByType.get(DmsResourceType.DOCUMENT))); for (DmsFileVersionEntity version : versions.values()) { documentIds.add(version.getDocumentId()); } Map documents = byId(loadDocuments(tenantId, documentIds), DmsDocumentEntity::getId); Set startFolderIds = new LinkedHashSet<>(); startFolderIds.addAll(orEmpty(idsByType.get(DmsResourceType.FOLDER))); for (DmsDocumentEntity document : documents.values()) { startFolderIds.add(document.getFolderId()); } Map> folderPaths = loadFolderPaths(tenantId, startFolderIds); Map result = new LinkedHashMap<>(); for (PermissionDecisionForm request : requests) { DmsResourcePath path = new DmsResourcePath(); path.setActualResourceId(request.getResourceId()); path.setActualResourceType(request.getResourceType().name()); if (request.getResourceType() == DmsResourceType.FOLDER) { path.setDirectFolderId(request.getResourceId()); path.setFolderPath(requiredFolderPath(folderPaths, request.getResourceId())); } else if (request.getResourceType() == DmsResourceType.DOCUMENT) { DmsDocumentEntity document = requireDocument(documents, request.getResourceId()); path.setDocumentId(document.getId()); path.setDirectFolderId(document.getFolderId()); path.setFolderPath(requiredFolderPath(folderPaths, document.getFolderId())); } else { DmsFileVersionEntity version = versions.get(request.getResourceId()); if (version == null) { throw missingBusinessObject(request.getResourceId()); } DmsDocumentEntity document = requireDocument(documents, version.getDocumentId()); path.setDocumentId(document.getId()); path.setDirectFolderId(document.getFolderId()); path.setFolderPath(requiredFolderPath(folderPaths, document.getFolderId())); } result.put(request.getResourceId(), path); } return result; } public List candidateResourceIds(DmsResourcePath path) { LinkedHashSet ids = new LinkedHashSet<>(); ids.add(path.getActualResourceId()); if (path.getDocumentId() != null) { ids.add(path.getDocumentId()); } ids.addAll(path.getFolderPath()); return new ArrayList<>(ids); } private List loadVersions(String tenantId, List ids) { return ids == null || ids.isEmpty() ? Collections.emptyList() : fileVersionMapper.selectByTenantAndIds(tenantId, distinct(ids)); } private List loadDocuments(String tenantId, Set ids) { return ids.isEmpty() ? Collections.emptyList() : documentMapper.selectByTenantAndIds(tenantId, new ArrayList<>(ids)); } private Map> loadFolderPaths(String tenantId, Set folderIds) { Map> result = new LinkedHashMap<>(); if (folderIds.isEmpty()) { return result; } List rows = folderMapper.selectAncestorRows(tenantId, new ArrayList<>(folderIds)); for (DmsFolderAncestorRow row : rows) { result.computeIfAbsent(row.getStartFolderId(), key -> new ArrayList<>()) .add(row.getAncestorFolderId()); } return result; } private DmsDocumentEntity requireDocument(Map documents, UUID id) { DmsDocumentEntity document = documents.get(id); if (document == null) { throw missingBusinessObject(id); } return document; } private List requiredFolderPath(Map> paths, UUID folderId) { List path = paths.get(folderId); if (path == null || path.isEmpty()) { throw missingBusinessObject(folderId); } return path; } private DmsPermissionException missingBusinessObject(UUID id) { return DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND, "权限登记对应的业务资源不存在: " + id); } private List distinct(List ids) { return new ArrayList<>(new LinkedHashSet<>(ids)); } private List orEmpty(List ids) { return ids == null ? Collections.emptyList() : ids; } private Map byId(List values, Function idGetter) { return values.stream().collect(Collectors.toMap(idGetter, Function.identity(), (left, right) -> left, LinkedHashMap::new)); } }