View Javadoc
1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.actions;
17  
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertTrue;
23  import static org.junit.Assert.fail;
24  
25  import java.util.Collection;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import mocks.MockEmailNotificationService;
30  
31  import org.junit.Test;
32  import org.kuali.rice.core.api.delegation.DelegationType;
33  import org.kuali.rice.kew.actionrequest.ActionRequestValue;
34  import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
35  import org.kuali.rice.kew.api.WorkflowDocument;
36  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
37  import org.kuali.rice.kew.api.action.InvalidActionTakenException;
38  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
39  import org.kuali.rice.kew.engine.node.service.RouteNodeService;
40  import org.kuali.rice.kew.service.KEWServiceLocator;
41  import org.kuali.rice.kew.test.KEWTestCase;
42  import org.kuali.rice.kew.test.TestUtilities;
43  import org.kuali.rice.kew.api.KewApiConstants;
44  import org.kuali.rice.test.BaselineTestCase.BaselineMode;
45  import org.kuali.rice.test.BaselineTestCase.Mode;
46  
47  @BaselineMode(Mode.CLEAR_DB)
48  public class BlanketApproveTest extends KEWTestCase {
49  
50  	@Override
51      protected void loadTestData() throws Exception {
52          loadXmlFile("ActionsConfig.xml");
53      }
54      
55      /**
56       * When a user is not in the blanket approver workgroup an exception should be thrown and 
57       * it should have a good message.
58       * 
59       * @throws Exception
60       */
61      @Test public void testBlanketApproverNotInBlanketApproverWorkgroup() throws Exception  {
62      	WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
63      	try {
64      		document.blanketApprove("");
65      		fail("InvalidActionTakenException should have been thrown");
66      	} catch (InvalidActionTakenException iate) {
67      		assertEquals("Exception on message is incorrent", "User is not authorized to BlanketApprove document", iate.getMessage());
68      	}
69          
70      }
71      
72      /**
73       * When a user is in the blanket approve workgroup but the user is not the initiator an exception
74       * should be thrown.
75       */
76      @Test public void testBlanketApproverNotInitiator() throws Exception  {
77          WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
78          WorkflowDocument newDocument = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
79          try {
80              newDocument.blanketApprove("");
81              fail("Exception should have been thrown when non-initiator user attempts blanket approve on default blanket approve policy document");
82          } catch (Exception e) {
83              e.printStackTrace();
84          }
85      }
86      
87      @SuppressWarnings("deprecation")
88  	@Test public void testBlanketApproveSequential() throws Exception {
89          WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
90          document.blanketApprove("");
91          document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
92          assertTrue("Document should be processed.", document.isProcessed());
93          Collection nodeInstances = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
94          // once the document is processed there are no active nodes
95          assertEquals("Wrong number of active nodes.", 0, nodeInstances.size());
96          nodeInstances = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
97          assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
98          RouteNodeInstance ackNodeInstance = (RouteNodeInstance)nodeInstances.iterator().next();
99          assertEquals("At wrong node.", SequentialSetup.ACKNOWLEDGE_2_NODE, ackNodeInstance.getRouteNode().getRouteNodeName());
100         assertTrue("Node should be complete.", ackNodeInstance.isComplete());
101         List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
102         assertEquals("Wrong number of pending action requests.", 5, actionRequests.size());
103         boolean isNotification1 = false;
104         boolean isNotification2 = false;
105         boolean isNotification3 = false;
106         boolean isAck1 = false;
107         boolean isAck2 = false;
108         for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
109             ActionRequestValue actionRequest = (ActionRequestValue) iterator.next();
110             assertEquals("Should only be acknowledges.", KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, actionRequest.getActionRequested());
111             RouteNodeInstance nodeInstance = actionRequest.getNodeInstance();
112             assertNotNull(nodeInstance);
113             String nodeName = nodeInstance.getRouteNode().getRouteNodeName();
114             if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("bmcgough"))) {
115                 isNotification1 = true;
116                 assertEquals(SequentialSetup.WORKFLOW_DOCUMENT_NODE, nodeName);
117                 assertEquals(KewApiConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, actionRequest.getResponsibilityId());
118             } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("rkirkend"))) {
119                 isNotification2 = true;
120                 assertEquals(SequentialSetup.WORKFLOW_DOCUMENT_NODE, nodeName);
121                 assertEquals(KewApiConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, actionRequest.getResponsibilityId());
122             } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("pmckown"))) {
123                 isNotification3 = true;
124                 assertEquals(SequentialSetup.WORKFLOW_DOCUMENT_2_NODE, nodeName);
125                 assertEquals(KewApiConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, actionRequest.getResponsibilityId());
126             } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("temay"))) {
127                 isAck1 = true;
128                 assertEquals(SequentialSetup.ACKNOWLEDGE_1_NODE, nodeName);
129                 assertFalse(KewApiConstants.MACHINE_GENERATED_RESPONSIBILITY_ID.equals(actionRequest.getResponsibilityId()));
130             } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("jhopf"))) {
131                 isAck2 = true;
132                 assertEquals(SequentialSetup.ACKNOWLEDGE_2_NODE, nodeName);
133                 assertFalse(KewApiConstants.MACHINE_GENERATED_RESPONSIBILITY_ID.equals(actionRequest.getResponsibilityId()));
134             }
135         }
136         assertTrue(isNotification1);
137         assertTrue(isNotification2);
138         assertTrue(isNotification3);
139         assertTrue(isAck1);
140         assertTrue(isAck2);
141         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
142         assertTrue(document.isProcessed());
143         assertTrue(document.isAcknowledgeRequested());
144         assertEquals("bmcgough should not have been sent an approve email", 0, getMockEmailService().immediateReminderEmailsSent("bmcgough", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_APPROVE_REQ));
145         assertEquals("bmcgough should not have been sent an ack email", 1, getMockEmailService().immediateReminderEmailsSent("bmcgough", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
146         document.acknowledge("");
147 
148         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
149         assertTrue(document.isProcessed());
150         assertTrue(document.isAcknowledgeRequested());
151         assertEquals("rkirkend should not have been sent an approve email", 0, getMockEmailService().immediateReminderEmailsSent("rkirkend", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_APPROVE_REQ));
152         assertEquals("rkirkend should not have been sent an ack email", 1, getMockEmailService().immediateReminderEmailsSent("rkirkend", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
153         document.acknowledge("");
154         
155         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("pmckown"), document.getDocumentId());
156         assertTrue(document.isProcessed());
157         assertTrue(document.isAcknowledgeRequested());
158         assertEquals("pmckown should not have been sent an approve email", 0, getMockEmailService().immediateReminderEmailsSent("pmckown", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_APPROVE_REQ));
159         assertEquals("pmckown should not have been sent an ack email", 1, getMockEmailService().immediateReminderEmailsSent("pmckown", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
160         document.acknowledge("");
161         
162         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("temay"), document.getDocumentId());
163         assertTrue(document.isProcessed());
164         assertTrue(document.isAcknowledgeRequested());
165         assertEquals("rkirkend should have been sent an temay", 1, getMockEmailService().immediateReminderEmailsSent("temay", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
166         document.acknowledge("");
167         
168         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId());
169         assertTrue(document.isProcessed());
170         assertTrue(document.isAcknowledgeRequested());
171         assertEquals("rkirkend should have been sent an jhopf", 1, getMockEmailService().immediateReminderEmailsSent("jhopf", document.getDocumentId(), KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
172         document.acknowledge("");
173         
174         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
175         assertTrue(document.isFinal());
176         
177         document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
178         document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_2_NODE);
179         assertTrue("Document should be enroute.", document.isEnroute());
180         nodeInstances = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
181         assertEquals("Should be one active node.", 1, nodeInstances.size());
182         RouteNodeInstance doc2Instance = (RouteNodeInstance)nodeInstances.iterator().next();
183         assertEquals("At wrong node.", SequentialSetup.WORKFLOW_DOCUMENT_2_NODE, doc2Instance.getRouteNode().getRouteNodeName());
184         
185     }
186     
187     @Test public void testBlanketApproveSequentialErrors() throws Exception {
188         // blanket approve to invalid node
189         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
190         try {
191             document.blanketApprove("", "TotallyInvalidNode");
192             fail("Should have thrown exception");
193         } catch (Exception e) {}
194         
195         // blanket approve backwards
196         document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
197         document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_2_NODE);
198         try {
199             document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_NODE);
200             fail("Should have thrown exception");
201         } catch (Exception e) {}
202         
203         // blanket approve to current node
204         document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
205         document.route("");
206         try {
207             document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_NODE);
208             fail("Should have thrown exception");
209         } catch (Exception e) {}
210         
211         // blanket approve as user not in the blanket approve workgroup
212         document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
213         try {
214             document.blanketApprove("");
215             fail("Shouldn't be able to blanket approve if not in blanket approve workgroup");
216         } catch (Exception e) {}
217     }
218     
219     @Test public void testBlanketApproveParallel() throws Exception {
220         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
221         document.blanketApprove("");        
222         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
223         assertTrue("Document should be processed.", document.isProcessed());
224         Collection nodeInstances = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
225         // once the document has gone processed there are no active nodes
226         assertEquals("Wrong number of active nodes.", 0, nodeInstances.size());
227         nodeInstances = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
228         assertEquals("Wrong number of terminal nodes.", 1, nodeInstances.size());
229         RouteNodeInstance ackNodeInstance = (RouteNodeInstance)nodeInstances.iterator().next();
230         assertEquals("At wrong node.", SequentialSetup.ACKNOWLEDGE_2_NODE, ackNodeInstance.getRouteNode().getRouteNodeName());
231         assertTrue("Node should be complete.", ackNodeInstance.isComplete());
232         List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
233         assertEquals("Wrong number of pending action requests.", 10, actionRequests.size());
234 
235     }
236     
237     @Test public void testBlanketApproveIntoBranch() throws Exception {
238         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
239         document.blanketApprove("", ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE);
240         List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
241         assertEquals("Wrong number of pending action requests.", 5, actionRequests.size());
242         
243         // document should now be at the node we blanket approved to and the join node
244         Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
245         assertEquals("Wrong number of active nodes.", 3, activeNodes.size());
246         boolean isAtWD2B1 = false;
247         boolean isAtJoin = false;
248         boolean isAtWD3B2 = false;
249         boolean isAtWD4B3 = false;
250         for (Iterator iterator = activeNodes.iterator(); iterator.hasNext();) {
251             RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next();
252             isAtWD2B1 = isAtWD2B1 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE);
253             isAtWD3B2 = isAtWD3B2 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_3_B2_NODE);
254             isAtWD4B3 = isAtWD4B3 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE);
255             isAtJoin = isAtJoin || nodeInstance.getName().equals(ParallelSetup.JOIN_NODE);
256         }
257         assertTrue("Should be at blanket approved node.", isAtWD2B1);
258         assertTrue("Should be at blanket approved node WD3B2.", isAtWD3B2);
259         assertTrue("Should be at blanket approved node WD4B3.", isAtWD4B3);        
260         assertFalse("Should be at join node.", isAtJoin);
261         
262         document.blanketApprove("");
263         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
264         assertTrue("Document should be processed.", document.isProcessed());
265         actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
266         
267         assertEquals("Wrong number of pending action requests.", 10, actionRequests.size());
268     }
269     
270     @Test public void testBlanketApproveToMultipleNodes() throws Exception {
271         
272         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
273         document.blanketApprove("", new String[] { ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE, ParallelSetup.WORKFLOW_DOCUMENT_3_B2_NODE });
274         List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
275         assertEquals("Wrong number of pending action requests.", 5, actionRequests.size());
276         
277         // document should now be at both nodes we blanket approved to and the join node
278         Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
279         assertEquals("Wrong number of active nodes.", 3, activeNodes.size());
280         boolean isAtWD2B1 = false;
281         boolean isAtWD3B2 = false;
282         boolean isAtJoin = false;
283         boolean isAtWD4B3 = false;
284         for (Iterator iterator = activeNodes.iterator(); iterator.hasNext();) {
285             RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next();
286             isAtWD2B1 = isAtWD2B1 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE);
287             isAtWD3B2 = isAtWD3B2 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_3_B2_NODE);
288             isAtWD4B3 = isAtWD4B3 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE);
289             isAtJoin = isAtJoin || nodeInstance.getName().equals(ParallelSetup.JOIN_NODE);
290         }
291         assertTrue("Should be at blanket approved node WD2B1.", isAtWD2B1);
292         assertTrue("Should be at blanket approved node WD3B2.", isAtWD3B2);
293         assertTrue("Should be at blanket approved node WD4B3.  https://jira.kuali.org/browse/KULRICE-8481 - "
294                 + "BlanketApproveTest.testBlanketApproveToMultipleNodes fails in CI with Should be at blanket approved node WD4B3.", isAtWD4B3);
295         assertFalse("Should not be at join node.", isAtJoin);
296         
297         document.blanketApprove("");
298         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
299         assertTrue("Document should be processed.", document.isProcessed());
300         actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
301         assertEquals("Wrong number of pending action requests.", 10, actionRequests.size());
302     }
303     
304     @Test public void testBlanketApproveToJoin() throws Exception {
305         
306         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
307         document.blanketApprove("", ParallelSetup.JOIN_NODE);
308         assertTrue("Document should still be enroute.", document.isEnroute());
309 
310         // document should now be at the workflow document final node
311         Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
312         assertEquals("Wrong number of active nodes.", 1, activeNodes.size());
313         RouteNodeInstance nodeInstance = (RouteNodeInstance)activeNodes.iterator().next();
314         assertEquals("Document at wrong node.", ParallelSetup.WORKFLOW_DOCUMENT_FINAL_NODE, nodeInstance.getName());
315         
316         document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("xqi"), document.getDocumentId());
317         assertTrue("Should have approve request.", document.isApprovalRequested());
318         document.blanketApprove("", ParallelSetup.ACKNOWLEDGE_1_NODE);
319         
320         activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
321         assertEquals("Wrong number of active nodes.", 0, activeNodes.size());
322         Collection terminalNodes = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
323         assertEquals("Wrong number of terminal nodes.", 1, terminalNodes.size());
324         nodeInstance = (RouteNodeInstance)terminalNodes.iterator().next();
325         assertEquals("Document at wrong node.", ParallelSetup.ACKNOWLEDGE_2_NODE, nodeInstance.getName());
326         assertTrue("Final node not complete.", nodeInstance.isComplete());
327     }
328     
329     @Test public void testBlanketApproveToAcknowledge() throws Exception {
330         
331         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
332         document.blanketApprove("", ParallelSetup.ACKNOWLEDGE_1_NODE);
333         assertTrue("Document should be processed.", document.isProcessed());
334 
335         // document should now be terminal
336         Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
337         assertEquals("Wrong number of active nodes.", 0, activeNodes.size());
338         Collection terminalNodes = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
339         assertEquals("Wrong number of terminal nodes.", 1, terminalNodes.size());
340         RouteNodeInstance nodeInstance = (RouteNodeInstance)terminalNodes.iterator().next();
341         assertEquals("Document at wrong node.", ParallelSetup.ACKNOWLEDGE_2_NODE, nodeInstance.getName());
342         assertTrue("Final node not complete.", nodeInstance.isComplete());
343     }
344     
345     @Test public void testBlanketApproveToMultipleNodesErrors() throws Exception {
346         
347         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
348         try {
349             document.blanketApprove("", new String[] { ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE, ParallelSetup.ACKNOWLEDGE_1_NODE });    
350             fail("document should have thrown exception");
351         } catch (Exception e) {
352             // Shouldn't be able to blanket approve past the join in conjunction with blanket approve within a branch
353         	TestUtilities.getExceptionThreader().join();
354         	document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
355             assertTrue("Document should be in exception routing.", document.isException());            
356         }
357     }
358     
359     /**
360      * Tests that the notifications are generated properly on a blanket approve.  Works against the "NotificationTest" document type.
361      */
362     @Test public void testBlanketApproveNotification() throws Exception {
363         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), NotifySetup.DOCUMENT_TYPE_NAME);
364         document.blanketApprove("");
365         ActionRequestService arService = KEWServiceLocator.getActionRequestService(); 
366         List actionRequests = arService.getRootRequests(arService.findPendingByDoc(document.getDocumentId()));
367         assertEquals("Should be 5 pending acknowledgements and 1 pending fyi", 6, actionRequests.size());
368         boolean foundJhopfNotification = false;
369         boolean foundRkirkendNotification = false;
370         boolean foundJitrueNotification = false;
371         boolean foundBmcgoughNotification = false;
372         boolean foundXqiAck = false;
373         boolean foundJthomasFYI = false;
374         for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
375             ActionRequestValue actionRequest = (ActionRequestValue) iterator.next();
376             RouteNodeInstance nodeInstance = actionRequest.getNodeInstance();
377             String netId = (actionRequest.getPrincipalId() == null ? null : getPrincipalNameForId(actionRequest.getPrincipalId()));
378             if ("jhopf".equals(netId)) {
379                 foundJhopfNotification = true;
380                 assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
381                 assertEquals(NotifySetup.NOTIFY_FIRST_NODE, nodeInstance.getName());
382             } else if ("rkirkend".equals(netId)) {
383                 foundRkirkendNotification = true;
384                 assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
385                 assertEquals(NotifySetup.NOTIFY_LEFT_NODE, nodeInstance.getName());
386                 assertEquals("Rkirkend should have three delegate acks.", 3, actionRequest.getChildrenRequests().size());
387                 assertTrue("Should be primary delegation.", actionRequest.isPrimaryDelegator());
388                 boolean foundTemayDelegate = false;
389                 boolean foundNonSITWGDelegate = false;
390                 boolean foundPmckownDelegate = false;
391                 for (Iterator iterator2 = actionRequest.getChildrenRequests().iterator(); iterator2.hasNext();) {
392                     ActionRequestValue childRequest = (ActionRequestValue) iterator2.next();
393                     assertTrue("Child request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
394                     String childId = (childRequest.isGroupRequest() ? childRequest.getGroup().getName(): getPrincipalNameForId(childRequest.getPrincipalId()));
395                     if ("temay".equals(childId)) {
396                         foundTemayDelegate = true;
397                         assertEquals("Should be primary delegation.", DelegationType.PRIMARY, childRequest.getDelegationType());
398                     } else if ("pmckown".equals(childId)) {
399                         foundPmckownDelegate = true;
400                         assertEquals("Should be secondary delegation.", DelegationType.SECONDARY, childRequest.getDelegationType());
401                     } else if ("NonSIT".equals(childId)) {
402                         foundNonSITWGDelegate = true;
403                         assertEquals("Should be primary delegation.", DelegationType.PRIMARY, childRequest.getDelegationType());
404                     }
405                 }
406                 assertTrue("Could not locate delegate request for temay.", foundTemayDelegate);
407                 assertTrue("Could not locate delegate request for NonSIT Group.", foundNonSITWGDelegate);
408                 assertTrue("Could not locate delegate request for pmckown.", foundPmckownDelegate);
409             } else if ("bmcgough".equals(netId)) {
410                 foundBmcgoughNotification = true;
411                 assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
412                 assertEquals(NotifySetup.NOTIFY_FINAL_NODE, nodeInstance.getName());
413                 
414             } else if ("xqi".equals(netId)) {
415                 foundXqiAck = true;
416                 assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
417                 assertEquals(NotifySetup.NOTIFY_FINAL_NODE, nodeInstance.getName());
418                 
419             } else if ("jthomas".equals(netId)) {
420                 foundJthomasFYI = true;
421                 assertTrue("Action request should be an FYI.", actionRequest.isFYIRequest());
422                 assertEquals(NotifySetup.NOTIFY_FINAL_NODE, nodeInstance.getName());
423             } else if (actionRequest.isRoleRequest()) {
424                List topLevelRequests = arService.getTopLevelRequests(actionRequest);
425                assertEquals(1, topLevelRequests.size());
426                actionRequest = (ActionRequestValue)topLevelRequests.get(0);
427                // this tests the notofication of the role to jitrue with delegates
428                assertEquals("Should be to jitrue.", "jitrue", getPrincipalNameForId(actionRequest.getPrincipalId()));
429                foundJitrueNotification = true;
430                List delegateRoleRequests = arService.getDelegateRequests(actionRequest);
431                assertEquals("Should be 1 delegate role requests", 1, delegateRoleRequests.size());
432                ActionRequestValue delegateRoleRequest = (ActionRequestValue)delegateRoleRequests.get(0);
433                assertEquals("Should be NotifyDelegate role", "NotifyDelegate", delegateRoleRequest.getRoleName());
434                assertEquals("Should be secondary delegation", DelegationType.SECONDARY, delegateRoleRequest.getDelegationType());
435                List delegateRequests = arService.getTopLevelRequests(delegateRoleRequest);
436                assertEquals("Should be 2 delegate requests", 2, delegateRequests.size());
437                boolean foundNatjohnsDelegate = false;
438                boolean foundShenlDelegate = false;
439                for (Iterator iterator2 = delegateRequests.iterator(); iterator2.hasNext();) {
440                    ActionRequestValue delegateRequest = (ActionRequestValue) iterator2.next();
441                    String delNetId = getPrincipalNameForId(delegateRequest.getPrincipalId());
442                    if ("natjohns".equals(delNetId)) {
443                        foundNatjohnsDelegate = true;
444                    } else if ("shenl".equals(delNetId)) {
445                        foundShenlDelegate = true;
446                    }
447                }
448                assertTrue("Could not locate natjohns role delegate request.", foundNatjohnsDelegate);
449                assertTrue("Could not locate shenl role delegate request.", foundShenlDelegate);
450             }
451         }
452         assertTrue("Could not locate notification for jhopf.", foundJhopfNotification);
453         assertTrue("Could not locate notification for rkirkend.", foundRkirkendNotification);
454         assertTrue("Could not locate notification for bmcgough.", foundBmcgoughNotification);
455         assertTrue("Could not locate acknowledgment for xqi.", foundXqiAck);
456         assertTrue("Could not locate FYI for jthomas.", foundJthomasFYI);
457         assertTrue("Could not locate notification for jitrue.", foundJitrueNotification);
458     }
459     
460     /**
461      * Tests that we can blanket approve past mandatory route nodes.
462      * Addresses issue http://fms.dfa.cornell.edu:8080/browse/KULWF-461
463      */
464     @Test public void testBlanketApprovePastMandatoryNode() throws Exception {
465         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "BlanketApproveMandatoryNodeTest");
466         document.blanketApprove("");
467         assertTrue("Document should be processed.", document.isProcessed());
468     }
469     
470     /**
471      * Tests the behavior of blanket approve through a role node and then through a node with a Workgroup including
472      * the individual(s) in the role.  Verifies that the Action List contains the proper entries in this case.
473      */
474     @Test public void testBlanketApproveThroughRoleAndWorkgroup() throws Exception {
475     	String jitruePrincipalId = getPrincipalIdForName("jitrue");
476     	WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "BlanketApproveThroughRoleAndWorkgroupTest");
477     	document.saveDocument("");
478     	assertTrue(document.isSaved());
479     	TestUtilities.assertNotInActionList(jitruePrincipalId, document.getDocumentId());
480     	document.blanketApprove("");
481     	
482     	// document should now be processed
483     	document = WorkflowDocumentFactory.loadDocument(jitruePrincipalId, document.getDocumentId());
484     	assertTrue(document.isProcessed());
485     	assertTrue(document.isAcknowledgeRequested());
486     	
487     	// there should be 3 root acknowledge requests, one to the WorkflowAdmin workgroup, one to jitrue in the Notify role and one to jitrue in the Notify2 role
488     	List actionRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocId(document.getDocumentId());
489     	assertEquals("There should be 3 root requests.", 3, actionRequests.size());
490     	
491     	// now check that the document is in jitrue's action list
492     	TestUtilities.assertInActionList(jitruePrincipalId, document.getDocumentId());
493     	
494     	// acknowledge as a member of the workgroup who is not jitrue
495     	document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
496     	assertTrue(document.isAcknowledgeRequested());
497     	document.acknowledge("");
498     	
499     	// document should still be processed
500     	document = WorkflowDocumentFactory.loadDocument(jitruePrincipalId, document.getDocumentId());
501     	assertTrue(document.isProcessed());
502     	assertTrue(document.isAcknowledgeRequested());
503     	
504     	// there should now be 2 root acknowledge requests, one to jitrue in the Notify role and one to jitrue in the Notify2 role
505     	actionRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocId(document.getDocumentId());
506     	assertEquals("There should be 2 root requests.", 2, actionRequests.size());
507     	
508     	// jitrue should still have this in his action list
509     	TestUtilities.assertInActionList(jitruePrincipalId, document.getDocumentId());
510     	document.acknowledge("");
511     	
512     	// document should now be final
513     	assertTrue(document.isFinal());
514     }
515     
516     private RouteNodeService getRouteNodeService() {
517         return KEWServiceLocator.getRouteNodeService();
518     }
519     
520     private class SequentialSetup {
521 
522         public static final String DOCUMENT_TYPE_NAME = "BlanketApproveSequentialTest";
523         public static final String ADHOC_NODE = "AdHoc";
524         public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
525         public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
526         public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
527         public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
528         
529     }
530     
531     private class ParallelSetup {
532 
533         public static final String DOCUMENT_TYPE_NAME = "BlanketApproveParallelTest";
534         public static final String ADHOC_NODE = "AdHoc";
535         public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
536         public static final String WORKFLOW_DOCUMENT_2_B1_NODE = "WorkflowDocument2-B1";
537         public static final String WORKFLOW_DOCUMENT_2_B2_NODE = "WorkflowDocument2-B2";
538         public static final String WORKFLOW_DOCUMENT_3_B1_NODE = "WorkflowDocument3-B1";
539         public static final String WORKFLOW_DOCUMENT_3_B2_NODE = "WorkflowDocument3-B2";
540         public static final String WORKFLOW_DOCUMENT_4_B3_NODE = "WorkflowDocument4-B3";
541         public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
542         public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
543         public static final String JOIN_NODE = "Join";
544         public static final String SPLIT_NODE = "Split";
545         public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
546         
547     }
548     
549     /*private class CycleSetup {
550 
551         public static final String DOCUMENT_TYPE_NAME = "BlanketApproveCycleTest";
552         public static final String ADHOC_NODE = "AdHoc";
553         public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
554         public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
555         public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
556         public static final String JOIN_NODE = "Join";
557         public static final String CUSTOM_CYCLE_SPLIT_NODE = "CustomCycleSplit";
558         
559     }*/
560     
561     public static class NotifySetup {
562 
563         public static final String DOCUMENT_TYPE_NAME = "NotificationTest";
564         public static final String ADHOC_NODE = "AdHoc";
565         public static final String NOTIFY_FIRST_NODE = "NotifyFirst";
566         public static final String NOTIFY_LEFT_NODE = "NotifyLeftBranch";
567         public static final String NOTIFY_RIGHT_NODE = "NotifyRightBranch";
568         public static final String NOTIFY_FINAL_NODE = "NotifyFinal";
569         public static final String SPLIT_NODE = "Split";
570         public static final String JOIN_NODE = "Join";
571         
572     }
573 
574     private MockEmailNotificationService getMockEmailService() {
575         return (MockEmailNotificationService)KEWServiceLocator.getActionListEmailService();
576     }
577     
578 }