View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.impl.peopleflow;
17  
18  import org.junit.Before;
19  import org.junit.Test;
20  import org.kuali.rice.core.api.delegation.DelegationType;
21  import org.kuali.rice.core.api.membership.MemberType;
22  import org.kuali.rice.kew.api.KewApiServiceLocator;
23  import org.kuali.rice.kew.api.WorkflowDocument;
24  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
25  import org.kuali.rice.kew.api.action.ActionRequest;
26  import org.kuali.rice.kew.api.action.ActionRequestPolicy;
27  import org.kuali.rice.kew.api.action.ActionRequestStatus;
28  import org.kuali.rice.kew.api.action.RecipientType;
29  import org.kuali.rice.kew.api.peopleflow.PeopleFlowDefinition;
30  import org.kuali.rice.kew.api.peopleflow.PeopleFlowDelegate;
31  import org.kuali.rice.kew.api.peopleflow.PeopleFlowMember;
32  import org.kuali.rice.kew.api.peopleflow.PeopleFlowService;
33  import org.kuali.rice.kew.test.KEWTestCase;
34  import org.kuali.rice.kim.api.role.Role;
35  import org.kuali.rice.kim.api.role.RoleService;
36  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
37  import org.kuali.rice.test.BaselineTestCase;
38  
39  import java.util.Collections;
40  import java.util.HashMap;
41  import java.util.List;
42  
43  import static org.junit.Assert.*;
44  
45  /**
46   * An integration test which tests document types with nodes on them which route to PeopleFlows in various configurations.
47   *
48   * @author Kuali Rice Team (rice.collab@kuali.org)
49   */
50  @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.CLEAR_DB)
51  public class PeopleFlowRoutingTest extends KEWTestCase {
52  
53      private static final String NAMESPACE_CODE = "TEST";
54      private static final String PEOPLE_FLOW_1 = "PeopleFlow1";
55      private static final String PEOPLE_FLOW_2 = "PeopleFlow2";
56      private static final String PEOPLE_FLOW_3 = "PeopleFlow3";
57  
58      private static final String SINGLE_PEOPLE_FLOW_PARALLEL_APPROVE = "SinglePeopleFlow-Parallel-Approve";
59      private static final String SINGLE_PEOPLE_FLOW_SEQUENTIAL_APPROVE = "SinglePeopleFlow-Sequential-Approve";
60      private static final String SINGLE_PEOPLE_FLOW_PRIORITY_PARALLEL_APPROVE = "SinglePeopleFlow-PriorityParallel-Approve";
61      private static final String MULTIPLE_PEOPLE_FLOW_PRIORITY_PARALLEL = "MultiplePeopleFlow-PriorityParallel";
62      private static final String DELEGATE_PEOPLE_FLOW_PRIORITY_PARALLEL_APPROVE = "DelegatePeopleFlow-PriorityParallel-Approve";
63  
64      private PeopleFlowService peopleFlowService;
65  
66      private String user1;
67      private String user2;
68      private String user3;
69      private String testuser1;
70      private String testuser2;
71      private String testuser3;
72      private String ewestfal;
73      private String testWorkgroup;
74  
75      protected void loadTestData() throws Exception {
76          loadXmlFile("PeopleFlowRoutingTest.xml");
77      }
78  
79      @Before
80      public void setupServiceUnderTest() {
81          setPeopleFlowService(KewApiServiceLocator.getPeopleFlowService());
82  
83          // setup principal and group ids
84          user1 = getPrincipalIdForName("user1");
85          user2 = getPrincipalIdForName("user2");
86          user3 = getPrincipalIdForName("user3");
87          testuser1 = getPrincipalIdForName("testuser1");
88          testuser2 = getPrincipalIdForName("testuser2");
89          testuser3 = getPrincipalIdForName("testuser3");
90          ewestfal = getPrincipalIdForName("ewestfal");
91          testWorkgroup = getGroupIdForName("KR-WKFLW", "TestWorkgroup");
92      }
93  
94      protected void setPeopleFlowService(PeopleFlowService peopleFlowService) {
95          this.peopleFlowService = peopleFlowService;
96      }
97  
98      protected PeopleFlowService getPeopleFlowService() {
99          return peopleFlowService;
100     }
101 
102     /**
103      * Defines a PeopleFlow as follows:
104      *
105      * <pre>
106      *
107      * Priority 1:
108      *   -> user1
109      * Priority 2:
110      *   -> user2
111      * Priority 3:
112      *   -> TestWorkgroup
113      *
114      * </pre>
115      */
116     private void createSimplePeopleFlow() {
117         PeopleFlowDefinition.Builder peopleFlow = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_1);
118         peopleFlow.addPrincipal(user1).setPriority(1);
119         peopleFlow.addPrincipal(user2).setPriority(2);
120         peopleFlow.addGroup(testWorkgroup).setPriority(3);
121         peopleFlowService.createPeopleFlow(peopleFlow.build());
122     }
123 
124     @Test
125     public void test_SinglePeopleFlow_Parallel_Approve() throws Exception {
126         createSimplePeopleFlow();
127 
128         // now route a document to it
129         WorkflowDocument document = WorkflowDocumentFactory.createDocument(user3, SINGLE_PEOPLE_FLOW_PARALLEL_APPROVE);
130         document.route("");
131         assertTrue("Document should be enroute.", document.isEnroute());
132 
133         // user3 should not have an approval request since they initiated the document
134         document.switchPrincipal(user3);
135 
136         // user1, user2, and TestWorkgroup (of which ewestfal is a member) should have the request
137         assertApproveRequested(document, user1, user2, ewestfal);
138 
139         // now approve as each, the document should be FINAL at the end
140         document.switchPrincipal(ewestfal);
141         document.approve("approving as ewestfal");
142         assertTrue("Document should still be enroute.", document.isEnroute());
143         document.switchPrincipal(user1);
144         document.approve("approving as user1");
145         assertTrue("Document should still be enroute.", document.isEnroute());
146         document.switchPrincipal(user2);
147         document.approve("approving as user2");
148         assertTrue("Document should now be FINAL.", document.isFinal());
149     }
150 
151     @Test
152     public void test_SinglePeopleFlow_Sequential_Approve() throws Exception {
153         createSimplePeopleFlow();
154 
155         // now route a document to it
156         WorkflowDocument document = WorkflowDocumentFactory.createDocument(user3, SINGLE_PEOPLE_FLOW_SEQUENTIAL_APPROVE);
157         document.route("");
158         assertTrue("Document should be enroute.", document.isEnroute());
159 
160         // user3 should not have an approval request since they initiated the document
161         document.switchPrincipal(user3);
162 
163         // document should be routed to user1, user2, and TestWorkgroup (of which "ewestfal" is a member) but only
164         // user1 request should be activated
165 
166         List<ActionRequest> rootActionRequests = document.getRootActionRequests();
167         assertEquals("Should have 3 root action requests", 3, rootActionRequests.size());
168         ActionRequest user1Request = null;
169         ActionRequest user2Request = null;
170         ActionRequest testWorkgroupRequest = null;
171         for (ActionRequest actionRequest : rootActionRequests) {
172             RecipientType recipientType = actionRequest.getRecipientType();
173             if (recipientType == RecipientType.PRINCIPAL) {
174                 if (user1.equals(actionRequest.getPrincipalId())) {
175                     user1Request = actionRequest;
176                 } else if (user2.equals(actionRequest.getPrincipalId())) {
177                     user2Request = actionRequest;
178                 }
179             } else if (recipientType == RecipientType.GROUP) {
180                 if (testWorkgroup.equals(actionRequest.getGroupId())) {
181                     testWorkgroupRequest = actionRequest;
182                 }
183             }
184         }
185         // now let's ensure we got the requests we wanted
186         assertNotNull(user1Request);
187         assertEquals(ActionRequestStatus.ACTIVATED, user1Request.getStatus());
188         assertNotNull(user2Request);
189         assertEquals(ActionRequestStatus.INITIALIZED, user2Request.getStatus());
190         assertNotNull(testWorkgroupRequest);
191         assertEquals(ActionRequestStatus.INITIALIZED, testWorkgroupRequest.getStatus());
192 
193         // let's double-check that before we start approving
194         assertApproveNotRequested(document, user2, ewestfal);
195 
196         // user1 should have the request for approval, however
197         assertApproveRequested(document, user1);
198 
199         // approve as user1
200         document.switchPrincipal(user1);
201         document.approve("");
202 
203         // should still be enroute
204         assertTrue(document.isEnroute());
205 
206         // now user1 should no longer have it, it should be activated approve to user2 with TestWorkgroup still initialized but not activated
207         assertApproveNotRequested(document, user1, ewestfal);
208         assertApproveRequested(document, user2);
209 
210         // approve as user2
211         document.switchPrincipal(user2);
212         document.approve("");
213         // should still be enroute
214         assertTrue(document.isEnroute());
215 
216         // now user1 and user2 have approved, should be activated to TestWorkgroup of which ewestfal is a member
217         assertApproveNotRequested(document, user2, user1);
218 
219         // ewestfal should have an approve request because he is a member of TestWorkgroup
220         assertApproveRequested(document, ewestfal);
221         document.switchPrincipal(ewestfal);
222         document.approve("");
223 
224         // now document should be final!
225         assertTrue(document.isFinal());
226     }
227 
228     /**
229      * Defines a PeopleFlow as follows:
230      *
231      * <pre>
232      *
233      * Priority 1:
234      *   -> user1
235      *   -> user2
236      * Priority 2:
237      *   -> testuser1
238      *   -> testuser2
239      * Priority 10:
240      *   -> TestWorkgroup
241      *   -> testuser3
242      *
243      * </pre>
244      */
245     private void createPriorityParallelPeopleFlow() {
246         PeopleFlowDefinition.Builder peopleFlow = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_2);
247         peopleFlow.addPrincipal(user1).setPriority(1);
248         peopleFlow.addPrincipal(user2).setPriority(1);
249         peopleFlow.addPrincipal(testuser1).setPriority(2);
250         peopleFlow.addPrincipal(testuser2).setPriority(2);
251         // add the last two at a priority which is not contiguous, should still work as expected
252         peopleFlow.addGroup(testWorkgroup).setPriority(10);
253         peopleFlow.addPrincipal(testuser3).setPriority(10);
254         peopleFlowService.createPeopleFlow(peopleFlow.build());
255     }
256 
257     @Test
258     public void test_SinglePeopleFlow_PriorityParallel_Approve() throws Exception {
259         createPriorityParallelPeopleFlow();
260 
261         // now route a document to it
262         WorkflowDocument document = WorkflowDocumentFactory.createDocument(user3, SINGLE_PEOPLE_FLOW_PRIORITY_PARALLEL_APPROVE);
263         document.route("");
264         assertTrue("Document should be enroute.", document.isEnroute());
265 
266         // user3 should not have an approval request since they initiated the document
267         document.switchPrincipal(user3);
268 
269         // document should be routed to user1, user2, testuser1, testuser2, TestWorkgroup, and testuser3
270         // But only user1 and user2 requests should be activated since those are at priority 1
271 
272         List<ActionRequest> rootActionRequests = document.getRootActionRequests();
273         assertEquals("Should have 6 root action requests", 6, rootActionRequests.size());
274         ActionRequest user1Request = null;
275         ActionRequest user2Request = null;
276         ActionRequest testuser1Request = null;
277         ActionRequest testuser2Request = null;
278         ActionRequest testWorkgroupRequest = null;
279         ActionRequest testuser3Request = null;
280         for (ActionRequest actionRequest : rootActionRequests) {
281             RecipientType recipientType = actionRequest.getRecipientType();
282             if (recipientType == RecipientType.PRINCIPAL) {
283                 if (user1.equals(actionRequest.getPrincipalId())) {
284                     user1Request = actionRequest;
285                 } else if (user2.equals(actionRequest.getPrincipalId())) {
286                     user2Request = actionRequest;
287                 } else if (testuser1.equals(actionRequest.getPrincipalId())) {
288                     testuser1Request = actionRequest;
289                 } else if (testuser2.equals(actionRequest.getPrincipalId())) {
290                     testuser2Request = actionRequest;
291                 } else if (testuser3.equals(actionRequest.getPrincipalId())) {
292                     testuser3Request = actionRequest;
293                 }
294             } else if (recipientType == RecipientType.GROUP) {
295                 if (testWorkgroup.equals(actionRequest.getGroupId())) {
296                     testWorkgroupRequest = actionRequest;
297                 }
298             }
299         }
300         // now let's ensure we got the requests we wanted
301         assertNotNull(user1Request);
302         assertEquals(ActionRequestStatus.ACTIVATED, user1Request.getStatus());
303         assertNotNull(user2Request);
304         assertEquals(ActionRequestStatus.ACTIVATED, user2Request.getStatus());
305         assertNotNull(testuser1Request);
306         assertEquals(ActionRequestStatus.INITIALIZED, testuser1Request.getStatus());
307         assertNotNull(testuser2Request);
308         assertEquals(ActionRequestStatus.INITIALIZED, testuser2Request.getStatus());
309         assertNotNull(testWorkgroupRequest);
310         assertEquals(ActionRequestStatus.INITIALIZED, testWorkgroupRequest.getStatus());
311         assertNotNull(testuser3Request);
312         assertEquals(ActionRequestStatus.INITIALIZED, testuser3Request.getStatus());
313 
314         // let's double-check that before we start approving
315 
316         assertApproveRequested(document, user1, user2);
317         assertApproveNotRequested(document, testuser1, testuser2, testuser3, ewestfal);
318 
319         // approve as user1 and user2
320         document.switchPrincipal(user1);
321         document.approve("");
322         assertApproveRequested(document, user2);
323         assertApproveNotRequested(document, user1);
324         document.switchPrincipal(user2);
325         document.approve("");
326         assertTrue(document.isEnroute());
327 
328         assertApproveRequested(document, testuser1, testuser2);
329         assertApproveNotRequested(document, user1, user2, testuser3, ewestfal);
330 
331         // approve as testuser1 and testuser2
332         document.switchPrincipal(testuser1);
333         document.approve("");
334         document.switchPrincipal(testuser2);
335         document.approve("");
336         assertTrue(document.isEnroute());
337 
338         assertApproveRequested(document, testuser3, ewestfal);
339         assertApproveNotRequested(document, user1, user2, testuser1, testuser2);
340 
341         // now approve as ewestfal and testuser3, then doc should be final
342         document.switchPrincipal(testuser3);
343         document.approve("");
344         document.switchPrincipal(ewestfal);
345         document.approve("");
346         assertTrue(document.isFinal());
347     }
348 
349     /**
350      * Defines PeopleFlow as follows:
351      *
352      * <pre>
353      *
354      * 1 - PeopleFlow - TEST:PeopleFlow1
355      *   -> Priority 1
356      *   ----> user1
357      *   -> Priority 2
358      *   ----> user2
359      * 2 - PeopleFlow - TEST:PeopleFlow2
360      *   -> Priority 1
361      *   ----> testuser1
362      *   -> Priority 2
363      *   ----> testuser2
364      * 3 - PeopleFlow - TEST:PeopleFlow3
365      *   -> Priority 1
366      *   ----> TestWorkgroup
367      *   -> Priority 10
368      *   ----> testuser3
369      *
370      * </pre>
371      */
372     private void createMultiplePeopleFlows() {
373         PeopleFlowDefinition.Builder peopleFlow1 = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_1);
374         peopleFlow1.addPrincipal(user1).setPriority(1);
375         peopleFlow1.addPrincipal(user2).setPriority(2);
376         peopleFlowService.createPeopleFlow(peopleFlow1.build());
377 
378         PeopleFlowDefinition.Builder peopleFlow2 = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_2);
379         peopleFlow2.addPrincipal(testuser1).setPriority(1);
380         peopleFlow2.addPrincipal(testuser2).setPriority(2);
381         peopleFlowService.createPeopleFlow(peopleFlow2.build());
382 
383         PeopleFlowDefinition.Builder peopleFlow3 = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_3);
384         peopleFlow3.addGroup(testWorkgroup).setPriority(1);
385         peopleFlow3.addPrincipal(testuser3).setPriority(10);
386         peopleFlowService.createPeopleFlow(peopleFlow3.build());
387     }
388 
389 
390     @Test
391     public void test_MultiplePeopleFlow_PriorityParallel() throws Exception {
392         createMultiplePeopleFlows();
393 
394         // now route a document to it
395         WorkflowDocument document = WorkflowDocumentFactory.createDocument(user3, MULTIPLE_PEOPLE_FLOW_PRIORITY_PARALLEL);
396         document.route("");
397         assertTrue("Document should be enroute.", document.isEnroute());
398 
399         // user3 should not have an approval request since they initiated the document
400         document.switchPrincipal(user3);
401 
402         // document should only send requests to the first people flow which should be user1 and user2
403         // But only user1 request should be activated
404 
405         List<ActionRequest> rootActionRequests = document.getRootActionRequests();
406         assertEquals("Should have 2 root action requests", 2, rootActionRequests.size());
407         ActionRequest user1Request = null;
408         ActionRequest user2Request = null;
409         for (ActionRequest actionRequest : rootActionRequests) {
410             RecipientType recipientType = actionRequest.getRecipientType();
411             if (recipientType == RecipientType.PRINCIPAL) {
412                 if (user1.equals(actionRequest.getPrincipalId())) {
413                     user1Request = actionRequest;
414                 } else if (user2.equals(actionRequest.getPrincipalId())) {
415                     user2Request = actionRequest;
416                 }
417             }
418         }
419         // now let's ensure we got the requests we wanted
420         assertNotNull(user1Request);
421         assertEquals(ActionRequestStatus.ACTIVATED, user1Request.getStatus());
422         assertNotNull(user2Request);
423         assertEquals(ActionRequestStatus.INITIALIZED, user2Request.getStatus());
424 
425         // now approve as user1
426         document.switchPrincipal(user1);
427         document.approve("");
428         document.switchPrincipal(user2);
429         assertTrue(document.isApprovalRequested());
430         document.approve("");
431 
432         // at this point, it should transition to the next people flow and generate Acknowledge requests to testuser1 and testuser2,
433         // and then generate an activated approve request to TestWorkgroup (of which "ewestfal" is a member) and then an
434         // initialized approve request to testuser3
435         assertTrue(document.isEnroute());
436         assertApproveRequested(document, ewestfal);
437         assertApproveNotRequested(document, user1, user2, testuser1, testuser2, testuser3);
438         assertAcknowledgeRequested(document, testuser1, testuser2);
439 
440         // now load as ewestfal (member of TestWorkgroup) and approve
441         document.switchPrincipal(ewestfal);
442         assertTrue(document.isApprovalRequested());
443         document.approve("");
444         assertTrue(document.isEnroute());
445 
446         // now the only remaining approval request should be to testuser3
447         assertApproveRequested(document, testuser3);
448         // just for fun, let's take testuser2's acknowledge action
449         document.switchPrincipal(testuser2);
450         assertTrue(document.isAcknowledgeRequested());
451         document.acknowledge("");
452         assertTrue(document.isEnroute());
453 
454         // testuser3 should still have an approve request, let's take it
455         assertApproveRequested(document, testuser3);
456         document.switchPrincipal(testuser3);
457         document.approve("");
458 
459         // document should now be in the processed state
460         assertTrue(document.isProcessed());
461         // load the last ack to testuser1 and take it
462         document.switchPrincipal(testuser1);
463         assertTrue(document.isAcknowledgeRequested());
464         document.acknowledge("");
465 
466         // now the document should be final!
467         assertTrue(document.isFinal());
468     }
469 
470     /**
471      * Defines a PeopleFlow as follows:
472      *
473      * <pre>
474      *
475      * Priority 1:
476      *   -> user1
477      *   -> user2
478      *   ----> testuser2 - primary delegate
479      * Priority 2:
480      *   -> testuser1
481      *   ----> TestWorkgroup - secondary delegate
482      *   ----> testuser3 - primary delegate
483      *   -> user3
484      *
485      * </pre>
486      */
487     private void createDelegatePeopleFlow() {
488         PeopleFlowDefinition.Builder peopleFlow = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_1);
489         peopleFlow.addPrincipal(user1).setPriority(1);
490 
491         PeopleFlowMember.Builder user2Builder = peopleFlow.addPrincipal(user2);
492         user2Builder.setPriority(1);
493         PeopleFlowDelegate.Builder user2PrimaryDelegateBuilder = PeopleFlowDelegate.Builder.create(testuser2,
494                 MemberType.PRINCIPAL);
495         user2PrimaryDelegateBuilder.setDelegationType(DelegationType.PRIMARY);
496         user2Builder.getDelegates().add(user2PrimaryDelegateBuilder);
497 
498         PeopleFlowMember.Builder testuser1Builder = peopleFlow.addPrincipal(testuser1);
499         testuser1Builder.setPriority(2);
500         PeopleFlowDelegate.Builder testWorkgroupSecondaryDelegateBuilder = PeopleFlowDelegate.Builder.create(testWorkgroup, MemberType.GROUP);
501         testWorkgroupSecondaryDelegateBuilder.setDelegationType(DelegationType.SECONDARY);
502         testuser1Builder.getDelegates().add(testWorkgroupSecondaryDelegateBuilder);
503         PeopleFlowDelegate.Builder testuser3PrimaryDelegateBuilder = PeopleFlowDelegate.Builder.create(testuser3, MemberType.PRINCIPAL);
504         testuser3PrimaryDelegateBuilder.setDelegationType(DelegationType.PRIMARY);
505         testuser1Builder.getDelegates().add(testuser3PrimaryDelegateBuilder);
506 
507         peopleFlow.addPrincipal(user3).setPriority(2);
508 
509         peopleFlowService.createPeopleFlow(peopleFlow.build());
510     }
511 
512     @Test
513     public void test_DelegatePeopleFlow_PriorityParallel_Approve() throws Exception {
514         createDelegatePeopleFlow();
515 
516         WorkflowDocument document = WorkflowDocumentFactory.createDocument(user3, DELEGATE_PEOPLE_FLOW_PRIORITY_PARALLEL_APPROVE);
517         document.route("");
518         assertTrue("Document should be enroute.", document.isEnroute());
519 
520         // user3 should not have an approval request since they initiated the document
521         document.switchPrincipal(user3);
522 
523         // user1, user2, and testuser2 (as user2's primary delegate) should all have activated requests, make sure the requests look correct
524         // user3 and testuser1 should have root requests as well, TestWorkgroup and testuser3 should be delegates of testuser1
525 
526         List<ActionRequest> rootActionRequests = document.getRootActionRequests();
527         assertEquals("Should have 4 root action requests", 4, rootActionRequests.size());
528         ActionRequest user1Request = null;
529         ActionRequest user2Request = null;
530         ActionRequest user3Request = null;
531         ActionRequest testuser1Request = null;
532         for (ActionRequest actionRequest : rootActionRequests) {
533             RecipientType recipientType = actionRequest.getRecipientType();
534             if (recipientType == RecipientType.PRINCIPAL) {
535                 if (user1.equals(actionRequest.getPrincipalId())) {
536                     user1Request = actionRequest;
537                 } else if (user2.equals(actionRequest.getPrincipalId())) {
538                     user2Request = actionRequest;
539                 } else if (user3.equals(actionRequest.getPrincipalId())) {
540                     user3Request = actionRequest;
541                 } else if (testuser1.equals(actionRequest.getPrincipalId())) {
542                     testuser1Request = actionRequest;
543                 }
544             }
545         }
546         // now let's ensure we got the requests we wanted
547         assertNotNull(user1Request);
548         assertEquals(ActionRequestStatus.ACTIVATED, user1Request.getStatus());
549         assertNotNull(user2Request);
550         assertEquals(ActionRequestStatus.ACTIVATED, user2Request.getStatus());
551         assertNotNull(user3Request);
552         assertEquals(ActionRequestStatus.INITIALIZED, user3Request.getStatus());
553         assertNotNull(testuser1Request);
554         assertEquals(ActionRequestStatus.INITIALIZED, testuser1Request.getStatus());
555 
556         // check delegate requests on user2Request now
557         assertEquals(1, user2Request.getChildRequests().size());
558         ActionRequest testuser2DelegateRequest = user2Request.getChildRequests().get(0);
559         assertEquals(testuser2, testuser2DelegateRequest.getPrincipalId());
560         assertEquals(DelegationType.PRIMARY, testuser2DelegateRequest.getDelegationType());
561         assertEquals(ActionRequestStatus.ACTIVATED, testuser2DelegateRequest.getStatus());
562 
563         // check delegate requests on testuser1Request now
564         assertEquals(2, testuser1Request.getChildRequests().size());
565         ActionRequest testWorkgroupRequest = null;
566         ActionRequest testuser3Request = null;
567         for (ActionRequest childActionRequest : testuser1Request.getChildRequests()) {
568             RecipientType recipientType = childActionRequest.getRecipientType();
569             if (recipientType == RecipientType.PRINCIPAL) {
570                 if (testuser3.equals(childActionRequest.getPrincipalId())) {
571                     testuser3Request = childActionRequest;
572                 }
573             } else if (recipientType == RecipientType.GROUP) {
574                 if (testWorkgroup.equals(childActionRequest.getGroupId())) {
575                     testWorkgroupRequest = childActionRequest;
576                 }
577             }
578         }
579         assertNotNull(testWorkgroupRequest);
580         assertEquals(ActionRequestStatus.INITIALIZED, testWorkgroupRequest.getStatus());
581         assertEquals(DelegationType.SECONDARY, testWorkgroupRequest.getDelegationType());
582         assertNotNull(testuser3Request);
583         assertEquals(ActionRequestStatus.INITIALIZED, testuser3Request.getStatus());
584         assertEquals(DelegationType.PRIMARY, testuser3Request.getDelegationType());
585 
586         // whew! now that that's done, let's run through the approvals for this peopleflow
587         assertApproveRequested(document, user1, user2, testuser2);
588         assertApproveNotRequested(document, testuser1, user3, ewestfal, testuser3);
589         // approve as testuser2 who is user2's primary delegate
590         document.switchPrincipal(testuser2);
591         document.approve("");
592 
593         // now approve as user1, this should push it to priority 2 in the peopleflow
594         assertApproveRequested(document, user1);
595         assertApproveNotRequested(document, user2, testuser2, testuser1, user3, ewestfal, testuser3);
596         document.switchPrincipal(user1);
597         document.approve("");
598 
599         // at this point all priorty2 folks should have approvals
600         assertApproveRequested(document, testuser1, user3, ewestfal, testuser3);
601         assertApproveNotRequested(document, user1, user2, testuser2);
602         // approve as ewestfal, a member of TestWorkgroup which is a delegate of testuser1
603         document.switchPrincipal(ewestfal);
604         document.approve("");
605 
606         // the only remaining approval at this point should be to user3, note that user3 initiated the document, but forceAction should = true by default on peopleflows
607         assertApproveRequested(document, user3);
608         assertApproveNotRequested(document, user1, user2, testuser2, testuser1, ewestfal, testuser3);
609         document.switchPrincipal(user3);
610         document.approve("");
611 
612         // document should now be FINAL!
613         assertTrue(document.isFinal());
614 
615     }
616 
617     private String roleId = null;
618     /**
619      * Defines a PeopleFlow with a single first approve role, that role has two members, one principal and one group.
620      */
621     private void createFirstApproveRolePeopleFlow() {
622         RoleService roleService = KimApiServiceLocator.getRoleService();
623         Role role = roleService.getRoleByNamespaceCodeAndName("KR-SYS", "Technical Administrator");
624         assertNotNull("Technical Administrator role should exist!", role);
625         assertEquals(2, roleService.getRoleMembers(Collections.singletonList(role.getId()),
626                 new HashMap<String, String>()).size());
627         roleId = role.getId();
628 
629         PeopleFlowDefinition.Builder peopleFlow = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_2);
630         PeopleFlowMember.Builder memberBuilder = peopleFlow.addRole(role.getId());
631         memberBuilder.setPriority(1);
632         memberBuilder.setActionRequestPolicy(ActionRequestPolicy.FIRST);
633         peopleFlowService.createPeopleFlow(peopleFlow.build());
634     }
635 
636     @Test
637     public void test_FirstApproveRolePeopleFlow() throws Exception {
638         createFirstApproveRolePeopleFlow();
639 
640         WorkflowDocument document = WorkflowDocumentFactory.createDocument(user3, SINGLE_PEOPLE_FLOW_PRIORITY_PARALLEL_APPROVE);
641         document.route("");
642         assertTrue("Document should be enroute.", document.isEnroute());
643 
644         // should have 1 root requests which is a role request with 2 children, one a principal request to the "admin"
645         // prinicipal, and one a group request to the WorkflowAdmin group
646         List<ActionRequest> rootActionRequests = document.getRootActionRequests();
647         assertEquals(1, rootActionRequests.size());
648         ActionRequest roleRequest = rootActionRequests.get(0);
649         assertEquals(ActionRequestPolicy.FIRST, roleRequest.getRequestPolicy());
650         assertEquals(roleId, roleRequest.getRoleName());
651         assertEquals(RecipientType.ROLE, roleRequest.getRecipientType());
652         assertEquals(2, roleRequest.getChildRequests().size());
653         for (ActionRequest childRequest : roleRequest.getChildRequests()) {
654             if (RecipientType.PRINCIPAL.equals(childRequest.getRecipientType())) {
655                 assertEquals(getPrincipalIdForName("admin"), childRequest.getPrincipalId());
656             } else if (RecipientType.GROUP.equals(childRequest.getRecipientType())) {
657                 assertEquals(getGroupIdForName("KR-WKFLW", "WorkflowAdmin"), childRequest.getGroupId());
658             } else {
659                 fail("Found a child request i didn't expect with a recipient type of: " + childRequest.getRecipientType());
660             }
661         }
662 
663         // should be able to approve as a member of the group on Technical Administrator role (which is WorkflowAdmin) as
664         // well as the 'admin' principal
665         document.switchPrincipal(getPrincipalNameForId("admin"));
666         assertTrue(document.isApprovalRequested());
667         document.switchPrincipal(getPrincipalIdForName("bmcgough"));
668         assertTrue(document.isApprovalRequested());
669 
670         // now approve as a member of WorkflowAdmin
671         document.approve("");
672 
673         // document should now be final because it's first approve
674         assertTrue(document.isFinal());
675 
676         // now try it by approving as admin, and ensure that the first approval works as well in that case
677         document = WorkflowDocumentFactory.createDocument(user3, SINGLE_PEOPLE_FLOW_PRIORITY_PARALLEL_APPROVE);
678         document.route("");
679         assertTrue("Document should be enroute.", document.isEnroute());
680         document.switchPrincipal(getPrincipalIdForName("bmcgough"));
681         assertTrue(document.isApprovalRequested());
682         document.switchPrincipal(getPrincipalNameForId("admin"));
683         assertTrue(document.isApprovalRequested());
684         // now approve as admin
685         document.approve("");
686         // document should now be final because it's first approve
687         assertTrue(document.isFinal());
688     }
689 
690     /**
691      * Defines a PeopleFlow with a single all approve role, that role has two members, one principal and one group.
692      */
693     private void createAllApproveRolePeopleFlow() {
694         RoleService roleService = KimApiServiceLocator.getRoleService();
695         Role role = roleService.getRoleByNamespaceCodeAndName("KR-SYS", "Technical Administrator");
696         assertNotNull("Technical Administrator role should exist!", role);
697         assertEquals(2, roleService.getRoleMembers(Collections.singletonList(role.getId()),
698                 new HashMap<String, String>()).size());
699         roleId = role.getId();
700 
701         PeopleFlowDefinition.Builder peopleFlow = PeopleFlowDefinition.Builder.create(NAMESPACE_CODE, PEOPLE_FLOW_2);
702         PeopleFlowMember.Builder memberBuilder = peopleFlow.addRole(role.getId());
703         memberBuilder.setPriority(1);
704         memberBuilder.setActionRequestPolicy(ActionRequestPolicy.ALL);
705         peopleFlowService.createPeopleFlow(peopleFlow.build());
706     }
707 
708     @Test
709     public void test_AllApproveRolePeopleFlow() throws Exception {
710         createAllApproveRolePeopleFlow();
711 
712         WorkflowDocument document = WorkflowDocumentFactory.createDocument(user3, SINGLE_PEOPLE_FLOW_PRIORITY_PARALLEL_APPROVE);
713         document.route("");
714         assertTrue("Document should be enroute.", document.isEnroute());
715 
716         // should have 1 root requests which is a role request with 2 children, one a principal request to the "admin"
717         // prinicipal, and one a group request to the WorkflowAdmin group
718         List<ActionRequest> rootActionRequests = document.getRootActionRequests();
719         assertEquals(1, rootActionRequests.size());
720         ActionRequest roleRequest = rootActionRequests.get(0);
721         assertEquals(ActionRequestPolicy.ALL, roleRequest.getRequestPolicy());
722         assertEquals(roleId, roleRequest.getRoleName());
723         assertEquals(RecipientType.ROLE, roleRequest.getRecipientType());
724         assertEquals(2, roleRequest.getChildRequests().size());
725         for (ActionRequest childRequest : roleRequest.getChildRequests()) {
726             if (RecipientType.PRINCIPAL.equals(childRequest.getRecipientType())) {
727                 assertEquals(getPrincipalIdForName("admin"), childRequest.getPrincipalId());
728             } else if (RecipientType.GROUP.equals(childRequest.getRecipientType())) {
729                 assertEquals(getGroupIdForName("KR-WKFLW", "WorkflowAdmin"), childRequest.getGroupId());
730             } else {
731                 fail("Found a child request i didn't expect with a recipient type of: " + childRequest.getRecipientType());
732             }
733         }
734 
735         // should be able to approve as a member of the group on Technical Administrator role (which is WorkflowAdmin) as
736         // well as the 'admin' principal
737         document.switchPrincipal(getPrincipalNameForId("admin"));
738         assertTrue(document.isApprovalRequested());
739         document.switchPrincipal(getPrincipalIdForName("bmcgough"));
740         assertTrue(document.isApprovalRequested());
741 
742         // now approve as a member of WorkflowAdmin
743         document.approve("");
744 
745         // document should still be enroute because this is an all approve situation and both the group and admin need to approve
746         assertTrue(document.isEnroute());
747         assertFalse(document.isApprovalRequested());
748 
749         document.switchPrincipal(getPrincipalNameForId("admin"));
750         assertTrue(document.isApprovalRequested());
751         document.approve("");
752         // after approving as admin, the last of the two role requests have been completed, document should be final
753         assertTrue(document.isFinal());
754     }
755     
756     private void assertApproveRequested(WorkflowDocument document, String... principalIds) {
757         for (String principalId : principalIds) {
758             document.switchPrincipal(principalId);
759             assertTrue("Approve should have been requested for '" + principalId + "'", document.isApprovalRequested());
760         }
761     }
762 
763     private void assertAcknowledgeRequested(WorkflowDocument document, String... principalIds) {
764         for (String principalId : principalIds) {
765             document.switchPrincipal(principalId);
766             assertTrue("Acknowledge should have been requested for '" + principalId + "'", document.isAcknowledgeRequested());
767         }
768     }
769 
770     private void assertApproveNotRequested(WorkflowDocument document, String... principalIds) {
771         for (String principalId : principalIds) {
772             document.switchPrincipal(principalId);
773             assertFalse("Approve should *NOT* have been requested for '" + principalId + "'", document.isApprovalRequested());
774         }
775     }
776 
777 }