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