001/* 002 * Copyright 2012 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.userpref; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Comparator; 021import java.util.HashMap; 022import java.util.Map; 023 024import org.apache.cocoon.components.ContextHelper; 025import org.apache.cocoon.environment.Request; 026 027import org.ametys.core.ui.Callable; 028import org.ametys.core.util.I18nizableTextKeyComparator; 029import org.ametys.runtime.i18n.I18nizableText; 030import org.ametys.runtime.model.CategorizedElementDefinitionHelper; 031import org.ametys.runtime.model.DefinitionContext; 032import org.ametys.runtime.model.SimpleViewItemGroup; 033import org.ametys.runtime.model.View; 034import org.ametys.runtime.model.ViewElement; 035import org.ametys.runtime.model.ViewItem; 036import org.ametys.runtime.model.ViewItemGroup; 037import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint; 038import org.ametys.runtime.workspace.WorkspaceMatcher; 039 040/** 041 * Extension point holding all {@link UserPreference} definitions. 042 */ 043public class UserPreferencesExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<UserPreferenceProvider> 044{ 045 /** Avalon Role */ 046 public static final String ROLE = UserPreferencesExtensionPoint.class.getName(); 047 048 /** 049 * Get the declared user preference with the given name. 050 * @param contextVars The context variables including environment elements 051 * @param name The preference's name 052 * @return the user preference, or <code>null</code> if none has been found. 053 */ 054 public UserPreference getUserPreference(Map<String, String> contextVars, String name) 055 { 056 return getUserPreferences(contextVars) 057 .stream() 058 .filter(userPreference -> name.equals(userPreference.getName())) 059 .findFirst() 060 .orElse(null); 061 } 062 063 /** 064 * Get all the declared user preferences. 065 * @param contextVars The context variables including environment elements 066 * @return the user preferences (read-only collection). 067 */ 068 public Collection<UserPreference> getUserPreferences(Map<String, String> contextVars) 069 { 070 Collection<UserPreference> userPreferences = new ArrayList<>(); 071 072 for (String extensionId : getExtensionsIds()) 073 { 074 UserPreferenceProvider provider = getExtension(extensionId); 075 userPreferences.addAll(provider.getPreferences(contextVars)); 076 } 077 078 return userPreferences; 079 } 080 081 /** 082 * Get the definition of user preferences 083 * @param excludePrivate true to exclude private preference from the view 084 * @return the view 085 */ 086 @Callable(rights = Callable.NO_CHECK_REQUIRED) 087 public Map<String, Object> getUserPreferencesViewAsJson(boolean excludePrivate) 088 { 089 Request request = ContextHelper.getRequest(_context); 090 Map<String, String> contextVars = Map.of(UserPreferenceProvider.CONTEXT_VAR_WORKSPACE, (String) request.getAttribute(WorkspaceMatcher.WORKSPACE_NAME)); 091 View userPreferencesView = getUserPreferencesView(excludePrivate, contextVars); 092 DefinitionContext definitionContext = DefinitionContext.newInstance() 093 .withEdition(true); 094 return userPreferencesView.toJSON(definitionContext); 095 } 096 097 /** 098 * Retrieves the view with all user preferences, classified by group and ordered. 099 * @param contextVars The context variables including environment elements 100 * @return the view with all user preferences, classified by group and ordered. 101 */ 102 public View getUserPreferencesView(Map<String, String> contextVars) 103 { 104 return getUserPreferencesView(false, contextVars); 105 } 106 107 /** 108 * Retrieves the view with all user preferences, classified by group and ordered. 109 * @param excludePrivate <code>true</code> to exclude private preferences from the view, <code>false</code> otherwise 110 * @param contextVars The context variables including environment elements 111 * @return the view with all user preferences, classified by group and ordered. 112 */ 113 public View getUserPreferencesView(boolean excludePrivate, Map<String, String> contextVars) 114 { 115 Collection<UserPreference> preferences = getUserPreferences(contextVars); 116 117 Comparator<I18nizableText> groupsComparator = new I18nizableTextKeyComparator(); 118 Comparator<UserPreference> userPreferencesComparator = new UserPreferencesPositionComparator(); 119 120 return _buildView(preferences, groupsComparator, userPreferencesComparator, excludePrivate); 121 } 122 123 private View _buildView(Collection<UserPreference> wrappers, Comparator<I18nizableText> groupsComparator, Comparator<UserPreference> userPreferencesComparator, boolean excludePrivate) 124 { 125 View view = new View(); 126 127 Map<I18nizableText, Collection<UserPreference>> groups = _groupUserPreferences(wrappers); 128 129 Collection<I18nizableText> sortedGroups = CategorizedElementDefinitionHelper.sortItemsList(groups.keySet(), groupsComparator); 130 for (I18nizableText groupLabel : sortedGroups) 131 { 132 ViewItem groupViewItem = _buildGroupViewItem(groupLabel, groups.get(groupLabel), userPreferencesComparator, excludePrivate); 133 view.addViewItem(groupViewItem); 134 } 135 return view; 136 } 137 138 private Map<I18nizableText, Collection<UserPreference>> _groupUserPreferences(Collection<UserPreference> preferences) 139 { 140 Map<I18nizableText, Collection<UserPreference>> groups = new HashMap<>(); 141 142 // Classify parameters by groups 143 for (UserPreference preference : preferences) 144 { 145 I18nizableText displayGroup = preference.getDisplayGroup(); 146 Collection<UserPreference> group = groups.computeIfAbsent(displayGroup, __ -> new ArrayList<>()); 147 group.add(preference); 148 } 149 150 return groups; 151 } 152 153 private ViewItem _buildGroupViewItem(I18nizableText groupLabel, Collection<UserPreference> preferences, Comparator<UserPreference> userPreferencesComparator, boolean excludePrivate) throws IllegalArgumentException 154 { 155 SimpleViewItemGroup groupViewItem = new SimpleViewItemGroup(); 156 groupViewItem.setRole(ViewItemGroup.FIELDSET_ROLE); 157 groupViewItem.setLabel(groupLabel); 158 159 Collection<UserPreference> items = CategorizedElementDefinitionHelper.sortItemsList(preferences, userPreferencesComparator); 160 for (UserPreference item : items) 161 { 162 if (!item.isPrivate() || !excludePrivate) 163 { 164 ViewElement userPreferenceViewItem = new ViewElement(); 165 userPreferenceViewItem.setDefinition(item); 166 groupViewItem.addViewItem(userPreferenceViewItem); 167 } 168 } 169 170 return groupViewItem; 171 } 172 173 /** 174 * Compares user preferences on their position in the group 175 */ 176 class UserPreferencesPositionComparator implements Comparator<UserPreference> 177 { 178 @Override 179 public int compare(UserPreference preference1, UserPreference preference2) 180 { 181 int positionComparison = CategorizedElementDefinitionHelper.comparePositions(preference1.getPosition(), preference2.getPosition()); 182 if (positionComparison != 0) 183 { 184 return positionComparison; 185 } 186 else 187 { 188 return preference1.compareTo(preference2); 189 } 190 } 191 } 192}