001    /*
002     * Copyright 2005-2007 The Kuali Foundation
003     * 
004     * 
005     * Licensed under the Educational Community License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     * 
009     * http://www.opensource.org/licenses/ecl2.php
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.kuali.rice.kew.actions;
018    
019    
020    import static org.junit.Assert.assertEquals;
021    import static org.junit.Assert.assertFalse;
022    import static org.junit.Assert.assertNotNull;
023    import static org.junit.Assert.assertTrue;
024    import static org.junit.Assert.fail;
025    
026    import java.util.Collection;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    import mocks.MockEmailNotificationService;
031    
032    import org.junit.Test;
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.DelegationType;
038    import org.kuali.rice.kew.api.action.InvalidActionTakenException;
039    import org.kuali.rice.kew.engine.node.RouteNodeInstance;
040    import org.kuali.rice.kew.engine.node.service.RouteNodeService;
041    import org.kuali.rice.kew.service.KEWServiceLocator;
042    import org.kuali.rice.kew.test.KEWTestCase;
043    import org.kuali.rice.kew.test.TestUtilities;
044    import org.kuali.rice.kew.util.KEWConstants;
045    import org.kuali.rice.test.BaselineTestCase.BaselineMode;
046    import org.kuali.rice.test.BaselineTestCase.Mode;
047    
048    @BaselineMode(Mode.CLEAR_DB)
049    public class BlanketApproveTest extends KEWTestCase {
050    
051            @Override
052        protected void loadTestData() throws Exception {
053            loadXmlFile("ActionsConfig.xml");
054        }
055        
056        /**
057         * When a user is not in the blanket approver workgroup an exception should be thrown and 
058         * it should have a good message.
059         * 
060         * @throws Exception
061         */
062        @Test public void testBlanketApproverNotInBlanketApproverWorkgroup() throws Exception  {
063            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
064            try {
065                    document.blanketApprove("");
066                    fail("InvalidActionTakenException should have been thrown");
067            } catch (InvalidActionTakenException iate) {
068                    assertEquals("Exception on message is incorrent", "User is not authorized to BlanketApprove document", iate.getMessage());
069            }
070            
071        }
072        
073        /**
074         * When a user is in the blanket approve workgroup but the user is not the initiator an exception
075         * should be thrown.
076         */
077        @Test public void testBlanketApproverNotInitiator() throws Exception  {
078            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
079            WorkflowDocument newDocument = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
080            try {
081                newDocument.blanketApprove("");
082                fail("Exception should have been thrown when non-initiator user attempts blanket approve on default blanket approve policy document");
083            } catch (Exception e) {
084                e.printStackTrace();
085            }
086        }
087        
088        @SuppressWarnings("deprecation")
089            @Test public void testBlanketApproveSequential() throws Exception {
090            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
091            document.blanketApprove("");
092            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
093            assertTrue("Document should be processed.", document.isProcessed());
094            Collection nodeInstances = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
095            // once the document is processed there are no active nodes
096            assertEquals("Wrong number of active nodes.", 0, nodeInstances.size());
097            nodeInstances = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
098            assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
099            RouteNodeInstance ackNodeInstance = (RouteNodeInstance)nodeInstances.iterator().next();
100            assertEquals("At wrong node.", SequentialSetup.ACKNOWLEDGE_2_NODE, ackNodeInstance.getRouteNode().getRouteNodeName());
101            assertTrue("Node should be complete.", ackNodeInstance.isComplete());
102            List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
103            assertEquals("Wrong number of pending action requests.", 5, actionRequests.size());
104            boolean isNotification1 = false;
105            boolean isNotification2 = false;
106            boolean isNotification3 = false;
107            boolean isAck1 = false;
108            boolean isAck2 = false;
109            for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
110                ActionRequestValue actionRequest = (ActionRequestValue) iterator.next();
111                assertEquals("Should only be acknowledges.", KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, actionRequest.getActionRequested());
112                RouteNodeInstance nodeInstance = actionRequest.getNodeInstance();
113                assertNotNull(nodeInstance);
114                String nodeName = nodeInstance.getRouteNode().getRouteNodeName();
115                if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("bmcgough"))) {
116                    isNotification1 = true;
117                    assertEquals(SequentialSetup.WORKFLOW_DOCUMENT_NODE, nodeName);
118                    assertEquals(KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, actionRequest.getResponsibilityId());
119                } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("rkirkend"))) {
120                    isNotification2 = true;
121                    assertEquals(SequentialSetup.WORKFLOW_DOCUMENT_NODE, nodeName);
122                    assertEquals(KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, actionRequest.getResponsibilityId());
123                } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("pmckown"))) {
124                    isNotification3 = true;
125                    assertEquals(SequentialSetup.WORKFLOW_DOCUMENT_2_NODE, nodeName);
126                    assertEquals(KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, actionRequest.getResponsibilityId());
127                } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("temay"))) {
128                    isAck1 = true;
129                    assertEquals(SequentialSetup.ACKNOWLEDGE_1_NODE, nodeName);
130                    assertFalse(KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID.equals(actionRequest.getResponsibilityId()));
131                } else if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("jhopf"))) {
132                    isAck2 = true;
133                    assertEquals(SequentialSetup.ACKNOWLEDGE_2_NODE, nodeName);
134                    assertFalse(KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID.equals(actionRequest.getResponsibilityId()));
135                }
136            }
137            assertTrue(isNotification1);
138            assertTrue(isNotification2);
139            assertTrue(isNotification3);
140            assertTrue(isAck1);
141            assertTrue(isAck2);
142            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
143            assertTrue(document.isProcessed());
144            assertTrue(document.isAcknowledgeRequested());
145            assertEquals("bmcgough should not have been sent an approve email", 0, getMockEmailService().immediateReminderEmailsSent("bmcgough", document.getDocumentId(), KEWConstants.ACTION_REQUEST_APPROVE_REQ));
146            assertEquals("bmcgough should not have been sent an ack email", 1, getMockEmailService().immediateReminderEmailsSent("bmcgough", document.getDocumentId(), KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
147            document.acknowledge("");
148    
149            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
150            assertTrue(document.isProcessed());
151            assertTrue(document.isAcknowledgeRequested());
152            assertEquals("rkirkend should not have been sent an approve email", 0, getMockEmailService().immediateReminderEmailsSent("rkirkend", document.getDocumentId(), KEWConstants.ACTION_REQUEST_APPROVE_REQ));        
153            assertEquals("rkirkend should not have been sent an ack email", 1, getMockEmailService().immediateReminderEmailsSent("rkirkend", document.getDocumentId(), KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
154            document.acknowledge("");
155            
156            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("pmckown"), document.getDocumentId());
157            assertTrue(document.isProcessed());
158            assertTrue(document.isAcknowledgeRequested());
159            assertEquals("pmckown should not have been sent an approve email", 0, getMockEmailService().immediateReminderEmailsSent("pmckown", document.getDocumentId(), KEWConstants.ACTION_REQUEST_APPROVE_REQ));
160            assertEquals("pmckown should not have been sent an ack email", 1, getMockEmailService().immediateReminderEmailsSent("pmckown", document.getDocumentId(), KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
161            document.acknowledge("");
162            
163            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("temay"), document.getDocumentId());
164            assertTrue(document.isProcessed());
165            assertTrue(document.isAcknowledgeRequested());
166            assertEquals("rkirkend should have been sent an temay", 1, getMockEmailService().immediateReminderEmailsSent("temay", document.getDocumentId(), KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));        
167            document.acknowledge("");
168            
169            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId());
170            assertTrue(document.isProcessed());
171            assertTrue(document.isAcknowledgeRequested());
172            assertEquals("rkirkend should have been sent an jhopf", 1, getMockEmailService().immediateReminderEmailsSent("jhopf", document.getDocumentId(), KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ));
173            document.acknowledge("");
174            
175            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
176            assertTrue(document.isFinal());
177            
178            document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
179            document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_2_NODE);
180            assertTrue("Document should be enroute.", document.isEnroute());
181            nodeInstances = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
182            assertEquals("Should be one active node.", 1, nodeInstances.size());
183            RouteNodeInstance doc2Instance = (RouteNodeInstance)nodeInstances.iterator().next();
184            assertEquals("At wrong node.", SequentialSetup.WORKFLOW_DOCUMENT_2_NODE, doc2Instance.getRouteNode().getRouteNodeName());
185            
186        }
187        
188        @Test public void testBlanketApproveSequentialErrors() throws Exception {
189            // blanket approve to invalid node
190            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
191            try {
192                document.blanketApprove("", "TotallyInvalidNode");
193                fail("Should have thrown exception");
194            } catch (Exception e) {}
195            
196            // blanket approve backwards
197            document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
198            document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_2_NODE);
199            try {
200                document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_NODE);
201                fail("Should have thrown exception");
202            } catch (Exception e) {}
203            
204            // blanket approve to current node
205            document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SequentialSetup.DOCUMENT_TYPE_NAME);
206            document.route("");
207            try {
208                document.blanketApprove("", SequentialSetup.WORKFLOW_DOCUMENT_NODE);
209                fail("Should have thrown exception");
210            } catch (Exception e) {}
211            
212            // blanket approve as user not in the blanket approve workgroup
213            document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SequentialSetup.DOCUMENT_TYPE_NAME);
214            try {
215                document.blanketApprove("");
216                fail("Shouldn't be able to blanket approve if not in blanket approve workgroup");
217            } catch (Exception e) {}
218        }
219        
220        @Test public void testBlanketApproveParallel() throws Exception {
221            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
222            document.blanketApprove("");        
223            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
224            assertTrue("Document should be processed.", document.isProcessed());
225            Collection nodeInstances = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
226            // once the document has gone processed there are no active nodes
227            assertEquals("Wrong number of active nodes.", 0, nodeInstances.size());
228            nodeInstances = getRouteNodeService().getTerminalNodeInstances(document.getDocumentId());
229            assertEquals("Wrong number of terminal nodes.", 1, nodeInstances.size());
230            RouteNodeInstance ackNodeInstance = (RouteNodeInstance)nodeInstances.iterator().next();
231            assertEquals("At wrong node.", SequentialSetup.ACKNOWLEDGE_2_NODE, ackNodeInstance.getRouteNode().getRouteNodeName());
232            assertTrue("Node should be complete.", ackNodeInstance.isComplete());
233            List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
234            assertEquals("Wrong number of pending action requests.", 10, actionRequests.size());
235    
236        }
237        
238        @Test public void testBlanketApproveIntoBranch() throws Exception {
239            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
240            document.blanketApprove("", ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE);
241            List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
242            assertEquals("Wrong number of pending action requests.", 5, actionRequests.size());
243            
244            // document should now be at the node we blanket approved to and the join node
245            Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
246            assertEquals("Wrong number of active nodes.", 3, activeNodes.size());
247            boolean isAtWD2B1 = false;
248            boolean isAtJoin = false;
249            boolean isAtWD3B2 = false;
250            boolean isAtWD4B3 = false;
251            for (Iterator iterator = activeNodes.iterator(); iterator.hasNext();) {
252                RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next();
253                isAtWD2B1 = isAtWD2B1 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE);
254                isAtWD3B2 = isAtWD3B2 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_3_B2_NODE);
255                isAtWD4B3 = isAtWD4B3 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE);
256                isAtJoin = isAtJoin || nodeInstance.getName().equals(ParallelSetup.JOIN_NODE);
257            }
258            assertTrue("Should be at blanket approved node.", isAtWD2B1);
259            assertTrue("Should be at blanket approved node WD3B2.", isAtWD3B2);
260            assertTrue("Should be at blanket approved node WD4B3.", isAtWD4B3);        
261            assertFalse("Should be at join node.", isAtJoin);
262            
263            document.blanketApprove("");
264            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), document.getDocumentId());
265            assertTrue("Document should be processed.", document.isProcessed());
266            actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
267            
268            assertEquals("Wrong number of pending action requests.", 10, actionRequests.size());
269        }
270        
271        @Test public void testBlanketApproveToMultipleNodes() throws Exception {
272            
273            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
274            document.blanketApprove("", new String[] { ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE, ParallelSetup.WORKFLOW_DOCUMENT_3_B2_NODE });
275            List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
276            assertEquals("Wrong number of pending action requests.", 5, actionRequests.size());
277            
278            // document should now be at both nodes we blanket approved to and the join node
279            Collection activeNodes = getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
280            assertEquals("Wrong number of active nodes.", 3, activeNodes.size());
281            boolean isAtWD2B1 = false;
282            boolean isAtWD3B2 = false;
283            boolean isAtJoin = false;
284            boolean isAtWD4B3 = false;
285            for (Iterator iterator = activeNodes.iterator(); iterator.hasNext();) {
286                RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next();
287                isAtWD2B1 = isAtWD2B1 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE);
288                isAtWD3B2 = isAtWD3B2 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_3_B2_NODE);
289                isAtWD4B3 = isAtWD4B3 || nodeInstance.getName().equals(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE);
290                isAtJoin = isAtJoin || nodeInstance.getName().equals(ParallelSetup.JOIN_NODE);
291            }
292            assertTrue("Should be at blanket approved node WD2B1.", isAtWD2B1);
293            assertTrue("Should be at blanket approved node WD3B2.", isAtWD3B2);
294            assertTrue("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.getCode(), childRequest.getDelegationType());
398                        } else if ("pmckown".equals(childId)) {
399                            foundPmckownDelegate = true;
400                            assertEquals("Should be secondary delegation.", DelegationType.SECONDARY.getCode(), childRequest.getDelegationType());
401                        } else if ("NonSIT".equals(childId)) {
402                            foundNonSITWGDelegate = true;
403                            assertEquals("Should be primary delegation.", DelegationType.PRIMARY.getCode(), 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.getCode(), 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    }