001/*
002 * (C) Copyright 2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.webapp.notification;
021
022import java.io.Serializable;
023import java.security.Principal;
024import java.util.ArrayList;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Map;
028
029import javax.faces.context.FacesContext;
030import javax.faces.model.SelectItem;
031
032import org.jboss.seam.ScopeType;
033import org.jboss.seam.annotations.In;
034import org.jboss.seam.annotations.Name;
035import org.jboss.seam.annotations.Out;
036import org.jboss.seam.annotations.Scope;
037import org.jboss.seam.faces.FacesMessages;
038import org.jboss.seam.international.StatusMessage;
039import org.nuxeo.common.utils.i18n.Labeler;
040import org.nuxeo.ecm.core.api.CoreSession;
041import org.nuxeo.ecm.core.api.DocumentModel;
042import org.nuxeo.ecm.core.api.NuxeoPrincipal;
043import org.nuxeo.ecm.platform.ec.notification.NotificationConstants;
044import org.nuxeo.ecm.platform.notification.api.Notification;
045import org.nuxeo.ecm.platform.notification.api.NotificationManager;
046import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
047import org.nuxeo.ecm.webapp.base.InputController;
048
049/**
050 * Handles the subscriptions page.
051 *
052 * @author <a href="mailto:npaslaru@nuxeo.com">Narcis Paslaru</a>
053 */
054@Name("groupsSubscriptionsAction")
055@Scope(ScopeType.PAGE)
056public class GroupsSubscriptionsAction extends InputController implements Serializable {
057
058    private static final long serialVersionUID = -2440187703248677446L;
059
060    private static final Labeler labeler = new Labeler("label.subscriptions");
061
062    @In(create = true, required = false)
063    protected transient CoreSession documentManager;
064
065    @In(create = true)
066    protected Principal currentUser;
067
068    @In(required = false)
069    @Out(required = false)
070    private List<String> selectedNotifications;
071
072    @In(create = true)
073    protected transient NotificationManager notificationManager;
074
075    private String selectedGrant;
076
077    private String selectedNotification;
078
079    private SelectItem[] permissionActionItems;
080
081    protected List<String> selectedEntries;
082
083    /**
084     * Gets all the notifications registered in the system.
085     */
086    public List<SelectItem> getNotificationList() {
087        String parentType = documentManager.getSuperParentType(navigationContext.getCurrentDocument());
088        List<Notification> notifs = notificationManager.getNotificationsForSubscriptions(parentType);
089        List<SelectItem> notifsResult = new ArrayList<SelectItem>();
090        for (Notification notification : notifs) {
091            String notifName = notification.getName();
092            String notifLabel = notification.getLabel();
093            notifsResult.add(new SelectItem(notifName, resourcesAccessor.getMessages().get(notifLabel)));
094        }
095        return notifsResult;
096    }
097
098    /**
099     * Registers the user's choices.
100     */
101    public void updateSubscriptions() {
102        List<String> selectedNotifications = getSelectedNotifications();
103        List<String> subscriptions = getSubscriptionsForCurrentUser();
104
105        List<String> newSubscriptions = getDisjunctElements(selectedNotifications, subscriptions);
106        List<String> removedSubscriptions = getDisjunctElements(subscriptions, selectedNotifications);
107
108        NuxeoPrincipal principal = (NuxeoPrincipal) currentUser;
109        DocumentModel currentDoc = navigationContext.getCurrentDocument();
110
111        // removing the unselected subscriptions
112        if (!removedSubscriptions.isEmpty()) {
113            for (String subscription : removedSubscriptions) {
114                notificationManager.removeSubscription("user:" + principal.getName(), subscription, currentDoc);
115            }
116        }
117
118        // adding the newly selected subscriptions
119        if (!newSubscriptions.isEmpty()) {
120            for (String subscription : newSubscriptions) {
121                notificationManager.addSubscription(NotificationConstants.USER_PREFIX + principal.getName(),
122                        subscription, currentDoc, false, principal, "");
123            }
124        }
125
126        facesMessages.add(StatusMessage.Severity.INFO,
127                resourcesAccessor.getMessages().get("label.notifications.registered"));
128    }
129
130    private static List<String> getDisjunctElements(List<String> array1, List<String> array2) {
131        List<String> result = new ArrayList<String>();
132        for (String elem1 : array1) {
133
134            if (!array2.contains(elem1)) {
135                result.add(elem1);
136            }
137        }
138        return result;
139    }
140
141    /**
142     * @return the previously selected notifications.
143     */
144    public List<String> getSelectedNotifications() {
145        if (selectedNotifications == null) {
146            selectedNotifications = getSubscriptionsForCurrentUser();
147        }
148        return selectedNotifications;
149    }
150
151    /**
152     * Returns the notifications that the user already subscribed for.
153     */
154    private List<String> getSubscriptionsForCurrentUser() {
155        DocumentModel currentDoc = navigationContext.getCurrentDocument();
156        NuxeoPrincipal principal = (NuxeoPrincipal) currentUser;
157        List<String> subscriptions = notificationManager.getSubscriptionsForUserOnDocument(
158                "user:" + principal.getName(), currentDoc);
159        return subscriptions;
160    }
161
162    /**
163     * Returns the users that subscribed to a notification.
164     */
165    public List<String> getSubscribedUsersForNotification(String notification) {
166        DocumentModel currentDoc = navigationContext.getCurrentDocument();
167        return notificationManager.getUsersSubscribedToNotificationOnDocument(notification, currentDoc);
168    }
169
170    /**
171     * Returns a map that contains all users and groups subscribed to notifications(keys).
172     */
173    public Map<String, List<String>> getUsersByNotificationsForCurrentDocument() {
174        Map<String, List<String>> result = new HashMap<String, List<String>>();
175
176        String superParentType = documentManager.getSuperParentType(navigationContext.getCurrentDocument());
177        List<Notification> notifications = notificationManager.getNotificationsForSubscriptions(superParentType);
178        for (Notification notification : notifications) {
179            result.put(notification.getLabel(), getSubscribedUsersForNotification(notification.getName()));
180        }
181        return result;
182    }
183
184    /**
185     * @param selectedNotifications The selectedNotifications to set.
186     */
187    public void setSelectedNotifications(List<String> selectedNotifications) {
188        this.selectedNotifications = selectedNotifications;
189    }
190
191    public SelectItem[] getNotificationActionItems() {
192        List<String> permissionActions = new ArrayList<String>();
193        List<SelectItem> jsfModelList = new ArrayList<SelectItem>();
194
195        permissionActions.add("Subscribe");
196        permissionActions.add("Unsubscribe");
197
198        for (String permissionAction : permissionActions) {
199            String label = labeler.makeLabel(permissionAction);
200            SelectItem it = new SelectItem(permissionAction, resourcesAccessor.getMessages().get(label));
201            jsfModelList.add(it);
202        }
203
204        permissionActionItems = jsfModelList.toArray(new SelectItem[0]);
205
206        return permissionActionItems;
207    }
208
209    public String getSelectedGrant() {
210        return selectedGrant;
211    }
212
213    public void setSelectedGrant(String selectedPermission) {
214        selectedGrant = selectedPermission;
215    }
216
217    public String getSelectedNotification() {
218        return selectedNotification;
219    }
220
221    public void setSelectedNotification(String selectedNotification) {
222        this.selectedNotification = selectedNotification;
223    }
224
225    public boolean getCanAddSubscriptions() {
226        return documentManager.hasPermission(currentDocument.getRef(), "WriteSecurity");
227    }
228
229    public String addSubscriptionsAndUpdate() {
230        if (selectedEntries == null || selectedEntries.isEmpty()) {
231            String message = ComponentUtils.translate(FacesContext.getCurrentInstance(),
232                    "error.notifManager.noUserSelected");
233            FacesMessages.instance().add(message);
234            return null;
235        }
236        String notificationName = resourcesAccessor.getMessages().get(
237                notificationManager.getNotificationByName(selectedNotification).getLabel());
238        boolean subscribe = selectedGrant.equals("Subscribe");
239
240        DocumentModel currentDoc = navigationContext.getCurrentDocument();
241        NuxeoPrincipal currentPrincipal = (NuxeoPrincipal) currentUser;
242
243        List<String> registeredNotifications = null;
244        if (subscribe) {
245            registeredNotifications = getSubscribedUsersForNotification(selectedNotification);
246        }
247
248        for (String selectedEntry : selectedEntries) {
249            if (subscribe) {
250                if (registeredNotifications == null || !registeredNotifications.contains(selectedEntry)) {
251                    notificationManager.addSubscription(selectedEntry, selectedNotification, currentDoc, true,
252                            currentPrincipal, notificationName);
253                } else {
254                    facesMessages.add(StatusMessage.Severity.WARN,
255                            resourcesAccessor.getMessages().get("label.notifications.alreadyRegistered"), selectedEntry);
256                }
257            } else {
258                notificationManager.removeSubscription(selectedEntry, selectedNotification, currentDoc);
259            }
260        }
261        // reset
262        selectedEntries = null;
263        facesMessages.add(StatusMessage.Severity.INFO,
264                resourcesAccessor.getMessages().get("label.notifications.registered"));
265        return null;
266    }
267
268    public List<String> getSelectedEntries() {
269        if (selectedEntries == null) {
270            selectedEntries = new ArrayList<String>();
271        }
272        return selectedEntries;
273    }
274
275    public void setSelectedEntries(List<String> selectedEntries) {
276        this.selectedEntries = selectedEntries;
277    }
278
279}