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(required = false)
068    @Out(required = false)
069    private List<String> selectedNotifications;
070
071    @In(create = true)
072    protected transient NotificationManager notificationManager;
073
074    private String selectedGrant;
075
076    private String selectedNotification;
077
078    private SelectItem[] permissionActionItems;
079
080    protected List<String> selectedEntries;
081
082    /**
083     * Gets all the notifications registered in the system.
084     */
085    public List<SelectItem> getNotificationList() {
086        String parentType = documentManager.getSuperParentType(navigationContext.getCurrentDocument());
087        List<Notification> notifs = notificationManager.getNotificationsForSubscriptions(parentType);
088        List<SelectItem> notifsResult = new ArrayList<SelectItem>();
089        for (Notification notification : notifs) {
090            String notifName = notification.getName();
091            String notifLabel = notification.getLabel();
092            notifsResult.add(new SelectItem(notifName, resourcesAccessor.getMessages().get(notifLabel)));
093        }
094        return notifsResult;
095    }
096
097    /**
098     * Registers the user's choices.
099     */
100    public void updateSubscriptions() {
101        List<String> selectedNotifications = getSelectedNotifications();
102        List<String> subscriptions = getSubscriptionsForCurrentUser();
103
104        List<String> newSubscriptions = getDisjunctElements(selectedNotifications, subscriptions);
105        List<String> removedSubscriptions = getDisjunctElements(subscriptions, selectedNotifications);
106
107        DocumentModel currentDoc = navigationContext.getCurrentDocument();
108
109        // removing the unselected subscriptions
110        if (!removedSubscriptions.isEmpty()) {
111            for (String subscription : removedSubscriptions) {
112                notificationManager.removeSubscription("user:" + currentUser.getName(), subscription, currentDoc);
113            }
114        }
115
116        // adding the newly selected subscriptions
117        if (!newSubscriptions.isEmpty()) {
118            for (String subscription : newSubscriptions) {
119                notificationManager.addSubscription(NotificationConstants.USER_PREFIX + currentUser.getName(),
120                        subscription, currentDoc, false, currentUser, "");
121            }
122        }
123
124        facesMessages.add(StatusMessage.Severity.INFO,
125                resourcesAccessor.getMessages().get("label.notifications.registered"));
126    }
127
128    private static List<String> getDisjunctElements(List<String> array1, List<String> array2) {
129        List<String> result = new ArrayList<String>();
130        for (String elem1 : array1) {
131
132            if (!array2.contains(elem1)) {
133                result.add(elem1);
134            }
135        }
136        return result;
137    }
138
139    /**
140     * @return the previously selected notifications.
141     */
142    public List<String> getSelectedNotifications() {
143        if (selectedNotifications == null) {
144            selectedNotifications = getSubscriptionsForCurrentUser();
145        }
146        return selectedNotifications;
147    }
148
149    /**
150     * Returns the notifications that the user already subscribed for.
151     */
152    private List<String> getSubscriptionsForCurrentUser() {
153        DocumentModel currentDoc = navigationContext.getCurrentDocument();
154        List<String> subscriptions = notificationManager.getSubscriptionsForUserOnDocument(
155                "user:" + currentUser.getName(), currentDoc);
156        return subscriptions;
157    }
158
159    /**
160     * Returns the users that subscribed to a notification.
161     */
162    public List<String> getSubscribedUsersForNotification(String notification) {
163        DocumentModel currentDoc = navigationContext.getCurrentDocument();
164        return notificationManager.getUsersSubscribedToNotificationOnDocument(notification, currentDoc);
165    }
166
167    /**
168     * Returns a map that contains all users and groups subscribed to notifications(keys).
169     */
170    public Map<String, List<String>> getUsersByNotificationsForCurrentDocument() {
171        Map<String, List<String>> result = new HashMap<String, List<String>>();
172
173        String superParentType = documentManager.getSuperParentType(navigationContext.getCurrentDocument());
174        List<Notification> notifications = notificationManager.getNotificationsForSubscriptions(superParentType);
175        for (Notification notification : notifications) {
176            result.put(notification.getLabel(), getSubscribedUsersForNotification(notification.getName()));
177        }
178        return result;
179    }
180
181    /**
182     * @param selectedNotifications The selectedNotifications to set.
183     */
184    public void setSelectedNotifications(List<String> selectedNotifications) {
185        this.selectedNotifications = selectedNotifications;
186    }
187
188    public SelectItem[] getNotificationActionItems() {
189        List<String> permissionActions = new ArrayList<String>();
190        List<SelectItem> jsfModelList = new ArrayList<SelectItem>();
191
192        permissionActions.add("Subscribe");
193        permissionActions.add("Unsubscribe");
194
195        for (String permissionAction : permissionActions) {
196            String label = labeler.makeLabel(permissionAction);
197            SelectItem it = new SelectItem(permissionAction, resourcesAccessor.getMessages().get(label));
198            jsfModelList.add(it);
199        }
200
201        permissionActionItems = jsfModelList.toArray(new SelectItem[0]);
202
203        return permissionActionItems;
204    }
205
206    public String getSelectedGrant() {
207        return selectedGrant;
208    }
209
210    public void setSelectedGrant(String selectedPermission) {
211        selectedGrant = selectedPermission;
212    }
213
214    public String getSelectedNotification() {
215        return selectedNotification;
216    }
217
218    public void setSelectedNotification(String selectedNotification) {
219        this.selectedNotification = selectedNotification;
220    }
221
222    public boolean getCanAddSubscriptions() {
223        return documentManager.hasPermission(currentDocument.getRef(), "WriteSecurity");
224    }
225
226    public String addSubscriptionsAndUpdate() {
227        if (selectedEntries == null || selectedEntries.isEmpty()) {
228            String message = ComponentUtils.translate(FacesContext.getCurrentInstance(),
229                    "error.notifManager.noUserSelected");
230            FacesMessages.instance().add(message);
231            return null;
232        }
233        String notificationName = resourcesAccessor.getMessages().get(
234                notificationManager.getNotificationByName(selectedNotification).getLabel());
235        boolean subscribe = selectedGrant.equals("Subscribe");
236
237        DocumentModel currentDoc = navigationContext.getCurrentDocument();
238
239        List<String> registeredNotifications = null;
240        if (subscribe) {
241            registeredNotifications = getSubscribedUsersForNotification(selectedNotification);
242        }
243
244        for (String selectedEntry : selectedEntries) {
245            if (subscribe) {
246                if (registeredNotifications == null || !registeredNotifications.contains(selectedEntry)) {
247                    notificationManager.addSubscription(selectedEntry, selectedNotification, currentDoc, true,
248                            currentUser, notificationName);
249                } else {
250                    facesMessages.add(StatusMessage.Severity.WARN,
251                            resourcesAccessor.getMessages().get("label.notifications.alreadyRegistered"), selectedEntry);
252                }
253            } else {
254                notificationManager.removeSubscription(selectedEntry, selectedNotification, currentDoc);
255            }
256        }
257        // reset
258        selectedEntries = null;
259        facesMessages.add(StatusMessage.Severity.INFO,
260                resourcesAccessor.getMessages().get("label.notifications.registered"));
261        return null;
262    }
263
264    public List<String> getSelectedEntries() {
265        if (selectedEntries == null) {
266            selectedEntries = new ArrayList<String>();
267        }
268        return selectedEntries;
269    }
270
271    public void setSelectedEntries(List<String> selectedEntries) {
272        this.selectedEntries = selectedEntries;
273    }
274
275}