View Javadoc

1   /*
2    * Copyright 2005-2007 The Kuali Foundation
3    * 
4    * 
5    * Licensed under the Educational Community License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    * 
9    * http://www.opensource.org/licenses/ecl2.php
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.kuali.rice.kew.engine;
18  
19  
20  import org.junit.Test;
21  import org.kuali.rice.kew.actionrequest.ActionRequestValue;
22  import org.kuali.rice.kew.dto.NetworkIdDTO;
23  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
24  import org.kuali.rice.kew.service.KEWServiceLocator;
25  import org.kuali.rice.kew.service.WorkflowDocument;
26  import org.kuali.rice.kew.test.KEWTestCase;
27  import org.kuali.rice.kew.util.KEWConstants;
28  
29  import java.util.*;
30  
31  
32  public class ParallelRoutingTest extends KEWTestCase {
33      
34      private static final String DOCUMENT_TYPE_NAME = "ParallelDocType";
35      private static final String PARALLEL_EMPTY_DOCUMENT_TYPE_NAME = "ParallelEmptyDocType";
36      private static final String PARALLEL_EMPTY_DOCUMENT_TYPE_2_NAME = "ParallelEmptyDocType2";
37      private static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
38      private static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
39      private static final String WORKFLOW_DOCUMENT_3_NODE = "WorkflowDocument3";
40      private static final String JOIN_NODE = "Join";
41      private static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
42  	
43      protected void loadTestData() throws Exception {
44          loadXmlFile("EngineConfig.xml");
45      }
46  
47      @Test public void testParallelRoute() throws Exception {
48          WorkflowDocument document = new WorkflowDocument(new NetworkIdDTO("ewestfal"), DOCUMENT_TYPE_NAME);
49          document.saveRoutingData();
50          assertTrue("Document should be initiated", document.stateIsInitiated());
51          assertEquals("Should be no action requests.", 0, document.getActionRequests().length);
52          assertEquals("Invalid route level.", new Integer(0), document.getRouteHeader().getDocRouteLevel());
53          Collection nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
54          assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
55          document.routeDocument("Routing for parallel");
56          
57          // should have generated a request to "bmcgough"
58          document = new WorkflowDocument(new NetworkIdDTO("bmcgough"), document.getRouteHeaderId());
59          assertTrue("Document should be enroute", document.stateIsEnroute());
60          List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getRouteHeaderId());
61          assertEquals("Incorrect pending action requests.", 1, actionRequests.size());
62          ActionRequestValue bRequest = (ActionRequestValue)actionRequests.get(0);
63          assertNotNull("Should have been routed through node instance.", bRequest.getNodeInstance());
64          assertTrue(document.isApprovalRequested());
65          
66          document.approve("Approving test");
67          
68          // document should split at this point and generate an ack to temay and approves to rkirkend and pmckown
69          document = new WorkflowDocument(new NetworkIdDTO("rkirkend"), document.getRouteHeaderId());
70          assertTrue("Document should be enroute", document.stateIsEnroute());
71          actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getRouteHeaderId());
72          assertEquals("Incorrect pending action requests.", 3, actionRequests.size());
73          boolean isToTemay = false;
74          boolean isToPmckown = false;
75          boolean isToRkirkend = false;
76          for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
77              ActionRequestValue actionRequest = (ActionRequestValue) iterator.next();
78              if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("temay"))) {
79                  isToTemay = true;
80                  assertEquals("Request should be activated.", KEWConstants.ACTION_REQUEST_ACTIVATED, actionRequest.getStatus());
81                  assertEquals("Wrong action requested.", KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, actionRequest.getActionRequested());
82                  assertNotNull("Should have been routed through node instance.", actionRequest.getNodeInstance());
83                  assertEquals("Invalid node.", ACKNOWLEDGE_1_NODE, actionRequest.getNodeInstance().getRouteNode().getRouteNodeName());
84              }
85              if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("rkirkend"))) {
86                  isToRkirkend = true;
87                  assertEquals("Request should be activated.", KEWConstants.ACTION_REQUEST_ACTIVATED, actionRequest.getStatus());
88                  assertEquals("Wrong action requested.", KEWConstants.ACTION_REQUEST_APPROVE_REQ, actionRequest.getActionRequested());
89                  assertNotNull("Should have been routed through node instance.", actionRequest.getNodeInstance());
90                  assertEquals("Invalid node.", WORKFLOW_DOCUMENT_2_NODE, actionRequest.getNodeInstance().getRouteNode().getRouteNodeName());
91              }
92              if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("pmckown"))) {
93                  isToPmckown = true;
94                  assertEquals("Request should be activated.", KEWConstants.ACTION_REQUEST_ACTIVATED, actionRequest.getStatus());
95                  assertEquals("Wrong action requested.", KEWConstants.ACTION_REQUEST_APPROVE_REQ, actionRequest.getActionRequested());
96                  assertNotNull("Should have been routed through node instance.", actionRequest.getNodeInstance());
97                  assertEquals("Invalid node.", WORKFLOW_DOCUMENT_3_NODE, actionRequest.getNodeInstance().getRouteNode().getRouteNodeName());
98              }
99          }
100         assertTrue("No request to temay.", isToTemay);
101         assertTrue("No request to pmckown.", isToPmckown);
102         assertTrue("No request to rkirkend.", isToRkirkend);
103         
104         // check that we are at both nodes, one in each branch
105         String[] nodeNames = document.getNodeNames();
106         assertEquals("Wrong number of node names.", 2, nodeNames.length);
107         boolean isNode2 = false;
108         boolean isNode3 = false;
109         for (int index = 0; index < nodeNames.length; index++) {
110             String name = nodeNames[index];
111             if (name.equals(WORKFLOW_DOCUMENT_2_NODE)) {
112                 isNode2 = true;
113             }
114             if (name.equals(WORKFLOW_DOCUMENT_3_NODE)) {
115                 isNode3 = true;
116             }
117         }
118         assertTrue("Not at node2.", isNode2);
119         assertTrue("Not at node3.", isNode3);
120         nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
121         assertEquals("Wrong number of active nodes.", 2, nodeInstances.size());
122         Iterator iterator = nodeInstances.iterator();
123         RouteNodeInstance instance1 = (RouteNodeInstance)iterator.next();
124         RouteNodeInstance instance2 = (RouteNodeInstance)iterator.next();
125         assertNotNull("Node should be in branch.", instance1.getBranch());
126         assertNotNull("Node should be in branch.", instance2.getBranch());
127         assertTrue("Branches should be different.", !instance1.getBranch().getBranchId().equals(instance2.getBranch().getBranchId()));
128         
129         document = new WorkflowDocument(new NetworkIdDTO("rkirkend"), document.getRouteHeaderId());
130         assertTrue("Should have request.", document.isApprovalRequested());
131         document.approve("Git-r-dun");
132         
133         nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
134         assertEquals("Wrong number of active nodes.", 2, nodeInstances.size());
135         boolean isAtJoin = false;
136         boolean isAtWD3 = false;
137         for (Iterator iter = nodeInstances.iterator(); iter.hasNext();) {
138             RouteNodeInstance nodeInstance = (RouteNodeInstance) iter.next();
139             if (nodeInstance.getRouteNode().getRouteNodeName().equals(JOIN_NODE)) {
140                 assertEquals("Join branch should be split branch.", instance1.getBranch().getParentBranch().getBranchId(), nodeInstance.getBranch().getBranchId());
141                 isAtJoin = true;
142             }
143             if (nodeInstance.getRouteNode().getRouteNodeName().equals(WORKFLOW_DOCUMENT_3_NODE)) {
144                 isAtWD3 = true;
145             }
146         }
147         assertTrue("Not at join", isAtJoin);
148         assertTrue("Not at WD3", isAtWD3);
149         
150         document = new WorkflowDocument(new NetworkIdDTO("pmckown"), document.getRouteHeaderId());
151         assertTrue("Should have request.", document.isApprovalRequested());
152         document.approve("Do it.");
153         
154         nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
155         assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
156         boolean isAtWDF = false;
157         for (Iterator iter = nodeInstances.iterator(); iter.hasNext();) {
158             RouteNodeInstance nodeInstance = (RouteNodeInstance) iter.next();
159             if (nodeInstance.getRouteNode().getRouteNodeName().equals(WORKFLOW_DOCUMENT_FINAL_NODE)) {
160                 isAtWDF = true;
161             }
162         }
163         assertTrue("Not at WDF", isAtWDF);
164         
165         document = new WorkflowDocument(new NetworkIdDTO("xqi"), document.getRouteHeaderId());
166         assertTrue("Should still be enroute.", document.stateIsEnroute());
167         assertTrue("Should have request.", document.isApprovalRequested());
168         document.approve("I'm the last approver");
169         
170         assertTrue("Document should be processed.", document.stateIsProcessed());
171         nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
172         //commented out because the final RouteNodeInstance is now not active when the doc goes final
173 //        assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
174 //        isAtWDF = false;
175 //        for (Iterator iter = nodeInstances.iterator(); iter.hasNext();) {
176 //            RouteNodeInstance nodeInstance = (RouteNodeInstance) iter.next();
177 //            if (nodeInstance.getRouteNode().getRouteNodeName().equals(WORKFLOW_DOCUMENT_FINAL_NODE)) {
178 //                isAtWDF = true;
179 //            }
180 //        }
181 //        assertTrue("Not at WDF", isAtWDF);
182         
183         document = new WorkflowDocument(new NetworkIdDTO("temay"), document.getRouteHeaderId());
184         assertTrue("Should have request.", document.isAcknowledgeRequested());
185         document.acknowledge("");
186         assertTrue(document.stateIsFinal());
187     }
188     
189     /**
190      * Tests that the document route past the join properly when there are parallel branches that don't generate requests.
191      * This was coded in response to a bug found while testing with ERA in order to track it down and fix it.
192      */
193     @Test public void testEmptyParallelBranches() throws Exception {
194         
195         WorkflowDocument document = new WorkflowDocument(new NetworkIdDTO("ewestfal"), PARALLEL_EMPTY_DOCUMENT_TYPE_NAME);
196         document.saveRoutingData();
197         assertTrue("Document should be initiated", document.stateIsInitiated());
198         assertEquals("Should be no action requests.", 0, document.getActionRequests().length);
199         assertEquals("Invalid route level.", new Integer(0), document.getRouteHeader().getDocRouteLevel());
200         Collection<? extends Object> nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
201         assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
202         document.routeDocument("");
203         
204         // should have generated a request to "bmcgough"
205         document = new WorkflowDocument(new NetworkIdDTO("bmcgough"), document.getRouteHeaderId());
206         assertTrue("Document should be enroute", document.stateIsEnroute());
207         List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getRouteHeaderId());
208         assertEquals("Incorrect pending action requests.", 1, actionRequests.size());
209         ActionRequestValue bRequest = (ActionRequestValue)actionRequests.get(0);
210         assertNotNull("Should have been routed through node instance.", bRequest.getNodeInstance());
211         assertTrue(document.isApprovalRequested());
212         
213         document.approve("");
214         
215         // now the document should have split, passed through nodes in each branch which didn't generate requests,
216         // and then passed the join node and generated requests at WorkflowDocumentFinal
217         document = new WorkflowDocument(new NetworkIdDTO("xqi"), document.getRouteHeaderId());
218         assertTrue("Document should be enroute", document.stateIsEnroute());
219         assertTrue(document.isApprovalRequested());
220         
221     }
222     
223     /**
224      * This runs the test with the adhoc approvers branch second instead of first
225      *//*
226     public void testEmptyParallelBranchesSwitched() throws Exception {
227         
228         WorkflowDocument document = new WorkflowDocument(new NetworkIdVO("ewestfal"), PARALLEL_EMPTY_DOCUMENT_TYPE_2_NAME);
229         document.saveRoutingData();
230         assertTrue("Document should be initiated", document.stateIsInitiated());
231         assertEquals("Should be no action requests.", 0, document.getActionRequests().length);
232         assertEquals("Invalid route level.", new Integer(0), document.getRouteHeader().getDocRouteLevel());
233         Collection nodeInstances = SpringServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
234         assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
235         document.routeDocument("");
236         
237         // should have generated a request to "bmcgough"
238         document = new WorkflowDocument(new NetworkIdVO("bmcgough"), document.getRouteHeaderId());
239         assertTrue("Document should be enroute", document.stateIsEnroute());
240         List actionRequests = TestUtilities.getActionRequestService().findPendingByDoc(document.getRouteHeaderId());
241         assertEquals("Incorrect pending action requests.", 1, actionRequests.size());
242         ActionRequestValue bRequest = (ActionRequestValue)actionRequests.get(0);
243         assertNotNull("Should have been routed through node instance.", bRequest.getNodeInstance());
244         assertTrue(document.isApprovalRequested());
245         
246         document.approve("");
247         
248         // now the document should have split, passed through nodes in each branch which didn't generate requests,
249         // and then passed the join node and generated requests at WorkflowDocumentFinal
250         document = new WorkflowDocument(new NetworkIdVO("xqi"), document.getRouteHeaderId());
251         assertTrue("Document should be enroute", document.stateIsEnroute());
252         assertTrue(document.isApprovalRequested());
253         
254     }*/
255     
256     @Test public void testAdhocApproversJoinScenario() throws Exception {
257         WorkflowDocument document = new WorkflowDocument(new NetworkIdDTO("ewestfal"), "AdHocApproversDocType");
258         document.routeDocument("");
259         
260         // should send an approve to bmcgough
261         document = new WorkflowDocument(new NetworkIdDTO("bmcgough"), document.getRouteHeaderId());
262         assertTrue("Bmcgough should have approve request.", document.isApprovalRequested());
263         document.approve("");
264         
265         // at this point the document should pass the split, and end up at the WorkflowDocument2 node and the AdHocApproversJoin node
266         // after bypassing the AdHocJoinPoint
267         Set<? extends String> nodeNames = new HashSet<String>(Arrays.asList(document.getNodeNames()));
268         assertEquals("There should be two node names.", 2, nodeNames.size());
269         assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("WorkflowDocument2"));
270         assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("AdHocApproversJoin"));
271         
272         // pmckown has the request at the adhoc approvers node, if we approve as him then the document should _not_ transition out
273         // of it's current nodes
274         document = new WorkflowDocument(new NetworkIdDTO("pmckown"), document.getRouteHeaderId());
275         assertTrue("Pmckown should have approve request.", document.isApprovalRequested());
276         document.approve("");
277         
278         // the document should still be at the same nodes
279         nodeNames = new HashSet<String>(Arrays.asList(document.getNodeNames()));
280         assertEquals("There should be two node names.", 2, nodeNames.size());
281         assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("WorkflowDocument2"));
282         assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("AdHocApproversJoin"));
283     
284         // at WorkflowDocument2, rkirkend is the approver, if we approve as him we should end up at the WorkflowDocumentFinal node
285         document = new WorkflowDocument(new NetworkIdDTO("rkirkend"), document.getRouteHeaderId());
286         assertTrue("Rkirkend should have approve request.", document.isApprovalRequested());
287         document.approve("");
288         
289         // the document should now be at WorkflowDocumentFinal with a request to xqi
290         nodeNames = new HashSet<String>(Arrays.asList(document.getNodeNames()));
291         assertEquals("There should be one node name.", 1, nodeNames.size());
292         assertTrue("Should be at WorkflowDocumentFinal node.", nodeNames.contains("WorkflowDocumentFinal"));
293         
294         document = new WorkflowDocument(new NetworkIdDTO("xqi"), document.getRouteHeaderId());
295         assertTrue("Document should still be enroute.", document.stateIsEnroute());
296         document.approve("");
297         assertTrue("Document should now be final.", document.stateIsFinal());
298         
299     }
300     
301 }