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 .map(escapeHTML -> StringUtils.replace(StringUtils.replace(escapeHTML, "&", "&"), "<", "<")) 047 .sorted() 048 .collect(Collectors.toList()); 049 050 return elementsToI18nizableText(profileLabel); 051 } 052 053 /** 054 * Helper to build a {@link I18nizableText} for groups 055 * @param groups the profile 056 * @return the {@link I18nizableText} 057 */ 058 public static I18nizableText groupsToI18nizableText(Set<Group> groups) 059 { 060 List<String> groupLabel = groups.stream() 061 .map(Group::getLabel) 062 .sorted() 063 .collect(Collectors.toList()); 064 065 return elementsToI18nizableText(groupLabel); 066 } 067 068 /** 069 * Helper to build a {@link I18nizableText} for a list of String 070 * @param elements the strings 071 * @return the {@link I18nizableText} 072 */ 073 public static I18nizableText elementsToI18nizableText(List<String> elements) 074 { 075 if (elements.size() == 1) 076 { 077 return new I18nizableText(elements.get(0)); 078 } 079 else 080 { 081 String elementsExceptLast = StringUtils.join(elements.subList(0, elements.size() - 1), ", "); 082 String lastElement = elements.get(elements.size() - 1); 083 084 return new I18nizableText("plugin.core", "PLUGINS_CORE_RIGHTS_EXPLAIN_TOOL_LIST_OF_ELEMENTS", Map.of("elementsExceptLast", new I18nizableText(elementsExceptLast), "lastElement", new I18nizableText(lastElement))); 085 } 086 } 087 088 public int compareTo(AccessExplanation o) 089 { 090 // order by AccessResult 091 int diff = this.accessResult().compareTo(o.accessResult()); 092 if (diff != 0) 093 { 094 return diff; 095 } 096 // and controller id as a fallback to keep consistent ordering 097 else 098 { 099 return o.accessControllerId().compareTo(o.accessControllerId()); 100 } 101 } 102} 103