001/** 002 * Copyright 2004-2015 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.impl.peopleflow; 017 018import org.apache.commons.collections.CollectionUtils; 019import org.apache.commons.lang.StringUtils; 020import org.kuali.rice.core.api.CoreConstants; 021import org.kuali.rice.core.api.config.ConfigurationException; 022import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 023import org.kuali.rice.core.api.exception.RiceIllegalStateException; 024import org.kuali.rice.core.api.membership.MemberType; 025import org.kuali.rice.core.api.util.VersionHelper; 026import org.kuali.rice.kew.actionrequest.ActionRequestFactory; 027import org.kuali.rice.kew.actionrequest.ActionRequestValue; 028import org.kuali.rice.kew.actionrequest.KimGroupRecipient; 029import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient; 030import org.kuali.rice.kew.actionrequest.Recipient; 031import org.kuali.rice.kew.api.action.ActionRequestPolicy; 032import org.kuali.rice.kew.api.action.ActionRequestType; 033import org.kuali.rice.kew.api.action.RecipientType; 034import org.kuali.rice.kew.api.document.Document; 035import org.kuali.rice.kew.api.document.DocumentContent; 036import org.kuali.rice.kew.api.peopleflow.PeopleFlowDefinition; 037import org.kuali.rice.kew.api.peopleflow.PeopleFlowDelegate; 038import org.kuali.rice.kew.api.peopleflow.PeopleFlowMember; 039import org.kuali.rice.kew.api.repository.type.KewTypeDefinition; 040import org.kuali.rice.kew.api.repository.type.KewTypeRepositoryService; 041import org.kuali.rice.kew.engine.RouteContext; 042import org.kuali.rice.kew.framework.peopleflow.PeopleFlowTypeService; 043import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 044import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValueContent; 045import org.kuali.rice.kim.api.group.Group; 046import org.kuali.rice.kim.api.identity.principal.Principal; 047import org.kuali.rice.kim.api.role.Role; 048import org.kuali.rice.kim.api.role.RoleMembership; 049import org.kuali.rice.kim.api.role.RoleService; 050import org.kuali.rice.kim.api.services.KimApiServiceLocator; 051import org.kuali.rice.ksb.api.KsbApiServiceLocator; 052import org.kuali.rice.ksb.api.bus.Endpoint; 053 054import javax.xml.namespace.QName; 055import java.util.ArrayList; 056import java.util.Collections; 057import java.util.List; 058import java.util.Map; 059 060/** 061 * Reference implementation of the {@code PeopleFlowRequestGenerator} which is responsible for generating Action 062 * Requests from a {@link PeopleFlowDefinition}. 063 * 064 * @author Kuali Rice Team (rice.collab@kuali.org) 065 */ 066public class PeopleFlowRequestGeneratorImpl implements PeopleFlowRequestGenerator { 067 068 private KewTypeRepositoryService typeRepositoryService; 069 private RoleService roleService; 070 071 @Override 072 public List<ActionRequestValue> generateRequests(RouteContext routeContext, PeopleFlowDefinition peopleFlow, ActionRequestType actionRequested) { 073 Context context = new Context(routeContext, peopleFlow, actionRequested); 074 for (PeopleFlowMember member : peopleFlow.getMembers()) { 075 generateRequestForMember(context, member); 076 } 077 078 return context.getActionRequestFactory().getRequestGraphs(); 079 } 080 081 protected void generateRequestForMember(Context context, PeopleFlowMember member) { 082 // used later for generating any delegate requests 083 List<ActionRequestValue> memberRequests = new ArrayList<ActionRequestValue>(); 084 085 if (MemberType.ROLE == member.getMemberType()) { 086 memberRequests.addAll(findNonRoleRequests(generateRequestsForRoleMember(context, member))); 087 } else { 088 ActionRequestValue actionRequest = context.getActionRequestFactory().addRootActionRequest( 089 context.getActionRequested().getCode(), member.getPriority(), toRecipient(member), "", 090 member.getResponsibilityId(), Boolean.TRUE, getActionRequestPolicyCode(member), null); 091 092 if (actionRequest != null) { 093 memberRequests.add(actionRequest); 094 } 095 } 096 097 // KULRICE-5726: Add support for delegates on roles in PeopleFlows as well as using roles as delegates 098 generateDelegationRequests(context, memberRequests, member); 099 } 100 101 /** 102 * generates requests for a PeopleFlow member of type Role. 103 * 104 * <p>Will resolve role qualifiers through the appropriate PeopleFlowTypeService, and if multiple qualifier maps are 105 * generated, it can generate multiple request trees. 106 * parent requests</p> 107 * 108 * @param context the context for request generation 109 * @param member the PeopleFlow member, which is assumed to be of MemberType ROLE 110 * @return a list of root action requests that were generated, or an empty list if no role members were resolved 111 */ 112 protected List<ActionRequestValue> generateRequestsForRoleMember(Context context, PeopleFlowMember member) { 113 List<ActionRequestValue> roleMemberRequests = new ArrayList<ActionRequestValue>(); // results 114 115 List<Map<String, String>> roleQualifierMaps = loadRoleQualifiers(context, member.getMemberId()); 116 Role role = getRoleService().getRole(member.getMemberId()); 117 118 boolean hasPeopleFlowDelegates = !CollectionUtils.isEmpty(member.getDelegates()); 119 120 if (role == null) { 121 throw new IllegalStateException("Failed to locate a role with the given role id of '" + 122 member.getMemberId() + "'"); 123 } 124 125 if (CollectionUtils.isEmpty(roleQualifierMaps)) { 126 ActionRequestValue request = addKimRoleRequest(context, member, role, Collections.<String, String>emptyMap(), 127 hasPeopleFlowDelegates); 128 129 if (request != null) { 130 roleMemberRequests.add(request); 131 if (hasPeopleFlowDelegates) { 132 for (PeopleFlowDelegate delegate : member.getDelegates()) { 133 if (MemberType.ROLE.equals(delegate.getMemberType())) { 134 Role delegateRole = getRoleService().getRole(delegate.getMemberId()); 135 if (delegateRole != null) { 136 //generateDelegationToRoleRequests(context, request, member, delegate, Collections.<String, String>emptyMap()); 137 addKimRoleDelegateRequest(context, request, member, delegate, delegateRole, Collections.<String, String>emptyMap()); 138 } 139 } 140 } 141 } 142 } 143 144 } else { 145 // we may have multiple maps of role qualifiers, so we'll add a request for each map 146 for (Map<String, String> roleQualifiers : roleQualifierMaps) { 147 ActionRequestValue request = addKimRoleRequest(context, member, role, roleQualifiers, 148 hasPeopleFlowDelegates); 149 if (request != null) { 150 roleMemberRequests.add(request); 151 if (hasPeopleFlowDelegates) { 152 for (PeopleFlowDelegate delegate : member.getDelegates()) { 153 if (MemberType.ROLE.equals(delegate.getMemberType())) { 154 Role delegateRole = getRoleService().getRole(delegate.getMemberId()); 155 if (delegateRole != null) { 156 //generateDelegationToRoleRequests(context, request, member, delegate, roleQualifiers); 157 addKimRoleDelegateRequest(context, request, member, delegate, delegateRole, roleQualifiers); 158 } 159 } 160 } 161 } 162 } 163 } 164 } 165 166 return roleMemberRequests; 167 } 168 169 /** 170 * Uses the ActionRequestFactory to build the request tree for the role members. 171 * 172 * <p>The role members themselves are derived here using the given qualifiers.</p> 173 * 174 * @param context the context for request generation 175 * @param member the PeopleFlow member 176 * @param role the role specified within the member 177 * @param roleQualifiers the qualifiers to use for role member selection 178 * @param ignoreKimDelegates should KIM delegates be ignored when generating requests? 179 * @return the root request of the generated action request tree, or null if no members are found 180 */ 181 private ActionRequestValue addKimRoleRequest(Context context, PeopleFlowMember member, Role role, 182 Map<String, String> roleQualifiers, boolean ignoreKimDelegates) { 183 184 ActionRequestValue roleMemberRequest = null; 185 186 List<RoleMembership> memberships = getRoleService().getRoleMembers(Collections.singletonList( 187 member.getMemberId()), roleQualifiers); 188 189 String actionRequestPolicyCode = getActionRequestPolicyCode(member); 190 191 if (!CollectionUtils.isEmpty(memberships)) { 192 roleMemberRequest = context.getActionRequestFactory().addKimRoleRequest( 193 context.getActionRequested().getCode(), member.getPriority(), role, memberships, null, 194 member.getResponsibilityId(), true, actionRequestPolicyCode, null, ignoreKimDelegates); 195 //memberships.get(0).getQualifier() 196 } 197 198 return roleMemberRequest; 199 } 200 201 /** 202 * Generates any needed requests for {@link PeopleFlowDelegate}s on the given member. 203 * 204 * <p>If there are no delegates, or if no requests were generated for the member, then this will be a no-op.</p> 205 * 206 * @param context the context for request generation 207 * @param memberRequests any action requests that were generated for the given member 208 * @param member the PeopleFlow member 209 */ 210 private void generateDelegationRequests(Context context, List<ActionRequestValue> memberRequests, 211 PeopleFlowMember member) { 212 213 if (CollectionUtils.isEmpty(member.getDelegates()) || CollectionUtils.isEmpty(memberRequests)) { 214 return; 215 } 216 217 /*for (PeopleFlowDelegate delegate : member.getDelegates()) { 218 if (MemberType.ROLE == delegate.getMemberType()) { 219 generateDelegationToRoleRequests(context, memberRequest, member, delegate); 220 } else { 221 for (ActionRequestValue memberRequest : memberRequests) { 222 generateDelegationToNonRoleRequest(context, memberRequest, member, delegate); 223 } 224 } 225 }*/ 226 /*List<RoleMembership> memberships = getRoleService().getRoleMembers(Collections.singletonList( 227 member.getMemberId()), roleQualifiers);*/ 228 for (PeopleFlowDelegate delegate : member.getDelegates()) { 229 for (ActionRequestValue memberRequest : memberRequests) { 230 if (!MemberType.ROLE.equals(delegate.getMemberType()) ){ 231 generateDelegationToNonRoleRequest(context, memberRequest, member, delegate); 232 } 233 } 234 } 235 } 236 237 /** 238 * Uses the ActionRequestFactory to add the delegate request to the given parent request. 239 * 240 * <p>Only handles non-role delegates. If a delegate of type role is passed, a RiceIllegalStateException will be 241 * thrown.</p> 242 * 243 * @param context the context for request generation 244 * @param memberRequest an action request that was generated for the given member 245 * @param member the PeopleFlow member 246 * @param delegate the delegate to generate a request to 247 */ 248 private void generateDelegationToNonRoleRequest(Context context, ActionRequestValue memberRequest, 249 PeopleFlowMember member, PeopleFlowDelegate delegate) { 250 251 Recipient recipient; 252 253 if (MemberType.PRINCIPAL == delegate.getMemberType()) { 254 recipient = new KimPrincipalRecipient(delegate.getMemberId()); 255 } else if (MemberType.GROUP == delegate.getMemberType()) { 256 recipient = new KimGroupRecipient(delegate.getMemberId()); 257 } else { 258 throw new RiceIllegalStateException("MemberType unknown: " + delegate.getMemberType()); 259 } 260 261 String actionRequestPolicyCode = getDelegateActionRequestPolicyCode(member, delegate); 262 263 String delegationAnnotation = generateDelegationAnnotation(memberRequest, member, delegate); 264 265 context.getActionRequestFactory().addDelegationRequest(memberRequest, recipient, 266 delegate.getResponsibilityId(), memberRequest.getForceAction(), 267 delegate.getDelegationType(), actionRequestPolicyCode, delegationAnnotation, null); 268 } 269 270 /** 271 * Builds the String that will be used for the annotation on the delegate requests 272 * 273 * @param parentRequest an action request that was generated for the given member 274 * @param member the PeopleFlow member 275 * @param delegate the delegate 276 * @return the annotation string 277 */ 278 private String generateDelegationAnnotation(ActionRequestValue parentRequest, PeopleFlowMember member, 279 PeopleFlowDelegate delegate) { 280 281 StringBuffer annotation = new StringBuffer( "Delegation of: " ); 282 annotation.append( parentRequest.getAnnotation() ); 283 annotation.append( " to " ); 284 285 if (delegate.getMemberType() == MemberType.PRINCIPAL) { 286 annotation.append( "principal " ); 287 Principal principal = KimApiServiceLocator.getIdentityService().getPrincipal(delegate.getMemberId()); 288 289 if ( principal != null ) { 290 annotation.append( principal.getPrincipalName() ); 291 } else { 292 annotation.append( member.getMemberId() ); 293 } 294 } else if (delegate.getMemberType() == MemberType.GROUP) { 295 annotation.append( "group " ); 296 Group group = KimApiServiceLocator.getGroupService().getGroup(delegate.getMemberId()); 297 298 if ( group != null ) { 299 annotation.append( group.getNamespaceCode() ).append( '/' ).append( group.getName() ); 300 } else { 301 annotation.append( member.getMemberId() ); 302 } 303 } else { 304 annotation.append( "?????? '" ); 305 annotation.append( member.getMemberId() ); 306 annotation.append( "'" ); 307 } 308 309 return annotation.toString(); 310 } 311 312 313 /** 314 * Generates any needed requests for the given {@link PeopleFlowDelegate}. 315 * 316 * <p>It is assumed that the given member has the given delegate configured.</p> 317 * 318 * @param context the context for request generation 319 * @param parentRequest an action request that was generated for the given member 320 * @param member the PeopleFlow member, which should contain the given delegate 321 * @param delegate the delegate, assumed to be of MemberType ROLE, to generate a request to 322 */ 323 protected void generateDelegationToRoleRequests(Context context, 324 ActionRequestValue parentRequest, PeopleFlowMember member, PeopleFlowDelegate delegate, Map<String, String> roleQualifiers) { 325 326 //List<Map<String, String>> roleQualifierList = loadRoleQualifiers(context, delegate.getMemberId()); 327 Role role = getRoleService().getRole(delegate.getMemberId()); 328 329 if (role == null) { 330 throw new IllegalStateException("Failed to locate a role with the given role id of '" + 331 delegate.getMemberId() + "'"); 332 } 333 334 if (roleQualifiers.isEmpty()) { 335 addKimRoleDelegateRequest(context, parentRequest, member, delegate, role, 336 Collections.<String, String>emptyMap()); 337 } else { 338 //for (Map<String, String> roleQualifiers : roleQualifiers) { 339 List<RoleMembership> memberships = getRoleService().getRoleMembers(Collections.singletonList( 340 member.getMemberId()), roleQualifiers); 341 for (RoleMembership membership : memberships) { 342 if (membership.getType().equals(MemberType.PRINCIPAL) 343 && StringUtils.equals(membership.getMemberId(), parentRequest.getPrincipalId())) { 344 addKimRoleDelegateRequest(context, parentRequest, member, delegate, role, roleQualifiers); 345 } else if (membership.getType().equals(MemberType.GROUP) 346 && StringUtils.equals(membership.getMemberId(), parentRequest.getGroupId())) { 347 addKimRoleDelegateRequest(context, parentRequest, member, delegate, role, roleQualifiers); 348 } 349 } 350 351 //} 352 } 353 } 354 355 /** 356 * Generates any needed requests for the given {@link PeopleFlowDelegate}. 357 * 358 * <p>It is assumed that the given member has the given delegate configured.</p> 359 * 360 * @param context the context for request generation 361 * @param parentRequest an action request that was generated for the given member 362 * @param member the PeopleFlow member, which should contain the given delegate 363 * @param delegate the delegate, assumed to be of MemberType ROLE, to generate a request to 364 */ 365 protected void generateDelegationToRoleRequests(Context context, 366 ActionRequestValue parentRequest, PeopleFlowMember member, PeopleFlowDelegate delegate) { 367 368 List<Map<String, String>> roleQualifierList = loadRoleQualifiers(context, delegate.getMemberId()); 369 Role role = getRoleService().getRole(delegate.getMemberId()); 370 371 if (role == null) { 372 throw new IllegalStateException("Failed to locate a role with the given role id of '" + 373 delegate.getMemberId() + "'"); 374 } 375 376 if (CollectionUtils.isEmpty(roleQualifierList)) { 377 addKimRoleDelegateRequest(context, parentRequest, member, delegate, role, 378 Collections.<String, String>emptyMap()); 379 } else { 380 for (Map<String, String> roleQualifiers : roleQualifierList) { 381 List<RoleMembership> memberships = getRoleService().getRoleMembers(Collections.singletonList( 382 member.getMemberId()), roleQualifiers); 383 for (RoleMembership membership : memberships) { 384 if (membership.getType().equals(MemberType.PRINCIPAL) 385 && StringUtils.equals(membership.getMemberId(), parentRequest.getPrincipalId())) { 386 addKimRoleDelegateRequest(context, parentRequest, member, delegate, role, roleQualifiers); 387 } else if (membership.getType().equals(MemberType.GROUP) 388 && StringUtils.equals(membership.getMemberId(), parentRequest.getGroupId())) { 389 addKimRoleDelegateRequest(context, parentRequest, member, delegate, role, roleQualifiers); 390 } 391 } 392 393 } 394 } 395 } 396 397 /** 398 * Helper method uses the ActionRequestFactory to add to the parent request the delegation request(s) to a role. 399 * 400 * <p>The role members themselves are derived here using the given qualifiers.</p> 401 * 402 * @param context the context for request generation 403 * @param parentRequest an action request that was generated for the given member 404 * @param member the PeopleFlow member 405 * @param delegate the delegate to generate a request to 406 * @param role the role specified within the delegate 407 * @param roleQualifiers the qualifiers to use for role member selection 408 */ 409 private void addKimRoleDelegateRequest(Context context, ActionRequestValue parentRequest, 410 PeopleFlowMember member, PeopleFlowDelegate delegate, Role role, Map<String, String> roleQualifiers) { 411 412 // sanity check 413 if (delegate.getMemberType() != MemberType.ROLE) { 414 throw new RiceIllegalArgumentException("delegate's member type must be ROLE"); 415 } else if (!delegate.getMemberId().equals(role.getId())) { 416 throw new RiceIllegalArgumentException("delegate's member id must match the given role's id"); 417 } 418 419 String actionRequestPolicyCode = getDelegateActionRequestPolicyCode(member, delegate); 420 421 List<RoleMembership> memberships = getRoleService().getRoleMembers(Collections.singletonList( 422 delegate.getMemberId()), roleQualifiers); 423 424 if (!CollectionUtils.isEmpty(memberships)) { 425 context.getActionRequestFactory().addDelegateKimRoleRequest(parentRequest, 426 delegate.getDelegationType(), context.getActionRequested().getCode(), member.getPriority(), role, 427 memberships, null, delegate.getResponsibilityId(), true, actionRequestPolicyCode, null); 428 } 429 } 430 431 /** 432 * Uses the appropriate {@link PeopleFlowTypeService} to get the role qualifier maps for the given document and 433 * role. 434 * 435 * <p>Note that the PeopleFlowTypeService is selected based on the type id of the PeopleFlow.</p> 436 * 437 * @param context the context for request generation 438 * @param roleId the ID of the role for whom qualifiers are being loaded 439 * @return the qualifier maps, or an empty list if there are none 440 */ 441 protected List<Map<String, String>> loadRoleQualifiers(Context context, String roleId) { 442 PeopleFlowTypeService peopleFlowTypeService = context.getPeopleFlowTypeService(); 443 List<Map<String, String>> roleQualifierList = new ArrayList<Map<String, String>>(); 444 445 if (peopleFlowTypeService != null) { 446 Document document = DocumentRouteHeaderValue.to(context.getRouteContext().getDocument()); 447 DocumentRouteHeaderValueContent content = new DocumentRouteHeaderValueContent(document.getDocumentId()); 448 content.setDocumentContent(context.getRouteContext().getDocumentContent().getDocContent()); 449 DocumentContent documentContent = DocumentRouteHeaderValueContent.to(content); 450 451 Map<String, String> roleQualifiers = peopleFlowTypeService.resolveRoleQualifiers( 452 context.getPeopleFlow().getTypeId(), roleId, document, documentContent 453 ); 454 455 if (roleQualifiers != null) { 456 roleQualifierList.add(roleQualifiers); 457 } 458 459 boolean versionOk = VersionHelper.compareVersion(context.getPeopleFlowTypeServiceVersion(), CoreConstants.Versions.VERSION_2_3_0) != -1; 460 if(versionOk) { 461 List<Map<String, String>> multipleRoleQualifiers = peopleFlowTypeService.resolveMultipleRoleQualifiers( 462 context.getPeopleFlow().getTypeId(), roleId, document, documentContent); 463 464 if (multipleRoleQualifiers != null) { 465 roleQualifierList.addAll(multipleRoleQualifiers); 466 } 467 } 468 469 } 470 471 return roleQualifierList; 472 } 473 474 /** 475 * Gets the action request policy code for the given delegate. 476 * 477 * <p>the delegate is considered first, and the member is used as a fallback. May return null.</p> 478 * 479 * @param member the PeopleFlow member 480 * @param delegate the delegate 481 * @return the action request policy code, or null if none is found 482 */ 483 private String getDelegateActionRequestPolicyCode(PeopleFlowMember member, PeopleFlowDelegate delegate) { 484 ActionRequestPolicy actionRequestPolicy = delegate.getActionRequestPolicy(); 485 486 return (actionRequestPolicy != null) ? actionRequestPolicy.getCode() : getActionRequestPolicyCode(member); 487 } 488 489 /** 490 * Gets the action request policy code for the given member. 491 * 492 * @param member the PeopleFlow member 493 * @return the action request policy code, or null if none is found 494 */ 495 private String getActionRequestPolicyCode(PeopleFlowMember member) { 496 ActionRequestPolicy actionRequestPolicy = member.getActionRequestPolicy(); 497 498 return (actionRequestPolicy != null) ? actionRequestPolicy.getCode() : null; 499 } 500 501 private Recipient toRecipient(PeopleFlowMember member) { 502 Recipient recipient; 503 if (MemberType.PRINCIPAL == member.getMemberType()) { 504 recipient = new KimPrincipalRecipient(member.getMemberId()); 505 } else if (MemberType.GROUP == member.getMemberType()) { 506 recipient = new KimGroupRecipient(member.getMemberId()); 507 } else { 508 throw new IllegalStateException("encountered a member type which I did not understand: " + 509 member.getMemberType()); 510 } 511 return recipient; 512 } 513 514 private Recipient toRecipient(PeopleFlowDelegate delegate) { 515 Recipient recipient; 516 if (MemberType.PRINCIPAL == delegate.getMemberType()) { 517 recipient = new KimPrincipalRecipient(delegate.getMemberId()); 518 } else if (MemberType.GROUP == delegate.getMemberType()) { 519 recipient = new KimGroupRecipient(delegate.getMemberId()); 520 } else { 521 throw new IllegalStateException("encountered a delegate member type which I did not understand: " + 522 delegate.getMemberType()); 523 } 524 return recipient; 525 } 526 527 public KewTypeRepositoryService getTypeRepositoryService() { 528 return typeRepositoryService; 529 } 530 531 public void setTypeRepositoryService(KewTypeRepositoryService typeRepositoryService) { 532 this.typeRepositoryService = typeRepositoryService; 533 } 534 535 public RoleService getRoleService() { 536 return roleService; 537 } 538 539 public void setRoleService(RoleService roleService) { 540 this.roleService = roleService; 541 } 542 543 /** 544 * Recursively find all non-delegate Group and Principal requests from all of the requests in the given list. 545 * 546 * @param actionRequestValues the list of {@link ActionRequestValue}s to search 547 * @return a list of the non-delegate Group and Principal requests found 548 */ 549 private List<ActionRequestValue> findNonRoleRequests(List<ActionRequestValue> actionRequestValues) { 550 List<ActionRequestValue> nonRoleRequests = new ArrayList<ActionRequestValue>(); 551 552 return findNonRoleRequests(actionRequestValues, nonRoleRequests); 553 } 554 555 // Recursion helper method 556 private List<ActionRequestValue> findNonRoleRequests(List<ActionRequestValue> actionRequestValues, 557 List<ActionRequestValue> nonRoleRequests) { 558 559 if (!CollectionUtils.isEmpty(actionRequestValues)) { 560 for (ActionRequestValue request : actionRequestValues) if (request.getDelegationType() == null) { 561 if (!CollectionUtils.isEmpty(request.getChildrenRequests())) { 562 findNonRoleRequests(request.getChildrenRequests(), nonRoleRequests); 563 } else { 564 // see if we have a principal request 565 if (!StringUtils.equals(RecipientType.ROLE.getCode(),request.getRecipientTypeCd())) { 566 nonRoleRequests.add(request); 567 } 568 } 569 } 570 } 571 572 return nonRoleRequests; 573 } 574 575 576 /** 577 * A simple class used to hold context during the PeopleFlow action request generation process. Construction of 578 * the context will validate that the given values are valid, non-null values where appropriate. 579 */ 580 final class Context { 581 582 private final RouteContext routeContext; 583 private final PeopleFlowDefinition peopleFlow; 584 private final ActionRequestType actionRequested; 585 private final ActionRequestFactory actionRequestFactory; 586 587 // lazily loaded 588 private PeopleFlowTypeService peopleFlowTypeService; 589 private boolean peopleFlowTypeServiceLoaded = false; 590 private String peopleFlowTypeServiceVersion; 591 592 Context(RouteContext routeContext, PeopleFlowDefinition peopleFlow, ActionRequestType actionRequested) { 593 if (routeContext == null) { 594 throw new IllegalArgumentException("routeContext was null"); 595 } 596 if (peopleFlow == null) { 597 throw new IllegalArgumentException("peopleFlow was null"); 598 } 599 if (!peopleFlow.isActive()) { 600 throw new ConfigurationException("Attempted to route to a PeopleFlow that is not active! " + peopleFlow); 601 } 602 if (actionRequested == null) { 603 actionRequested = ActionRequestType.APPROVE; 604 } 605 this.routeContext = routeContext; 606 this.peopleFlow = peopleFlow; 607 this.actionRequested = actionRequested; 608 this.actionRequestFactory = new ActionRequestFactory(routeContext); 609 } 610 611 RouteContext getRouteContext() { 612 return routeContext; 613 } 614 615 PeopleFlowDefinition getPeopleFlow() { 616 return peopleFlow; 617 } 618 619 ActionRequestType getActionRequested() { 620 return actionRequested; 621 } 622 623 ActionRequestFactory getActionRequestFactory() { 624 return actionRequestFactory; 625 } 626 627 /** 628 * Lazily loads and caches the {@code PeopleFlowTypeService} (if necessary) and returns it. 629 */ 630 PeopleFlowTypeService getPeopleFlowTypeService() { 631 if (peopleFlowTypeServiceLoaded) { 632 return this.peopleFlowTypeService; 633 } 634 635 if (getPeopleFlow().getTypeId() != null) { 636 KewTypeDefinition typeDefinition = getTypeRepositoryService().getTypeById(getPeopleFlow().getTypeId()); 637 638 if (typeDefinition == null) { 639 throw new IllegalStateException("Failed to locate a PeopleFlow type for the given type id of '" + getPeopleFlow().getTypeId() + "'"); 640 } 641 642 if (StringUtils.isNotBlank(typeDefinition.getServiceName())) { 643 Endpoint endpoint = KsbApiServiceLocator.getServiceBus().getEndpoint(QName.valueOf(typeDefinition.getServiceName())); 644 645 if (endpoint == null) { 646 throw new IllegalStateException("Failed to load the PeopleFlowTypeService with the name '" + typeDefinition.getServiceName() + "'"); 647 } 648 649 this.peopleFlowTypeService = (PeopleFlowTypeService)endpoint.getService(); 650 this.peopleFlowTypeServiceVersion = endpoint.getServiceConfiguration().getServiceVersion(); 651 } 652 } 653 peopleFlowTypeServiceLoaded = true; 654 return this.peopleFlowTypeService; 655 } 656 657 String getPeopleFlowTypeServiceVersion() { 658 if (!this.peopleFlowTypeServiceLoaded) { 659 // execute getPeopleFlowTypeService first to lazy load 660 getPeopleFlowTypeService(); 661 } 662 663 return this.peopleFlowTypeServiceVersion; 664 } 665 } 666}