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