001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 */
016package org.nuxeo.ecm.platform.task.core.service;
017
018import java.io.Serializable;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.commons.lang.StringUtils;
025import org.nuxeo.ecm.core.api.CoreSession;
026import org.nuxeo.ecm.core.api.DocumentModel;
027import org.nuxeo.ecm.core.api.DocumentModelList;
028import org.nuxeo.ecm.core.api.NuxeoException;
029import org.nuxeo.ecm.core.api.NuxeoPrincipal;
030import org.nuxeo.ecm.core.api.SortInfo;
031import org.nuxeo.ecm.platform.query.api.PageProvider;
032import org.nuxeo.ecm.platform.query.api.PageProviderDefinition;
033import org.nuxeo.ecm.platform.query.api.PageProviderService;
034import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider;
035import org.nuxeo.ecm.platform.task.Task;
036import org.nuxeo.ecm.platform.task.TaskEventNames;
037import org.nuxeo.ecm.platform.task.TaskProvider;
038import org.nuxeo.ecm.platform.task.TaskQueryConstant;
039import org.nuxeo.ecm.platform.task.TaskService;
040import org.nuxeo.ecm.platform.task.core.helpers.TaskActorsHelper;
041import org.nuxeo.runtime.api.Framework;
042
043/**
044 * @author Laurent Doguin
045 * @author Antoine Taillefer
046 * @since 5.5
047 */
048public class DocumentTaskProvider implements TaskProvider {
049
050    private static final long serialVersionUID = 1L;
051
052    @Override
053    public List<Task> getCurrentTaskInstances(CoreSession coreSession) {
054
055        // Get tasks for current user
056        // We need to build the task actors list: prefixed and unprefixed names
057        // of the principal and all its groups
058        NuxeoPrincipal principal = (NuxeoPrincipal) coreSession.getPrincipal();
059        List<String> actors = TaskActorsHelper.getTaskActors(principal);
060
061        return getCurrentTaskInstances(actors, coreSession);
062    }
063
064    /**
065     * Provide @param sortInfo to handle sort page-provider contributions (see {@link #getCurrentTaskInstances})
066     *
067     * @since 5.9.3
068     */
069    @Override
070    public List<Task> getCurrentTaskInstances(CoreSession coreSession, List<SortInfo> sortInfos) {
071
072        // Get tasks for current user
073        // We need to build the task actors list: prefixed and unprefixed names
074        // of the principal and all its groups
075        NuxeoPrincipal principal = (NuxeoPrincipal) coreSession.getPrincipal();
076        List<String> actors = TaskActorsHelper.getTaskActors(principal);
077
078        return getCurrentTaskInstances(actors, coreSession, sortInfos);
079    }
080
081    /**
082     * Returns a list of task instances assigned to one of the actors in the list or to its pool.
083     *
084     * @param actors a list used as actorId to retrieve the tasks.
085     * @param filter
086     * @return
087     */
088    @Override
089    public List<Task> getCurrentTaskInstances(List<String> actors, CoreSession coreSession) {
090        if (actors == null || actors.isEmpty()) {
091            return new ArrayList<Task>();
092        }
093        return getTasks(TaskQueryConstant.GET_TASKS_FOR_ACTORS_PP, coreSession, true, null, actors);
094    }
095
096    /**
097     * Provide @param sortInfo to handle sort page-provider contributions (see {@link #getCurrentTaskInstances})
098     *
099     * @since 5.9.3
100     */
101    @Override
102    public List<Task> getCurrentTaskInstances(List<String> actors, CoreSession coreSession, List<SortInfo> sortInfos)
103            {
104        if (actors == null || actors.isEmpty()) {
105            return new ArrayList<Task>();
106        }
107        return getTasks(TaskQueryConstant.GET_TASKS_FOR_ACTORS_PP, coreSession, true, sortInfos, actors);
108    }
109
110    @Override
111    public List<Task> getTaskInstances(DocumentModel dm, NuxeoPrincipal user, CoreSession coreSession)
112            {
113        if (user == null) {
114            return getTasks(TaskQueryConstant.GET_TASKS_FOR_TARGET_DOCUMENTS_PP, coreSession, true, null, dm.getId(),
115                    dm.getId());
116        } else {
117            List<String> actors = TaskActorsHelper.getTaskActors(user);
118            return getTasks(TaskQueryConstant.GET_TASKS_FOR_TARGET_DOCUMENTS_AND_ACTORS_PP, coreSession, true, null,
119                    dm.getId(), dm.getId(), actors);
120        }
121    }
122
123    @Override
124    public List<Task> getTaskInstances(DocumentModel dm, List<String> actors, CoreSession coreSession)
125            {
126        if (actors == null || actors.isEmpty()) {
127            return new ArrayList<Task>();
128        }
129        return getTasks(TaskQueryConstant.GET_TASKS_FOR_TARGET_DOCUMENTS_AND_ACTORS_PP, coreSession, true, null,
130                dm.getId(), dm.getId(), actors);
131    }
132
133    @Override
134    public List<Task> getAllTaskInstances(String processId, CoreSession session) {
135        return getTasks(TaskQueryConstant.GET_TASKS_FOR_PROCESS_PP, session, true, null, processId);
136    }
137
138    @Override
139    public List<Task> getAllTaskInstances(String processId, NuxeoPrincipal user, CoreSession session)
140            {
141        List<String> actors = TaskActorsHelper.getTaskActors(user);
142        return getAllTaskInstances(processId, actors, session);
143    }
144
145    @Override
146    public List<Task> getAllTaskInstances(String processId, List<String> actors, CoreSession session)
147            {
148        return getTasks(TaskQueryConstant.GET_TASKS_FOR_PROCESS_AND_ACTORS_PP, session, true, null, processId, actors);
149    }
150
151    /**
152     * Converts a {@link DocumentModelList} to a list of {@link Task}s.
153     *
154     * @since 6.0
155     * @param taskDocuments
156     */
157    public static List<Task> wrapDocModelInTask(List<DocumentModel> taskDocuments) {
158        List<Task> tasks = new ArrayList<Task>();
159        for (DocumentModel doc : taskDocuments) {
160            tasks.add(doc.getAdapter(Task.class));
161        }
162        return tasks;
163    }
164
165    /**
166     * @deprecated since 6.0, use {@link #wrapDocModelInTask(List)} instead.
167     */
168    @Deprecated
169    public static List<Task> wrapDocModelInTask(DocumentModelList taskDocuments) {
170        return wrapDocModelInTask(taskDocuments, false);
171    }
172
173    /**
174     * Converts a {@link DocumentModelList} to a list of {@link Task}s.
175     *
176     * @param detach if {@code true}, detach each document before converting it to a {@code Task}.
177     * @deprecated since 6.0, use {@link #wrapDocModelInTask(List)} instead.
178     */
179    @Deprecated
180    public static List<Task> wrapDocModelInTask(DocumentModelList taskDocuments, boolean detach) {
181        List<Task> tasks = new ArrayList<Task>();
182        for (DocumentModel doc : taskDocuments) {
183            if (detach) {
184                doc.detach(true);
185            }
186            tasks.add(doc.getAdapter(Task.class));
187        }
188        return tasks;
189    }
190
191    @Override
192    public String endTask(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment,
193            String eventName, boolean isValidated) {
194
195        // put user comment on the task
196        if (!StringUtils.isEmpty(comment)) {
197            task.addComment(principal.getName(), comment);
198        }
199
200        // end the task, adding boolean marker that task was validated or
201        // rejected
202        task.setVariable(TaskService.VariableName.validated.name(), String.valueOf(isValidated));
203        task.end(coreSession);
204        // make sure taskDoc is attached to prevent sending event with null session
205        DocumentModel taskDocument = task.getDocument();
206        if (taskDocument.getSessionId() == null) {
207            taskDocument.attach(coreSession.getSessionId());
208        }
209        coreSession.saveDocument(taskDocument);
210        if (StringUtils.isNotBlank(eventName)) {
211            TaskEventNotificationHelper.notifyTaskEnded(coreSession, principal, task, comment, eventName, null);
212        }
213        String seamEventName = isValidated ? TaskEventNames.WORKFLOW_TASK_COMPLETED
214                : TaskEventNames.WORKFLOW_TASK_REJECTED;
215        return seamEventName;
216    }
217
218
219
220    @Override
221    public List<Task> getAllTaskInstances(String processId, String nodeId, CoreSession session) {
222        return getTasks(TaskQueryConstant.GET_TASKS_FOR_PROCESS_AND_NODE_PP, session, true, null, processId, nodeId);
223    }
224
225    @Override
226    public List<Task> getTaskInstances(DocumentModel dm, List<String> actors, boolean includeDelegatedTasks,
227            CoreSession session) {
228        if (includeDelegatedTasks) {
229            return getTasks(TaskQueryConstant.GET_TASKS_FOR_TARGET_DOCUMENTS_AND_ACTORS_OR_DELEGATED_ACTORS_PP,
230                    session, true, null, dm.getId(), dm.getId(), actors, actors);
231        } else {
232            return getTasks(TaskQueryConstant.GET_TASKS_FOR_TARGET_DOCUMENTS_AND_ACTORS_PP, session, true, null,
233                    dm.getId(), dm.getId(), actors);
234        }
235    }
236
237    @Override
238    public List<Task> getAllCurrentTaskInstances(CoreSession session,
239            List<SortInfo> sortInfos) {
240        // Get tasks for current user
241        // We need to build the task actors list: prefixed and unprefixed names
242        // of the principal and all its groups
243        NuxeoPrincipal principal = (NuxeoPrincipal) session.getPrincipal();
244        List<String> actors = TaskActorsHelper.getTaskActors(principal);
245
246        return getTasks(TaskQueryConstant.GET_TASKS_FOR_ACTORS_OR_DELEGATED_ACTORS_PP, session, true, sortInfos,
247                actors, actors);
248    }
249
250    /**
251     * @since 6.0
252     */
253    @SuppressWarnings("unchecked")
254    public static List<Task> getTasks(String pageProviderName, CoreSession session, boolean unrestricted,
255            List<SortInfo> sortInfos, Object... params) {
256        PageProviderService ppService = Framework.getService(PageProviderService.class);
257        if (ppService == null) {
258            throw new RuntimeException("Missing PageProvider service");
259        }
260        Map<String, Serializable> props = new HashMap<String, Serializable>();
261        // first retrieve potential props from definition
262        PageProviderDefinition def = ppService.getPageProviderDefinition(pageProviderName);
263        if (def != null) {
264            Map<String, String> defProps = def.getProperties();
265            if (defProps != null) {
266                props.putAll(defProps);
267            }
268        }
269        props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) session);
270        if (unrestricted) {
271            props.put(CoreQueryDocumentPageProvider.USE_UNRESTRICTED_SESSION_PROPERTY, Boolean.TRUE);
272        }
273        PageProvider<DocumentModel> pp = (PageProvider<DocumentModel>) ppService.getPageProvider(pageProviderName,
274                sortInfos, null, null, props, params);
275        if (pp == null) {
276            throw new NuxeoException("Page provider not found: " + pageProviderName);
277        }
278        return wrapDocModelInTask(pp.getCurrentPage());
279    }
280
281}