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