001/*
002 *  Copyright 2019 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.web.frontoffice.search.requesttime.input;
017
018import java.util.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.stream.Collectors;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027import org.apache.cocoon.environment.Request;
028import org.apache.commons.lang3.tuple.Pair;
029
030import org.ametys.cms.search.Sort.Order;
031import org.ametys.core.user.CurrentUserProvider;
032import org.ametys.core.user.UserIdentity;
033import org.ametys.core.userpref.UserPreferencesException;
034import org.ametys.core.userpref.UserPreferencesManager;
035import org.ametys.core.util.JSONUtils;
036import org.ametys.runtime.plugin.component.AbstractLogEnabled;
037import org.ametys.web.frontoffice.search.instance.SearchServiceInstance;
038import org.ametys.web.frontoffice.search.requesttime.input.impl.FormSearchUserInputs;
039import org.ametys.web.frontoffice.search.requesttime.input.impl.UserPrefsSearchUserInputs;
040
041/**
042 * The {@link SearchUserInputs} retriever.
043 */
044public class SearchUserInputsRetriever extends AbstractLogEnabled implements Component, Serviceable
045{
046    /** The avalon role */
047    public static final String ROLE = SearchUserInputsRetriever.class.getName();
048    
049    /** The current user provider */
050    protected CurrentUserProvider _currentUserProvider;
051    /** The user preferences manager */
052    protected UserPreferencesManager _userPrefsManager;
053    /** The JSON utils */
054    protected JSONUtils _jsonUtils;
055    
056    @Override
057    public void service(ServiceManager manager) throws ServiceException
058    {
059        _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
060        _userPrefsManager = (UserPreferencesManager) manager.lookup(UserPreferencesManager.ROLE);
061        _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
062    }
063    
064    /**
065     * Get the user inputs. Implementation depends on the search parameters.
066     * @param request The request
067     * @param isFormSubmitted <code>true</code> if the form has been submitted
068     * @param serviceInstance The search service instance
069     * @return The search user inputs (criteria, facets, sorts)
070     */
071    public SearchUserInputs getUserInputs(Request request, boolean isFormSubmitted, SearchServiceInstance serviceInstance)
072    {
073        SearchUserInputs searchUserInputs = null;
074        
075        if (!isFormSubmitted && serviceInstance.saveUserPrefs())
076        {
077            searchUserInputs = _getCurrentSearchUserInputs(serviceInstance.getId());
078        }
079        
080        if (searchUserInputs == null)
081        {
082            searchUserInputs = new FormSearchUserInputs(request);
083        }
084        
085        getLogger().info("Got user inputs: {}", searchUserInputs);
086        
087        return searchUserInputs;
088    }
089    
090    /**
091     * Get the current search user inputs for the given service.
092     * @param serviceId The service ID
093     * @return A {@link SearchUserInputs} object if the user is authenticated and have saved filters for this service. Otherwise, it returns <code>null</code>.
094     */
095    @SuppressWarnings({"unchecked"})
096    protected SearchUserInputs _getCurrentSearchUserInputs(String serviceId)
097    {
098        SearchUserInputs searchUserInputs = null;
099        
100        try
101        {
102            UserIdentity user = _currentUserProvider.getUser();
103            if (user != null)
104            {
105                Map<String, String> userPreferences = _userPrefsManager.getUnTypedUserPrefs(user, "search-" + serviceId, new HashMap<>());
106
107                if (!userPreferences.isEmpty())
108                {
109                    Map<String, Object> criteria = _jsonUtils.convertJsonToMap(userPreferences.get("search.criteria"));
110                    Map<String, List<String>> facets = (Map<String, List<String>>) (Object) _jsonUtils.convertJsonToMap(userPreferences.get("search.facets"));
111                    List<Map<String, String>> sortsJSON = (List<Map<String, String>>) (Object) _jsonUtils.convertJsonToList(userPreferences.get("search.sorts"));
112                    
113                    List<Pair<String, Order>> sorts = sortsJSON
114                        .stream()
115                        .map(map -> Pair.of(map.get("key"), Order.valueOf(map.get("order"))))
116                        .collect(Collectors.toList());
117                    
118                    searchUserInputs = new UserPrefsSearchUserInputs(criteria, facets, sorts);
119                }
120            }
121            else
122            {
123                getLogger().debug("There is no authenticated user.");
124            }
125        }
126        catch (UserPreferencesException e)
127        {
128            getLogger().error("An error occured while getting the user preferences.", e);
129        }
130        
131        return searchUserInputs;
132    }
133}