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 */
016package org.kuali.rice.kew.actions;
017
018
019import static org.junit.Assert.assertEquals;
020import static org.junit.Assert.assertFalse;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertTrue;
023import static org.junit.Assert.fail;
024
025import java.util.Collection;
026import java.util.Iterator;
027import java.util.List;
028
029import mocks.MockEmailNotificationService;
030
031import org.junit.Test;
032import org.kuali.rice.core.api.delegation.DelegationType;
033import org.kuali.rice.kew.actionrequest.ActionRequestValue;
034import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
035import org.kuali.rice.kew.api.WorkflowDocument;
036import org.kuali.rice.kew.api.WorkflowDocumentFactory;
037import org.kuali.rice.kew.api.action.InvalidActionTakenException;
038import org.kuali.rice.kew.engine.node.RouteNodeInstance;
039import org.kuali.rice.kew.engine.node.service.RouteNodeService;
040import org.kuali.rice.kew.service.KEWServiceLocator;
041import org.kuali.rice.kew.test.KEWTestCase;
042import org.kuali.rice.kew.test.TestUtilities;
043import org.kuali.rice.kew.api.KewApiConstants;
044import org.kuali.rice.test.BaselineTestCase.BaselineMode;
045import org.kuali.rice.test.BaselineTestCase.Mode;
046
047@BaselineMode(Mode.CLEAR_DB)
048public 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}