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    }