package it.inaf.ia2.gms.service; import it.inaf.ia2.gms.exception.BadRequestException; import it.inaf.ia2.gms.persistence.GroupsDAO; import it.inaf.ia2.gms.persistence.model.GroupEntity; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * Utility class for retrieving the complete names (including parents) from a * set of group paths. */ @Service public class GroupNameService { private final GroupsDAO groupsDAO; @Autowired public GroupNameService(GroupsDAO groupsDAO) { this.groupsDAO = groupsDAO; } public List getGroupsNamesFromIdentifiers(Set groupIdentifiers) { return getGroupsNames(groupsDAO.findGroupsByIds(groupIdentifiers)); } public String getGroupCompleteName(GroupEntity group) { return getGroupsNames(Collections.singletonList(group)).get(0); } /** * Returns the list of the group complete names, given a list of GroupEntity * objects. */ public List getGroupsNames(List groups) { Set groupIds = groups.stream().map(g -> g.getId()).collect(Collectors.toSet()); List names = new ArrayList<>(groupsDAO.getGroupCompleteNamesFromId(groupIds).values()); Collections.sort(names); return names; } /** * @param groups * @return map having group id as keys and group names as values */ public Map> getNames(Set groups) { Set groupIds = groups.stream() .map(g -> g.getId()).collect(Collectors.toSet()); return getNamesFromIds(groupIds); } public Map> getNamesFromIds(Set groupIds) { Map> result = new HashMap<>(); if (groupIds.contains("ROOT")) { result.put("ROOT", Collections.singletonList(getRoot().getName())); } for (Map.Entry entry : groupsDAO.getGroupCompleteNamesFromId(groupIds).entrySet()) { List names = splitNames(entry.getValue()); result.put(entry.getKey(), names); } return result; } private List splitNames(String completeGroupName) { return Arrays.asList(completeGroupName.split("(? groupPrefix) { if (groupPrefix.isPresent() && !groupPrefix.get().isBlank()) { if (groupPrefix.get().endsWith(".")) { // this branch is kept for retro-compatibility with old API, it will be removed in the future return completeGroupName.substring(groupPrefix.get().length()); } else { return completeGroupName.substring(groupPrefix.get().length() + 1); } } return completeGroupName; } public GroupEntity getGroupFromNames(Optional group) { List groupNames = extractGroupNames(group); if (groupNames.isEmpty()) { return getRoot(); } return getGroupFromNamesAndIndex(groupNames, groupNames.size() - 1); } public GroupEntity getGroupFromNamesAndIndex(Optional group, int index) { List groupNames = extractGroupNames(group); return getGroupFromNamesAndIndex(groupNames, index); } private GroupEntity getGroupFromNamesAndIndex(List groupNames, int index) { String parentPath = ""; // starting from ROOT GroupEntity group = null; for (int i = 0; i < index + 1; i++) { String groupName = groupNames.get(i); group = groupsDAO.findGroupByParentAndName(parentPath, groupName) .orElseThrow(() -> new BadRequestException("Unable to find group " + groupName)); parentPath = group.getPath(); } if (group == null) { throw new IllegalStateException(); } return group; } private List extractGroupNames(Optional group) { return extractGroupNames(group.orElse(null)); } public List extractGroupNames(String groupStr) { if (groupStr == null || groupStr.isEmpty()) { return new ArrayList<>(); } groupStr = URLDecoder.decode(groupStr, StandardCharsets.UTF_8); List names = new ArrayList<>(); String currentName = ""; for (int i = 0; i < groupStr.length(); i++) { char c = groupStr.charAt(i); // dot is the group separator and it must be escaped if used inside // group names if (c == '.' && groupStr.charAt(i - 1) != '\\') { names.add(currentName.replace("\\.", ".")); currentName = ""; } else { currentName += c; } } names.add(currentName.replace("\\.", ".")); return names; } public String getCompleteName(List names) { return String.join(".", names.stream() .map(n -> n.replace(".", "\\.")) .collect(Collectors.toList())); } private GroupEntity getRoot() { return groupsDAO.findGroupById("ROOT") .orElseThrow(() -> new IllegalStateException("Missing root group")); } }