001/** 002 * Copyright 2005-2014 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.engine.node; 017 018import static org.junit.Assert.assertEquals; 019import static org.junit.Assert.assertNotNull; 020import static org.junit.Assert.assertTrue; 021import static org.junit.Assert.fail; 022 023import java.util.ArrayList; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Set; 027 028import org.junit.Test; 029import org.kuali.rice.kew.api.WorkflowDocument; 030import org.kuali.rice.kew.api.WorkflowDocumentFactory; 031import org.kuali.rice.kew.engine.node.service.RouteNodeService; 032import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 033import org.kuali.rice.kew.service.KEWServiceLocator; 034import org.kuali.rice.kew.test.KEWTestCase; 035import org.kuali.rice.kew.test.TestUtilities; 036 037public class RouteNodeServiceTest extends KEWTestCase { 038 039 private RouteNodeService routeNodeService; 040 041 protected void setUpAfterDataLoad() throws Exception { 042 routeNodeService = KEWServiceLocator.getRouteNodeService(); 043 } 044 045 protected void loadTestData() throws Exception { 046 loadXmlFile("NodeConfig.xml"); 047 } 048 049 @Test public void testGetFlattenedNodeInstances() throws Exception { 050 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "SeqDocType"); 051 document.saveDocument(""); 052 053 DocumentRouteHeaderValue serverDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()); 054 List routeNodeInstances = routeNodeService.getFlattenedNodeInstances(serverDocument, true); 055 assertEquals(1, routeNodeInstances.size()); 056 assertEquals("AdHoc", ((RouteNodeInstance)routeNodeInstances.get(0)).getName()); 057 058 document.blanketApprove(""); 059 assertTrue(document.isProcessed()); 060 061 serverDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()); 062 routeNodeInstances = routeNodeService.getFlattenedNodeInstances(serverDocument, true); 063 assertEquals(4, routeNodeInstances.size()); 064 assertEquals("AdHoc", ((RouteNodeInstance)routeNodeInstances.get(0)).getName()); 065 assertEquals("WorkflowDocument", ((RouteNodeInstance)routeNodeInstances.get(1)).getName()); 066 assertEquals("Acknowledge1", ((RouteNodeInstance)routeNodeInstances.get(2)).getName()); 067 assertEquals("Acknowledge2", ((RouteNodeInstance)routeNodeInstances.get(3)).getName()); 068 } 069 070 @Test public void testSearchNodeGraphSequentailBackward() throws Exception { 071 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "SeqDocType"); 072 document.blanketApprove("", "WorkflowDocument"); 073 List activeNodeInstances = routeNodeService.getActiveNodeInstances(document.getDocumentId()); 074 NodeGraphSearchCriteria criteria = new NodeGraphSearchCriteria(NodeGraphSearchCriteria.SEARCH_DIRECTION_BACKWARD, activeNodeInstances, "AdHoc"); 075 NodeGraphSearchResult result = routeNodeService.searchNodeGraph(criteria); 076 assertEquals("Path should have two nodes.", 2, result.getPath().size()); 077 RouteNodeInstance resultNodeInstance = result.getResultNodeInstance(); 078 assertNotNull("Should have a resulting node instance.", resultNodeInstance); 079 assertEquals("Result node should be the adhoc node.", "AdHoc", resultNodeInstance.getName()); 080 081 // take it to the end 082 document.blanketApprove(""); 083 assertTrue("Document should be processed.", document.isProcessed()); 084 List terminalNodeInstances = routeNodeService.getTerminalNodeInstances(document.getDocumentId()); 085 criteria = new NodeGraphSearchCriteria(NodeGraphSearchCriteria.SEARCH_DIRECTION_BACKWARD, terminalNodeInstances, "AdHoc"); 086 result = routeNodeService.searchNodeGraph(criteria); 087 assertEquals("Path should have 4 nodes.", 4, result.getPath().size()); 088 resultNodeInstance = result.getResultNodeInstance(); 089 assertNotNull("Should have a resulting node instance.", resultNodeInstance); 090 assertEquals("Result node should be the adhoc node.", "AdHoc", resultNodeInstance.getName()); 091 092 // now try searching from the Ack1 node for the WorkflowDocument node 093 RouteNodeInstance ack1NodeInstance = null; 094 for (Iterator iterator = result.getPath().iterator(); iterator.hasNext(); ) { 095 RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next(); 096 if (nodeInstance.getName().equals("Acknowledge1")) { 097 ack1NodeInstance = nodeInstance; 098 break; 099 } 100 } 101 assertNotNull("Could not locate the Acknowledge1 node in the path.", ack1NodeInstance); 102 List<RouteNodeInstance> startNodes = new ArrayList<RouteNodeInstance>(); 103 startNodes.add(ack1NodeInstance); 104 criteria = new NodeGraphSearchCriteria(NodeGraphSearchCriteria.SEARCH_DIRECTION_BACKWARD, startNodes, "WorkflowDocument"); 105 result = routeNodeService.searchNodeGraph(criteria); 106 // since we started at 'Acknowledge1' there should just be 'Acknowledge1' and 'WorkflowDocument' in the path 107 assertEquals("Path should have 2 nodes.", 2, result.getPath().size()); 108 resultNodeInstance = result.getResultNodeInstance(); 109 assertNotNull("Should have a resulting node instance.", resultNodeInstance); 110 assertEquals("Result node should be the workflow document node.", "WorkflowDocument", resultNodeInstance.getName()); 111 } 112 113 @Test public void testSearchNodeGraphParallelBackward() throws Exception { 114 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "ParallelDocType"); 115 document.blanketApprove("", new String[] { "WorkflowDocument2", "WorkflowDocument3" }); 116 List activeNodeInstances = routeNodeService.getActiveNodeInstances(document.getDocumentId()); 117 assertEquals("Should be 2 active nodes.", 2, activeNodeInstances.size()); 118 Set<? extends String> nodeNames = TestUtilities.createNodeInstanceNameSet(activeNodeInstances); 119 assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("WorkflowDocument2")); 120 assertTrue("Should be at the WorkflowDocument3 node.", nodeNames.contains("WorkflowDocument3")); 121 122 123 // search backward to the adhoc node 124 NodeGraphSearchCriteria criteria = new NodeGraphSearchCriteria(NodeGraphSearchCriteria.SEARCH_DIRECTION_BACKWARD, activeNodeInstances, "AdHoc"); 125 NodeGraphSearchResult result = routeNodeService.searchNodeGraph(criteria); 126 assertEquals("Path should have eight nodes.", 8, result.getPath().size()); 127 RouteNodeInstance resultNodeInstance = result.getResultNodeInstance(); 128 assertNotNull("Should have a resulting node instance.", resultNodeInstance); 129 assertEquals("Result node should be the adhoc node.", "AdHoc", resultNodeInstance.getName()); 130 nodeNames = TestUtilities.createNodeInstanceNameSet(result.getPath()); 131 // the following nodes should be in the list of 8 132 assertTrue(nodeNames.contains("WorkflowDocument3")); 133 assertTrue(nodeNames.contains("WorkflowDocument5")); 134 assertTrue(nodeNames.contains("WorkflowDocument2")); 135 assertTrue(nodeNames.contains("Acknowledge1")); 136 assertTrue(nodeNames.contains("WorkflowDocument4")); 137 assertTrue(nodeNames.contains("Split")); 138 assertTrue(nodeNames.contains("WorkflowDocument")); 139 assertTrue(nodeNames.contains("AdHoc")); 140 141 // extract our active node instances 142 RouteNodeInstance workflowDocument2Node = null; 143 RouteNodeInstance workflowDocument3Node = null; 144 for (Iterator iterator = activeNodeInstances.iterator(); iterator.hasNext(); ) { 145 RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next(); 146 if (nodeInstance.getName().equals("WorkflowDocument2")) { 147 workflowDocument2Node = nodeInstance; 148 } else if (nodeInstance.getName().equals("WorkflowDocument3")) { 149 workflowDocument3Node = nodeInstance; 150 } 151 } 152 assertNotNull("Could not locate WorkflowDocument2 node.", workflowDocument2Node); 153 assertNotNull("Could not locate WorkflowDocument3 node.", workflowDocument3Node); 154 155 // now try searching backward for WorkflowDocument4 from WorkflowDocument2, this should keep us on the branch 156 List<RouteNodeInstance> startNodeInstances = new ArrayList<RouteNodeInstance>(); 157 startNodeInstances.add(workflowDocument2Node); 158 criteria = new NodeGraphSearchCriteria(NodeGraphSearchCriteria.SEARCH_DIRECTION_BACKWARD, activeNodeInstances, "WorkflowDocument4"); 159 result = routeNodeService.searchNodeGraph(criteria); 160 assertEquals("Path should have three nodes.", 3, result.getPath().size()); 161 resultNodeInstance = result.getResultNodeInstance(); 162 assertEquals("Result node should be the WorkflowDocument4 node.", "WorkflowDocument4", resultNodeInstance.getName()); 163 nodeNames = TestUtilities.createNodeInstanceNameSet(result.getPath()); 164 // the following nodes should be in the list of 3 165 assertTrue(nodeNames.contains("WorkflowDocument2")); 166 assertTrue(nodeNames.contains("Acknowledge1")); 167 assertTrue(nodeNames.contains("WorkflowDocument4")); 168 169 // try searching backward for WorkflowDocument5 170 startNodeInstances = new ArrayList<RouteNodeInstance>(); 171 startNodeInstances.add(workflowDocument3Node); 172 criteria = new NodeGraphSearchCriteria(NodeGraphSearchCriteria.SEARCH_DIRECTION_BACKWARD, activeNodeInstances, "WorkflowDocument5"); 173 result = routeNodeService.searchNodeGraph(criteria); 174 assertEquals("Path should have two nodes.", 2, result.getPath().size()); 175 resultNodeInstance = result.getResultNodeInstance(); 176 assertEquals("Result node should be the WorkflowDocument5 node.", "WorkflowDocument5", resultNodeInstance.getName()); 177 nodeNames = TestUtilities.createNodeInstanceNameSet(result.getPath()); 178 // the following nodes should be in the list of 2 179 assertTrue(nodeNames.contains("WorkflowDocument3")); 180 assertTrue(nodeNames.contains("WorkflowDocument5")); 181 } 182 183 /** 184 * currently searching forward does not work and needs to be implemented, we'll stub in a test 185 * that shows it throws an UnsupportedOperationException and then this test can be modified when the 186 * functionality is implemented. 187 */ 188 @Test public void testSearchNodeGraphForward() throws Exception { 189 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "SeqDocType"); 190 document.route(""); 191 List initialNodeInstances = KEWServiceLocator.getRouteNodeService().getInitialNodeInstances(document.getDocumentId()); 192 NodeGraphSearchCriteria criteria = new NodeGraphSearchCriteria(NodeGraphSearchCriteria.SEARCH_DIRECTION_FORWARD, initialNodeInstances, "WorkflowDocument"); 193 try { 194 routeNodeService.searchNodeGraph(criteria); 195 fail("Should have thrown UnsupportedOperationException"); 196 } catch (UnsupportedOperationException e) { 197 } 198 } 199 200}