org.kuali.coeus.sys.impl.workflow.KcWorkflowServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.coeus.sys.impl.workflow.KcWorkflowServiceImpl.java

Source

/*
 * Kuali Coeus, a comprehensive research administration system for higher education.
 * 
 * Copyright 2005-2015 Kuali, Inc.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kuali.coeus.sys.impl.workflow;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kuali.coeus.sys.framework.workflow.KcWorkflowService;
import org.kuali.rice.kew.api.KewApiConstants;
import org.kuali.rice.kew.api.WorkflowDocument;
import org.kuali.rice.kew.api.WorkflowDocumentFactory;
import org.kuali.rice.kew.api.action.*;
import org.kuali.rice.kew.api.actionlist.ActionListService;
import org.kuali.rice.kew.api.document.DocumentDetail;
import org.kuali.rice.kew.api.document.WorkflowDocumentService;
import org.kuali.rice.krad.bo.DocumentHeader;
import org.kuali.rice.krad.document.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * KRA Workflow Service Implementation.
 */
@Component("kcWorkflowService")
public class KcWorkflowServiceImpl implements KcWorkflowService {
    private static final Log LOG = LogFactory.getLog(KcWorkflowService.class);

    @Autowired
    @Qualifier("workflowDocumentActionsService")
    protected WorkflowDocumentActionsService workflowDocumentActionsService;

    @Autowired
    @Qualifier("kewWorkflowDocumentService")
    protected WorkflowDocumentService workflowDocumentService;

    @Autowired
    @Qualifier("actionListService")
    protected ActionListService actionListService;

    private static final List<String> approvalCodes = new ArrayList<>();

    static {
        approvalCodes.add(ActionRequestType.COMPLETE.getCode());
        approvalCodes.add(ActionRequestType.APPROVE.getCode());
    }

    @Override
    public boolean hasWorkflowPermission(String userId, Document doc) {
        boolean hasPermission = false;
        WorkflowDocument workflowDoc = getWorkflowDocument(doc);
        if (workflowDoc != null && !isInitiated(doc)) {
            String routeHeaderId = workflowDoc.getDocumentId();
            hasPermission = workflowDocumentActionsService.isUserInRouteLog(routeHeaderId, userId, true);
        }
        return hasPermission;
    }

    @Override
    public boolean isClosed(Document doc) {
        boolean isClosed = false;
        WorkflowDocument workflowDoc = getWorkflowDocument(doc);
        if (workflowDoc != null) {
            isClosed = workflowDoc.isApproved() || workflowDoc.isCanceled() || workflowDoc.isDisapproved()
                    || workflowDoc.isException();
        }
        return isClosed;
    }

    @Override
    public boolean isEnRoute(Document doc) {
        boolean isEnRoute = false;
        WorkflowDocument workflowDoc = getWorkflowDocument(doc);
        if (workflowDoc != null) {
            isEnRoute = workflowDoc.isEnroute();
        }
        return isEnRoute;
    }

    @Override
    public boolean isInWorkflow(Document doc) {
        boolean isInWorkflow = false;
        WorkflowDocument workflowDoc = getWorkflowDocument(doc);
        if (workflowDoc != null) {
            isInWorkflow = !(workflowDoc.isInitiated() || workflowDoc.isSaved());
        }
        return isInWorkflow;
    }

    public boolean isInitiated(Document doc) {
        boolean isInitiated = false;
        WorkflowDocument workflowDoc = getWorkflowDocument(doc);
        if (workflowDoc != null) {
            isInitiated = workflowDoc.isInitiated();
        }
        return isInitiated;
    }

    /**
     * Get the corresponding workflow document.  
     * @param doc the document
     * @return the workflow document or null if there is none
     */
    protected WorkflowDocument getWorkflowDocument(Document doc) {
        WorkflowDocument workflowDocument = null;
        if (doc != null) {
            DocumentHeader header = doc.getDocumentHeader();
            if (header != null) {
                try {
                    workflowDocument = header.getWorkflowDocument();
                } catch (RuntimeException ex) {
                    // do nothing; there is no workflow document
                }
            }
        }
        return workflowDocument;
    }

