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