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