1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.impl.peopleflow;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.CoreConstants;
21 import org.kuali.rice.core.api.config.ConfigurationException;
22 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
23 import org.kuali.rice.core.api.exception.RiceIllegalStateException;
24 import org.kuali.rice.core.api.membership.MemberType;
25 import org.kuali.rice.core.api.util.VersionHelper;
26 import org.kuali.rice.kew.actionrequest.ActionRequestFactory;
27 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
28 import org.kuali.rice.kew.actionrequest.KimGroupRecipient;
29 import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient;
30 import org.kuali.rice.kew.actionrequest.Recipient;
31 import org.kuali.rice.kew.api.action.ActionRequestPolicy;
32 import org.kuali.rice.kew.api.action.ActionRequestType;
33 import org.kuali.rice.kew.api.action.RecipientType;
34 import org.kuali.rice.kew.api.document.Document;
35 import org.kuali.rice.kew.api.document.DocumentContent;
36 import org.kuali.rice.kew.api.peopleflow.PeopleFlowDefinition;
37 import org.kuali.rice.kew.api.peopleflow.PeopleFlowDelegate;
38 import org.kuali.rice.kew.api.peopleflow.PeopleFlowMember;
39 import org.kuali.rice.kew.api.repository.type.KewTypeDefinition;
40 import org.kuali.rice.kew.api.repository.type.KewTypeRepositoryService;
41 import org.kuali.rice.kew.engine.RouteContext;
42 import org.kuali.rice.kew.framework.peopleflow.PeopleFlowTypeService;
43 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
44 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValueContent;
45 import org.kuali.rice.kim.api.group.Group;
46 import org.kuali.rice.kim.api.identity.principal.Principal;
47 import org.kuali.rice.kim.api.role.Role;
48 import org.kuali.rice.kim.api.role.RoleMembership;
49 import org.kuali.rice.kim.api.role.RoleService;
50 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
51 import org.kuali.rice.ksb.api.KsbApiServiceLocator;
52 import org.kuali.rice.ksb.api.bus.Endpoint;
53
54 import javax.xml.namespace.QName;
55 import java.util.ArrayList;
56 import java.util.Collections;
57 import java.util.List;
58 import java.util.Map;
59
60
61
62
63
64
65
66 public class PeopleFlowRequestGeneratorImpl implements PeopleFlowRequestGenerator {
67
68 private KewTypeRepositoryService typeRepositoryService;
69 private RoleService roleService;
70
71 @Override
72 public List<ActionRequestValue> generateRequests(RouteContext routeContext, PeopleFlowDefinition peopleFlow, ActionRequestType actionRequested) {
73 Context context = new Context(routeContext, peopleFlow, actionRequested);
74 for (PeopleFlowMember member : peopleFlow.getMembers()) {
75 generateRequestForMember(context, member);
76 }
77
78 return context.getActionRequestFactory().getRequestGraphs();
79 }
80
81 protected void generateRequestForMember(Context context, PeopleFlowMember member) {
82
83 List<ActionRequestValue> memberRequests = new ArrayList<ActionRequestValue>();
84
85 if (MemberType.ROLE == member.getMemberType()) {
86 memberRequests.addAll(findNonRoleRequests(generateRequestsForRoleMember(context, member)));
87 } else {
88 ActionRequestValue actionRequest = context.getActionRequestFactory().addRootActionRequest(
89 context.getActionRequested().getCode(), member.getPriority(), toRecipient(member), "",
90 member.getResponsibilityId(), Boolean.TRUE, getActionRequestPolicyCode(member), null);
91
92 if (actionRequest != null) {
93 memberRequests.add(actionRequest);
94 }
95 }
96
97
98 generateDelegationRequests(context, memberRequests, member);
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112 protected List<ActionRequestValue> generateRequestsForRoleMember(Context context, PeopleFlowMember member) {
113 List<ActionRequestValue> roleMemberRequests = new ArrayList<ActionRequestValue>();
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
137 addKimRoleDelegateRequest(context, request, member, delegate, delegateRole, Collections.<String, String>emptyMap());
138 }
139 }
140 }
141 }
142 }
143
144 } else {
145
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
157 addKimRoleDelegateRequest(context, request, member, delegate, delegateRole, roleQualifiers);
158 }
159 }
160 }
161 }
162 }
163 }
164 }
165
166 return roleMemberRequests;
167 }
168
169
170
171
172
173
174
175
176
177
178
179
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
196 }
197
198 return roleMemberRequest;
199 }
200
201
202
203
204
205
206
207
208
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
218
219
220
221
222
223
224
225
226
227
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
239
240
241
242
243
244
245
246
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
272
273
274
275
276
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
315
316
317
318
319
320
321
322
323 protected void generateDelegationToRoleRequests(Context context,
324 ActionRequestValue parentRequest, PeopleFlowMember member, PeopleFlowDelegate delegate, Map<String, String> roleQualifiers) {
325
326
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
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
357
358
359
360
361
362
363
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
399
400
401
402
403
404
405
406
407
408
409 private void addKimRoleDelegateRequest(Context context, ActionRequestValue parentRequest,
410 PeopleFlowMember member, PeopleFlowDelegate delegate, Role role, Map<String, String> roleQualifiers) {
411
412
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
433
434
435
436
437
438
439
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
476
477
478
479
480
481
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
491
492
493
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
545
546
547
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
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
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
578
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
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
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
660 getPeopleFlowTypeService();
661 }
662
663 return this.peopleFlowTypeServiceVersion;
664 }
665 }
666 }