001/*
002 * (C) Copyright 2019 Nuxeo (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 *     Guillaume Renard
018 */
019package org.nuxeo.ecm.platform.routing.core.provider;
020
021import static java.util.stream.Collectors.toList;
022import static org.nuxeo.ecm.core.query.sql.NXQL.ECM_UUID;
023
024import java.io.Serializable;
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.List;
028import java.util.Map;
029
030import org.apache.commons.lang3.StringUtils;
031import org.nuxeo.ecm.core.api.CoreSession;
032import org.nuxeo.ecm.core.api.IdRef;
033import org.nuxeo.ecm.core.api.NuxeoException;
034import org.nuxeo.ecm.core.api.NuxeoPrincipal;
035import org.nuxeo.ecm.core.api.PartialList;
036import org.nuxeo.ecm.core.query.sql.NXQL;
037import org.nuxeo.ecm.platform.query.api.AbstractPageProvider;
038import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider;
039import org.nuxeo.ecm.platform.task.Task;
040import org.nuxeo.ecm.platform.task.TaskConstants;
041import org.nuxeo.ecm.platform.task.core.helpers.TaskActorsHelper;
042import org.nuxeo.ecm.platform.usermanager.UserManager;
043import org.nuxeo.runtime.api.Framework;
044
045/**
046 * Page provider to retrieve workflow tasks. Two parameters are taken into account:
047 *
048 * <pre>
049 * - the actorId at index 0 of {@link RoutingTaskPageProvider#getParameters()}
050 * - workflowInstanceId at index 1 of {@link RoutingTaskPageProvider#getParameters()}
051 * </pre>
052 *
053 * Results are ordered by due date ascending.
054 *
055 * @since 11.1
056 */
057public class RoutingTaskPageProvider extends AbstractPageProvider<Task> {
058
059    private static final long serialVersionUID = 1L;
060
061    @Override
062    public List<Task> getCurrentPage() {
063        Object[] parameters = getParameters();
064        if (parameters == null || parameters.length != 2) {
065            throw new IllegalStateException("Invalid parameters: " + Arrays.toString(parameters));
066        }
067        String actorId = (String) parameters[0];
068        String workflowInstanceId = (String) parameters[1];
069        CoreSession session = getCoreSession();
070        StringBuilder query = new StringBuilder(
071                String.format("SELECT * FROM Document WHERE ecm:mixinType = '%s' AND ecm:currentLifeCycleState = '%s'",
072                        TaskConstants.TASK_FACET_NAME, TaskConstants.TASK_OPENED_LIFE_CYCLE_STATE));
073        if (StringUtils.isNotBlank(actorId)) {
074            List<String> actors = new ArrayList<>();
075            UserManager userManager = Framework.getService(UserManager.class);
076            NuxeoPrincipal principal = userManager.getPrincipal(actorId);
077            if (principal != null) {
078                for (String actor : TaskActorsHelper.getTaskActors(principal)) {
079                    actors.add(NXQL.escapeString(actor));
080                }
081            } else {
082                actors.add(NXQL.escapeString(actorId));
083            }
084            String actorsParam = String.join(", ", actors);
085            query.append(String.format(" AND (nt:actors/* IN (%s) OR nt:delegatedActors/* IN (%s))", actorsParam,
086                    actorsParam));
087        }
088        if (StringUtils.isNotBlank(workflowInstanceId)) {
089            query.append(String.format(" AND nt:processId = %s", NXQL.escapeString(workflowInstanceId)));
090        }
091        query.append(String.format(" ORDER BY %s ASC", TaskConstants.TASK_DUE_DATE_PROPERTY_NAME));
092
093        PartialList<Map<String, Serializable>> results = session.queryProjection(query.toString(), getPageSize(),
094                getCurrentPageOffset(), true);
095        setResultsCount(results.totalSize());
096        return results.stream()
097                      .map(map -> session.getDocument(new IdRef((String) map.get(ECM_UUID))))
098                      .map(doc -> doc.getAdapter(Task.class))
099                      .collect(toList());
100    }
101
102    protected CoreSession getCoreSession() {
103        Map<String, Serializable> props = getProperties();
104        CoreSession coreSession = (CoreSession) props.get(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY);
105        if (coreSession == null) {
106            throw new NuxeoException("cannot find core session");
107        }
108        return coreSession;
109    }
110
111}