View Javadoc

1   /*
2    * Copyright 2005-2007 The Kuali Foundation
3    *
4    *
5    * Licensed under the Educational Community License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.opensource.org/licenses/ecl2.php
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.kuali.rice.kew.actions;
18  
19  import java.util.Iterator;
20  import java.util.List;
21  
22  import org.apache.log4j.MDC;
23  import org.kuali.rice.kew.actionrequest.ActionRequestValue;
24  import org.kuali.rice.kew.actiontaken.ActionTakenValue;
25  import org.kuali.rice.kew.exception.InvalidActionTakenException;
26  import org.kuali.rice.kew.exception.WorkflowException;
27  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
28  import org.kuali.rice.kew.service.KEWServiceLocator;
29  import org.kuali.rice.kew.util.KEWConstants;
30  import org.kuali.rice.kew.util.Utilities;
31  import org.kuali.rice.kim.bo.entity.KimPrincipal;
32  
33  
34  /**
35   * Cancels a document at the request of a client app.
36   *
37   * @author Kuali Rice Team (rice.collab@kuali.org)
38   */
39  public class CancelAction extends ActionTakenEvent {
40  
41      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CancelAction.class);
42  
43      public CancelAction(DocumentRouteHeaderValue rh, KimPrincipal principal) {
44          super(KEWConstants.ACTION_TAKEN_CANCELED_CD, rh, principal);
45      }
46  
47      public CancelAction(DocumentRouteHeaderValue rh, KimPrincipal principal, String annotation) {
48          super(KEWConstants.ACTION_TAKEN_CANCELED_CD, rh, principal, annotation);
49      }
50  
51      /* (non-Javadoc)
52       * @see org.kuali.rice.kew.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List)
53       */
54      @Override
55      public String validateActionRules() {
56          return validateActionRules(getActionRequestService().findAllPendingRequests(routeHeader.getRouteHeaderId()));
57      }
58  
59      public String validateActionRules(List<ActionRequestValue> actionRequests) {
60          // FYI delyea:  This is new validation check... was not being checked previously
61          if (!getRouteHeader().isValidActionToTake(getActionPerformedCode())) {
62              return "Document is not in a state to be cancelled";
63          }
64          List<ActionRequestValue> filteredActionRequests = filterActionRequestsByCode(actionRequests, KEWConstants.ACTION_REQUEST_COMPLETE_REQ);
65          if (!isActionCompatibleRequest(filteredActionRequests)) {
66              return "No request for the user is compatible with the Cancel Action";
67          }
68      	// check state before checking kim
69          if (! KEWServiceLocator.getDocumentTypePermissionService().canCancel(getPrincipal().getPrincipalId(), getRouteHeaderId().toString(), getRouteHeader().getDocumentType(), getRouteHeader().getCurrentNodeNames(), getRouteHeader().getDocRouteStatus(), getRouteHeader().getInitiatorWorkflowId())) {
70              return "User is not authorized to Cancel document";
71          }
72          return "";
73      }
74  
75      /* (non-Javadoc)
76       * @see org.kuali.rice.kew.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List)
77       */
78      @Override
79      public boolean isActionCompatibleRequest(List<ActionRequestValue> requests) {
80  
81          // can always cancel saved or initiated document
82          if (routeHeader.isStateInitiated() || routeHeader.isStateSaved()) {
83              return true;
84          }
85  
86          boolean actionCompatible = false;
87          Iterator ars = requests.iterator();
88          ActionRequestValue actionRequest = null;
89  
90          while (ars.hasNext()) {
91              actionRequest = (ActionRequestValue) ars.next();
92              String request = actionRequest.getActionRequested();
93  
94              // APPROVE and COMPLETE request matches CANCEL Taken code
95              if ( (KEWConstants.ACTION_REQUEST_APPROVE_REQ.equals(request)) ||
96                   (KEWConstants.ACTION_REQUEST_COMPLETE_REQ.equals(request)) ) {
97                  actionCompatible = true;
98                  break;
99              }
100         }
101 
102         return actionCompatible;
103     }
104 
105     public void recordAction() throws InvalidActionTakenException {
106         MDC.put("docId", getRouteHeader().getRouteHeaderId());
107         updateSearchableAttributesIfPossible();
108 
109         LOG.debug("Canceling document : " + annotation);
110 
111         List actionRequests = getActionRequestService().findAllValidRequests(getPrincipal().getPrincipalId(), getRouteHeaderId(), KEWConstants.ACTION_REQUEST_COMPLETE_REQ);
112         LOG.debug("Checking to see if the action is legal");
113         String errorMessage = validateActionRules(actionRequests);
114         if (!Utilities.isEmpty(errorMessage)) {
115             throw new InvalidActionTakenException(errorMessage);
116         }
117 
118         LOG.debug("Record the cancel action");
119         ActionTakenValue actionTaken = saveActionTaken(findDelegatorForActionRequests(actionRequests));
120 
121         LOG.debug("Deactivate all pending action requests");
122         actionRequests = getActionRequestService().findPendingByDoc(getRouteHeaderId());
123 
124         getActionRequestService().deactivateRequests(actionTaken, actionRequests);
125         notifyActionTaken(actionTaken);
126 
127         LOG.debug("Canceling document");
128 
129         try {
130             String oldStatus = getRouteHeader().getDocRouteStatus();
131             getRouteHeader().markDocumentCanceled();
132             String newStatus = getRouteHeader().getDocRouteStatus();
133             KEWServiceLocator.getRouteHeaderService().saveRouteHeader(getRouteHeader());
134             notifyStatusChange(newStatus, oldStatus);
135         } catch (WorkflowException ex) {
136             LOG.warn(ex, ex);
137             throw new InvalidActionTakenException(ex.getMessage());
138         }
139     }
140 }