View Javadoc

1   /**
2    * Copyright 2005-2011 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.cxf.common.util.StringUtils;
19  import org.kuali.rice.kew.actionrequest.*;
20  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
21  import org.kuali.rice.kew.api.exception.InvalidActionTakenException;
22  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
23  import org.kuali.rice.kew.service.KEWServiceLocator;
24  import org.kuali.rice.kew.api.KewApiConstants;
25  import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
26  import org.kuali.rice.kim.api.group.Group;
27  
28  
29  import java.util.List;
30  
31  
32  /**
33   * Responsible for creating adhoc requests that are requested from the client.
34   *
35   * @author Kuali Rice Team (rice.collab@kuali.org)
36   */
37  public class AdHocAction extends ActionTakenEvent {
38      /**
39       * AdHoc actions don't actually result in an action being taken...it's a special case that generates other action requests
40       */
41      private static final String NO_ACTION_TAKEN_CODE = null;
42  
43  	private String actionRequested;
44  	private String nodeName;
45      private Integer priority;
46  	private String responsibilityDesc;
47  	private Boolean forceAction;
48  	private Recipient recipient;
49  	private String annotation;
50  	private String requestLabel;
51  
52      public AdHocAction(DocumentRouteHeaderValue routeHeader, PrincipalContract principal) {
53          super(NO_ACTION_TAKEN_CODE, routeHeader, principal);
54      }
55  
56  	public AdHocAction(DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String annotation, String actionRequested, String nodeName, Integer priority, Recipient recipient, String responsibilityDesc, Boolean forceAction, String requestLabel) {
57  		super(NO_ACTION_TAKEN_CODE, routeHeader, principal, annotation);
58  		this.actionRequested = actionRequested;
59  		this.nodeName = nodeName;
60          this.priority = priority;
61  		this.responsibilityDesc = responsibilityDesc;
62  		this.forceAction = forceAction;
63  		this.recipient = recipient;
64  		this.annotation = annotation;
65  		this.requestLabel = requestLabel;
66  	}
67  
68  	public void recordAction() throws InvalidActionTakenException {
69  		String errorMessage = validateActionRules();
70          if (!org.apache.commons.lang.StringUtils.isEmpty(errorMessage)) {
71              throw new InvalidActionTakenException(errorMessage);
72          }
73  		List targetNodes = KEWServiceLocator.getRouteNodeService().getCurrentNodeInstances(getDocumentId());
74          String error = adhocRouteAction(targetNodes, false);
75          if (!org.apache.commons.lang.StringUtils.isEmpty(error)) {
76              throw new InvalidActionTakenException(error);
77          }
78      }
79  
80      /* (non-Javadoc)
81       * @see org.kuali.rice.kew.actions.ActionTakenEvent#validateActionRules()
82       */
83      @Override
84      public String validateActionRules() {
85          List targetNodes = KEWServiceLocator.getRouteNodeService().getCurrentNodeInstances(getDocumentId());
86          return validateActionRulesInternal(targetNodes);
87      }
88      
89      @Override
90      public String validateActionRules(List<ActionRequestValue> actionRequests) {
91      	return validateActionRules();
92      }
93  
94      private String validateActionRulesInternal(List<RouteNodeInstance> targetNodes) {
95      	// recipient will be null when this is invoked from ActionRegistry.getValidActions
96      	if (recipient != null) {
97      		if (recipient instanceof KimPrincipalRecipient) {
98      			KimPrincipalRecipient principalRecipient = (KimPrincipalRecipient)recipient;
99      			if (!KEWServiceLocator.getDocumentTypePermissionService().canReceiveAdHocRequest(principalRecipient.getPrincipalId(), getRouteHeader().getDocumentType(), actionRequested)) {
100     				return "The principal '" + principalRecipient.getPrincipal().getPrincipalName() + "' does not have permission to recieve ad hoc requests on DocumentType '" + getRouteHeader().getDocumentType().getName() + "'";
101     			}
102     		} else if (recipient instanceof KimGroupRecipient) {
103     			Group group = ((KimGroupRecipient)recipient).getGroup();
104     			if (!KEWServiceLocator.getDocumentTypePermissionService().canGroupReceiveAdHocRequest("" + group.getId(), getRouteHeader().getDocumentType(), actionRequested)) {
105     				return "The group '" + group.getName() + "' does not have permission to recieve ad hoc requests on DocumentType '" + getRouteHeader().getDocumentType().getName() + "'";
106     			}
107     		} else {
108     			return "Invalid Recipient type encountered: " + recipient.getClass();
109     		}
110     	}
111         return adhocRouteAction(targetNodes, true);
112     }
113 
114     private String adhocRouteAction(List<RouteNodeInstance> targetNodes, boolean forValidationOnly) {
115         //if (targetNodes.isEmpty()) {
116         //    return "Could not locate an node instance on the document with the name '" + nodeName + "'";
117         //}
118         boolean requestCreated = false;
119         for (RouteNodeInstance routeNode : targetNodes)
120         {
121             // if the node name is null, then adhoc it to the first available node
122             if (nodeName == null || routeNode.getName().equals(nodeName))
123             {
124                 String message = createAdHocRequest(routeNode, forValidationOnly);
125                 if (!StringUtils.isEmpty(message))
126                 {
127                     return message;
128                 }
129                 requestCreated = true;
130                 if (nodeName == null)
131                 {
132                     break;
133                 }
134             }
135         }
136         
137         if (!requestCreated && targetNodes.isEmpty()) {
138             String message = createAdHocRequest(null, forValidationOnly);
139             if (!StringUtils.isEmpty(message)) {
140                 return message;
141             }
142             requestCreated = true;
143         }
144         
145         if (!requestCreated) {
146             return "Didn't create request.  The node name " + nodeName + " given is probably invalid ";
147         }
148         return "";
149     }
150     
151     private String createAdHocRequest(RouteNodeInstance routeNode, boolean forValidationOnly) {
152                 ActionRequestValue adhocRequest = new ActionRequestValue();
153                 if (!forValidationOnly) {
154                     ActionRequestFactory arFactory = new ActionRequestFactory(routeHeader, routeNode);
155                     adhocRequest = arFactory.createActionRequest(actionRequested, recipient, responsibilityDesc, forceAction, annotation);
156                     adhocRequest.setResponsibilityId(KewApiConstants.ADHOC_REQUEST_RESPONSIBILITY_ID);
157                     adhocRequest.setRequestLabel(requestLabel);
158                     if (priority != null) {
159                         adhocRequest.setPriority(priority);
160                     }
161                 } else {
162                     adhocRequest.setActionRequested(actionRequested);
163                 }
164                 if (adhocRequest.isApproveOrCompleteRequest() && ! (routeHeader.isEnroute() || routeHeader.isStateInitiated() ||
165                         routeHeader.isStateSaved())) {
166             return "Cannot AdHoc a Complete or Approve request when document is in state '" + routeHeader.getDocRouteStatusLabel() + "'.";
167                 }
168                 if (!forValidationOnly) {
169      
170                 	if (routeHeader.isDisaproved() || routeHeader.isCanceled() || routeHeader.isFinal() || routeHeader.isProcessed()) {
171                         getActionRequestService().activateRequest(adhocRequest);
172                     } else {
173                         KEWServiceLocator.getActionRequestService().saveActionRequest(adhocRequest);
174                     }
175                 }
176         return "";
177     }
178 }