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.actionlist.web;
018:
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.Comparator;
023: import java.util.Iterator;
024: import java.util.LinkedHashMap;
025: import java.util.List;
026: import java.util.Map;
027:
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.http.HttpServletResponse;
030:
031: import org.apache.commons.collections.ComparatorUtils;
032: import org.apache.commons.collections.comparators.ComparableComparator;
033: import org.apache.commons.lang.StringUtils;
034: import org.apache.struts.Globals;
035: import org.apache.struts.action.ActionErrors;
036: import org.apache.struts.action.ActionForm;
037: import org.apache.struts.action.ActionForward;
038: import org.apache.struts.action.ActionMapping;
039: import org.apache.struts.action.ActionMessage;
040: import org.apache.struts.action.ActionMessages;
041: import org.displaytag.pagination.PaginatedList;
042: import org.displaytag.properties.SortOrderEnum;
043: import org.displaytag.util.LookupUtil;
044:
045: import edu.iu.uis.eden.EdenConstants;
046: import edu.iu.uis.eden.KEWServiceLocator;
047: import edu.iu.uis.eden.actionitem.ActionItem;
048: import edu.iu.uis.eden.actionitem.ActionItemActionListExtension;
049: import edu.iu.uis.eden.actionlist.ActionListFilter;
050: import edu.iu.uis.eden.actionlist.ActionListService;
051: import edu.iu.uis.eden.actionlist.ActionToTake;
052: import edu.iu.uis.eden.actionlist.PaginatedActionList;
053: import edu.iu.uis.eden.actions.ActionSet;
054: import edu.iu.uis.eden.actions.asyncservices.ActionInvocation;
055: import edu.iu.uis.eden.exception.WorkflowException;
056: import edu.iu.uis.eden.plugin.attributes.CustomActionListAttribute;
057: import edu.iu.uis.eden.preferences.Preferences;
058: import edu.iu.uis.eden.routeheader.DocumentRouteHeaderValueActionListExtension;
059: import edu.iu.uis.eden.user.AuthenticationUserId;
060: import edu.iu.uis.eden.user.Recipient;
061: import edu.iu.uis.eden.user.UserService;
062: import edu.iu.uis.eden.user.WorkflowUser;
063: import edu.iu.uis.eden.util.PerformanceLogger;
064: import edu.iu.uis.eden.util.Utilities;
065: import edu.iu.uis.eden.web.WorkflowAction;
066: import edu.iu.uis.eden.web.session.UserSession;
067: import edu.iu.uis.eden.workgroup.GroupNameId;
068: import edu.iu.uis.eden.workgroup.Workgroup;
069: import edu.iu.uis.eden.workgroup.WorkgroupService;
070:
071: /**
072: * Action doing Action list stuff
073: *
074: * @author rkirkend
075: * @author temay
076: * @author ewestfal
077: *
078: */
079: public class ActionListAction extends WorkflowAction {
080:
081: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
082: .getLogger(ActionListAction.class);
083:
084: private static String ACTION_LIST_KEY = "actionList";
085: private static String ACTION_LIST_PAGE_KEY = "actionListPage";
086: private static String ACTION_LIST_USER_KEY = "actionList.user";
087: private static String REQUERY_ACTION_LIST_KEY = "requeryActionList";
088:
089: public ActionForward start(ActionMapping mapping,
090: ActionForm actionForm, HttpServletRequest request,
091: HttpServletResponse response) throws Exception {
092: PerformanceLogger plog = new PerformanceLogger();
093: plog.log("starting ActionList fetch");
094: ActionListForm form = (ActionListForm) actionForm;
095: ActionErrors errors = new ActionErrors();
096: ActionListService actionListSrv = KEWServiceLocator
097: .getActionListService();
098:
099: // process display tag parameters
100: Integer page = form.getPage();
101: String sortCriterion = form.getSort();
102: SortOrderEnum sortOrder = SortOrderEnum.ASCENDING;
103: if (form.getDir() != null) {
104: sortOrder = parseSortOrder(form.getDir());
105: }
106:
107: // if both the page and the sort criteria are null, that means its the first entry into the page, use defaults
108: if (page == null && sortCriterion == null) {
109: page = new Integer(1);
110: sortCriterion = ActionItemComparator.DOCUMENT_ID;
111: }
112:
113: // if the page is still null, that means the user just performed a sort action, pull the currentPage off of the form
114: if (page == null) {
115: page = form.getCurrentPage();
116: }
117:
118: // update the values of the "current" display tag parameters
119: form.setCurrentPage(page);
120: if (!StringUtils.isEmpty(sortCriterion)) {
121: form.setCurrentSort(sortCriterion);
122: form.setCurrentDir(getSortOrderValue(sortOrder));
123: }
124:
125: // reset the default action on the form
126: form.setDefaultActionToTake("NONE");
127:
128: boolean freshActionList = true;
129: // retrieve cached action list
130: List actionList = (List) request.getSession().getAttribute(
131: ACTION_LIST_KEY);
132: plog.log("Time to initialize");
133: try {
134: UserSession uSession = getUserSession(request);
135: WorkflowUser workflowUser = null;
136: if (uSession.getActionListFilter() == null) {
137: ActionListFilter filter = new ActionListFilter();
138: filter
139: .setDelegationType(EdenConstants.DELEGATION_SECONDARY);
140: filter.setExcludeDelegationType(true);
141: uSession.setActionListFilter(filter);
142: }
143:
144: if (uSession.getHelpDeskActionListUser() != null) {
145: workflowUser = uSession.getHelpDeskActionListUser();
146: } else {
147: if (!StringUtils.isEmpty(form.getDocType())) {
148: uSession.getActionListFilter().setDocumentType(
149: form.getDocType());
150: uSession.getActionListFilter()
151: .setExcludeDocumentType(false);
152: }
153: workflowUser = uSession.getWorkflowUser();
154: }
155:
156: Preferences preferences = getUserSession(request)
157: .getPreferences();
158:
159: if (!StringUtils.isEmpty(form.getDelegationId())) {
160: uSession.getActionListFilter().setDelegatorId(
161: form.getDelegationId());
162: uSession.getActionListFilter().setExcludeDelegatorId(
163: false);
164: actionList = null;
165: }
166:
167: // if the user has changed, we need to refresh the action list
168: if (!workflowUser.getWorkflowId().equals(
169: (String) request.getSession().getAttribute(
170: ACTION_LIST_USER_KEY))) {
171: actionList = null;
172: }
173:
174: if (actionList == null) {
175: // fetch the action list
176: actionList = new ArrayList(actionListSrv.getActionList(
177: workflowUser, uSession.getActionListFilter()));
178: request.getSession().setAttribute(ACTION_LIST_USER_KEY,
179: workflowUser.getWorkflowId());
180: } else if (actionListSrv.refreshActionList(getUserSession(
181: request).getWorkflowUser())) {
182: actionList = new ArrayList(actionListSrv.getActionList(
183: workflowUser, uSession.getActionListFilter()));
184: request.getSession().setAttribute(ACTION_LIST_USER_KEY,
185: workflowUser.getWorkflowId());
186: } else if (request.getSession().getAttribute(
187: REQUERY_ACTION_LIST_KEY) != null) {
188: actionList = new ArrayList(actionListSrv.getActionList(
189: workflowUser, uSession.getActionListFilter()));
190: request.getSession().setAttribute(ACTION_LIST_USER_KEY,
191: workflowUser.getWorkflowId());
192: } else {
193: freshActionList = false;
194: }
195: // reset the requery action list key
196: request.getSession().setAttribute(REQUERY_ACTION_LIST_KEY,
197: null);
198:
199: // build the drop-down of delegators
200: if (EdenConstants.DELEGATORS_ON_ACTION_LIST_PAGE
201: .equalsIgnoreCase(preferences.getDelegatorFilter())) {
202: form.setDelegators(getDelegators(actionListSrv,
203: workflowUser,
204: EdenConstants.DELEGATION_SECONDARY));
205: form.setDelegationId(uSession.getActionListFilter()
206: .getDelegatorId());
207: }
208:
209: form.setFilterLegend(uSession.getActionListFilter()
210: .getFilterLegend());
211: plog.log("Setting attributes");
212:
213: int pageSize = getPageSize(preferences);
214: // initialize the action list if necessary
215: if (freshActionList) {
216: initializeActionList(actionList, preferences, errors);
217: // put this in to resolve EN-112 (http://beatles.uits.indiana.edu:8081/jira/browse/EN-112)
218: // if the action list gets "refreshed" in between page switches, we need to be sure and re-sort it, even though we don't have sort criteria on the request
219: if (sortCriterion == null) {
220: sortCriterion = form.getCurrentSort();
221: sortOrder = parseSortOrder(form.getCurrentDir());
222: }
223: }
224: // sort the action list if necessary
225: if (sortCriterion != null) {
226: sortActionList(actionList, sortCriterion, sortOrder);
227: }
228: PaginatedList currentPage = buildCurrentPage(actionList,
229: form.getCurrentPage(), form.getCurrentSort(), form
230: .getCurrentDir(), pageSize, preferences,
231: errors, form);
232: request.setAttribute(ACTION_LIST_PAGE_KEY, currentPage);
233: request.getSession().setAttribute(ACTION_LIST_KEY,
234: actionList);
235: plog
236: .log("finished setting attributes, finishing action list fetch");
237: } catch (Exception e) {
238: LOG.error("Error loading action list.", e);
239: }
240:
241: saveErrors(request, errors);
242: LOG.info("end start ActionListAction");
243: return mapping.findForward("viewActionList");
244: }
245:
246: private SortOrderEnum parseSortOrder(String dir)
247: throws WorkflowException {
248: if ("asc".equals(dir)) {
249: return SortOrderEnum.ASCENDING;
250: } else if ("desc".equals(dir)) {
251: return SortOrderEnum.DESCENDING;
252: }
253: throw new WorkflowException("Invalid sort direction: " + dir);
254: }
255:
256: private String getSortOrderValue(SortOrderEnum sortOrder) {
257: if (SortOrderEnum.ASCENDING.equals(sortOrder)) {
258: return "asc";
259: } else if (SortOrderEnum.DESCENDING.equals(sortOrder)) {
260: return "desc";
261: }
262: return null;
263: }
264:
265: private void sortActionList(List actionList, String sortName,
266: SortOrderEnum sortOrder) {
267: if (StringUtils.isEmpty(sortName)) {
268: return;
269: }
270: Comparator comparator = new ActionItemComparator(sortName);
271: if (SortOrderEnum.DESCENDING.equals(sortOrder)) {
272: comparator = ComparatorUtils.reversedComparator(comparator);
273: }
274: Collections.sort(actionList, comparator);
275: // re-index the action items
276: int index = 0;
277: for (Iterator iterator = actionList.iterator(); iterator
278: .hasNext();) {
279: ActionItemActionListExtension actionItem = (ActionItemActionListExtension) iterator
280: .next();
281: actionItem.setActionItemIndex(new Integer(index++));
282: }
283: }
284:
285: private void initializeActionList(List actionList,
286: Preferences preferences, ActionErrors errors)
287: throws WorkflowException {
288: List actionItemProblemIds = new ArrayList();
289: int index = 0;
290: for (Iterator iterator = actionList.iterator(); iterator
291: .hasNext();) {
292: ActionItemActionListExtension actionItem = (ActionItemActionListExtension) iterator
293: .next();
294: if (actionItem.getRouteHeaderId() == null) {
295: LOG
296: .error("Somehow there exists an ActionItem with a null document id! actionItemId="
297: + actionItem.getActionItemId());
298: iterator.remove();
299: continue;
300: }
301: try {
302: actionItem.initialize();
303: DocumentRouteHeaderValueActionListExtension routeHeaderExtension = (DocumentRouteHeaderValueActionListExtension) actionItem
304: .getRouteHeader();
305: routeHeaderExtension
306: .setActionListInitiatorUser(routeHeaderExtension
307: .getInitiatorUser());
308: actionItem.setActionItemIndex(new Integer(index));
309: //set background colors for document statuses
310: if (EdenConstants.ROUTE_HEADER_APPROVED_CD
311: .equalsIgnoreCase(actionItem.getRouteHeader()
312: .getDocRouteStatus())) {
313: actionItem
314: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
315: .get(preferences.getColorApproved()));
316: } else if (EdenConstants.ROUTE_HEADER_CANCEL_CD
317: .equalsIgnoreCase(actionItem.getRouteHeader()
318: .getDocRouteStatus())) {
319: actionItem
320: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
321: .get(preferences.getColorCanceled()));
322: } else if (EdenConstants.ROUTE_HEADER_DISAPPROVED_CD
323: .equalsIgnoreCase(actionItem.getRouteHeader()
324: .getDocRouteStatus())) {
325: actionItem
326: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
327: .get(preferences
328: .getColorDissaproved()));
329: } else if (EdenConstants.ROUTE_HEADER_ENROUTE_CD
330: .equalsIgnoreCase(actionItem.getRouteHeader()
331: .getDocRouteStatus())) {
332: actionItem
333: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
334: .get(preferences.getColorEnroute()));
335: } else if (EdenConstants.ROUTE_HEADER_EXCEPTION_CD
336: .equalsIgnoreCase(actionItem.getRouteHeader()
337: .getDocRouteStatus())) {
338: actionItem
339: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
340: .get(preferences
341: .getColorException()));
342: } else if (EdenConstants.ROUTE_HEADER_FINAL_CD
343: .equalsIgnoreCase(actionItem.getRouteHeader()
344: .getDocRouteStatus())) {
345: actionItem
346: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
347: .get(preferences.getColorFinal()));
348: } else if (EdenConstants.ROUTE_HEADER_INITIATED_CD
349: .equalsIgnoreCase(actionItem.getRouteHeader()
350: .getDocRouteStatus())) {
351: actionItem
352: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
353: .get(preferences
354: .getColorInitiated()));
355: } else if (EdenConstants.ROUTE_HEADER_PROCESSED_CD
356: .equalsIgnoreCase(actionItem.getRouteHeader()
357: .getDocRouteStatus())) {
358: actionItem
359: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
360: .get(preferences
361: .getColorProccessed()));
362: } else if (EdenConstants.ROUTE_HEADER_SAVED_CD
363: .equalsIgnoreCase(actionItem.getRouteHeader()
364: .getDocRouteStatus())) {
365: actionItem
366: .setRowStyleClass((String) EdenConstants.ACTION_LIST_COLOR_PALETTE
367: .get(preferences.getColorSaved()));
368: }
369: index++;
370: } catch (Exception e) {
371: // if there's a problem loading the action item, we don't want to blow out the whole screen but we will remove it from the list
372: // and display an approriate error message to the user
373: LOG.error("Error loading action list for action item "
374: + actionItem.getActionItemId(), e);
375: iterator.remove();
376: actionItemProblemIds.add(actionItem.getRouteHeaderId());
377: }
378: }
379: generateActionItemErrors(errors, "actionlist.badActionItems",
380: actionItemProblemIds);
381: }
382:
383: /**
384: * Gets the page size of the Action List. Uses the user's preferences for page size unless the action list
385: * has been throttled by an application constant, in which case it uses the smaller of the two values.
386: */
387: protected int getPageSize(Preferences preferences) {
388: int pageSize = Integer.parseInt(preferences.getPageSize());
389: String pageSizeThrottle = Utilities
390: .getApplicationConstant(EdenConstants.ACTION_LIST_PAGE_SIZE_THROTTLE);
391: if (!StringUtils.isEmpty(pageSizeThrottle)) {
392: try {
393: int throttle = Integer.parseInt(pageSizeThrottle);
394: if (throttle > 0 && throttle < pageSize) {
395: pageSize = throttle;
396: }
397: } catch (Exception e) {
398: LOG.warn("Encountered an error when parsing "
399: + EdenConstants.ACTION_LIST_PAGE_SIZE_THROTTLE
400: + ", " + e.getClass().getName() + ": "
401: + e.getMessage());
402: }
403: }
404: return pageSize;
405: }
406:
407: protected PaginatedList buildCurrentPage(List actionList,
408: Integer page, String sortCriterion, String sortDirection,
409: int pageSize, Preferences preferences, ActionErrors errors,
410: ActionListForm form) throws WorkflowException {
411: List currentPage = new ArrayList(pageSize);
412: boolean haveFyis = false;
413: boolean haveApproves = false;
414: boolean haveAcknowledges = false;
415: boolean haveCancels = false;
416: boolean haveDisapproves = false;
417: boolean haveCustomActions = false;
418: List customActionListProblemIds = new ArrayList();
419: SortOrderEnum sortOrder = parseSortOrder(sortDirection);
420: int startIndex = (page.intValue() - 1) * pageSize;
421: int endIndex = startIndex + pageSize;
422: for (int index = startIndex; index < endIndex
423: && index < actionList.size(); index++) {
424: ActionItemActionListExtension actionItem = (ActionItemActionListExtension) actionList
425: .get(index);
426: // evaluate custom action list component for mass actions
427: try {
428: boolean itemHasApproves = false;
429: boolean itemHasDisapproves = false;
430: boolean itemHasCancels = false;
431: boolean itemHasAcknowledges = false;
432: boolean itemHasFyis = false;
433: boolean itemHasCustomActions = false;
434: CustomActionListAttribute customActionListAttribute = actionItem
435: .getRouteHeader()
436: .getCustomActionListAttribute();
437: if (customActionListAttribute != null) {
438: Map customActions = new LinkedHashMap();
439: customActions.put("NONE", "NONE");
440: ActionSet legalActions = customActionListAttribute
441: .getLegalActions(UserSession
442: .getAuthenticatedUser(), actionItem);
443: if (legalActions != null
444: && legalActions.hasApprove()
445: && isActionCompatibleRequest(
446: actionItem,
447: EdenConstants.ACTION_TAKEN_APPROVED_CD)) {
448: customActions
449: .put(
450: EdenConstants.ACTION_TAKEN_APPROVED_CD,
451: EdenConstants.ACTION_REQUEST_APPROVE_REQ_LABEL);
452: itemHasApproves = true;
453: }
454: if (legalActions != null
455: && legalActions.hasDisapprove()
456: && isActionCompatibleRequest(
457: actionItem,
458: EdenConstants.ACTION_TAKEN_DENIED_CD)) {
459: customActions
460: .put(
461: EdenConstants.ACTION_TAKEN_DENIED_CD,
462: EdenConstants.ACTION_REQUEST_DISAPPROVE_LABEL);
463: itemHasDisapproves = true;
464: }
465: if (legalActions != null
466: && legalActions.hasCancel()
467: && isActionCompatibleRequest(
468: actionItem,
469: EdenConstants.ACTION_TAKEN_CANCELED_CD)) {
470: customActions
471: .put(
472: EdenConstants.ACTION_TAKEN_CANCELED_CD,
473: EdenConstants.ACTION_REQUEST_CANCEL_REQ_LABEL);
474: itemHasCancels = true;
475: }
476: if (legalActions != null
477: && legalActions.hasAcknowledge()
478: && isActionCompatibleRequest(
479: actionItem,
480: EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD)) {
481: customActions
482: .put(
483: EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD,
484: EdenConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ_LABEL);
485: itemHasAcknowledges = true;
486: }
487: if (legalActions != null
488: && legalActions.hasFyi()
489: && isActionCompatibleRequest(actionItem,
490: EdenConstants.ACTION_TAKEN_FYI_CD)
491: && EdenConstants.PREFERENCES_YES_VAL
492: .equalsIgnoreCase(preferences
493: .getShowClearFyi())) {
494: customActions
495: .put(
496: EdenConstants.ACTION_TAKEN_FYI_CD,
497: EdenConstants.ACTION_REQUEST_FYI_REQ_LABEL);
498: itemHasFyis = true;
499: }
500: if (customActions.size() > 1) {
501: actionItem.setCustomActions(customActions);
502: itemHasCustomActions = true;
503: }
504: actionItem
505: .setDisplayParameters(customActionListAttribute
506: .getDocHandlerDisplayParameters(
507: UserSession
508: .getAuthenticatedUser(),
509: actionItem));
510: haveApproves = haveApproves || itemHasApproves;
511: haveAcknowledges = haveAcknowledges
512: || itemHasAcknowledges;
513: haveFyis = haveFyis || itemHasFyis;
514: haveDisapproves = haveDisapproves
515: || itemHasDisapproves;
516: haveCancels = haveCancels || itemHasCancels;
517: haveCustomActions = haveCustomActions
518: || itemHasCustomActions;
519: }
520: } catch (Exception e) {
521: // if there's a problem loading the custom action list attribute, let's go ahead and display the vanilla action item
522: LOG.error(
523: "Problem loading custom action list attribute",
524: e);
525: customActionListProblemIds.add(actionItem
526: .getRouteHeaderId());
527: }
528: currentPage.add(actionItem);
529: }
530:
531: // configure custom actions on form
532: form.setHasCustomActions(new Boolean(haveCustomActions));
533: Map defaultActions = new LinkedHashMap();
534: defaultActions.put("NONE", "NONE");
535: if (haveApproves) {
536: defaultActions.put(EdenConstants.ACTION_TAKEN_APPROVED_CD,
537: EdenConstants.ACTION_REQUEST_APPROVE_REQ_LABEL);
538: form.setCustomActionList(Boolean.TRUE);
539: }
540: if (haveDisapproves) {
541: defaultActions.put(EdenConstants.ACTION_TAKEN_DENIED_CD,
542: EdenConstants.ACTION_REQUEST_DISAPPROVE_LABEL);
543: form.setCustomActionList(Boolean.TRUE);
544: }
545: if (haveCancels) {
546: defaultActions.put(EdenConstants.ACTION_TAKEN_CANCELED_CD,
547: EdenConstants.ACTION_REQUEST_CANCEL_REQ_LABEL);
548: form.setCustomActionList(Boolean.TRUE);
549: }
550: if (haveAcknowledges) {
551: defaultActions.put(
552: EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD,
553: EdenConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ_LABEL);
554: form.setCustomActionList(Boolean.TRUE);
555: }
556: //clearing FYI's can be done in any action list not just a customized one
557: if (haveFyis
558: && EdenConstants.PREFERENCES_YES_VAL
559: .equalsIgnoreCase(preferences.getShowClearFyi())) {
560: defaultActions.put(EdenConstants.ACTION_TAKEN_FYI_CD,
561: EdenConstants.ACTION_REQUEST_FYI_REQ_LABEL);
562: }
563: if (defaultActions.size() > 1) {
564: form.setDefaultActions(defaultActions);
565: }
566:
567: generateActionItemErrors(errors,
568: "actionlist.badCustomActionListItems",
569: customActionListProblemIds);
570: return new PaginatedActionList(currentPage, actionList.size(),
571: page.intValue(), pageSize, "actionList", sortCriterion,
572: sortOrder);
573: }
574:
575: private void generateActionItemErrors(ActionErrors errors,
576: String errorKey, List documentIds) {
577: if (!documentIds.isEmpty()) {
578: String documentIdsString = StringUtils.join(documentIds
579: .iterator(), ", ");
580: errors.add(Globals.ERROR_KEY, new ActionMessage(errorKey,
581: documentIdsString));
582: }
583: }
584:
585: public List getDelegators(ActionListService actionListSrv,
586: WorkflowUser workflowUser, String delegationType)
587: throws Exception {
588: Collection delegators = actionListSrv.findUserDelegators(
589: workflowUser, delegationType);
590: return getWebFriendlyRecipients(delegators);
591: }
592:
593: public ActionForward takeMassActions(ActionMapping mapping,
594: ActionForm form, HttpServletRequest request,
595: HttpServletResponse response) throws Exception {
596: ActionListForm actionListForm = (ActionListForm) form;
597: List actionList = (List) request.getSession().getAttribute(
598: ACTION_LIST_KEY);
599: if (actionList == null) {
600: return start(mapping, new ActionListForm(), request,
601: response);
602: }
603: ActionMessages messages = new ActionMessages();
604: List invocations = new ArrayList();
605: int index = 0;
606: for (Iterator iterator = actionListForm.getActionsToTake()
607: .iterator(); iterator.hasNext();) {
608: ActionToTake actionToTake = (ActionToTake) iterator.next();
609: if (actionToTake != null
610: && actionToTake.getActionTakenCd() != null
611: && !"".equals(actionToTake.getActionTakenCd())
612: && !"NONE".equalsIgnoreCase(actionToTake
613: .getActionTakenCd())
614: && actionToTake.getActionItemId() != null) {
615: ActionItem actionItem = getActionItemFromActionList(
616: actionList, actionToTake.getActionItemId());
617: if (actionItem == null) {
618: LOG
619: .warn("Could not locate the ActionItem to take mass action against in the action list: "
620: + actionToTake.getActionItemId());
621: continue;
622: }
623: invocations.add(new ActionInvocation(actionItem
624: .getActionItemId(), actionToTake
625: .getActionTakenCd()));
626: }
627: index++;
628: }
629: KEWServiceLocator.getWorkflowDocumentService().takeMassActions(
630: getUserSession(request).getWorkflowUser(), invocations);
631: messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
632: "general.routing.processed"));
633: saveMessages(request, messages);
634: ActionListForm cleanForm = new ActionListForm();
635: request.setAttribute(mapping.getName(), cleanForm);
636: request.getSession().setAttribute(REQUERY_ACTION_LIST_KEY,
637: "true");
638: return start(mapping, cleanForm, request, response);
639: }
640:
641: protected ActionItem getActionItemFromActionList(List actionList,
642: Long actionItemId) {
643: for (Iterator iterator = actionList.iterator(); iterator
644: .hasNext();) {
645: ActionItem actionItem = (ActionItem) iterator.next();
646: if (actionItem.getActionItemId().equals(actionItemId)) {
647: return actionItem;
648: }
649: }
650: return null;
651: }
652:
653: public ActionForward helpDeskActionListLogin(ActionMapping mapping,
654: ActionForm form, HttpServletRequest request,
655: HttpServletResponse response) throws Exception {
656: ActionListForm actionListForm = (ActionListForm) form;
657: UserService userSrv = (UserService) KEWServiceLocator
658: .getUserService();
659: WorkflowUser helpDeskActionListUser = userSrv
660: .getWorkflowUser(new AuthenticationUserId(
661: actionListForm.getHelpDeskActionListUserName()));
662: getUserSession(request).setHelpDeskActionListUser(
663: helpDeskActionListUser);
664: actionListForm.setDelegator(null);
665: request.getSession().setAttribute("requeryActionList", "true");
666: return start(mapping, form, request, response);
667: }
668:
669: public ActionForward clearFilter(ActionMapping mapping,
670: ActionForm form, HttpServletRequest request,
671: HttpServletResponse response) throws Exception {
672: LOG.info("clearFilter ActionListAction");
673: UserSession session = getUserSession(request);
674: session.setActionListFilter(null);
675: request.getSession().setAttribute("requeryActionList", "true");
676: KEWServiceLocator.getUserOptionsService()
677: .saveRefreshUserOption(session.getWorkflowUser());
678: LOG.info("end clearFilter ActionListAction");
679: return start(mapping, form, request, response);
680: }
681:
682: public ActionForward clearHelpDeskActionListUser(
683: ActionMapping mapping, ActionForm form,
684: HttpServletRequest request, HttpServletResponse response)
685: throws Exception {
686: LOG.info("clearHelpDeskActionListUser ActionListAction");
687: getUserSession(request).setHelpDeskActionListUser(null);
688: LOG.info("end clearHelpDeskActionListUser ActionListAction");
689: return start(mapping, form, request, response);
690: }
691:
692: private boolean isActionCompatibleRequest(
693: ActionItemActionListExtension actionItem,
694: String actionTakenCode) {
695: boolean actionCompatible = false;
696: String requestCd = actionItem.getActionRequestCd();
697:
698: //FYI request matches FYI
699: if (EdenConstants.ACTION_REQUEST_FYI_REQ.equals(requestCd)
700: && EdenConstants.ACTION_TAKEN_FYI_CD
701: .equals(actionTakenCode)) {
702: actionCompatible = true || actionCompatible;
703: }
704:
705: // ACK request matches ACK
706: if (EdenConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ
707: .equals(requestCd)
708: && EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
709: .equals(actionTakenCode)) {
710: actionCompatible = true || actionCompatible;
711: }
712:
713: // APPROVE request matches all but FYI and ACK
714: if (EdenConstants.ACTION_REQUEST_APPROVE_REQ.equals(requestCd)
715: && !(EdenConstants.ACTION_TAKEN_FYI_CD
716: .equals(actionTakenCode) || EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
717: .equals(actionTakenCode))) {
718: actionCompatible = true || actionCompatible;
719: }
720:
721: // COMPLETE request matches all but FYI and ACK
722: if (EdenConstants.ACTION_REQUEST_COMPLETE_REQ.equals(requestCd)
723: && !(EdenConstants.ACTION_TAKEN_FYI_CD
724: .equals(actionTakenCode) || EdenConstants.ACTION_TAKEN_ACKNOWLEDGED_CD
725: .equals(actionTakenCode))) {
726: actionCompatible = true || actionCompatible;
727: }
728:
729: return actionCompatible;
730: }
731:
732: public ActionMessages establishRequiredState(
733: HttpServletRequest request, ActionForm form)
734: throws Exception {
735: LOG.info("establishRequiredState ActionListAction");
736: ActionListForm actionListForm = (ActionListForm) form;
737:
738: // take the UserSession from the HttpSession and add it to the request
739: request.setAttribute("UserSession", getUserSession(request));
740:
741: //refactor actionlist.jsp not to be dependent on this
742: request.setAttribute("preferences", getUserSession(request)
743: .getPreferences());
744:
745: WorkgroupService workgroupSrv = (WorkgroupService) KEWServiceLocator
746: .getWorkgroupService();
747: String edenHelpDeskWgName = Utilities
748: .getApplicationConstant(EdenConstants.HELP_DESK_ACTION_LIST_KEY);
749: if (edenHelpDeskWgName != null
750: && workgroupSrv.isUserMemberOfGroup(new GroupNameId(
751: edenHelpDeskWgName), getUserSession(request)
752: .getWorkflowUser())) {
753: request.setAttribute("helpDeskActionList", "true");
754: }
755: String routeLogPopup = Utilities
756: .getApplicationConstant(EdenConstants.ACTION_LIST_ROUTE_LOG_POPUP_KEY);
757: if (StringUtils.isEmpty(routeLogPopup)) {
758: routeLogPopup = "false";
759: }
760: String documentPopup = Utilities
761: .getApplicationConstant(EdenConstants.ACTION_LIST_DOCUMENT_POPUP_KEY);
762: if (StringUtils.isEmpty(documentPopup)) {
763: documentPopup = "false";
764: }
765: actionListForm.setRouteLogPopup(routeLogPopup.trim());
766: actionListForm.setDocumentPopup(documentPopup.trim());
767: LOG.info("end establishRequiredState ActionListAction");
768: return null;
769: }
770:
771: public ActionMessages establishFinalState(
772: HttpServletRequest request, ActionForm form)
773: throws Exception {
774: LOG.info("establishFinalState ActionListAction");
775: ActionListForm actionListForm = (ActionListForm) form;
776: if (getUserSession(request).getHelpDeskActionListUser() != null) {
777: actionListForm
778: .setHelpDeskActionListUserName(getUserSession(
779: request).getHelpDeskActionListUser()
780: .getAuthenticationUserId()
781: .getAuthenticationId());
782: }
783: LOG.info("end establishFinalState ActionListAction");
784: return null;
785: }
786:
787: private List getWebFriendlyRecipients(Collection recipients) {
788: Collection newRecipients = new ArrayList(recipients.size());
789: for (Iterator iterator = recipients.iterator(); iterator
790: .hasNext();) {
791: newRecipients.add(new WebFriendlyRecipient(
792: (Recipient) iterator.next()));
793: }
794: List recipientList = new ArrayList(newRecipients);
795: Collections.sort(recipientList, new Comparator() {
796: Comparator comp = new ComparableComparator();
797:
798: public int compare(Object o1, Object o2) {
799: return comp.compare(((WebFriendlyRecipient) o1)
800: .getDisplayName().trim().toLowerCase(),
801: ((WebFriendlyRecipient) o2).getDisplayName()
802: .trim().toLowerCase());
803: }
804: });
805: return recipientList;
806: }
807:
808: public class WebFriendlyRecipient {
809: private String displayName;
810: private String recipientId;
811:
812: public WebFriendlyRecipient(Recipient recipient) {
813: if (recipient instanceof Workgroup) {
814: recipientId = ((Workgroup) recipient)
815: .getWorkflowGroupId().getGroupId().toString();
816: displayName = recipient.getDisplayName();
817: } else if (recipient instanceof WorkflowUser) {
818: recipientId = ((WorkflowUser) recipient)
819: .getWorkflowUserId().getWorkflowId();
820: displayName = ((WorkflowUser) recipient)
821: .getTransposedName();
822: }
823: }
824:
825: public String getRecipientId() {
826: return recipientId;
827: }
828:
829: public String getDisplayName() {
830: return displayName;
831: }
832: }
833:
834: private class ActionItemComparator implements Comparator {
835:
836: private static final String DOCUMENT_ID = "routeHeaderId";
837:
838: private final String sortName;
839:
840: public ActionItemComparator(String sortName) {
841: if (StringUtils.isEmpty(sortName)) {
842: sortName = DOCUMENT_ID;
843: }
844: this .sortName = sortName;
845: }
846:
847: public int compare(Object object1, Object object2) {
848: try {
849: ActionItem actionItem1 = (ActionItem) object1;
850: ActionItem actionItem2 = (ActionItem) object2;
851: // invoke the power of the lookup functionality provided by the display tag library, this LookupUtil method allows for us
852: // to evaulate nested bean properties (like workgroup.groupNameId.nameId) in a null-safe manner. For example, in the
853: // example if workgroup evaluated to NULL then LookupUtil.getProperty would return null rather than blowing an exception
854: Object property1 = LookupUtil.getProperty(actionItem1,
855: sortName);
856: Object property2 = LookupUtil.getProperty(actionItem2,
857: sortName);
858: if (property1 == null && property2 == null) {
859: return 0;
860: } else if (property1 == null) {
861: return -1;
862: } else if (property2 == null) {
863: return 1;
864: }
865: if (property1 instanceof Comparable) {
866: return ((Comparable) property1)
867: .compareTo(property2);
868: }
869: return property1.toString().compareTo(
870: property2.toString());
871: } catch (Exception e) {
872: if (e instanceof RuntimeException) {
873: throw (RuntimeException) e;
874: }
875: throw new RuntimeException(
876: "Could not sort for the given sort name: "
877: + sortName, e);
878: }
879: }
880: }
881:
882: }
|