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