001 /**
002 * Copyright 2005-2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kew.engine;
017
018
019 import static org.junit.Assert.assertEquals;
020 import static org.junit.Assert.assertNotNull;
021 import static org.junit.Assert.assertNull;
022 import static org.junit.Assert.assertTrue;
023
024 import java.util.Collection;
025 import java.util.List;
026
027 import org.junit.Test;
028 import org.kuali.rice.kew.api.WorkflowDocument;
029 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
030 import org.kuali.rice.kew.engine.node.DynamicNode;
031 import org.kuali.rice.kew.engine.node.DynamicResult;
032 import org.kuali.rice.kew.engine.node.NodeState;
033 import org.kuali.rice.kew.engine.node.RouteNode;
034 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
035 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
036 import org.kuali.rice.kew.service.KEWServiceLocator;
037 import org.kuali.rice.kew.test.KEWTestCase;
038
039
040 public class DynamicRoutingTest extends KEWTestCase {
041
042 private static final String SEQ_DOC_TYPE_NAME = "DynSeqDocType";
043 private static final String INIT = "Initial";
044 private static final String FIRST = "First";
045 private static final String DYNAMIC_SEQ = "DynSeq";
046 private static final String SUB_REQUESTS = "SubRequests";
047 private static final String LAST = "Last";
048
049 protected void loadTestData() throws Exception {
050 loadXmlFile("EngineConfig.xml");
051 }
052
053 @Test public void testDynamicParallelRoute() throws Exception {
054 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), SEQ_DOC_TYPE_NAME);
055 document.saveDocumentData();
056 assertTrue("Document should be initiated", document.isInitiated());
057 assertEquals("Should be no action requests.", 0, document.getRootActionRequests().size());
058 Collection nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
059 assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
060 assertEquals("Wrong active node.", INIT, ((RouteNodeInstance) nodeInstances.iterator().next()).getRouteNode().getRouteNodeName());
061 document.route("");
062
063 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
064 assertTrue("Approve should be requested.", document.isApprovalRequested());
065 document.approve("");
066
067 nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
068 assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
069 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("pmckown"), document.getDocumentId());
070 assertTrue("Approve should be requested.", document.isApprovalRequested());
071 document.approve("");
072
073 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("temay"), document.getDocumentId());
074 assertTrue("Approve should be requested.", document.isApprovalRequested());
075 document.approve("");
076
077 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), document.getDocumentId());
078 assertTrue("Approve should be requested.", document.isApprovalRequested());
079 document.approve("");
080
081 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
082 assertTrue("Approve should be requested.", document.isApprovalRequested());
083 document.approve("");
084
085 // document = WorkflowDocumentFactory.loadDocument(new NetworkIdVO("ewestfal"), document.getDocumentId());
086 // assertTrue("Document should be final.", document.isFinal());
087
088 verifyRoutingPath(document.getDocumentId());
089 }
090
091 private void verifyRoutingPath(String documentId) {
092 DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
093 List initial = document.getInitialRouteNodeInstances();
094 assertEquals(1, initial.size());
095 RouteNodeInstance init = (RouteNodeInstance) initial.get(0);
096 assertEquals(INIT, init.getRouteNode().getRouteNodeName());
097 assertEquals(0, init.getPreviousNodeInstances().size());
098
099 List next = init.getNextNodeInstances();
100 assertEquals(1, next.size());
101 RouteNodeInstance first = (RouteNodeInstance) next.get(0);
102 assertEquals(FIRST, first.getRouteNode().getRouteNodeName());
103 assertEquals(1, first.getPreviousNodeInstances().size());
104
105 next = first.getNextNodeInstances();
106 assertEquals(1, next.size());
107 RouteNodeInstance pmckownNode = (RouteNodeInstance) next.get(0);
108 assertEquals(SUB_REQUESTS, pmckownNode.getRouteNode().getRouteNodeName());
109 assertEquals(1, pmckownNode.getPreviousNodeInstances().size());
110 assertInSubProcess(pmckownNode);
111
112 next = pmckownNode.getNextNodeInstances();
113 assertEquals(1, next.size());
114 RouteNodeInstance temayNode = (RouteNodeInstance) next.get(0);
115 assertEquals(SUB_REQUESTS, temayNode.getRouteNode().getRouteNodeName());
116 assertEquals(1, temayNode.getPreviousNodeInstances().size());
117 assertInSubProcess(temayNode);
118
119 next = temayNode.getNextNodeInstances();
120 assertEquals(1, next.size());
121 RouteNodeInstance jhopfNode = (RouteNodeInstance) next.get(0);
122 assertEquals(SUB_REQUESTS, jhopfNode.getRouteNode().getRouteNodeName());
123 assertEquals(1, jhopfNode.getPreviousNodeInstances().size());
124 assertInSubProcess(jhopfNode);
125
126 next = jhopfNode.getNextNodeInstances();
127 assertEquals(1, next.size());
128 RouteNodeInstance last = (RouteNodeInstance) next.get(0);
129 assertNull(last.getProcess());
130 assertEquals(LAST, last.getRouteNode().getRouteNodeName());
131 assertEquals(1, last.getPreviousNodeInstances().size());
132 assertEquals(0, last.getNextNodeInstances().size());
133 }
134
135 private void assertInSubProcess(RouteNodeInstance nodeInstance) {
136 RouteNodeInstance subProcess = nodeInstance.getProcess();
137 assertNotNull(subProcess);
138 assertEquals(DYNAMIC_SEQ, subProcess.getRouteNode().getRouteNodeName());
139 }
140
141 public static class MockSequentialDynamicNode implements DynamicNode {
142
143 public DynamicResult transitioningInto(RouteContext context, RouteNodeInstance process, RouteHelper helper) throws Exception {
144 RouteNodeInstance routeNodeInstance = context.getNodeInstance();
145 RouteNode dynamicRequestNode = helper.getNodeFactory().getRouteNode(context, SUB_REQUESTS);
146 RouteNodeInstance dynamicRequestNodeInstance1 = helper.getNodeFactory().createRouteNodeInstance(context.getDocument().getDocumentId(), dynamicRequestNode);
147 dynamicRequestNodeInstance1.addNodeState(new NodeState("role", "pmckown"));
148 RouteNodeInstance dynamicRequestNodeInstance2 = helper.getNodeFactory().createRouteNodeInstance(context.getDocument().getDocumentId(), dynamicRequestNode);
149 dynamicRequestNodeInstance2.addNodeState(new NodeState("role", "temay"));
150 RouteNodeInstance dynamicRequestNodeInstance3 = helper.getNodeFactory().createRouteNodeInstance(context.getDocument().getDocumentId(), dynamicRequestNode);
151 dynamicRequestNodeInstance3.addNodeState(new NodeState("role", "jhopf"));
152 dynamicRequestNodeInstance1.addNextNodeInstance(dynamicRequestNodeInstance2);
153 dynamicRequestNodeInstance2.addNextNodeInstance(dynamicRequestNodeInstance3);
154 routeNodeInstance.addNodeState(new NodeState("beenHere", "val"));
155 return new DynamicResult(true, dynamicRequestNodeInstance1);
156 }
157
158 public DynamicResult transitioningOutOf(RouteContext context, RouteHelper helper) throws Exception {
159 return new DynamicResult(true, null);
160 }
161 }
162 }