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<UUID, DmsResourcePath> resolveAll(String tenantId, List<PermissionDecisionForm> requests) {
|
Set<UUID> allIds = requests.stream().map(PermissionDecisionForm::getResourceId)
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
Map<UUID, DmsPermissionResourceEntity> registry = byId(
|
resourceMapper.selectByTenantAndIds(tenantId, new ArrayList<>(allIds)),
|
DmsPermissionResourceEntity::getId);
|
|
Map<DmsResourceType, List<UUID>> 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<UUID, DmsFileVersionEntity> versions = byId(loadVersions(tenantId,
|
idsByType.get(DmsResourceType.FILE_VERSION)), DmsFileVersionEntity::getId);
|
Set<UUID> documentIds = new LinkedHashSet<>();
|
documentIds.addAll(orEmpty(idsByType.get(DmsResourceType.DOCUMENT)));
|
for (DmsFileVersionEntity version : versions.values()) {
|
documentIds.add(version.getDocumentId());
|
}
|
Map<UUID, DmsDocumentEntity> documents = byId(loadDocuments(tenantId, documentIds),
|
DmsDocumentEntity::getId);
|
|
Set<UUID> startFolderIds = new LinkedHashSet<>();
|
startFolderIds.addAll(orEmpty(idsByType.get(DmsResourceType.FOLDER)));
|
for (DmsDocumentEntity document : documents.values()) {
|
startFolderIds.add(document.getFolderId());
|
}
|
Map<UUID, List<UUID>> folderPaths = loadFolderPaths(tenantId, startFolderIds);
|
|
Map<UUID, DmsResourcePath> 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<UUID> candidateResourceIds(DmsResourcePath path) {
|
LinkedHashSet<UUID> 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<DmsFileVersionEntity> loadVersions(String tenantId, List<UUID> ids) {
|
return ids == null || ids.isEmpty()
|
? Collections.<DmsFileVersionEntity>emptyList()
|
: fileVersionMapper.selectByTenantAndIds(tenantId, distinct(ids));
|
}
|
|
private List<DmsDocumentEntity> loadDocuments(String tenantId, Set<UUID> ids) {
|
return ids.isEmpty()
|
? Collections.<DmsDocumentEntity>emptyList()
|
: documentMapper.selectByTenantAndIds(tenantId, new ArrayList<>(ids));
|
}
|
|
private Map<UUID, List<UUID>> loadFolderPaths(String tenantId, Set<UUID> folderIds) {
|
Map<UUID, List<UUID>> result = new LinkedHashMap<>();
|
if (folderIds.isEmpty()) {
|
return result;
|
}
|
List<DmsFolderAncestorRow> 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<UUID, DmsDocumentEntity> documents, UUID id) {
|
DmsDocumentEntity document = documents.get(id);
|
if (document == null) {
|
throw missingBusinessObject(id);
|
}
|
return document;
|
}
|
|
private List<UUID> requiredFolderPath(Map<UUID, List<UUID>> paths, UUID folderId) {
|
List<UUID> 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<UUID> distinct(List<UUID> ids) {
|
return new ArrayList<>(new LinkedHashSet<>(ids));
|
}
|
|
private List<UUID> orEmpty(List<UUID> ids) {
|
return ids == null ? Collections.<UUID>emptyList() : ids;
|
}
|
|
private <T> Map<UUID, T> byId(List<T> values, Function<T, UUID> idGetter) {
|
return values.stream().collect(Collectors.toMap(idGetter, Function.identity(), (left, right) -> left,
|
LinkedHashMap::new));
|
}
|
}
|