    /**
     * This method gets the workflow document using the given principalId.
     *
     */
    protected WorkflowDocument getWorkflowDocument(Document doc, String principalId) {
        return WorkflowDocumentFactory.loadDocument(principalId,
                doc.getDocumentHeader().getWorkflowDocument().getDocumentId());
    }

    @Override
    public boolean isUserApprovalRequested(Document doc, String principalId) {
        boolean hasApprovalRequest = false;
        WorkflowDocument workDoc = getWorkflowDocument(doc, principalId);
        if (workDoc != null) {
            hasApprovalRequest = workDoc.isApprovalRequested();
        }
        return hasApprovalRequest;
    }

    @Override
    public boolean isUserActionRequested(Document doc, String principalId) {
        boolean hasActionRequest = false;
        WorkflowDocument workDoc = getWorkflowDocument(doc, principalId);
        if (workDoc != null) {
            hasActionRequest = workDoc.isApprovalRequested() || workDoc.isAcknowledgeRequested()
                    || workDoc.isFYIRequested();
        }
        return hasActionRequest;
    }

    @Override
    public boolean isDocumentOnNode(Document document, String nodeName) {
        boolean result;
        try {
            result = document != null
                    && document.getDocumentHeader().getWorkflowDocument().getNodeNames().contains(nodeName);
            return result;
        } catch (Exception we) {
            LOG.error(String.format(
                    "Exception generated when trying to determine if document %s is on active %s node.  Reason:%s",
                    nodeName, document.getDocumentNumber(), we.getMessage()));
            throw new RuntimeException(String.format(
                    "Exception generated when trying determine if document %s is on active %s route node.  Reason:%s",
                    nodeName, document.getDocumentNumber(), we.getMessage()), we);
        }
    }

    @Override
    public boolean isCurrentNode(Document document, String nodeName) {
        boolean result;
        try {
            result = document != null
                    && document.getDocumentHeader().getWorkflowDocument().getCurrentNodeNames().contains(nodeName);
            return result;
        } catch (Exception we) {
            LOG.error(String.format(
                    "Exception generated when trying to determine if document %s is on active or terminal %s node.  Reason:%s",
                    nodeName, document.getDocumentNumber(), we.getMessage()));
            throw new RuntimeException(String.format(
                    "Exception generated when trying determine if document %s is on active or terminal %s route node.  Reason:%s",
                    nodeName, document.getDocumentNumber(), we.getMessage()), we);
        }
    }

