001/*
002 *  Copyright 2024 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.right;
017
018import java.util.List;
019import java.util.Map;
020import java.util.Set;
021import java.util.stream.Collectors;
022
023import org.apache.commons.lang.StringUtils;
024
025import org.ametys.core.group.Group;
026import org.ametys.core.right.AccessController.AccessResult;
027import org.ametys.runtime.i18n.I18nizableText;
028
029/**
030 * Explanation of an {@link AccessResult} provided by an {@link AccessController}
031 * @param accessControllerId the controller id
032 * @param accessResult the access result
033 * @param explanation The explanation as a {@link I18nizableText}
034 */
035public record AccessExplanation(String accessControllerId, AccessResult accessResult, I18nizableText explanation) implements Comparable<AccessExplanation> {
036    
037    /**
038     * Helper to build a {@link I18nizableText} for profiles
039     * @param profiles the profile
040     * @return the {@link I18nizableText}
041     */
042    public static I18nizableText profilesToI18nizableText(Set<Profile> profiles)
043    {
044        List<String> profileLabel = profiles.stream()
045            .map(Profile::getLabel)
046            .sorted()
047            .collect(Collectors.toList());
048        
049        return elementsToI18nizableText(profileLabel);
050    }
051    
052    /**
053     * Helper to build a {@link I18nizableText} for groups
054     * @param groups the profile
055     * @return the {@link I18nizableText}
056     */
057    public static I18nizableText groupsToI18nizableText(Set<Group> groups)
058    {
059        List<String> groupLabel = groups.stream()
060            .map(Group::getLabel)
061            .sorted()
062            .collect(Collectors.toList());
063        
064        return elementsToI18nizableText(groupLabel);
065    }
066    
067    /**
068     * Helper to build a {@link I18nizableText} for a list of String
069     * @param elements the strings
070     * @return the {@link I18nizableText}
071     */
072    public static I18nizableText elementsToI18nizableText(List<String> elements)
073    {
074        if (elements.size() == 1)
075        {
076            return new I18nizableText(elements.get(0));
077        }
078        else
079        {
080            String elementsExceptLast = StringUtils.join(elements.subList(0, elements.size() - 1), ", ");
081            String lastElement = elements.get(elements.size() - 1);
082            
083            return new I18nizableText("plugin.core", "PLUGINS_CORE_RIGHTS_EXPLAIN_TOOL_LIST_OF_ELEMENTS", Map.of("elementsExceptLast", new I18nizableText(elementsExceptLast), "lastElement", new I18nizableText(lastElement)));
084        }
085    }
086
087    public int compareTo(AccessExplanation o)
088    {
089        // order by AccessResult
090        int diff = this.accessResult().compareTo(o.accessResult());
091        if (diff != 0)
092        {
093            return diff;
094        }
095        // and controller id as a fallback to keep consistent ordering
096        else
097        {
098            return o.accessControllerId().compareTo(o.accessControllerId());
099        }
100    }
101}
102