001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kew.actions;
017    
018    
019    import static org.junit.Assert.assertEquals;
020    import static org.junit.Assert.assertFalse;
021    import static org.junit.Assert.assertNotNull;
022    import static org.junit.Assert.assertTrue;
023    import static org.junit.Assert.fail;
024    
025    import java.util.Collection;
026    import java.util.Iterator;
027    import java.util.List;
028    
029    import mocks.MockEmailNotificationService;
030    
031    import org.junit.Test;
032    import org.kuali.rice.core.api.delegation.DelegationType;
033    import org.kuali.rice.kew.actionrequest.ActionRequestValue;
034    import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
035    import org.kuali.rice.kew.api.WorkflowDocument;
036    import org.kuali.rice.kew.api.WorkflowDocumentFactory;
037    import org.kuali.rice.kew.api.action.InvalidActionTakenException;
038    import org.kuali.rice.kew.engine.node.RouteNodeInstance;
039    import org.kuali.rice.kew.engine.node.service.RouteNodeService;
040    import org.kuali.rice.kew.service.KEWServiceLocator;
041    import org.kuali.rice.kew.test.KEWTestCase;
042    import org.kuali.rice.kew.test.TestUtilities;
043    import org.kuali.rice.kew.api.KewApiConstants;
044    import org.kuali.rice.test.BaselineTestCase.BaselineMode;
045    import org.kuali.rice.test.BaselineTestCase.Mode;
046    
047    @BaselineMode(Mode.CLEAR_DB)
048    public class BlanketApproveTest extends KEWTestCase {
049    
050            @Override
051        protected void loadTestData() throws Exception {
052            loadXmlFile("ActionsConfig.xml");
053        }
054        
055        /**
056         * When a user is not in the blanket approver workgroup an exception should be thrown and 
057         * it should have a good message.
058         * 
059         * @throws Exception
060         */
061        @Test public void testBlanketApproverNotInBlanketApproverWorkgroup() throws Exception  {
062            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
063            try {
064                    document.blanketApprove("");
065                    fail("InvalidActionTakenException should have been thrown");
066            } catch (InvalidActionTakenException iate) {
067                    assertEquals("Exception on message is incorrent", "User is not authorized to BlanketApprove document", iate.getMessage());
068            }
069            
070        }
071        
072        /**
073         * When a user is in the blanket approve workgroup but the user is not the initiator an exception
074         * should be thrown.
075         */
076        @Test public void testBlanketApproverNotInitiator() throws Exception  {
077            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
078            WorkflowDocument newDocument = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
079            try {
080                newDocument.blanketApprove("");
081                fail("Exception should have been thrown when non-initiator user attempts blanket approve on default blanket approve policy document");
082            } catch (Exception e) {
083                e.printStackTrace();
084            }
085        }
086        
087        @SuppressWarnings("deprecation")
088            @Test public void testBlanketApproveSequential() throws Exception {
089            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
090            document.blanketApprove("");
091            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
092            assertTrue("Document should be processed.", document.isProcessed());
093            Collection nodeInstances = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
094            // once the document is processed there are no active nodes
095            assertEquals("Wrong number of active nodes.", 0, nodeInstances.size());
096            nodeInstances = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
097            assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
098            RouteNodeInstance ackNodeInstance = (RouteNodeInstance)nodeInstances.iterator().next();
099            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    
481            document.blanketApprove("");
482            
483            // document should now be processed
484            document = WorkflowDocumentFactory.loadDocument(jitruePrincipalId, document.getDocumentId());
485            assertTrue(document.isProcessed());
486            assertTrue(document.isAcknowledgeRequested());
487            
488            // 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
489            List actionRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocId(document.getDocumentId());
490            assertEquals("There should be 3 root requests.", 3, actionRequests.size());
491            
492            // now check that the document is in jitrue's action list
493            TestUtilities.assertInActionList(jitruePrincipalId, document.getDocumentId());
494            
495            // acknowledge as a member of the workgroup who is not jitrue
496            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
497            assertTrue(document.isAcknowledgeRequested());
498            document.acknowledge("");
499            
500            // document should still be processed
501            document = WorkflowDocumentFactory.loadDocument(jitruePrincipalId, document.getDocumentId());
502            assertTrue(document.isProcessed());
503            assertTrue(document.isAcknowledgeRequested());
504            
505            // there should now be 2 root acknowledge requests, one to jitrue in the Notify role and one to jitrue in the Notify2 role
506            actionRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocId(document.getDocumentId());
507            assertEquals("There should be 2 root requests.", 2, actionRequests.size());
508            
509            // jitrue should still have this in his action list
510            TestUtilities.assertInActionList(jitruePrincipalId, document.getDocumentId());
511            document.acknowledge("");
512            
513            // document should now be final
514            assertTrue(document.isFinal());
515        }
516        
517        private RouteNodeService getRouteNodeService() {
518            return KEWServiceLocator.getRouteNodeService();
519        }
520        
521        private class SequentialSetup {
522    
523            public static final String DOCUMENT_TYPE_NAME = "BlanketApproveSequentialTest";
524            public static final String ADHOC_NODE = "AdHoc";
525            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
526            public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
527            public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
528            public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
529            
530        }
531        
532        private class ParallelSetup {
533    
534            public static final String DOCUMENT_TYPE_NAME = "BlanketApproveParallelTest";
535            public static final String ADHOC_NODE = "AdHoc";
536            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
537            public static final String WORKFLOW_DOCUMENT_2_B1_NODE = "WorkflowDocument2-B1";
538            public static final String WORKFLOW_DOCUMENT_2_B2_NODE = "WorkflowDocument2-B2";
539            public static final String WORKFLOW_DOCUMENT_3_B1_NODE = "WorkflowDocument3-B1";
540            public static final String WORKFLOW_DOCUMENT_3_B2_NODE = "WorkflowDocument3-B2";
541            public static final String WORKFLOW_DOCUMENT_4_B3_NODE = "WorkflowDocument4-B3";
542            public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
543            public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
544            public static final String JOIN_NODE = "Join";
545            public static final String SPLIT_NODE = "Split";
546            public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
547            
548        }
549        
550        /*private class CycleSetup {
551    
552            public static final String DOCUMENT_TYPE_NAME = "BlanketApproveCycleTest";
553            public static final String ADHOC_NODE = "AdHoc";
554            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
555            public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
556            public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
557            public static final String JOIN_NODE = "Join";
558            public static final String CUSTOM_CYCLE_SPLIT_NODE = "CustomCycleSplit";
559            
560        }*/
561        
562        public static class NotifySetup {
563    
564            public static final String DOCUMENT_TYPE_NAME = "NotificationTest";
565            public static final String ADHOC_NODE = "AdHoc";
566            public static final String NOTIFY_FIRST_NODE = "NotifyFirst";
567            public static final String NOTIFY_LEFT_NODE = "NotifyLeftBranch";
568            public static final String NOTIFY_RIGHT_NODE = "NotifyRightBranch";
569            public static final String NOTIFY_FINAL_NODE = "NotifyFinal";
570            public static final String SPLIT_NODE = "Split";
571            public static final String JOIN_NODE = "Join";
572            
573        }
574    
575        private MockEmailNotificationService getMockEmailService() {
576            return (MockEmailNotificationService)KEWServiceLocator.getActionListEmailService();
577        }
578        
579    }