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.plugins.newsletter.userpref;
017
018import java.util.ArrayList;
019import java.util.Date;
020import java.util.HashMap;
021import java.util.HashSet;
022import java.util.List;
023import java.util.Map;
024import java.util.Set;
025import java.util.UUID;
026
027import org.apache.avalon.framework.component.Component;
028import org.apache.avalon.framework.logger.AbstractLogEnabled;
029import org.apache.avalon.framework.service.ServiceException;
030import org.apache.avalon.framework.service.ServiceManager;
031import org.apache.avalon.framework.service.Serviceable;
032
033import org.ametys.core.user.User;
034import org.ametys.core.user.UserIdentity;
035import org.ametys.core.user.UserManager;
036import org.ametys.core.userpref.UserPreferencesException;
037import org.ametys.core.userpref.UserPreferencesStorage;
038import org.ametys.plugins.newsletter.category.CategoryProviderExtensionPoint;
039import org.ametys.plugins.newsletter.daos.Subscriber;
040import org.ametys.plugins.newsletter.daos.SubscribersDAO;
041import org.ametys.web.userpref.FOUserPreferencesConstants;
042
043/**
044 * Retrieves and stores newsletter user preferences values as subscriptions.
045 */
046public class NewsletterUserPreferencesStorage extends AbstractLogEnabled implements UserPreferencesStorage, Component, Serviceable
047{
048    
049    /** The front-office users manager. */
050    protected UserManager _foUserManager;
051    
052    /** The category provider extension point. */
053    protected CategoryProviderExtensionPoint _categoryEP;
054    
055    /** The subscribers DAO. */
056    protected SubscribersDAO _subscribersDao;
057    
058    @Override
059    public void service(ServiceManager serviceManager) throws ServiceException
060    {
061        _foUserManager = (UserManager) serviceManager.lookup(UserManager.ROLE);
062        _categoryEP = (CategoryProviderExtensionPoint) serviceManager.lookup(CategoryProviderExtensionPoint.ROLE);
063        _subscribersDao = (SubscribersDAO) serviceManager.lookup(SubscribersDAO.ROLE);
064    }
065    
066    @Override
067    public Map<String, String> getUnTypedUserPrefs(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars) throws UserPreferencesException
068    {
069        try
070        {
071            Map<String, String> preferenceValues = new HashMap<>();
072            
073            User user = _foUserManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin());
074            String siteName = contextVars.get(FOUserPreferencesConstants.CONTEXT_VAR_SITENAME);
075            
076            if (user != null && siteName != null)
077            {
078                List<Subscriber> subscriptions = _subscribersDao.getSubscriptions(user.getEmail(), siteName);
079                for (Subscriber subscription : subscriptions)
080                {
081                    preferenceValues.put(subscription.getCategoryId(), "true");
082                }
083            }
084            
085            return preferenceValues;
086        }
087        catch (Exception e)
088        {
089            String message = "Error getting newsletter user preferences for login " + userIdentity + " and context " + storageContext;
090            getLogger().error(message, e);
091            throw new UserPreferencesException(message, e);
092        }
093    }
094    
095    @Override
096    public void setUserPreferences(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars, Map<String, String> preferences) throws UserPreferencesException
097    {
098        try
099        {
100            User user = _foUserManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin());
101            String siteName = contextVars.get(FOUserPreferencesConstants.CONTEXT_VAR_SITENAME);
102            
103            if (user != null && siteName != null)
104            {
105                List<Subscriber> newSubscribers = new ArrayList<>();
106                Set<String> removeTokens = new HashSet<>();
107                
108                Map<String, String> existingCategoryIds = getExistingCategoryIds(user.getEmail(), siteName);
109                
110                for (String categoryId : preferences.keySet())
111                {
112                    String value = preferences.get(categoryId);
113                    
114                    if (value.equals("true") && _categoryEP.hasCategory(categoryId) && !existingCategoryIds.containsKey(categoryId))
115                    {
116                        Subscriber subscriber = getSubscription(siteName, user, categoryId);
117                        newSubscribers.add(subscriber);
118                    }
119                    else if (!value.equals("true") && _categoryEP.hasCategory(categoryId) && existingCategoryIds.containsKey(categoryId))
120                    {
121                        String token = existingCategoryIds.get(categoryId);
122                        removeTokens.add(token);
123                    }
124                }
125                
126                // Modify the subscriptions.
127                _subscribersDao.modifySubscriptions(newSubscribers, removeTokens);
128            }
129        }
130        catch (Exception e)
131        {
132            String message = "Error setting newsletter user preferences for login " + userIdentity + " and context " + storageContext;
133            getLogger().error(message, e);
134            throw new UserPreferencesException(message, e);
135        }
136    }
137    
138    @Override
139    public void removeUserPreferences(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars) throws UserPreferencesException
140    {
141        try
142        {
143            User user = _foUserManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin());
144            String siteName = contextVars.get(FOUserPreferencesConstants.CONTEXT_VAR_SITENAME);
145            
146            if (user != null && siteName != null)
147            {
148                // Remove the subscriptions.
149                _subscribersDao.unsubscribe(user.getEmail(), storageContext);
150            }
151        }
152        catch (Exception e)
153        {
154            String message = "Error removing newsletter subscriptions for login " + userIdentity + " and context " + storageContext;
155            getLogger().error(message, e);
156            throw new UserPreferencesException(message, e);
157        }
158    }
159    
160    @Override
161    public String getUserPreferenceAsString(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars, String id) throws UserPreferencesException
162    {
163        String value = null;
164        
165        Boolean booleanValue = getUserPreferenceAsBoolean(userIdentity, storageContext, contextVars, id);
166        
167        if (booleanValue != null)
168        {
169            value = booleanValue.toString();
170        }
171        
172        return value;
173    }
174    
175    @Override
176    public Long getUserPreferenceAsLong(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars, String id) throws UserPreferencesException
177    {
178        return null;
179    }
180    
181    @Override
182    public Date getUserPreferenceAsDate(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars, String id) throws UserPreferencesException
183    {
184        return null;
185    }
186    
187    @Override
188    public Boolean getUserPreferenceAsBoolean(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars, String id) throws UserPreferencesException
189    {
190        try
191        {
192            Boolean value = null;
193            
194            User user = _foUserManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin());
195            String siteName = contextVars.get(FOUserPreferencesConstants.CONTEXT_VAR_SITENAME);
196            
197            if (user != null && siteName != null)
198            {
199                Subscriber subscriber = _subscribersDao.getSubscriber(user.getEmail(), siteName, id);
200                
201                value = new Boolean(subscriber != null);
202            }
203            
204            return value;
205        }
206        catch (Exception e)
207        {
208            throw new UserPreferencesException("Error getting newsletter user preferences for login " + userIdentity + " and context " + storageContext, e);
209        }
210    }
211    
212    @Override
213    public Double getUserPreferenceAsDouble(UserIdentity userIdentity, String storageContext, Map<String, String> contextVars, String id) throws UserPreferencesException
214    {
215        return null;
216    }
217    
218    /**
219     * Create a subscriber object from the given input. 
220     * @param siteName the site name.
221     * @param user the user.
222     * @param categoryId the category ID.
223     * @return the Subscriber object.
224     */
225    protected Subscriber getSubscription(String siteName, User user, String categoryId)
226    {
227        return getSubscription(siteName, user, categoryId, true);
228    }
229    
230    /**
231     * Create a subscriber object from the given input. 
232     * @param siteName the site name.
233     * @param user the user.
234     * @param categoryId the category ID.
235     * @param generateDateAndToken true to generate a token and set the subscription date, false otherwise.
236     * @return the Subscriber object.
237     */
238    protected Subscriber getSubscription(String siteName, User user, String categoryId, boolean generateDateAndToken)
239    {
240        Subscriber subscriber = new Subscriber();
241        subscriber.setEmail(user.getEmail());
242        subscriber.setSiteName(siteName);
243        subscriber.setCategoryId(categoryId);
244        
245        if (generateDateAndToken)
246        {
247            subscriber.setSubscribedAt(new Date());
248            
249            // Generate unique token.
250            String token = UUID.randomUUID().toString();
251            subscriber.setToken(token);
252        }
253        
254        return subscriber;
255    }
256    
257    /**
258     * Get the existing subscriptions for a user in a given site.
259     * @param email the user e-mail address.
260     * @param siteName the site name.
261     * @return a Set of category IDs, to which user has subscribed.
262     */
263    protected Map<String, String> getExistingCategoryIds(String email, String siteName)
264    {
265        Map<String, String> existingCategoryIds = new HashMap<>();
266        
267        List<Subscriber> existingSubscriptions = _subscribersDao.getSubscriptions(email, siteName);
268        for (Subscriber subscription : existingSubscriptions)
269        {
270            existingCategoryIds.put(subscription.getCategoryId(), subscription.getToken());
271        }
272        
273        return existingCategoryIds;
274    }
275}