001: /*
002: * Copyright 2005-2006 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.actions;
018:
019: import java.util.Collection;
020: import java.util.HashSet;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Set;
024:
025: import org.apache.log4j.MDC;
026:
027: import edu.iu.uis.eden.EdenConstants;
028: import edu.iu.uis.eden.KEWServiceLocator;
029: import edu.iu.uis.eden.actionrequests.ActionRequestFactory;
030: import edu.iu.uis.eden.actionrequests.ActionRequestValue;
031: import edu.iu.uis.eden.actiontaken.ActionTakenValue;
032: import edu.iu.uis.eden.engine.node.RouteNodeInstance;
033: import edu.iu.uis.eden.exception.EdenUserNotFoundException;
034: import edu.iu.uis.eden.exception.InvalidActionTakenException;
035: import edu.iu.uis.eden.exception.WorkflowException;
036: import edu.iu.uis.eden.routeheader.DocumentRouteHeaderValue;
037: import edu.iu.uis.eden.user.Recipient;
038: import edu.iu.uis.eden.user.WorkflowUser;
039: import edu.iu.uis.eden.util.Utilities;
040: import edu.iu.uis.eden.workgroup.GroupNameId;
041: import edu.iu.uis.eden.workgroup.Workgroup;
042:
043: /**
044: * Disapproves a document. This deactivates all requests on the document and sends
045: * acknowlegde requests to anybody who had already completed or approved the document.
046: *
047: * @author rkirkend
048: * @author ewestfal
049: * @author seiffert
050: */
051: public class DisapproveAction extends ActionTakenEvent {
052: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
053: .getLogger(DisapproveAction.class);
054:
055: /**
056: * @param rh RouteHeader for the document upon which the action is taken.
057: * @param user User taking the action.
058: */
059: public DisapproveAction(DocumentRouteHeaderValue rh,
060: WorkflowUser user) {
061: super (rh, user);
062: setActionTakenCode(EdenConstants.ACTION_TAKEN_DENIED_CD);
063: }
064:
065: /**
066: * @param rh RouteHeader for the document upon which the action is taken.
067: * @param user User taking the action.
068: * @param annotation User comment on the action taken
069: */
070: public DisapproveAction(DocumentRouteHeaderValue rh,
071: WorkflowUser user, String annotation) {
072: super (rh, user, annotation);
073: setActionTakenCode(EdenConstants.ACTION_TAKEN_DENIED_CD);
074: }
075:
076: /* (non-Javadoc)
077: * @see edu.iu.uis.eden.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List)
078: */
079: @Override
080: public String validateActionRules()
081: throws EdenUserNotFoundException {
082: return validateActionRules(getActionRequestService()
083: .findAllValidRequests(getUser(),
084: routeHeader.getRouteHeaderId(),
085: EdenConstants.ACTION_REQUEST_COMPLETE_REQ));
086: }
087:
088: private String validateActionRules(List actionRequests)
089: throws EdenUserNotFoundException {
090: String super Error = super .validateActionTakenRules();
091: if (!Utilities.isEmpty(super Error)) {
092: return super Error;
093: }
094: if (!getRouteHeader().isValidActionToTake(
095: getActionPerformedCode())) {
096: return "Document is not in a state to be disapproved";
097: }
098: if (!isActionCompatibleRequest(actionRequests)) {
099: return "No request for the user is compatible "
100: + "with the DISAPPROVE or DENY action";
101: }
102: return "";
103: }
104:
105: /* (non-Javadoc)
106: * @see edu.iu.uis.eden.actions.ActionTakenEvent#isActionCompatibleRequest(java.util.List)
107: */
108: @Override
109: public boolean isActionCompatibleRequest(List requests)
110: throws EdenUserNotFoundException {
111: // can always cancel saved or initiated document
112: if (routeHeader.isStateInitiated()
113: || routeHeader.isStateSaved()) {
114: return true;
115: }
116:
117: boolean actionCompatible = false;
118: Iterator ars = requests.iterator();
119: ActionRequestValue actionRequest = null;
120:
121: while (ars.hasNext()) {
122: actionRequest = (ActionRequestValue) ars.next();
123: String request = actionRequest.getActionRequested();
124:
125: // APPROVE request matches all but FYI and ACK
126: if ((EdenConstants.ACTION_REQUEST_APPROVE_REQ
127: .equals(request))
128: || (EdenConstants.ACTION_REQUEST_COMPLETE_REQ
129: .equals(request))) {
130: actionCompatible = true;
131: break;
132: }
133: }
134:
135: return actionCompatible;
136: }
137:
138: /**
139: * Records the disapprove action. - Checks to make sure the document status allows the action. - Checks that the user has not taken a previous action. - Deactivates the pending requests for this user - Records the action
140: *
141: * @throws InvalidActionTakenException
142: * @throws EdenUserNotFoundException
143: */
144: public void recordAction() throws InvalidActionTakenException,
145: EdenUserNotFoundException {
146: MDC.put("docId", getRouteHeader().getRouteHeaderId());
147: checkLocking();
148: updateSearchableAttributesIfPossible();
149:
150: LOG.debug("Disapproving document : " + annotation);
151:
152: List actionRequests = getActionRequestService()
153: .findAllValidRequests(getUser(), getRouteHeaderId(),
154: EdenConstants.ACTION_REQUEST_COMPLETE_REQ);
155: LOG.debug("Checking to see if the action is legal");
156: String errorMessage = validateActionRules(actionRequests);
157: if (!Utilities.isEmpty(errorMessage)) {
158: throw new InvalidActionTakenException(errorMessage);
159: }
160:
161: // if (!getRouteHeader().isValidActionToTake(getActionTakenCode())) {
162: // LOG.warn("Document not in state to be disapproved.");
163: // throw new InvalidActionTakenException("Document is not in a state to be disapproved");
164: // }
165: //
166: // List actionRequests = getActionRequestService().findAllValidRequests(getUser(), getRouteHeaderId(), EdenConstants.ACTION_REQUEST_COMPLETE_REQ);
167: // if (!isActionCompatibleRequest(actionRequests, getActionTakenCode())) {
168: // throw new InvalidActionTakenException("No request for the user is compatible " + "with the DISAPPROVE or DENY action");
169: // }
170:
171: LOG.debug("Record the disapproval action");
172: Recipient delegator = findDelegatorForActionRequests(actionRequests);
173: saveActionTaken(delegator);
174:
175: // actionRequests = getActionRequestService().findByStatusAndDocId(EdenConstants.ACTION_REQUEST_DONE_STATE, getRouteHeaderId());
176: // List actionRequestsToNotify = new ArrayList();
177: // for (Iterator iter = actionRequests.iterator(); iter.hasNext();) {
178: // ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
179: // //action request must be a complete and not to initiator (initiator will get specific request because they are initiator)
180: // if (actionRequest.isApproveOrCompleteRequest() && ! actionRequest.isRecipientRoutedRequest(getRouteHeader().getInitiatorUser())) {
181: // actionRequestsToNotify.add(actionRequest);
182: // }
183: // }
184:
185: LOG.debug("Deactivate all pending action requests");
186: actionRequests = getActionRequestService().findPendingByDoc(
187: getRouteHeaderId());
188: getActionRequestService().deactivateRequests(actionTaken,
189: actionRequests);
190: notifyActionTaken(this .actionTaken);
191:
192: LOG
193: .debug("Sending Acknowledgements to all previous approvers/completers");
194: // Generate the notification requests in the first node we find that the current user has an approve request
195: RouteNodeInstance notificationNodeInstance = null;
196: // if (actionRequests.size() > 0) { //I don't see why this matters let me know if it does rk
197: notificationNodeInstance = ((ActionRequestValue) actionRequests
198: .get(0)).getNodeInstance();
199: // }
200: generateNotifications(notificationNodeInstance);
201:
202: LOG.debug("Disapproving document");
203: try {
204: String oldStatus = getRouteHeader().getDocRouteStatus();
205: routeHeader.markDocumentDisapproved();
206: String newStatus = getRouteHeader().getDocRouteStatus();
207: getRouteHeaderService().saveRouteHeader(routeHeader);
208: notifyStatusChange(newStatus, oldStatus);
209: } catch (WorkflowException ex) {
210: LOG.warn(ex, ex);
211: throw new InvalidActionTakenException(ex.getMessage());
212: }
213: }
214:
215: //generate notifications to all people that have approved the document including the initiator
216: private void generateNotifications(
217: RouteNodeInstance notificationNodeInstance)
218: throws EdenUserNotFoundException {
219: Workgroup systemUserWorkgroup = getWorkgroupService()
220: .getWorkgroup(
221: new GroupNameId(
222: Utilities
223: .getApplicationConstant(EdenConstants.NOTIFICATION_EXCLUDED_USERS_WORKGROUP_NAME)));
224: Set<WorkflowUser> systemUserWorkflowIds = new HashSet<WorkflowUser>();
225: if (systemUserWorkgroup != null) {
226: systemUserWorkflowIds = new HashSet<WorkflowUser>(
227: systemUserWorkgroup.getUsers());
228: }
229: ActionRequestFactory arFactory = new ActionRequestFactory(
230: getRouteHeader(), notificationNodeInstance);
231: Collection actions = KEWServiceLocator.getActionTakenService()
232: .findByRouteHeaderId(getRouteHeaderId());
233: //one notification per person
234: Set usersNotified = new HashSet();
235: for (Iterator iter = actions.iterator(); iter.hasNext();) {
236: ActionTakenValue action = (ActionTakenValue) iter.next();
237: if ((action.isApproval() || action.isCompletion())
238: && !usersNotified.contains(action.getWorkflowId())) {
239: if (!systemUserWorkflowIds.contains(action
240: .getWorkflowUser())) {
241: ActionRequestValue request = arFactory
242: .createNotificationRequest(
243: EdenConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ,
244: action.getWorkflowUser(),
245: getActionTakenCode(), getUser(),
246: getActionTakenCode());
247: KEWServiceLocator.getActionRequestService()
248: .activateRequest(request);
249: usersNotified.add(request.getWorkflowId());
250: }
251: }
252: }
253: }
254: }
|