    public boolean isUserAdHocRequestRecipient(Document document, String principalId, String nodeName) {
        try {
            List<ActionRequest> actionRequestsForCurrentUser = workflowDocumentService
                    .getActionRequestsForPrincipalAtNode(document.getDocumentNumber(), nodeName, principalId);
            for (ActionRequest actionRequest : actionRequestsForCurrentUser) {
                if (actionRequest.isAdHocRequest() && actionRequest.isPending()) {
                    return true;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return false;
    }

    public boolean isUserRouteRespRequestRecipient(Document document, String principalId, String nodeName) {
        try {
            List<ActionRequest> actionRequestsForCurrentUser = workflowDocumentService
                    .getActionRequestsForPrincipalAtNode(document.getDocumentNumber(), nodeName, principalId);
            for (ActionRequest actionRequest : actionRequestsForCurrentUser) {
                if (actionRequest.isPending() && actionRequest.isRouteModuleRequest()) {
                    return true;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return false;
    }

    @Override
    public boolean isFinalApproval(WorkflowDocument workflowDoc) {
        RoutingReportCriteria.Builder reportCriteriaBuilder = RoutingReportCriteria.Builder
                .createByDocumentId(workflowDoc.getDocumentId());
        Set<String> approvalNodes = new HashSet<>();
        String currentRequest = null;

        DocumentDetail results1 = workflowDocumentActionsService.executeSimulation(reportCriteriaBuilder.build());
        for (ActionRequest actionRequest : results1.getActionRequests()) {
            if (actionRequest.isPending() && actionRequest.isApprovalRequest()) {
                if (actionRequest.isUserRequest()
                        && willReceiveFutureRequests(workflowDoc, actionRequest.getPrincipalId())) {
                    approvalNodes.add(actionRequest.getNodeName());
                } else if (actionRequest.isGroupRequest()) {
                    approvalNodes.add(actionRequest.getNodeName());
                } else if (actionRequest.isRoleRequest() && !requestAlreadyApproved(workflowDoc, actionRequest)) {
                    approvalNodes.add(actionRequest.getNodeName());
                }
            }
        }
        if (currentRequest != null) {
            approvalNodes.remove(currentRequest);
        }

        return approvalNodes.size() == 0;
    }

    @Override
    public boolean requestAlreadyApproved(WorkflowDocument workflowDoc, ActionRequest actionRequest) {
        boolean result = false;
        for (ActionRequest childRequest : actionRequest.getChildRequests()) {
            if (childRequest.isUserRequest()) {
                boolean futureRequests = willReceiveFutureRequests(workflowDoc, childRequest.getPrincipalId());
                if (actionRequest.getRequestPolicy() == ActionRequestPolicy.ALL && futureRequests) {
                    result = false;
                } else if (actionRequest.getRequestPolicy() == ActionRequestPolicy.FIRST && !futureRequests) {
                    result = true;
                }
            } else if (childRequest.isGroupRequest()) {
                if (actionRequest.getRequestPolicy() == ActionRequestPolicy.ALL) {
                    result = false;
                }
            } else if (childRequest.isRoleRequest()) {
                if (requestAlreadyApproved(workflowDoc, childRequest)) {
                    if (actionRequest.getRequestPolicy() == ActionRequestPolicy.FIRST) {
                        result = true;
                    }
                } else if (actionRequest.getRequestPolicy() == ActionRequestPolicy.ALL) {
                    result = false;
                }
            }
        }
        return result;
    }

    /**
     * Checks to see if the user has asked to receive future requests or not.
     */
    private boolean willReceiveFutureRequests(WorkflowDocument workflowDoc, String principalId) {
        boolean doNotReceiveFutureRequests = false;

        Map<String, String> variables = workflowDoc.getVariables();
        if (variables != null && CollectionUtils.isNotEmpty(variables.keySet())) {
            Iterator<String> variableIterator = variables.keySet().iterator();
            while (variableIterator.hasNext()) {
                String variableKey = variableIterator.next();
                String variableValue = variables.get(variableKey);
                if (variableKey.startsWith(KewApiConstants.RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_KEY)
                        && variableValue.toUpperCase()
                                .equals(KewApiConstants.DONT_RECEIVE_FUTURE_REQUESTS_BRANCH_STATE_VALUE)
                        && variableKey.contains(principalId)) {
                    doNotReceiveFutureRequests = true;
                    break;
                }
            }
        }

        return !doNotReceiveFutureRequests;
    }

    public boolean hasPendingApprovalRequests(WorkflowDocument workflowDoc) {
        return !actionListService.getActionItems(workflowDoc.getDocumentId(), approvalCodes).isEmpty();
    }

    protected ActionListService getActionListService() {
        return actionListService;
    }

    public void setActionListService(ActionListService actionListService) {
        this.actionListService = actionListService;
    }

    public void setWorkflowDocumentActionsService(WorkflowDocumentActionsService workflowDocumentActionsService) {
        this.workflowDocumentActionsService = workflowDocumentActionsService;
    }

    public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) {
        this.workflowDocumentService = workflowDocumentService;
    }
}