Coverage Report - org.kuali.rice.kew.actionrequest.ActionRequestFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
ActionRequestFactory
0%
0/306
0%
0/152
3.903
 
 1  
 /*
 2  
  * Copyright 2006-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.kuali.rice.kew.actionrequest;
 18  
 
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.apache.log4j.Logger;
 21  
 import org.kuali.rice.core.api.exception.RiceRuntimeException;
 22  
 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
 23  
 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
 24  
 import org.kuali.rice.kew.api.WorkflowRuntimeException;
 25  
 import org.kuali.rice.kew.api.action.ActionRequestPolicy;
 26  
 import org.kuali.rice.kew.api.action.ActionRequestStatus;
 27  
 import org.kuali.rice.kew.api.action.RecipientType;
 28  
 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
 29  
 import org.kuali.rice.kew.identity.Id;
 30  
 import org.kuali.rice.kew.identity.service.IdentityHelperService;
 31  
 import org.kuali.rice.kew.role.KimRoleRecipient;
 32  
 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
 33  
 import org.kuali.rice.kew.rule.ResolvedQualifiedRole;
 34  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 35  
 import org.kuali.rice.kew.user.RoleRecipient;
 36  
 import org.kuali.rice.kew.user.UserId;
 37  
 import org.kuali.rice.kew.util.CodeTranslator;
 38  
 import org.kuali.rice.kew.util.KEWConstants;
 39  
 import org.kuali.rice.kew.util.Utilities;
 40  
 import org.kuali.rice.kew.workgroup.GroupId;
 41  
 import org.kuali.rice.kim.api.common.delegate.DelegateType;
 42  
 import org.kuali.rice.kim.api.group.Group;
 43  
 import org.kuali.rice.kim.api.group.GroupService;
 44  
 import org.kuali.rice.kim.api.identity.principal.Principal;
 45  
 import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
 46  
 import org.kuali.rice.kim.api.responsibility.ResponsibilityAction;
 47  
 import org.kuali.rice.kim.api.role.Role;
 48  
 import org.kuali.rice.kim.api.role.RoleService;
 49  
 import org.kuali.rice.kim.api.services.IdentityService;
 50  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 51  
 import org.kuali.rice.krad.util.KRADConstants;
 52  
 
 53  
 import java.sql.Timestamp;
 54  
 import java.util.ArrayList;
 55  
 import java.util.Collection;
 56  
 import java.util.HashSet;
 57  
 import java.util.Iterator;
 58  
 import java.util.List;
 59  
 import java.util.Map;
 60  
 import java.util.Set;
 61  
 
 62  
 
 63  
 /**
 64  
  * A factory to aid in creating the ever-so-gnarly ActionRequestValue object.
 65  
  *
 66  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 67  
  */
 68  
 public class ActionRequestFactory {
 69  
 
 70  0
         private static final Logger LOG = Logger.getLogger(ActionRequestFactory.class);
 71  
 
 72  
         private static RoleService roleService;
 73  
         private static IdentityHelperService identityHelperService;
 74  
         private static IdentityService identityService;
 75  
     private static GroupService groupService;
 76  
         private static ActionRequestService actionRequestService;
 77  
         
 78  
         private DocumentRouteHeaderValue document;
 79  
         private RouteNodeInstance routeNode;
 80  0
         private List<ActionRequestValue> requestGraphs = new ArrayList<ActionRequestValue>();
 81  
 
 82  0
         public ActionRequestFactory() {
 83  0
         }
 84  
 
 85  0
         public ActionRequestFactory(DocumentRouteHeaderValue document) {
 86  0
                 this.document = document;
 87  0
         }
 88  
 
 89  0
         public ActionRequestFactory(DocumentRouteHeaderValue document, RouteNodeInstance routeNode) {
 90  0
                 this.document = document;
 91  0
                 this.routeNode = routeNode;
 92  0
         }
 93  
 
 94  
         /**
 95  
          * Constructs ActionRequestValue using default priority and 0 as responsibility
 96  
          *
 97  
          * @param actionRequested
 98  
          * @param recipient
 99  
          * @param description
 100  
          * @param forceAction
 101  
          * @param annotation
 102  
      * @return ActionRequestValue
 103  
          */
 104  
         public ActionRequestValue createActionRequest(String actionRequested, Recipient recipient, String description, Boolean forceAction, String annotation) {
 105  0
                 return createActionRequest(actionRequested, 0, recipient, description, KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, forceAction, annotation);
 106  
         }
 107  
 
 108  
         public ActionRequestValue createActionRequest(String actionRequested, Integer priority, Recipient recipient, String description, String responsibilityId, Boolean forceAction, String annotation) {
 109  0
             return createActionRequest(actionRequested, priority, recipient, description, responsibilityId, forceAction, null, null, annotation);
 110  
     }
 111  
 
 112  
         public ActionRequestValue createActionRequest(String actionRequested, Integer priority, Recipient recipient, String description, String responsibilityId, Boolean forceAction, String approvePolicy, String ruleId, String annotation) {
 113  0
                 return createActionRequest(actionRequested, priority, recipient, description, responsibilityId, forceAction, approvePolicy, ruleId, annotation, null);
 114  
         }
 115  
 
 116  
         public ActionRequestValue createActionRequest(String actionRequested, Integer priority, Recipient recipient, String description, String responsibilityId, Boolean forceAction, String approvePolicy, String ruleId, String annotation, String requestLabel) {
 117  0
                 ActionRequestValue actionRequest = new ActionRequestValue();
 118  0
         actionRequest.setActionRequested(actionRequested);
 119  0
         actionRequest.setDocVersion(document.getDocVersion());
 120  0
         actionRequest.setPriority(priority);
 121  0
         actionRequest.setRouteHeader(document);
 122  0
         actionRequest.setDocumentId(document.getDocumentId());
 123  0
         actionRequest.setRouteLevel(document.getDocRouteLevel());
 124  0
             actionRequest.setNodeInstance(routeNode);
 125  0
             actionRequest.setResponsibilityId(responsibilityId);
 126  0
             actionRequest.setResponsibilityDesc(description);
 127  0
             actionRequest.setApprovePolicy(approvePolicy);
 128  0
             actionRequest.setForceAction(forceAction);
 129  0
             actionRequest.setRuleBaseValuesId(ruleId);
 130  0
             actionRequest.setAnnotation(annotation);
 131  0
             actionRequest.setRequestLabel(requestLabel);
 132  0
             setDefaultProperties(actionRequest);
 133  0
             resolveRecipient(actionRequest, recipient);
 134  
 
 135  0
         return actionRequest;
 136  
         }
 137  
 
 138  
         public ActionRequestValue createBlankActionRequest() {
 139  0
                 ActionRequestValue request = new ActionRequestValue();
 140  0
                 request.setRouteHeader(document);
 141  0
                 if (document != null) {
 142  0
                         request.setDocumentId(document.getDocumentId());
 143  
                 }
 144  0
                 request.setNodeInstance(routeNode);
 145  0
                 return request;
 146  
         }
 147  
 
 148  
 
 149  
     public ActionRequestValue createNotificationRequest(String actionRequestCode, PrincipalContract principal, String reasonActionCode, PrincipalContract reasonActionUser, String responsibilityDesc) {
 150  0
             ActionRequestValue request = createActionRequest(actionRequestCode, new KimPrincipalRecipient(principal), responsibilityDesc, Boolean.TRUE, null);
 151  0
             String annotation = generateNotificationAnnotation(reasonActionUser, actionRequestCode, reasonActionCode, request);
 152  0
             request.setAnnotation(annotation);
 153  0
             return request;
 154  
     }
 155  
 
 156  
     //unify these 2 methods if possible
 157  
     public List<ActionRequestValue> generateNotifications(List requests, PrincipalContract principal, Recipient delegator,
 158  
             String notificationRequestCode, String actionTakenCode)
 159  
     {
 160  0
         String groupName =  CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KEWConstants.KEW_NAMESPACE,
 161  
                 KRADConstants.DetailTypes.WORKGROUP_DETAIL_TYPE,
 162  
                 KEWConstants.NOTIFICATION_EXCLUDED_USERS_WORKGROUP_NAME_IND);
 163  
         
 164  
         
 165  0
         Group notifyExclusionWorkgroup = null;
 166  0
         if(!StringUtils.isBlank(groupName)){
 167  0
                 notifyExclusionWorkgroup = getGroupService().getGroupByName(Utilities.parseGroupNamespaceCode(groupName), Utilities.parseGroupName(groupName));
 168  
         }
 169  
         
 170  
  
 171  
         
 172  0
         return generateNotifications(null, getActionRequestService().getRootRequests(requests), principal, delegator, notificationRequestCode, actionTakenCode, notifyExclusionWorkgroup);
 173  
     }
 174  
 
 175  
     private List<ActionRequestValue> generateNotifications(ActionRequestValue parentRequest,
 176  
             List requests, PrincipalContract principal, Recipient delegator, String notificationRequestCode,
 177  
             String actionTakenCode, Group notifyExclusionWorkgroup)
 178  
     {
 179  0
         List<ActionRequestValue> notificationRequests = new ArrayList<ActionRequestValue>();
 180  0
         for (Object request : requests)
 181  
         {
 182  0
             ActionRequestValue actionRequest = (ActionRequestValue) request;
 183  0
             if (!(actionRequest.isRecipientRoutedRequest(principal.getPrincipalId()) || actionRequest.isRecipientRoutedRequest(delegator)))
 184  
             {
 185  
                 // skip user requests to system users
 186  0
                 if ((notifyExclusionWorkgroup != null) &&
 187  
                         (isRecipientInGroup(notifyExclusionWorkgroup, actionRequest.getRecipient())))
 188  
                 {
 189  0
                     continue;
 190  
                 }
 191  0
                 ActionRequestValue notificationRequest = createNotificationRequest(actionRequest, principal, notificationRequestCode, actionTakenCode);
 192  0
                 notificationRequests.add(notificationRequest);
 193  0
                 if (parentRequest != null)
 194  
                 {
 195  0
                     notificationRequest.setParentActionRequest(parentRequest);
 196  0
                     parentRequest.getChildrenRequests().add(notificationRequest);
 197  
                 }
 198  0
                 notificationRequests.addAll(generateNotifications(notificationRequest, actionRequest.getChildrenRequests(), principal, delegator, notificationRequestCode, actionTakenCode, notifyExclusionWorkgroup));
 199  
             }
 200  0
         }
 201  0
         return notificationRequests;
 202  
     }
 203  
 
 204  
     private boolean isRecipientInGroup(Group group, Recipient recipient)
 205  
     {
 206  0
         boolean isMember = false;
 207  
 
 208  0
         if(recipient instanceof KimPrincipalRecipient)
 209  
         {
 210  0
             String principalId = ((KimPrincipalRecipient) recipient).getPrincipalId();
 211  0
             String groupId = group.getId();
 212  0
             isMember = getGroupService().isMemberOfGroup(principalId, groupId);
 213  0
         }
 214  0
         else if (recipient instanceof KimGroupRecipient)
 215  
         {
 216  0
             String kimRecipientId = ((KimGroupRecipient) recipient).getGroup().getId();
 217  0
             isMember = getGroupService().isGroupMemberOfGroup(kimRecipientId, group.getId() );
 218  
         }
 219  0
         return isMember;
 220  
     }
 221  
 
 222  
     private ActionRequestValue createNotificationRequest(ActionRequestValue actionRequest, PrincipalContract reasonPrincipal, String notificationRequestCode, String actionTakenCode) {
 223  
 
 224  0
             String annotation = generateNotificationAnnotation(reasonPrincipal, notificationRequestCode, actionTakenCode, actionRequest);
 225  0
         ActionRequestValue request = createActionRequest(notificationRequestCode, actionRequest.getPriority(), actionRequest.getRecipient(), actionRequest.getResponsibilityDesc(), KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, Boolean.TRUE, annotation);
 226  
 
 227  0
         request.setDocVersion(actionRequest.getDocVersion());
 228  0
         request.setApprovePolicy(actionRequest.getApprovePolicy());
 229  0
         request.setRoleName(actionRequest.getRoleName());
 230  0
         request.setQualifiedRoleName(actionRequest.getQualifiedRoleName());
 231  0
         request.setQualifiedRoleNameLabel(actionRequest.getQualifiedRoleNameLabel());
 232  0
         request.setDelegationType(actionRequest.getDelegationType());
 233  0
         return request;
 234  
     }
 235  
 
 236  
     private void setDefaultProperties(ActionRequestValue actionRequest) {
 237  0
             if (actionRequest.getApprovePolicy() == null) {
 238  0
                     actionRequest.setApprovePolicy(ActionRequestPolicy.FIRST.getCode());
 239  
             }
 240  0
         actionRequest.setCreateDate(new Timestamp(System.currentTimeMillis()));
 241  0
         actionRequest.setCurrentIndicator(Boolean.TRUE);
 242  0
         if (actionRequest.getForceAction() == null) {
 243  0
                 actionRequest.setForceAction(Boolean.FALSE);
 244  
         }
 245  0
         if (routeNode != null) {
 246  0
                 actionRequest.setNodeInstance(routeNode);
 247  
         }
 248  0
         actionRequest.setJrfVerNbr(0);
 249  0
         actionRequest.setStatus(ActionRequestStatus.INITIALIZED.getCode());
 250  0
         actionRequest.setRouteHeader(document);
 251  0
         actionRequest.setDocumentId(document.getDocumentId());
 252  0
     }
 253  
 
 254  
     private static void resolveRecipient(ActionRequestValue actionRequest, Recipient recipient) {
 255  0
             if (recipient instanceof KimPrincipalRecipient) {
 256  0
                     actionRequest.setRecipientTypeCd(RecipientType.PRINCIPAL.getCode());
 257  0
                     actionRequest.setPrincipalId(((KimPrincipalRecipient)recipient).getPrincipal().getPrincipalId());
 258  0
             }  else if (recipient instanceof KimGroupRecipient) {
 259  0
                     KimGroupRecipient kimGroupRecipient = (KimGroupRecipient)recipient;
 260  0
                     actionRequest.setRecipientTypeCd(RecipientType.GROUP.getCode());
 261  0
                     actionRequest.setGroupId(kimGroupRecipient.getGroup().getId());
 262  0
             } else if (recipient instanceof RoleRecipient){
 263  0
                     RoleRecipient role = (RoleRecipient)recipient;
 264  0
                     actionRequest.setRecipientTypeCd(RecipientType.ROLE.getCode());
 265  0
                     actionRequest.setRoleName(role.getRoleName());
 266  0
                     actionRequest.setQualifiedRoleName(role.getQualifiedRoleName());
 267  0
                     ResolvedQualifiedRole qualifiedRole = role.getResolvedQualifiedRole();
 268  0
                     if (qualifiedRole != null) {
 269  0
                             actionRequest.setAnnotation(qualifiedRole.getAnnotation() == null ? "" : qualifiedRole.getAnnotation());
 270  0
                             actionRequest.setQualifiedRoleNameLabel(qualifiedRole.getQualifiedRoleLabel());
 271  
                     }
 272  0
                     Recipient targetRecipient = role.getTarget();
 273  0
                     if (role.getTarget() != null) {
 274  0
                             if (targetRecipient instanceof RoleRecipient) {
 275  0
                                     throw new WorkflowRuntimeException("Role Cannot Target a role problem activating request for document " + actionRequest.getDocumentId());
 276  
                             }
 277  0
                             resolveRecipient(actionRequest, role.getTarget());
 278  
                     }
 279  0
             } else if (recipient instanceof KimRoleRecipient) {
 280  0
                     KimRoleRecipient roleRecipient = (KimRoleRecipient)recipient;
 281  0
                     actionRequest.setRecipientTypeCd(RecipientType.ROLE.getCode());
 282  0
                     actionRequest.setRoleName(roleRecipient.getResponsibilities().get(0).getRoleId());
 283  0
                     actionRequest.setQualifiedRoleName(roleRecipient.getResponsibilities().get(0).getResponsibilityName());
 284  
                     // what about qualified role name label?
 285  
 //                    actionRequest.setAnnotation(roleRecipient.getResponsibilities().get(0).getResponsibilityName());
 286  0
                     Recipient targetRecipient = roleRecipient.getTarget();
 287  0
                     if (targetRecipient != null) {
 288  0
                             if (targetRecipient instanceof RoleRecipient) {
 289  0
                                     throw new WorkflowRuntimeException("Role Cannot Target a role problem activating request for document " + actionRequest.getDocumentId());
 290  
                             }
 291  0
                             resolveRecipient(actionRequest, roleRecipient.getTarget());
 292  
                     }
 293  
             }
 294  0
     }
 295  
 
 296  
     /**
 297  
      * Creates a root Role Request
 298  
      * @param role
 299  
      * @param actionRequested
 300  
      * @param approvePolicy
 301  
      * @param priority
 302  
      * @param responsibilityId
 303  
      * @param forceAction
 304  
      * @param description
 305  
      * @param ruleId
 306  
      * @return the created root role request
 307  
      */
 308  
     public ActionRequestValue addRoleRequest(RoleRecipient role, String actionRequested, String approvePolicy, Integer priority, String responsibilityId, Boolean forceAction, String description, String ruleId) {
 309  
 
 310  0
             ActionRequestValue requestGraph = createActionRequest(actionRequested, priority, role, description, responsibilityId, forceAction, approvePolicy, ruleId, null);
 311  0
             if (role != null && role.getResolvedQualifiedRole() != null && role.getResolvedQualifiedRole().getRecipients() != null) {
 312  0
                 int legitimateTargets = 0;
 313  0
             for (Id recipientId : role.getResolvedQualifiedRole().getRecipients())
 314  
             {
 315  0
                 if (recipientId.isEmpty())
 316  
                 {
 317  0
                     throw new WorkflowRuntimeException("Failed to resolve id of type " + recipientId.getClass().getName() + " returned from role '" + role.getRoleName() + "'.  Id returned contained a null or empty value.");
 318  
                 }
 319  0
                 if (recipientId instanceof UserId)
 320  
                 {
 321  0
                     Principal principal = getIdentityHelperService().getPrincipal((UserId) recipientId);
 322  0
                     role.setTarget(new KimPrincipalRecipient(principal));
 323  0
                 } else if (recipientId instanceof GroupId)
 324  
                 {
 325  0
                     role.setTarget(new KimGroupRecipient(getIdentityHelperService().getGroup((GroupId) recipientId)));
 326  
                 } else
 327  
                 {
 328  0
                     throw new WorkflowRuntimeException("Could not process the given type of id: " + recipientId.getClass());
 329  
                 }
 330  0
                 if (role.getTarget() != null)
 331  
                 {
 332  0
                     legitimateTargets++;
 333  0
                     ActionRequestValue request = createActionRequest(actionRequested, priority, role, description, responsibilityId, forceAction, null, ruleId, null);
 334  0
                     request.setParentActionRequest(requestGraph);
 335  0
                     requestGraph.getChildrenRequests().add(request);
 336  0
                 }
 337  
             }
 338  0
             if (legitimateTargets == 0) {
 339  0
             LOG.warn("Role did not yield any legitimate recipients");
 340  
         }
 341  0
             } else {
 342  0
                     LOG.warn("Didn't create action requests for action request description '" + description + "' because of null role or null part of role object graph.");
 343  
             }
 344  0
             requestGraphs.add(requestGraph);
 345  0
             return requestGraph;
 346  
     }
 347  
 
 348  
     /**
 349  
      * Generates an ActionRequest graph for the given KIM Responsibilities.  This graph includes any associated delegations.
 350  
      * @param responsibilities
 351  
      * @param approvePolicy
 352  
      */
 353  
     public void addRoleResponsibilityRequest(List<ResponsibilityAction> responsibilities, String approvePolicy) {
 354  0
             if (responsibilities == null || responsibilities.isEmpty()) {
 355  0
                     LOG.warn("Didn't create action requests for action request description because no responsibilities were defined.");
 356  0
                     return;
 357  
             }
 358  
             // it's assumed the that all in the list have the same action type code, priority number, etc.
 359  0
             String actionTypeCode = responsibilities.get(0).getActionTypeCode();
 360  0
             Integer priority = responsibilities.get(0).getPriorityNumber();
 361  0
             boolean forceAction = responsibilities.get(0).isForceAction();
 362  0
             KimRoleRecipient roleRecipient = new KimRoleRecipient(responsibilities);
 363  
 
 364  
             // Creation of a parent graph entry for ????
 365  0
             ActionRequestValue requestGraph = null;
 366  0
             StringBuffer parentAnnotation = null;
 367  
             // set to allow for suppression of duplicate annotations on the parent action request
 368  0
             Set<String> uniqueChildAnnotations = null;
 369  0
             if ( responsibilities.size() > 1 ) {
 370  0
                     requestGraph = createActionRequest(
 371  
                             actionTypeCode, 
 372  
                             priority, 
 373  
                             roleRecipient, 
 374  
                             "", // description 
 375  
                             KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID, 
 376  
                             forceAction, 
 377  
                             approvePolicy, 
 378  
                             null, // ruleId
 379  
                             null );// annotation
 380  0
                     requestGraphs.add(requestGraph);
 381  0
                     parentAnnotation = new StringBuffer();
 382  0
                     uniqueChildAnnotations = new HashSet<String>( responsibilities.size() );
 383  
             }
 384  0
             StringBuffer annotation = new StringBuffer();
 385  0
             for (ResponsibilityAction responsibility : responsibilities) {
 386  0
                     if ( LOG.isDebugEnabled() ) {
 387  0
                             LOG.debug( "Processing Responsibility for action request: " + responsibility );
 388  
                     }
 389  
                 // KFSMI-2381 - pull information from KIM to populate annotation
 390  0
                     annotation.setLength( 0 );
 391  0
                     Role role = getRoleService().getRole(responsibility.getRoleId());
 392  0
                     annotation.append( role.getNamespaceCode() ).append( ' ' ).append( role.getName() ).append( ' ' );
 393  0
                     Map<String, String> qualifier = responsibility.getQualifier();
 394  0
                     if ( qualifier != null ) {
 395  0
                             for ( String key : qualifier.keySet() ) {
 396  0
                                 annotation.append( qualifier.get( key ) ).append( ' ' );
 397  
                             }
 398  
                     }
 399  0
                         if (responsibility.getPrincipalId() != null) {
 400  0
                                 roleRecipient.setTarget(new KimPrincipalRecipient(responsibility.getPrincipalId()));
 401  0
                         } else if (responsibility.getGroupId() != null) {
 402  0
                                 roleRecipient.setTarget(new KimGroupRecipient(responsibility.getGroupId()));
 403  
                         } else {
 404  0
                                 throw new RiceRuntimeException("Failed to identify a group or principal on the given ResponsibilityResolutionInfo:" + responsibility);
 405  
                         }
 406  0
                         String annotationStr = annotation.toString();
 407  0
                         ActionRequestValue request = createActionRequest(
 408  
                                 responsibility.getActionTypeCode(), 
 409  
                                 responsibility.getPriorityNumber(), 
 410  
                                 roleRecipient, 
 411  
                                 responsibility.getParallelRoutingGroupingCode(), // description
 412  
                                 responsibility.getResponsibilityId(), 
 413  
                                 responsibility.isForceAction(), 
 414  
                                 // If not nested in a parent action request, ensure that the request
 415  
                                 // is first approve so delegations of this request do not require 
 416  
                                 // ALL_APPROVE as well
 417  
                                 (responsibilities.size() == 1)?ActionRequestPolicy.FIRST.getCode():approvePolicy, 
 418  
                                 null, // ruleId
 419  
                                 annotationStr);
 420  
                         // if there is only a single request, don't create the nesting structure
 421  0
                         if ( responsibilities.size() > 1 ) {
 422  0
                                 request.setParentActionRequest(requestGraph);
 423  0
                                 requestGraph.getChildrenRequests().add(request);
 424  0
                                 generateRoleResponsibilityDelegationRequests(responsibility, request);
 425  0
                                 if ( !uniqueChildAnnotations.contains(annotationStr) ) {
 426  0
                                         parentAnnotation.append( annotationStr ).append( " -- " );
 427  0
                                         uniqueChildAnnotations.add(annotationStr);
 428  
                                 }
 429  
                         } else {
 430  0
                                 requestGraphs.add(request);
 431  0
                                 generateRoleResponsibilityDelegationRequests(responsibility, request);
 432  
                         }
 433  0
             }
 434  0
             if ( responsibilities.size() > 1 ) {
 435  0
                     requestGraph.setAnnotation( StringUtils.chomp( parentAnnotation.toString(), " -- " ) );
 436  
             }
 437  0
     }
 438  
 
 439  
     private void generateRoleResponsibilityDelegationRequests(ResponsibilityAction responsibility, ActionRequestValue parentRequest) {
 440  0
             List<DelegateType> delegates = responsibility.getDelegates();
 441  0
             for (DelegateType delegate : delegates) {
 442  
                     Recipient recipient;
 443  0
                     boolean isPrincipal = delegate.getDelegationTypeCode().equals(Role.PRINCIPAL_MEMBER_TYPE);
 444  0
             boolean isGroup = delegate.getDelegationTypeCode().equals(Role.GROUP_MEMBER_TYPE);
 445  0
                     if (isPrincipal) {
 446  0
                             recipient = new KimPrincipalRecipient(delegate.getDelegationId());
 447  0
                     } else if (isGroup) {
 448  0
                             recipient = new KimGroupRecipient(delegate.getDelegationId());
 449  
                     } else {
 450  0
                             throw new RiceRuntimeException("Invalid DelegateInfo memberTypeCode encountered, was '" + delegate.getDelegationTypeCode() + "'");
 451  
                     }
 452  0
                     String delegationAnnotation = generateRoleResponsibilityDelegateAnnotation(delegate, isPrincipal, isGroup, parentRequest);
 453  0
                     addDelegationRequest(parentRequest, recipient, delegate.getDelegationId(), parentRequest.getForceAction(), delegate.getDelegationTypeCode(), delegationAnnotation, null);
 454  0
             }
 455  0
     }
 456  
 
 457  
     private String generateRoleResponsibilityDelegateAnnotation(DelegateType delegate, boolean isPrincipal, boolean isGroup, ActionRequestValue parentRequest) {
 458  0
             StringBuffer annotation = new StringBuffer( "Delegation of: " );
 459  0
             annotation.append( parentRequest.getAnnotation() );
 460  0
             annotation.append( " to " );
 461  0
             if (isPrincipal) {
 462  0
                     annotation.append( "principal " );
 463  0
                     Principal principal = getIdentityService().getPrincipal( delegate.getDelegationId() );
 464  0
                     if ( principal != null ) {
 465  0
                             annotation.append( principal.getPrincipalName() );
 466  
                     } else {
 467  0
                             annotation.append( delegate.getDelegationId() );
 468  
                     }
 469  0
             } else if (isGroup) {
 470  0
                     annotation.append( "group " );
 471  0
                     Group group = getGroupService().getGroup( delegate.getDelegationId() );
 472  0
                     if ( group != null ) {
 473  0
                             annotation.append( group.getNamespaceCode() ).append( '/' ).append( group.getName() );
 474  
                     } else {
 475  0
                             annotation.append( delegate.getDelegationId() );
 476  
                     }
 477  0
             } else {
 478  0
                     annotation.append( "?????? '" );
 479  0
                         annotation.append( delegate.getDelegationId() );
 480  0
                     annotation.append( "'" );
 481  
             }
 482  0
             return annotation.toString();
 483  
     }
 484  
 
 485  
     public ActionRequestValue addDelegationRoleRequest(ActionRequestValue parentRequest, String approvePolicy, RoleRecipient role, String responsibilityId, Boolean forceAction, String delegationType, String description, String ruleId) {
 486  0
             Recipient parentRecipient = parentRequest.getRecipient();
 487  0
             if (parentRecipient instanceof RoleRecipient) {
 488  0
                     throw new WorkflowRuntimeException("Cannot delegate on Role Request.  It must be a request to a person or workgroup, although that request may be in a role");
 489  
             }
 490  0
             if (! relatedToRoot(parentRequest)) {
 491  0
                     throw new WorkflowRuntimeException("The parent request is not related to any request managed by this factory");
 492  
             }
 493  0
             ActionRequestValue delegationRoleRequest = createActionRequest(parentRequest.getActionRequested(), parentRequest.getPriority(), role, description, responsibilityId, forceAction, approvePolicy, ruleId, null);
 494  0
             delegationRoleRequest.setDelegationType(delegationType);
 495  0
             int count = 0;
 496  0
             for (Iterator<Id> iter = role.getResolvedQualifiedRole().getRecipients().iterator(); iter.hasNext(); count++) {
 497  
                     //repeat of createRoleRequest code
 498  0
                     Id recipientId = iter.next();
 499  0
                     if (recipientId.isEmpty()) {
 500  0
                                 throw new WorkflowRuntimeException("Failed to resolve id of type " + recipientId.getClass().getName() + " returned from role '" + role.getRoleName() + "'.  Id returned contained a null or empty value.");
 501  
                         }
 502  0
                         if (recipientId instanceof UserId) {
 503  0
                                 role.setTarget(new KimPrincipalRecipient(getIdentityHelperService().getPrincipal((UserId) recipientId)));
 504  0
                         } else if (recipientId instanceof GroupId) {
 505  0
                             role.setTarget(new KimGroupRecipient(getIdentityHelperService().getGroup((GroupId) recipientId)));
 506  
                         } else {
 507  0
                                 throw new WorkflowRuntimeException("Could not process the given type of id: " + recipientId.getClass());
 508  
                         }
 509  0
                         ActionRequestValue request = createActionRequest(parentRequest.getActionRequested(), parentRequest.getPriority(), role, description, responsibilityId, forceAction, null, ruleId, null);
 510  0
                         request.setDelegationType(delegationType);
 511  
                         //end repeat
 512  0
                         request.setParentActionRequest(delegationRoleRequest);
 513  0
                         delegationRoleRequest.getChildrenRequests().add(request);
 514  
             }
 515  
 
 516  
             //put this mini graph in the larger graph
 517  0
             if (count > 0) {
 518  0
                     parentRequest.getChildrenRequests().add(delegationRoleRequest);
 519  0
                     delegationRoleRequest.setParentActionRequest(parentRequest);
 520  
             }
 521  
 
 522  0
             return delegationRoleRequest;
 523  
     }
 524  
 
 525  
     public ActionRequestValue addDelegationRequest(ActionRequestValue parentRequest, Recipient recipient, String responsibilityId, Boolean forceAction, String delegationType, String annotation, String ruleId) {
 526  0
             if (! relatedToRoot(parentRequest)) {
 527  0
                     throw new WorkflowRuntimeException("The parent request is not related to any request managed by this factory");
 528  
             }
 529  0
             ActionRequestValue delegationRequest = createActionRequest(parentRequest.getActionRequested(), parentRequest.getPriority(), recipient, parentRequest.getResponsibilityDesc(), responsibilityId, forceAction, null, ruleId, annotation);
 530  0
             delegationRequest.setDelegationType(delegationType);
 531  
             
 532  0
         parentRequest.getChildrenRequests().add(delegationRequest); 
 533  0
         delegationRequest.setParentActionRequest(parentRequest);
 534  
 
 535  0
             return delegationRequest;
 536  
     }
 537  
 
 538  
     //could probably base behavior off of recipient type
 539  
     public ActionRequestValue addRootActionRequest(String actionRequested, Integer priority, Recipient recipient, String description, String responsibilityId, Boolean forceAction, String approvePolicy, String ruleId) {
 540  0
             ActionRequestValue requestGraph = createActionRequest(actionRequested, priority, recipient, description, responsibilityId, forceAction, approvePolicy, ruleId, null);
 541  0
             requestGraphs.add(requestGraph);
 542  0
             return requestGraph;
 543  
     }
 544  
 
 545  
 
 546  
 
 547  
     //return true if requestGraph (root) is in this requests' parents
 548  
     public boolean relatedToRoot(ActionRequestValue request) {
 549  0
             int i = 0;
 550  0
             while(i < 3) {
 551  0
                     if (requestGraphs.contains(request)) {
 552  0
                             return true;
 553  0
                     } else if (request == null) {
 554  0
                             return false;
 555  
                     }
 556  0
                     i++;
 557  0
                     request = request.getParentActionRequest();
 558  
             }
 559  0
             return false;
 560  
     }
 561  
 
 562  
         public List<ActionRequestValue> getRequestGraphs() {
 563  
                 //clean up all the trailing role requests with no children -
 564  0
                 requestGraphs.removeAll(cleanUpChildren(requestGraphs));
 565  0
                 return requestGraphs;
 566  
         }
 567  
 
 568  
         private Collection<ActionRequestValue> cleanUpChildren(Collection<ActionRequestValue> children) {
 569  0
                 Collection<ActionRequestValue> requestsToRemove = new ArrayList<ActionRequestValue>();
 570  0
         for (ActionRequestValue aChildren : children)
 571  
         {
 572  
 
 573  0
             if (aChildren.isRoleRequest())
 574  
             {
 575  0
                 if (aChildren.getChildrenRequests().isEmpty())
 576  
                 {
 577  0
                     requestsToRemove.add(aChildren);
 578  
                 } else
 579  
                 {
 580  0
                     Collection<ActionRequestValue> childRequestsToRemove = cleanUpChildren(aChildren.getChildrenRequests());
 581  0
                     aChildren.getChildrenRequests().removeAll(childRequestsToRemove);
 582  0
                                 }
 583  
                         }                                                                                 
 584  
                 }
 585  0
                 return requestsToRemove;
 586  
         }
 587  
 
 588  
     private String generateNotificationAnnotation(PrincipalContract principal, String notificationRequestCode, String actionTakenCode, ActionRequestValue request) {
 589  0
             String notification = "Action " + CodeTranslator.getActionRequestLabel(notificationRequestCode) + " generated by Workflow because " + principal.getPrincipalName() + " took action "
 590  
                                 + CodeTranslator.getActionTakenLabel(actionTakenCode);
 591  
             // FIXME: KULRICE-5201 switched rsp_id to a varchar, so the comparison below is no longer valid
 592  
 //            if (request.getResponsibilityId() != null && request.getResponsibilityId() != 0) {
 593  
             // TODO: KULRICE-5329 Verify that this code below makes sense and is sufficient
 594  0
             if (request.getResponsibilityId() != null && !KEWConstants.MACHINE_GENERATED_RESPONSIBILITY_ID.equals(request.getResponsibilityId())) {
 595  0
                     notification += " Responsibility " + request.getResponsibilityId();
 596  
             }
 597  0
             if (request.getRuleBaseValuesId() != null) {
 598  0
                     notification += " Rule Id " + request.getRuleBaseValuesId();
 599  
             }
 600  0
             if (request.getAnnotation() != null && request.getAnnotation().length()!=0){
 601  0
                     notification += " " + request.getAnnotation();
 602  
             }
 603  0
             return notification;
 604  
         }
 605  
 
 606  
     protected static ActionRequestService getActionRequestService() {
 607  0
                 if ( actionRequestService == null ) {
 608  0
                         actionRequestService = KEWServiceLocator.getActionRequestService();
 609  
                 }
 610  0
                 return actionRequestService;
 611  
     }
 612  
 
 613  
         /**
 614  
          * @return the roleService
 615  
          */
 616  
     protected static RoleService getRoleService() {
 617  0
                 if ( roleService == null ) {
 618  0
                         roleService = KimApiServiceLocator.getRoleService();
 619  
                 }
 620  0
                 return roleService;
 621  
         }
 622  
 
 623  
         /**
 624  
          * @return the identityHelperService
 625  
          */
 626  
     protected static IdentityHelperService getIdentityHelperService() {
 627  0
                 if ( identityHelperService == null ) {
 628  0
                         identityHelperService = KEWServiceLocator.getIdentityHelperService();
 629  
                 }
 630  0
                 return identityHelperService;
 631  
         }
 632  
 
 633  
         /**
 634  
          * @return the identityService
 635  
          */
 636  
     protected static IdentityService getIdentityService() {
 637  0
                 if ( identityService == null ) {
 638  0
                         identityService = KimApiServiceLocator.getIdentityService();
 639  
                 }
 640  0
                 return identityService;
 641  
         }
 642  
 
 643  
     protected static GroupService getGroupService() {
 644  0
                 if ( groupService == null ) {
 645  0
                         groupService = KimApiServiceLocator.getGroupService();
 646  
                 }
 647  0
                 return groupService;
 648  
         }
 649  
 }