View Javadoc

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