001/*
002 *  Copyright 2014 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.pagesubscription;
017
018import java.util.Arrays;
019import java.util.HashMap;
020import java.util.HashSet;
021import java.util.Map;
022import java.util.Set;
023import java.util.stream.Collectors;
024
025import javax.jcr.Node;
026import javax.jcr.RepositoryException;
027import javax.jcr.Value;
028
029import org.apache.avalon.framework.component.Component;
030import org.apache.avalon.framework.service.ServiceException;
031import org.apache.avalon.framework.service.ServiceManager;
032import org.apache.avalon.framework.service.Serviceable;
033import org.apache.commons.lang3.StringUtils;
034
035import org.ametys.core.observation.Event;
036import org.ametys.core.observation.ObservationManager;
037import org.ametys.core.user.CurrentUserProvider;
038import org.ametys.core.util.LambdaUtils;
039import org.ametys.plugins.repository.RepositoryConstants;
040import org.ametys.plugins.repository.jcr.JCRAmetysObject;
041import org.ametys.runtime.plugin.component.AbstractLogEnabled;
042import org.ametys.web.ObservationConstants;
043import org.ametys.web.repository.page.Page;
044import org.ametys.web.repository.page.jcr.DefaultPage;
045
046/**
047 * DAO for page subscription
048 *
049 */
050public class PageSubscriptionDAO extends AbstractLogEnabled implements Component, Serviceable
051{
052    /** The Avalon role */
053    public static final String ROLE = PageSubscriptionDAO.class.getName();
054    
055    private static final String __SUBSCRIBERS_PROPERTY_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":subscriberMails";
056
057    private ObservationManager _observationManager;
058
059    private CurrentUserProvider _currentUserProvider;
060
061    public void service(ServiceManager smanager) throws ServiceException
062    {
063        _observationManager = (ObservationManager) smanager.lookup(ObservationManager.ROLE);
064        _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
065    }
066    
067    /**
068     * Get the subscribers on a page
069     * @param page the page
070     * @return the subscribers
071     * @throws IllegalArgumentException if the page does not support subscription
072     */
073    public Set<String> getSubscribers(Page page) throws IllegalArgumentException
074    {
075        if (page instanceof JCRAmetysObject)
076        {
077            try
078            {
079                Node node = ((JCRAmetysObject) page).getNode();
080                if (node.hasProperty(__SUBSCRIBERS_PROPERTY_NAME))
081                {
082                    Value[] values = node.getProperty(__SUBSCRIBERS_PROPERTY_NAME).getValues();
083                    
084                    try
085                    {
086                        return Arrays.stream(values)
087                                .map(LambdaUtils.wrap(Value::getString))
088                                .map(String::trim)
089                                .filter(StringUtils::isNotEmpty)
090                                .collect(Collectors.toSet());
091                    }
092                    catch (RuntimeException e)
093                    {
094                        // A wrapped RepositoryException occurs on #getString
095                        getLogger().error("Unable to retrieve subscribers for page of id '" + page.getId() + "'", e.getCause());
096                    }
097                }
098            }
099            catch (RepositoryException e)
100            {
101                getLogger().error("Unable to retrieve subscribers for page of id '" + page.getId() + "'", e);
102            }
103        }
104        else
105        {
106            throw new IllegalArgumentException("The page of id '" + page.getId() + "' does not support subscription");
107        }
108        
109        return new HashSet<>();
110    }
111    
112    /**
113     * Determines if the given email is a subcriber of the given page
114     * @param page The page
115     * @param email The email to test
116     * @return true if the given email is a subcriber of the given page
117     */
118    public boolean isSubscriber(Page page, String email)
119    {
120        return getSubscribers(page).contains(email);
121    }
122    
123    /**
124     * Add a subscriber to a page
125     * @param page The page
126     * @param email The email to add
127     * @throws IllegalArgumentException if the page does not support subscription
128     */
129    public void addSubscriber(Page page, String email) throws IllegalArgumentException
130    {
131        Set<String> subscribers = getSubscribers(page);
132        subscribers.add(email);
133        setSubscribers(page, subscribers);
134    }
135    
136    /**
137     * Remove a subscriber from a page
138     * @param page The page
139     * @param email The email to remove
140     * @throws IllegalArgumentException if the page does not support subscription
141     */
142    public void removeSubscriber(Page page, String email) throws IllegalArgumentException
143    {
144        Set<String> subscribers = getSubscribers(page);
145        subscribers.remove(email);
146        setSubscribers(page, subscribers);
147    }
148    
149    /**
150     * Set the subscribers to a page
151     * @param page The page
152     * @param subscribers The email of subscribers
153     * @throws IllegalArgumentException if the page does not support subscription
154     */
155    public void setSubscribers(Page page, Set<String> subscribers) throws IllegalArgumentException
156    {
157        if (page instanceof DefaultPage)
158        {
159            try
160            {
161                Node node = ((DefaultPage) page).getNode();
162                
163                String[] subscribersAsStringArray = subscribers.toArray(new String[subscribers.size()]);
164                node.setProperty(__SUBSCRIBERS_PROPERTY_NAME, subscribersAsStringArray);
165                ((DefaultPage) page).saveChanges();
166                
167                // Notify observers that page data has been changed.
168                Map<String, Object> eventParams = new HashMap<>();
169                eventParams.put(ObservationConstants.ARGS_PAGE, page);
170                eventParams.put(ObservationConstants.ARGS_PAGE_ID, page.getId());
171                _observationManager.notify(new Event(ObservationConstants.EVENT_PAGE_UPDATED, _currentUserProvider.getUser(), eventParams));
172            }
173            catch (RepositoryException e)
174            {
175                getLogger().error("Unable to set subscribers for page of id '" + page.getId() + "'", e);
176            }
177        }
178        else
179        {
180            throw new IllegalArgumentException("The page of id '" + page.getId() + "' does not support subscription");
181        }
182        
183    }
184}