001/*
002 *  Copyright 2013 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.plugins.core.userpref;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.LinkedHashMap;
021import java.util.List;
022import java.util.Map;
023import java.util.Map.Entry;
024
025import org.apache.avalon.framework.parameters.Parameters;
026import org.apache.cocoon.ProcessingException;
027import org.apache.cocoon.acting.ServiceableAction;
028import org.apache.cocoon.environment.ObjectModelHelper;
029import org.apache.cocoon.environment.Redirector;
030import org.apache.cocoon.environment.Request;
031import org.apache.cocoon.environment.SourceResolver;
032import org.apache.commons.lang.StringUtils;
033
034import org.ametys.core.cocoon.JSonReader;
035import org.ametys.core.user.CurrentUserProvider;
036import org.ametys.core.user.UserIdentity;
037import org.ametys.core.userpref.UserPreference;
038import org.ametys.core.userpref.UserPreferenceProvider;
039import org.ametys.core.userpref.UserPreferencesException;
040import org.ametys.core.userpref.UserPreferencesExtensionPoint;
041import org.ametys.core.userpref.UserPreferencesManager;
042import org.ametys.runtime.i18n.I18nizableText;
043import org.ametys.runtime.parameter.ParameterHelper;
044import org.ametys.runtime.workspace.WorkspaceMatcher;
045
046/**
047 * Get user preferences as a JSON object
048 */
049public class GetUserPreferencesAction extends ServiceableAction
050{
051    /** The user preferences extension point. */
052    protected UserPreferencesExtensionPoint _userPrefEP;
053    /** The user preferences manager. */
054    protected UserPreferencesManager _userPrefManager;
055    /** The current user provider */
056    private CurrentUserProvider _currentUserProvider;
057    
058    @Override
059    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
060    {
061        if (_userPrefEP == null)
062        {
063            _userPrefEP = (UserPreferencesExtensionPoint) manager.lookup(UserPreferencesExtensionPoint.ROLE);
064            _userPrefManager = (UserPreferencesManager) manager.lookup(UserPreferencesManager.ROLE);
065            _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
066        }
067        
068        Request request = ObjectModelHelper.getRequest(objectModel);
069        String storageContext = parameters.getParameter("prefContext", request.getParameter("prefContext"));
070        
071        boolean excludePrivate = parameters.getParameterAsBoolean("excludePrivate", false);
072        
073        Map<String, String> contextVars = getContextVars(request);
074        UserIdentity user = getUser(parameters);
075        
076        if (StringUtils.isBlank(storageContext))
077        {
078            throw new ProcessingException("Preferences context can't be blank");
079        }
080        
081        Map<String, Object> jsonObject = new HashMap<>();
082        jsonObject.put("username", user.getLogin());
083        jsonObject.put("userpopulation", user.getPopulationId());
084        jsonObject.put("context", storageContext);
085        jsonObject.put("preferences", userPrefs2JsonObject(storageContext, contextVars, user, excludePrivate));
086        
087        request.setAttribute(JSonReader.OBJECT_TO_READ, jsonObject);
088        return EMPTY_MAP;
089    }
090
091    /**
092     * Convert user preferences to JSON object
093     * @param storageContext the preferences context.
094     * @param contextVars The context vars
095     * @param user the user
096     * @param excludePrivate true to exclude private preferences
097     * @return The JSON object representing the user preferences
098     * @throws ProcessingException if an error occurred
099     * @throws UserPreferencesException if an error occurred
100     */
101    @SuppressWarnings("unchecked")
102    protected Map<String, Object> userPrefs2JsonObject (String storageContext, Map<String, String> contextVars, UserIdentity user, boolean excludePrivate) throws ProcessingException, UserPreferencesException
103    {
104        Map<String, Object> jsonObject = new LinkedHashMap<>();
105        jsonObject.put("fieldsets", new ArrayList<Map<String, Object>>());
106        
107        Map<I18nizableText, List<UserPreference>> groups = _userPrefEP.getCategorizedPreferences(contextVars);
108        Map<String, String> prefValues = _userPrefManager.getUnTypedUserPrefs(user, storageContext, contextVars);
109        
110        for (Entry<I18nizableText, List<UserPreference>> groupEntry : groups.entrySet())
111        {
112            Map<String, Object> fieldSetObject = new LinkedHashMap<>();
113            fieldSetObject.put("role", "fieldset");
114            fieldSetObject.put("label", groupEntry.getKey());
115            
116            fieldSetObject.put("elements", userPrefs2JsonObject(groupEntry.getValue(), prefValues, excludePrivate));
117            
118            List<Map<String, Object>> fieldsets = (List<Map<String, Object>>) jsonObject.get("fieldsets");
119            fieldsets.add(fieldSetObject);
120        }
121        
122        return jsonObject;
123    }
124    
125    /**
126     * Convert user preferences to JSON object
127     * @param userPrefs the user preferences.
128     * @param prefValues The values
129     * @param excludePrivate true to exclude private preferences
130     * @return The JSON object representing the user preferences
131     * @throws ProcessingException if an error occurred
132     */
133    protected Map<String, Object> userPrefs2JsonObject (List<UserPreference> userPrefs, Map<String, String> prefValues, boolean excludePrivate) throws ProcessingException
134    {
135        Map<String, Object> jsonObject = new LinkedHashMap<>();
136        
137        for (UserPreference userPref : userPrefs)
138        {
139            if (!excludePrivate || !userPref.isPrivate())
140            {
141                jsonObject.put(userPref.getId(), userPref2JsonObject(userPref, prefValues.get(userPref.getId())));
142            }
143        }
144        
145        return jsonObject;
146    }
147    
148    /**
149     * Convert a user preference to JSON object
150     * @param userPref the user preference.
151     * @param value The value
152     * @return The JSON object representing the user preferences
153     * @throws ProcessingException if an error occurred
154     */
155    protected Map<String, Object> userPref2JsonObject (UserPreference userPref, Object value) throws ProcessingException
156    {
157        Map<String, Object> jsonObject = ParameterHelper.toJSON(userPref);
158        
159        jsonObject.put("private", userPref.isPrivate());
160        jsonObject.put("multiple", userPref.isMultiple());
161        
162        if (value != null)
163        {
164            jsonObject.put("value", value);
165        }
166        else
167        {
168            jsonObject.put("value", userPref.getDefaultValue());
169        }
170        
171        return jsonObject;
172    }
173    
174    /**
175     * Get the user in the user manager.
176     * @param parameters The parameters
177     * @return the user .
178     */
179    protected UserIdentity getUser(Parameters parameters)
180    {
181        String login = parameters.getParameter("username", "");
182        String populationId = parameters.getParameter("populationId", "");
183        UserIdentity user;
184        if (StringUtils.isEmpty(login) || StringUtils.isEmpty(populationId))
185        {
186            user = _currentUserProvider.getUser();
187        }
188        else
189        {
190            user = new UserIdentity(login, populationId);
191        }
192        return user;
193    }
194    
195
196    /**
197     * Get the preferences context.
198     * @param request the request.
199     * @return the preferences context as a Map.
200     */
201    protected Map<String, String> getContextVars(Request request)
202    {
203        Map<String, String> contextVars = new HashMap<>();
204        contextVars.put(UserPreferenceProvider.CONTEXT_VAR_WORKSPACE, (String) request.getAttribute(WorkspaceMatcher.WORKSPACE_NAME));
205        return contextVars;
206    }
207}