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.util.ArrayList;
026import java.util.List;
027
028import javax.faces.context.FacesContext;
029
030import org.apache.commons.logging.Log;
031import org.apache.commons.logging.LogFactory;
032import org.jboss.seam.ScopeType;
033import org.jboss.seam.annotations.Factory;
034import org.jboss.seam.annotations.In;
035import org.jboss.seam.annotations.Name;
036import org.jboss.seam.annotations.Observer;
037import org.jboss.seam.annotations.Scope;
038import org.jboss.seam.annotations.datamodel.DataModel;
039import org.jboss.seam.annotations.datamodel.DataModelSelection;
040import org.jboss.seam.annotations.intercept.BypassInterceptors;
041import org.jboss.seam.faces.FacesMessages;
042import org.jboss.seam.international.StatusMessage;
043import org.nuxeo.ecm.core.api.CoreSession;
044import org.nuxeo.ecm.core.api.DocumentModel;
045import org.nuxeo.ecm.core.api.NuxeoPrincipal;
046import org.nuxeo.ecm.platform.ec.notification.NotificationConstants;
047import org.nuxeo.ecm.platform.notification.api.Notification;
048import org.nuxeo.ecm.platform.notification.api.NotificationManager;
049import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
050import org.nuxeo.ecm.webapp.base.InputController;
051import org.nuxeo.ecm.webapp.helpers.EventNames;
052import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor;
053
054/**
055 * Handles the subscriptions page.
056 *
057 * @author <a href="mailto:npaslaru@nuxeo.com">Narcis Paslaru</a>
058 */
059@Name("subscriptionAction")
060@Scope(ScopeType.PAGE)
061public class SubscriptionsAction extends InputController implements Serializable {
062
063    private static final long serialVersionUID = -2440187703248677446L;
064
065    private static final Log log = LogFactory.getLog(SubscriptionsAction.class);
066
067    @In
068    protected transient NavigationContext navigationContext;
069
070    @In(create = true, required = false)
071    protected transient CoreSession documentManager;
072
073    @DataModel("notificationList")
074    protected List<SelectableSubscription> notificationList;
075
076    @DataModel("inheritedNotifications")
077    private List<Notification> inheritedNotifications;
078
079    @DataModelSelection(value = "notificationList")
080    private SelectableSubscription currentSubscription;
081
082    @In(create = true)
083    protected transient NotificationManager notificationManager;
084
085    @In(create = true, required = false)
086    protected transient FacesMessages facesMessages;
087
088    @In(create = true)
089    protected ResourcesAccessor resourcesAccessor;
090
091    public static final String CONFIRM_FOLLOW = "label.subscriptions.follow.confirm";
092
093    public static final String CONFIRM_UNFOLLOW = "label.subscriptions.unfollow.confirm";
094
095    /**
096     * Gets all the notifications the user may subscribe to.
097     */
098    @Factory("notificationList")
099    public void getNotificationsList() {
100        log.debug("Factory for notifications list");
101
102        DocumentModel currentDocument = navigationContext.getCurrentDocument();
103        String superParentType = documentManager.getSuperParentType(currentDocument);
104
105        List<Notification> notifs = notificationManager.getNotificationsForSubscriptions(superParentType);
106
107        List<String> subscriptions = getSelectedNotifications();
108        log.debug("Selected notifications : " + subscriptions);
109
110        List<SelectableSubscription> notifsResult = new ArrayList<SelectableSubscription>();
111        for (Notification notification : notifs) {
112            String notifName = notification.getName();
113            if (subscriptions.contains(notifName)) {
114                notifsResult.add(new SelectableSubscription(true, notification));
115            } else {
116                notifsResult.add(new SelectableSubscription(false, notification));
117            }
118        }
119        notificationList = notifsResult;
120    }
121
122    /**
123     * Gets all the notifications the user may subscribe to.
124     */
125    @Factory("inheritedNotifications")
126    public void loadInheritedNotifications() throws ClassNotFoundException {
127        inheritedNotifications = new ArrayList<Notification>();
128        DocumentModel currentDoc = navigationContext.getCurrentDocument();
129        NuxeoPrincipal principal = (NuxeoPrincipal) FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
130        for (String group : principal.getAllGroups()) {
131            List<String> notifs = notificationManager.getSubscriptionsForUserOnDocument("group:" + group,
132                    currentDoc);
133            for (String inheritedNotification : notifs) {
134                Notification notif = notificationManager.getNotificationByName(inheritedNotification);
135                inheritedNotifications.add(notif);
136            }
137        }
138    }
139
140    /**
141     * Registers the user's choices.
142     */
143    public void updateSubscriptions() {
144
145        NuxeoPrincipal principal = (NuxeoPrincipal) FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
146        DocumentModel currentDoc = navigationContext.getCurrentDocument();
147        if (currentSubscription.isSelected()) {
148            notificationManager.removeSubscription("user:" + principal.getName(),
149                    currentSubscription.getNotification().getName(), currentDoc);
150        } else {
151            notificationManager.addSubscription(NotificationConstants.USER_PREFIX + principal.getName(),
152                    currentSubscription.getNotification().getName(), currentDoc, false, principal, "");
153        }
154        getNotificationsList();
155    }
156
157    /**
158     * Manage (un)subscription to all notifications
159     */
160    public void updateAllSubscriptions() {
161        NuxeoPrincipal principal = (NuxeoPrincipal) FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
162        DocumentModel currentDoc = navigationContext.getCurrentDocument();
163        List<String> userSubscriptions = notificationManager.getSubscriptionsForUserOnDocument(
164                NotificationConstants.USER_PREFIX + principal.getName(), currentDoc);
165        if (userSubscriptions.size() == 0) {
166            notificationManager.addSubscriptions(NotificationConstants.USER_PREFIX + principal.getName(), currentDoc,
167                    false, principal);
168            facesMessages.add(StatusMessage.Severity.INFO, resourcesAccessor.getMessages().get(CONFIRM_FOLLOW));
169        } else {
170            notificationManager.removeSubscriptions(NotificationConstants.USER_PREFIX + principal.getName(),
171                    userSubscriptions, currentDoc);
172            facesMessages.add(StatusMessage.Severity.INFO, resourcesAccessor.getMessages().get(CONFIRM_UNFOLLOW));
173        }
174        getNotificationsList();
175    }
176
177    @Observer(value = EventNames.DOCUMENT_SELECTION_CHANGED, create = false)
178    @BypassInterceptors
179    public void invalidateNotificationsSelection() {
180        log.debug("Invalidate archive records.................");
181        notificationList = null;
182        currentSubscription = null;
183        inheritedNotifications = null;
184    }
185
186    /**
187     * @return the previously selected notifications.
188     */
189    public List<String> getSelectedNotifications() {
190        return getSubscriptionsForCurrentUser();
191    }
192
193    /**
194     * Returns the notifications that the user already subscribed for.
195     */
196    private List<String> getSubscriptionsForCurrentUser() {
197
198        DocumentModel currentDoc = navigationContext.getCurrentDocument();
199        NuxeoPrincipal principal = (NuxeoPrincipal) FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
200        List<String> subscriptions = notificationManager.getSubscriptionsForUserOnDocument(
201                "user:" + principal.getName(), currentDoc);
202        return subscriptions;
203    }
204
205    public SelectableSubscription getCurrentSubscription() {
206        return currentSubscription;
207    }
208
209    public void setCurrentSubscription(SelectableSubscription currentSubscription) {
210        this.currentSubscription = currentSubscription;
211    }
212
213    public List<SelectableSubscription> getNotificationList() {
214        return notificationList;
215    }
216
217    public void setNotificationList(List<SelectableSubscription> notificationList) {
218        this.notificationList = notificationList;
219    }
220
221    public List<Notification> getInheritedNotifications() {
222        return inheritedNotifications;
223    }
224
225    public void setInheritedNotifications(List<Notification> inheritedNotifications) {
226        this.inheritedNotifications = inheritedNotifications;
227    }
228
229}