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