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.HashMap;
019import java.util.LinkedHashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Map.Entry;
023import java.util.UUID;
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    protected Map<String, Object> userPrefs2JsonObject (String storageContext, Map<String, String> contextVars, UserIdentity user, boolean excludePrivate) throws ProcessingException, UserPreferencesException
102    {
103        Map<String, Object> jsonObject = new LinkedHashMap<>();
104        
105        Map<I18nizableText, List<UserPreference>> groups = _userPrefEP.getCategorizedPreferences(contextVars);
106        Map<String, String> prefValues = _userPrefManager.getUnTypedUserPrefs(user, storageContext, contextVars);
107        
108        for (Entry<I18nizableText, List<UserPreference>> groupEntry : groups.entrySet())
109        {
110            Map<String, Object> fieldSetObject = new LinkedHashMap<>();
111            fieldSetObject.put("role", "fieldset");
112            fieldSetObject.put("label", groupEntry.getKey());
113            fieldSetObject.put("elements", userPrefs2JsonObject(groupEntry.getValue(), prefValues, excludePrivate));
114            
115            String fieldsetId = UUID.randomUUID().toString();
116            jsonObject.put(fieldsetId, fieldSetObject);
117        }
118        
119        return jsonObject;
120    }
121    
122    /**
123     * Convert user preferences to JSON object
124     * @param userPrefs the user preferences.
125     * @param prefValues The values
126     * @param excludePrivate true to exclude private preferences
127     * @return The JSON object representing the user preferences
128     * @throws ProcessingException if an error occurred
129     */
130    protected Map<String, Object> userPrefs2JsonObject (List<UserPreference> userPrefs, Map<String, String> prefValues, boolean excludePrivate) throws ProcessingException
131    {
132        Map<String, Object> jsonObject = new LinkedHashMap<>();
133        
134        for (UserPreference userPref : userPrefs)
135        {
136            if (!excludePrivate || !userPref.isPrivate())
137            {
138                jsonObject.put(userPref.getId(), userPref2JsonObject(userPref, prefValues.get(userPref.getId())));
139            }
140        }
141        
142        return jsonObject;
143    }
144    
145    /**
146     * Convert a user preference to JSON object
147     * @param userPref the user preference.
148     * @param value The value
149     * @return The JSON object representing the user preferences
150     * @throws ProcessingException if an error occurred
151     */
152    protected Map<String, Object> userPref2JsonObject (UserPreference userPref, Object value) throws ProcessingException
153    {
154        Map<String, Object> jsonObject = ParameterHelper.toJSON(userPref);
155        
156        jsonObject.put("private", userPref.isPrivate());
157        jsonObject.put("multiple", userPref.isMultiple());
158        
159        if (value != null)
160        {
161            jsonObject.put("value", value);
162        }
163        else
164        {
165            jsonObject.put("value", userPref.getDefaultValue());
166        }
167        
168        return jsonObject;
169    }
170    
171    /**
172     * Get the user in the user manager.
173     * @param parameters The parameters
174     * @return the user .
175     */
176    protected UserIdentity getUser(Parameters parameters)
177    {
178        String login = parameters.getParameter("username", "");
179        String populationId = parameters.getParameter("populationId", "");
180        UserIdentity user;
181        if (StringUtils.isEmpty(login) || StringUtils.isEmpty(populationId))
182        {
183            user = _currentUserProvider.getUser();
184        }
185        else
186        {
187            user = new UserIdentity(login, populationId);
188        }
189        return user;
190    }
191    
192
193    /**
194     * Get the preferences context.
195     * @param request the request.
196     * @return the preferences context as a Map.
197     */
198    protected Map<String, String> getContextVars(Request request)
199    {
200        Map<String, String> contextVars = new HashMap<>();
201        contextVars.put(UserPreferenceProvider.CONTEXT_VAR_WORKSPACE, (String) request.getAttribute(WorkspaceMatcher.WORKSPACE_NAME));
202        return contextVars;
203    }
204}