001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 */
016package org.kuali.rice.kew.actions;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.apache.commons.collections.CollectionUtils;
022import org.apache.log4j.MDC;
023import org.kuali.rice.kew.actionrequest.ActionRequestValue;
024import org.kuali.rice.kew.actionrequest.Recipient;
025import org.kuali.rice.kew.actiontaken.ActionTakenValue;
026import org.kuali.rice.kew.api.action.AdHocRevoke;
027import org.kuali.rice.kew.api.exception.InvalidActionTakenException;
028import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
029import org.kuali.rice.kew.api.KewApiConstants;
030import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
031
032
033/**
034 * The RevokeAdHocApprove revokes the specified AdHoc requests.
035 *
036 * @author Kuali Rice Team (rice.collab@kuali.org)
037 */
038public class RevokeAdHocAction extends ActionTakenEvent {
039
040    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RevokeAdHocAction.class);
041
042    private String actionRequestId;
043    private AdHocRevoke revoke;
044
045    public RevokeAdHocAction(DocumentRouteHeaderValue routeHeader, PrincipalContract principal) {
046        super(KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD, routeHeader, principal);
047    }
048
049    public RevokeAdHocAction(DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String actionRequestId, String annotation) {
050        super(KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD, routeHeader, principal, annotation);
051        this.actionRequestId = actionRequestId;
052    }
053    
054    public RevokeAdHocAction(DocumentRouteHeaderValue routeHeader, PrincipalContract principal, AdHocRevoke revoke, String annotation) {
055        super(KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD, routeHeader, principal, annotation);
056        this.revoke = revoke;
057    }
058
059    /* (non-Javadoc)
060     * @see org.kuali.rice.kew.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List)
061     */
062    @Override
063    public String validateActionRules() {
064        if (!getRouteHeader().isValidActionToTake(getActionPerformedCode())) {
065            return "Revoke adhoc request is not valid on this document";
066        }
067        return "";
068    }
069    
070    @Override
071    public String validateActionRules(List<ActionRequestValue> actionRequests) {
072        return validateActionRules();
073    }
074
075    /**
076     * Records the approve action.
077     * - Checks to make sure the document status allows the action.
078     * - Checks that the user has not taken a previous action.
079     * - Deactivates the pending requests for this user
080     * - Records the action
081     *
082     * @throws InvalidActionTakenException
083     */
084    public void recordAction() throws InvalidActionTakenException {
085        MDC.put("docId", getRouteHeader().getDocumentId());
086        updateSearchableAttributesIfPossible();
087
088        String errorMessage = validateActionRules();
089        if (!org.apache.commons.lang.StringUtils.isEmpty(errorMessage)) {
090            throw new InvalidActionTakenException(errorMessage);
091        }
092
093        LOG.debug("Revoking adhoc request : " + annotation);
094
095        List<ActionRequestValue> requestsToRevoke = new ArrayList<ActionRequestValue>();
096        List<ActionRequestValue> actionRequests = getActionRequestService().findPendingRootRequestsByDocId(getDocumentId());
097        for (ActionRequestValue actionRequest : actionRequests)
098        {
099            if (matchesActionRequest(revoke, actionRequest))
100            {
101                requestsToRevoke.add(actionRequest);
102            }
103        }
104        if (requestsToRevoke.isEmpty() && actionRequestId != null) {
105                throw new InvalidActionTakenException("Failed to revoke action request with id " + actionRequestId +
106                                ".  ID does not represent a valid ad hoc request!");
107        }
108
109        Recipient delegator = findDelegatorForActionRequests(actionRequests);
110        LOG.debug("Record the revoke action");
111        ActionTakenValue actionTaken = saveActionTaken(delegator);
112
113        LOG.debug("Revoke all matching action requests, number of matching requests: " + requestsToRevoke.size());
114        getActionRequestService().deactivateRequests(actionTaken, requestsToRevoke);
115        notifyActionTaken(actionTaken);
116
117    }
118    
119    /**
120         * Determines if the given action request is an ad hoc request which matches this set of criteria.
121         */
122        protected boolean matchesActionRequest(AdHocRevoke adHocRevokeCommand, ActionRequestValue actionRequest) {
123                if (!actionRequest.isAdHocRequest()) {
124                        return false;
125                }               
126                if (actionRequestId != null) {
127                        return actionRequestId.equals(actionRequest.getActionRequestId());
128                } else if (adHocRevokeCommand != null) {
129                        boolean principalOrGroupId = !CollectionUtils.isEmpty(adHocRevokeCommand.getPrincipalIds()) || !CollectionUtils.isEmpty(adHocRevokeCommand.getGroupIds());
130                        if (!CollectionUtils.isEmpty(adHocRevokeCommand.getNodeNames()) && !adHocRevokeCommand.getNodeNames().contains(actionRequest.getNodeInstance().getName())) {
131                                return false;
132                        }
133                        if (actionRequest.isUserRequest() && !CollectionUtils.isEmpty(adHocRevokeCommand.getPrincipalIds())) {
134                                return adHocRevokeCommand.getPrincipalIds().contains(actionRequest.getPrincipalId());
135                        }
136                        if (actionRequest.isGroupRequest() && !CollectionUtils.isEmpty(adHocRevokeCommand.getGroupIds())) {
137                                return adHocRevokeCommand.getGroupIds().contains(actionRequest.getGroupId());
138                        }
139                        return !principalOrGroupId;
140                }
141                return true;
142        }
143
144}