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.actions; 017 018 import org.junit.Test; 019 import org.kuali.rice.kew.api.KewApiServiceLocator; 020 import org.kuali.rice.kew.api.WorkflowDocument; 021 import org.kuali.rice.kew.api.WorkflowDocumentFactory; 022 import org.kuali.rice.kew.api.action.ActionRequest; 023 import org.kuali.rice.kew.api.action.ActionRequestType; 024 import org.kuali.rice.kew.api.action.AdHocRevoke; 025 import org.kuali.rice.kew.api.action.InvalidActionTakenException; 026 import org.kuali.rice.kew.api.exception.WorkflowException; 027 import org.kuali.rice.kew.service.KEWServiceLocator; 028 import org.kuali.rice.kew.test.KEWTestCase; 029 import org.kuali.rice.kew.test.TestUtilities; 030 import org.kuali.rice.kew.api.KewApiConstants; 031 import org.kuali.rice.kim.api.KimConstants; 032 033 import java.util.Collection; 034 import java.util.List; 035 036 import static org.junit.Assert.*; 037 038 public class RevokeAdHocActionTest extends KEWTestCase { 039 040 private static final String ADH0C_DOC = "AdhocRouteTest"; 041 private String docId; 042 043 protected void loadTestData() throws Exception { 044 loadXmlFile("ActionsConfig.xml"); 045 } 046 047 /** 048 * Tests revoking by action request id. 049 */ 050 @Test public void testRevokeByActionRequestId() throws Exception { 051 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), ADH0C_DOC); 052 docId = doc.getDocumentId(); 053 doc.adHocToPrincipal(ActionRequestType.APPROVE, "AdHoc", "annotation1", getPrincipalIdForName("dewey"), "respDesc1", false); 054 055 // check the action requests 056 TestUtilities.assertNumberOfPendingRequests(docId, 1); 057 TestUtilities.assertUserHasPendingRequest(docId, "dewey"); 058 059 // now revoke by a bad action request id, we should recieve a WorkflowException 060 try { 061 doc.revokeAdHocRequestById("123456789", ""); 062 fail("Revoking by a bad action request id should have thrown an exception!"); 063 } catch (InvalidActionTakenException e) {} 064 065 // revoke by the real action request id 066 List<ActionRequest> actionRequestVOs = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(docId); 067 assertEquals(1, actionRequestVOs.size()); 068 String actionRequestId = actionRequestVOs.get(0).getId(); 069 doc.revokeAdHocRequestById(actionRequestId, ""); 070 071 // there should now be no pending requests 072 TestUtilities.assertNumberOfPendingRequests(docId, 0); 073 074 // route the document, this doc type is configured to route to user1 075 doc.route(""); 076 doc = getDocument("user1"); 077 assertTrue(doc.isApprovalRequested()); 078 079 // now attempt to revoke this non-adhoc request by id, it should throw an error 080 actionRequestVOs = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(docId); 081 for (int index = 0; index < actionRequestVOs.size(); index++) { 082 if (actionRequestVOs.get(index).isPending()) { 083 try { 084 doc.revokeAdHocRequestById(actionRequestVOs.get(index).getId().toString(), ""); 085 fail("Attempted to revoke by an invalid action request id, should have thrown an error!"); 086 } catch (InvalidActionTakenException e) {} 087 } 088 } 089 090 } 091 092 /** 093 * Tests revoking by user and workgroup. 094 */ 095 @Test public void testRevokeByUserAndGroup() throws Exception { 096 // ad hoc the document to dewey (twice) and the workgroup WorkflowAdmin 097 WorkflowDocument doc =WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), ADH0C_DOC); 098 docId = doc.getDocumentId(); 099 String principalId = getPrincipalIdForName("dewey"); 100 doc.adHocToPrincipal(ActionRequestType.APPROVE, "AdHoc", "annotationDewey1", principalId, "respDesc1", false); 101 doc.adHocToPrincipal(ActionRequestType.APPROVE, "AdHoc", "annotationDewey2", principalId, "respDesc1", false); 102 String groupId = getGroupIdForName(KimConstants.KIM_GROUP_WORKFLOW_NAMESPACE_CODE, "WorkflowAdmin"); 103 doc.adHocToGroup(ActionRequestType.APPROVE, "AdHoc", "Annotation WorkflowAdmin", groupId, "respDesc2", true); 104 105 TestUtilities.assertNumberOfPendingRequests(docId, 3); 106 TestUtilities.assertUserHasPendingRequest(docId, "dewey"); 107 TestUtilities.assertUserHasPendingRequest(docId, "quickstart"); 108 109 // route the document, this should activate the ad hoc requests 110 doc.route(""); 111 assertTrue(doc.isEnroute()); 112 TestUtilities.assertAtNodeNew(doc, "AdHoc"); 113 TestUtilities.assertNumberOfPendingRequests(docId, 3); 114 115 String testGroupId = getGroupIdForName(KimConstants.KIM_GROUP_WORKFLOW_NAMESPACE_CODE, "TestWorkgroup"); 116 // try revoking by a user and workgroup without adhoc requests, it should effectively be a no-op 117 AdHocRevoke revoke = AdHocRevoke.createRevokeFromPrincipal(getPrincipalIdForName("ewestfal")); 118 doc.revokeAdHocRequests(revoke, "This should be a no-op"); 119 revoke = AdHocRevoke.createRevokeFromGroup(testGroupId); 120 doc.revokeAdHocRequests(revoke, "This should be a no-op"); 121 doc = getDocument("rkirkend"); 122 TestUtilities.assertNumberOfPendingRequests(docId, 3); 123 TestUtilities.assertUserHasPendingRequest(docId, "dewey"); 124 TestUtilities.assertUserHasPendingRequest(docId, "quickstart"); 125 126 // now revoke each request in turn, after the second one is invoked the document should transition to it's next route level 127 // and route to user1 128 revoke = AdHocRevoke.createRevokeFromPrincipal(getPrincipalIdForName("dewey")); 129 doc.revokeAdHocRequests(revoke, "revokeUser"); 130 TestUtilities.assertNumberOfPendingRequests(docId, 1); 131 doc = getDocument("dewey"); 132 assertFalse("dewey should no longer have an approve request.", doc.isApprovalRequested()); 133 revoke = AdHocRevoke.createRevokeFromGroup(groupId); 134 doc.revokeAdHocRequests(revoke, "revokeWorkgroup"); 135 136 // the doc should now transition to the next node 137 doc = getDocument("user1"); 138 TestUtilities.assertAtNodeNew(doc, "One"); 139 assertTrue("user1 should have an approve request.", doc.isApprovalRequested()); 140 doc.approve(""); 141 142 // doc should now be final 143 assertTrue("doc should be final", doc.isFinal()); 144 } 145 146 /** 147 * Tests revoking by node name. 148 */ 149 @Test public void testRevokeByNodeName() throws Exception { 150 // ad hoc requests at the AdHoc node and then revoke the entire node 151 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), ADH0C_DOC); 152 docId = doc.getDocumentId(); 153 doc.adHocToPrincipal(ActionRequestType.APPROVE, "AdHoc", "annotationDewey1", getPrincipalIdForName("dewey"), "respDesc1", false); 154 String groupId = getGroupIdForName(KimConstants.KIM_GROUP_WORKFLOW_NAMESPACE_CODE, "WorkflowAdmin"); 155 doc.adHocToGroup(ActionRequestType.APPROVE, "AdHoc", "Annotation WorkflowAdmin", groupId, "respDesc2", true); 156 TestUtilities.assertNumberOfPendingRequests(docId, 2); 157 158 // now revoke the node 159 doc.revokeAdHocRequests(AdHocRevoke.createRevokeAtNode("AdHoc"), ""); 160 TestUtilities.assertNumberOfPendingRequests(docId, 0); 161 // send an Acknowledge to the AdHoc node prior to routing 162 doc.adHocToPrincipal(ActionRequestType.ACKNOWLEDGE, "AdHoc", "annotationEwestfal1", getPrincipalIdForName("ewestfal"), "respDesc1", false); 163 164 // route the document 165 doc = getDocument("rkirkend"); 166 doc.route(""); 167 TestUtilities.assertAtNodeNew(doc, "One"); 168 169 // ewestfal should have an acknowledge request 170 doc = getDocument("ewestfal"); 171 assertTrue(doc.isAcknowledgeRequested()); 172 173 // approve the document, it should go PROCESSED 174 doc = getDocument("user1"); 175 assertTrue(doc.isApprovalRequested()); 176 doc.approve(""); 177 assertTrue(doc.isProcessed()); 178 179 // revoke at the "One" node where there are no requests, it should be a no-op (the document should stay processed) 180 doc.revokeAdHocRequests(AdHocRevoke.createRevokeAtNode("One"), ""); 181 doc = getDocument("ewestfal"); 182 assertTrue(doc.isProcessed()); 183 184 // now revoke the ACKNOWLEDGE to ewestfal by revoking at the "AdHoc" node, the document should go FINAL 185 doc.revokeAdHocRequests(AdHocRevoke.createRevokeAtNode("AdHoc"), ""); 186 doc = getDocument("ewestfal"); 187 assertTrue(doc.isFinal()); 188 } 189 190 /** 191 * Tests the behavior revocation of ad hoc requests prior to the routing of the document. 192 * 193 * @throws Exception 194 */ 195 @Test public void testRevokePriorToRouting() throws Exception { 196 // ad hoc the document to dewey and the workgroup WorkflowAdmin 197 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), ADH0C_DOC); 198 docId = doc.getDocumentId(); 199 doc.adHocToPrincipal(ActionRequestType.APPROVE, "AdHoc", "annotation1", getPrincipalIdForName("dewey"), "respDesc1", false); 200 201 doc = getDocument("dewey"); 202 assertFalse("User andlee should not have an approve request yet. Document not yet routed.", doc.isApprovalRequested()); 203 String groupId = getGroupIdForName(KimConstants.KIM_GROUP_WORKFLOW_NAMESPACE_CODE, "WorkflowAdmin"); 204 doc.adHocToGroup(ActionRequestType.APPROVE, "AdHoc", "annotation2", groupId , "respDesc2", true); 205 doc = getDocument("quickstart"); 206 assertFalse("User should not have approve request yet. Document not yet routed.", doc.isApprovalRequested()); 207 208 // the document should be initiated at this point 209 assertTrue("Document should still be intitiated.", doc.isInitiated()); 210 211 // check and revoke the actual ActionRequestVOs 212 // reaquire the document as the initiator 213 doc = getDocument("rkirkend"); 214 List<ActionRequest> actionRequestVOs = KewApiServiceLocator.getWorkflowDocumentService().getRootActionRequests(doc.getDocumentId()); 215 assertEquals("There should be 2 ad hoc requests.", 2, actionRequestVOs.size()); 216 for (ActionRequest requestVO : actionRequestVOs) { 217 assertTrue("Should be an ad hoc request.", requestVO.isAdHocRequest()); 218 // revoke by id 219 doc.revokeAdHocRequestById(requestVO.getId().toString(), ""); 220 } 221 222 // now the document should have no pending action requests on it 223 List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(docId); 224 assertEquals("There should be no pending requests.", 0, actionRequests.size()); 225 226 // check that the "ActionTakens" have been properly recorded 227 Collection actionTakens = KEWServiceLocator.getActionTakenService().findByDocIdAndAction(docId, KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD); 228 assertEquals("There should be 2 'AdHocRevoked' action takens", 2, actionTakens.size()); 229 230 // now check that the document is still intiated 231 doc = getDocument("rkirkend"); 232 assertTrue("Document should still be intitiated.", doc.isInitiated()); 233 } 234 235 /** 236 * Tests the revocation of ad hoc requests after a blanket approve. The goal of this test is to verify that revocation of 237 * ad hoc requests doesn't have any adverse effects on the notification requests 238 */ 239 @Test public void testRevokeAfterBlanketApprove() throws Exception { 240 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), ADH0C_DOC); 241 docId = doc.getDocumentId(); 242 // send an FYI to the AdHoc node prior to blanket approving 243 doc.adHocToPrincipal(ActionRequestType.FYI, "AdHoc", "annotationEwestfal1", getPrincipalIdForName("ewestfal"), "respDesc1", false); 244 245 // blanket approve the document 246 doc.blanketApprove(""); 247 assertTrue(doc.isProcessed()); 248 249 // ewestfal should have his ad hoc FYI and user1 should have an ack from the blanket approve 250 doc = getDocument("ewestfal"); 251 assertTrue(doc.isFYIRequested()); 252 doc = getDocument("user1"); 253 assertTrue(doc.isAcknowledgeRequested()); 254 255 // revoke all ad hoc requests 256 doc.revokeAllAdHocRequests("revoking all adhocs"); 257 assertTrue(doc.isProcessed()); 258 TestUtilities.assertNumberOfPendingRequests(docId, 1); 259 260 // user1 should still have acknowledge request 261 assertTrue(doc.isAcknowledgeRequested()); 262 263 // ewestfal should no longer have an fyi 264 doc = getDocument("ewestfal"); 265 assertFalse(doc.isFYIRequested()); 266 } 267 268 private WorkflowDocument getDocument(String netid) throws WorkflowException { 269 return WorkflowDocumentFactory.loadDocument(getPrincipalIdForName(netid), docId); 270 } 271 272 }