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