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}