001 /**
002 * Copyright 2005-2014 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 */
016 package org.kuali.rice.kew.actions;
017
018 import org.apache.log4j.MDC;
019 import org.kuali.rice.kew.actionrequest.ActionRequestFactory;
020 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
021 import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient;
022 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
023 import org.kuali.rice.kew.api.KewApiConstants;
024 import org.kuali.rice.kew.api.action.ActionType;
025 import org.kuali.rice.kew.api.exception.InvalidActionTakenException;
026 import org.kuali.rice.kew.api.exception.WorkflowException;
027 import org.kuali.rice.kew.doctype.bo.DocumentType;
028 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
029 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
030 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
031 import org.kuali.rice.kew.service.KEWServiceLocator;
032 import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
033
034 import java.util.ArrayList;
035 import java.util.List;
036
037
038 /**
039 * Super user Approves a single action request.
040 *
041 * @author Kuali Rice Team (rice.collab@kuali.org)
042 */
043 public class SuperUserActionRequestApproveEvent extends SuperUserActionTakenEvent {
044 /**
045 * This is the only action which is polymorphic...the action taken code is dynamically determined
046 * based on action requested. All other actions' action taken code is immutable, so the field could otherwise
047 * be set to final and initialized in the constructor...however it would not be advisable to perform in the
048 * constructor the work required by this class to determine the action taken. So for now the class initializes
049 * the action taken to null (this would be the behavior anyway if the constructor did not enforce an action taken code
050 * to be supplied). An alternative would be to do away with the stored superclass field and simply delegate to a subclass
051 * getActionTakenCode implementation when necessary. It is also not clear that this would be a good choice as it may be
052 * called multiple times in arbitrary contexts.
053 */
054 private static final String UNDEFINED_ACTION_TAKEN_CODE = null;
055
056 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SuperUserActionRequestApproveEvent.class);
057 private String actionRequestId;
058
059 public SuperUserActionRequestApproveEvent(DocumentRouteHeaderValue routeHeader, PrincipalContract principal) {
060 super(UNDEFINED_ACTION_TAKEN_CODE, KewApiConstants.SUPER_USER_ACTION_REQUEST_APPROVE, routeHeader, principal);
061 }
062
063 public SuperUserActionRequestApproveEvent(DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String actionRequestId, String annotation, boolean runPostProcessor) {
064 super(UNDEFINED_ACTION_TAKEN_CODE, KewApiConstants.SUPER_USER_ACTION_REQUEST_APPROVE, routeHeader, principal, annotation, runPostProcessor);
065 this.actionRequestId = actionRequestId;
066 }
067
068 public void setActionTaken() {
069 String actionRequestCode = "";
070
071 ActionRequestValue actionRequest = getActionRequestService().findByActionRequestId(actionRequestId);
072
073 setActionRequest(actionRequest);
074
075 actionRequestCode = actionRequest.getActionRequested();
076
077 ActionType suActionType = ActionType.toSuperUserActionType(ActionType.fromCode(actionRequestCode, true));
078 if (suActionType == null) {
079 //TODO this should be checked
080 LOG.error("Invalid SU delegation action request code: " + actionRequestCode);
081 throw new RuntimeException("Invalid SU delegation action request code: " + actionRequestCode);
082 } else {
083 this.setActionTakenCode(suActionType.getCode());
084 }
085 }
086
087 protected ActionTakenValue processActionRequests() throws InvalidActionTakenException {
088 //this method has been written to process all of the actions though only approvals are currently processed
089
090 DocumentType docType = getRouteHeader().getDocumentType();
091 // boolean userAuthorized = getDocumentTypeService().verifySUAuthority(docType, getUser());
092
093 String errorMessage = super.validateActionRules();
094 if (!org.apache.commons.lang.StringUtils.isEmpty(errorMessage)) {
095 LOG.info("User not authorized");
096 List<WorkflowServiceErrorImpl> errors = new ArrayList<WorkflowServiceErrorImpl>();
097 errors.add(new WorkflowServiceErrorImpl(errorMessage, SuperUserActionTakenEvent.AUTHORIZATION));
098 throw new WorkflowServiceErrorException(errorMessage, errors);
099 }
100 // if (!docType.isSuperUser(getUser())) {
101 // List errors = new ArrayList();
102 // errors.add(new WorkflowServiceErrorImpl("User not authorized for super user action", SuperUserActionTakenEvent.AUTHORIZATION));
103 // throw new WorkflowServiceErrorException("Super User Authorization Error", errors);
104 // }
105
106 this.setActionTaken();
107
108 MDC.put("docId", getRouteHeader().getDocumentId());
109
110 LOG.debug("Super User Delegation Action on action request: " + annotation);
111 KimPrincipalRecipient superUserRecipient = null;
112 if (getActionRequest().getPrincipal() != null) {
113 superUserRecipient = new KimPrincipalRecipient(getActionRequest().getPrincipal());
114 }
115
116 ActionTakenValue actionTaken = this.saveActionTaken(superUserRecipient);
117
118 LOG.debug("Deactivate this action request");
119
120 ActionRequestValue request = getActionRequest();
121 getActionRequestService().deactivateRequest(actionTaken, request);
122 if (docType.getSuperUserApproveNotificationPolicy().getPolicyValue() && request.isApproveOrCompleteRequest()) {
123 KEWServiceLocator.getActionRequestService().activateRequest(
124 new ActionRequestFactory(this.getRouteHeader()).createNotificationRequest(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, request.getPrincipal(), this.getActionTakenCode(), getPrincipal(), null));
125 }
126 notifyActionTaken(actionTaken);
127
128 if (!(KewApiConstants.ACTION_TAKEN_SU_ACTION_REQUEST_FYI_CD.equals(this.getActionTakenCode()) && KewApiConstants.ACTION_TAKEN_SU_ACTION_REQUEST_ACKNOWLEDGED_CD.equals(this.getActionTakenCode()))) {
129 if (getRouteHeader().isInException()) {
130 LOG.debug("Moving document back to Enroute from Exception");
131
132 String oldStatus = getRouteHeader().getDocRouteStatus();
133 this.getRouteHeader().markDocumentEnroute();
134
135 String newStatus = getRouteHeader().getDocRouteStatus();
136 this.notifyStatusChange(newStatus, oldStatus);
137 KEWServiceLocator.getRouteHeaderService().saveRouteHeader(getRouteHeader());
138 }
139 else if (getRouteHeader().isStateSaved()) {
140 if (KewApiConstants.SAVED_REQUEST_RESPONSIBILITY_ID.equals(request.getResponsibilityId())) {
141 LOG.debug("Moving document to Enroute from Saved because action request was request generated by save action");
142
143 String oldStatus = getRouteHeader().getDocRouteStatus();
144 this.getRouteHeader().markDocumentEnroute();
145 String newStatus = getRouteHeader().getDocRouteStatus();
146 this.notifyStatusChange(newStatus, oldStatus);
147 KEWServiceLocator.getRouteHeaderService().saveRouteHeader(getRouteHeader());
148 }
149 }
150 }
151
152 return actionTaken;
153 }
154
155 public void recordAction() throws InvalidActionTakenException {
156 this.processActionRequests();
157 this.queueDocumentProcessing();
158 }
159
160 protected void markDocument() throws WorkflowException {
161 }
162 }