View Javadoc
1   /*******************************************************************************
2    * Copyright 2014 Internet2
3    *  
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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 edu.internet2.middleware.grouper.grouperUi.serviceLogic;
17  
18  import java.util.Collection;
19  import java.util.Collections;
20  import java.util.Comparator;
21  import java.util.Date;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.LinkedHashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.TreeSet;
29  import java.util.regex.Matcher;
30  import java.util.regex.Pattern;
31  
32  import javax.servlet.http.HttpServletRequest;
33  import javax.servlet.http.HttpServletResponse;
34  
35  import org.apache.commons.lang.StringUtils;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  
39  import edu.internet2.middleware.grouper.Composite;
40  import edu.internet2.middleware.grouper.CompositeFinder;
41  import edu.internet2.middleware.grouper.Field;
42  import edu.internet2.middleware.grouper.FieldFinder;
43  import edu.internet2.middleware.grouper.FieldType;
44  import edu.internet2.middleware.grouper.Group;
45  import edu.internet2.middleware.grouper.GroupCopy;
46  import edu.internet2.middleware.grouper.GroupFinder;
47  import edu.internet2.middleware.grouper.GroupMove;
48  import edu.internet2.middleware.grouper.GroupSave;
49  import edu.internet2.middleware.grouper.GrouperSession;
50  import edu.internet2.middleware.grouper.GrouperSourceAdapter;
51  import edu.internet2.middleware.grouper.Member;
52  import edu.internet2.middleware.grouper.MemberFinder;
53  import edu.internet2.middleware.grouper.Membership;
54  import edu.internet2.middleware.grouper.MembershipFinder;
55  import edu.internet2.middleware.grouper.Stem;
56  import edu.internet2.middleware.grouper.StemFinder;
57  import edu.internet2.middleware.grouper.SubjectFinder;
58  import edu.internet2.middleware.grouper.app.grouperTypes.GrouperObjectTypesAttributeValue;
59  import edu.internet2.middleware.grouper.app.grouperTypes.GrouperObjectTypesConfiguration;
60  import edu.internet2.middleware.grouper.app.loader.GrouperLoader;
61  import edu.internet2.middleware.grouper.app.loader.GrouperLoaderType;
62  import edu.internet2.middleware.grouper.app.loader.ldap.LoaderLdapUtils;
63  import edu.internet2.middleware.grouper.app.workflow.GrouperWorkflowConfig;
64  import edu.internet2.middleware.grouper.app.workflow.GrouperWorkflowConfigService;
65  import edu.internet2.middleware.grouper.app.workflow.GrouperWorkflowInstance;
66  import edu.internet2.middleware.grouper.app.workflow.GrouperWorkflowInstanceService;
67  import edu.internet2.middleware.grouper.attr.AttributeDef;
68  import edu.internet2.middleware.grouper.attr.AttributeDefName;
69  import edu.internet2.middleware.grouper.attr.assign.AttributeAssign;
70  import edu.internet2.middleware.grouper.attr.finder.AttributeAssignValueFinder;
71  import edu.internet2.middleware.grouper.attr.finder.AttributeAssignValueFinder.AttributeAssignValueFinderResult;
72  import edu.internet2.middleware.grouper.attr.finder.AttributeDefFinder;
73  import edu.internet2.middleware.grouper.attr.finder.AttributeDefNameFinder;
74  import edu.internet2.middleware.grouper.audit.AuditEntry;
75  import edu.internet2.middleware.grouper.audit.UserAuditQuery;
76  import edu.internet2.middleware.grouper.cfg.GrouperConfig;
77  import edu.internet2.middleware.grouper.exception.GroupDeleteException;
78  import edu.internet2.middleware.grouper.exception.GroupNotFoundException;
79  import edu.internet2.middleware.grouper.exception.GrouperSessionException;
80  import edu.internet2.middleware.grouper.exception.GrouperValidationException;
81  import edu.internet2.middleware.grouper.exception.InsufficientPrivilegeException;
82  import edu.internet2.middleware.grouper.group.TypeOfGroup;
83  import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiGroup;
84  import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiMembershipSubjectContainer;
85  import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiPITMembershipView;
86  import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiRuleDefinition;
87  import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiSubject;
88  import edu.internet2.middleware.grouper.grouperUi.beans.api.objectTypes.GuiGrouperObjectTypesAttributeValue;
89  import edu.internet2.middleware.grouper.grouperUi.beans.dojo.DojoComboLogic;
90  import edu.internet2.middleware.grouper.grouperUi.beans.dojo.DojoComboQueryLogicBase;
91  import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiPaging;
92  import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiResponseJs;
93  import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiScreenAction;
94  import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiScreenAction.GuiMessageType;
95  import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiSorting;
96  import edu.internet2.middleware.grouper.grouperUi.beans.ui.GroupContainer;
97  import edu.internet2.middleware.grouper.grouperUi.beans.ui.GrouperLoaderContainer;
98  import edu.internet2.middleware.grouper.grouperUi.beans.ui.GrouperRequestContainer;
99  import edu.internet2.middleware.grouper.grouperUi.beans.ui.GuiAuditEntry;
100 import edu.internet2.middleware.grouper.grouperUi.beans.ui.GuiGrouperWorkflowConfig;
101 import edu.internet2.middleware.grouper.grouperUi.beans.ui.GuiLoaderManagedGroup;
102 import edu.internet2.middleware.grouper.grouperUi.beans.ui.RulesContainer;
103 import edu.internet2.middleware.grouper.grouperUi.beans.ui.TextContainer;
104 import edu.internet2.middleware.grouper.grouperUi.beans.ui.WorkflowContainer;
105 import edu.internet2.middleware.grouper.hooks.examples.MembershipCannotAddSelfToGroupHook;
106 import edu.internet2.middleware.grouper.internal.dao.QueryOptions;
107 import edu.internet2.middleware.grouper.membership.MembershipSubjectContainer;
108 import edu.internet2.middleware.grouper.membership.MembershipType;
109 import edu.internet2.middleware.grouper.misc.CompositeType;
110 import edu.internet2.middleware.grouper.misc.GrouperCheckConfig;
111 import edu.internet2.middleware.grouper.misc.GrouperDAOFactory;
112 import edu.internet2.middleware.grouper.misc.GrouperSessionHandler;
113 import edu.internet2.middleware.grouper.misc.SaveMode;
114 import edu.internet2.middleware.grouper.misc.SaveResultType;
115 import edu.internet2.middleware.grouper.pit.PITMembershipView;
116 import edu.internet2.middleware.grouper.privs.AccessPrivilege;
117 import edu.internet2.middleware.grouper.privs.AttributeDefPrivilege;
118 import edu.internet2.middleware.grouper.privs.NamingPrivilege;
119 import edu.internet2.middleware.grouper.privs.Privilege;
120 import edu.internet2.middleware.grouper.rules.RuleDefinition;
121 import edu.internet2.middleware.grouper.rules.RuleFinder;
122 import edu.internet2.middleware.grouper.subj.GrouperSubject;
123 import edu.internet2.middleware.grouper.subj.SubjectBean;
124 import edu.internet2.middleware.grouper.subj.SubjectHelper;
125 import edu.internet2.middleware.grouper.subj.UnresolvableSubject;
126 import edu.internet2.middleware.grouper.ui.GrouperUiFilter;
127 import edu.internet2.middleware.grouper.ui.tags.GrouperPagingTag2;
128 import edu.internet2.middleware.grouper.ui.util.GrouperUiConfig;
129 import edu.internet2.middleware.grouper.ui.util.GrouperUiUserData;
130 import edu.internet2.middleware.grouper.ui.util.GrouperUiUtils;
131 import edu.internet2.middleware.grouper.userData.GrouperUserDataApi;
132 import edu.internet2.middleware.grouper.util.GrouperUtil;
133 import edu.internet2.middleware.subject.Source;
134 import edu.internet2.middleware.subject.Subject;
135 import edu.internet2.middleware.subject.SubjectNotUniqueException;
136 import edu.internet2.middleware.subject.provider.SourceManager;
137 
138 /**
139  * operations in the group screen
140  * @author mchyzer
141  *
142  */
143 public class UiV2Group {
144 
145   
146   /**
147    * results from retrieving results
148    *
149    */
150   public static class RetrieveGroupHelperResult {
151   
152     /**
153      * group
154      */
155     private Group group;
156   
157     /**
158      * group
159      * @return group
160      */
161     public Group getGroup() {
162       return this.group;
163     }
164   
165     /**
166      * group
167      * @param group1
168      */
169     public void setGroup(Group group1) {
170       this.group = group1;
171     }
172     
173     /**
174      * if added error to screen
175      */
176     private boolean addedError;
177   
178     /**
179      * if added error to screen
180      * @return if error
181      */
182     public boolean isAddedError() {
183       return this.addedError;
184     }
185   
186     /**
187      * if added error to screen
188      * @param addedError1
189      */
190     public void setAddedError(boolean addedError1) {
191       this.addedError = addedError1;
192     }
193   }
194 
195   
196   /**
197    * view this groups privileges inherited from folders
198    * @param request
199    * @param response
200    */
201   public void thisGroupMembersPrivilegesInheritedFromFolders(HttpServletRequest request, HttpServletResponse response) {
202     //TODO 
203     
204   }
205   
206   /**
207    * view this groups privileges inherited from folders
208    * @param request
209    * @param response
210    */
211   public void thisGroupsPrivilegesInheritedFromFolders(HttpServletRequest request, HttpServletResponse response) {
212     
213     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
214     
215     GrouperSession grouperSession = null;
216   
217     Group group = null;
218   
219     try {
220   
221       grouperSession = GrouperSession.start(loggedInSubject);
222   
223       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
224       
225       if (group == null) {
226         return;
227       }
228   
229       if (!GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().isCanReadPrivilegeInheritance()) {
230         throw new RuntimeException("Not allowed to read privilege inheritance! " + GrouperUtil.subjectToString(loggedInSubject));
231       }
232 
233       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
234 
235       RulesContainer rulesContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getRulesContainer();
236       
237       Set<GuiRuleDefinition> guiRuleDefinitions = new TreeSet<GuiRuleDefinition>();
238       {
239         Set<RuleDefinition> groupRuleDefinitions  = RuleFinder.findGroupPrivilegeInheritRules(group.getParentStem());
240         for (RuleDefinition ruleDefinition : GrouperUtil.nonNull(groupRuleDefinitions)) {
241           GuiRuleDefinitioneans/api/GuiRuleDefinition.html#GuiRuleDefinition">GuiRuleDefinition guiRuleDefinition = new GuiRuleDefinition(ruleDefinition);
242           if (guiRuleDefinition.getOwnerGuiStem() != null) {
243             guiRuleDefinitions.add(guiRuleDefinition);
244           }
245         }
246       }
247       
248       for (GuiRuleDefinition guiRuleDefinition : guiRuleDefinitions) {
249         if (StringUtils.equals(group.getParentStem().getUuid(), guiRuleDefinition.getOwnerGuiStem().getStem().getUuid())) {
250           guiRuleDefinition.setDirect(true);
251         }
252       }
253       rulesContainer.setGuiRuleDefinitions(guiRuleDefinitions);
254 
255       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
256           "/WEB-INF/grouperUi2/group/thisGroupsPrivilegesInheritedFromFolders.jsp"));
257 
258     } finally {
259       GrouperSession.stopQuietly(grouperSession);
260     }
261     
262   }
263 
264  
265   /**
266    * view group
267    * @param request
268    * @param response
269    */
270   public void viewGroup(HttpServletRequest request, HttpServletResponse response) {
271     
272     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
273     
274     GrouperSession grouperSession = null;
275   
276     Group group = null;
277   
278     try {
279   
280       grouperSession = GrouperSession.start(loggedInSubject);
281   
282       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
283       
284       if (group == null) {
285         return;
286       }
287 
288       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
289       
290       if (group.getTypeOfGroup() == TypeOfGroup.entity) {
291         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Subject.viewSubject&sourceId=grouperEntities&subjectId=" + group.getId() + "')"));
292         return;
293       }
294       
295       if (retrieveGroupHelper(request, AccessPrivilege.UPDATE, false).getGroup() != null) {
296         UiV2Attestation.setupAttestation(group);            
297       }
298       
299       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
300           "/WEB-INF/grouperUi2/group/viewGroup.jsp"));
301 
302       if (GrouperUiUtils.isMenuRefreshOnView()) {
303         guiResponseJs.addAction(GuiScreenAction.newScript("openFolderTreePathToObject(" + GrouperUiUtils.pathArrayToCurrentObject(grouperSession, group) + ")"));
304       }
305 
306       if (GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().isCanRead()) {
307         filterHelper(request, response, group);
308       }
309     } finally {
310       GrouperSession.stopQuietly(grouperSession);
311     }
312     
313   }
314 
315   /**
316    * the filter button was pressed, or paging or sorting or something
317    * @param request
318    * @param response
319    */
320   public void filter(HttpServletRequest request, HttpServletResponse response) {
321     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
322         
323     GrouperSession grouperSession = null;
324     
325     try {
326       grouperSession = GrouperSession.start(loggedInSubject);
327   
328   
329       Group group = retrieveGroupHelper(request, AccessPrivilege.READ).getGroup();
330       
331       if (group == null) {
332         return;
333       }
334   
335       filterHelper(request, response, group);
336       
337     } finally {
338       GrouperSession.stopQuietly(grouperSession);
339     }
340     
341   }
342 
343   /**
344    * the filter button was pressed, or paging or sorting, or view Group or something
345    * @param request
346    * @param response
347    */
348   public void removeMemberForThisGroupsMemberships(HttpServletRequest request, HttpServletResponse response) {
349   
350     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
351   
352     GrouperSession grouperSession = null;
353   
354     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
355   
356     try {
357       grouperSession = GrouperSession.start(loggedInSubject);
358   
359       final Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
360   
361       if (group == null) {
362         return;
363       }
364 
365       String ownerGroupId = request.getParameter("ownerGroupId");
366       
367       Group ownerGroup = GroupFinder.findByUuid(grouperSession, ownerGroupId, false);
368 
369       //not sure why this would happen
370       if (ownerGroup == null) {
371         
372         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
373             TextContainer.retrieveFromRequest().getText().get("groupDeleteMemberCantFindOwnerGroup")));
374         
375       } else {
376       
377         boolean madeChanges = ownerGroup.deleteMember(group.toSubject(), false);
378         
379         if (madeChanges) {
380     
381           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
382               TextContainer.retrieveFromRequest().getText().get("groupDeleteFromOwnerSuccess")));
383               
384         } else {
385           
386           //not sure why this would happen (race condition?)
387           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
388               TextContainer.retrieveFromRequest().getText().get("groupDeleteFromOwnerNoChangesSuccess")));
389     
390         }
391       }
392       
393       filterThisGroupsMembershipsHelper(request, response, group);
394 
395       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
396           loggedInSubject, group);
397 
398     } catch (RuntimeException re) {
399       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
400         return;
401       }
402       throw re;
403     } finally {
404       GrouperSession.stopQuietly(grouperSession);
405     }
406   }
407 
408 
409   /**
410    * the remove from groups button was pressed
411    * @param request
412    * @param response
413    */
414   public void removeMembersForThisGroupsMemberships(HttpServletRequest request, HttpServletResponse response) {
415   
416     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
417   
418     GrouperSession grouperSession = null;
419   
420     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
421   
422     try {
423       grouperSession = GrouperSession.start(loggedInSubject);
424   
425       final Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
426   
427       if (group == null) {
428         return;
429       }
430 
431       Set<String> membershipsIds = new HashSet<String>();
432       
433       for (int i=0;i<1000;i++) {
434         String membershipId = request.getParameter("membershipRow_" + i + "[]");
435         if (!StringUtils.isBlank(membershipId)) {
436           membershipsIds.add(membershipId);
437         }
438       }
439 
440       if (membershipsIds.size() == 0) {
441         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
442             TextContainer.retrieveFromRequest().getText().get("thisGroupsMembershipsRemoveNoGroupsSelects")));
443         return;
444       }
445       int successes = 0;
446       int failures = 0;
447       
448       Subject groupSubject = group.toSubject();
449       for (String membershipId : membershipsIds) {
450         try {
451           Membership membership = new MembershipFinder().addMembershipId(membershipId).findMembership(true);
452           Group ownerGroup = membership.getOwnerGroup();
453           //dont worry about if no change, thats a success
454           ownerGroup.deleteMember(groupSubject, false);
455           successes++;
456         } catch (Exception e) {
457           LOG.warn("Error with membership: " + membershipId + ", user: " + loggedInSubject, e);
458           failures++;
459         }
460       }
461 
462       GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().setSuccessCount(successes);
463       GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().setFailureCount(failures);
464 
465       if (failures > 0) {
466         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
467             TextContainer.retrieveFromRequest().getText().get("groupDeleteFromOwnerErrors")));
468       } else {
469         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
470             TextContainer.retrieveFromRequest().getText().get("groupDeleteFromOwnerSuccesses")));
471       }
472       
473       filterThisGroupsMembershipsHelper(request, response, group);
474 
475       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
476           loggedInSubject, group);
477 
478     } catch (RuntimeException re) {
479       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
480         return;
481       }
482       throw re;
483     } finally {
484       GrouperSession.stopQuietly(grouperSession);
485     }
486   }
487   
488   /**
489    * remove one member from the group
490    * @param request
491    * @param response
492    */
493   public void removeMember(HttpServletRequest request, HttpServletResponse response) {
494   
495     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
496   
497     GrouperSession grouperSession = null;
498   
499     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
500   
501     try {
502       grouperSession = GrouperSession.start(loggedInSubject);
503   
504       final Group group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
505   
506       if (group == null) {
507         return;
508       }
509 
510       String memberId = request.getParameter("memberId");
511       
512       Member member = MemberFinder.findByUuid(grouperSession, memberId, false);
513 
514       //not sure why this would happen
515       if (member == null) {
516         
517         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
518             TextContainer.retrieveFromRequest().getText().get("groupDeleteMemberCantFindMember")));
519         
520       } else {
521       
522         boolean madeChanges = group.deleteMember(member, false);
523         
524         if (madeChanges) {
525     
526           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
527               TextContainer.retrieveFromRequest().getText().get("groupDeleteMemberSuccess")));
528               
529         } else {
530           
531           //not sure why this would happen (race condition?)
532           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
533               TextContainer.retrieveFromRequest().getText().get("groupDeleteMemberNoChangesSuccess")));
534     
535         }
536       }
537       
538       filterHelper(request, response, group);
539 
540       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
541           loggedInSubject, group);
542 
543       GrouperUserDataApi.recentlyUsedMemberAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
544           loggedInSubject, member);
545 
546     } catch (RuntimeException re) {
547       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
548         return;
549       }
550       throw re;
551     } finally {
552       GrouperSession.stopQuietly(grouperSession);
553     }
554   }
555 
556   /**
557    * the filter button was pressed, or paging or sorting, or view Group or something
558    * @param request
559    * @param response
560    * @param group
561    */
562   private void filterHelper(HttpServletRequest request, HttpServletResponse response, Group group) {
563     
564     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
565     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
566     
567     String filterText = request.getParameter("filterText");
568     String membershipEnabledDisabledOptions = request.getParameter("membershipEnabledDisabledOptions");
569     String membershipPITOptions = request.getParameter("membershipPITOptions");
570     String membershipPITToDate = request.getParameter("membershipPITToDate");
571     String membershipPITFromDate = request.getParameter("membershipPITFromDate");
572     String membershipCustomCompositeOptions = request.getParameter("membershipCustomCompositeOptions");
573     GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
574     
575     //if filtering by subjects that have a certain type
576     String membershipTypeString = request.getParameter("membershipType");
577     MembershipType membershipType = null;
578     if (!StringUtils.isBlank(membershipTypeString)) {
579       membershipType = MembershipType.valueOfIgnoreCase(membershipTypeString, true);
580     }
581 
582     GuiPaging guiPaging = groupContainer.getGuiPaging();
583     QueryOptions queryOptions = new QueryOptions();
584 
585     GrouperPagingTag2.processRequest(request, guiPaging, queryOptions);
586 
587     MembershipFinder membershipFinder = new MembershipFinder()
588       .addGroupId(group.getId()).assignCheckSecurity(true)
589       .assignHasFieldForMember(true)
590       .assignQueryOptionsForMember(queryOptions)
591       .assignSplitScopeForMember(true);
592     
593     if (!StringUtils.isBlank(filterText)) {
594       membershipFinder.assignScopeForMember(filterText);
595     }
596     
597     if ("yes".equals(membershipPITOptions)) {
598       groupContainer.setShowPointInTimeAudit(true);
599       groupContainer.setShowEnabledStatus(false);
600       
601       if (StringUtils.isNotBlank(membershipPITFromDate)) {
602         membershipFinder.assignPointInTimeFrom(GrouperUtil.stringToTimestamp(membershipPITFromDate));
603       }
604       
605       if (StringUtils.isNotBlank(membershipPITToDate)) {
606         membershipFinder.assignPointInTimeTo(GrouperUtil.stringToTimestamp(membershipPITToDate));
607       }
608       
609       //set of subjects, and what memberships each subject has
610       Set<Object[]> result = membershipFinder.findPITMembershipsMembers();
611       
612       //lets get all the subjects by member id
613       Map<String, Subject> memberIdToSubject = new HashMap<String, Subject>();
614 
615       {
616         Map<String, SubjectBean> memberIdToSubjectBean = new HashMap<String, SubjectBean>();
617         Set<SubjectBean> subjectBeans = new HashSet<SubjectBean>();
618         for (Object[] membershipResult : result) {
619           Member member = (Member)membershipResult[3];
620           SubjectBean subjectBean = new SubjectBean(member.getSubjectId(), member.getSubjectSourceId());
621           memberIdToSubjectBean.put(member.getUuid(), subjectBean);
622           subjectBeans.add(subjectBean);
623         }
624         Map<SubjectBean, Subject> subjectBeanToSubject = SubjectFinder.findBySubjectBeans(subjectBeans);
625     
626         for (String memberId : memberIdToSubjectBean.keySet()) {
627           SubjectBean subjectBean = memberIdToSubjectBean.get(memberId);
628           Subject subject = subjectBeanToSubject.get(subjectBean);
629 
630           if (subject == null) {
631             subject = new UnresolvableSubject(subjectBean.getId(), null, subjectBean.getSourceId());  
632           }
633           
634           memberIdToSubject.put(memberId, subject);
635         }
636       }
637       
638       Set<GuiPITMembershipView> guiPITMembershipViews = new LinkedHashSet<GuiPITMembershipView>();
639       
640       for (Object[] membershipResult : result) {
641         PITMembershipView pitMembershipView = (PITMembershipView)membershipResult[0];
642         GuiPITMembershipViewpi/GuiPITMembershipView.html#GuiPITMembershipView">GuiPITMembershipView guiPITMembershipView = new GuiPITMembershipView(pitMembershipView);
643         String memberId = pitMembershipView.getPITMember().getSourceId();
644         Subject subject = memberIdToSubject.get(memberId);
645         guiPITMembershipView.setGuiSubject(new GuiSubject(subject));
646         guiPITMembershipViews.add(guiPITMembershipView);
647       }
648 
649       groupContainer.setGuiPITMembershipViews(guiPITMembershipViews);
650     } else {
651       groupContainer.setShowPointInTimeAudit(false);
652       membershipFinder.assignHasMembershipTypeForMember(true);
653       
654       if (membershipType != null) {
655         membershipFinder.assignMembershipType(membershipType);
656       }
657       
658       groupContainer.setShowEnabledStatus(true);
659       
660       if ("status".equals(membershipEnabledDisabledOptions)) {
661         // include enabled and disabled memberships
662         membershipFinder.assignEnabled(null);
663       } else if ("disabled_dates".equals(membershipEnabledDisabledOptions)) {
664         // include memberships that have a disabled date
665         membershipFinder.assignHasDisabledDate(true);
666       } else if ("enabled_dates".equals(membershipEnabledDisabledOptions)) {
667         // include memberships that have an enabled date
668         membershipFinder.assignHasEnabledDate(true);
669       } else {
670         // default
671         membershipFinder.assignEnabled(true);
672         groupContainer.setShowEnabledStatus(false);
673       }
674       
675       if (!StringUtils.isBlank(membershipCustomCompositeOptions) && !"nothing".equals(membershipCustomCompositeOptions)) {
676         String groupName = GrouperConfig.retrieveConfig().getProperty("grouper.membership.customComposite.groupName." + membershipCustomCompositeOptions, null);
677         String compositeType = GrouperConfig.retrieveConfig().getProperty("grouper.membership.customComposite.compositeType." + membershipCustomCompositeOptions, null);
678         Group customCompositeGroup = GroupFinder.findByName(GrouperSession.staticGrouperSession(), groupName, true);
679         CompositeType customCompositeType = CompositeType.valueOfIgnoreCase(compositeType);
680         membershipFinder.assignCustomCompositeGroup(customCompositeGroup).assignCustomCompositeType(customCompositeType);
681       }
682       
683       //set of subjects, and what memberships each subject has
684       Set<MembershipSubjectContainer> results = membershipFinder
685           .findMembershipResult().getMembershipSubjectContainers();
686 
687       groupContainer.setGuiMembershipSubjectContainers(GuiMembershipSubjectContainer.convertFromMembershipSubjectContainers(results));
688     }
689     
690     guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
691     
692     guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupFilterResultsId", 
693         "/WEB-INF/grouperUi2/group/groupContents.jsp"));
694   
695   }
696 
697   /**
698    * combo filter
699    * @param request
700    * @param response
701    */
702   public void addMemberFilter(HttpServletRequest request, HttpServletResponse response) {
703 
704     //run the combo logic
705     DojoComboLogic.logic(request, response, new DojoComboQueryLogicBase<Subject>() {
706 
707       /**
708        */
709       @Override
710       public Subject lookup(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
711 
712         //when we refer to subjects in the dropdown, we will use a sourceId / subject tuple
713         
714         Subject subject = null;
715             
716         try {
717           GrouperSourceAdapter.searchForGroupsWithReadPrivilege(true);
718           if (query != null && query.contains("||")) {
719             String sourceId = GrouperUtil.prefixOrSuffix(query, "||", true);
720             String subjectId = GrouperUtil.prefixOrSuffix(query, "||", false);
721             subject =  SubjectFinder.findByIdOrIdentifierAndSource(subjectId, sourceId, false);
722           } else {
723             try { 
724               
725               final String requireSources = GrouperUiConfig.retrieveConfig().propertyValueString(
726                   "uiV2.subjectLookupRequireSources");
727               
728               if (!StringUtils.isBlank(requireSources)) {
729                 Set<Source> sources = GrouperUtil.convertSources(requireSources);
730                 subject = SubjectFinder.findByIdOrIdentifierAndSource(query, sources, false);
731               } else {
732                 
733                 subject = SubjectFinder.findByIdOrIdentifier(query, false);
734               }
735             } catch (SubjectNotUniqueException snue) {
736               //ignore this...
737               if (LOG.isDebugEnabled()) {
738                 LOG.debug("Find by id or identifier not unique: '" + query + "'");
739               }
740             }
741           }
742         } finally {
743           GrouperSourceAdapter.clearSearchForGroupsWithReadPrivilege();
744         }
745         
746         return subject;
747       }
748 
749       /**
750        * 
751        */
752       @Override
753       public Collection<Subject> search(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
754         
755         Group group = UiV2Group.retrieveGroupHelper(localRequest, AccessPrivilege.UPDATE, false).getGroup();
756         String stemName = null;
757         if (group == null) {
758           Stem stem = UiV2Stem.retrieveStemHelper(localRequest, true, false, false).getStem();
759           stemName = stem == null ? null : stem.getName();
760         } else {
761           stemName = group.getParentStemName();
762         }
763         try {
764           GrouperSourceAdapter.searchForGroupsWithReadPrivilege(true);
765           
766           final String requireSources = GrouperUiConfig.retrieveConfig().propertyValueString(
767               "uiV2.subjectSearchRequireSources");
768           
769           Collection<Subject> results = null;
770           if (!StringUtils.isBlank(requireSources)) {
771             Set<Source> sources = GrouperUtil.convertSources(requireSources);
772             results = StringUtils.isBlank(stemName) ? 
773                 SubjectFinder.findPage(query, sources).getResults()
774                 : SubjectFinder.findPageInStem(stemName, query, sources).getResults();
775            
776           } else {
777             results = StringUtils.isBlank(stemName) ? 
778                 SubjectFinder.findPage(query).getResults()
779                 : SubjectFinder.findPageInStem(stemName, query).getResults();
780           }
781           return results;
782         } finally {
783           GrouperSourceAdapter.clearSearchForGroupsWithReadPrivilege();
784         }
785       
786       }
787 
788       /**
789        * 
790        * @param t
791        * @return source with id
792        */
793       @Override
794       public String retrieveId(GrouperSession grouperSession, Subject t) {
795         return t.getSourceId() + "||" + t.getId();
796       }
797       
798       /**
799        * 
800        */
801       @Override
802       public String retrieveLabel(GrouperSession grouperSession, Subject t) {
803         return new GuiSubject(t).getScreenLabelLong();
804       }
805 
806       /**
807        * 
808        */
809       @Override
810       public String retrieveHtmlLabel(GrouperSession grouperSession, Subject t) {
811         String value = new GuiSubject(t).getScreenLabelLongWithIcon();
812         return value;
813       }
814 
815       /**
816        * 
817        */
818       @Override
819       public String initialValidationError(HttpServletRequest localRequest, GrouperSession grouperSession) {
820 
821         //MCH 20140316
822         //Group group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
823         //
824         //if (group == null) {
825         //  
826         //  return "Not allowed to edit group";
827         //}
828         //
829         return null;
830       }
831     });
832 
833               
834   }
835   
836   /**
837    * search for a subject to add to the group
838    * @param request
839    * @param response
840    */
841   public void addMemberSearch(HttpServletRequest request, HttpServletResponse response) {
842 
843     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
844     
845     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
846     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
847   
848     GrouperSession grouperSession = null;
849     
850     try {
851       grouperSession = GrouperSession.start(loggedInSubject);
852   
853   
854       GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
855   
856       String searchString = request.getParameter("addMemberSubjectSearch");
857       
858       Group group = retrieveGroupHelper(request, AccessPrivilege.UPDATE, false).getGroup();
859       String stemName = null;
860       if (group != null) {
861         stemName = group.getParentStemName();
862       } else {
863         Stem stem = UiV2Stem.retrieveStemHelper(request, true, false, false).getStem();
864         if (stem != null) {
865           stemName = stem.getName();
866         } else {
867           AttributeDef attributeDef = UiV2AttributeDef.retrieveAttributeDefHelper(request, AttributeDefPrivilege.ATTR_ADMIN, true).getAttributeDef();
868           if (attributeDef != null) {
869             stemName = attributeDef.getParentStemName();
870           }
871         }
872       }
873       
874       boolean searchOk = GrouperUiUtils.searchStringValid(searchString);
875       if (!searchOk) {
876         
877         guiResponseJs.addAction(GuiScreenAction.newInnerHtml("#addMemberResults", 
878             TextContainer.retrieveFromRequest().getText().get("groupAddMemberNotEnoughChars")));
879         return;
880       }
881 
882       String matchExactIdString = request.getParameter("matchExactId[]");
883       boolean matchExactId = GrouperUtil.booleanValue(matchExactIdString, false);
884 
885       String sourceId = request.getParameter("sourceId");
886       
887       Set<Subject> subjects = null;
888       if (matchExactId) {
889         if (GrouperConfig.retrieveConfig().propertyValueBoolean("grouperQuerySubjectsMultipleQueriesCommaSeparated", true)) {
890           Set<String> searchStrings = GrouperUtil.splitTrimToSet(searchString, ",");
891           if (StringUtils.equals("all", sourceId)) {
892             subjects = new LinkedHashSet<Subject>(GrouperUtil.nonNull(SubjectFinder.findByIdsOrIdentifiers(searchStrings)).values());
893           } else {
894             subjects = new LinkedHashSet<Subject>(GrouperUtil.nonNull(SubjectFinder.findByIdsOrIdentifiers(searchStrings, sourceId)).values());
895           }
896         } else {
897           Subject subject = null;
898           if (StringUtils.equals("all", sourceId)) {
899             try {
900               subject = SubjectFinder.findByIdOrIdentifier(searchString, false);
901             } catch (SubjectNotUniqueException snue) {
902               //ignore
903             }
904           } else {
905             subject = SubjectFinder.findByIdOrIdentifierAndSource(searchString, sourceId, false);
906           }
907 
908           subjects = new LinkedHashSet<Subject>();
909           if (subject != null) {
910             subjects.add(subject);
911           }
912         }
913       } else {
914         if (StringUtils.equals("all", sourceId)) {
915           if (group != null) {
916             subjects = SubjectFinder.findPageInStem(stemName, searchString).getResults();
917           } else {
918             subjects = SubjectFinder.findPage(searchString).getResults();
919           }
920         } else {
921           Set<Source> sources = GrouperUtil.toSet(SourceManager.getInstance().getSource(sourceId));
922           if (group != null) {
923             subjects = SubjectFinder.findPageInStem(stemName, searchString, sources).getResults();
924           } else {
925             subjects = SubjectFinder.findPage(searchString, sources).getResults();
926           }
927         }
928       }
929       
930       if (GrouperUtil.length(subjects) == 0) {
931 
932         guiResponseJs.addAction(GuiScreenAction.newInnerHtml("#addMemberResults", 
933             TextContainer.retrieveFromRequest().getText().get("groupAddMemberNoSubjectsFound")));
934         return;
935       }
936       
937       Set<GuiSubject> guiSubjects = GuiSubject.convertFromSubjects(subjects, "uiV2.subjectSearchResults", 30);
938       
939       groupContainer.setGuiSubjectsAddMember(guiSubjects);
940   
941       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#addMemberResults", 
942           "/WEB-INF/grouperUi2/group/addMemberResults.jsp"));
943       
944     } finally {
945       GrouperSession.stopQuietly(grouperSession);
946     }
947   }
948   
949   /**
950    * submit button on add member form pressed
951    * @param request
952    * @param response
953    */
954   public void addMemberSubmit(final HttpServletRequest request, final HttpServletResponse response) {
955 
956     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
957 
958     GrouperSession grouperSession = null;
959 
960     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
961 
962     try {
963       grouperSession = GrouperSession.start(loggedInSubject);
964   
965       final Group group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
966   
967       if (group == null) {
968         return;
969       }
970     
971       String subjectString = request.getParameter("groupAddMemberComboName");
972   
973       Subject subject = null;
974       
975       if (subjectString != null && subjectString.contains("||")) {
976         String sourceId = GrouperUtil.prefixOrSuffix(subjectString, "||", true);
977         String subjectId = GrouperUtil.prefixOrSuffix(subjectString, "||", false);
978         subject =  SubjectFinder.findByIdOrIdentifierAndSource(subjectId, sourceId, false);
979 
980       } else {
981         try {
982           subject = SubjectFinder.findByIdOrIdentifier(subjectString, false);
983         } catch (SubjectNotUniqueException snue) {
984           //ignore
985         }
986           
987       }
988 
989       if (subject == null) {
990         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
991             TextContainer.retrieveFromRequest().getText().get("groupAddMemberCantFindSubject")));
992         return;
993       }      
994 
995       Boolean defaultPrivs = null;
996       
997       {
998         String privilegeOptionsValue = request.getParameter("privilege-options[]");
999         
1000         if (StringUtils.equals(privilegeOptionsValue, "default")) {
1001           defaultPrivs = true;
1002         } else if (StringUtils.equals(privilegeOptionsValue, "custom")) {
1003           defaultPrivs = false;
1004         } else {
1005           throw new RuntimeException("For privilege-options expecting default or custom but was: '" + privilegeOptionsValue + "'");
1006         }
1007       }
1008       
1009       boolean memberChecked = GrouperUtil.booleanValue(request.getParameter("privileges_members[]"), false);
1010       boolean adminChecked = GrouperUtil.booleanValue(request.getParameter("privileges_admins[]"), false);
1011       boolean updateChecked = GrouperUtil.booleanValue(request.getParameter("privileges_updaters[]"), false);
1012       boolean readChecked = GrouperUtil.booleanValue(request.getParameter("privileges_readers[]"), false);
1013       boolean viewChecked = GrouperUtil.booleanValue(request.getParameter("privileges_viewers[]"), false);
1014       boolean optinChecked = GrouperUtil.booleanValue(request.getParameter("privileges_optins[]"), false);
1015       boolean optoutChecked = GrouperUtil.booleanValue(request.getParameter("privileges_optouts[]"), false);
1016       boolean attrReadChecked = GrouperUtil.booleanValue(request.getParameter("privileges_groupAttrReaders[]"), false);
1017       boolean attrUpdateChecked = GrouperUtil.booleanValue(request.getParameter("privileges_groupAttrUpdaters[]"), false);
1018       
1019       if (!defaultPrivs && !memberChecked && !adminChecked && !updateChecked
1020           && !readChecked && !viewChecked && !optinChecked && !optoutChecked
1021           && !attrReadChecked && !attrUpdateChecked) {
1022         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
1023             "#groupPrivsErrorId",
1024             TextContainer.retrieveFromRequest().getText().get("groupAddMemberPrivRequired")));
1025         return;
1026         
1027       }
1028 
1029       boolean madeChanges = group.addOrEditMember(subject, defaultPrivs, memberChecked, adminChecked, 
1030           updateChecked, readChecked, viewChecked, optinChecked, optoutChecked, attrReadChecked, 
1031           attrUpdateChecked, null, null, false);
1032       
1033       if (madeChanges) {
1034 
1035         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1036             TextContainer.retrieveFromRequest().getText().get("groupAddMemberMadeChangesSuccess")));
1037 
1038         //what subscreen are we on?
1039         String groupRefreshPart = request.getParameter("groupRefreshPart");
1040         if (StringUtils.equals(groupRefreshPart, "audits")) {
1041           viewAuditsFilter(request, response);
1042         } else if (StringUtils.equals(groupRefreshPart, "privileges")) {
1043           filterPrivilegesHelper(request, response, group);
1044         } else if (StringUtils.equals(groupRefreshPart, "thisGroupsAttributeDefPrivileges")) {
1045           //doesnt affect
1046         } else if (StringUtils.equals(groupRefreshPart, "thisGroupsGroupPrivileges")) {
1047           //doesnt affect
1048         } else if (StringUtils.equals(groupRefreshPart, "thisGroupsStemPrivileges")) {
1049           //doesnt affect
1050         } else if (StringUtils.equals(groupRefreshPart, "thisGroupsMemberships")) {
1051           //doesnt affect
1052         } else {
1053           filterHelper(request, response, group);
1054         }
1055 
1056       } else {
1057 
1058         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
1059             TextContainer.retrieveFromRequest().getText().get("groupAddMemberNoChangesSuccess")));
1060 
1061       }
1062 
1063       //clear out the combo
1064       guiResponseJs.addAction(GuiScreenAction.newScript(
1065           "dijit.byId('groupAddMemberComboId').set('displayedValue', ''); " +
1066           "dijit.byId('groupAddMemberComboId').set('value', '');"));
1067 
1068       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1069           loggedInSubject, group);
1070       GrouperUserDataApi.recentlyUsedMemberAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1071           loggedInSubject, subject);
1072 
1073     } catch (RuntimeException re) {
1074       if (GrouperUiUtils.vetoHandle(guiResponseJs, re)) {
1075         return;
1076       }
1077       throw re;
1078     } finally {
1079       GrouperSession.stopQuietly(grouperSession);
1080     }
1081 
1082   }
1083   
1084   /**
1085    * assign or remove a privilege from a user, and redraw the filter screen... put a success at top
1086    * @param request
1087    * @param response
1088    */
1089   public void assignPrivilege(HttpServletRequest request, HttpServletResponse response) {
1090   
1091     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
1092   
1093     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1094   
1095     GrouperSession grouperSession = null;
1096     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1097     
1098     try {
1099       grouperSession = GrouperSession.start(loggedInSubject);
1100   
1101       Group group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
1102   
1103       if (group == null) {
1104         return;
1105       }
1106   
1107       GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
1108   
1109       //?assign=false&groupId=${grouperRequestContainer.groupContainer.guiGroup.stem.id}&fieldName=${fieldName}&memberId=${guiMembershipSubjectContainer.guiMember.member.uuid}
1110       String assignString = request.getParameter("assign");
1111       boolean assign = GrouperUtil.booleanValue(assignString);
1112       String fieldName = request.getParameter("fieldName");
1113       String memberId = request.getParameter("memberId");
1114   
1115       Member member = MemberFinder.findByUuid(grouperSession, memberId, true);
1116       
1117       Privilege privilege = AccessPrivilege.listToPriv(fieldName);
1118       
1119       if (privilege == null) {
1120         throw new RuntimeException("Why is privilege not found???? " + fieldName);
1121       }
1122       
1123       //if someone revoked in the meantime, who cares...
1124       if (assign) {
1125         group.grantPriv(member.getSubject(), privilege, false);
1126         
1127         //set a success message
1128         //messes up screen
1129         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1130         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessGrantedPrivilege")));
1131         
1132       } else {
1133         group.revokePriv(member.getSubject(), privilege, false);
1134         
1135         //messes up screen
1136         //set a success message
1137         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1138         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessRevokedPrivilege")));
1139       }
1140   
1141       //reset the data (not really necessary, just in case)
1142       groupContainer.setPrivilegeGuiMembershipSubjectContainers(null);
1143       
1144       
1145       filterPrivilegesHelper(request, response, group);
1146   
1147       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1148           loggedInSubject, group);
1149 
1150       GrouperUserDataApi.recentlyUsedMemberAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1151           loggedInSubject, member);
1152     } catch (RuntimeException re) {
1153       if (GrouperUiUtils.vetoHandle(guiResponseJs, re)) {
1154         return;
1155       }
1156       throw re;
1157 
1158     } finally {
1159       GrouperSession.stopQuietly(grouperSession);
1160     }
1161   
1162   
1163   }
1164 
1165   /**
1166    * join the current group
1167    * @param request
1168    * @param response
1169    */
1170   public void joinGroup(final HttpServletRequest request, final HttpServletResponse response) {
1171 
1172     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1173     
1174     GrouperSession grouperSession = null;
1175   
1176     Group group = null;
1177   
1178     try {
1179   
1180       grouperSession = GrouperSession.start(loggedInSubject);
1181   
1182       group = retrieveGroupHelper(request, AccessPrivilege.OPTIN, false).getGroup();
1183       final GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1184       
1185       if (group == null) {
1186         new UiV2GrouperWorkflow().showJoinGroupForm(request, response);
1187         // guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2GrouperWorkflow.showJoinGroupForm&groupId=" + group.getId() + "')"));
1188         return;
1189       } else {
1190         final Group GROUP = group;
1191         
1192         group.addMember(loggedInSubject, false);
1193         
1194         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1195             TextContainer.retrieveFromRequest().getText().get("groupJoinSuccess")));
1196         
1197         //redisplay so the button will change, note, this will not change the memberships
1198         guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupMoreActionsButtonContentsDivId", 
1199             "/WEB-INF/grouperUi2/group/groupMoreActionsButtonContents.jsp"));
1200         
1201         GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1202             loggedInSubject, group);
1203         
1204         filterHelper(request, response, group);
1205       }
1206       
1207       
1208     } finally {
1209       GrouperSession.stopQuietly(grouperSession);
1210     }
1211 
1212   }
1213   
1214   /**
1215    * leave the current group
1216    * @param request
1217    * @param response
1218    */
1219   public void leaveGroup(HttpServletRequest request, HttpServletResponse response) {
1220 
1221     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1222     
1223     GrouperSession grouperSession = null;
1224   
1225     Group group = null;
1226   
1227     try {
1228   
1229       grouperSession = GrouperSession.start(loggedInSubject);
1230   
1231       group = retrieveGroupHelper(request, AccessPrivilege.OPTOUT).getGroup();
1232       
1233       if (group == null) {
1234         return;
1235       }
1236 
1237       group.deleteMember(loggedInSubject, false);
1238 
1239       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1240       
1241       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1242           TextContainer.retrieveFromRequest().getText().get("groupLeaveSuccess")));
1243 
1244       //redisplay so the button will change, note, this will not change the memberships
1245       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupMoreActionsButtonContentsDivId", 
1246           "/WEB-INF/grouperUi2/group/groupMoreActionsButtonContents.jsp"));
1247 
1248       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1249           loggedInSubject, group);
1250       
1251       filterHelper(request, response, group);
1252 
1253     } finally {
1254       GrouperSession.stopQuietly(grouperSession);
1255     }
1256 
1257   }
1258   
1259   /**
1260    * 
1261    * @param request
1262    * @param response
1263    */
1264   public void addToMyFavorites(HttpServletRequest request, HttpServletResponse response) {
1265     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1266     
1267     GrouperSession grouperSession = null;
1268   
1269     Group group = null;
1270   
1271     try {
1272   
1273       grouperSession = GrouperSession.start(loggedInSubject);
1274   
1275       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
1276       
1277       if (group == null) {
1278         return;
1279       }
1280 
1281       GrouperUserDataApi.favoriteGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), loggedInSubject, group);
1282 
1283       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1284       
1285       if (group.getTypeOfGroup() == TypeOfGroup.entity) {
1286         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1287             TextContainer.retrieveFromRequest().getText().get("localEntitySuccessAddedToMyFavorites")));
1288         //redisplay so the button will change
1289         guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupMoreActionsButtonContentsDivId", 
1290             "/WEB-INF/grouperUi2/localEntity/localEntityMoreActionsButtonContents.jsp"));
1291       } else {
1292         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1293             TextContainer.retrieveFromRequest().getText().get("groupSuccessAddedToMyFavorites")));
1294         //redisplay so the button will change
1295         guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupMoreActionsButtonContentsDivId", 
1296             "/WEB-INF/grouperUi2/group/groupMoreActionsButtonContents.jsp"));
1297       }
1298 
1299 
1300     } catch (RuntimeException re) {
1301       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
1302         return;
1303       }
1304       throw re;
1305     } finally {
1306       GrouperSession.stopQuietly(grouperSession);
1307     }
1308 
1309   }
1310   
1311 
1312   /**
1313    * ajax logic to remove from my favorites
1314    * @param request
1315    * @param response
1316    */
1317   public void removeFromMyFavorites(HttpServletRequest request, HttpServletResponse response) {
1318     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1319     
1320     GrouperSession grouperSession = null;
1321   
1322     Group group = null;
1323   
1324     try {
1325   
1326       grouperSession = GrouperSession.start(loggedInSubject);
1327   
1328       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
1329       
1330       if (group == null) {
1331         return;
1332       }
1333 
1334       GrouperUserDataApi.favoriteGroupRemove(GrouperUiUserData.grouperUiGroupNameForUserData(), loggedInSubject, group);
1335 
1336       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1337       
1338       if (group.getTypeOfGroup() == TypeOfGroup.entity) {
1339         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1340             TextContainer.retrieveFromRequest().getText().get("localEntitySuccessRemovedFromMyFavorites")));
1341         //redisplay so the button will change
1342         guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupMoreActionsButtonContentsDivId", 
1343             "/WEB-INF/grouperUi2/localEntity/localEntityMoreActionsButtonContents.jsp"));
1344       } else {
1345 
1346         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1347             TextContainer.retrieveFromRequest().getText().get("groupSuccessRemovedFromMyFavorites")));
1348   
1349         //redisplay so the button will change
1350         guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupMoreActionsButtonContentsDivId", 
1351             "/WEB-INF/grouperUi2/group/groupMoreActionsButtonContents.jsp"));
1352       }
1353       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1354           loggedInSubject, group);
1355 
1356     } finally {
1357       GrouperSession.stopQuietly(grouperSession);
1358     }
1359 
1360   }
1361   
1362   /**
1363    * submit the main form on the privilege screen which can do batch operations on a number of rows
1364    * @param request
1365    * @param response
1366    */
1367   public void assignPrivilegeBatch(HttpServletRequest request, HttpServletResponse response) {
1368   
1369     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
1370   
1371     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1372 
1373     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1374   
1375     GrouperSession grouperSession = null;
1376     
1377     try {
1378       grouperSession = GrouperSession.start(loggedInSubject);
1379   
1380       Group group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
1381   
1382       if (group == null) {
1383         return;
1384       }
1385   
1386       GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
1387   
1388       //UiV2Group.assignPrivilegeBatch?groupId=${grouperRequestContainer.groupContainer.guiGroup.group.id}
1389       
1390       String groupPrivilegeBatchUpdateOperation = request.getParameter("groupPrivilegeBatchUpdateOperation");
1391       Pattern operationPattern = Pattern.compile("^(assign|revoke)_(.*)$");
1392       Matcher operationMatcher = operationPattern.matcher(groupPrivilegeBatchUpdateOperation);
1393       if (!operationMatcher.matches()) {
1394         throw new RuntimeException("Invalid submission, should have a valid operation: '" + groupPrivilegeBatchUpdateOperation + "'");
1395       }
1396       
1397       String assignOrRevokeString = operationMatcher.group(1);
1398       boolean assign = StringUtils.equals("assign", assignOrRevokeString);
1399       if (!assign && !StringUtils.equals("revoke", assignOrRevokeString)) {
1400         throw new RuntimeException("Cant find assign or revoke: '" + assignOrRevokeString + "'");
1401       }
1402       String fieldName = operationMatcher.group(2);
1403       
1404       boolean assignAll = StringUtils.equals(fieldName, "all");
1405       boolean readersUpdaters = StringUtils.equals(fieldName, "readersUpdaters");
1406       
1407       //lets see how many are on a page
1408       int pageSize = GrouperPagingTag2.pageSize(request);
1409       
1410       //lets loop and get all the checkboxes
1411       Set<Member> members = new LinkedHashSet<Member>();
1412       
1413       //loop through all the checkboxes and collect all the members
1414       for (int i=0;i<pageSize;i++) {
1415         String memberId = request.getParameter("privilegeSubjectRow_" + i + "[]");
1416         if (!StringUtils.isBlank(memberId)) {
1417           Member member = MemberFinder.findByUuid(grouperSession, memberId, true);
1418           members.add(member);
1419         }
1420       }
1421   
1422       if (GrouperUtil.length(members) == 0) {
1423   
1424         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
1425             TextContainer.retrieveFromRequest().getText().get("stemErrorEntityRequired")));
1426         guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
1427         return;
1428       }
1429       
1430       int changes = 0;
1431 
1432       Privilege[] privileges = null;
1433       if (assignAll) {
1434         if (assign) {
1435           privileges = new Privilege[]{AccessPrivilege.listToPriv(Field.FIELD_NAME_ADMINS)};
1436         } else {
1437           privileges = new Privilege[]{
1438                   AccessPrivilege.listToPriv(Field.FIELD_NAME_GROUP_ATTR_READERS),
1439                   AccessPrivilege.listToPriv(Field.FIELD_NAME_GROUP_ATTR_UPDATERS),
1440                   AccessPrivilege.listToPriv(Field.FIELD_NAME_OPTOUTS),
1441                   AccessPrivilege.listToPriv(Field.FIELD_NAME_READERS),
1442                   AccessPrivilege.listToPriv(Field.FIELD_NAME_VIEWERS),
1443                   AccessPrivilege.listToPriv(Field.FIELD_NAME_UPDATERS),
1444                   AccessPrivilege.listToPriv(Field.FIELD_NAME_OPTINS),
1445                   AccessPrivilege.listToPriv(Field.FIELD_NAME_ADMINS)
1446           };
1447         }
1448       } else {
1449         if (readersUpdaters) {
1450           privileges = new Privilege[]{AccessPrivilege.listToPriv(Field.FIELD_NAME_READERS),
1451                   AccessPrivilege.listToPriv(Field.FIELD_NAME_UPDATERS)};
1452         } else {
1453           privileges = new Privilege[]{AccessPrivilege.listToPriv(fieldName)};
1454         }
1455       }
1456       
1457       int count = 0;
1458       for (Member member : members) {
1459         
1460         for (Privilege privilege : privileges) {
1461           if (assign) {
1462             changes += group.grantPriv(member.getSubject(), privilege, false) ? 1 : 0;
1463           } else {
1464             changes += group.revokePriv(member.getSubject(), privilege, false) ? 1 : 0;
1465           }
1466         }
1467         
1468         if (count++ < 5) {
1469           GrouperUserDataApi.recentlyUsedMemberAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1470               loggedInSubject, member);
1471 
1472         }
1473         
1474       }
1475       
1476       //reset the data (not really necessary, just in case)
1477       groupContainer.setPrivilegeGuiMembershipSubjectContainers(null);
1478   
1479       if (changes > 0) {
1480         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1481             TextContainer.retrieveFromRequest().getText().get(
1482                 assign ? "groupSuccessGrantedPrivileges" : "groupSuccessRevokedPrivileges")));
1483       } else {
1484         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
1485             TextContainer.retrieveFromRequest().getText().get(
1486                 assign ? "groupNoteNoGrantedPrivileges" : "groupNoteNoRevokedPrivileges")));
1487         
1488       }
1489       guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
1490 
1491       // TODO 20180101 MCH: I think this should be "canAdmin" not "hasAdmin"
1492       if (group.hasAdmin(loggedInSubject)) {
1493         filterPrivilegesHelper(request, response, group);
1494       } else {
1495         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Main.indexMain')"));
1496       }
1497   
1498       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1499           loggedInSubject, group);
1500 
1501     } catch (RuntimeException re) {
1502       if (GrouperUiUtils.vetoHandle(guiResponseJs, re)) {
1503         return;
1504       }
1505       throw re;
1506     } finally {
1507       GrouperSession.stopQuietly(grouperSession);
1508     }
1509   
1510   }
1511 
1512   /**
1513    * the filter button for privileges was pressed, or paging or sorting or something
1514    * @param request
1515    * @param response
1516    */
1517   public void filterPrivileges(HttpServletRequest request, HttpServletResponse response) {
1518     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1519     
1520     GrouperSession grouperSession = null;
1521     
1522     try {
1523       grouperSession = GrouperSession.start(loggedInSubject);
1524   
1525   
1526       Group group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
1527       
1528       if (group == null) {
1529         return;
1530       }
1531   
1532       filterPrivilegesHelper(request, response, group);
1533       
1534     } finally {
1535       GrouperSession.stopQuietly(grouperSession);
1536     }
1537     
1538   }
1539 
1540   /**
1541    * the filter button for this groups memberships was pressed, or paging or sorting or something
1542    * @param request
1543    * @param response
1544    */
1545   public void filterThisGroupsMemberships(HttpServletRequest request, HttpServletResponse response) {
1546     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1547     
1548     GrouperSession grouperSession = null;
1549     
1550     try {
1551       grouperSession = GrouperSession.start(loggedInSubject);
1552   
1553   
1554       Group group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
1555       
1556       if (group == null) {
1557         return;
1558       }
1559   
1560       filterThisGroupsMembershipsHelper(request, response, group);
1561       
1562     } finally {
1563       GrouperSession.stopQuietly(grouperSession);
1564     }
1565     
1566   }
1567 
1568   /**
1569    * the filter button was pressed for privileges, or paging or sorting, or view Group privileges or something
1570    * @param request
1571    * @param response
1572    * @param group 
1573    */
1574   private void filterPrivilegesHelper(HttpServletRequest request, HttpServletResponse response, Group group) {
1575     
1576     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
1577   
1578     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1579   
1580     //if filtering text in subjects
1581     String privilegeFilterText = request.getParameter("privilegeFilterText");
1582     
1583     String privilegeFieldName = request.getParameter("privilegeField");
1584     
1585     Field privilegeField = null;
1586     if (!StringUtils.isBlank(privilegeFieldName)) {
1587       privilegeField = FieldFinder.find(privilegeFieldName, true);
1588     }
1589     
1590     //if filtering by subjects that have a certain type
1591     String membershipTypeString = request.getParameter("privilegeMembershipType");
1592     MembershipType membershipType = null;
1593     if (!StringUtils.isBlank(membershipTypeString)) {
1594       membershipType = MembershipType.valueOfIgnoreCase(membershipTypeString, true);
1595     }
1596 
1597     GuiPaging guiPaging = grouperRequestContainer.getGroupContainer().getPrivilegeGuiPaging();
1598     QueryOptions queryOptions = new QueryOptions();
1599     
1600     GrouperPagingTag2.processRequest(request, guiPaging, queryOptions);
1601     
1602     MembershipFinder membershipFinder = new MembershipFinder()
1603       .addGroupId(group.getId()).assignCheckSecurity(true)
1604       .assignFieldType(FieldType.ACCESS)
1605       .assignEnabled(true)
1606       .assignHasFieldForMember(true)
1607       .assignHasMembershipTypeForMember(true)
1608       .assignQueryOptionsForMember(queryOptions)
1609       .assignSplitScopeForMember(true);
1610     
1611     if (membershipType != null) {
1612       membershipFinder.assignMembershipType(membershipType);
1613     }
1614 
1615     if (privilegeField != null) {
1616       membershipFinder.assignField(privilegeField);
1617     }
1618 
1619     if (!StringUtils.isBlank(privilegeFilterText)) {
1620       membershipFinder.assignScopeForMember(privilegeFilterText);
1621     }
1622 
1623     //set of subjects, and what privs each subject has
1624     Set<MembershipSubjectContainer> results = membershipFinder
1625         .findMembershipResult().getMembershipSubjectContainers();
1626     
1627     //inherit from grouperAll or Groupersystem or privilege inheritance
1628     MembershipSubjectContainer.considerAccessPrivilegeInheritance(results);
1629 
1630     grouperRequestContainer.getGroupContainer().setPrivilegeGuiMembershipSubjectContainers(
1631         GuiMembershipSubjectContainer.convertFromMembershipSubjectContainers(results));
1632 
1633     guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
1634 
1635     
1636     guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupPrivilegeFilterResultsId", 
1637         "/WEB-INF/grouperUi2/group/groupPrivilegeContents.jsp"));
1638   
1639   }
1640 
1641   /**
1642    * view group privileges
1643    * @param request
1644    * @param response
1645    */
1646   public void groupPrivileges(HttpServletRequest request, HttpServletResponse response) {
1647     
1648     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1649     
1650     GrouperSession grouperSession = null;
1651   
1652     Group group = null;
1653   
1654     try {
1655   
1656       grouperSession = GrouperSession.start(loggedInSubject);
1657   
1658       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
1659       
1660       if (group == null) {
1661         return;
1662       }
1663   
1664       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1665   
1666       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
1667           "/WEB-INF/grouperUi2/group/groupPrivileges.jsp"));
1668       filterPrivilegesHelper(request, response, group);
1669 
1670     } finally {
1671       GrouperSession.stopQuietly(grouperSession);
1672     }
1673   }
1674 
1675   /**
1676    * delete group (show confirm screen)
1677    * @param request
1678    * @param response
1679    */
1680   public void groupDelete(HttpServletRequest request, HttpServletResponse response) {
1681     
1682     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1683     
1684     GrouperSession grouperSession = null;
1685   
1686     Group group = null;
1687   
1688     try {
1689   
1690       grouperSession = GrouperSession.start(loggedInSubject);
1691   
1692       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
1693       
1694       if (group == null) {
1695         return;
1696       }
1697 
1698       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1699       
1700       if (GrouperUiConfig.retrieveConfig().propertyValueBoolean("uiV2.group.checkForFactorWhenDeletingGroup", true)) {
1701         Set<Composite> composites = CompositeFinder.findAsFactor(group);
1702         
1703         if (GrouperUtil.length(composites) > 0) {
1704           StringBuilder result = new StringBuilder();
1705           result.append(TextContainer.retrieveFromRequest().getText()
1706               .get("groupProblemDeleteWithCompositeFactor")).append(" ");
1707           boolean firstLine = true;
1708           for (Composite composite : composites) {
1709             
1710             try {
1711               if (!firstLine) {
1712                 result.append(", ");
1713               }
1714               
1715               Group theGroup = composite.getOwnerGroup();
1716     
1717               GuiGrouprouper/grouperUi/beans/api/GuiGroup.html#GuiGroup">GuiGroup guiGroup = new GuiGroup(theGroup);
1718               result.append(guiGroup.getShortLink());
1719               
1720             } catch (GroupNotFoundException gnfe) {
1721               result.append(TextContainer.retrieveFromRequest().getText().get("groupLabelNotAllowedToViewOwner"));
1722             }
1723             
1724             firstLine = false;
1725             
1726           }
1727           
1728           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, result.toString()));
1729           return;
1730         }
1731       }
1732       
1733       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
1734           "/WEB-INF/grouperUi2/group/groupDelete.jsp"));
1735   
1736     } finally {
1737       GrouperSession.stopQuietly(grouperSession);
1738     }
1739   }
1740 
1741   /**
1742    * hit submit on the delete group screen
1743    * @param request
1744    * @param response
1745    */
1746   public void groupDeleteSubmit(HttpServletRequest request, HttpServletResponse response) {
1747   
1748     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1749   
1750     GrouperSession grouperSession = null;
1751   
1752     Group group = null;
1753   
1754     try {
1755   
1756       grouperSession = GrouperSession.start(loggedInSubject);
1757   
1758       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
1759     
1760       if (group == null) {
1761         return;
1762       }
1763       
1764       String stemId = group.getParentUuid();
1765       
1766       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1767   
1768       try {
1769   
1770         //delete the group
1771         group.delete();
1772   
1773       } catch (InsufficientPrivilegeException ipe) {
1774         
1775         LOG.warn("Insufficient privilege exception for group delete: " + SubjectHelper.getPretty(loggedInSubject), ipe);
1776         
1777         //go to the view group screen
1778         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "')"));
1779     
1780         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
1781             TextContainer.retrieveFromRequest().getText().get("groupDeleteInsufficientPrivileges")));
1782         return;
1783   
1784       } catch (GroupDeleteException sde) {
1785         
1786         LOG.warn("Error deleting group: " + SubjectHelper.getPretty(loggedInSubject) + ", " + group, sde);
1787         
1788         //go to the view group screen
1789         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "')"));
1790     
1791         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
1792             TextContainer.retrieveFromRequest().getText().get("groupErrorCantDelete")));
1793   
1794         return;
1795   
1796       }
1797       
1798       //go to the view stem screen
1799       guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Stem.viewStem&stemId=" + stemId + "')"));
1800   
1801       //lets show a success message on the new screen
1802       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1803           TextContainer.retrieveFromRequest().getText().get("groupDeleteSuccess")));
1804       
1805       GrouperUserDataApi.recentlyUsedGroupRemove(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1806           loggedInSubject, group);
1807 
1808     } catch (RuntimeException re) {
1809       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
1810         return;
1811       }
1812       throw re;
1813 
1814     } finally {
1815       GrouperSession.stopQuietly(grouperSession);
1816     }
1817   
1818   }
1819 
1820   
1821 
1822   /**
1823    * new group submit
1824    * @param request
1825    * @param response
1826    */
1827   public void newGroupSubmit(HttpServletRequest request, HttpServletResponse response) {
1828     
1829     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
1830 
1831     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
1832 
1833     GrouperSession grouperSession = null;
1834   
1835     Group group = null;
1836   
1837     try {
1838   
1839       grouperSession = GrouperSession.start(loggedInSubject);
1840 
1841       final boolean editIdChecked = GrouperUtil.booleanValue(request.getParameter("nameDifferentThanId[]"), false);
1842       final String displayExtension = request.getParameter("displayExtension");
1843       final String extension = editIdChecked ? request.getParameter("extension") : displayExtension;
1844       final String description = request.getParameter("description");
1845       final boolean adminChecked = GrouperUtil.booleanValue(request.getParameter("privileges_admins[]"), false);
1846       final boolean updateChecked = GrouperUtil.booleanValue(request.getParameter("privileges_updaters[]"), false);
1847       final boolean readChecked = GrouperUtil.booleanValue(request.getParameter("privileges_readers[]"), false);
1848       final boolean viewChecked = GrouperUtil.booleanValue(request.getParameter("privileges_viewers[]"), false);
1849       final boolean optinChecked = GrouperUtil.booleanValue(request.getParameter("privileges_optins[]"), false);
1850       final boolean optoutChecked = GrouperUtil.booleanValue(request.getParameter("privileges_optouts[]"), false);
1851       final boolean attrReadChecked = GrouperUtil.booleanValue(request.getParameter("privileges_groupAttrReaders[]"), false);
1852       final boolean attrUpdateChecked = GrouperUtil.booleanValue(request.getParameter("privileges_groupAttrUpdaters[]"), false);
1853 
1854       String groupType = request.getParameter("groupType[]");
1855       
1856       final TypeOfGroup typeOfGroup = TypeOfGroup.valueOfIgnoreCase(groupType, true);
1857       
1858       if (typeOfGroup != TypeOfGroup.group && typeOfGroup != TypeOfGroup.role) {
1859         throw new RuntimeException("Invalid group type, should be group or role: " + typeOfGroup);
1860       }
1861 
1862       String parentFolderId = request.getParameter("parentFolderComboName");
1863       
1864       //just get what they typed in
1865       if (StringUtils.isBlank(parentFolderId)) {
1866         parentFolderId = request.getParameter("parentFolderComboNameDisplay");
1867       }
1868       
1869       if (StringUtils.isBlank(parentFolderId)) {
1870         
1871         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
1872             "#parentFolderComboErrorId",
1873             TextContainer.retrieveFromRequest().getText().get("groupCreateRequiredParentStemId")));
1874         return;
1875       }
1876       
1877       final Stem parentFolder = new StemFinder().assignPrivileges(NamingPrivilege.CREATE_PRIVILEGES)
1878           .assignSubject(loggedInSubject)
1879           .assignScope(parentFolderId).assignFindByUuidOrName(true).findStem();
1880 
1881       if (parentFolder == null) {
1882         
1883         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
1884             "#parentFolderComboErrorId",
1885             TextContainer.retrieveFromRequest().getText().get("groupCreateCantFindParentStemId")));
1886         return;
1887         
1888       }
1889       
1890       if (StringUtils.isBlank(displayExtension)) {
1891         
1892         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
1893             "#groupName",
1894             TextContainer.retrieveFromRequest().getText().get("groupCreateErrorDisplayExtensionRequired")));
1895         return;
1896         
1897       }
1898 
1899       if (StringUtils.isBlank(extension)) {
1900         
1901         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
1902             "#groupId",
1903             TextContainer.retrieveFromRequest().getText().get("groupCreateErrorExtensionRequired")));
1904         return;
1905         
1906       }
1907 
1908       if (parentFolder.isRootStem()) {
1909         
1910         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
1911             "#parentFolderComboErrorId",
1912             TextContainer.retrieveFromRequest().getText().get("groupCreateCantCreateInRoot")));
1913         return;
1914         
1915       }
1916 
1917       final String groupName = parentFolder.getName() + ":" + extension;
1918       
1919       //search as an admin to see if the group exists
1920       group = (Group)GrouperSession.callbackGrouperSession(grouperSession.internal_getRootSession(), new GrouperSessionHandler() {
1921         
1922         public Object callback(GrouperSession theGrouperSession) throws GrouperSessionException {
1923           
1924           return GroupFinder.findByName(theGrouperSession, groupName, false);
1925         }
1926       });
1927 
1928       if (group != null) {
1929         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
1930             editIdChecked ? "#groupId" : "#groupName",
1931             TextContainer.retrieveFromRequest().getText().get("groupCreateCantCreateAlreadyExists")));
1932         return;
1933       }
1934       
1935       try {
1936 
1937         //create the group
1938         group = new GroupSave(grouperSession).assignName(groupName).assignSaveMode(SaveMode.INSERT)
1939             .assignDisplayExtension(displayExtension).assignDescription(description).assignTypeOfGroup(typeOfGroup)
1940             .assignPrivAllAdmin(adminChecked).assignPrivAllAttrRead(attrReadChecked)
1941             .assignPrivAllAttrUpdate(attrUpdateChecked).assignPrivAllOptin(optinChecked)
1942             .assignPrivAllOptout(optoutChecked).assignPrivAllRead(readChecked)
1943             .assignPrivAllUpdate(updateChecked).assignPrivAllView(viewChecked)
1944             .save();
1945   
1946       } catch (GrouperValidationException gve) {
1947         handleGrouperValidationException(guiResponseJs, gve);
1948         return;
1949 
1950         
1951       } catch (InsufficientPrivilegeException ipe) {
1952         
1953         LOG.warn("Insufficient privilege exception for group create: " + SubjectHelper.getPretty(loggedInSubject), ipe);
1954         
1955         //dont change screens
1956         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
1957             TextContainer.retrieveFromRequest().getText().get("groupCreateInsufficientPrivileges")));
1958         return;
1959 
1960         
1961       } catch (Exception sde) {
1962         
1963         LOG.warn("Error creating group: " + SubjectHelper.getPretty(loggedInSubject) + ", " + group, sde);
1964         
1965         if (GrouperUiUtils.vetoHandle(guiResponseJs, sde)) {
1966           return;
1967         }
1968         
1969         //dont change screens
1970         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
1971             TextContainer.retrieveFromRequest().getText().get("groupCreateError") 
1972             + ": " + GrouperUtil.xmlEscape(sde.getMessage(), true)));
1973 
1974         return;
1975 
1976       }
1977 
1978       //go to the view group screen
1979       guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "')"));
1980 
1981       //lets show a success message on the new screen
1982       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
1983           TextContainer.retrieveFromRequest().getText().get("groupCreateSuccess")));
1984 
1985       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
1986           loggedInSubject, group);
1987   
1988     } catch (RuntimeException re) {
1989       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
1990         return;
1991       }
1992       throw re;
1993     } finally {
1994       GrouperSession.stopQuietly(grouperSession);
1995     }
1996   }
1997 
1998   /**
1999    * @param guiResponseJs
2000    * @param gve
2001    */
2002   public static void handleGrouperValidationException(GuiResponseJs guiResponseJs,
2003       GrouperValidationException gve) {
2004     //  groupValidation_groupDescriptionTooLong = Error, group description is too long
2005     //  groupValidation_groupDisplayExtensionTooLong = Error, group name is too long
2006     //  groupValidation_groupExtensionTooLong = Error, group ID is too long
2007     //  groupValidation_groupDisplayNameTooLong = Error, the group name causes the path to be too long, please shorten it
2008     //  groupValidation_groupNameTooLong = Error, the group ID causes the ID path to be too long, please shorten it
2009     
2010     if (StringUtils.equals(Group.VALIDATION_GROUP_DESCRIPTION_TOO_LONG_KEY, gve.getGrouperValidationKey())) {
2011       
2012       guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
2013           "#groupDescription",
2014           TextContainer.retrieveFromRequest().getText().get("groupValidation_" + gve.getGrouperValidationKey())));
2015       return;
2016       
2017     } else if (StringUtils.equals(Group.VALIDATION_GROUP_EXTENSION_TOO_LONG_KEY, gve.getGrouperValidationKey())
2018         || StringUtils.equals(Group.VALIDATION_GROUP_NAME_TOO_LONG_KEY, gve.getGrouperValidationKey())) {
2019 
2020       guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
2021           "#groupId",
2022           TextContainer.retrieveFromRequest().getText().get("groupValidation_" + gve.getGrouperValidationKey())));
2023       return;
2024       
2025     } else if (StringUtils.equals(Group.VALIDATION_GROUP_DISPLAY_EXTENSION_TOO_LONG_KEY, gve.getGrouperValidationKey())
2026         || StringUtils.equals(Group.VALIDATION_GROUP_DISPLAY_NAME_TOO_LONG_KEY, gve.getGrouperValidationKey())) {
2027 
2028       guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
2029           "#groupName",
2030           TextContainer.retrieveFromRequest().getText().get("groupValidation_" + gve.getGrouperValidationKey())));
2031       return;
2032       
2033     } else {
2034       LOG.error("Non-fatal error, not expecting GrouperValidationException: " + gve.getGrouperValidationKey(), gve);
2035       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, gve.getMessage()));
2036       return;
2037     }
2038   }
2039 
2040   
2041   /**
2042    * new group (show create screen)
2043    * @param request
2044    * @param response
2045    */
2046   public void newGroup(HttpServletRequest request, HttpServletResponse response) {
2047     
2048     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2049     
2050     GrouperSession grouperSession = null;
2051   
2052     try {
2053   
2054       grouperSession = GrouperSession.start(loggedInSubject);
2055   
2056       //see if there is a stem id for this
2057       String objectStemId = request.getParameter("objectStemId");
2058       
2059       Pattern pattern = Pattern.compile("^[a-zA-Z0-9-_]+$");
2060       
2061       if (!StringUtils.isBlank(objectStemId) && pattern.matcher(objectStemId).matches()) {
2062         
2063         GrouperRequestContainer.retrieveFromRequestOrCreate().getStemContainer().setObjectStemId(objectStemId);
2064         
2065       }
2066       
2067       UiV2Stem.retrieveStemHelper(request, false, false, false).getStem();
2068       
2069       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2070       
2071       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2072           "/WEB-INF/grouperUi2/group/newGroup.jsp"));
2073   
2074     } finally {
2075       GrouperSession.stopQuietly(grouperSession);
2076     }
2077   }
2078 
2079   /**
2080    * edit a group, show the edit screen
2081    * @param request
2082    * @param response
2083    */
2084   public void groupEdit(HttpServletRequest request, HttpServletResponse response) {
2085     
2086     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2087     
2088     GrouperSession grouperSession = null;
2089   
2090     Group group = null;
2091   
2092     try {
2093   
2094       grouperSession = GrouperSession.start(loggedInSubject);
2095   
2096       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
2097       
2098       if (group == null) {
2099         return;
2100       }
2101   
2102       GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().getGuiGroup().setShowBreadcrumbLink(true);
2103       GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().getGuiGroup().setShowBreadcrumbLinkSeparator(false);
2104       
2105       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2106       
2107       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2108           "/WEB-INF/grouperUi2/group/groupEdit.jsp"));
2109   
2110     } finally {
2111       GrouperSession.stopQuietly(grouperSession);
2112     }
2113   }
2114 
2115   /**
2116    * edit group submit
2117    * @param request
2118    * @param response
2119    */
2120   public void groupEditSubmit(HttpServletRequest request, HttpServletResponse response) {
2121     
2122     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2123   
2124     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2125 
2126     GrouperSession grouperSession = null;
2127 
2128     Group group = null;
2129 
2130     try {
2131   
2132       grouperSession = GrouperSession.start(loggedInSubject);
2133 
2134       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
2135       
2136       if (group == null) {
2137         return;
2138       }
2139 
2140       final GrouperSession GROUPER_SESSION = grouperSession;
2141       
2142       final String extension = request.getParameter("extension");
2143       final String displayExtension = request.getParameter("displayExtension");
2144       final String description = request.getParameter("description");
2145       final String alternateName = request.getParameter("alternateName");
2146       final boolean setAlternateNameIfRename = GrouperUtil.booleanValue(request.getParameter("setAlternateNameIfRename[]"), false);
2147       final boolean adminChecked = GrouperUtil.booleanValue(request.getParameter("privileges_admins[]"), false);
2148       final boolean updateChecked = GrouperUtil.booleanValue(request.getParameter("privileges_updaters[]"), false);
2149       final boolean readChecked = GrouperUtil.booleanValue(request.getParameter("privileges_readers[]"), false);
2150       final boolean viewChecked = GrouperUtil.booleanValue(request.getParameter("privileges_viewers[]"), false);
2151       final boolean optinChecked = GrouperUtil.booleanValue(request.getParameter("privileges_optins[]"), false);
2152       final boolean optoutChecked = GrouperUtil.booleanValue(request.getParameter("privileges_optouts[]"), false);
2153       final boolean attrReadChecked = GrouperUtil.booleanValue(request.getParameter("privileges_groupAttrReaders[]"), false);
2154       final boolean attrUpdateChecked = GrouperUtil.booleanValue(request.getParameter("privileges_groupAttrUpdaters[]"), false);
2155       final boolean cannotAddSelf = GrouperUtil.booleanValue(request.getParameter("groupCreateCannotAddSelfName"), false);
2156       String groupType = request.getParameter("groupType[]");
2157       
2158       final TypeOfGroup typeOfGroup = TypeOfGroup.valueOfIgnoreCase(groupType, true);
2159       
2160       if (typeOfGroup != TypeOfGroup.group && typeOfGroup != TypeOfGroup.role) {
2161         throw new RuntimeException("Invalid group type, should be group or role: " + typeOfGroup);
2162       }
2163       
2164       
2165       
2166       if (StringUtils.isBlank(displayExtension)) {
2167         
2168         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
2169             "#groupName",
2170             TextContainer.retrieveFromRequest().getText().get("groupCreateErrorDisplayExtensionRequired")));
2171         return;
2172         
2173       }
2174   
2175       if (StringUtils.isBlank(extension)) {
2176         
2177         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
2178             "#groupId",
2179             TextContainer.retrieveFromRequest().getText().get("groupCreateErrorExtensionRequired")));
2180         return;
2181         
2182       }
2183   
2184       try {
2185   
2186         //create the group
2187         GroupSave groupSave = new GroupSave(GROUPER_SESSION).assignUuid(group.getId())
2188             .assignSaveMode(SaveMode.UPDATE)
2189             .assignName(group.getParentStemName() + ":" + extension)
2190             .assignAlternateName(alternateName)
2191             .assignSetAlternateNameIfRename(setAlternateNameIfRename)
2192             .assignDisplayExtension(displayExtension).assignDescription(description).assignTypeOfGroup(typeOfGroup)
2193             .assignPrivAllAdmin(adminChecked).assignPrivAllAttrRead(attrReadChecked)
2194             .assignPrivAllAttrUpdate(attrUpdateChecked).assignPrivAllOptin(optinChecked)
2195             .assignPrivAllOptout(optoutChecked).assignPrivAllRead(readChecked)
2196             .assignPrivAllUpdate(updateChecked).assignPrivAllView(viewChecked);
2197         group = groupSave.save();
2198 
2199         boolean madeChange = groupSave.getSaveResultType() != SaveResultType.NO_CHANGE;
2200         
2201         GroupContainer groupContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer();
2202         if (groupContainer.isCannotAddSelfUserCanEdit()) {
2203           if (cannotAddSelf && !groupContainer.isCannotAddSelfAssignedToGroup()) {
2204             MembershipCannotAddSelfToGroupHook.cannotAddSelfAssign(group);
2205             madeChange = true;
2206           } else if (!cannotAddSelf && groupContainer.isCannotAddSelfAssignedToGroup()) {
2207             MembershipCannotAddSelfToGroupHook.cannotAddSelfRevoke(group);
2208             madeChange = true;
2209           }
2210         }
2211         
2212         //go to the view group screen
2213         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "')"));
2214     
2215         //lets show a success message on the new screen
2216         if (!madeChange) {
2217           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
2218               TextContainer.retrieveFromRequest().getText().get("groupEditNoChangeNote")));
2219         } else {
2220           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
2221               TextContainer.retrieveFromRequest().getText().get("groupEditSuccess")));
2222         }
2223       
2224   
2225       } catch (GrouperValidationException gve) {
2226         handleGrouperValidationException(guiResponseJs, gve);
2227         return;
2228 
2229       } catch (InsufficientPrivilegeException ipe) {
2230         
2231         LOG.warn("Insufficient privilege exception for group edit: " + SubjectHelper.getPretty(loggedInSubject), ipe);
2232         
2233         //dont change screens
2234         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2235             TextContainer.retrieveFromRequest().getText().get("groupCreateInsufficientPrivileges")));
2236         return;
2237   
2238       } catch (Exception sde) {
2239         
2240         LOG.warn("Error edit group: " + SubjectHelper.getPretty(loggedInSubject) + ", " + group, sde);
2241 
2242         if (GrouperUiUtils.vetoHandle(guiResponseJs, sde)) {
2243           return;
2244         }
2245 
2246         //dont change screens
2247         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2248             TextContainer.retrieveFromRequest().getText().get("groupEditError") 
2249             + ": " + GrouperUtil.xmlEscape(sde.getMessage(), true)));
2250   
2251         return;
2252   
2253       }
2254     
2255     } finally {
2256       GrouperSession.stopQuietly(grouperSession);
2257     }
2258   }
2259 
2260   /**
2261    * copy group
2262    * @param request
2263    * @param response
2264    */
2265   public void groupCopy(HttpServletRequest request, HttpServletResponse response) {
2266     
2267     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2268     
2269     GrouperSession grouperSession = null;
2270   
2271     Group group = null;
2272   
2273     try {
2274   
2275       grouperSession = GrouperSession.start(loggedInSubject);
2276   
2277       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
2278       
2279       if (group == null) {
2280         return;
2281       }
2282   
2283       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2284       
2285       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2286           "/WEB-INF/grouperUi2/group/groupCopy.jsp"));
2287   
2288     } finally {
2289       GrouperSession.stopQuietly(grouperSession);
2290     }
2291   }
2292 
2293   /**
2294    * view audits for group
2295    * @param request
2296    * @param response
2297    */
2298   public void viewAudits(HttpServletRequest request, HttpServletResponse response) {
2299     
2300     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2301     
2302     GrouperSession grouperSession = null;
2303   
2304     Group group = null;
2305   
2306     try {
2307   
2308       grouperSession = GrouperSession.start(loggedInSubject);
2309   
2310       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
2311       
2312       if (group == null) {
2313         return;
2314       }
2315   
2316       GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
2317       grouperRequestContainer.getGroupContainer().setAuditType(request.getParameter("auditType"));
2318       
2319       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2320       
2321       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2322           "/WEB-INF/grouperUi2/group/groupViewAudits.jsp"));
2323       
2324       viewAuditsHelper(request, response, group);
2325 
2326     } finally {
2327       GrouperSession.stopQuietly(grouperSession);
2328     }
2329   }
2330 
2331   /**
2332    * move group
2333    * @param request
2334    * @param response
2335    */
2336   public void groupMove(HttpServletRequest request, HttpServletResponse response) {
2337     
2338     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2339     
2340     GrouperSession grouperSession = null;
2341   
2342     Group group = null;
2343   
2344     try {
2345   
2346       grouperSession = GrouperSession.start(loggedInSubject);
2347   
2348       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
2349       
2350       if (group == null) {
2351         return;
2352       }
2353   
2354       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2355       
2356       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2357           "/WEB-INF/grouperUi2/group/groupMove.jsp"));
2358   
2359     } finally {
2360       GrouperSession.stopQuietly(grouperSession);
2361     }
2362   }
2363 
2364   /**
2365    * 
2366    * @param request
2367    * @param response
2368    */
2369   public void groupMoveSubmit(HttpServletRequest request, HttpServletResponse response) {
2370   
2371     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2372   
2373     GrouperSession grouperSession = null;
2374   
2375     Group group = null;
2376   
2377     try {
2378   
2379       grouperSession = GrouperSession.start(loggedInSubject);
2380   
2381       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
2382     
2383       if (group == null) {
2384         return;
2385       }
2386   
2387       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2388   
2389       String parentFolderId = request.getParameter("parentFolderComboName");
2390       
2391       //just get what they typed in
2392       if (StringUtils.isBlank(parentFolderId)) {
2393         parentFolderId = request.getParameter("parentFolderComboNameDisplay");
2394       }
2395       
2396       boolean moveChangeAlternateNames = GrouperUtil.booleanValue(request.getParameter("moveChangeAlternateNames[]"), false);
2397       
2398       final Stem parentFolder = new StemFinder().assignPrivileges(NamingPrivilege.CREATE_PRIVILEGES)
2399           .assignSubject(loggedInSubject)
2400           .assignScope(parentFolderId).assignFindByUuidOrName(true).findStem();
2401       
2402       if (parentFolder == null) {
2403         
2404         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2405             TextContainer.retrieveFromRequest().getText().get("groupCopyCantFindParentStemId")));
2406         return;
2407         
2408       }
2409   
2410       //MCH 20131224: dont need this since we are searching by stemmed folders above
2411       
2412       try {
2413   
2414         //get the new folder that was created
2415         new GroupMove(group, parentFolder).assignAlternateName(moveChangeAlternateNames).save();
2416   
2417       } catch (InsufficientPrivilegeException ipe) {
2418         
2419         LOG.warn("Insufficient privilege exception for group move: " + SubjectHelper.getPretty(loggedInSubject), ipe);
2420         
2421         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2422             TextContainer.retrieveFromRequest().getText().get("groupMoveInsufficientPrivileges")));
2423         return;
2424   
2425       }
2426       
2427       //go to the view group screen
2428       guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "')"));
2429   
2430       //lets show a success message on the new screen
2431       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
2432           TextContainer.retrieveFromRequest().getText().get("groupMoveSuccess")));
2433       
2434       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
2435           loggedInSubject, group);
2436   
2437     } catch (RuntimeException re) {
2438       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
2439         return;
2440       }
2441       throw re;
2442     } finally {
2443       GrouperSession.stopQuietly(grouperSession);
2444     }
2445   
2446   }
2447 
2448   /**
2449    * 
2450    * @param request
2451    * @param response
2452    */
2453   public void groupCopySubmit(HttpServletRequest request, HttpServletResponse response) {
2454   
2455     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2456   
2457     GrouperSession grouperSession = null;
2458   
2459     Group group = null;
2460   
2461     try {
2462   
2463       grouperSession = GrouperSession.start(loggedInSubject);
2464   
2465       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
2466     
2467       if (group == null) {
2468         return;
2469       }
2470   
2471       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2472   
2473       String displayExtension = request.getParameter("displayExtension");
2474       String extension = request.getParameter("extension");
2475   
2476       boolean copyGroupAttributes = GrouperUtil.booleanValue(request.getParameter("copyGroupAttributes[]"), false);
2477       boolean copyListMemberships = GrouperUtil.booleanValue(request.getParameter("copyListMemberships[]"), false);
2478       boolean copyGroupPrivileges = GrouperUtil.booleanValue(request.getParameter("copyGroupPrivileges[]"), false);
2479       boolean copyListMembershipsInOtherGroups = GrouperUtil.booleanValue(request.getParameter("copyListMembershipsInOtherGroups[]"), false);
2480       boolean copyPrivsInOtherGroups = GrouperUtil.booleanValue(request.getParameter("copyPrivsInOtherGroups[]"), false);
2481       
2482       String parentFolderId = request.getParameter("parentFolderComboName");
2483       
2484       //just get what they typed in
2485       if (StringUtils.isBlank(parentFolderId)) {
2486         parentFolderId = request.getParameter("parentFolderComboNameDisplay");
2487       }
2488       
2489       if (StringUtils.isBlank(extension)) {
2490         extension = group.getExtension();
2491       }
2492       
2493       if (StringUtils.isBlank(displayExtension)) {
2494         displayExtension = group.getDisplayExtension();
2495       }
2496       
2497       final Stem parentFolder = StringUtils.isBlank(parentFolderId) ? null : new StemFinder()
2498           .assignPrivileges(NamingPrivilege.CREATE_PRIVILEGES)
2499           .assignSubject(loggedInSubject)
2500           .assignScope(parentFolderId).assignFindByUuidOrName(true).findStem();
2501       
2502       if (parentFolder == null) {
2503         
2504         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2505             TextContainer.retrieveFromRequest().getText().get("groupCopyCantFindParentStemId")));
2506   
2507         return;
2508         
2509       }
2510   
2511       Group newGroup = null;
2512       
2513       try {
2514   
2515         //get the new folder that was created
2516         newGroup = new GroupCopy(group, parentFolder).copyAttributes(copyGroupAttributes)
2517             .copyListGroupAsMember(copyListMembershipsInOtherGroups)
2518             .copyListMembersOfGroup(copyListMemberships)
2519             .copyPrivilegesOfGroup(copyGroupPrivileges)
2520             .copyGroupAsPrivilege(copyPrivsInOtherGroups)
2521             .setDisplayExtension(displayExtension)
2522             .setExtension(extension).save();
2523   
2524       } catch (InsufficientPrivilegeException ipe) {
2525         
2526         LOG.warn("Insufficient privilege exception for group copy: " + SubjectHelper.getPretty(loggedInSubject), ipe);
2527         
2528         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2529             TextContainer.retrieveFromRequest().getText().get("groupCopyInsufficientPrivileges")));
2530         return;
2531   
2532       }
2533       
2534       guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + newGroup.getId() + "')"));
2535   
2536       //lets show a success message on the new screen
2537       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
2538           TextContainer.retrieveFromRequest().getText().get("groupCopySuccess")));
2539       
2540       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
2541           loggedInSubject, group);
2542       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
2543           loggedInSubject, newGroup);
2544   
2545     } catch (RuntimeException re) {
2546       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
2547         return;
2548       }
2549       throw re;
2550     } finally {
2551       GrouperSession.stopQuietly(grouperSession);
2552     }
2553   
2554   }
2555 
2556   /** logger */
2557   protected static final Log LOG = LogFactory.getLog(UiV2Group.class);
2558 
2559 
2560   /**
2561    * get the group from the request
2562    * @param request
2563    * @param requirePrivilege (view is automatic)
2564    * @return the group finder result
2565    */
2566   public static RetrieveGroupHelperResult retrieveGroupHelper(HttpServletRequest request, Privilege requirePrivilege) {
2567     
2568     return retrieveGroupHelper(request, requirePrivilege, true);
2569     
2570   }
2571 
2572   /**
2573    * get the group from the request
2574    * @param request
2575    * @param requirePrivilege (view is automatic)
2576    * @param errorIfNotFound will put an error on the screen if nothing passed in
2577    * @return the group finder result
2578    */
2579   public static RetrieveGroupHelperResult retrieveGroupHelper(HttpServletRequest request, Privilege requirePrivilege, boolean errorIfNotFound) {
2580   
2581     //initialize the bean
2582     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
2583     
2584     RetrieveGroupHelperResult result = new RetrieveGroupHelperResult();
2585   
2586     GrouperSession grouperSession = GrouperSession.staticGrouperSession();
2587 
2588     GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
2589 
2590     Group group = null;
2591   
2592     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2593 
2594     
2595     
2596     String groupId = request.getParameter("groupId");
2597     String groupIndex = request.getParameter("groupIndex");
2598     String groupName = request.getParameter("groupName");
2599     
2600     boolean addedError = false;
2601     
2602     if (!StringUtils.isBlank(groupId)) {
2603       group = GroupFinder.findByUuid(grouperSession, groupId, false);
2604     } else if (!StringUtils.isBlank(groupName)) {
2605       group = GroupFinder.findByName(grouperSession, groupName, false);
2606     } else if (!StringUtils.isBlank(groupIndex)) {
2607       long idIndex = GrouperUtil.longValue(groupIndex);
2608       group = GroupFinder.findByIdIndexSecure(idIndex, false, null);
2609     } else {
2610       
2611       //if viewing a subject, and that subject is a group, just show the group screen
2612       Subject subject = UiV2Subject.retrieveSubjectHelper(request, false);
2613       if (subject != null && GrouperSourceAdapter.groupSourceId().equals(subject.getSourceId())) {
2614         group = GroupFinder.findByUuid(grouperSession, subject.getId(), false);
2615       } else {
2616         if (errorIfNotFound) {
2617           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2618               TextContainer.retrieveFromRequest().getText().get("groupCantFindGroupId")));
2619           
2620           addedError = true;
2621         }
2622       }
2623     }
2624   
2625     if (group != null) {
2626       groupContainer.setGuiGroup(new GuiGroup(group));      
2627       boolean privsOk = true;
2628 
2629       if (requirePrivilege != null) {
2630         if (requirePrivilege.equals(AccessPrivilege.ADMIN) && !groupContainer.isCanAdmin()) {
2631           if (errorIfNotFound) {
2632             guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2633                 TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToAdminGroup")));
2634             addedError = true;
2635             }
2636           privsOk = false;
2637         }
2638         else if (requirePrivilege.equals(AccessPrivilege.VIEW) && !groupContainer.isCanView()) {
2639           if (errorIfNotFound) {
2640             guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2641                 TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToViewGroup")));
2642             addedError = true;
2643           }
2644           privsOk = false;
2645         }
2646         else if (requirePrivilege.equals(AccessPrivilege.READ) && !groupContainer.isCanRead()) {
2647           if (errorIfNotFound) {
2648             guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2649                 TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToReadGroup")));
2650             addedError = true;
2651           }
2652           privsOk = false;
2653         } else if (requirePrivilege.equals(AccessPrivilege.OPTIN) && !groupContainer.isCanOptin()) {
2654           if (errorIfNotFound) {
2655             guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2656                 TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToOptinGroup")));
2657             addedError = true;
2658           }
2659           privsOk = false;
2660         } else if (requirePrivilege.equals(AccessPrivilege.OPTOUT) && !groupContainer.isCanOptout()) {
2661           if (errorIfNotFound) {
2662             guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2663                 TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToOptoutGroup")));
2664             addedError = true;
2665           }
2666           privsOk = false;
2667         } else if (requirePrivilege.equals(AccessPrivilege.UPDATE) && !groupContainer.isCanUpdate()) {
2668           if (errorIfNotFound) {
2669             guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2670                 TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToUpdateGroup")));
2671             addedError = true;
2672           }
2673           privsOk = false;
2674         }  
2675       }
2676       
2677       if (privsOk) {
2678         result.setGroup(group);
2679         
2680         List<GrouperObjectTypesAttributeValue> attributeValuesForGroup = GrouperObjectTypesConfiguration.getGrouperObjectTypesAttributeValues(group);
2681         grouperRequestContainer.getObjectTypeContainer().setGuiConfiguredGrouperObjectTypesAttributeValues(GuiGrouperObjectTypesAttributeValue.convertFromGrouperObjectTypesAttributeValues(attributeValuesForGroup));
2682         
2683         GrouperLoaderContainer grouperLoaderContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getGrouperLoaderContainer();
2684 
2685         boolean canSeeLoader = grouperLoaderContainer.isCanSeeLoader();
2686         if (canSeeLoader) {
2687           UiV2GrouperLoader.setupLoaderManagedGroup(group, grouperLoaderContainer);
2688         }
2689         
2690       }
2691 
2692     } else {
2693       
2694       if (!addedError && (!StringUtils.isBlank(groupId) || !StringUtils.isBlank(groupName) || !StringUtils.isBlank(groupIndex))) {
2695         result.setAddedError(true);
2696         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2697             TextContainer.retrieveFromRequest().getText().get("groupCantFindGroup")));
2698         addedError = true;
2699       }
2700       
2701     }
2702     result.setAddedError(addedError);
2703   
2704     //go back to the main screen, cant find group
2705     if (addedError && errorIfNotFound) {
2706       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2707           "/WEB-INF/grouperUi2/index/indexMain.jsp"));
2708     }
2709 
2710     return result;
2711   }
2712 
2713   
2714   
2715   /**
2716    * this groups memberships
2717    * @param request
2718    * @param response
2719    */
2720   public void thisGroupsMemberships(HttpServletRequest request, HttpServletResponse response) {
2721     
2722     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2723     
2724     GrouperSession grouperSession = null;
2725   
2726     Group group = null;
2727   
2728     try {
2729   
2730       grouperSession = GrouperSession.start(loggedInSubject);
2731   
2732       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
2733       
2734       if (group == null) {
2735         return;
2736       }
2737   
2738       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2739   
2740       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2741           "/WEB-INF/grouperUi2/group/thisGroupsMemberships.jsp"));
2742       filterThisGroupsMembershipsHelper(request, response, group);
2743 
2744     } finally {
2745       GrouperSession.stopQuietly(grouperSession);
2746     }
2747   }
2748 
2749   /**
2750    * the filter button was pressed of this groups memberships screen, 
2751    * or paging or sorting, or view Group or something
2752    * @param request
2753    * @param response
2754    * @param group 
2755    */
2756   private void filterThisGroupsMembershipsHelper(HttpServletRequest request, HttpServletResponse response, Group group) {
2757     
2758     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
2759     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2760     
2761     String filterText = request.getParameter("filterText");
2762     GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
2763     
2764     //if filtering by subjects that have a certain type
2765     String membershipTypeString = request.getParameter("membershipType");
2766     MembershipType membershipType = null;
2767     if (!StringUtils.isBlank(membershipTypeString)) {
2768       membershipType = MembershipType.valueOfIgnoreCase(membershipTypeString, true);
2769     }
2770 
2771     GuiPaging guiPaging = groupContainer.getGuiPaging();
2772     QueryOptions queryOptions = new QueryOptions();
2773     
2774     GrouperPagingTag2.processRequest(request, guiPaging, queryOptions);
2775     
2776     MembershipFinder membershipFinder = new MembershipFinder()
2777       .addMemberId(group.toMember().getId())
2778       .assignCheckSecurity(true)
2779       .assignHasFieldForGroup(true)
2780       .assignEnabled(true)
2781       .assignHasMembershipTypeForGroup(true)
2782       .assignQueryOptionsForGroup(queryOptions)
2783       .assignSplitScopeForGroup(true);
2784     
2785     if (membershipType != null) {
2786       membershipFinder.assignMembershipType(membershipType);
2787     }
2788   
2789     if (!StringUtils.isBlank(filterText)) {
2790       membershipFinder.assignScopeForGroup(filterText);
2791     }
2792   
2793     //set of subjects, and what memberships each subject has
2794     Set<MembershipSubjectContainer> results = membershipFinder
2795         .findMembershipResult().getMembershipSubjectContainers();
2796   
2797     groupContainer.setGuiMembershipSubjectContainers(GuiMembershipSubjectContainer.convertFromMembershipSubjectContainers(results));
2798     
2799     guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
2800     
2801     guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#thisGroupsMembershipsFilterResultsId", 
2802         "/WEB-INF/grouperUi2/group/thisGroupsMembershipsContents.jsp"));
2803   
2804   }
2805 
2806   /**
2807    * the remove members button was pressed
2808    * @param request
2809    * @param response
2810    */
2811   public void removeMembers(HttpServletRequest request, HttpServletResponse response) {
2812   
2813     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2814   
2815     GrouperSession grouperSession = null;
2816   
2817     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2818   
2819     try {
2820       grouperSession = GrouperSession.start(loggedInSubject);
2821   
2822       final Group group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
2823   
2824       if (group == null) {
2825         return;
2826       }
2827   
2828       final Set<String> membershipsIds = new HashSet<String>();
2829       
2830       for (int i=0;i<1000;i++) {
2831         String membershipId = request.getParameter("membershipRow_" + i + "[]");
2832         if (!StringUtils.isBlank(membershipId)) {
2833           membershipsIds.add(membershipId);
2834         }
2835       }
2836   
2837       if (membershipsIds.size() == 0) {
2838         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2839             TextContainer.retrieveFromRequest().getText().get("groupMembershipsRemoveNoSubjectSelects")));
2840         return;
2841       }
2842       final int[] successes = new int[]{0};
2843       final int[] failures = new int[]{0};
2844       
2845       final int[] count = new int[]{0};
2846       
2847       //subject has update, so this operation as root in case removing affects the membership
2848       GrouperSession.internal_callbackRootGrouperSession(new GrouperSessionHandler() {
2849         
2850         public Object callback(GrouperSession grouperSession2) throws GrouperSessionException {
2851           for (String membershipId : membershipsIds) {
2852             try {
2853               Membership membership = new MembershipFinder().addMembershipId(membershipId).findMembership(true);
2854 
2855               Member member = membership.getMember();
2856               group.deleteMember(member, false);
2857               
2858               if (count[0]++ < 5 && group.canHavePrivilege(loggedInSubject, AccessPrivilege.VIEW.getName(), false)) {
2859                 GrouperUserDataApi.recentlyUsedMemberAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
2860                     loggedInSubject, member);
2861 
2862               }
2863               
2864               successes[0]++;
2865             } catch (Exception e) {
2866               LOG.warn("Error with membership: " + membershipId + ", user: " + loggedInSubject, e);
2867               failures[0]++;
2868             }
2869           }
2870           
2871           if (group.canHavePrivilege(loggedInSubject, AccessPrivilege.VIEW.getName(), false)) {
2872             GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
2873               loggedInSubject, group);
2874           }
2875           
2876           return null;
2877         }
2878       });
2879       
2880       GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().setSuccessCount(successes[0]);
2881       GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer().setFailureCount(failures[0]);
2882 
2883 
2884       if (!group.canHavePrivilege(loggedInSubject, AccessPrivilege.UPDATE.getName(), false) 
2885           || !group.canHavePrivilege(loggedInSubject, AccessPrivilege.READ.getName(), false)) {
2886         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Main.indexMain')"));
2887       } else {
2888         filterHelper(request, response, group);
2889       }
2890       
2891       //put this after redirect
2892       if (failures[0] > 0) {
2893         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
2894             TextContainer.retrieveFromRequest().getText().get("groupDeleteMembersErrors")));
2895       } else {
2896         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
2897             TextContainer.retrieveFromRequest().getText().get("groupDeleteMembersSuccesses")));
2898       }
2899 
2900     } catch (RuntimeException re) {
2901       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
2902         return;
2903       }
2904       throw re;
2905     } finally {
2906       GrouperSession.stopQuietly(grouperSession);
2907     }
2908   }
2909 
2910   /**
2911    * this groups group privileges
2912    * @param request
2913    * @param response
2914    */
2915   public void thisGroupsGroupPrivileges(HttpServletRequest request, HttpServletResponse response) {
2916     
2917     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2918     
2919     GrouperSession grouperSession = null;
2920   
2921     Group group = null;
2922   
2923     try {
2924   
2925       grouperSession = GrouperSession.start(loggedInSubject);
2926   
2927       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
2928       
2929       if (group == null) {
2930         return;
2931       }
2932   
2933       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2934   
2935       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
2936           "/WEB-INF/grouperUi2/group/thisGroupsGroupPrivileges.jsp"));
2937       filterThisGroupsGroupPrivilegesHelper(request, response, group);
2938   
2939     } finally {
2940       GrouperSession.stopQuietly(grouperSession);
2941     }
2942   }
2943 
2944   /**
2945    * the filter button for this groups privileges was pressed, or paging or sorting or something
2946    * @param request
2947    * @param response
2948    */
2949   public void filterThisGroupsGroupPrivileges(HttpServletRequest request, HttpServletResponse response) {
2950     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
2951     
2952     GrouperSession grouperSession = null;
2953     
2954     try {
2955       grouperSession = GrouperSession.start(loggedInSubject);
2956   
2957   
2958       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
2959       
2960       if (group == null) {
2961         return;
2962       }
2963   
2964       filterThisGroupsGroupPrivilegesHelper(request, response, group);
2965 
2966     } finally {
2967       GrouperSession.stopQuietly(grouperSession);
2968     }
2969 
2970   }
2971 
2972   /**
2973    * the filter button was pressed of this groups group privileges screen, 
2974    * or paging or sorting, or view Group or something
2975    * @param request
2976    * @param response
2977    * @param group 
2978    */
2979   private void filterThisGroupsGroupPrivilegesHelper(HttpServletRequest request, HttpServletResponse response, Group group) {
2980 
2981     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
2982 
2983     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
2984 
2985     //if filtering text in subjects
2986     String privilegeFilterText = request.getParameter("privilegeFilterText");
2987     
2988     String privilegeFieldName = request.getParameter("privilegeField");
2989     
2990     Field privilegeField = null;
2991     if (!StringUtils.isBlank(privilegeFieldName)) {
2992       privilegeField = FieldFinder.find(privilegeFieldName, true);
2993     }
2994     
2995     //if filtering by subjects that have a certain type
2996     String membershipTypeString = request.getParameter("privilegeMembershipType");
2997     MembershipType membershipType = null;
2998     if (!StringUtils.isBlank(membershipTypeString)) {
2999       membershipType = MembershipType.valueOfIgnoreCase(membershipTypeString, true);
3000     }
3001     
3002     GuiPaging guiPaging = grouperRequestContainer.getGroupContainer().getPrivilegeGuiPaging();
3003     QueryOptions queryOptions = new QueryOptions();
3004     
3005     GrouperPagingTag2.processRequest(request, guiPaging, queryOptions); 
3006     
3007     MembershipFinder membershipFinder = new MembershipFinder()
3008       .addSubject(group.toSubject()).assignCheckSecurity(true)
3009       .assignFieldType(FieldType.ACCESS)
3010       .assignEnabled(true)
3011       .assignHasFieldForGroup(true)
3012       .assignHasMembershipTypeForGroup(true)
3013       .assignQueryOptionsForGroup(queryOptions)
3014       .assignSplitScopeForGroup(true);
3015     
3016     if (membershipType != null) {
3017       membershipFinder.assignMembershipType(membershipType);
3018     }
3019 
3020     if (privilegeField != null) {
3021       membershipFinder.assignField(privilegeField);
3022       membershipFinder.assignIncludeInheritedPrivileges(true);
3023     }
3024 
3025     if (!StringUtils.isBlank(privilegeFilterText)) {
3026       membershipFinder.assignScopeForGroup(privilegeFilterText);
3027     }
3028 
3029     //set of subjects, and what privs each subject has
3030     Set<MembershipSubjectContainer> results = membershipFinder
3031         .findMembershipResult().getMembershipSubjectContainers();
3032 
3033     MembershipSubjectContainer.considerAccessPrivilegeInheritance(results);
3034 
3035     grouperRequestContainer.getGroupContainer().setPrivilegeGuiMembershipSubjectContainers(
3036         GuiMembershipSubjectContainer.convertFromMembershipSubjectContainers(results));
3037 
3038     guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
3039 
3040     guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#thisGroupsGroupPrivilegesFilterResultsId", 
3041         "/WEB-INF/grouperUi2/group/thisGroupsGroupPrivilegesContents.jsp"));
3042 
3043   }
3044 
3045   /**
3046    * assign or remove a privilege from a group, on this groups privileges
3047    * @param request
3048    * @param response
3049    */
3050   public void thisGroupsPrivilegesAssignPrivilege(HttpServletRequest request, HttpServletResponse response) {
3051     
3052     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3053   
3054     GrouperSession grouperSession = null;
3055     
3056     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3057 
3058     try {
3059       grouperSession = GrouperSession.start(loggedInSubject);
3060   
3061       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3062   
3063       if (group == null) {
3064         return;
3065       }
3066   
3067       //?assign=false&groupId=${grouperRequestContainer.groupContainer.guiGroup.stem.id}&fieldName=${fieldName}&memberId=${guiMembershipSubjectContainer.guiMember.member.uuid}
3068       String assignString = request.getParameter("assign");
3069       boolean assign = GrouperUtil.booleanValue(assignString);
3070       String fieldName = request.getParameter("fieldName");
3071       String parentGroupId = request.getParameter("parentGroupId");
3072   
3073       Group parentGroup = GroupFinder.findByUuid(grouperSession, parentGroupId, false);
3074       
3075       if (parentGroup == null || !parentGroup.canHavePrivilege(loggedInSubject, AccessPrivilege.ADMIN.getName(), false)) {
3076         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3077             TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToAdminAnotherGroup")));
3078         filterThisGroupsGroupPrivilegesHelper(request, response, group);
3079         return;
3080       }
3081       
3082       Privilege privilege = AccessPrivilege.listToPriv(fieldName);
3083       
3084       if (privilege == null) {
3085         throw new RuntimeException("Why is privilege not found???? " + fieldName);
3086       }
3087       
3088       //if someone revoked in the meantime, who cares...
3089       if (assign) {
3090         parentGroup.grantPriv(group.toSubject(), privilege, false);
3091         
3092         //set a success message
3093         //messes up screen
3094         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3095         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessGrantedPrivilege")));
3096         
3097       } else {
3098         parentGroup.revokePriv(group.toSubject(), privilege, false);
3099         
3100         //messes up screen
3101         //set a success message
3102         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3103         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessRevokedPrivilege")));
3104       }
3105   
3106       filterThisGroupsGroupPrivilegesHelper(request, response, group);
3107   
3108       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
3109           loggedInSubject, group);
3110 
3111     } catch (RuntimeException re) {
3112       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
3113         return;
3114       }
3115       throw re;
3116     } finally {
3117       GrouperSession.stopQuietly(grouperSession);
3118     }
3119   
3120   
3121   }
3122 
3123   /**
3124    * submit the main form on the this groups privilege screen which can do batch operations on a number of rows
3125    * @param request
3126    * @param response
3127    */
3128   public void thisGroupsPrivilegesAssignPrivilegeBatch(HttpServletRequest request, HttpServletResponse response) {
3129   
3130     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3131   
3132     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3133   
3134     GrouperSession grouperSession = null;
3135     
3136     try {
3137       grouperSession = GrouperSession.start(loggedInSubject);
3138   
3139       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3140   
3141       if (group == null) {
3142         return;
3143       }
3144         
3145       String groupPrivilegeBatchUpdateOperation = request.getParameter("groupPrivilegeBatchUpdateOperation");
3146       Pattern operationPattern = Pattern.compile("^(assign|revoke)_(.*)$");
3147       Matcher operationMatcher = operationPattern.matcher(groupPrivilegeBatchUpdateOperation);
3148       if (!operationMatcher.matches()) {
3149         throw new RuntimeException("Invalid submission, should have a valid operation: '" + groupPrivilegeBatchUpdateOperation + "'");
3150       }
3151       
3152       String assignOrRevokeString = operationMatcher.group(1);
3153       boolean assign = StringUtils.equals("assign", assignOrRevokeString);
3154       if (!assign && !StringUtils.equals("revoke", assignOrRevokeString)) {
3155         throw new RuntimeException("Cant find assign or revoke: '" + assignOrRevokeString + "'");
3156       }
3157       String fieldName = operationMatcher.group(2);
3158       
3159       boolean assignAll = StringUtils.equals(fieldName, "all");
3160       boolean readersUpdaters = StringUtils.equals(fieldName, "readersUpdaters");
3161       
3162       //lets see how many are on a page
3163       int pageSize = GrouperPagingTag2.pageSize(request);
3164       
3165       //lets loop and get all the checkboxes
3166       Set<Group> parentGroups = new LinkedHashSet<Group>();
3167       
3168       //loop through all the checkboxes and collect all the groups
3169       for (int i=0;i<pageSize;i++) {
3170         String parentGroupId = request.getParameter("privilegeSubjectRow_" + i + "[]");
3171         if (!StringUtils.isBlank(parentGroupId)) {
3172           
3173           Group parentGroup = GroupFinder.findByUuid(grouperSession, parentGroupId, false);
3174           
3175           if (parentGroup != null && parentGroup.canHavePrivilege(loggedInSubject, AccessPrivilege.ADMIN.getName(), false)) {
3176             parentGroups.add(parentGroup);
3177           }
3178         }
3179       }
3180   
3181       if (GrouperUtil.length(parentGroups) == 0) {
3182   
3183         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
3184             TextContainer.retrieveFromRequest().getText().get("thisGroupsPrivilegesErrorGroupRequired")));
3185         guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
3186         filterThisGroupsGroupPrivilegesHelper(request, response, group);
3187         return;
3188       }
3189       
3190       int changes = 0;
3191       
3192       Privilege[] privileges = assignAll ? (assign ? new Privilege[]{  
3193           AccessPrivilege.listToPriv(Field.FIELD_NAME_ADMINS)} : new Privilege[]{  
3194           AccessPrivilege.listToPriv(Field.FIELD_NAME_ADMINS),
3195           AccessPrivilege.listToPriv(Field.FIELD_NAME_GROUP_ATTR_READERS),
3196           AccessPrivilege.listToPriv(Field.FIELD_NAME_GROUP_ATTR_UPDATERS),
3197           AccessPrivilege.listToPriv(Field.FIELD_NAME_OPTOUTS),
3198           AccessPrivilege.listToPriv(Field.FIELD_NAME_READERS),
3199           AccessPrivilege.listToPriv(Field.FIELD_NAME_VIEWERS),
3200           AccessPrivilege.listToPriv(Field.FIELD_NAME_UPDATERS),
3201           AccessPrivilege.listToPriv(Field.FIELD_NAME_OPTINS)
3202           } ) : (readersUpdaters ? new Privilege[]{AccessPrivilege.listToPriv(Field.FIELD_NAME_READERS),
3203               AccessPrivilege.listToPriv(Field.FIELD_NAME_UPDATERS)
3204           } : new Privilege[]{AccessPrivilege.listToPriv(fieldName)});
3205       
3206       for (Group parentGroup : parentGroups) {
3207         
3208         for (Privilege privilege : privileges) {
3209           if (assign) {
3210             changes += parentGroup.grantPriv(group.toSubject(), privilege, false) ? 1 : 0;
3211           } else {
3212             changes += parentGroup.revokePriv(group.toSubject(), privilege, false) ? 1 : 0;
3213           }
3214         }
3215       }
3216       
3217       if (changes > 0) {
3218         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3219             TextContainer.retrieveFromRequest().getText().get(
3220                 assign ? "groupSuccessGrantedPrivileges" : "groupSuccessRevokedPrivileges")));
3221       } else {
3222         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
3223             TextContainer.retrieveFromRequest().getText().get(
3224                 assign ? "groupNoteNoGrantedPrivileges" : "groupNoteNoRevokedPrivileges")));
3225         
3226       }
3227       guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
3228   
3229       filterThisGroupsGroupPrivilegesHelper(request, response, group);
3230   
3231       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
3232           loggedInSubject, group);
3233 
3234     } finally {
3235       GrouperSession.stopQuietly(grouperSession);
3236     }
3237   
3238   }
3239 
3240   /**
3241    * the filter button for this groups stem privileges was pressed, or paging or sorting or something
3242    * @param request
3243    * @param response
3244    */
3245   public void filterThisGroupsStemPrivileges(HttpServletRequest request, HttpServletResponse response) {
3246     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3247     
3248     GrouperSession grouperSession = null;
3249     
3250     try {
3251       grouperSession = GrouperSession.start(loggedInSubject);
3252   
3253   
3254       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3255       
3256       if (group == null) {
3257         return;
3258       }
3259   
3260       filterThisGroupsStemPrivilegesHelper(request, response, group);
3261   
3262     } finally {
3263       GrouperSession.stopQuietly(grouperSession);
3264     }
3265   
3266   }
3267 
3268   /**
3269    * the filter button was pressed of this groups stem privileges screen, 
3270    * or paging or sorting, or view Group or something
3271    * @param request
3272    * @param response
3273    * @param group 
3274    */
3275   private void filterThisGroupsStemPrivilegesHelper(HttpServletRequest request, HttpServletResponse response, Group group) {
3276   
3277     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
3278   
3279     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3280   
3281     //if filtering text in subjects
3282     String privilegeFilterText = request.getParameter("privilegeFilterText");
3283     
3284     String privilegeFieldName = request.getParameter("privilegeField");
3285     
3286     Field privilegeField = null;
3287     if (!StringUtils.isBlank(privilegeFieldName)) {
3288       privilegeField = FieldFinder.find(privilegeFieldName, true);
3289     }
3290     
3291     //if filtering by subjects that have a certain type
3292     String membershipTypeString = request.getParameter("privilegeMembershipType");
3293     MembershipType membershipType = null;
3294     if (!StringUtils.isBlank(membershipTypeString)) {
3295       membershipType = MembershipType.valueOfIgnoreCase(membershipTypeString, true);
3296     }
3297     
3298     GuiPaging guiPaging = grouperRequestContainer.getGroupContainer().getPrivilegeGuiPaging();
3299     QueryOptions queryOptions = new QueryOptions();
3300     GrouperPagingTag2.processRequest(request, guiPaging, queryOptions); 
3301       
3302     MembershipFinder membershipFinder = new MembershipFinder()
3303       .addSubject(group.toSubject()).assignCheckSecurity(true)
3304       .assignFieldType(FieldType.NAMING)
3305       .assignEnabled(true)
3306       .assignHasFieldForStem(true)
3307       .assignHasMembershipTypeForStem(true)
3308       .assignQueryOptionsForStem(queryOptions)
3309       .assignSplitScopeForStem(true);
3310     
3311     if (membershipType != null) {
3312       membershipFinder.assignMembershipType(membershipType);
3313     }
3314   
3315     if (privilegeField != null) {
3316       membershipFinder.assignField(privilegeField);
3317       membershipFinder.assignIncludeInheritedPrivileges(true);
3318     }
3319   
3320     if (!StringUtils.isBlank(privilegeFilterText)) {
3321       membershipFinder.assignScopeForStem(privilegeFilterText);
3322     }
3323   
3324     //set of subjects, and what privs each subject has
3325     Set<MembershipSubjectContainer> results = membershipFinder
3326         .findMembershipResult().getMembershipSubjectContainers();
3327   
3328     //inherit from grouperAll or Groupersystem or privilege inheritance
3329     MembershipSubjectContainer.considerNamingPrivilegeInheritance(results);
3330   
3331     grouperRequestContainer.getGroupContainer().setPrivilegeGuiMembershipSubjectContainers(
3332         GuiMembershipSubjectContainer.convertFromMembershipSubjectContainers(results));
3333   
3334     guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
3335   
3336     guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#thisGroupsStemPrivilegesFilterResultsId", 
3337         "/WEB-INF/grouperUi2/group/thisGroupsStemPrivilegesContents.jsp"));
3338   
3339   }
3340 
3341   /**
3342    * this groups stem privileges
3343    * @param request
3344    * @param response
3345    */
3346   public void thisGroupsStemPrivileges(HttpServletRequest request, HttpServletResponse response) {
3347     
3348     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3349     
3350     GrouperSession grouperSession = null;
3351   
3352     Group group = null;
3353   
3354     try {
3355   
3356       grouperSession = GrouperSession.start(loggedInSubject);
3357   
3358       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3359       
3360       if (group == null) {
3361         return;
3362       }
3363   
3364       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3365   
3366       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
3367           "/WEB-INF/grouperUi2/group/thisGroupsStemPrivileges.jsp"));
3368       filterThisGroupsStemPrivilegesHelper(request, response, group);
3369   
3370     } finally {
3371       GrouperSession.stopQuietly(grouperSession);
3372     }
3373   }
3374 
3375   /**
3376    * assign or remove a privilege from a stem, on this groups privileges
3377    * @param request
3378    * @param response
3379    */
3380   public void thisGroupsPrivilegesAssignStemPrivilege(HttpServletRequest request, HttpServletResponse response) {
3381     
3382     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3383   
3384     GrouperSession grouperSession = null;
3385     
3386     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3387   
3388     try {
3389       grouperSession = GrouperSession.start(loggedInSubject);
3390   
3391       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3392   
3393       if (group == null) {
3394         return;
3395       }
3396   
3397       //?assign=false&groupId=${grouperRequestContainer.groupContainer.guiGroup.stem.id}&fieldName=${fieldName}&memberId=${guiMembershipSubjectContainer.guiMember.member.uuid}
3398       String assignString = request.getParameter("assign");
3399       boolean assign = GrouperUtil.booleanValue(assignString);
3400       String fieldName = request.getParameter("fieldName");
3401       String parentStemId = request.getParameter("parentStemId");
3402   
3403       Stem parentStem = StemFinder.findByUuid(grouperSession, parentStemId, false);
3404       
3405       if (parentStem == null || !parentStem.canHavePrivilege(loggedInSubject, NamingPrivilege.STEM_ADMIN.getName(), false)) {
3406         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3407             TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToAdminAnotherStem")));
3408         filterThisGroupsGroupPrivilegesHelper(request, response, group);
3409         return;
3410       }
3411       
3412       Privilege privilege = NamingPrivilege.listToPriv(fieldName);
3413       
3414       if (privilege == null) {
3415         throw new RuntimeException("Why is privilege not found???? " + fieldName);
3416       }
3417       
3418       //if someone revoked in the meantime, who cares...
3419       if (assign) {
3420         parentStem.grantPriv(group.toSubject(), privilege, false);
3421         
3422         //set a success message
3423         //messes up screen
3424         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3425         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessGrantedPrivilege")));
3426         
3427       } else {
3428         parentStem.revokePriv(group.toSubject(), privilege, false);
3429         
3430         //messes up screen
3431         //set a success message
3432         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3433         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessRevokedPrivilege")));
3434       }
3435   
3436       filterThisGroupsStemPrivilegesHelper(request, response, group);
3437   
3438       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
3439           loggedInSubject, group);
3440 
3441     } catch (RuntimeException re) {
3442       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
3443         return;
3444       }
3445       throw re;
3446     } finally {
3447       GrouperSession.stopQuietly(grouperSession);
3448     }
3449   
3450   }
3451 
3452   /**
3453    * submit the main form on the this groups stem privilege screen which can do batch operations on a number of rows
3454    * @param request
3455    * @param response
3456    */
3457   public void thisGroupsPrivilegesAssignStemPrivilegeBatch(HttpServletRequest request, HttpServletResponse response) {
3458   
3459     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3460   
3461     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3462   
3463     GrouperSession grouperSession = null;
3464     
3465     try {
3466       grouperSession = GrouperSession.start(loggedInSubject);
3467   
3468       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3469   
3470       if (group == null) {
3471         return;
3472       }
3473         
3474       String groupPrivilegeBatchUpdateOperation = request.getParameter("groupPrivilegeBatchUpdateOperation");
3475       Pattern operationPattern = Pattern.compile("^(assign|revoke)_(.*)$");
3476       Matcher operationMatcher = operationPattern.matcher(groupPrivilegeBatchUpdateOperation);
3477       if (!operationMatcher.matches()) {
3478         throw new RuntimeException("Invalid submission, should have a valid operation: '" + groupPrivilegeBatchUpdateOperation + "'");
3479       }
3480       
3481       String assignOrRevokeString = operationMatcher.group(1);
3482       boolean assign = StringUtils.equals("assign", assignOrRevokeString);
3483       if (!assign && !StringUtils.equals("revoke", assignOrRevokeString)) {
3484         throw new RuntimeException("Cant find assign or revoke: '" + assignOrRevokeString + "'");
3485       }
3486       String fieldName = operationMatcher.group(2);
3487       
3488       boolean assignAll = StringUtils.equals(fieldName, "all");
3489       
3490       //lets see how many are on a page
3491       int pageSize = GrouperPagingTag2.pageSize(request);
3492       
3493       //lets loop and get all the checkboxes
3494       Set<Stem> parentStems = new LinkedHashSet<Stem>();
3495       
3496       //loop through all the checkboxes and collect all the groups
3497       for (int i=0;i<pageSize;i++) {
3498         String parentStemId = request.getParameter("privilegeSubjectRow_" + i + "[]");
3499         if (!StringUtils.isBlank(parentStemId)) {
3500           
3501           Stem parentStem = StemFinder.findByUuid(grouperSession, parentStemId, false);
3502           
3503           if (parentStem != null && parentStem.canHavePrivilege(loggedInSubject, NamingPrivilege.STEM_ADMIN.getName(), false)) {
3504             parentStems.add(parentStem);
3505           }
3506         }
3507       }
3508   
3509       if (GrouperUtil.length(parentStems) == 0) {
3510   
3511         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
3512             TextContainer.retrieveFromRequest().getText().get("thisGroupsPrivilegesErrorStemRequired")));
3513         guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
3514         filterThisGroupsStemPrivilegesHelper(request, response, group);
3515         return;
3516       }
3517       
3518       int changes = 0;
3519       
3520       Privilege[] privileges = assignAll ? (assign ? new Privilege[]{  
3521           NamingPrivilege.listToPriv(Field.FIELD_NAME_STEM_ADMINS)} : new Privilege[]{  
3522             NamingPrivilege.listToPriv(Field.FIELD_NAME_STEM_ADMINS),
3523             NamingPrivilege.listToPriv(Field.FIELD_NAME_CREATORS),
3524             NamingPrivilege.listToPriv(Field.FIELD_NAME_STEM_ATTR_READERS),
3525             NamingPrivilege.listToPriv(Field.FIELD_NAME_STEM_ATTR_UPDATERS)
3526           } ) : new Privilege[]{NamingPrivilege.listToPriv(fieldName)};
3527       
3528       for (Stem parentStem : parentStems) {
3529         
3530         for (Privilege privilege : privileges) {
3531           if (assign) {
3532             changes += parentStem.grantPriv(group.toSubject(), privilege, false) ? 1 : 0;
3533           } else {
3534             changes += parentStem.revokePriv(group.toSubject(), privilege, false) ? 1 : 0;
3535           }
3536         }
3537       }
3538       
3539       if (changes > 0) {
3540         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3541             TextContainer.retrieveFromRequest().getText().get(
3542                 assign ? "groupSuccessGrantedPrivileges" : "groupSuccessRevokedPrivileges")));
3543       } else {
3544         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
3545             TextContainer.retrieveFromRequest().getText().get(
3546                 assign ? "groupNoteNoGrantedPrivileges" : "groupNoteNoRevokedPrivileges")));
3547         
3548       }
3549       guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
3550   
3551       filterThisGroupsStemPrivilegesHelper(request, response, group);
3552   
3553       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
3554           loggedInSubject, group);
3555 
3556     } catch (RuntimeException re) {
3557       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
3558         return;
3559       }
3560       throw re;
3561     } finally {
3562       GrouperSession.stopQuietly(grouperSession);
3563     }
3564   
3565   }
3566 
3567   /**
3568    * the filter button for this groups attribute def privileges was pressed, or paging or sorting or something
3569    * @param request
3570    * @param response
3571    */
3572   public void filterThisGroupsAttributeDefPrivileges(HttpServletRequest request, HttpServletResponse response) {
3573     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3574     
3575     GrouperSession grouperSession = null;
3576     
3577     try {
3578       grouperSession = GrouperSession.start(loggedInSubject);
3579   
3580   
3581       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3582       
3583       if (group == null) {
3584         return;
3585       }
3586   
3587       filterThisGroupsAttributeDefPrivilegesHelper(request, response, group);
3588   
3589     } finally {
3590       GrouperSession.stopQuietly(grouperSession);
3591     }
3592   
3593   }
3594 
3595   /**
3596    * the filter button was pressed of this groups attributeDef privileges screen, 
3597    * or paging or sorting
3598    * @param request
3599    * @param response
3600    * @param group 
3601    */
3602   private void filterThisGroupsAttributeDefPrivilegesHelper(HttpServletRequest request, HttpServletResponse response, Group group) {
3603   
3604     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
3605   
3606     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3607   
3608     //if filtering text in subjects
3609     String privilegeFilterText = request.getParameter("privilegeFilterText");
3610     
3611     String privilegeFieldName = request.getParameter("privilegeField");
3612     
3613     Field privilegeField = null;
3614     if (!StringUtils.isBlank(privilegeFieldName)) {
3615       privilegeField = FieldFinder.find(privilegeFieldName, true);
3616     }
3617     
3618     //if filtering by subjects that have a certain type
3619     String membershipTypeString = request.getParameter("privilegeMembershipType");
3620     MembershipType membershipType = null;
3621     if (!StringUtils.isBlank(membershipTypeString)) {
3622       membershipType = MembershipType.valueOfIgnoreCase(membershipTypeString, true);
3623     }
3624     
3625     GuiPaging guiPaging = grouperRequestContainer.getGroupContainer().getPrivilegeGuiPaging();
3626     QueryOptions queryOptions = new QueryOptions();
3627 
3628     GrouperPagingTag2.processRequest(request, guiPaging, queryOptions); 
3629     
3630     MembershipFinder membershipFinder = new MembershipFinder()
3631       .addSubject(group.toSubject()).assignCheckSecurity(true)
3632       .assignFieldType(FieldType.ATTRIBUTE_DEF)
3633       .assignEnabled(true)
3634       .assignHasFieldForAttributeDef(true)
3635       .assignHasMembershipTypeForAttributeDef(true)
3636       .assignQueryOptionsForAttributeDef(queryOptions)
3637       .assignSplitScopeForAttributeDef(true);
3638     
3639     if (membershipType != null) {
3640       membershipFinder.assignMembershipType(membershipType);
3641     }
3642   
3643     if (privilegeField != null) {
3644       membershipFinder.assignField(privilegeField);
3645       membershipFinder.assignIncludeInheritedPrivileges(true);
3646     }
3647   
3648     if (!StringUtils.isBlank(privilegeFilterText)) {
3649       membershipFinder.assignScopeForAttributeDef(privilegeFilterText);
3650     }
3651   
3652     //set of subjects, and what privs each subject has
3653     Set<MembershipSubjectContainer> results = membershipFinder
3654         .findMembershipResult().getMembershipSubjectContainers();
3655   
3656     //inherit from grouperAll or Groupersystem or privilege inheritance
3657     MembershipSubjectContainer.considerAttributeDefPrivilegeInheritance(results);
3658   
3659     grouperRequestContainer.getGroupContainer().setPrivilegeGuiMembershipSubjectContainers(
3660         GuiMembershipSubjectContainer.convertFromMembershipSubjectContainers(results));
3661   
3662     guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
3663   
3664     guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#thisGroupsAttributeDefPrivilegesFilterResultsId", 
3665         "/WEB-INF/grouperUi2/group/thisGroupsAttributeDefPrivilegesContents.jsp"));
3666   
3667   }
3668 
3669   /**
3670    * assign or remove a privilege from a group, on this groups privileges
3671    * @param request
3672    * @param response
3673    */
3674   public void thisGroupsPrivilegesAssignAttributeDefPrivilege(HttpServletRequest request, HttpServletResponse response) {
3675     
3676     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3677   
3678     GrouperSession grouperSession = null;
3679     
3680     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3681   
3682     try {
3683       grouperSession = GrouperSession.start(loggedInSubject);
3684   
3685       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3686   
3687       if (group == null) {
3688         return;
3689       }
3690   
3691       //?assign=false&groupId=${grouperRequestContainer.groupContainer.guiGroup.stem.id}&fieldName=${fieldName}&memberId=${guiMembershipSubjectContainer.guiMember.member.uuid}
3692       String assignString = request.getParameter("assign");
3693       boolean assign = GrouperUtil.booleanValue(assignString);
3694       String fieldName = request.getParameter("fieldName");
3695       String parentAttributeDefId = request.getParameter("parentAttributeDefId");
3696   
3697       AttributeDef parentAttributeDef = AttributeDefFinder.findById(parentAttributeDefId, false);
3698       
3699       if (parentAttributeDef == null || !parentAttributeDef.getPrivilegeDelegate().canHavePrivilege(loggedInSubject, 
3700           AttributeDefPrivilege.ATTR_ADMIN.getName(), false)) {
3701         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3702             TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToAdminAnotherAttributeDef")));
3703         filterThisGroupsAttributeDefPrivilegesHelper(request, response, group);
3704         return;
3705       }
3706       
3707       Privilege privilege = AttributeDefPrivilege.listToPriv(fieldName);
3708       
3709       if (privilege == null) {
3710         throw new RuntimeException("Why is privilege not found???? " + fieldName);
3711       }
3712       
3713       //if someone revoked in the meantime, who cares...
3714       if (assign) {
3715         parentAttributeDef.getPrivilegeDelegate().grantPriv(group.toSubject(), privilege, false);
3716         
3717         //set a success message
3718         //messes up screen
3719         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3720         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessGrantedPrivilege")));
3721         
3722       } else {
3723         parentAttributeDef.getPrivilegeDelegate().revokePriv(group.toSubject(), privilege, false);
3724         
3725         //messes up screen
3726         //set a success message
3727         //guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3728         //    TextContainer.retrieveFromRequest().getText().get("stemSuccessRevokedPrivilege")));
3729       }
3730   
3731       filterThisGroupsAttributeDefPrivilegesHelper(request, response, group);
3732   
3733       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
3734           loggedInSubject, group);
3735 
3736     } catch (RuntimeException re) {
3737       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
3738         return;
3739       }
3740       throw re;
3741     } finally {
3742       GrouperSession.stopQuietly(grouperSession);
3743     }
3744   
3745   
3746   }
3747 
3748   /**
3749    * submit the main form on the this groups privilege screen which can do batch operations on a number of rows
3750    * @param request
3751    * @param response
3752    */
3753   public void thisGroupsPrivilegesAssignAttributeDefPrivilegeBatch(HttpServletRequest request, HttpServletResponse response) {
3754   
3755     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3756   
3757     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3758   
3759     GrouperSession grouperSession = null;
3760     
3761     try {
3762       grouperSession = GrouperSession.start(loggedInSubject);
3763   
3764       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3765   
3766       if (group == null) {
3767         return;
3768       }
3769         
3770       String groupPrivilegeBatchUpdateOperation = request.getParameter("groupPrivilegeBatchUpdateOperation");
3771       Pattern operationPattern = Pattern.compile("^(assign|revoke)_(.*)$");
3772       Matcher operationMatcher = operationPattern.matcher(groupPrivilegeBatchUpdateOperation);
3773       if (!operationMatcher.matches()) {
3774         throw new RuntimeException("Invalid submission, should have a valid operation: '" + groupPrivilegeBatchUpdateOperation + "'");
3775       }
3776       
3777       String assignOrRevokeString = operationMatcher.group(1);
3778       boolean assign = StringUtils.equals("assign", assignOrRevokeString);
3779       if (!assign && !StringUtils.equals("revoke", assignOrRevokeString)) {
3780         throw new RuntimeException("Cant find assign or revoke: '" + assignOrRevokeString + "'");
3781       }
3782       String fieldName = operationMatcher.group(2);
3783       
3784       boolean assignAll = StringUtils.equals(fieldName, "all");
3785       boolean readersUpdaters = StringUtils.equals(fieldName, "readersUpdaters");
3786       
3787       //lets see how many are on a page
3788       int pageSize = GrouperPagingTag2.pageSize(request);
3789       
3790       //lets loop and get all the checkboxes
3791       Set<AttributeDef> parentAttributeDefs = new LinkedHashSet<AttributeDef>();
3792       
3793       //loop through all the checkboxes and collect all the groups
3794       for (int i=0;i<pageSize;i++) {
3795         String parentAttributeDefId = request.getParameter("privilegeSubjectRow_" + i + "[]");
3796         if (!StringUtils.isBlank(parentAttributeDefId)) {
3797           
3798           AttributeDef parentAttributeDef = AttributeDefFinder.findById(parentAttributeDefId, false);
3799           
3800           if (parentAttributeDef != null && parentAttributeDef.getPrivilegeDelegate().canHavePrivilege(loggedInSubject, AttributeDefPrivilege.ATTR_ADMIN.getName(), false)) {
3801             parentAttributeDefs.add(parentAttributeDef);
3802           }
3803         }
3804       }
3805   
3806       if (GrouperUtil.length(parentAttributeDefs) == 0) {
3807   
3808         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
3809             TextContainer.retrieveFromRequest().getText().get("thisGroupsPrivilegesErrorAttributeDefRequired")));
3810         guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
3811         filterThisGroupsAttributeDefPrivilegesHelper(request, response, group);
3812         return;
3813       }
3814       
3815       int changes = 0;
3816       
3817       Privilege[] privileges = assignAll ? (assign ? new Privilege[]{  
3818           AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_ADMINS)} : new Privilege[]{  
3819             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_ADMINS),
3820             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_DEF_ATTR_READERS),
3821             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_DEF_ATTR_UPDATERS),
3822             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_OPTOUTS),
3823             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_READERS),
3824             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_VIEWERS),
3825             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_UPDATERS),
3826             AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_OPTINS)
3827           } ) : (readersUpdaters ? new Privilege[]{AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_READERS),
3828               AttributeDefPrivilege.listToPriv(Field.FIELD_NAME_ATTR_UPDATERS)
3829           } : new Privilege[]{AttributeDefPrivilege.listToPriv(fieldName)});
3830       
3831       for (AttributeDef parentAttributeDef : parentAttributeDefs) {
3832         
3833         for (Privilege privilege : privileges) {
3834           if (assign) {
3835             changes += parentAttributeDef.getPrivilegeDelegate().grantPriv(group.toSubject(), privilege, false) ? 1 : 0;
3836           } else {
3837             changes += parentAttributeDef.getPrivilegeDelegate().revokePriv(group.toSubject(), privilege, false) ? 1 : 0;
3838           }
3839         }
3840       }
3841       
3842       if (changes > 0) {
3843         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
3844             TextContainer.retrieveFromRequest().getText().get(
3845                 assign ? "groupSuccessGrantedPrivileges" : "groupSuccessRevokedPrivileges")));
3846       } else {
3847         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
3848             TextContainer.retrieveFromRequest().getText().get(
3849                 assign ? "groupNoteNoGrantedPrivileges" : "groupNoteNoRevokedPrivileges")));
3850         
3851       }
3852       guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
3853   
3854       filterThisGroupsAttributeDefPrivilegesHelper(request, response, group);
3855   
3856       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
3857           loggedInSubject, group);
3858 
3859     } finally {
3860       GrouperSession.stopQuietly(grouperSession);
3861     }
3862   
3863   }
3864 
3865   /**
3866    * this groups attributeDef privileges
3867    * @param request
3868    * @param response
3869    */
3870   public void thisGroupsAttributeDefPrivileges(HttpServletRequest request, HttpServletResponse response) {
3871     
3872     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3873     
3874     GrouperSession grouperSession = null;
3875   
3876     Group group = null;
3877   
3878     try {
3879   
3880       grouperSession = GrouperSession.start(loggedInSubject);
3881   
3882       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
3883       
3884       if (group == null) {
3885         return;
3886       }
3887   
3888       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
3889   
3890       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
3891           "/WEB-INF/grouperUi2/group/thisGroupsAttributeDefPrivileges.jsp"));
3892       filterThisGroupsAttributeDefPrivilegesHelper(request, response, group);
3893   
3894     } finally {
3895       GrouperSession.stopQuietly(grouperSession);
3896     }
3897   }
3898 
3899   /**
3900    * combo filter create group folder.  Note, this cannot be composite (since you cant
3901    * add members to a composite)
3902    * @param request
3903    * @param response
3904    */
3905   public void groupUpdateFilter(final HttpServletRequest request, HttpServletResponse response) {
3906   
3907     //run the combo logic
3908     DojoComboLogic.logic(request, response, new DojoComboQueryLogicBase<Group>() {
3909   
3910       /**
3911        * 
3912        */
3913       @Override
3914       public Group lookup(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
3915         Subject loggedInSubject = grouperSession.getSubject();
3916         GroupFinder groupFinder = new GroupFinder().assignPrivileges(AccessPrivilege.UPDATE_PRIVILEGES)
3917             .assignSubject(loggedInSubject).assignCompositeOwner(false)
3918             .assignFindByUuidOrName(true).assignScope(query);
3919         
3920         String typeOfGroup = localRequest.getParameter("typeOfGroup");
3921         if (StringUtils.isNotBlank(typeOfGroup)) {
3922           TypeOfGroup groupType = TypeOfGroup.valueOfIgnoreCase(typeOfGroup, true);
3923           groupFinder.addTypeOfGroup(groupType);
3924         }
3925         
3926         return groupFinder.findGroup();
3927       }
3928   
3929       /**
3930        * 
3931        */
3932       @Override
3933       public Collection<Group> search(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
3934         Subject loggedInSubject = grouperSession.getSubject();
3935         
3936         int groupComboSize = GrouperUiConfig.retrieveConfig().propertyValueInt("uiV2.groupComboboxResultSize", 200);
3937         QueryOptions queryOptions = QueryOptions.create(null, null, 1, groupComboSize);
3938         GroupFinder groupFinder = new GroupFinder().assignPrivileges(AccessPrivilege.UPDATE_PRIVILEGES)
3939             .assignScope(query).assignSubject(loggedInSubject).assignCompositeOwner(false)
3940             .assignSplitScope(true).assignQueryOptions(queryOptions);
3941         
3942         String typeOfGroup = localRequest.getParameter("typeOfGroup");
3943         if (StringUtils.isNotBlank(typeOfGroup)) {
3944           TypeOfGroup groupType = TypeOfGroup.valueOfIgnoreCase(typeOfGroup, true);
3945           Set<TypeOfGroup> typesOfGroup = new HashSet<TypeOfGroup>();
3946           typesOfGroup.add(groupType);
3947           groupFinder.assignTypeOfGroups(typesOfGroup);
3948         }
3949         
3950         return groupFinder.findGroups();
3951         
3952       }
3953   
3954       /**
3955        * 
3956        * @param t
3957        * @return id
3958        */
3959       @Override
3960       public String retrieveId(GrouperSession grouperSession, Group t) {
3961         return t.getId();
3962       }
3963       
3964       /**
3965        * 
3966        */
3967       @Override
3968       public String retrieveLabel(GrouperSession grouperSession, Group t) {
3969         return t.getDisplayName();
3970       }
3971   
3972       /**
3973        * 
3974        */
3975       @Override
3976       public String retrieveHtmlLabel(GrouperSession grouperSession, Group t) {
3977         //description could be null?
3978         String label = GrouperUiUtils.escapeHtml(t.getDisplayName(), true);
3979         String htmlLabel = "<img src=\"../../grouperExternal/public/assets/images/group.gif\" /> " + label;
3980         return htmlLabel;
3981       }
3982   
3983     });
3984     
3985   }
3986 
3987   /**
3988    * filter audits for group
3989    * @param request
3990    * @param response
3991    */
3992   public void viewAuditsFilter(HttpServletRequest request, HttpServletResponse response) {
3993     
3994     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
3995     
3996     GrouperSession grouperSession = null;
3997   
3998     Group group = null;
3999   
4000     try {
4001   
4002       grouperSession = GrouperSession.start(loggedInSubject);
4003   
4004       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
4005       
4006       if (group == null) {
4007         return;
4008       }
4009   
4010       viewAuditsHelper(request, response, group);
4011   
4012     } finally {
4013       GrouperSession.stopQuietly(grouperSession);
4014     }
4015   }
4016 
4017   /**
4018    * the audit filter button was pressed, or paging or sorting, or view audits or something
4019    * @param request
4020    * @param response
4021    * @param group 
4022    */
4023   private void viewAuditsHelper(HttpServletRequest request, HttpServletResponse response, Group group) {
4024     
4025     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
4026     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4027 
4028     //all, on, before, between, or since
4029     String filterTypeString = request.getParameter("filterType");
4030   
4031     if (StringUtils.isBlank(filterTypeString)) {
4032       filterTypeString = "all";
4033     }
4034     
4035     String filterFromDateString = request.getParameter("filterFromDate");
4036     String filterToDateString = request.getParameter("filterToDate");
4037 
4038     //massage dates
4039     if (StringUtils.equals(filterTypeString, "all")) {
4040       guiResponseJs.addAction(GuiScreenAction.newFormFieldValue("filterFromDate", ""));
4041       filterFromDateString = null;
4042       guiResponseJs.addAction(GuiScreenAction.newFormFieldValue("filterToDate", ""));
4043       filterToDateString = null;
4044     } else if (StringUtils.equals(filterTypeString, "on")) {
4045 
4046       guiResponseJs.addAction(GuiScreenAction.newFormFieldValue("filterToDate", ""));
4047       filterToDateString = null;
4048     } else if (StringUtils.equals(filterTypeString, "before")) {
4049       guiResponseJs.addAction(GuiScreenAction.newFormFieldValue("filterToDate", ""));
4050       filterToDateString = null;
4051     } else if (StringUtils.equals(filterTypeString, "between")) {
4052     } else if (StringUtils.equals(filterTypeString, "since")) {
4053       guiResponseJs.addAction(GuiScreenAction.newFormFieldValue("filterToDate", ""));
4054       filterToDateString = null;
4055     } else {
4056       //should never happen
4057       throw new RuntimeException("Not expecting filterType string: " + filterTypeString);
4058     }
4059 
4060     Date filterFromDate = null;
4061     Date filterToDate = null;
4062 
4063     if (StringUtils.equals(filterTypeString, "on") || StringUtils.equals(filterTypeString, "before")
4064         || StringUtils.equals(filterTypeString, "between") || StringUtils.equals(filterTypeString, "since")) {
4065       if (StringUtils.isBlank(filterFromDateString)) {
4066         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
4067             "#from-date",
4068             TextContainer.retrieveFromRequest().getText().get("groupAuditLogFilterFromDateRequired")));
4069         return;
4070       }
4071       try {
4072         filterFromDate = GrouperUtil.stringToTimestamp(filterFromDateString);
4073       } catch (Exception e) {
4074         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
4075             "#from-date",
4076             TextContainer.retrieveFromRequest().getText().get("groupAuditLogFilterFromDateInvalid")));
4077         return;
4078       }
4079     }
4080     if (StringUtils.equals(filterTypeString, "between")) {
4081       if (StringUtils.isBlank(filterToDateString)) {
4082         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
4083             "#to-date",
4084             TextContainer.retrieveFromRequest().getText().get("groupAuditLogFilterToDateRequired")));
4085         return;
4086       }
4087       try {
4088         filterToDate = GrouperUtil.stringToTimestamp(filterToDateString);
4089       } catch (Exception e) {
4090         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
4091             "#to-date",
4092             TextContainer.retrieveFromRequest().getText().get("groupAuditLogFilterToDateInvalid")));
4093         return;
4094       }
4095     }
4096     
4097     boolean extendedResults = false;
4098 
4099     {
4100       String showExtendedResultsString = request.getParameter("showExtendedResults[]");
4101       if (!StringUtils.isBlank(showExtendedResultsString)) {
4102         extendedResults = GrouperUtil.booleanValue(showExtendedResultsString);
4103       }
4104     }
4105     
4106     GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
4107     
4108     GuiPaging guiPaging = groupContainer.getGuiPaging();
4109     QueryOptions queryOptions = new QueryOptions();
4110   
4111     GrouperPagingTag2.processRequest(request, guiPaging, queryOptions);
4112   
4113     UserAuditQuery query = new UserAuditQuery();
4114 
4115     //process dates
4116     if (StringUtils.equals(filterTypeString, "on")) {
4117 
4118       query.setOnDate(filterFromDate);
4119     } else  if (StringUtils.equals(filterTypeString, "between")) {
4120       query.setFromDate(filterFromDate);
4121       query.setToDate(filterToDate);
4122     } else  if (StringUtils.equals(filterTypeString, "since")) {
4123       query.setFromDate(filterFromDate);
4124     } else  if (StringUtils.equals(filterTypeString, "before")) {
4125       query.setToDate(filterToDate);
4126     }
4127     
4128     query.setQueryOptions(queryOptions);
4129 
4130     queryOptions.sortDesc("lastUpdatedDb");
4131     
4132     GuiSortinger/grouperUi/beans/json/GuiSorting.html#GuiSorting">GuiSorting guiSorting = new GuiSorting(queryOptions.getQuerySort());
4133     groupContainer.setGuiSorting(guiSorting);
4134 
4135     guiSorting.processRequest(request);
4136     
4137     String auditType = request.getParameter("auditType");
4138     Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4139     GrouperSession grouperSession = GrouperSession.startIfNotStarted(loggedInSubject).getGrouperSession();
4140     Subject subj = SubjectFinder.findById(group.getUuid(), true);
4141     Member member = MemberFinder.findBySubject(grouperSession, subj, false);
4142     
4143     if ("membership".equals(auditType)) {
4144       query.addAuditTypeFieldValue("memberId", member.getUuid());
4145     } else if ("actions".equals(auditType)) {
4146       query=query.loggedInMember(member);
4147       query=query.actAsMember(member);
4148     } else if ("privileges".equals(auditType)) {
4149       query=query.addAuditTypeCategory("privilege").addAuditTypeFieldValue("memberId", member.getUuid());
4150     } else {
4151       query.addAuditTypeFieldValue("groupId", group.getId());
4152     }
4153     
4154     groupContainer.setAuditType(auditType);
4155     
4156     List<AuditEntry> auditEntries = query.execute();
4157 
4158     groupContainer.setGuiAuditEntries(GuiAuditEntry.convertFromAuditEntries(auditEntries));
4159 
4160     guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
4161 
4162     if (GrouperUtil.length(auditEntries) == 0) {
4163       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info,
4164           TextContainer.retrieveFromRequest().getText().get("groupAuditLogNoEntriesFound")));
4165     }
4166     
4167     groupContainer.setAuditExtendedResults(extendedResults);
4168     guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupAuditFilterResultsId", 
4169         "/WEB-INF/grouperUi2/group/groupViewAuditsContents.jsp"));
4170   
4171   }
4172 
4173   /**
4174    * remove all members submit
4175    * @param request
4176    * @param response
4177    */
4178   public void groupRemoveAllMembersSubmit(HttpServletRequest request, HttpServletResponse response) {
4179     
4180     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4181   
4182     GrouperSession grouperSession = null;
4183   
4184     Group group = null;
4185   
4186     try {
4187   
4188       grouperSession = GrouperSession.start(loggedInSubject);
4189   
4190       group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
4191     
4192       if (group == null) {
4193         return;
4194       }
4195       
4196       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4197   
4198   
4199       if(group.hasComposite()) {
4200         
4201         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
4202             TextContainer.retrieveFromRequest().getText().get("groupProblemWithComposite")));
4203         return;
4204       }
4205 
4206       Set<Member> members = group.getImmediateMembers();
4207       for (Member member : members) {
4208         group.deleteMember(member);
4209       }
4210       
4211       //go to the view group screen
4212       guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "')"));
4213   
4214       //lets show a success message on the new screen
4215       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
4216           TextContainer.retrieveFromRequest().getText().get("groupRemoveMembersSuccess")));
4217   
4218       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
4219           loggedInSubject, group);
4220 
4221     } catch (RuntimeException re) {
4222       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
4223         return;
4224       }
4225       throw re;
4226     } finally {
4227       GrouperSession.stopQuietly(grouperSession);
4228     }
4229 
4230   }
4231   
4232   /**
4233    * remove all members from a group (show confirm screen)
4234    * @param request
4235    * @param response
4236    */
4237   public void groupRemoveAllMembers(HttpServletRequest request, HttpServletResponse response) {
4238     
4239     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4240     
4241     GrouperSession grouperSession = null;
4242   
4243     Group group = null;
4244   
4245     try {
4246   
4247       grouperSession = GrouperSession.start(loggedInSubject);
4248   
4249       group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
4250       
4251       if (group == null) {
4252         return;
4253       }
4254   
4255       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4256       
4257       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
4258           "/WEB-INF/grouperUi2/group/groupRemoveMembers.jsp"));
4259   
4260     } finally {
4261       GrouperSession.stopQuietly(grouperSession);
4262     }
4263   }
4264 
4265   /**
4266    * modal search form results for left group factor
4267    * @param request
4268    * @param response
4269    */
4270   public void leftGroupFactorSearch(HttpServletRequest request, HttpServletResponse response) {
4271     
4272     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
4273     
4274     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4275     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4276   
4277     GrouperSession grouperSession = null;
4278   
4279     GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
4280     
4281     try {
4282       grouperSession = GrouperSession.start(loggedInSubject);
4283   
4284       String searchString = request.getParameter("leftFactorSearchName");
4285       
4286       boolean searchOk = GrouperUiUtils.searchStringValid(searchString);
4287       if (!searchOk) {
4288         
4289         guiResponseJs.addAction(GuiScreenAction.newInnerHtml("#leftFactorGroupResults", 
4290             TextContainer.retrieveFromRequest().getText().get("groupCompositeNotEnoughChars")));
4291         return;
4292       }
4293 
4294       String matchExactIdString = request.getParameter("matchExactId[]");
4295       boolean matchExactId = GrouperUtil.booleanValue(matchExactIdString, false);
4296 
4297       GuiPaging guiPaging = groupContainer.getGuiPaging();
4298       QueryOptions queryOptions = new QueryOptions();
4299 
4300       GrouperPagingTag2.processRequest(request, guiPaging, queryOptions); 
4301 
4302       Set<Group> groups = null;
4303     
4304     
4305       GroupFinder groupFinder = new GroupFinder().assignPrivileges(AccessPrivilege.READ_PRIVILEGES)
4306         .assignScope(searchString).assignSplitScope(true).assignQueryOptions(queryOptions);
4307       
4308       if (matchExactId) {
4309         groupFinder.assignFindByUuidOrName(true);
4310       }
4311       
4312       groups = groupFinder.findGroups();
4313       
4314       guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
4315       
4316       if (GrouperUtil.length(groups) == 0) {
4317 
4318         guiResponseJs.addAction(GuiScreenAction.newInnerHtml("#leftFactorGroupResults", 
4319             TextContainer.retrieveFromRequest().getText().get("groupCompositeSearchNoGroupsFound")));
4320         return;
4321       }
4322       
4323       Set<GuiGroup> guiGroups = GuiGroup.convertFromGroups(groups);
4324       
4325       groupContainer.setGuiGroups(guiGroups);
4326   
4327       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#leftFactorGroupResults", 
4328           "/WEB-INF/grouperUi2/group/groupCompositeLeftFactorSearchResults.jsp"));
4329       
4330     } finally {
4331       GrouperSession.stopQuietly(grouperSession);
4332     }
4333     
4334   }
4335 
4336   /**
4337    * combobox results for add composite factor filter search
4338    * @param request
4339    * @param response
4340    */
4341   public void groupCompositeFactorFilter(HttpServletRequest request, HttpServletResponse response) {
4342     this.groupReadFilter(request, response);
4343   }
4344   
4345   /**
4346    * edit a group composite, show the edit composite screen
4347    * @param request
4348    * @param response
4349    */
4350   public void groupEditComposite(HttpServletRequest request, HttpServletResponse response) {
4351     
4352     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4353     
4354     GrouperSession grouperSession = null;
4355   
4356     Group group = null;
4357   
4358     try {
4359 
4360       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4361 
4362       grouperSession = GrouperSession.start(loggedInSubject);
4363   
4364       group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
4365       
4366       if (group == null) {
4367         return;
4368       }
4369 
4370       if (!group.canHavePrivilege(loggedInSubject, AccessPrivilege.READ.getName(), false)) {
4371         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
4372             TextContainer.retrieveFromRequest().getText().get("groupNotAllowedToReadGroup")));
4373         return;
4374       }
4375 
4376       if (group.isHasMembers()) {
4377         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
4378             TextContainer.retrieveFromRequest().getText().get("groupCompositeErrorCannotHaveMembers")));
4379         return;
4380       }
4381 
4382       GroupContainer groupContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer();
4383       groupContainer.getGuiGroup().setShowBreadcrumbLink(true);
4384       groupContainer.getGuiGroup().setShowBreadcrumbLinkSeparator(false);
4385       
4386       groupContainer.setCompositeOwnerGuiGroup(groupContainer.getGuiGroup());
4387 
4388       Composite composite = group.getComposite(false);
4389       
4390       if (composite != null) {
4391         
4392         groupContainer.setCompositeLeftFactorGuiGroup(new GuiGroup(composite.getLeftGroup()));
4393         groupContainer.setCompositeRightFactorGuiGroup(new GuiGroup(composite.getRightGroup()));
4394         
4395       }
4396       
4397       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
4398           "/WEB-INF/grouperUi2/group/groupEditComposite.jsp"));
4399   
4400     } finally {
4401       GrouperSession.stopQuietly(grouperSession);
4402     }
4403   }
4404 
4405   /**
4406    * combo filter read group folder
4407    * @param request
4408    * @param response
4409    */
4410   public void groupReadFilter(final HttpServletRequest request, HttpServletResponse response) {
4411   
4412     //run the combo logic
4413     DojoComboLogic.logic(request, response, new DojoComboQueryLogicBase<Group>() {
4414   
4415       /**
4416        * 
4417        */
4418       @Override
4419       public Group lookup(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
4420         Subject loggedInSubject = grouperSession.getSubject();
4421         Group theGroup = new GroupFinder().assignPrivileges(AccessPrivilege.READ_PRIVILEGES)
4422             .assignSubject(loggedInSubject)
4423             .assignFindByUuidOrName(true).assignScope(query).findGroup();
4424         return theGroup;
4425       }
4426   
4427       /**
4428        * 
4429        */
4430       @Override
4431       public Collection<Group> search(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
4432         Subject loggedInSubject = grouperSession.getSubject();
4433         int groupComboSize = GrouperUiConfig.retrieveConfig().propertyValueInt("uiV2.groupComboboxResultSize", 200);
4434         QueryOptions queryOptions = QueryOptions.create(null, null, 1, groupComboSize);
4435         return new GroupFinder().assignPrivileges(AccessPrivilege.READ_PRIVILEGES)
4436             .assignScope(query).assignSubject(loggedInSubject)
4437             .assignSplitScope(true).assignQueryOptions(queryOptions).findGroups();
4438       }
4439   
4440       /**
4441        * 
4442        * @param t
4443        * @return id
4444        */
4445       @Override
4446       public String retrieveId(GrouperSession grouperSession, Group t) {
4447         return t.getId();
4448       }
4449       
4450       /**
4451        * 
4452        */
4453       @Override
4454       public String retrieveLabel(GrouperSession grouperSession, Group t) {
4455         return t.getDisplayName();
4456       }
4457   
4458       /**
4459        * 
4460        */
4461       @Override
4462       public String retrieveHtmlLabel(GrouperSession grouperSession, Group t) {
4463         //description could be null?
4464         String label = GrouperUiUtils.escapeHtml(t.getDisplayName(), true);
4465         String htmlLabel = "<img src=\"../../grouperExternal/public/assets/images/group.gif\" /> " + label;
4466         return htmlLabel;
4467       }
4468   
4469     });
4470     
4471   }
4472 
4473   /**
4474    * modal search form results for right group factor
4475    * @param request
4476    * @param response
4477    */
4478   public void rightGroupFactorSearch(HttpServletRequest request, HttpServletResponse response) {
4479     
4480     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
4481     
4482     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4483     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4484   
4485     GrouperSession grouperSession = null;
4486   
4487     GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
4488     
4489     try {
4490       grouperSession = GrouperSession.start(loggedInSubject);
4491   
4492       String searchString = request.getParameter("rightFactorSearchName");
4493       
4494       boolean searchOk = GrouperUiUtils.searchStringValid(searchString);
4495       if (!searchOk) {
4496         
4497         guiResponseJs.addAction(GuiScreenAction.newInnerHtml("#rightFactorGroupResults", 
4498             TextContainer.retrieveFromRequest().getText().get("groupCompositeNotEnoughChars")));
4499         return;
4500       }
4501   
4502       String matchExactIdString = request.getParameter("matchExactId[]");
4503       boolean matchExactId = GrouperUtil.booleanValue(matchExactIdString, false);
4504   
4505       GuiPaging guiPaging = groupContainer.getGuiPaging();
4506       QueryOptions queryOptions = new QueryOptions();
4507   
4508       GrouperPagingTag2.processRequest(request, guiPaging, queryOptions); 
4509   
4510       Set<Group> groups = null;
4511     
4512     
4513       GroupFinder groupFinder = new GroupFinder().assignPrivileges(AccessPrivilege.READ_PRIVILEGES)
4514         .assignScope(searchString).assignSplitScope(true).assignQueryOptions(queryOptions);
4515       
4516       if (matchExactId) {
4517         groupFinder.assignFindByUuidOrName(true);
4518       }
4519       
4520       groups = groupFinder.findGroups();
4521       
4522       guiPaging.setTotalRecordCount(queryOptions.getQueryPaging().getTotalRecordCount());
4523       
4524       if (GrouperUtil.length(groups) == 0) {
4525   
4526         guiResponseJs.addAction(GuiScreenAction.newInnerHtml("#rightFactorGroupResults", 
4527             TextContainer.retrieveFromRequest().getText().get("groupCompositeSearchNoGroupsFound")));
4528         return;
4529       }
4530       
4531       Set<GuiGroup> guiGroups = GuiGroup.convertFromGroups(groups);
4532       
4533       groupContainer.setGuiGroups(guiGroups);
4534   
4535       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#rightFactorGroupResults", 
4536           "/WEB-INF/grouperUi2/group/groupCompositeRightFactorSearchResults.jsp"));
4537       
4538     } finally {
4539       GrouperSession.stopQuietly(grouperSession);
4540     }
4541     
4542   }
4543 
4544   /**
4545    * edit group composite submit
4546    * @param request
4547    * @param response
4548    */
4549   public void groupEditCompositeSubmit(HttpServletRequest request, HttpServletResponse response) {
4550     
4551     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4552   
4553     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4554   
4555     GrouperSession grouperSession = null;
4556   
4557     Group group = null;
4558   
4559     try {
4560   
4561       grouperSession = GrouperSession.start(loggedInSubject);
4562   
4563       group = retrieveGroupHelper(request, AccessPrivilege.UPDATE).getGroup();
4564       
4565       if (group == null) {
4566         return;
4567       }
4568   
4569       //see if composite, should submit true or false
4570       boolean userSelectedComposite = GrouperUtil.booleanValue(request.getParameter("groupComposite[]"));
4571       
4572       if (!userSelectedComposite) {
4573         
4574         if (!group.isHasComposite()) {
4575 
4576           guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
4577               TextContainer.retrieveFromRequest().getText().get("groupCompositeNoteNoChangesMade")));
4578           return;
4579           
4580         }
4581         
4582         //we need to remove the composite
4583         group.deleteCompositeMember();
4584 
4585         //go back to view group
4586         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "');"));
4587 
4588         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
4589             TextContainer.retrieveFromRequest().getText().get("groupCompositeSuccessRemovedComposite")));
4590 
4591 
4592         return;
4593       }
4594 
4595       //this should never happen unless race condition
4596       if (group.isHasMembers()) {
4597         //go back to view group
4598         guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "');"));
4599 
4600         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error, 
4601             TextContainer.retrieveFromRequest().getText().get("groupCompositeErrorCannotHaveMembers")));
4602         
4603       }
4604       
4605       Composite composite = group.getComposite(false);
4606 
4607       // Get left group and validate
4608       String leftFactorGroupId = request.getParameter("groupCompositeLeftFactorComboName");
4609       
4610       Group leftFactorGroup = StringUtils.isBlank(leftFactorGroupId) ? null : new GroupFinder()
4611           .assignScope(leftFactorGroupId).assignPrivileges(AccessPrivilege.READ_PRIVILEGES)
4612           .assignFindByUuidOrName(true).assignSubject(loggedInSubject).findGroup();
4613       
4614       if (leftFactorGroup == null) {
4615         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
4616           "#groupCompositeLeftFactorComboErrorId",
4617           TextContainer.retrieveFromRequest().getText().get("groupCompositeErrorLeftGroupProblem")));
4618         return;
4619         
4620         
4621       }
4622       
4623       // get operation and validate
4624       String compositeTypeString = request.getParameter("compositeOperation");
4625       CompositeType compositeType = StringUtils.isBlank(compositeTypeString) ? null : CompositeType.valueOfIgnoreCase(compositeTypeString);
4626 
4627       //we dont allow new groups to have union, or switch to union.  shouldnt be possible unles someone is hacking...
4628       if (compositeType != null && compositeType == CompositeType.UNION) {
4629         if (composite == null || composite.getType() != CompositeType.UNION) {
4630           compositeType = null;
4631         }
4632       }
4633       
4634       if (compositeType == null) {
4635         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
4636             "#compositeOperationId",
4637             TextContainer.retrieveFromRequest().getText().get("groupCompositeErrorOperationRequired")));
4638           return;
4639       }
4640 
4641       // get right group and validate
4642       String rightFactorGroupId = request.getParameter("groupCompositeRightFactorComboName");
4643       
4644       Group rightFactorGroup = StringUtils.isBlank(rightFactorGroupId) ? null : new GroupFinder()
4645           .assignScope(rightFactorGroupId).assignPrivileges(AccessPrivilege.READ_PRIVILEGES)
4646           .assignFindByUuidOrName(true).assignSubject(loggedInSubject).findGroup();
4647       
4648       if (rightFactorGroup == null) {
4649         guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error, 
4650           "#groupCompositeRightFactorComboErrorId",
4651           TextContainer.retrieveFromRequest().getText().get("groupCompositeErrorRightGroupProblem")));
4652         return;
4653       }
4654 
4655       //lets see if no changes
4656       if (composite != null && StringUtils.equals(composite.getLeftFactorUuid(), leftFactorGroup.getId())
4657           && composite.getType() == compositeType && StringUtils.equals(composite.getRightFactorUuid(), rightFactorGroup.getId())) {
4658         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info, 
4659             TextContainer.retrieveFromRequest().getText().get("groupCompositeNoteNoChangesMade")));
4660         return;
4661         
4662       }
4663 
4664       //to edit a composite, delete and add
4665       if (composite != null) {
4666         group.deleteCompositeMember();
4667       }
4668       //create composite
4669       group.addCompositeMember(compositeType, leftFactorGroup, rightFactorGroup);
4670 
4671       
4672       //go back to view group
4673       guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2Group.viewGroup&groupId=" + group.getId() + "');"));
4674 
4675       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
4676           TextContainer.retrieveFromRequest().getText().get("groupCompositeSuccess")));
4677 
4678       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
4679           loggedInSubject, group);
4680       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
4681           loggedInSubject, leftFactorGroup);
4682       GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(), 
4683           loggedInSubject, rightFactorGroup);
4684     
4685     } catch (RuntimeException re) {
4686       if (GrouperUiUtils.vetoHandle(GuiResponseJs.retrieveGuiResponseJs(), re)) {
4687         return;
4688       }
4689       throw re;
4690     } finally {
4691       GrouperSession.stopQuietly(grouperSession);
4692     }
4693   }
4694 
4695   /**
4696    * force grouperLoader to update this loader group
4697    * don't throw exception, display success or error message directly on New Ui screen
4698    * @param request
4699    * @param response
4700    */
4701   public void updateLoaderGroup(HttpServletRequest request, HttpServletResponse response) {
4702 
4703     if (!GrouperUiConfig.retrieveConfig().propertyValueBoolean("uiV2.group.allowGroupAdminsToRefreshLoaderJobs", true)) {
4704       throw new RuntimeException("Cant refresh loader groups from UI due to config param uiV2.group.allowGroupAdminsToRefreshLoaderJobs set to false");
4705     }
4706     
4707     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4708 
4709     GrouperSession grouperSession = null;
4710 
4711     Group group = null;
4712 
4713     try {
4714 
4715       grouperSession = GrouperSession.start(loggedInSubject);
4716 
4717       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
4718 
4719       if (group == null) {
4720         return;
4721       }
4722 
4723       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4724 
4725       try {
4726         final Group GROUP = group;
4727         GrouperSession.internal_callbackRootGrouperSession(new GrouperSessionHandler() {
4728           
4729           public Object callback(GrouperSession rootGrouperSession) throws GrouperSessionException {
4730             return GrouperLoader.runJobOnceForGroup(rootGrouperSession, GROUP, true);
4731           }
4732         });
4733          
4734       } catch (Exception e) {
4735 
4736         LOG.error("Error running loader job from ui for group: " + group.getName(), e);
4737         
4738         //lets show an error message on the new screen  
4739         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error,
4740             TextContainer.retrieveFromRequest().getText().get("loaderGroupUpdateError") + "<br />"
4741                 + e.getMessage()));
4742         return;
4743       }
4744               
4745       //lets show a success message on the new screen
4746       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success,
4747           TextContainer.retrieveFromRequest().getText().get("loaderGroupUpdateSuccess")));
4748 
4749       filterHelper(request, response, group);
4750 
4751     } finally {
4752       GrouperSession.stopQuietly(grouperSession);
4753     }
4754   }
4755   
4756   /**
4757    * view all loader managed groups
4758    * @param request
4759    * @param response
4760    */
4761   public void viewAllLoaderManagedGroups(HttpServletRequest request, HttpServletResponse response) { 
4762     
4763     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4764     GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4765     
4766     GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
4767     
4768     GrouperSession grouperSession = null;
4769   
4770     GroupContainer groupContainer = grouperRequestContainer.getGroupContainer();
4771     Set<GuiLoaderManagedGroup> guiLoaderManagedGroups = new LinkedHashSet<GuiLoaderManagedGroup>();
4772     
4773     try {
4774       grouperSession = GrouperSession.start(loggedInSubject);
4775       
4776       Group group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
4777 
4778       if (group == null) {
4779         return;
4780       }
4781       
4782       AttributeDefName loaderMetadataAttributeDefName = AttributeDefNameFinder.findByName(GrouperCheckConfig.loaderMetadataStemName()+":"+GrouperLoader.ATTRIBUTE_GROUPER_LOADER_METADATA_GROUP_ID, false);
4783       AttributeDefName loaderMetadataLoadedAttributeDefName = AttributeDefNameFinder.findByName(GrouperCheckConfig.loaderMetadataStemName()+":"+GrouperLoader.ATTRIBUTE_GROUPER_LOADER_METADATA_LOADED, false);
4784 
4785       //get all groups with settings
4786       int maxPageSize = GrouperUiConfig.retrieveConfig().propertyValueInt("grouperUi.grouperLoader.maxGroupsShown", 200);
4787       Set<Group> groupsWithLoaderMetadata = new GroupFinder().assignPrivileges(AccessPrivilege.VIEW_PRIVILEGES)
4788           .assignIdOfAttributeDefName(loaderMetadataAttributeDefName.getId())
4789           .assignAttributeValuesOnAssignment(GrouperUtil.toSetObjectType(group.getId()))
4790           .assignIdOfAttributeDefName2(loaderMetadataLoadedAttributeDefName.getId())
4791           .assignAttributeValuesOnAssignment2(GrouperUtil.toSetObjectType("true"))
4792           .assignAttributeCheckReadOnAttributeDef(false)
4793           .assignQueryOptions(QueryOptions.create("displayName", true, 1, maxPageSize))
4794           .findGroups();
4795       
4796       if (GrouperUtil.length(groupsWithLoaderMetadata) > 0) {
4797         
4798         String loaderMetadataAttributeName = GrouperCheckConfig.loaderMetadataStemName()+":"+GrouperLoader.LOADER_METADATA_VALUE_DEF;
4799         AttributeDefName attributeDefName = AttributeDefNameFinder.findByName(loaderMetadataAttributeName, false);
4800         
4801         AttributeAssignValueFinderResult attributeAssignValueFinderResult = new AttributeAssignValueFinder()
4802             .assignOwnerGroupsOfAssignAssign(groupsWithLoaderMetadata)
4803             .addAttributeDefNameId(attributeDefName.getId())
4804             .assignAttributeCheckReadOnAttributeDef(false)
4805             .findAttributeAssignValuesResult();
4806         
4807         guiLoaderManagedGroups.addAll(GuiLoaderManagedGroup.convertGroupIntoGuiLoaderManagedGroups(groupsWithLoaderMetadata, attributeAssignValueFinderResult));
4808         
4809       }
4810       
4811       groupContainer.setGuiLoaderManagedGroups(guiLoaderManagedGroups);
4812   
4813       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId",
4814           "/WEB-INF/grouperUi2/group/loaderManagedGroupsTab.jsp"));
4815       
4816       if (GrouperUtil.length(groupsWithLoaderMetadata) == maxPageSize) {
4817         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.info,
4818             TextContainer.retrieveFromRequest().getText().get("loaderGroupMaxSize")));
4819 
4820       }
4821       
4822     } finally {
4823       GrouperSession.stopQuietly(grouperSession);
4824     }
4825     
4826     
4827   }
4828 
4829   /**
4830    * schedule loader job
4831    * don't throw exception, display success or error message directly on New Ui screen
4832    * @param request
4833    * @param response
4834    */
4835   public void scheduleLoaderGroup(HttpServletRequest request, HttpServletResponse response) {
4836 
4837     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4838 
4839     GrouperSession grouperSession = null;
4840 
4841     Group group = null;
4842 
4843     try {
4844 
4845       grouperSession = GrouperSession.start(loggedInSubject);
4846 
4847       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
4848 
4849       if (group == null) {
4850         return;
4851       }
4852 
4853       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4854 
4855       try {
4856         boolean foundLoaderType = false;
4857     
4858         // check sql first
4859         AttributeDefName grouperLoader = GrouperDAOFactory.getFactory().getAttributeDefName()
4860             .findByNameSecure(GrouperConfig.retrieveConfig().propertyValueString("grouper.rootStemForBuiltinObjects", "etc") + ":legacy:attribute:legacyGroupType_grouperLoader", false);
4861     
4862         if (grouperLoader != null) {
4863           if (group.getAttributeDelegate().hasAttribute(grouperLoader)) {
4864             foundLoaderType = true;
4865             GrouperLoaderType.validateAndScheduleSqlLoad(group, null, false);
4866           }
4867         }
4868         
4869         // ok now check ldap
4870         if (!foundLoaderType) {
4871           AttributeDefName grouperLoaderLdapName = GrouperDAOFactory.getFactory().getAttributeDefName()
4872               .findByNameSecure(LoaderLdapUtils.grouperLoaderLdapName(), false);
4873           
4874           if (grouperLoaderLdapName != null) {
4875             AttributeAssign assign = group.getAttributeDelegate().retrieveAssignment("assign", grouperLoaderLdapName, true, false);
4876             if (assign != null) {
4877               foundLoaderType = true;
4878               GrouperLoaderType.validateAndScheduleLdapLoad(assign, null, false);
4879             }
4880           }
4881         }
4882         
4883         if (!foundLoaderType) {
4884           throw new RuntimeException("Group is not a loader group.");
4885         }
4886       } catch (Exception e) {
4887 
4888         LOG.error("Error scheduling loader job from ui for group: " + group.getName(), e);
4889         
4890         //lets show an error message on the new screen  
4891         guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error,
4892             TextContainer.retrieveFromRequest().getText().get("loaderGroupScheduleError") + "<br />"
4893                 + e.getMessage()));
4894         return;
4895       }
4896 
4897       //lets show a success message on the new screen
4898       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success,
4899           TextContainer.retrieveFromRequest().getText().get("loaderGroupScheduleSuccess")));
4900 
4901       filterHelper(request, response, group);
4902 
4903     } finally {
4904       GrouperSession.stopQuietly(grouperSession);
4905     }
4906   }
4907 
4908   /**
4909    * this subjects privileges inherited from folders
4910    * @param request
4911    * @param response
4912    */
4913   public void inheritedPrivilegesAssignedToThisGroupFromFolders(HttpServletRequest request, HttpServletResponse response) {
4914     
4915     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4916     
4917     GrouperSession grouperSession = null;
4918   
4919     Group group = null;
4920     
4921     try {
4922   
4923       grouperSession = GrouperSession.start(loggedInSubject);
4924   
4925       group = retrieveGroupHelper(request, AccessPrivilege.VIEW).getGroup();
4926       
4927       if (group == null) {
4928         return;
4929       }
4930   
4931       //if viewing a subject, and that subject is a group, just show the group screen
4932       GrouperSubject grouperSubject = new GrouperSubject(group);
4933 
4934       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4935   
4936       RulesContainer rulesContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getRulesContainer();
4937       
4938       Set<GuiRuleDefinition> guiRuleDefinitions = new TreeSet<GuiRuleDefinition>();
4939       {
4940         Set<RuleDefinition> groupRuleDefinitions  = RuleFinder.findSubjectPrivilegeInheritRules(grouperSubject, true);
4941         for (RuleDefinition ruleDefinition : GrouperUtil.nonNull(groupRuleDefinitions)) {
4942           GuiRuleDefinitioneans/api/GuiRuleDefinition.html#GuiRuleDefinition">GuiRuleDefinition guiRuleDefinition = new GuiRuleDefinition(ruleDefinition);
4943           if (guiRuleDefinition.getOwnerGuiStem() != null) {
4944             guiRuleDefinitions.add(guiRuleDefinition);
4945           }
4946         }
4947       }
4948       
4949       rulesContainer.setGuiRuleDefinitions(guiRuleDefinitions);
4950   
4951       guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
4952           "/WEB-INF/grouperUi2/group/assignedToGroupInheritedPrivilegesInvolvement.jsp"));
4953   
4954     } finally {
4955       GrouperSession.stopQuietly(grouperSession);
4956     }
4957   }
4958   
4959   /**
4960    * convert group to role from permissions screen
4961    * @param request
4962    * @param response
4963    */
4964   public void convertGroupToRole(HttpServletRequest request, HttpServletResponse response) {
4965     
4966     final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
4967     
4968     GrouperSession grouperSession = null;
4969   
4970     Group group = null;
4971     
4972     try {
4973   
4974       grouperSession = GrouperSession.start(loggedInSubject);
4975   
4976       group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
4977       
4978       if (group == null) {
4979         return;
4980       }
4981       
4982       //update the group
4983       group.setTypeOfGroup(TypeOfGroup.role);
4984       group.store();
4985 
4986       GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
4987   
4988       guiResponseJs.addAction(GuiScreenAction.newScript("guiV2link('operation=UiV2GroupPermission.groupPermission&groupId=" + group.getId() + "')"));
4989       
4990       //lets show a success message on the new screen
4991       guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.success, 
4992           TextContainer.retrieveFromRequest().getText().get("groupConvertedToRoleSuccess")));
4993   
4994     } finally {
4995       GrouperSession.stopQuietly(grouperSession);
4996     }
4997     
4998   }
4999 
5000 /**
5001    * combo filter create group folder.  Note, this cannot be composite (since you cant
5002    * add members to a composite)
5003    * @param request
5004    * @param response
5005    */
5006   public void groupRoleAssignPermissionFilter(final HttpServletRequest request, HttpServletResponse response) {
5007   
5008     //run the combo logic
5009     DojoComboLogic.logic(request, response, new DojoComboQueryLogicBase<Group>() {
5010   
5011       /**
5012        * 
5013        */
5014       @Override
5015       public Group lookup(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
5016         Subject loggedInSubject = grouperSession.getSubject();
5017         GroupFinder groupFinder = new GroupFinder().assignPrivileges(AccessPrivilege.ATTRIBUTE_UPDATE_PRIVILEGES)
5018             .assignSubject(loggedInSubject)
5019             .assignFindByUuidOrName(true).assignScope(query).addTypeOfGroup(TypeOfGroup.role);
5020         
5021         return groupFinder.findGroup();
5022       }
5023   
5024       /**
5025        * 
5026        */
5027       @Override
5028       public Collection<Group> search(HttpServletRequest localRequest, GrouperSession grouperSession, String query) {
5029         Subject loggedInSubject = grouperSession.getSubject();
5030         
5031         int groupComboSize = GrouperUiConfig.retrieveConfig().propertyValueInt("uiV2.groupComboboxResultSize", 200);
5032         QueryOptions queryOptions = QueryOptions.create(null, null, 1, groupComboSize);
5033         GroupFinder groupFinder = new GroupFinder().assignPrivileges(AccessPrivilege.ATTRIBUTE_UPDATE_PRIVILEGES)
5034             .assignScope(query).assignSubject(loggedInSubject)
5035             .assignSplitScope(true).assignQueryOptions(queryOptions).addTypeOfGroup(TypeOfGroup.role);
5036         
5037         return groupFinder.findGroups();
5038         
5039       }
5040   
5041       /**
5042        * 
5043        * @param t
5044        * @return id
5045        */
5046       @Override
5047       public String retrieveId(GrouperSession grouperSession, Group t) {
5048         return t.getId();
5049       }
5050       
5051       /**
5052        * 
5053        */
5054       @Override
5055       public String retrieveLabel(GrouperSession grouperSession, Group t) {
5056         return t.getDisplayName();
5057       }
5058   
5059       /**
5060        * 
5061        */
5062       @Override
5063       public String retrieveHtmlLabel(GrouperSession grouperSession, Group t) {
5064         //description could be null?
5065         String label = GrouperUiUtils.escapeHtml(t.getDisplayName(), true);
5066         String htmlLabel = "<img src=\"../../grouperExternal/public/assets/images/group.gif\" /> " + label;
5067         return htmlLabel;
5068       }
5069   
5070     });
5071     
5072   }
5073   
5074 }
5075 
5076 //  /**
5077 //   * this subjects privileges inherited from folders
5078 //   * @param request
5079 //   * @param response
5080 //   */
5081 //  public void provisioning(HttpServletRequest request, HttpServletResponse response) {
5082 //    
5083 //    final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
5084 //    
5085 //    GrouperSession grouperSession = null;
5086 //  
5087 //    Group group = null;
5088 //    
5089 //    try {
5090 //  
5091 //      grouperSession = GrouperSession.start(loggedInSubject);
5092 //  
5093 //      group = retrieveGroupHelper(request, AccessPrivilege.ADMIN).getGroup();
5094 //      
5095 //      if (group == null) {
5096 //        return;
5097 //      }
5098 //  
5099 //      ProvisioningContainer provisioningContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getProvisioningContainer();
5100 //      
5101 //      //if viewing a subject, and that subject is a group, just show the group screen
5102 //      GrouperSubject grouperSubject = new GrouperSubject(group);
5103 //
5104 //      GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
5105 //  
5106 //  
5107 //      guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId", 
5108 //          "/WEB-INF/grouperUi2/group/groupProvisioning.jsp"));
5109 //  
5110 //    } finally {
5111 //      GrouperSession.stopQuietly(grouperSession);
5112 //    }
5113 //  }
5114