001/*
002 * (C) Copyright 2012 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 *     Anahide Tchertchian, Antoine Taillefer
018 */
019package org.nuxeo.ecm.platform.task.web;
020
021import java.util.ArrayList;
022import java.util.List;
023
024import org.jboss.seam.ScopeType;
025import org.jboss.seam.annotations.Factory;
026import org.jboss.seam.annotations.In;
027import org.jboss.seam.annotations.Name;
028import org.jboss.seam.annotations.Observer;
029import org.jboss.seam.annotations.Scope;
030import org.jboss.seam.annotations.intercept.BypassInterceptors;
031import org.jboss.seam.core.Events;
032import org.jboss.seam.faces.FacesMessages;
033import org.jboss.seam.international.LocaleSelector;
034import org.jboss.seam.international.StatusMessage;
035import org.nuxeo.ecm.core.api.CoreSession;
036import org.nuxeo.ecm.core.api.DocumentModel;
037import org.nuxeo.ecm.core.api.NuxeoPrincipal;
038import org.nuxeo.ecm.platform.contentview.seam.ContentViewActions;
039import org.nuxeo.ecm.platform.task.Task;
040import org.nuxeo.ecm.platform.task.TaskEventNames;
041import org.nuxeo.ecm.platform.task.TaskService;
042import org.nuxeo.ecm.platform.task.core.helpers.TaskActorsHelper;
043import org.nuxeo.ecm.platform.task.dashboard.DashBoardItem;
044import org.nuxeo.ecm.platform.task.dashboard.DashBoardItemImpl;
045import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
046import org.nuxeo.ecm.platform.ui.web.invalidations.AutomaticDocumentBasedInvalidation;
047import org.nuxeo.ecm.platform.ui.web.invalidations.DocumentContextBoundActionBean;
048import org.nuxeo.ecm.webapp.helpers.EventNames;
049import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor;
050
051/**
052 * Seam component holding tasks actions created using the {@link TaskService} in document context cache.
053 *
054 * @author Anahide Tchertchian
055 */
056@Name("taskActions")
057@Scope(ScopeType.CONVERSATION)
058@AutomaticDocumentBasedInvalidation
059public class TaskActionsBean extends DocumentContextBoundActionBean {
060
061    private static final long serialVersionUID = 1L;
062
063    /**
064     * @since 7.2
065     */
066    public static final String TASKS_CACHE_RESET = "tasksCacheReset";
067
068    @In(create = true, required = false)
069    protected transient CoreSession documentManager;
070
071    @In(create = true)
072    protected ContentViewActions contentViewActions;
073
074    @In(create = true)
075    protected transient TaskService taskService;
076
077    @In(create = true)
078    protected transient NavigationContext navigationContext;
079
080    @In(create = true, required = false)
081    protected FacesMessages facesMessages;
082
083    @In(create = true)
084    protected ResourcesAccessor resourcesAccessor;
085
086    @In(create = true)
087    protected transient LocaleSelector localeSelector;
088
089    protected List<Task> tasks;
090
091    protected List<DashBoardItem> items;
092
093    protected String comment;
094
095    @Factory(value = "currentSingleTasks", scope = ScopeType.EVENT)
096    public List<Task> getCurrentDocumentTasks() {
097        if (tasks == null) {
098            tasks = new ArrayList<Task>();
099            DocumentModel currentDocument = navigationContext.getCurrentDocument();
100            if (currentDocument != null) {
101                NuxeoPrincipal principal = (NuxeoPrincipal) documentManager.getPrincipal();
102                List<String> actors = new ArrayList<String>();
103                actors.addAll(TaskActorsHelper.getTaskActors(principal));
104                tasks = taskService.getTaskInstances(currentDocument, actors, true, documentManager);
105            }
106        }
107        return tasks;
108    }
109
110    @Factory(value = "currentDashBoardItems", scope = ScopeType.EVENT)
111    public List<DashBoardItem> getCurrentDashBoardItems() {
112        if (items == null) {
113            items = new ArrayList<DashBoardItem>();
114            for (Task task : getCurrentDocumentTasks()) {
115                DashBoardItem item = new DashBoardItemImpl(task, navigationContext.getCurrentDocument(),
116                        localeSelector.getLocale());
117                items.add(item);
118            }
119        }
120        return items;
121    }
122
123    @Factory(value = "currentDashBoardItemsExceptPublishingTasks", scope = ScopeType.EVENT)
124    public List<DashBoardItem> getCurrentDashBoardItemsExceptPublishingTasks() {
125        if (items == null) {
126            items = new ArrayList<DashBoardItem>();
127            for (Task task : getCurrentDocumentTasks()) {
128                String taskType = task.getVariable(Task.TaskVariableName.taskType.name());
129                if (!"publish_moderate".equals(taskType)) {
130                    DashBoardItem item = new DashBoardItemImpl(task, navigationContext.getCurrentDocument(),
131                            localeSelector.getLocale());
132                    items.add(item);
133                }
134            }
135        }
136        return items;
137    }
138
139    public String getComment() {
140        return comment;
141    }
142
143    public void setComment(String comment) {
144        this.comment = comment;
145    }
146
147    public void acceptTask(Task task) {
148        acceptTask(task, getComment());
149        setComment(null);
150    }
151
152    public void acceptTask(Task task, String comment) {
153        String seamEventName = taskService.acceptTask(documentManager, (NuxeoPrincipal) documentManager.getPrincipal(),
154                task, comment);
155        if (seamEventName != null) {
156            Events.instance().raiseEvent(seamEventName);
157        }
158    }
159
160    public void rejectTask(Task task) {
161        String userComment = getComment();
162        if (userComment != null && !"".equals(userComment)) {
163            rejectTask(task, userComment);
164            setComment(null);
165        } else {
166            facesMessages.add(StatusMessage.Severity.ERROR,
167                    resourcesAccessor.getMessages().get("label.review.task.enterComment"));
168        }
169
170    }
171
172    public void rejectTask(Task task, String comment) {
173        String seamEventName = taskService.rejectTask(documentManager, (NuxeoPrincipal) documentManager.getPrincipal(),
174                task, comment);
175        if (seamEventName != null) {
176            Events.instance().raiseEvent(seamEventName);
177        }
178    }
179
180    @Override
181    public void resetBeanCache(DocumentModel newCurrentDocumentModel) {
182        resetCache();
183    }
184
185    @Observer(value = { TaskEventNames.WORKFLOW_ENDED, TaskEventNames.WORKFLOW_NEW_STARTED,
186            TaskEventNames.WORKFLOW_TASK_START, TaskEventNames.WORKFLOW_TASK_STOP,
187            TaskEventNames.WORKFLOW_TASK_REJECTED, TaskEventNames.WORKFLOW_USER_ASSIGNMENT_CHANGED,
188            TaskEventNames.WORKFLOW_TASK_REASSIGNED, TaskEventNames.WORKFLOW_TASK_DELEGATED,
189            TaskEventNames.WORKFLOW_TASK_COMPLETED, TaskEventNames.WORKFLOW_TASK_REMOVED,
190            TaskEventNames.WORK_ITEMS_LIST_LOADED, TaskEventNames.WORKFLOW_TASKS_COMPUTED,
191            TaskEventNames.WORKFLOW_ABANDONED, TaskEventNames.WORKFLOW_CANCELED, EventNames.DOMAIN_SELECTION_CHANGED,
192            "documentPublicationRejected", "documentPublished" }, create = false)
193    @BypassInterceptors
194    public void resetCache() {
195        tasks = null;
196        items = null;
197        Events.instance().raiseEvent(TASKS_CACHE_RESET);
198    }
199
200    /**
201     * @since 7.2
202     */
203    @Observer({ TASKS_CACHE_RESET })
204    public void resetTasksCache() {
205        contentViewActions.refreshOnSeamEvent(TASKS_CACHE_RESET);
206        contentViewActions.resetPageProviderOnSeamEvent(TASKS_CACHE_RESET);
207    }
208
209}