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 }