001: /*
002: * Copyright 2005-2007 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.routeheader;
018:
019: import java.sql.Timestamp;
020: import java.util.Date;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Set;
025:
026: import edu.iu.uis.eden.EdenConstants;
027: import edu.iu.uis.eden.KEWServiceLocator;
028: import edu.iu.uis.eden.actionitem.ActionItem;
029: import edu.iu.uis.eden.actions.AcknowledgeAction;
030: import edu.iu.uis.eden.actions.ActionTakenEvent;
031: import edu.iu.uis.eden.actions.AdHocAction;
032: import edu.iu.uis.eden.actions.AdHocRevoke;
033: import edu.iu.uis.eden.actions.ApproveAction;
034: import edu.iu.uis.eden.actions.BlanketApproveAction;
035: import edu.iu.uis.eden.actions.CancelAction;
036: import edu.iu.uis.eden.actions.ClearFYIAction;
037: import edu.iu.uis.eden.actions.CompleteAction;
038: import edu.iu.uis.eden.actions.DisapproveAction;
039: import edu.iu.uis.eden.actions.LogDocumentActionAction;
040: import edu.iu.uis.eden.actions.MoveDocumentAction;
041: import edu.iu.uis.eden.actions.MovePoint;
042: import edu.iu.uis.eden.actions.ReleaseWorkgroupAuthority;
043: import edu.iu.uis.eden.actions.ReturnToPreviousNodeAction;
044: import edu.iu.uis.eden.actions.RevokeAdHocAction;
045: import edu.iu.uis.eden.actions.RouteDocumentAction;
046: import edu.iu.uis.eden.actions.SaveActionEvent;
047: import edu.iu.uis.eden.actions.SuperUserActionRequestApproveEvent;
048: import edu.iu.uis.eden.actions.SuperUserApproveEvent;
049: import edu.iu.uis.eden.actions.SuperUserCancelEvent;
050: import edu.iu.uis.eden.actions.SuperUserDisapproveEvent;
051: import edu.iu.uis.eden.actions.SuperUserNodeApproveEvent;
052: import edu.iu.uis.eden.actions.SuperUserReturnToPreviousNodeAction;
053: import edu.iu.uis.eden.actions.TakeWorkgroupAuthority;
054: import edu.iu.uis.eden.actions.asyncservices.ActionInvocation;
055: import edu.iu.uis.eden.actions.asyncservices.ActionInvocationService;
056: import edu.iu.uis.eden.actions.asyncservices.BlanketApproveProcessorService;
057: import edu.iu.uis.eden.docsearch.SearchableAttributeProcessingService;
058: import edu.iu.uis.eden.engine.CompatUtils;
059: import edu.iu.uis.eden.engine.RouteContext;
060: import edu.iu.uis.eden.engine.node.RouteNode;
061: import edu.iu.uis.eden.exception.DocumentTypeNotFoundException;
062: import edu.iu.uis.eden.exception.EdenUserNotFoundException;
063: import edu.iu.uis.eden.exception.InvalidActionTakenException;
064: import edu.iu.uis.eden.exception.WorkflowException;
065: import edu.iu.uis.eden.exception.WorkflowRuntimeException;
066: import edu.iu.uis.eden.messaging.MessageServiceNames;
067: import edu.iu.uis.eden.user.Recipient;
068: import edu.iu.uis.eden.user.WorkflowUser;
069: import edu.iu.uis.eden.util.Utilities;
070: import edu.iu.uis.eden.workgroup.Workgroup;
071:
072: /**
073: * @author rkirkend
074: *
075: * this class mainly interacts with ActionEvent 'action' classes and non-vo objects.
076: *
077: */
078:
079: public class WorkflowDocumentServiceImpl implements
080: WorkflowDocumentService {
081:
082: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
083: .getLogger(WorkflowDocumentServiceImpl.class);
084:
085: private void init(DocumentRouteHeaderValue routeHeader) {
086: KEWServiceLocator.getRouteHeaderService().lockRouteHeader(
087: routeHeader.getRouteHeaderId(), true);
088: KEWServiceLocator.getRouteHeaderService().saveRouteHeader(
089: routeHeader);
090: }
091:
092: private DocumentRouteHeaderValue finish(
093: DocumentRouteHeaderValue routeHeader) {
094: // reload the document from the database to get a "fresh and clean" copy if we aren't in the context of a
095: // document being routed
096: if (RouteContext.getCurrentRouteContext().getDocument() == null) {
097: return KEWServiceLocator.getRouteHeaderService()
098: .getRouteHeader(routeHeader.getRouteHeaderId(),
099: true);
100: } else {
101: // we could enter this case if someone calls a method on WorkflowDocument (such as app specific route)
102: // from their post processor, in that case, if we cleared the database case as above we would
103: // end up getting an optimistic lock exception when the engine attempts to save the document after
104: // the post processor call
105: return routeHeader;
106: }
107: }
108:
109: public DocumentRouteHeaderValue acknowledgeDocument(
110: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
111: String annotation) throws InvalidActionTakenException,
112: EdenUserNotFoundException {
113: AcknowledgeAction action = new AcknowledgeAction(routeHeader,
114: user, annotation);
115: action.recordAction();
116: action.queueDocument();
117: return finish(routeHeader);
118: }
119:
120: public DocumentRouteHeaderValue releaseWorkgroupAuthority(
121: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
122: Workgroup workgroup, String annotation)
123: throws InvalidActionTakenException,
124: EdenUserNotFoundException {
125: ReleaseWorkgroupAuthority action = new ReleaseWorkgroupAuthority(
126: routeHeader, user, annotation, workgroup);
127: action.recordAction();
128: action.queueDocument();
129: return finish(routeHeader);
130: }
131:
132: public DocumentRouteHeaderValue takeWorkgroupAuthority(
133: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
134: Workgroup workgroup, String annotation)
135: throws InvalidActionTakenException,
136: EdenUserNotFoundException {
137: TakeWorkgroupAuthority action = new TakeWorkgroupAuthority(
138: routeHeader, user, annotation, workgroup);
139: action.recordAction();
140: action.queueDocument();
141: return finish(routeHeader);
142: }
143:
144: public DocumentRouteHeaderValue approveDocument(WorkflowUser user,
145: DocumentRouteHeaderValue routeHeader, String annotation)
146: throws InvalidActionTakenException,
147: EdenUserNotFoundException {
148: ApproveAction action = new ApproveAction(routeHeader, user,
149: annotation);
150: action.recordAction();
151: action.queueDocument();
152: return finish(routeHeader);
153: }
154:
155: public DocumentRouteHeaderValue appSpecificRouteDocument(
156: WorkflowUser user, DocumentRouteHeaderValue document,
157: String actionRequested, String nodeName, String annotation,
158: Recipient recipient, String responsibilityDesc,
159: Boolean ignorePrevious) throws WorkflowException {
160: AdHocAction action = new AdHocAction(document, user,
161: annotation, actionRequested, nodeName, recipient,
162: responsibilityDesc, ignorePrevious);
163: action.recordAction();
164: action.queueDocument();
165: return finish(document);
166: }
167:
168: public DocumentRouteHeaderValue blanketApproval(WorkflowUser user,
169: DocumentRouteHeaderValue routeHeader, String annotation,
170: Integer routeLevel) throws InvalidActionTakenException,
171: EdenUserNotFoundException {
172: RouteNode node = (routeLevel == null ? null : CompatUtils
173: .getNodeForLevel(routeHeader.getDocumentType(),
174: routeLevel));
175: if (node == null && routeLevel != null) {
176: throw new InvalidActionTakenException(
177: "Could not locate node for route level "
178: + routeLevel);
179: }
180: Set<String> nodeNames = new HashSet<String>();
181: if (node != null) {
182: nodeNames = Utilities.asSet(node.getRouteNodeName());
183: }
184: ActionTakenEvent action = new BlanketApproveAction(routeHeader,
185: user, annotation, nodeNames);
186: action.recordAction();
187: try {
188:
189: BlanketApproveProcessorService blanketApprove = MessageServiceNames
190: .getBlanketApproveProcessorService(routeHeader);
191: blanketApprove.doBlanketApproveWork(routeHeader
192: .getRouteHeaderId(), user, action
193: .getActionTakenId(), nodeNames);
194: // KEWAsyncronousJavaService blanketApproveProcessor = (KEWAsyncronousJavaService)SpringServiceLocator.getMessageHelper().getServiceAsynchronously(
195: // MessageServiceNames.BLANKET_APPROVE_PROCESSING_SERVICE, routeHeader);
196: //
197: // blanketApproveProcessor.invoke(BlanketApproveProcessor.getPayLoad(user, action.getActionTaken(), nodeNames, routeHeader));
198:
199: // SpringServiceLocator.getMessageHelper().sendMessage(MessageServiceNames.BLANKET_APPROVE_PROCESSING_SERVICE,
200: // BlanketApproveProcessor.getPayLoad(user, action.getActionTaken(), nodeNames, routeHeader), routeHeader);
201: } catch (Exception e) {
202: LOG.error(e);
203: throw new WorkflowRuntimeException(e);
204: }
205:
206: // SpringServiceLocator.getRouteQueueService().requeueDocument(routeHeader.getRouteHeaderId(), EdenConstants.ROUTE_QUEUE_BLANKET_APPROVE_PRIORITY, new Long(0),
207: // BlanketApproveProcessor.class.getName(), BlanketApproveProcessor.getBlanketApproveProcessorValue(user, action.getActionTaken(), nodeNames));
208: return finish(routeHeader);
209: }
210:
211: public DocumentRouteHeaderValue blanketApproval(WorkflowUser user,
212: DocumentRouteHeaderValue routeHeader, String annotation,
213: Set nodeNames) throws InvalidActionTakenException,
214: EdenUserNotFoundException {
215: BlanketApproveAction action = new BlanketApproveAction(
216: routeHeader, user, annotation, nodeNames);
217: action.recordAction();
218:
219: try {
220:
221: BlanketApproveProcessorService blanketApprove = MessageServiceNames
222: .getBlanketApproveProcessorService(routeHeader);
223: blanketApprove.doBlanketApproveWork(routeHeader
224: .getRouteHeaderId(), user, action
225: .getActionTakenId(), nodeNames);
226: //
227:
228: // KEWAsyncronousJavaService blanketApproveProcessor = (KEWAsyncronousJavaService)SpringServiceLocator.getMessageHelper().getServiceAsynchronously(
229: // MessageServiceNames.BLANKET_APPROVE_PROCESSING_SERVICE, routeHeader);
230: // blanketApproveProcessor.invoke(BlanketApproveProcessor.getPayLoad(user, action.getActionTaken(), nodeNames, routeHeader));
231:
232: // SpringServiceLocator.getMessageHelper().sendMessage(MessageServiceNames.BLANKET_APPROVE_PROCESSING_SERVICE,
233: // BlanketApproveProcessor.getPayLoad(user, action.getActionTaken(), nodeNames, routeHeader), routeHeader);
234: } catch (Exception e) {
235: LOG.error(e);
236: throw new WorkflowRuntimeException(e);
237: }
238: // SpringServiceLocator.getRouteQueueService().requeueDocument(routeHeader.getRouteHeaderId(), EdenConstants.ROUTE_QUEUE_BLANKET_APPROVE_PRIORITY, new Long(0),
239: // BlanketApproveProcessor.class.getName(), BlanketApproveProcessor.getBlanketApproveProcessorValue(user, action.getActionTaken(), nodeNames));
240: return finish(routeHeader);
241: }
242:
243: public DocumentRouteHeaderValue cancelDocument(WorkflowUser user,
244: DocumentRouteHeaderValue routeHeader, String annotation)
245: throws InvalidActionTakenException,
246: EdenUserNotFoundException {
247: // init(routeHeader);
248: CancelAction action = new CancelAction(routeHeader, user,
249: annotation);
250: action.recordAction();
251: return finish(routeHeader);
252: }
253:
254: public DocumentRouteHeaderValue clearFYIDocument(WorkflowUser user,
255: DocumentRouteHeaderValue routeHeader)
256: throws InvalidActionTakenException,
257: EdenUserNotFoundException {
258: // init(routeHeader);
259: ClearFYIAction action = new ClearFYIAction(routeHeader, user,
260: "");
261: action.recordAction();
262: return finish(routeHeader);
263: }
264:
265: public DocumentRouteHeaderValue completeDocument(WorkflowUser user,
266: DocumentRouteHeaderValue routeHeader, String annotation)
267: throws InvalidActionTakenException,
268: EdenUserNotFoundException {
269: CompleteAction action = new CompleteAction(routeHeader, user,
270: annotation);
271: action.recordAction();
272: action.queueDocument();
273: return finish(routeHeader);
274: }
275:
276: public DocumentRouteHeaderValue createDocument(WorkflowUser user,
277: DocumentRouteHeaderValue routeHeader)
278: throws DocumentTypeNotFoundException, WorkflowException {
279:
280: LOG.debug("Rmi createDocument() with "); // add some sort of a
281: // routeheader logger
282:
283: if (routeHeader.getRouteHeaderId() != null) { // this is a debateable
284: // check - means the
285: // client is off
286: throw new InvalidActionTakenException(
287: "Document already has a Document id");
288: }
289:
290: if (!routeHeader.getDocumentType().isDocTypeActive()) {
291: // don't allow creation if document type is inactive
292: throw new InvalidActionTakenException("Document type '"
293: + routeHeader.getDocumentType().getName()
294: + "' is inactive");
295: }
296:
297: routeHeader.setInitiatorWorkflowId(user.getWorkflowUserId()
298: .getWorkflowId());
299: if (routeHeader.getDocRouteStatus() == null) {
300: routeHeader
301: .setDocRouteStatus(EdenConstants.ROUTE_HEADER_INITIATED_CD);
302: }
303: if (routeHeader.getDocRouteLevel() == null) {
304: routeHeader.setDocRouteLevel(new Integer(
305: EdenConstants.ADHOC_ROUTE_LEVEL));
306: }
307: if (routeHeader.getCreateDate() == null) {
308: routeHeader.setCreateDate(new Timestamp(new Date()
309: .getTime()));
310: }
311: if (routeHeader.getDocVersion() == null) {
312: routeHeader.setDocVersion(new Integer(
313: EdenConstants.CURRENT_DOCUMENT_VERSION));
314: }
315: if (routeHeader.getDocContent() == null) {
316: routeHeader
317: .setDocContent(EdenConstants.DEFAULT_DOCUMENT_CONTENT);
318: }
319: routeHeader
320: .setStatusModDate(new Timestamp(new Date().getTime()));
321: KEWServiceLocator.getRouteHeaderService().saveRouteHeader(
322: routeHeader);
323: KEWServiceLocator.getWorkflowEngine().initializeDocument(
324: routeHeader);
325: KEWServiceLocator.getRouteHeaderService().saveRouteHeader(
326: routeHeader);
327: return routeHeader;
328: }
329:
330: public DocumentRouteHeaderValue disapproveDocument(
331: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
332: String annotation) throws InvalidActionTakenException,
333: EdenUserNotFoundException {
334: DisapproveAction action = new DisapproveAction(routeHeader,
335: user, annotation);
336: action.recordAction();
337: return finish(routeHeader);
338: }
339:
340: public DocumentRouteHeaderValue returnDocumentToPreviousRouteLevel(
341: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
342: Integer destRouteLevel, String annotation)
343: throws InvalidActionTakenException,
344: EdenUserNotFoundException {
345: RouteNode node = (destRouteLevel == null ? null : CompatUtils
346: .getNodeForLevel(routeHeader.getDocumentType(),
347: destRouteLevel));
348: if (node == null && destRouteLevel != null) {
349: throw new InvalidActionTakenException(
350: "Could not locate node for route level "
351: + destRouteLevel);
352: }
353: ReturnToPreviousNodeAction action = new ReturnToPreviousNodeAction(
354: routeHeader, user, annotation, node.getRouteNodeName(),
355: true);
356: action.recordAction();
357: action.queueDocument();
358: return finish(routeHeader);
359: }
360:
361: public DocumentRouteHeaderValue returnDocumentToPreviousNode(
362: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
363: String destinationNodeName, String annotation)
364: throws InvalidActionTakenException,
365: EdenUserNotFoundException {
366: ReturnToPreviousNodeAction action = new ReturnToPreviousNodeAction(
367: routeHeader, user, annotation, destinationNodeName,
368: true);
369: action.recordAction();
370: action.queueDocument();
371: return finish(routeHeader);
372: }
373:
374: public DocumentRouteHeaderValue routeDocument(WorkflowUser user,
375: DocumentRouteHeaderValue routeHeader, String annotation)
376: throws WorkflowException, InvalidActionTakenException,
377: EdenUserNotFoundException {
378: RouteDocumentAction actionEvent = new RouteDocumentAction(
379: routeHeader, user, annotation);
380: actionEvent.recordAction();
381: LOG.info("routeDocument: " + routeHeader);
382: actionEvent.queueDocument();
383: return finish(routeHeader);
384: }
385:
386: public DocumentRouteHeaderValue saveRoutingData(WorkflowUser user,
387: DocumentRouteHeaderValue routeHeader) {
388: KEWServiceLocator.getRouteHeaderService().saveRouteHeader(
389: routeHeader);
390: if (routeHeader.getDocumentType().hasSearchableAttributes()) {
391: SearchableAttributeProcessingService searchableAttService = (SearchableAttributeProcessingService) MessageServiceNames
392: .getSearchableAttributeService(routeHeader);
393: searchableAttService.indexDocument(routeHeader
394: .getRouteHeaderId());
395: }
396: return finish(routeHeader);
397: }
398:
399: public DocumentRouteHeaderValue saveDocument(WorkflowUser user,
400: DocumentRouteHeaderValue routeHeader, String annotation)
401: throws InvalidActionTakenException,
402: EdenUserNotFoundException {
403: SaveActionEvent action = new SaveActionEvent(routeHeader, user,
404: annotation);
405: action.recordAction();
406: action.queueDocument();
407: return finish(routeHeader);
408: }
409:
410: public void deleteDocument(WorkflowUser user,
411: DocumentRouteHeaderValue routeHeader)
412: throws WorkflowException {
413: if (routeHeader.getRouteHeaderId() == null) {
414: LOG.info("Null Document id passed.");
415: throw new WorkflowException("Document id must not be null.");
416: }
417: KEWServiceLocator.getRouteHeaderService().deleteRouteHeader(
418: routeHeader);
419: }
420:
421: public void logDocumentAction(WorkflowUser user,
422: DocumentRouteHeaderValue routeHeader, String annotation)
423: throws EdenUserNotFoundException,
424: InvalidActionTakenException {
425: LogDocumentActionAction action = new LogDocumentActionAction(
426: routeHeader, user, annotation);
427: action.recordAction();
428: }
429:
430: public DocumentRouteHeaderValue moveDocument(WorkflowUser user,
431: DocumentRouteHeaderValue routeHeader, MovePoint movePoint,
432: String annotation) throws InvalidActionTakenException,
433: EdenUserNotFoundException {
434: MoveDocumentAction action = new MoveDocumentAction(routeHeader,
435: user, annotation, movePoint);
436: action.recordAction();
437: action.queueDocument();
438: return finish(routeHeader);
439: }
440:
441: public DocumentRouteHeaderValue super UserActionRequestApproveAction(
442: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
443: Long actionRequestId, String annotation)
444: throws InvalidActionTakenException,
445: EdenUserNotFoundException {
446: init(routeHeader);
447: SuperUserActionRequestApproveEvent suActionRequestApprove = new SuperUserActionRequestApproveEvent(
448: routeHeader, user, actionRequestId, annotation);
449: suActionRequestApprove.recordAction();
450: // suActionRequestApprove.queueDocument();
451: return finish(routeHeader);
452: }
453:
454: public DocumentRouteHeaderValue super UserApprove(WorkflowUser user,
455: DocumentRouteHeaderValue routeHeader, String annotation)
456: throws InvalidActionTakenException,
457: EdenUserNotFoundException {
458: init(routeHeader);
459: new SuperUserApproveEvent(routeHeader, user, annotation)
460: .recordAction();
461: return finish(routeHeader);
462: }
463:
464: public DocumentRouteHeaderValue super UserCancelAction(
465: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
466: String annotation) throws InvalidActionTakenException,
467: EdenUserNotFoundException {
468: init(routeHeader);
469: new SuperUserCancelEvent(routeHeader, user, annotation)
470: .recordAction();
471: return finish(routeHeader);
472: }
473:
474: public DocumentRouteHeaderValue super UserDisapproveAction(
475: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
476: String annotation) throws InvalidActionTakenException,
477: EdenUserNotFoundException {
478: init(routeHeader);
479: new SuperUserDisapproveEvent(routeHeader, user, annotation)
480: .recordAction();
481: return finish(routeHeader);
482: }
483:
484: public DocumentRouteHeaderValue super UserNodeApproveAction(
485: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
486: String nodeName, String annotation)
487: throws InvalidActionTakenException,
488: EdenUserNotFoundException {
489: init(routeHeader);
490: new SuperUserNodeApproveEvent(routeHeader, user, annotation,
491: nodeName).recordAction();
492: return finish(routeHeader);
493: }
494:
495: /**
496: * TODO remove this implementation in favor of having the SuperUserAction call through the WorkflowDocument object. This
497: * method is here to resolve KULWF-727 where we were getting an optimistic lock exception from the super user screen on
498: * return to previous node. This allows us to load the DocumentRouteHeaderValue inside of the transaction interceptor
499: * so that we can stay within the same PersistenceBroker cache.
500: */
501: public DocumentRouteHeaderValue super UserReturnDocumentToPreviousNode(
502: WorkflowUser user, Long documentId, String nodeName,
503: String annotation) throws InvalidActionTakenException,
504: EdenUserNotFoundException {
505: return super UserReturnDocumentToPreviousNode(user,
506: KEWServiceLocator.getRouteHeaderService()
507: .getRouteHeader(documentId), nodeName,
508: annotation);
509: }
510:
511: public DocumentRouteHeaderValue super UserReturnDocumentToPreviousNode(
512: WorkflowUser user, DocumentRouteHeaderValue routeHeader,
513: String nodeName, String annotation)
514: throws InvalidActionTakenException,
515: EdenUserNotFoundException {
516: init(routeHeader);
517: SuperUserReturnToPreviousNodeAction action = new SuperUserReturnToPreviousNodeAction(
518: routeHeader, user, annotation, nodeName);
519: action.recordAction();
520: // action.queueDocument();
521:
522: return finish(routeHeader);
523: }
524:
525: public void takeMassActions(WorkflowUser user,
526: List actionInvocations) {
527: for (Iterator iterator = actionInvocations.iterator(); iterator
528: .hasNext();) {
529: ActionInvocation invocation = (ActionInvocation) iterator
530: .next();
531: ActionItem actionItem = KEWServiceLocator
532: .getActionListService().findByActionItemId(
533: invocation.getActionItemId());
534: if (actionItem == null) {
535: LOG
536: .warn("Could not locate action item for the given action item id ["
537: + invocation.getActionItemId()
538: + "], not taking mass action on it.");
539: continue;
540: }
541: KEWServiceLocator.getActionListService().deleteActionItem(
542: actionItem);
543: ActionInvocationService actionInvocService = MessageServiceNames
544: .getActionInvocationProcessorService(actionItem
545: .getRouteHeader());
546: actionInvocService.invokeAction(user, actionItem
547: .getRouteHeaderId(), invocation);
548: // ActionInvocationProcessor.queueActionInvocation(user, actionItem.getRouteHeaderId(), invocation);
549: }
550: }
551:
552: public DocumentRouteHeaderValue revokeAdHocRequests(
553: WorkflowUser user, DocumentRouteHeaderValue document,
554: AdHocRevoke revoke, String annotation)
555: throws InvalidActionTakenException,
556: EdenUserNotFoundException {
557: RevokeAdHocAction action = new RevokeAdHocAction(document,
558: user, revoke, annotation);
559: action.recordAction();
560: action.queueDocument();
561: return finish(document);
562: }
563:
564: }
|