001 /** 002 * Copyright 2005-2013 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.commons.lang.StringUtils; 019 import org.apache.log4j.MDC; 020 import org.kuali.rice.kew.actionrequest.ActionRequestFactory; 021 import org.kuali.rice.kew.actionrequest.ActionRequestValue; 022 import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient; 023 import org.kuali.rice.kew.actiontaken.ActionTakenValue; 024 import org.kuali.rice.kew.api.exception.InvalidActionTakenException; 025 import org.kuali.rice.kew.api.exception.WorkflowException; 026 import org.kuali.rice.kew.engine.node.RouteNodeInstance; 027 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 028 import org.kuali.rice.kew.service.KEWServiceLocator; 029 import org.kuali.rice.kew.api.KewApiConstants; 030 import org.kuali.rice.kim.api.identity.principal.PrincipalContract; 031 import org.kuali.rice.krad.util.KRADConstants; 032 033 034 import java.util.List; 035 036 037 /** 038 * Saves a document. Puts the document in the persons action list that saved the document. 039 * This can currently only be done by the initiator of the document. 040 * 041 * @author Kuali Rice Team (rice.collab@kuali.org) 042 * 043 */ 044 public class SaveActionEvent extends ActionTakenEvent { 045 046 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SaveActionEvent.class); 047 048 private static final String RESPONSIBILITY_DESCRIPTION = "Initiator needs to complete document."; 049 050 public SaveActionEvent(DocumentRouteHeaderValue routeHeader, PrincipalContract principal) { 051 super(KewApiConstants.ACTION_TAKEN_SAVED_CD, routeHeader, principal); 052 } 053 054 public SaveActionEvent(DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String annotation) { 055 super(KewApiConstants.ACTION_TAKEN_SAVED_CD, routeHeader, principal, annotation); 056 } 057 058 /* (non-Javadoc) 059 * @see org.kuali.rice.kew.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List) 060 */ 061 @Override 062 public String validateActionRules() { 063 return validateActionRulesCustom(true); 064 } 065 066 private String validateActionRulesCustom(boolean checkIfActionIsValid) { 067 if (checkIfActionIsValid && (!getRouteHeader().isValidActionToTake(getActionPerformedCode()))) { 068 return "Document is not in a state to be saved"; 069 } 070 // check state before checking kim 071 if (!StringUtils.equals(getPrincipal().getPrincipalName(), KRADConstants.SYSTEM_USER)) { 072 if (! KEWServiceLocator.getDocumentTypePermissionService().canSave(getPrincipal().getPrincipalId(), getRouteHeader())) { 073 return "User is not authorized to Save document"; 074 } 075 } 076 return ""; 077 } 078 079 /** 080 * This overridden method ... 081 * 082 * @see org.kuali.rice.kew.actions.ActionTakenEvent#validateActionRules(java.util.List) 083 */ 084 @Override 085 public String validateActionRules(List<ActionRequestValue> actionRequests) { 086 return validateActionRules(); 087 } 088 089 public void recordAction() throws InvalidActionTakenException { 090 MDC.put("docId", getRouteHeader().getDocumentId()); 091 LOG.debug("Checking to see if the action is legal"); 092 /* Code below for variable 'checkIfActionIsValid' is used to identify when the 093 * DocumentRouteHeaderValue 'legal actions' should be checked for the current 094 * document. The 'legal actions' for a document that is in status ENROUTE or 095 * EXCEPTION will currently say that a Save action is not valid to be performed 096 * however we still want to allow the Save action to occur if called for backward 097 * compatibility issues. 098 */ 099 boolean checkIfActionIsValid = true; 100 if (getRouteHeader().isEnroute() || getRouteHeader().isInException()) { 101 // if document is enroute or exception... don't check if the action is valid... we will assume it is valid 102 checkIfActionIsValid = false; 103 } 104 String errorMessage = validateActionRulesCustom(checkIfActionIsValid); 105 if (!org.apache.commons.lang.StringUtils.isEmpty(errorMessage)) { 106 throw new InvalidActionTakenException(errorMessage); 107 } 108 109 updateSearchableAttributesIfPossible(); 110 111 // if (getRouteHeader().isValidActionToTake(getActionTakenCode())) { 112 if (getRouteHeader().isStateInitiated()) { 113 LOG.debug("Record the save action"); 114 ActionTakenValue actionTaken = saveActionTaken(); 115 //getRouteHeader().getActionRequests().add(generateSaveRequest()); 116 this.getActionRequestService().saveActionRequest(generateSaveRequest()); 117 notifyActionTaken(actionTaken); 118 LOG.debug("Marking document saved"); 119 try { 120 String oldStatus = getRouteHeader().getDocRouteStatus(); 121 getRouteHeader().markDocumentSaved(); 122 String newStatus = getRouteHeader().getDocRouteStatus(); 123 notifyStatusChange(newStatus, oldStatus); 124 KEWServiceLocator.getRouteHeaderService().saveRouteHeader(routeHeader); 125 } catch (WorkflowException ex) { 126 LOG.warn(ex, ex); 127 throw new InvalidActionTakenException(ex.getMessage()); 128 } 129 } 130 } 131 132 protected ActionRequestValue generateSaveRequest() { 133 RouteNodeInstance initialNode = null; 134 List initialNodes = KEWServiceLocator.getRouteNodeService().getInitialNodeInstances(getDocumentId()); 135 if (!initialNodes.isEmpty()) { 136 initialNode = (RouteNodeInstance)initialNodes.get(0); 137 } 138 //RouteNodeInstance initialNode = (RouteNodeInstance) KEWServiceLocator.getRouteNodeService().getInitialNodeInstances(getDocumentId()).get(0); 139 ActionRequestFactory arFactory = new ActionRequestFactory(getRouteHeader(), initialNode); 140 ActionRequestValue saveRequest = arFactory.createActionRequest(KewApiConstants.ACTION_REQUEST_COMPLETE_REQ, 141 0, new KimPrincipalRecipient(getPrincipal()), RESPONSIBILITY_DESCRIPTION, KewApiConstants.SAVED_REQUEST_RESPONSIBILITY_ID, 142 Boolean.TRUE, annotation); 143 // this.getActionRequestService().saveActionRequest(saveRequest); 144 this.getActionRequestService().activateRequest(saveRequest); 145 return saveRequest; 146 } 147 148 }