001    /**
002     * Copyright 2005-2011 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.", isAtWD4B3);
294            assertFalse("Should not be at join node.", isAtJoin);
295            
296            document.blanketApprove("");
297            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
298            assertTrue("Document should be processed.", document.isProcessed());
299            actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
300            assertEquals("Wrong number of pending action requests.", 10, actionRequests.size());
301        }
302        
303        @Test public void testBlanketApproveToJoin() throws Exception {
304            
305            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
306            document.blanketApprove("", ParallelSetup.JOIN_NODE);
307            assertTrue("Document should still be enroute.", document.isEnroute());
308    
309            // document should now be at the workflow document final node
310            Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
311            assertEquals("Wrong number of active nodes.", 1, activeNodes.size());
312            RouteNodeInstance nodeInstance = (RouteNodeInstance)activeNodes.iterator().next();
313            assertEquals("Document at wrong node.", ParallelSetup.WORKFLOW_DOCUMENT_FINAL_NODE, nodeInstance.getName());
314            
315            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("xqi"), document.getDocumentId());
316            assertTrue("Should have approve request.", document.isApprovalRequested());
317            document.blanketApprove("", ParallelSetup.ACKNOWLEDGE_1_NODE);
318            
319            activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
320            assertEquals("Wrong number of active nodes.", 0, activeNodes.size());
321            Collection terminalNodes = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
322            assertEquals("Wrong number of terminal nodes.", 1, terminalNodes.size());
323            nodeInstance = (RouteNodeInstance)terminalNodes.iterator().next();
324            assertEquals("Document at wrong node.", ParallelSetup.ACKNOWLEDGE_2_NODE, nodeInstance.getName());
325            assertTrue("Final node not complete.", nodeInstance.isComplete());
326        }
327        
328        @Test public void testBlanketApproveToAcknowledge() throws Exception {
329            
330            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
331            document.blanketApprove("", ParallelSetup.ACKNOWLEDGE_1_NODE);
332            assertTrue("Document should be processed.", document.isProcessed());
333    
334            // document should now be terminal
335            Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
336            assertEquals("Wrong number of active nodes.", 0, activeNodes.size());
337            Collection terminalNodes = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
338            assertEquals("Wrong number of terminal nodes.", 1, terminalNodes.size());
339            RouteNodeInstance nodeInstance = (RouteNodeInstance)terminalNodes.iterator().next();
340            assertEquals("Document at wrong node.", ParallelSetup.ACKNOWLEDGE_2_NODE, nodeInstance.getName());
341            assertTrue("Final node not complete.", nodeInstance.isComplete());
342        }
343        
344        @Test public void testBlanketApproveToMultipleNodesErrors() throws Exception {
345            
346            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
347            try {
348                document.blanketApprove("", new String[] { ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE, ParallelSetup.ACKNOWLEDGE_1_NODE });    
349                fail("document should have thrown exception");
350            } catch (Exception e) {
351                // Shouldn't be able to blanket approve past the join in conjunction with blanket approve within a branch
352                    TestUtilities.getExceptionThreader().join();
353                    document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
354                assertTrue("Document should be in exception routing.", document.isException());            
355            }
356        }
357        
358        /**
359         * Tests that the notifications are generated properly on a blanket approve.  Works against the "NotificationTest" document type.
360         */
361        @Test public void testBlanketApproveNotification() throws Exception {
362            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), NotifySetup.DOCUMENT_TYPE_NAME);
363            document.blanketApprove("");
364            ActionRequestService arService = KEWServiceLocator.getActionRequestService(); 
365            List actionRequests = arService.getRootRequests(arService.findPendingByDoc(document.getDocumentId()));
366            assertEquals("Should be 5 pending acknowledgements and 1 pending fyi", 6, actionRequests.size());
367            boolean foundJhopfNotification = false;
368            boolean foundRkirkendNotification = false;
369            boolean foundJitrueNotification = false;
370            boolean foundBmcgoughNotification = false;
371            boolean foundXqiAck = false;
372            boolean foundJthomasFYI = false;
373            for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
374                ActionRequestValue actionRequest = (ActionRequestValue) iterator.next();
375                RouteNodeInstance nodeInstance = actionRequest.getNodeInstance();
376                String netId = (actionRequest.getPrincipalId() == null ? null : getPrincipalNameForId(actionRequest.getPrincipalId()));
377                if ("jhopf".equals(netId)) {
378                    foundJhopfNotification = true;
379                    assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
380                    assertEquals(NotifySetup.NOTIFY_FIRST_NODE, nodeInstance.getName());
381                } else if ("rkirkend".equals(netId)) {
382                    foundRkirkendNotification = true;
383                    assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
384                    assertEquals(NotifySetup.NOTIFY_LEFT_NODE, nodeInstance.getName());
385                    assertEquals("Rkirkend should have three delegate acks.", 3, actionRequest.getChildrenRequests().size());
386                    assertTrue("Should be primary delegation.", actionRequest.isPrimaryDelegator());
387                    boolean foundTemayDelegate = false;
388                    boolean foundNonSITWGDelegate = false;
389                    boolean foundPmckownDelegate = false;
390                    for (Iterator iterator2 = actionRequest.getChildrenRequests().iterator(); iterator2.hasNext();) {
391                        ActionRequestValue childRequest = (ActionRequestValue) iterator2.next();
392                        assertTrue("Child request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
393                        String childId = (childRequest.isGroupRequest() ? childRequest.getGroup().getName(): getPrincipalNameForId(childRequest.getPrincipalId()));
394                        if ("temay".equals(childId)) {
395                            foundTemayDelegate = true;
396                            assertEquals("Should be primary delegation.", DelegationType.PRIMARY, childRequest.getDelegationType());
397                        } else if ("pmckown".equals(childId)) {
398                            foundPmckownDelegate = true;
399                            assertEquals("Should be secondary delegation.", DelegationType.SECONDARY, childRequest.getDelegationType());
400                        } else if ("NonSIT".equals(childId)) {
401                            foundNonSITWGDelegate = true;
402                            assertEquals("Should be primary delegation.", DelegationType.PRIMARY, childRequest.getDelegationType());
403                        }
404                    }
405                    assertTrue("Could not locate delegate request for temay.", foundTemayDelegate);
406                    assertTrue("Could not locate delegate request for NonSIT Group.", foundNonSITWGDelegate);
407                    assertTrue("Could not locate delegate request for pmckown.", foundPmckownDelegate);
408                } else if ("bmcgough".equals(netId)) {
409                    foundBmcgoughNotification = true;
410                    assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
411                    assertEquals(NotifySetup.NOTIFY_FINAL_NODE, nodeInstance.getName());
412                    
413                } else if ("xqi".equals(netId)) {
414                    foundXqiAck = true;
415                    assertTrue("Action request should be an acknowledge.", actionRequest.isAcknowledgeRequest());
416                    assertEquals(NotifySetup.NOTIFY_FINAL_NODE, nodeInstance.getName());
417                    
418                } else if ("jthomas".equals(netId)) {
419                    foundJthomasFYI = true;
420                    assertTrue("Action request should be an FYI.", actionRequest.isFYIRequest());
421                    assertEquals(NotifySetup.NOTIFY_FINAL_NODE, nodeInstance.getName());
422                } else if (actionRequest.isRoleRequest()) {
423                   List topLevelRequests = arService.getTopLevelRequests(actionRequest);
424                   assertEquals(1, topLevelRequests.size());
425                   actionRequest = (ActionRequestValue)topLevelRequests.get(0);
426                   // this tests the notofication of the role to jitrue with delegates
427                   assertEquals("Should be to jitrue.", "jitrue", getPrincipalNameForId(actionRequest.getPrincipalId()));
428                   foundJitrueNotification = true;
429                   List delegateRoleRequests = arService.getDelegateRequests(actionRequest);
430                   assertEquals("Should be 1 delegate role requests", 1, delegateRoleRequests.size());
431                   ActionRequestValue delegateRoleRequest = (ActionRequestValue)delegateRoleRequests.get(0);
432                   assertEquals("Should be NotifyDelegate role", "NotifyDelegate", delegateRoleRequest.getRoleName());
433                   assertEquals("Should be secondary delegation", DelegationType.SECONDARY, delegateRoleRequest.getDelegationType());
434                   List delegateRequests = arService.getTopLevelRequests(delegateRoleRequest);
435                   assertEquals("Should be 2 delegate requests", 2, delegateRequests.size());
436                   boolean foundNatjohnsDelegate = false;
437                   boolean foundShenlDelegate = false;
438                   for (Iterator iterator2 = delegateRequests.iterator(); iterator2.hasNext();) {
439                       ActionRequestValue delegateRequest = (ActionRequestValue) iterator2.next();
440                       String delNetId = getPrincipalNameForId(delegateRequest.getPrincipalId());
441                       if ("natjohns".equals(delNetId)) {
442                           foundNatjohnsDelegate = true;
443                       } else if ("shenl".equals(delNetId)) {
444                           foundShenlDelegate = true;
445                       }
446                   }
447                   assertTrue("Could not locate natjohns role delegate request.", foundNatjohnsDelegate);
448                   assertTrue("Could not locate shenl role delegate request.", foundShenlDelegate);
449                }
450            }
451            assertTrue("Could not locate notification for jhopf.", foundJhopfNotification);
452            assertTrue("Could not locate notification for rkirkend.", foundRkirkendNotification);
453            assertTrue("Could not locate notification for bmcgough.", foundBmcgoughNotification);
454            assertTrue("Could not locate acknowledgment for xqi.", foundXqiAck);
455            assertTrue("Could not locate FYI for jthomas.", foundJthomasFYI);
456            assertTrue("Could not locate notification for jitrue.", foundJitrueNotification);
457        }
458        
459        /**
460         * Tests that we can blanket approve past mandatory route nodes.
461         * Addresses issue http://fms.dfa.cornell.edu:8080/browse/KULWF-461
462         */
463        @Test public void testBlanketApprovePastMandatoryNode() throws Exception {
464            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "BlanketApproveMandatoryNodeTest");
465            document.blanketApprove("");
466            assertTrue("Document should be processed.", document.isProcessed());
467        }
468        
469        /**
470         * Tests the behavior of blanket approve through a role node and then through a node with a Workgroup including
471         * the individual(s) in the role.  Verifies that the Action List contains the proper entries in this case.
472         */
473        @Test public void testBlanketApproveThroughRoleAndWorkgroup() throws Exception {
474            String jitruePrincipalId = getPrincipalIdForName("jitrue");
475            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "BlanketApproveThroughRoleAndWorkgroupTest");
476            document.saveDocument("");
477            assertTrue(document.isSaved());
478            TestUtilities.assertNotInActionList(jitruePrincipalId, document.getDocumentId());
479            document.blanketApprove("");
480            
481            // document should now be processed
482            document = WorkflowDocumentFactory.loadDocument(jitruePrincipalId, document.getDocumentId());
483            assertTrue(document.isProcessed());
484            assertTrue(document.isAcknowledgeRequested());
485            
486            // 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
487            List actionRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocId(document.getDocumentId());
488            assertEquals("There should be 3 root requests.", 3, actionRequests.size());
489            
490            // now check that the document is in jitrue's action list
491            TestUtilities.assertInActionList(jitruePrincipalId, document.getDocumentId());
492            
493            // acknowledge as a member of the workgroup who is not jitrue
494            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
495            assertTrue(document.isAcknowledgeRequested());
496            document.acknowledge("");
497            
498            // document should still be processed
499            document = WorkflowDocumentFactory.loadDocument(jitruePrincipalId, document.getDocumentId());
500            assertTrue(document.isProcessed());
501            assertTrue(document.isAcknowledgeRequested());
502            
503            // there should now be 2 root acknowledge requests, one to jitrue in the Notify role and one to jitrue in the Notify2 role
504            actionRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocId(document.getDocumentId());
505            assertEquals("There should be 2 root requests.", 2, actionRequests.size());
506            
507            // jitrue should still have this in his action list
508            TestUtilities.assertInActionList(jitruePrincipalId, document.getDocumentId());
509            document.acknowledge("");
510            
511            // document should now be final
512            assertTrue(document.isFinal());
513        }
514        
515        private RouteNodeService getRouteNodeService() {
516            return KEWServiceLocator.getRouteNodeService();
517        }
518        
519        private class SequentialSetup {
520    
521            public static final String DOCUMENT_TYPE_NAME = "BlanketApproveSequentialTest";
522            public static final String ADHOC_NODE = "AdHoc";
523            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
524            public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
525            public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
526            public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
527            
528        }
529        
530        private class ParallelSetup {
531    
532            public static final String DOCUMENT_TYPE_NAME = "BlanketApproveParallelTest";
533            public static final String ADHOC_NODE = "AdHoc";
534            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
535            public static final String WORKFLOW_DOCUMENT_2_B1_NODE = "WorkflowDocument2-B1";
536            public static final String WORKFLOW_DOCUMENT_2_B2_NODE = "WorkflowDocument2-B2";
537            public static final String WORKFLOW_DOCUMENT_3_B1_NODE = "WorkflowDocument3-B1";
538            public static final String WORKFLOW_DOCUMENT_3_B2_NODE = "WorkflowDocument3-B2";
539            public static final String WORKFLOW_DOCUMENT_4_B3_NODE = "WorkflowDocument4-B3";
540            public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
541            public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
542            public static final String JOIN_NODE = "Join";
543            public static final String SPLIT_NODE = "Split";
544            public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
545            
546        }
547        
548        /*private class CycleSetup {
549    
550            public static final String DOCUMENT_TYPE_NAME = "BlanketApproveCycleTest";
551            public static final String ADHOC_NODE = "AdHoc";
552            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
553            public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
554            public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
555            public static final String JOIN_NODE = "Join";
556            public static final String CUSTOM_CYCLE_SPLIT_NODE = "CustomCycleSplit";
557            
558        }*/
559        
560        public static class NotifySetup {
561    
562            public static final String DOCUMENT_TYPE_NAME = "NotificationTest";
563            public static final String ADHOC_NODE = "AdHoc";
564            public static final String NOTIFY_FIRST_NODE = "NotifyFirst";
565            public static final String NOTIFY_LEFT_NODE = "NotifyLeftBranch";
566            public static final String NOTIFY_RIGHT_NODE = "NotifyRightBranch";
567            public static final String NOTIFY_FINAL_NODE = "NotifyFinal";
568            public static final String SPLIT_NODE = "Split";
569            public static final String JOIN_NODE = "Join";
570            
571        }
572    
573        private MockEmailNotificationService getMockEmailService() {
574            return (MockEmailNotificationService)KEWServiceLocator.getActionListEmailService();
575        }
576        
577    }