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     */
016    package org.kuali.rice.kew.actions;
017    
018    import org.junit.Test;
019    import org.kuali.rice.kew.actionrequest.ActionRequestValue;
020    import org.kuali.rice.kew.api.KewApiServiceLocator;
021    import org.kuali.rice.kew.api.WorkflowDocument;
022    import org.kuali.rice.kew.api.WorkflowDocumentFactory;
023    import org.kuali.rice.kew.api.action.MovePoint;
024    import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
025    import org.kuali.rice.kew.api.document.WorkflowDocumentService;
026    import org.kuali.rice.kew.service.KEWServiceLocator;
027    import org.kuali.rice.kew.test.KEWTestCase;
028    import org.kuali.rice.kew.test.TestUtilities;
029    
030    import java.util.List;
031    import java.util.Set;
032    
033    import static org.junit.Assert.*;
034    
035    public class MoveDocumentTest extends KEWTestCase {
036    
037        protected void loadTestData() throws Exception {
038            loadXmlFile("ActionsConfig.xml");
039        }
040       
041        /**
042         * Tests that we can move a sequential document forward and backward.
043         *
044         */
045        @Test public void testMoveDocumentSequential() throws Exception {
046            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SeqSetup.DOCUMENT_TYPE_NAME);
047            document.route("");
048            
049            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
050            assertTrue("Bmcgough should have an approve.", document.isApprovalRequested());
051            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
052            assertTrue("Rkirkend should have an approve.", document.isApprovalRequested());
053            assertEquals("Should be at the WorkflowDocument Node.", SeqSetup.WORKFLOW_DOCUMENT_NODE, document.getNodeNames().iterator().next());
054            
055            // move the document forward one node
056            document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_NODE, 1), "");
057            
058            List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
059            assertEquals("Should be only 1 pending approve request to pmckown.", 1, actionRequests.size());
060            assertEquals("Should be at the WorkflowDocument2 Node.", SeqSetup.WORKFLOW_DOCUMENT_2_NODE, document.getNodeNames().iterator().next());
061            
062            // after moving the document forward, bmcgough and rkirkend should no longer have requests, but phil should
063            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
064            assertFalse("Bmcgough should NOT have an approve.", document.isApprovalRequested());
065            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
066            assertFalse("Rkirkend should NOT have an approve.", document.isApprovalRequested());
067            
068            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("pmckown"), document.getDocumentId());
069            assertTrue("Pmckown should have an approve.", document.isApprovalRequested());
070            ActionRequestValue pmckownRequest = (ActionRequestValue)actionRequests.get(0);
071            
072            // now try moving it to itself, effectively refreshing the node
073            document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_2_NODE, 0), "");
074            assertTrue("Pmckown should still have an approve.", document.isApprovalRequested());
075            actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
076            assertEquals("Should be only 1 pending approve request to pmckown.", 1, actionRequests.size());
077            assertEquals("Should be at the WorkflowDocument2 Node.", SeqSetup.WORKFLOW_DOCUMENT_2_NODE, document.getNodeNames().iterator().next());
078            
079            // since this should have invoked a refresh, let's ensure that the action request ids are different after the move
080            assertFalse("Action request ids should be different.", pmckownRequest.getActionRequestId().equals(((ActionRequestValue)actionRequests.get(0)).getActionRequestId()));
081            
082            // now try moving it back
083            document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_2_NODE, -1), "");
084            
085            // document should now be back at the WorkflowDocumentNode with requests to rkirkend and brian
086            actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
087            assertEquals("Should be 2 pending requests.", 2, actionRequests.size());
088            
089            assertEquals("Should be at the WorkflowDocument Node.", SeqSetup.WORKFLOW_DOCUMENT_NODE, document.getNodeNames().iterator().next());
090            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
091            assertTrue("Bmcgough should have an approve.", document.isApprovalRequested());
092            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
093            assertTrue("Rkirkend should have an approve.", document.isApprovalRequested());
094            
095            
096            // Let's do a sanity check to make sure we're still ENROUTE and move the doc to an ack node, rendering it PROCESSED,
097            // also, we'll check that there are no permissions enforced on the move document action by moving as a random user
098            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("xqi"), document.getDocumentId());
099            assertTrue("Doc should be ENROUTE.", document.isEnroute());
100            document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_NODE, 2), "");
101            assertTrue("Doc should be PROCESSED.", document.isProcessed());
102        }
103    
104        /**
105         * This tests that we can invoke the move document command inside of a sub process.
106         */
107        @Test public void testMoveDocumentInsideProcess() throws Exception {
108            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "MoveInProcessTest");
109            document.route("");
110            
111            // approve as bmcgough and rkirkend to move into process
112            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
113            assertTrue("bmcgough should have approve", document.isApprovalRequested());
114            document.approve("");
115            document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
116            assertTrue("rkirkend should have approve", document.isApprovalRequested());
117            document.approve("");
118    
119            WorkflowDocumentService workflowDocumentService = KewApiServiceLocator.getWorkflowDocumentService();
120            List<RouteNodeInstance> activeNodeInstances = workflowDocumentService.getActiveRouteNodeInstances(document.getDocumentId());
121            assertEquals("Should be 1 active node instance.", 1, activeNodeInstances.size());
122            RouteNodeInstance node2 = activeNodeInstances.get(0);
123            assertEquals("Should be at the WorkflowDocument2 node.", SeqSetup.WORKFLOW_DOCUMENT_2_NODE, node2.getName());
124            assertTrue("Node should be in a process.", node2.getProcessId() != null);
125            
126            // now try to move the document forward one which will keep us inside the subprocess
127            document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_2_NODE, 1), "");
128            
129            activeNodeInstances = workflowDocumentService.getActiveRouteNodeInstances(document.getDocumentId());
130            RouteNodeInstance node3 = activeNodeInstances.get(0);
131            assertEquals("Should be at the WorkflowDocument3 node.", SeqSetup.WORKFLOW_DOCUMENT_3_NODE, node3.getName());
132            assertTrue("Node should be in a process.", node3.getProcessId() != null);
133            assertEquals("Node 2 and 3 should be in the same process.", node2.getProcessId(), node3.getProcessId());
134            
135            document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_3_NODE, 0), "");
136            
137            document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_3_NODE, -1), "");
138        }
139        
140        @Test public void testMoveDocumentParallel() throws Exception {
141            WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
142            document.blanketApprove("", new String[] { ParallelSetup.WORKFLOW_DOCUMENT_2_B2_NODE, ParallelSetup.WORKFLOW_DOCUMENT_3_B1_NODE, ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE });
143            Set nodeNames = TestUtilities.createNodeInstanceNameSet(KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()));
144            assertEquals("There should be 3 active nodes.", 3, nodeNames.size());
145            assertTrue("Should be at WorkflowDocument3-B1", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_3_B1_NODE));
146            assertTrue("Should be at WorkflowDocument2-B2", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_2_B2_NODE));
147            assertTrue("Should be at WorkflowDocument4-B3", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE));
148            
149            // try to move the document from WorkflowDocument3-B1 to WorkflowDocument2-B1
150            document.move(MovePoint.create(ParallelSetup.WORKFLOW_DOCUMENT_3_B1_NODE, -1), "");
151            nodeNames = TestUtilities.createNodeInstanceNameSet(KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()));
152            assertEquals("There should be 3 active nodes.", 3, nodeNames.size());
153            assertTrue("Should be at WorkflowDocument2-B1", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE));
154            assertTrue("Should be at WorkflowDocument2-B2", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_2_B2_NODE));
155            assertTrue("Should be at WorkflowDocument4-B3", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE));
156        }
157        
158        private class SeqSetup {
159    
160            public static final String DOCUMENT_TYPE_NAME = "MoveSequentialTest";
161            public static final String ADHOC_NODE = "AdHoc";
162            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
163            public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
164            public static final String WORKFLOW_DOCUMENT_3_NODE = "WorkflowDocument3";
165            public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
166            public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
167            
168        }
169        
170        private class ParallelSetup {
171    
172            public static final String DOCUMENT_TYPE_NAME = "BlanketApproveParallelTest";
173            public static final String ADHOC_NODE = "AdHoc";
174            public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
175            public static final String WORKFLOW_DOCUMENT_2_B1_NODE = "WorkflowDocument2-B1";
176            public static final String WORKFLOW_DOCUMENT_2_B2_NODE = "WorkflowDocument2-B2";
177            public static final String WORKFLOW_DOCUMENT_3_B1_NODE = "WorkflowDocument3-B1";
178            public static final String WORKFLOW_DOCUMENT_3_B2_NODE = "WorkflowDocument3-B2";
179            public static final String WORKFLOW_DOCUMENT_4_B3_NODE = "WorkflowDocument4-B3";
180            public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
181            public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
182            public static final String JOIN_NODE = "Join";
183            public static final String SPLIT_NODE = "Split";
184            public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
185            
186        }
187       
188    }