View Javadoc

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