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