View Javadoc

1   /**
2    * Copyright 2005-2012 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.kim.web.struts.action;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.struts.action.ActionForm;
20  import org.apache.struts.action.ActionForward;
21  import org.apache.struts.action.ActionMapping;
22  import org.kuali.rice.core.api.membership.MemberType;
23  import org.kuali.rice.core.api.util.RiceConstants;
24  import org.kuali.rice.core.api.util.RiceKeyConstants;
25  import org.kuali.rice.kew.api.exception.WorkflowException;
26  import org.kuali.rice.kim.api.KimConstants;
27  import org.kuali.rice.kim.api.group.Group;
28  import org.kuali.rice.kim.api.identity.principal.Principal;
29  import org.kuali.rice.kim.api.role.Role;
30  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
31  import org.kuali.rice.kim.bo.ui.KimDocumentRoleMember;
32  import org.kuali.rice.kim.bo.ui.KimDocumentRolePermission;
33  import org.kuali.rice.kim.bo.ui.KimDocumentRoleQualifier;
34  import org.kuali.rice.kim.bo.ui.KimDocumentRoleResponsibility;
35  import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMember;
36  import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMemberQualifier;
37  import org.kuali.rice.kim.document.IdentityManagementRoleDocument;
38  import org.kuali.rice.kim.impl.responsibility.AddResponsibilityEvent;
39  import org.kuali.rice.kim.impl.responsibility.ResponsibilityBo;
40  import org.kuali.rice.kim.impl.type.KimTypeLookupableHelperServiceImpl;
41  import org.kuali.rice.kim.rule.event.ui.AddDelegationMemberEvent;
42  import org.kuali.rice.kim.rule.event.ui.AddMemberEvent;
43  import org.kuali.rice.kim.rule.event.ui.AddPermissionEvent;
44  import org.kuali.rice.kim.web.struts.form.IdentityManagementRoleDocumentForm;
45  import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
46  import org.kuali.rice.kns.web.struts.form.KualiTableRenderFormMetadata;
47  import org.kuali.rice.kns.question.ConfirmationQuestion;
48  import org.kuali.rice.krad.service.KRADServiceLocator;
49  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
50  import org.kuali.rice.krad.util.GlobalVariables;
51  import org.kuali.rice.krad.util.KRADConstants;
52  
53  import javax.servlet.http.HttpServletRequest;
54  import javax.servlet.http.HttpServletResponse;
55  import java.sql.Timestamp;
56  import java.util.ArrayList;
57  import java.util.Arrays;
58  import java.util.Calendar;
59  import java.util.HashMap;
60  import java.util.List;
61  import java.util.Map;
62  
63  /**
64   * @author Kuali Rice Team (rice.collab@kuali.org)
65   */
66  public class IdentityManagementRoleDocumentAction extends IdentityManagementDocumentActionBase {
67  
68      public static final String CHANGE_DEL_ROLE_MEMBER_METHOD_TO_CALL = "changeDelegationRoleMember";
69      public static final String SWITCH_TO_ROLE_MEMBER_METHOD_TO_CALL = "jumpToRoleMember";
70      public static final String REMOVE_AFFECTED_DELEGATES_QUESTION_ID = "RemoveAffectedDelegates";
71  
72      protected List<String> methodToCallToUncheckedList = new ArrayList<String>();
73  	
74      /**
75       * This method doesn't actually sort the column - it's just that we need a sort method in
76       * order to exploit the existing methodToCall logic. The sorting is handled in the execute
77       * method below, and delegated to the KualiTableRenderFormMetadata object. 
78       * 
79       * @param mapping
80       * @param form 
81       * @param request
82       * @param response
83       * @return
84       * @throws Exception
85       */
86      {
87          methodToCallToUncheckedList.add(CHANGE_DEL_ROLE_MEMBER_METHOD_TO_CALL);
88          methodToCallToUncheckedList.add(CHANGE_MEMBER_TYPE_CODE_METHOD_TO_CALL);
89          methodToCallToUncheckedList.add(CHANGE_NAMESPACE_METHOD_TO_CALL);
90          methodToCallToUncheckedList.add(SWITCH_TO_ROLE_MEMBER_METHOD_TO_CALL);
91      }
92  
93      /**
94       * This constructs a ...
95       */
96      public IdentityManagementRoleDocumentAction() {
97          super();
98          for (String methodToCallToUncheck : methodToCallToUncheckedList) {
99              addMethodToCallToUncheckedList(methodToCallToUncheck);
100         }
101     }
102 
103     public ActionForward sort(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
104 
105     	return mapping.findForward(RiceConstants.MAPPING_BASIC);
106     }
107 
108     @Override
109 	public ActionForward execute(ActionMapping mapping, ActionForm form,
110 			HttpServletRequest request, HttpServletResponse response) throws Exception {
111         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
112         if (roleDocumentForm.getRoleId() == null) {
113             String roleId = request.getParameter(KimConstants.PrimaryKeyConstants.SUB_ROLE_ID);
114             roleDocumentForm.setRoleId(roleId);
115         }
116 
117 		KualiTableRenderFormMetadata memberTableMetadata = roleDocumentForm.getMemberTableMetadata();
118 		if (roleDocumentForm.getRoleDocument()!=null && roleDocumentForm.getMemberRows() != null) {
119 			memberTableMetadata.jumpToPage(memberTableMetadata.getViewedPageNumber(), roleDocumentForm.getMemberRows().size(), roleDocumentForm.getRecordsPerPage());
120 			// KULRICE-3972: need to be able to sort by column header like on lookups when editing large roles and groups
121 			memberTableMetadata.sort(roleDocumentForm.getMemberRows(), roleDocumentForm.getRecordsPerPage());
122 		}
123 
124         // KULRICE-4762: active delegates of "inactivated" role members cause validation problems
125         ActionForward forward = promptForAffectedDelegates(mapping, form, request, response,
126                 roleDocumentForm);
127         // if we need to prompt the user due to affected delegates, do so:
128         if (forward != null) { return forward; }
129 
130         forward = super.execute(mapping, roleDocumentForm, request, response);
131 
132         roleDocumentForm.setCanAssignRole(validAssignRole(roleDocumentForm.getRoleDocument()));
133         if (KimTypeLookupableHelperServiceImpl.hasDerivedRoleTypeService(roleDocumentForm.getRoleDocument().getKimType())) {
134             roleDocumentForm.setCanModifyAssignees(false);
135         }
136         GlobalVariables.getUserSession().addObject(KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_SHORT_KEY, roleDocumentForm.getRoleDocument());
137         return forward;
138     }
139 
140     /**
141      * This overridden method ...
142      *
143      * @see org.kuali.rice.krad.web.struts.action.KualiDocumentActionBase#loadDocument(org.kuali.rice.krad.web.struts.form.KualiDocumentFormBase)
144      */
145     @Override
146     protected void loadDocument(KualiDocumentFormBase form)
147             throws WorkflowException {
148         super.loadDocument(form);
149 
150         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
151         setKimType(roleDocumentForm.getRoleDocument().getRoleTypeId(), roleDocumentForm);
152         getUiDocumentService().setDelegationMembersInDocument(roleDocumentForm.getRoleDocument());
153 
154         roleDocumentForm.setMember(roleDocumentForm.getRoleDocument().getBlankMember());
155         roleDocumentForm.setDelegationMember(roleDocumentForm.getRoleDocument().getBlankDelegationMember());
156 
157         KualiTableRenderFormMetadata memberTableMetadata = roleDocumentForm.getMemberTableMetadata();
158         if (roleDocumentForm.getMemberRows() != null) {
159             memberTableMetadata.jumpToFirstPage(roleDocumentForm.getMemberRows().size(), roleDocumentForm.getRecordsPerPage());
160         }
161     }
162 
163     /**
164      * This overridden method ...
165      *
166      * @see org.kuali.rice.krad.web.struts.action.KualiDocumentActionBase#createDocument(org.kuali.rice.krad.web.struts.form.KualiDocumentFormBase)
167      */
168     @Override
169     protected void createDocument(KualiDocumentFormBase form)
170             throws WorkflowException {
171         super.createDocument(form);
172         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
173 
174         if (roleDocumentForm.getRoleId() == null) {
175             roleDocumentForm.getRoleDocument().setKimType(roleDocumentForm.getKimType());
176             roleDocumentForm.getRoleDocument().initializeDocumentForNewRole();
177             roleDocumentForm.setRoleId(roleDocumentForm.getRoleDocument().getRoleId());
178             //roleDocumentForm.setKimType(KimApiServiceLocator.getKimTypeInfoService().getKimType(roleDocumentForm.getRoleDocument().getRoleTypeId()));
179         } else {
180             loadRoleIntoDocument(roleDocumentForm.getRoleId(), roleDocumentForm);
181         }
182 
183         roleDocumentForm.setMember(roleDocumentForm.getRoleDocument().getBlankMember());
184         roleDocumentForm.setDelegationMember(roleDocumentForm.getRoleDocument().getBlankDelegationMember());
185 
186         KualiTableRenderFormMetadata memberTableMetadata = roleDocumentForm.getMemberTableMetadata();
187         if (roleDocumentForm.getMemberRows() != null) {
188             memberTableMetadata.jumpToFirstPage(roleDocumentForm.getMemberRows().size(), roleDocumentForm.getRecordsPerPage());
189         }
190     }
191 
192     protected void setKimType(String kimTypeId, IdentityManagementRoleDocumentForm roleDocumentForm) {
193         if (StringUtils.isNotBlank(kimTypeId)) {
194             roleDocumentForm.setKimType(KimApiServiceLocator.getKimTypeInfoService().getKimType(kimTypeId));
195             if (roleDocumentForm.getRoleDocument() != null) {
196                 roleDocumentForm.getRoleDocument().setKimType(roleDocumentForm.getKimType());
197             }
198         } else if (roleDocumentForm.getRoleDocument() != null && StringUtils.isNotBlank(roleDocumentForm.getRoleDocument().getRoleTypeId())) {
199             roleDocumentForm.setKimType(KimApiServiceLocator.getKimTypeInfoService().getKimType(
200                     roleDocumentForm.getRoleDocument().getRoleTypeId()));
201             roleDocumentForm.getRoleDocument().setKimType(roleDocumentForm.getKimType());
202         }
203     }
204 
205     protected void loadRoleIntoDocument(String roleId, IdentityManagementRoleDocumentForm roleDocumentForm) {
206         Role role = KimApiServiceLocator.getRoleService().getRole(roleId);
207         roleDocumentForm.getRoleDocument().setMemberMetaDataTypeToSort(roleDocumentForm.getMemberTableMetadata().getColumnToSortIndex());
208         getUiDocumentService().loadRoleDoc(roleDocumentForm.getRoleDocument(), role);
209     }
210 
211     /**
212      * @see org.kuali.rice.kim.web.struts.action.IdentityManagementDocumentActionBase#getActionName()
213      */
214     public String getActionName() {
215         return KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_ACTION;
216     }
217 
218     protected boolean validAssignRole(IdentityManagementRoleDocument document) {
219         boolean rulePassed = true;
220         if (StringUtils.isNotEmpty(document.getRoleNamespace())) {
221             Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
222             additionalPermissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, document.getRoleNamespace());
223             additionalPermissionDetails.put(KimConstants.AttributeConstants.ROLE_NAME, document.getRoleName());
224             if (!getDocumentHelperService().getDocumentAuthorizer(document).isAuthorizedByTemplate(
225                     document,
226                     KimConstants.NAMESPACE_CODE,
227                     KimConstants.PermissionTemplateNames.ASSIGN_ROLE,
228                     GlobalVariables.getUserSession().getPrincipalId(),
229                     additionalPermissionDetails, null)) {
230                 rulePassed = false;
231             }
232         }
233         return rulePassed;
234     }
235 
236     public ActionForward changeMemberTypeCode(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
237         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
238         roleDocumentForm.getMember().setMemberId("");
239         return refresh(mapping, roleDocumentForm, request, response);
240     }
241 
242     public ActionForward changeDelegationMemberTypeCode(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
243         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
244         KimDocumentRoleMember roleMember = roleDocumentForm.getRoleDocument().getMember(roleDocumentForm.getDelegationMember().getRoleMemberId());
245         if (roleMember != null) {
246             RoleDocumentDelegationMemberQualifier delegationMemberQualifier;
247             for (KimDocumentRoleQualifier roleQualifier : roleMember.getQualifiers()) {
248                 delegationMemberQualifier = roleDocumentForm.getDelegationMember().getQualifier(roleQualifier.getKimAttrDefnId());
249                 delegationMemberQualifier.setAttrVal(roleQualifier.getAttrVal());
250             }
251         }
252         return refresh(mapping, roleDocumentForm, request, response);
253     }
254 
255     public ActionForward addResponsibility(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
256         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
257         KimDocumentRoleResponsibility newResponsibility = roleDocumentForm.getResponsibility();
258         if (newResponsibility != null && StringUtils.isNotBlank(newResponsibility.getResponsibilityId())) {
259             Map<String, String> criteria = new HashMap<String, String>();
260             criteria.put(KimConstants.PrimaryKeyConstants.RESPONSIBILITY_ID, newResponsibility.getResponsibilityId());
261             ResponsibilityBo responsibilityImpl = KRADServiceLocator.getBusinessObjectService().findByPrimaryKey(ResponsibilityBo.class, criteria);
262             newResponsibility.setKimResponsibility(responsibilityImpl);
263         }
264 
265         if (KRADServiceLocatorWeb.getKualiRuleService().applyRules(new AddResponsibilityEvent("", roleDocumentForm.getRoleDocument(), newResponsibility))) {
266             if (newResponsibility != null) {
267                 newResponsibility.setDocumentNumber(roleDocumentForm.getDocument().getDocumentNumber());
268             }
269             roleDocumentForm.getRoleDocument().addResponsibility(newResponsibility);
270             roleDocumentForm.setResponsibility(new KimDocumentRoleResponsibility());
271             roleDocumentForm.getRoleDocument().updateMembers(newResponsibility);
272         }
273         return mapping.findForward(RiceConstants.MAPPING_BASIC);
274     }
275 
276     public ActionForward deleteResponsibility(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
277         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
278         roleDocumentForm.getRoleDocument().getResponsibilities().remove(getLineToDelete(request));
279         roleDocumentForm.getRoleDocument().updateMembers(roleDocumentForm);
280         return mapping.findForward(RiceConstants.MAPPING_BASIC);
281     }
282 
283     public ActionForward addPermission(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
284         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
285         KimDocumentRolePermission newPermission = roleDocumentForm.getPermission();
286         if (KRADServiceLocatorWeb.getKualiRuleService().applyRules(new AddPermissionEvent("", roleDocumentForm.getRoleDocument(), newPermission))) {
287             newPermission.setDocumentNumber(roleDocumentForm.getDocument().getDocumentNumber());
288             newPermission.setRoleId(roleDocumentForm.getRoleDocument().getRoleId());
289             roleDocumentForm.getRoleDocument().getPermissions().add(newPermission);
290             roleDocumentForm.setPermission(new KimDocumentRolePermission());
291         }
292         return mapping.findForward(RiceConstants.MAPPING_BASIC);
293     }
294 
295     public ActionForward addMember(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
296         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
297         KimDocumentRoleMember newMember = roleDocumentForm.getMember();
298 
299         //See if possible to add with just Group Details filled in (not returned from lookup)
300         if (StringUtils.isEmpty(newMember.getMemberId())
301                 && StringUtils.isNotEmpty(newMember.getMemberName())
302                 && StringUtils.isNotEmpty(newMember.getMemberNamespaceCode())
303                 && StringUtils.equals(newMember.getMemberTypeCode(), KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE.getCode())) {
304             Group tempGroup = KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName(
305                     newMember.getMemberNamespaceCode(), newMember.getMemberName());
306             if (tempGroup != null) {
307                 newMember.setMemberId(tempGroup.getId());
308             }
309         }
310 
311         //See if possible to grab details for Principal
312         if (StringUtils.isEmpty(newMember.getMemberId())
313                 && StringUtils.isNotEmpty(newMember.getMemberName())
314                 && StringUtils.equals(newMember.getMemberTypeCode(), KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.getCode())) {
315             Principal principal = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(newMember.getMemberName());
316             if (principal != null) {
317                 newMember.setMemberId(principal.getPrincipalId());
318             }
319         }
320         if (checkKimDocumentRoleMember(newMember) &&
321                 KRADServiceLocatorWeb.getKualiRuleService().applyRules(new AddMemberEvent("", roleDocumentForm.getRoleDocument(), newMember))) {
322             newMember.setDocumentNumber(roleDocumentForm.getDocument().getDocumentNumber());
323             roleDocumentForm.getRoleDocument().addMember(newMember);
324             roleDocumentForm.setMember(roleDocumentForm.getRoleDocument().getBlankMember());
325             roleDocumentForm.getMemberTableMetadata().jumpToLastPage(roleDocumentForm.getMemberRows().size(), roleDocumentForm.getRecordsPerPage());
326         }
327         return mapping.findForward(RiceConstants.MAPPING_BASIC);
328     }
329 
330     protected boolean checkKimDocumentRoleMember(KimDocumentRoleMember newMember) {
331         boolean memberExists = false;
332         String memberName = null;
333         String memberNamespace = null;
334 
335         if (StringUtils.isBlank(newMember.getMemberTypeCode()) || StringUtils.isBlank(newMember.getMemberId())) {
336             GlobalVariables.getMessageMap().putError("document.member.memberId", RiceKeyConstants.ERROR_EMPTY_ENTRY,
337                     new String[]{"Member Type Code and Member ID"});
338             return false;
339         }
340 
341         if (MemberType.PRINCIPAL.getCode().equals(newMember.getMemberTypeCode())) {
342             Principal pi = this.getIdentityService().getPrincipal(newMember.getMemberId());
343             if (pi != null) {
344                 memberExists = true;
345                 memberName = pi.getPrincipalName();
346                 memberNamespace = "";
347             }
348         } else if (MemberType.GROUP.getCode().equals(newMember.getMemberTypeCode())) {
349             Group gi = KimApiServiceLocator.getGroupService().getGroup(newMember.getMemberId());
350             if (gi != null) {
351                 memberExists = true;
352                 memberName = gi.getName();
353                 memberNamespace = gi.getNamespaceCode();
354             }
355         } else if (MemberType.ROLE.getCode().equals(newMember.getMemberTypeCode())) {
356             Role ri = KimApiServiceLocator.getRoleService().getRole(newMember.getMemberId());
357             if (!validateRole(newMember.getMemberId(), ri, "document.member.memberId", "Role")) {
358                 return false;
359             } else {
360                 memberExists = true;
361                 memberName = ri.getName();
362                 memberNamespace = ri.getNamespaceCode();
363             }
364         }
365 
366         if (!memberExists) {
367             GlobalVariables.getMessageMap().putError("document.member.memberId", RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
368                     new String[]{newMember.getMemberId()});
369             return false;
370         }
371         newMember.setMemberName(memberName);
372         newMember.setMemberNamespaceCode(memberNamespace);
373         return true;
374     }
375 
376     public ActionForward deleteMember(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
377         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
378         KimDocumentRoleMember inactivatedRoleMember = roleDocumentForm.getRoleDocument().getMembers().get(getLineToDelete(request));
379 
380         // KULRICE-4762: active delegates of "inactivated" role members cause validation problems
381         ActionForward forward = promptForAffectedDelegates(mapping, form, request, response,
382                 roleDocumentForm, /* we haven't actually inactivated them yet, so specify them here */ inactivatedRoleMember);
383         // if we need to prompt the user due to affected delegates, do so:
384         if (forward != null) {
385             return forward;
386         }
387 
388         Calendar cal = Calendar.getInstance();
389         inactivatedRoleMember.setActiveToDate(new Timestamp(cal.getTimeInMillis()));
390 
391         roleDocumentForm.getRoleDocument().getMembers().set(getLineToDelete(request), inactivatedRoleMember);
392         return mapping.findForward(RiceConstants.MAPPING_BASIC);
393     }
394 
395     public ActionForward deletePermission(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
396         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
397         roleDocumentForm.getRoleDocument().getPermissions().remove(getLineToDelete(request));
398         return mapping.findForward(RiceConstants.MAPPING_BASIC);
399     }
400 
401     protected boolean checkDelegationMember(RoleDocumentDelegationMember newMember) {
402         if (StringUtils.isBlank(newMember.getMemberTypeCode()) || StringUtils.isBlank(newMember.getMemberId())) {
403             GlobalVariables.getMessageMap().putError("document.delegationMember.memberId", RiceKeyConstants.ERROR_EMPTY_ENTRY,
404                     new String[]{"Member Type Code and Member ID"});
405             return false;
406         }
407         if (MemberType.PRINCIPAL.getCode().equals(newMember.getMemberTypeCode())) {
408             Principal principalInfo = getIdentityService().getPrincipal(newMember.getMemberId());
409             if (principalInfo == null) {
410                 GlobalVariables.getMessageMap().putError("document.delegationMember.memberId", RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
411                         new String[]{newMember.getMemberId()});
412                 return false;
413             } else {
414                 newMember.setMemberName(principalInfo.getPrincipalName());
415             }
416         } else if (MemberType.GROUP.getCode().equals(newMember.getMemberTypeCode())) {
417             Group groupInfo = null;
418             groupInfo = getGroupService().getGroup(newMember.getMemberId());
419             if (groupInfo == null) {
420                 GlobalVariables.getMessageMap().putError("document.delegationMember.memberId", RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
421                         new String[]{newMember.getMemberId()});
422                 return false;
423             } else {
424                 newMember.setMemberName(groupInfo.getName());
425                 newMember.setMemberNamespaceCode(groupInfo.getNamespaceCode());
426             }
427         } else if (MemberType.ROLE.getCode().equals(newMember.getMemberTypeCode())) {
428             Role roleInfo = KimApiServiceLocator.getRoleService().getRole(newMember.getMemberId());
429             if (roleInfo == null) {
430                 GlobalVariables.getMessageMap().putError("document.delegationMember.memberId", RiceKeyConstants.ERROR_MEMBERID_MEMBERTYPE_MISMATCH,
431                         new String[]{newMember.getMemberId()});
432                 return false;
433             } else {
434                 newMember.setMemberName(roleInfo.getName());
435                 newMember.setMemberNamespaceCode(roleInfo.getNamespaceCode());
436             }
437         }
438         return true;
439     }
440 
441     public ActionForward addDelegationMember(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
442         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
443         RoleDocumentDelegationMember newDelegationMember = roleDocumentForm.getDelegationMember();
444 
445         //See if possible to add with just Group Details filled in (not returned from lookup)
446         if (StringUtils.isEmpty(newDelegationMember.getMemberId())
447                 && StringUtils.isNotEmpty(newDelegationMember.getMemberName())
448                 && StringUtils.isNotEmpty(newDelegationMember.getMemberNamespaceCode())
449                 && StringUtils.equals(newDelegationMember.getMemberTypeCode(), KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE.getCode())) {
450             Group tempGroup = KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName(
451                     newDelegationMember.getMemberNamespaceCode(), newDelegationMember.getMemberName());
452             if (tempGroup != null) {
453                 newDelegationMember.setMemberId(tempGroup.getId());
454             }
455         }
456 
457         //See if possible to grab details for Principal
458         if (StringUtils.isEmpty(newDelegationMember.getMemberId())
459                 && StringUtils.isNotEmpty(newDelegationMember.getMemberName())
460                 && StringUtils.equals(newDelegationMember.getMemberTypeCode(), KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.getCode())) {
461             Principal principal = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(newDelegationMember.getMemberName());
462             if (principal != null) {
463                 newDelegationMember.setMemberId(principal.getPrincipalId());
464             }
465         }
466 
467         if (checkDelegationMember(newDelegationMember) && KRADServiceLocatorWeb.getKualiRuleService().applyRules(
468                 new AddDelegationMemberEvent("", roleDocumentForm.getRoleDocument(), newDelegationMember))) {
469             newDelegationMember.setDocumentNumber(roleDocumentForm.getDocument().getDocumentNumber());
470             roleDocumentForm.getRoleDocument().addDelegationMember(newDelegationMember);
471             roleDocumentForm.setDelegationMember(roleDocumentForm.getRoleDocument().getBlankDelegationMember());
472         }
473         return mapping.findForward(RiceConstants.MAPPING_BASIC);
474     }
475 
476     public ActionForward deleteDelegationMember(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
477         IdentityManagementRoleDocumentForm roleDocumentForm = (IdentityManagementRoleDocumentForm) form;
478         // Removing, not inactivating -- is this what we really want?
479         roleDocumentForm.getRoleDocument().getDelegationMembers().remove(getLineToDelete(request));
480         roleDocumentForm.setDelegationMember(roleDocumentForm.getRoleDocument().getBlankDelegationMember());
481         return mapping.findForward(RiceConstants.MAPPING_BASIC);
482     }
483 
484     /**
485      * @see org.kuali.rice.kns.web.struts.action.KualiTableRenderAction#switchToPage(org.apache.struts.action.ActionMapping,
486      *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
487      */
488     public ActionForward jumpToRoleMember(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
489         IdentityManagementRoleDocumentForm idmForm = (IdentityManagementRoleDocumentForm) form;
490         String delegationRoleMemberId = getDelegationRoleMemberToJumpTo(request);
491         KualiTableRenderFormMetadata memberTableMetadata = idmForm.getMemberTableMetadata();
492         memberTableMetadata.jumpToPage(idmForm.getPageNumberOfRoleMemberId(delegationRoleMemberId),
493                 idmForm.getMemberRows().size(), idmForm.getRecordsPerPage());
494         memberTableMetadata.setColumnToSortIndex(memberTableMetadata.getPreviouslySortedColumnIndex());
495         idmForm.setAnchor(delegationRoleMemberId);
496         return mapping.findForward(RiceConstants.MAPPING_BASIC);
497     }
498 
499     protected String getDelegationRoleMemberToJumpTo(HttpServletRequest request) {
500         String delegationRoleMemberIdToJumpTo = "";
501         String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
502         if (StringUtils.isNotBlank(parameterName)) {
503             delegationRoleMemberIdToJumpTo = StringUtils.substringBetween(parameterName, ".dmrmi", ".");
504         }
505         return delegationRoleMemberIdToJumpTo;
506     }
507 
508 
509     /**
510      * Side-effecting method returns an ActionForward if needed for handling prompting of the user about automatically
511      * "inactivating" active delegates of inactive role members.  If the user has already responded "Yes", delegates are
512      * "inactivated" here, and a null forward is returned.  Otherwise, an appropriate forward is returned.
513      *
514      * @param roleMembersToConsiderInactive additional role members to consider inactive for the purposes of this computation
515      */
516     private ActionForward promptForAffectedDelegates(ActionMapping mapping,
517                                                      ActionForm form, HttpServletRequest request,
518                                                      HttpServletResponse response,
519                                                      IdentityManagementRoleDocumentForm roleDocumentForm, KimDocumentRoleMember... roleMembersToConsiderInactive)
520             throws Exception {
521         // KULRICE-4762: Role: Removed an Assignee who has delegations associated with him and now the Role cannot be updated
522         // To solve this issue, prompt for confirmation if there are active delegates for the role member being "inactivated",
523         // and upon confirmation, "inactivate" the delegates too.
524         List<RoleDocumentDelegationMember> activeDelegatesOfInactiveRoleMembers =
525                 getActiveDelegatesOfInactiveRoleMembers(roleDocumentForm, roleMembersToConsiderInactive);
526         ActionForward forward = getAffectedDelegatesQuestionActionForward(activeDelegatesOfInactiveRoleMembers, mapping, form, request,
527                 response, roleDocumentForm);
528         // if the question logic gave us a forward, do it
529         if (forward != null) {
530             return forward;
531         }
532         // otherwise, inactivate affected delegates
533         if (activeDelegatesOfInactiveRoleMembers.size() > 0) {
534             Calendar cal = Calendar.getInstance();
535             // deactivate (inactivate?) delegates
536             for (RoleDocumentDelegationMember delegateToDeactivate : activeDelegatesOfInactiveRoleMembers) {
537                 delegateToDeactivate.setActiveToDate(new Timestamp(cal.getTimeInMillis()));
538             }
539         }
540         return null;
541     }
542 
543     /**
544      * <p>If there are active delegates of an "inactivated" role member, return an ActionForward to prompt the user
545      * letting them know that the delegates will be "inactivated" too if they proceed.
546      * <p>Also, if the user has already responded to the question and the response was (1) "Yes", then return null, signifying
547      * that we can go ahead and take the needed action to "inactivate" the delegates; or (2) "No", then return a basic forward that
548      * will cancel further action.
549      */
550     private ActionForward getAffectedDelegatesQuestionActionForward(List<RoleDocumentDelegationMember> activeDelegatesOfInactiveRoleMembers,
551                                                                     ActionMapping mapping, ActionForm form, HttpServletRequest request,
552                                                                     HttpServletResponse response,
553                                                                     IdentityManagementRoleDocumentForm roleDocumentForm)
554             throws Exception {
555 
556         if (activeDelegatesOfInactiveRoleMembers.size() > 0) {
557             Object question = getQuestion(request);
558             // logic for delegates question
559             if (question == null || !REMOVE_AFFECTED_DELEGATES_QUESTION_ID.equals(question)) {
560                 return performQuestionWithoutInput(mapping, form, request, response, REMOVE_AFFECTED_DELEGATES_QUESTION_ID,
561                         getKualiConfigurationService().getPropertyValueAsString(
562                                 RiceKeyConstants.QUESTION_ACTIVE_DELEGATES_FOR_INACTIVE_MEMBERS),
563                         KRADConstants.CONFIRMATION_QUESTION, roleDocumentForm.getMethodToCall(), StringUtils.EMPTY);
564             }
565             Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
566             if ((REMOVE_AFFECTED_DELEGATES_QUESTION_ID.equals(question)) && ConfirmationQuestion.YES.equals(buttonClicked)) {
567                 // the question was answered in the affirmative.
568                 // fall through, no special mapping to return
569             } else {
570                 // NO was clicked ... what to do?  Return basic mapping without "inactivating" anything
571                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
572             }
573         }
574 
575         return null;
576     }
577 
578     /**
579      * This method returns a list of all active delegates for role members that are inactive
580      *
581      * @param roleDocumentForm              form bean
582      * @param roleMembersToConsiderInactive additional role members to consider inactive for the purposes of this computation
583      * @return the active delegates of inactive role members
584      */
585     private List<RoleDocumentDelegationMember> getActiveDelegatesOfInactiveRoleMembers(
586             IdentityManagementRoleDocumentForm roleDocumentForm, KimDocumentRoleMember... roleMembersToConsiderInactive) {
587         List<KimDocumentRoleMember> roleMembers = roleDocumentForm.getMemberRows();
588         List<KimDocumentRoleMember> inactiveRoleMembers = new ArrayList<KimDocumentRoleMember>();
589         List<RoleDocumentDelegationMember> activeDelegatesOfInactivatedRoleMembers = new ArrayList<RoleDocumentDelegationMember>();
590 
591         inactiveRoleMembers.addAll(Arrays.asList(roleMembersToConsiderInactive));
592 
593         if (roleMembers != null) {
594             for (KimDocumentRoleMember roleMember : roleMembers) {
595                 if (roleMember != null) {
596                     if (!roleMember.isActive()) {
597                         inactiveRoleMembers.add(roleMember);
598                     }
599                 }
600             }
601         }
602 
603         for (KimDocumentRoleMember inactiveRoleMember : inactiveRoleMembers) {
604             // check if there are delegates for the member being removed
605             List<RoleDocumentDelegationMember> delegationMembers = roleDocumentForm.getRoleDocument().getDelegationMembers();
606             if (delegationMembers != null) {
607                 for (RoleDocumentDelegationMember delegationMember : delegationMembers) {
608                     if (delegationMember != null && delegationMember.isActive()) {
609                         // if the roleMember for this delegation is the same as the inactivatedRoleMember
610                         if (delegationMember.getRoleMemberId().equals(inactiveRoleMember.getRoleMemberId())) {
611                             activeDelegatesOfInactivatedRoleMembers.add(delegationMember);
612                         }
613                     }
614                 }
615             }
616         }
617         return activeDelegatesOfInactivatedRoleMembers;
618     }
619 
620     /**
621      * This method overrides validateRole() from IdentityManagementDocumentActionBase.
622      * The difference with this method is that it allows derived roles.
623      * The base implementation returns false if the role is a derived role.
624      *
625      */
626     @Override
627     protected boolean validateRole(String roleId, Role role, String propertyName, String message) {
628         if (role == null) {
629             GlobalVariables.getMessageMap().putError(propertyName, RiceKeyConstants.ERROR_INVALID_ROLE, roleId);
630             return false;
631         }
632         return true;
633     }
634 
635 
636 }