View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.actions;
17  
18  import org.apache.log4j.MDC;
19  import org.kuali.rice.kew.actionrequest.ActionRequestValue;
20  import org.kuali.rice.kew.actionrequest.Recipient;
21  import org.kuali.rice.kew.actiontaken.ActionTakenValue;
22  import org.kuali.rice.kew.doctype.DocumentTypePolicy;
23  import org.kuali.rice.kew.api.exception.InvalidActionTakenException;
24  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
25  import org.kuali.rice.kew.service.KEWServiceLocator;
26  import org.kuali.rice.kew.api.KewApiConstants;
27  import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
28  
29  
30  import java.util.Iterator;
31  import java.util.List;
32  
33  
34  /**
35   * The ApproveAction records and processes an approve action.
36   *
37   * The routeheader is first checked to make sure the action is valid for the document.
38   * Next the user is checked to make sure he/she has not taken a previous action on this
39   * document at the actions responsibility or below. The action is recorded.
40   * Any requests related to this user are deactivated.
41   *
42   * @author Kuali Rice Team (rice.collab@kuali.org)
43   */
44  public class ApproveAction extends ActionTakenEvent {
45      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ApproveAction.class);
46  
47      /**
48       * @param routeHeader
49       *            RouteHeader for the document upon which the action is taken.
50       * @param principal
51       *            User taking the action.
52       */
53      public ApproveAction(DocumentRouteHeaderValue routeHeader, PrincipalContract principal) {
54          super(KewApiConstants.ACTION_TAKEN_APPROVED_CD, routeHeader, principal);
55      }
56  
57      /**
58       * @param routeHeader
59       *            RouteHeader for the document upon which the action is taken.
60       * @param principal
61       *            User taking the action.
62       * @param annotation
63       *            User comment on the action taken
64       */
65      public ApproveAction(DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String annotation) {
66          super(KewApiConstants.ACTION_TAKEN_APPROVED_CD, routeHeader, principal, annotation);
67      }
68  
69      /* (non-Javadoc)
70       * @see org.kuali.rice.kew.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List)
71       */
72      @Override
73      public String validateActionRules() {
74          return validateActionRules(getActionRequestService().findAllPendingRequests(routeHeader.getDocumentId()));
75      }
76  
77      public String validateActionRules(List<ActionRequestValue> actionRequests) {
78          if (!getRouteHeader().isValidActionToTake(getActionPerformedCode())) {
79              return "Document is not in a state to be approved";
80          }
81          List<ActionRequestValue> filteredActionRequests = filterActionRequestsByCode(actionRequests, KewApiConstants.ACTION_REQUEST_APPROVE_REQ);
82          if (!isActionCompatibleRequest(filteredActionRequests)) {
83              return "No request for the user is compatible " + "with the APPROVE action";
84          }
85          return "";
86      }
87  
88      /* (non-Javadoc)
89       * @see org.kuali.rice.kew.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List)
90       */
91      @Override
92      public boolean isActionCompatibleRequest(List<ActionRequestValue> requests) {
93          // we allow pre-approval
94          if (requests.isEmpty()) {
95              return true;
96          }
97  
98          // can always cancel saved or initiated document
99          if (routeHeader.isStateInitiated() || routeHeader.isStateSaved()) {
100             return true;
101         }
102 
103         boolean actionCompatible = false;
104         Iterator ars = requests.iterator();
105         ActionRequestValue actionRequest = null;
106 
107         while (ars.hasNext()) {
108             actionRequest = (ActionRequestValue) ars.next();
109             String request = actionRequest.getActionRequested();
110 
111             // Approve action matches Complete, Approve, FYI, and ACK requests
112             if ( (KewApiConstants.ACTION_REQUEST_FYI_REQ.equals(request)) ||
113                     (KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ.equals(request)) ||
114                     (KewApiConstants.ACTION_REQUEST_APPROVE_REQ.equals(request)) ||
115                     (KewApiConstants.ACTION_REQUEST_COMPLETE_REQ.equals(request)) ) {
116                 actionCompatible = true;
117                 break;
118             }
119         }
120         return actionCompatible;
121     }
122 
123     /**
124      * Records the approve action.
125      * - Checks to make sure the document status allows the action.
126      * - Checks that the user has not taken a previous action.
127      * - Deactivates the pending requests for this user
128      * - Records the action
129      *
130      * @throws InvalidActionTakenException
131      * @throws org.kuali.rice.kew.api.exception.ResourceUnavailableException
132      */
133     public void recordAction() throws InvalidActionTakenException {
134         MDC.put("docId", getRouteHeader().getDocumentId());
135         updateSearchableAttributesIfPossible();
136         LOG.debug("Approving document : " + annotation);
137 
138         List actionRequests = getActionRequestService().findAllValidRequests(getPrincipal().getPrincipalId(), getDocumentId(), KewApiConstants.ACTION_REQUEST_APPROVE_REQ);
139         if (actionRequests == null || actionRequests.isEmpty()) {
140             DocumentTypePolicy allowUnrequested = getRouteHeader().getDocumentType().getAllowUnrequestedActionPolicy();
141             if (allowUnrequested != null) {
142             	if (!allowUnrequested.getPolicyValue()) {
143             		throw new InvalidActionTakenException("No request for the user is compatible " + "with the APPROVE action. " + "Doctype policy ALLOW_UNREQUESTED_ACTION is set to false and someone else likely just took action on the document.");
144             	}
145             }
146         }
147         String errorMessage = validateActionRules(actionRequests);
148         if (!org.apache.commons.lang.StringUtils.isEmpty(errorMessage)) {
149             throw new InvalidActionTakenException(errorMessage);
150         }
151 
152         Recipient delegator = findDelegatorForActionRequests(actionRequests);
153 
154         LOG.debug("Record the approve action");
155         ActionTakenValue actionTaken = saveActionTaken(delegator);
156 
157         LOG.debug("Deactivate all pending action requests");
158         getActionRequestService().deactivateRequests(actionTaken, actionRequests);
159         notifyActionTaken(actionTaken);
160 
161         boolean isException = getRouteHeader().isInException();
162         boolean isSaved = getRouteHeader().isStateSaved();
163         if (isException || isSaved) {
164             String oldStatus = getRouteHeader().getDocRouteStatus();
165             LOG.debug("Moving document back to Enroute from "+KewApiConstants.DOCUMENT_STATUSES.get(oldStatus));
166             getRouteHeader().markDocumentEnroute();
167             String newStatus = getRouteHeader().getDocRouteStatus();
168             notifyStatusChange(newStatus, oldStatus);
169             KEWServiceLocator.getRouteHeaderService().saveRouteHeader(getRouteHeader());
170         }
171     }
172 }