package jnpf.dmsService; import jnpf.dmsEntity.permission.entity.DmsDocumentEntity; import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity; import jnpf.dmsEntity.permission.entity.DmsFolderEntity; import jnpf.dmsEntity.permission.enums.DmsResourceType; import jnpf.dmsEntity.permission.vo.DmsCursorPageVO; import jnpf.dmsEntity.permission.vo.DmsPermissionResourceVO; import jnpf.dmsEntity.permission.vo.DmsResourceTypeDefinitionVO; import jnpf.dmsMapper.DmsDocumentMapper; import jnpf.dmsMapper.DmsFileVersionMapper; import jnpf.dmsMapper.DmsFolderMapper; import jnpf.dmsMapper.DmsPermissionResourceMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import jnpf.dmsPermission.DmsCursorCodec; import jnpf.dmsPermission.DmsPermissionError; import jnpf.dmsPermission.DmsPermissionException; import jnpf.dmsPermission.DmsPermissionProperties; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.UUID; @Service @RequiredArgsConstructor public class DmsResourceQueryService { private final DmsCurrentIdentity currentIdentity; private final DmsPermissionProperties properties; private final DmsCursorCodec cursorCodec; private final DmsPermissionResourceMapper resourceMapper; private final DmsFolderMapper folderMapper; private final DmsDocumentMapper documentMapper; private final DmsFileVersionMapper fileVersionMapper; public List typeDefinitions() { currentIdentity.requirePermissionAdministrator(); return Arrays.asList( new DmsResourceTypeDefinitionVO("FOLDER", "FOLDER", Arrays.asList("SELF", "SUBTREE"), Arrays.asList("CREATE", "READ", "UPDATE", "DELETE")), new DmsResourceTypeDefinitionVO("DOCUMENT", "FOLDER", Collections.singletonList("SELF"), Arrays.asList("READ", "UPDATE", "DELETE")), new DmsResourceTypeDefinitionVO("FILE_VERSION", "DOCUMENT", Collections.singletonList("SELF"), Arrays.asList("READ", "UPDATE", "DELETE"))); } @Transactional(readOnly = true) public DmsCursorPageVO page(String resourceType, String cursor, Integer pageSize) { currentIdentity.requirePermissionAdministrator(); String normalizedType = normalizeResourceType(resourceType); int limit = pageSize(pageSize); DmsCursorCodec.Cursor decoded = cursorCodec.decode(cursor); List rows = resourceMapper.selectPage(currentIdentity.tenantId(), normalizedType, decoded.getTime(), decoded.getId(), limit + 1); return page(rows, limit); } @Transactional(readOnly = true) public List children(UUID parentId, Integer pageSize) { currentIdentity.requirePermissionAdministrator(); return resourceMapper.selectChildren(currentIdentity.tenantId(), parentId, pageSize(pageSize)); } @Transactional(readOnly = true) public DmsPermissionResourceVO resource(UUID id) { currentIdentity.requirePermissionAdministrator(); DmsPermissionResourceVO value = resourceMapper.selectView(currentIdentity.tenantId(), id); return require(value, id); } @Transactional(readOnly = true) public DmsFolderEntity folder(UUID id) { currentIdentity.requirePermissionAdministrator(); DmsFolderEntity value = folderMapper.selectByTenantAndId(currentIdentity.tenantId(), id); return require(value, id); } @Transactional(readOnly = true) public DmsDocumentEntity document(UUID id) { currentIdentity.requirePermissionAdministrator(); DmsDocumentEntity value = documentMapper.selectByTenantAndId(currentIdentity.tenantId(), id); return require(value, id); } @Transactional(readOnly = true) public DmsFileVersionEntity fileVersion(UUID id) { currentIdentity.requirePermissionAdministrator(); DmsFileVersionEntity value = fileVersionMapper.selectByTenantAndId(currentIdentity.tenantId(), id); return require(value, id); } private DmsCursorPageVO page(List rows, int limit) { DmsCursorPageVO result = new DmsCursorPageVO<>(); boolean hasMore = rows.size() > limit; if (hasMore) { rows = rows.subList(0, limit); } result.setList(rows); result.setHasMore(hasMore); if (hasMore && !rows.isEmpty()) { DmsPermissionResourceVO last = rows.get(rows.size() - 1); result.setNextCursor(cursorCodec.encode(last.getCreatedAt(), last.getId())); } return result; } private int pageSize(Integer requested) { int value = requested == null ? properties.getDefaultPageSize() : requested; if (value < 1 || value > properties.getMaxPageSize()) { throw DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST, "pageSize 必须在 1 到 " + properties.getMaxPageSize() + " 之间"); } return value; } private String normalizeResourceType(String resourceType) { if (resourceType == null || resourceType.trim().isEmpty()) { return null; } try { return DmsResourceType.valueOf(resourceType.trim().toUpperCase()).name(); } catch (IllegalArgumentException ex) { throw DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST, "resourceType 无效"); } } private T require(T value, UUID id) { if (value == null) { throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND, "资源不存在: " + id); } return value; } }