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.rule.service.impl; 017 018 019 import static org.junit.Assert.assertEquals; 020 import static org.junit.Assert.assertTrue; 021 import static org.junit.Assert.fail; 022 023 import java.util.ArrayList; 024 import java.util.Iterator; 025 import java.util.List; 026 027 import org.junit.Test; 028 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 029 import org.kuali.rice.kew.actionrequest.ActionRequestValue; 030 import org.kuali.rice.kew.api.WorkflowDocument; 031 import org.kuali.rice.kew.api.WorkflowDocumentFactory; 032 import org.kuali.rice.kew.api.action.ActionRequestStatus; 033 import org.kuali.rice.kew.api.action.RecipientType; 034 import org.kuali.rice.kew.role.service.RoleService; 035 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 036 import org.kuali.rice.kew.routemodule.TestDocContent; 037 import org.kuali.rice.kew.routemodule.TestRecipient; 038 import org.kuali.rice.kew.routemodule.TestResponsibility; 039 import org.kuali.rice.kew.routemodule.TestRouteLevel; 040 import org.kuali.rice.kew.routemodule.TestRouteModuleXMLHelper; 041 import org.kuali.rice.kew.rule.TestRuleAttribute; 042 import org.kuali.rice.kew.service.KEWServiceLocator; 043 import org.kuali.rice.kew.test.KEWTestCase; 044 import org.kuali.rice.kew.api.KewApiConstants; 045 import org.kuali.rice.kim.api.identity.principal.Principal; 046 047 /** 048 * Tests the role re-resolving. This test depends on the route queue being synchronous. 049 */ 050 public class RoleServiceTest extends KEWTestCase { 051 052 private static final String TEST_ROLE = "TestRole"; 053 private static final String TEST_GROUP_1 = "TestGroup1"; 054 private static final String TEST_GROUP_2 = "TestGroup2"; 055 private RoleService roleService; 056 private String documentId; 057 private List<String> group1 = new ArrayList<String>(); 058 private List<String> group2 = new ArrayList<String>(); 059 060 061 protected void setUpAfterDataLoad() throws Exception { 062 super.setUpAfterDataLoad(); 063 roleService = KEWServiceLocator.getRoleService(); 064 initializeAttribute(); 065 documentId = routeDocument(); 066 } 067 068 private void initializeAttribute() throws Exception { 069 group1.add(getPrincipalIdForName("jhopf")); 070 group1.add(getPrincipalIdForName("pmckown")); 071 group2.add(getPrincipalIdForName("xqi")); 072 group2.add(getPrincipalIdForName("tbazler")); 073 TestRuleAttribute.addRole(TEST_ROLE); 074 TestRuleAttribute.addQualifiedRole(TEST_ROLE, TEST_GROUP_1); 075 TestRuleAttribute.addQualifiedRole(TEST_ROLE, TEST_GROUP_2); 076 TestRuleAttribute.setRecipientPrincipalIds(TEST_ROLE, TEST_GROUP_1, group1); 077 TestRuleAttribute.setRecipientPrincipalIds(TEST_ROLE, TEST_GROUP_2, group2); 078 } 079 080 private String routeDocument() throws Exception { 081 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "TestDocumentType"); 082 document.setApplicationContent(TestRouteModuleXMLHelper.toXML(generateDocContent())); 083 document.route("testing only"); 084 return document.getDocumentId(); 085 } 086 087 @Test public void testReResolveQualifiedRole() throws Exception { 088 DocumentRouteHeaderValue loadedDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId); 089 assertEquals(KewApiConstants.ROUTE_HEADER_ENROUTE_CD, loadedDocument.getDocRouteStatus()); 090 List requests = getTestRoleRequests(loadedDocument); 091 assertEquals("Incorrect number of role control requests.", 2, requests.size()); 092 assertRequestGraphs(requests); 093 094 // change the membership in TEST_GROUP_1 095 List<String> newGroup1Recipients = new ArrayList<String>(); 096 newGroup1Recipients.add(getPrincipalIdForName("bmcgough")); 097 newGroup1Recipients.add(getPrincipalIdForName("xqi")); 098 newGroup1Recipients.add(getPrincipalIdForName("rkirkend")); 099 TestRuleAttribute.setRecipientPrincipalIds(TEST_ROLE, TEST_GROUP_1, newGroup1Recipients); 100 roleService.reResolveQualifiedRole(loadedDocument, TEST_ROLE, TEST_GROUP_1); 101 loadedDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId); 102 assertEquals(KewApiConstants.ROUTE_HEADER_ENROUTE_CD, loadedDocument.getDocRouteStatus()); 103 requests = getTestRoleRequests(loadedDocument); 104 // rkirkend is the initiator so his action should count for the TEST_GROUP_1 role after re-resolving, leaving only a single role request 105 assertEquals("Incorrect number of role control requests.", 1, requests.size()); 106 assertRequestGraphs(requests); 107 assertInitiatorRequestDone(TEST_ROLE, TEST_GROUP_1); 108 109 // if we attempt to re-resolve with an non-existant qualified role, it _should_ be legal 110 roleService.reResolveQualifiedRole(loadedDocument, TEST_ROLE, "random cool name"); 111 requests = getTestRoleRequests(loadedDocument); 112 assertEquals("Incorrect number of role control requests.", 1, requests.size()); 113 assertRequestGraphs(requests); 114 } 115 116 @Test public void testReResolveQualifiedRoleErrors() throws Exception { 117 // attempting to re-resolve with null values should throw exceptions 118 try { 119 roleService.reResolveQualifiedRole((DocumentRouteHeaderValue)null, null, null); 120 fail("Exception should have been thrown when null values are passed."); 121 } catch (Exception e) {} 122 123 DocumentRouteHeaderValue loadedDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId); 124 try { 125 roleService.reResolveQualifiedRole(loadedDocument, null, null); 126 fail("Exception should have been thrown when null values are passed."); 127 } catch (Exception e) {} 128 129 // need to have a valid role name 130 try { 131 roleService.reResolveQualifiedRole(loadedDocument, "GimpyRoleName", TEST_GROUP_1); 132 fail("Exception should be thrown when attempting to re-resolve with a bad role name."); 133 } catch (Exception e) {} 134 135 // now blanket approve a document to make it processed 136 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "TestDocumentType"); 137 document.setApplicationContent(TestRouteModuleXMLHelper.toXML(generateDocContent())); 138 document.blanketApprove(""); 139 DocumentRouteHeaderValue baDoc = KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()); 140 try { 141 roleService.reResolveQualifiedRole(baDoc, TEST_ROLE, TEST_GROUP_1); 142 fail("Shouldn't be able to resolve on a document with no active nodes."); 143 } catch (Exception e) {} 144 145 } 146 147 @Test public void testReResolveRole() throws Exception { 148 DocumentRouteHeaderValue loadedDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId); 149 assertEquals(KewApiConstants.ROUTE_HEADER_ENROUTE_CD, loadedDocument.getDocRouteStatus()); 150 List requests = getTestRoleRequests(loadedDocument); 151 assertEquals("Incorrect number of role control requests.", 2, requests.size()); 152 assertRequestGraphs(requests); 153 154 // change membership in TEST_GROUP_1 and TEST_GROUP_2 155 List<String> newGroup1 = new ArrayList<String>(); 156 List<String> newGroup2 = new ArrayList<String>(); 157 newGroup2.add(getPrincipalIdForName("ewestfal")); 158 newGroup2.add(getPrincipalIdForName("jthomas")); 159 // TEST_GROUP_1 should now be an empty role, therefore there should not be a request generated for it after re-resolution 160 TestRuleAttribute.setRecipientPrincipalIds(TEST_ROLE, TEST_GROUP_1, newGroup1); 161 TestRuleAttribute.setRecipientPrincipalIds(TEST_ROLE, TEST_GROUP_2, newGroup2); 162 // re-resolve entire role 163 roleService.reResolveRole(loadedDocument, TEST_ROLE); 164 loadedDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId); 165 assertEquals(KewApiConstants.ROUTE_HEADER_ENROUTE_CD, loadedDocument.getDocRouteStatus()); 166 requests = getTestRoleRequests(loadedDocument); 167 // should be 1 because group 1 has no members 168 assertEquals("Incorrect number of role control requests.", 1, requests.size()); 169 assertRequestGraphs(requests); 170 } 171 172 @Test public void testReResolveRoleErrors() throws Exception { 173 // attempting to re-resolve with null values should throw exceptions 174 try { 175 roleService.reResolveRole((DocumentRouteHeaderValue)null, null); 176 fail("Exception should have been thrown when null values are passed."); 177 } catch (RiceIllegalArgumentException e) {} 178 179 DocumentRouteHeaderValue loadedDocument = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId); 180 try { 181 roleService.reResolveRole(loadedDocument, null); 182 fail("Exception should have been thrown when null values are passed."); 183 } catch (Exception e) {} 184 185 // need to have a valid role name 186 try { 187 roleService.reResolveRole(loadedDocument, "GimpyRoleName"); 188 fail("Exception should be thrown when attempting to re-resolve with a bad role name."); 189 } catch (Exception e) {} 190 191 // now blanket approve a document to make it processed 192 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("rkirkend"), "TestDocumentType"); 193 document.setApplicationContent(TestRouteModuleXMLHelper.toXML(generateDocContent())); 194 document.blanketApprove(""); 195 DocumentRouteHeaderValue baDoc = KEWServiceLocator.getRouteHeaderService().getRouteHeader(document.getDocumentId()); 196 try { 197 roleService.reResolveRole(baDoc, TEST_ROLE); 198 fail("Shouldn't be able to re-resolve on a document with no active nodes."); 199 } catch (Exception e) {} 200 } 201 202 /** 203 * Extract requests sent to TestRole. 204 */ 205 private List getTestRoleRequests(DocumentRouteHeaderValue document) { 206 List testRoleRequests = new ArrayList(); 207 List requests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocIdAtRouteLevel(document.getDocumentId(), document.getDocRouteLevel()); 208 for (Iterator iterator = requests.iterator(); iterator.hasNext();) { 209 ActionRequestValue actionRequest = (ActionRequestValue) iterator.next(); 210 if (TEST_ROLE.equals(actionRequest.getRoleName())) { 211 testRoleRequests.add(actionRequest); 212 } 213 } 214 return testRoleRequests; 215 } 216 217 private void assertRequestGraphs(List requests) throws Exception { 218 for (Iterator iterator = requests.iterator(); iterator.hasNext();) { 219 ActionRequestValue request = (ActionRequestValue) iterator.next(); 220 if (TEST_GROUP_1.equals(request.getQualifiedRoleName())) { 221 assertQualifiedRoleRequest(request, TEST_ROLE, TEST_GROUP_1); 222 } else if (TEST_GROUP_2.equals(request.getQualifiedRoleName())) { 223 assertQualifiedRoleRequest(request, TEST_ROLE, TEST_GROUP_2); 224 } 225 } 226 } 227 228 private void assertQualifiedRoleRequest(ActionRequestValue request, String roleName, String qualifiedRoleName) throws Exception { 229 assertActionRequest(request, roleName, qualifiedRoleName); 230 List<String> recipients = TestRuleAttribute.getRecipientPrincipalIds(roleName, qualifiedRoleName); 231 assertEquals("Incorrect number of children requests.", recipients.size(), request.getChildrenRequests().size()); 232 for (Iterator childIt = request.getChildrenRequests().iterator(); childIt.hasNext();) { 233 ActionRequestValue childRequest = (ActionRequestValue) childIt.next(); 234 assertActionRequest(childRequest, roleName, qualifiedRoleName); 235 assertTrue("Child request to invalid user: "+childRequest.getPrincipalId(), containsUser(recipients, childRequest.getPrincipalId())); 236 assertEquals("Child request should have no children.", 0, childRequest.getChildrenRequests().size()); 237 } 238 } 239 240 private void assertActionRequest(ActionRequestValue request, String roleName, String qualifiedRoleName) { 241 assertEquals("Incorrect role name.", roleName, request.getRoleName()); 242 assertEquals("Incorrect qualified role name.", qualifiedRoleName, request.getQualifiedRoleName()); 243 assertEquals("Incorrect qualified role name label.", qualifiedRoleName, request.getQualifiedRoleNameLabel()); 244 assertTrue("Request should be activated or done.", ActionRequestStatus.ACTIVATED.getCode().equals(request.getStatus()) || 245 ActionRequestStatus.DONE.getCode().equals(request.getStatus())); 246 } 247 248 private boolean containsUser(List<String> principalIds, String principalId) throws Exception { 249 return principalIds.contains(principalId); 250 } 251 252 /** 253 * Gets all "DONE" action requests that are to the initiator (rkirkend). It then verifies that the initiator has a 254 * complete request and a re-resolved request. 255 */ 256 private void assertInitiatorRequestDone(String roleName, String qualifiedRoleNameLabel) throws Exception { 257 Principal initiator = KEWServiceLocator.getIdentityHelperService().getPrincipalByPrincipalName("rkirkend"); 258 List requests = KEWServiceLocator.getActionRequestService().findByStatusAndDocId(ActionRequestStatus.DONE.getCode(), documentId); 259 for (Iterator iterator = requests.iterator(); iterator.hasNext();) { 260 ActionRequestValue request = (ActionRequestValue) iterator.next(); 261 if (!initiator.getPrincipalId().equals(request.getPrincipalId())) { 262 iterator.remove(); 263 } 264 } 265 assertEquals("Initiator should have a complete request and their re-resolved request.", 2, requests.size()); 266 int roleRequestCount = 0; 267 for (Iterator iterator = requests.iterator(); iterator.hasNext();) { 268 ActionRequestValue actionRequest = (ActionRequestValue) iterator.next(); 269 if (TEST_ROLE.equals(actionRequest.getRoleName())) { 270 roleRequestCount++; 271 assertActionRequest(actionRequest, roleName, qualifiedRoleNameLabel); 272 assertTrue("Initiator request should have a parent.", actionRequest.getParentActionRequest() != null); 273 } 274 } 275 assertEquals("There should be 1 DONE request from the result of the role re-resolve.", 1, roleRequestCount); 276 } 277 278 private TestDocContent generateDocContent() { 279 TestDocContent docContent = new TestDocContent(); 280 List routeLevels = new ArrayList(); 281 TestRouteLevel routeLevel1 = new TestRouteLevel(); 282 routeLevels.add(routeLevel1); 283 docContent.setRouteLevels(routeLevels); 284 routeLevel1.setPriority(1); 285 List responsibilities = new ArrayList(); 286 routeLevel1.setResponsibilities(responsibilities); 287 TestResponsibility responsibility1 = new TestResponsibility(); 288 responsibility1.setActionRequested(KewApiConstants.ACTION_REQUEST_APPROVE_REQ); 289 responsibility1.setPriority(1); 290 TestRecipient recipient1 = new TestRecipient(); 291 recipient1.setId(getPrincipalIdForName("rkirkend")); 292 recipient1.setType(RecipientType.PRINCIPAL.getCode()); 293 responsibility1.setRecipient(recipient1); 294 responsibilities.add(responsibility1); 295 return docContent; 296 } 297 298 }