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