View Javadoc
1   /*******************************************************************************
2    * Copyright 2012 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  /*
17  Copyright 2004-2007 University Corporation for Advanced Internet Development, Inc.
18  Copyright 2004-2007 The University Of Bristol
19  
20  Licensed under the Apache License, Version 2.0 (the "License");
21  you may not use this file except in compliance with the License.
22  You may obtain a copy of the License at
23  
24    http://www.apache.org/licenses/LICENSE-2.0
25  
26  Unless required by applicable law or agreed to in writing, software
27  distributed under the License is distributed on an "AS IS" BASIS,
28  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29  See the License for the specific language governing permissions and
30  limitations under the License.
31  */
32  
33  package edu.internet2.middleware.grouper;
34  
35  
36  import java.util.ArrayList;
37  import java.util.Collection;
38  import java.util.HashMap;
39  import java.util.HashSet;
40  import java.util.Iterator;
41  import java.util.LinkedHashMap;
42  import java.util.LinkedHashSet;
43  import java.util.LinkedList;
44  import java.util.List;
45  import java.util.Map;
46  import java.util.MissingResourceException;
47  import java.util.ResourceBundle;
48  import java.util.Set;
49  
50  import org.apache.commons.logging.Log;
51  import org.apache.commons.logging.LogFactory;
52  
53  import edu.internet2.middleware.grouper.attr.AttributeDef;
54  import edu.internet2.middleware.grouper.attr.AttributeDefName;
55  import edu.internet2.middleware.grouper.attr.assign.AttributeAssign;
56  import edu.internet2.middleware.grouper.cfg.GrouperConfig;
57  import edu.internet2.middleware.grouper.exception.AttributeDefNotFoundException;
58  import edu.internet2.middleware.grouper.exception.CompositeNotFoundException;
59  import edu.internet2.middleware.grouper.exception.GrantPrivilegeException;
60  import edu.internet2.middleware.grouper.exception.GroupNotFoundException;
61  import edu.internet2.middleware.grouper.exception.InsufficientPrivilegeException;
62  import edu.internet2.middleware.grouper.exception.MemberAddException;
63  import edu.internet2.middleware.grouper.exception.MemberDeleteException;
64  import edu.internet2.middleware.grouper.exception.MemberNotFoundException;
65  import edu.internet2.middleware.grouper.exception.MembershipNotFoundException;
66  import edu.internet2.middleware.grouper.exception.QueryException;
67  import edu.internet2.middleware.grouper.exception.SchemaException;
68  import edu.internet2.middleware.grouper.exception.SessionException;
69  import edu.internet2.middleware.grouper.exception.StemNotFoundException;
70  import edu.internet2.middleware.grouper.filter.GroupAnyAttributeFilter;
71  import edu.internet2.middleware.grouper.filter.GroupAttributeFilter;
72  import edu.internet2.middleware.grouper.filter.GrouperQuery;
73  import edu.internet2.middleware.grouper.filter.StemNameAnyFilter;
74  import edu.internet2.middleware.grouper.misc.GrouperDAOFactory;
75  import edu.internet2.middleware.grouper.privs.AccessPrivilege;
76  import edu.internet2.middleware.grouper.privs.NamingPrivilege;
77  import edu.internet2.middleware.grouper.privs.Privilege;
78  import edu.internet2.middleware.grouper.privs.PrivilegeHelper;
79  import edu.internet2.middleware.grouper.subj.LazySubject;
80  import edu.internet2.middleware.grouper.subj.SubjectHelper;
81  import edu.internet2.middleware.grouper.subj.UnresolvableSubject;
82  import edu.internet2.middleware.grouper.ui.GroupOrStem;
83  import edu.internet2.middleware.grouper.ui.GrouperUiFilter;
84  import edu.internet2.middleware.grouper.ui.PersonalStem;
85  import edu.internet2.middleware.grouper.ui.UIThreadLocal;
86  import edu.internet2.middleware.grouper.ui.util.GroupAsMap;
87  import edu.internet2.middleware.grouper.ui.util.MembershipAsMap;
88  import edu.internet2.middleware.grouper.ui.util.ObjectAsMap;
89  import edu.internet2.middleware.grouper.ui.util.SubjectAsMap;
90  import edu.internet2.middleware.subject.Source;
91  import edu.internet2.middleware.subject.Subject;
92  import edu.internet2.middleware.subject.SubjectNotFoundException;
93  import edu.internet2.middleware.subject.SubjectNotUniqueException;
94  import edu.internet2.middleware.subject.SubjectType;
95  import edu.internet2.middleware.subject.provider.SourceManager;
96  
97  /**
98   * High level wrapper methods for the Grouper API, including workarounds. 
99   * Primarily developed for the UI.<p />
100  * Occasionally takes advantage of protected access to the Grouper API, however,
101  * this access should not be required once the API is fully implemented.
102  * <p />
103  * 
104  * @author Gary Brown.
105  * @version $Id: GrouperHelper.java,v 1.64 2009-11-07 12:20:32 isgwb Exp $
106  */
107 
108 
109 public class GrouperHelper {
110   
111   /** logger */
112 	protected static final Log LOG = edu.internet2.middleware.grouper.util.GrouperUtil.getLog(GrouperHelper.class);
113 
114 	private static Map superPrivs = null; //Privs automatically granted to the
115 										  // system user
116 
117 	private static List personSources = null; //Subject sources which source
118 											  // 'people'
119 
120 	public static final String HIER_DELIM = ":"; //Currently :
121 																// (name
122 																// separator)
123 	public static final String NS_ROOT = "Grouper.NS_ROOT";
124 
125 	//Initialise system user privs
126 	static {
127 		superPrivs = new HashMap();
128 		superPrivs.put("read", Boolean.TRUE);
129 		superPrivs.put("view", Boolean.TRUE);
130 		superPrivs.put("update", Boolean.TRUE);
131     superPrivs.put("admin", Boolean.TRUE);
132     superPrivs.put("groupAttrRead", Boolean.TRUE);
133     superPrivs.put("groupAttrUpdate", Boolean.TRUE);
134 		superPrivs.put("create", Boolean.TRUE);
135     superPrivs.put("stemAdmin", Boolean.TRUE);
136     superPrivs.put("stemAttrRead", Boolean.TRUE);
137     superPrivs.put("stemAttrUpdate", Boolean.TRUE);
138 		//superPrivs.put("OPTIN", Boolean.TRUE);
139 		//superPrivs.put("OPTOUT", Boolean.TRUE);
140 	}
141 	
142 	//Privs which relate to Groups - access privileges
143 	private static String[] groupPrivs = { "admin", "update","read","view","optin","optout","groupAttrRead","groupAttrUpdate" };
144 	
145 //	Privs which relate to Groups - access privileges + member
146 	private static String[] groupPrivsWithMember = { "member", "admin", "update","read","view","optin","optout","groupAttrRead","groupAttrUpdate"};
147 	
148 	//Privs which relate to Stems - naming privileges
149 	//CH 20080324 change for UI from:  "STEM", "CREATE" 
150 	//private static String[] stemPrivs = {"Create Group", "Create Folder"};
151 	//GB 20080415 changed back, but UI looks up display name now for select options 
152 	private static String[] stemPrivs = {"create", "stemAdmin", "stemAttrRead", "stemAttrUpdate"};
153 	public static void main(String args[]) throws Exception{
154 		Subject subj = SubjectFinder.findById("GrouperSystem", true);
155 		GrouperSession s = GrouperSession.start(subj);
156 
157 		//GroupType type = GroupType.createType(s,"teaching");
158 		GroupType type = GroupTypeFinder.find("committee", true);
159 		/*type.addField(s,"enforcer",FieldType.ATTRIBUTE,Privilege.getInstance("read"),Privilege.getInstance("update"),true);
160 		type = GroupTypeFinder.find("mailingList");
161 		type.addField(s,"alias",FieldType.ATTRIBUTE,Privilege.getInstance("read"),Privilege.getInstance("update"),true);
162 		type = GroupTypeFinder.find("studentUnion");
163 		type.addField(s,"campus",FieldType.ATTRIBUTE,Privilege.getInstance("read"),Privilege.getInstance("update"),true);
164 		type = GroupTypeFinder.find("personal");
165 		type.addField(s,"proxy",FieldType.ATTRIBUTE,Privilege.getInstance("read"),Privilege.getInstance("update"),true);
166 		*/
167 		type = GroupTypeFinder.find("community", true);
168 		type.addList(s,"contributors",Privilege.getInstance("read"),Privilege.getInstance("update"));
169 		type.addAttribute(s,"scope",true);
170 		type = GroupTypeFinder.find("staff", true);
171 		type.addAttribute(s,"dept",true);
172 		/*type.addField(s,"staff",FieldType.LIST,Privilege.getInstance("read"),Privilege.getInstance("update"),false);
173 		type.addField(s,"clerical",FieldType.LIST,Privilege.getInstance("read"),Privilege.getInstance("update"),false);
174 		type.addField(s,"faculty_code",FieldType.ATTRIBUTE,Privilege.getInstance("read"),Privilege.getInstance("update"),true);
175 		type.addField(s,"org_code",FieldType.ATTRIBUTE,Privilege.getInstance("read"),Privilege.getInstance("update"),true);
176 		
177 		Group g = new Group(s,StemFinder.findRootStem(s),"tGroup","Teaching Group");
178 		g.addType(type);
179 		g.setAttribute("faculty_code","ARTF");
180 		g.setAttribute("org_code","FREN");
181 		Set x = SubjectFinder.findAll("keith"); 
182 		Iterator it = x.iterator();
183 		Subject subject;
184 		while(it.hasNext()) {
185 			subject=(Subject)it.next();
186 			g.addMember(subject,FieldFinder.find("staff"));
187 		}
188 		
189 		x = SubjectFinder.findAll("fiona");
190 		it = x.iterator();
191 		
192 		while(it.hasNext()) {
193 			subject=(Subject)it.next();
194 			g.addMember(subject,FieldFinder.find("clerical"));
195 		}
196 		
197 		
198 		
199 		
200 		*/
201 		
202 		s.stop();
203 	}
204 
205 
206 	/**
207 	 * Given a GrouperStem id return a list of stems and groups for which the
208 	 * GrouperStem is an immediate parent
209 	 * @param s GrouperSession for authenticated user
210 	 * @param stemId GrouperStem id
211 	 * @return List of all stems and groups for stemId
212 	 */
213 	public static List getChildren(GrouperSession s, String stemId) throws StemNotFoundException{
214 		Stem stem =null;
215 		if("".equals(stemId)) {
216 			stem=StemFinder.findRootStem(s);
217 		}else{
218 			stem=StemFinder.findByName(s, stemId, true);
219 		}
220 		ArrayList res = new ArrayList();
221 		Set children = stem.getChildStems();
222 		Iterator it = children.iterator();
223 		Stem childStem = null;
224 		while(it.hasNext()) {
225 			childStem=(Stem)it.next();
226 			res.add(GroupOrStem.findByStem(s,childStem));
227 		}
228 		children=stem.getChildGroups();
229 		it = children.iterator();
230 		Group childGroup = null;
231 		while(it.hasNext()) {
232 			childGroup=(Group)it.next();
233 			res.add(GroupOrStem.findByGroup(s,childGroup));
234 		}
235 		return res;
236 	}
237 
238 	/**
239 	 * Given a list of GrouperAttributes, return a list of GrouperStems
240 	 * which the attributes belong to, and load all atributes for these Stems
241 	 * 
242 	 * @param s GrouperSession for authenticated user
243 	 * @param list of GrouperAttributes
244 	 * @return List of GrouperGroups or GrouperStems
245 	 */
246 	/*public static List instantiateStems(GrouperSession s, List list) {
247 		return instantiateGroups(s, list);
248 	}*/
249 
250 
251 
252 	/**
253 	 * Given a list of GrouperAttributes, return a list of GrouperGroups
254 	 * which the attributes belong to, and load all atributes for these groups
255 	 * 
256 	 * @param s GrouperSession for authenticated user
257 	 * @param list of GrouperAtributes
258 	 * @return List of GrouperGroups or GrouperStems
259 	 */
260 	/*public static List instantiateGroups(GrouperSession s, List list) {
261 		List instantiated = new ArrayList();
262 		Attribute attr = null;
263 		String key;
264 		Stem stem = null;
265 		for (int i = 0; i < list.size(); i++) {
266 			attr = (Attribute) list.get(i);
267 			key = attr.key();
268 
269 			//stem=Cache.instance().getGroup(s,key);
270 			if (stem == null) {
271 				try {
272 				stem = (GrouperGroup) GrouperGroup.loadByKey(s, key);
273 				}catch(InsufficientPrivilegeException e) {
274 					throw new RuntimeException(e);
275 				}
276 				//Cache.instance().put(s,key,stem);
277 			}
278 
279 
280 	/**
281 	 * Given a list of GrouperList objects return a list of instantiated
282 	 * GrouperGroups as Maps
283 	 * 
284 	 * @param s GrouperSession for authenticated user
285 	 * @param groups List of GrouperLists
286 	 * @return List of GrouperGroups wrapped as Maps
287 	 */
288 	public static List groups2Maps(GrouperSession s, List groups) throws GroupNotFoundException{
289 		List maps = new ArrayList();
290 		Object obj;
291 		for (int i = 0; i < groups.size(); i++) {
292 			//Just in case something goes wrong - Group doesn't exist but still
293 			// a pointer to it
294 			try {
295 				obj = groups.get(i);
296 				if (obj instanceof Membership)
297 					obj = ((Membership) obj).getGroup();
298 				maps.add(group2Map(s, (Group) obj));
299 			} catch (NullPointerException e) {
300 				//@TODO What should happen?
301 			}
302 		}
303 		return maps;
304 
305 	}
306 
307 	/**
308 	 * Given a ist of GrouperList objects return a list of instantiated GrouperStems
309 	 * as Maps
310 	 * @param s GrouperSession for authenticated user
311 	 * @param stems List of GrouperLists
312 	 * @return List of GrouperStems wrapped as Maps
313 	 */
314 	public static List stems2Maps(GrouperSession s, List stems) throws GroupNotFoundException{
315 		List maps = new ArrayList();
316 		Object obj;
317 		for (int i = 0; i < stems.size(); i++) {
318 			//Just in case something goes wrong - Group doesn't exist but still
319 			// a pointer to it
320 			try {
321 				obj = stems.get(i);
322 				
323 				maps.add(stem2Map(s, (Stem) obj));
324 			} catch (NullPointerException e) {
325 				//@TODO What should happen?
326 			}
327 		}
328 		return maps;
329 
330 	}
331 	
332 	/**
333 	 * Given a GrouperStem return a Map representing it
334 	 * @param s GrouperSession for authenticated user
335 	 * @param stem GrouperStem to wrap
336 	 * @return GrouperStem wrapped as a Map
337 	 */
338 	public static Map stem2Map(GrouperSession s, Stem stem) {
339 		Map stemMap = ObjectAsMap.getInstance("StemAsMap", stem, s);
340 		if("".equals(stem.getName())) {
341 			stemMap.put("isRootStem",Boolean.TRUE);
342 		}
343 		return stemMap;
344 
345 	}
346 	
347 	/**
348 	 * Given a Stem return a Map representing it
349 	 * @param s GrouperSession for authenticated user
350 	 * @param stem GrouperStem to wrap
351 	 * @return Stem wrapped as a Map
352 	 */
353 	public static Map group2Map(GrouperSession s, Stem stem) {
354 		return ObjectAsMap.getInstance("StemAsMap", stem, s);		
355 	}
356 	
357 	/**
358 	 * Given a GroupOrStem return a Map representing it
359 	 * @param s GrouperSession for authenticated user
360 	 * @param groupOrStem GroupOrStem to wrap
361 	 * @return GroupOrStem wrapped as a Map
362 	 */
363 	public static Map group2Map(GrouperSession s, GroupOrStem groupOrStem) {
364 		return groupOrStem.getAsMap();
365 	}
366 
367 	/**
368 	 * Given a Group  return
369 	 * a Map representation of it
370 	 * @param s GrouperSession for authenticated user
371 	 * @param group Group to wrap
372 	 * @return Group wrapped as a Map
373 	 */
374 	public static Map group2Map(GrouperSession s, Group group){ 
375 		ObjectAsMap map = new GroupAsMap(group, s);
376 			if (map.get("displayExtension") == null)
377 				map.put("displayExtension", map.get("extension"));
378 		return (Map) map;
379 	}
380 
381 	/**
382 	 * Given a GrouperGroup or GrouperStem return a list of ancestor GrouperStems
383 	 * as Maps
384 	 * 
385 	 * @param s GrouperSession for authenticated user
386 	 * @param groupOrStem GrouperGroup or GrouperStem
387 	 * @return List of ancestor GrouperStems wrapped as Maps
388 	 */
389 	public static List parentStemsAsMaps(GrouperSession s, GroupOrStem groupOrStem) throws StemNotFoundException{
390 		List path = new ArrayList();
391 		if(groupOrStem==null) return path;
392 		Map map = group2Map(s, groupOrStem);
393 
394 		Stem curStem = null;
395 		while (!GrouperHelper.NS_ROOT.equals(map.get("stem"))) {
396 			curStem = StemFinder.findByName(s, (String) map.get("stem"), true);
397 			if (curStem != null) {
398 				map = stem2Map(s, curStem);
399 				path.add(0, map);
400 			}
401 		}
402 		return path;
403 	}
404 
405 	
406 	/**
407 	 * Given a GrouperGroup or GrouperStem return a Map where the keys
408 	 * are access or naming privileges that s.subject() has.
409 	 * 
410 	 * @param s GrouperSession for authenticated user
411 	 * @param groupOrStem GrouperGroup or GroupeStem for which privileges are being requested
412 	 * @return Map representing privileges
413 	 */
414 	public static Map hasAsMap(GrouperSession s, GroupOrStem groupOrStem) throws MemberNotFoundException{
415 		return hasAsMap(s, groupOrStem, false);
416 	}
417 
418 	/**
419 	 * Given a GrouperGroup or GrouperStem return a Map where the keys are
420 	 * access or naming privileges that s.subject() has. If isMortal == false
421 	 * and the subject is the system user, all privileges are returned.
422 	 * @param s GrouperSession for authenticated user
423 	 * @param groupOrStem GrouperGroup or GroupeStem for which privileges are being requested
424 	 * @param isMortal if system user should they be teated as such
425 	 * @return Map representing privileges
426 	 */
427 	public static Map hasAsMap(GrouperSession s, GroupOrStem groupOrStem,
428 			boolean isMortal) throws MemberNotFoundException{
429 		Map privs = null;
430 
431 		Group g = null;
432 		Stem stem = null;
433 		boolean isActiveWheelGroupMember = Boolean.TRUE.equals(UIThreadLocal.get("isActiveWheelGroupMember"));
434 		privs = new HashMap();
435 		if (!isMortal
436 				&& ("GrouperSystem".equals(s.getSubject().getId())
437 						|| isActiveWheelGroupMember)) {
438 			privs.putAll(superPrivs);
439 			if(groupOrStem==null) return privs;
440 			
441 			if (groupOrStem.isGroup()) {
442 				g = groupOrStem.getGroup();
443 				
444 				if (g.hasMember(s.getSubject())) {
445 					privs.put("member", Boolean.TRUE);
446 				}
447 			} else {
448 				stem = groupOrStem.getStem();
449 				if(stem.isRootStem()) privs.remove("create");
450 			}
451 			if (privs == null)
452 				privs = superPrivs;
453 			return privs;
454 		}
455 		if("GrouperSystem".equals(s.getSubject().getId())
456 				||isActiveWheelGroupMember) {
457 			privs = new HashMap();
458 			privs.put("stemAdmin",Boolean.TRUE);
459 			if(groupOrStem!=null && groupOrStem.isStem()&& !"".equals(groupOrStem.getStem().getName())) {
460 				privs.put("create",Boolean.TRUE);
461 			}
462 			return privs;
463 		}
464 		
465 		if(groupOrStem==null) return new HashMap();
466 		
467 			g = groupOrStem.getGroup();
468 		
469 			stem = groupOrStem.getStem();
470 		
471 		Set privList = null;
472 		if (g != null) {
473 			privList = g.getPrivs(s.getSubject());
474 		} else {
475 			privList = stem.getPrivs(s.getSubject());
476 		}
477 		if(privList !=null) {
478 			Iterator it = privList.iterator();
479 			Object p = null;
480 			while(it.hasNext()){
481 				p=it.next();
482 				if(p instanceof AccessPrivilege) {
483 					privs.put(((AccessPrivilege)p).getName(), Boolean.TRUE);
484 				}else if(p instanceof NamingPrivilege) {
485 					privs.put(((NamingPrivilege)p).getName(), Boolean.TRUE);
486 				}else{
487 					privs.put(it.next(), Boolean.TRUE);
488 				}
489 			}
490 		}
491 		if (g != null) {
492 			
493 			if (g.hasMember(s.getSubject()))
494 				privs.put("member", Boolean.TRUE);
495 		}
496 		return privs;
497 	}
498 
499 	/**
500 	 * Given a GrouperGroup or GrouperStem return a Map where the keys
501 	 * are access or naming privileges that member.subject() has.
502 	 * 
503 	 * @param s GrouperSession for authenticated user
504 	 * @param groupOrStem GrouperGroup or GroupeStem for which privileges are being requested
505 	 * @param member Subject who privileges were granted to
506 	 * @return Map representing privileges
507 	 */
508 	public static Map hasAsMap(GrouperSession s, GroupOrStem groupOrStem,
509 		Member member,Field field) throws SubjectNotFoundException,SchemaException{
510 		Map privs = null;
511 		if ("GrouperSystem".equals(member.getSubjectId())) {
512 			//@TODO Review
513 			//return superPrivs;
514 
515 		}
516 		Set privList = null;
517 
518 		privs = new HashMap();
519 		Group group = null;
520 		Stem stem = null;
521 		if (groupOrStem.isGroup()) {
522 			group = groupOrStem.getGroup();
523 			privList = group.getPrivs(member.getSubject());
524 		} else {
525 			stem = groupOrStem.getStem();
526 			privList = stem.getPrivs(member.getSubject());
527 		}
528 		Iterator it = privList.iterator();
529 		Object obj;
530 		String p;
531 		while(it.hasNext()) {
532 			obj=it.next();
533 			if(obj instanceof AccessPrivilege) {
534 				p = ((AccessPrivilege)obj).getName();
535 			}else{
536 				p = ((NamingPrivilege)obj).getName();
537 			}
538 			privs.put(p, Boolean.TRUE);
539 		}
540 		if (group != null) {
541 			if (group.hasMember(member.getSubject(),field))
542 				privs.put("member", Boolean.TRUE);
543 		}
544 
545 		return privs;
546 	}
547 
548 	/** Given a Subject return a Map representation of it
549 	 * @param subject to be wrapped
550 	 * @return Subject wrapped as a Map
551 	 */
552 	public static Map subject2Map(Subject subject) {
553 		//@TODO what should happen if Group - see next method
554 		SubjectAsMap map = (SubjectAsMap)ObjectAsMap.getInstance("SubjectAsMap", subject);
555 		return (Map) map;
556 	}
557 	
558 	/** Given a Subject return a Map representation of it
559 	 * @param subject to be wrapped
560 	 * @param addAttr Map of additional attributes
561 	 * @return Subject wrapped as a Map
562 	 */
563 	public static Map<Object, Object> subject2Map(Subject subject,Map addAttr) {
564 		//@TODO what should happen if Group - see next method
565 		SubjectAsMap map = (SubjectAsMap)ObjectAsMap.getInstance("SubjectAsMap", subject);
566 		if(addAttr !=null) map.putAll(addAttr);
567 		return (Map) map;
568 	}
569 
570 	/**
571 	 * Given a subject id and subject type and a Map, return a Map representation of the
572 	 * subject and add the key/value pairs from the input Map.
573 	 * 
574 	 * @param s GrouperSession for authenticated user
575 	 * @param subjectId Subject id
576 	 * @param subjectType Subject type e.g. person, group
577 	 * @param addAttr Map of aditional attributes
578 	 * @return Subject wrapped as a Map
579 	 */
580 	public static Map subject2Map(GrouperSession s, String subjectId,
581 			String subjectType,String sourceId,Map addAttr) throws SubjectNotFoundException{
582 		Map subjectMap = subject2Map(s,subjectId,subjectType,sourceId);
583 		if(addAttr !=null) subjectMap.putAll(addAttr);
584 		return subjectMap;
585 	}
586 	
587 	/**
588 	 * Given a subject id and subject type return a Map representation of it.
589 	 * 
590 	 * @param s GrouperSession for authenticated user
591 	 * @param subjectId Subject id
592 	 * @param subjectType Subject type e.g. person, group
593 	 * @return Subject wrapped as a Map
594 	 */
595 	public static Map subject2Map(GrouperSession s, String subjectId,
596 			String subjectType,String sourceId) throws SubjectNotFoundException{
597 		if (!"group".equals(subjectType)) {
598 			Subject subject = null;
599 			try {
600 				subject = SubjectFinder.findById(subjectId, subjectType,sourceId, true);
601 			} catch (Exception e) {
602 				LOG.error(e);
603 				subject = new UnresolvableSubject(subjectId,subjectType,sourceId); 
604 			}
605 			SubjectAsMap map =(SubjectAsMap)ObjectAsMap.getInstance("SubjectAsMap", subject);
606 			return (Map) map;
607 		}
608 		try {
609 		Group group = GroupFinder.findByUuid(s, subjectId, true);
610 		Map groupMap = group2Map(s, group);
611 		return groupMap;
612 		}catch(GroupNotFoundException e) {
613 			throw new SubjectNotFoundException(e.getMessage(), e);
614 		}
615 	}
616 	
617 	/**
618 	 * Given an array of Subjects return a List of Maps representing those subjects
619 	 * 
620 	 * @param objects array of Subjects
621 	 * @param addAttr Map of additional attributes
622 	 * @return List of Subjects wrapped as Maps
623 	 */
624 	public static List subjects2Maps(Object[] objects,Map addAttr) {
625 		if (objects instanceof Subject[])
626 			return subjects2Maps((Subject[]) objects);
627 		Subject[] subjects = new Subject[objects.length];
628 		for (int i = 0; i < objects.length; i++) {
629 			subjects[i] = (Subject) objects[i];
630 		}
631 		return subjects2Maps(subjects,addAttr);
632 	}
633 	
634 	/**
635 	 * Given an array of Subjects return a List of Maps representing those subjects
636 	 * 
637 	 * @param objects array of Subjects
638 	 * @return List of Subjects wrapped as Maps
639 	 */
640 	public static List subjects2Maps(Object[] objects) {
641 		
642 		return subjects2Maps(objects,null);
643 	}
644 
645 	/**
646 	 * Given an array of Subjects return a List of Maps representing those subjects
647 	 * 
648 	 * @param subjects array of Subjects
649 	 * @param addAttr Map of aditional attributes
650 	 * @return List of Subjects wrapped as Maps
651 	 */
652 	public static List<Map<Object,Object>> subjects2Maps(Subject[] subjects,Map addAttr) {
653 		List maps = new ArrayList();
654 		for (int i = 0; i < subjects.length; i++) {
655 			if(subjects[i]!=null) maps.add(subject2Map(subjects[i],addAttr));
656 		}
657 		return maps;
658 	}
659 	
660 	/**
661 	 * Given an array of Subjects return a List of Maps representing those subjects
662 	 * 
663 	 * @param subjects array of Subjects
664 	 * @return List of Subjects wrapped as Maps
665 	 */
666 	public static List subjects2Maps(Subject[] subjects) {
667 		List maps = new ArrayList();
668 		for (int i = 0; i < subjects.length; i++) {
669 			maps.add(subject2Map(subjects[i]));
670 		}
671 		return maps;
672 	}
673 
674 	
675 	/**
676 	 * Given a list of GrouperList objects return a sublist from 
677 	 * start to start + pageSize of each GrouperList.member() as a Map
678 	 *  
679 	 * @param s GrouperSession for authenticated user
680 	 * @param members List of GrouperLists or GrouperMembers
681 	 * @param start 0 based start index
682 	 * @param pageSize number of results to return
683 	 * @return List of Subjects wrapped as Maps
684 	 */
685 	public static List groupList2SubjectsMaps(GrouperSession s, List members,
686 			int start, int pageSize) 
687 		throws GroupNotFoundException,SubjectNotFoundException,
688 		MemberNotFoundException,SubjectNotUniqueException{
689 		return groupList2SubjectsMaps(s, members, null, start, pageSize);
690 	}
691 
692 	/**
693 	 * Given a list of GrouperMembers return a list of Map representations of them
694 	 * @param s GrouperSession for authenticated user
695 	 * @param members List of GrouperLists or GrouperMembers
696 	 * @return List of Subjects wrapped as Maps
697 	 */
698 	public static List groupList2SubjectsMaps(GrouperSession s, List members) 
699 		throws GroupNotFoundException,SubjectNotFoundException,
700 		MemberNotFoundException,SubjectNotUniqueException{
701 		return groupList2SubjectsMaps(s, members, null);
702 	}
703 
704 	/**
705 	 * Given a list of GrouperMembers return a list of Map representations of them
706 	 * where the key asMemberOf is set to the value of the parameter asMemberOf
707 	 * @param s GrouperSession for authenticated user
708 	 * @param members List of GrouperLists or GrouperMembers
709 	 * @param asMemberOf GrouperGroup id identifying context
710 	 * @return List of Subjects wrapped as Maps
711 	 */
712 	public static List groupList2SubjectsMaps(GrouperSession s, List members,
713 			String asMemberOf) 
714 			throws GroupNotFoundException,SubjectNotFoundException,
715 			MemberNotFoundException,SubjectNotUniqueException{
716 		return groupList2SubjectsMaps(s, members, asMemberOf, 0, members.size());
717 	}
718 
719 	/**
720 	 * Given a list of GrouperMembers return a list of Map representations of 
721 	 * a sublist of them (from start to start + pageSize) where the key 
722 	 * asMemberOf is set to the value of the parameter asMemberOf
723 	 * @param s GrouperSession for authenticated user
724 	 * @param members List of GrouperLists or GrouperMembers
725 	 * @param asMemberOf GrouperGroup id identifying context
726 	 * @param start of sublist
727 	 * @param pageSize number of results to return
728 	 * @return List of Subjects wrapped as Maps
729 	 */
730 	public static List groupList2SubjectsMaps(GrouperSession s, List members,
731 			String asMemberOf, int start, int pageSize) 
732 			throws GroupNotFoundException,SubjectNotFoundException,
733 				MemberNotFoundException,SubjectNotUniqueException{
734 		int end = start + pageSize;
735 		if (end > members.size())
736 			end = members.size();
737 		List maps = new ArrayList();
738 		Membership list = null;
739 		Member member = null;
740 		Subject subject=null;
741 		Map subjMap = null;
742 		Object listItem;
743 		Group via = null;
744 		Set chain = null;
745 		Object chainItem = null;
746 		Group firstInChain = null;
747 		Member chainMember = null;
748 		String[] chainGroupIds = null;
749 		int chainSizeAdjustment=1;
750 		String[] emptyStrArray=new String[]{};
751 		boolean isChainSameAsList = false;
752 		for (int i = start; i < end; i++) {
753 			chainGroupIds = emptyStrArray;
754 			listItem = members.get(i);
755 			if (listItem instanceof Membership) {
756 				list = (Membership) listItem;
757 				try{
758 					via = (Group) list.getViaGroup();
759 				}catch(GroupNotFoundException e){via=null;}
760 				chain = list.getChildMemberships();
761 
762 				if (chain != null && chain.size() > 0) {
763 					//chainGroupIds = getChainGroupIds(s,list);
764 					
765 				} else {
766 					firstInChain = null;
767 				}
768 				member = list.getMember();
769 				try {
770 					subject = member.getSubject();
771 				} catch (Exception e) {
772 					throw new RuntimeException(e);
773 				}
774 
775 			} else if (listItem instanceof Membership) {
776 				member = (Member) list.getMember();
777 				try {
778 					subject = member.getSubject();
779 				} catch (Exception e) {
780 					throw new RuntimeException(e);
781 				}
782 			}else if(listItem instanceof Subject) {
783 				subject = (Subject)listItem;
784 			}else if(listItem instanceof Group) {
785 				
786 				Subject subj = SubjectFinder.findById(asMemberOf, true);
787 				Map gSubjMap = subject2Map(subj);
788 				Map gMap = group2Map(s,(Group)listItem);
789 				gSubjMap.put("memberOfGroup",gMap);
790 				gSubjMap.put("asMemberOf",((Group)listItem).getUuid());
791 				maps.add(gSubjMap);
792 				continue;
793 			}else if(listItem instanceof Stem) {
794 				
795 				Subject subj = SubjectFinder.findById(asMemberOf, true);
796 				Map sSubjMap = subject2Map(subj);
797 				Map sMap = stem2Map(s,(Stem)listItem);
798 				sSubjMap.put("memberOfGroup",sMap);
799 				sSubjMap.put("asMemberOf",((Stem)listItem).getUuid());
800 				maps.add(sSubjMap);
801 				continue;
802 			}
803 			
804 			if (subject.getType().getName().equals("group")) {
805 				Group group = GroupFinder.findByUuid(s, subject.getId());
806 				subjMap = group2Map(s, group);
807 			} else {
808 				subjMap = subject2Map(subject);
809 			}
810 			if (firstInChain != null)
811 				subjMap.put("via", group2Map(s, firstInChain));
812 			//Group group = list.getGroup();
813 			
814 			if (asMemberOf != null) {
815 				try{
816 					subjMap.put("memberOfGroup",group2Map(s,GroupFinder.findByUuid(s,asMemberOf)));
817 					subjMap.put("asMemberOf", asMemberOf);
818 				}catch(GroupNotFoundException e){}
819 			}else{
820 				if(list !=null) {
821 					subjMap.put("memberOfGroup",group2Map(s,list.getGroup()));
822 					subjMap.put("asMemberOf", list.getGroup().getUuid());
823 					
824 				}
825 				//subjMap.put("asMemberOf", group.getUuid());
826 			}
827 			if (chain != null) {
828 				subjMap.put("chain", chain);
829 				//subjMap.put("chainSize", new Integer(chain.size()));
830 				//subjMap.put("chainGroupIds", chainGroupIds);
831 			}
832 			if(via!=null)subjMap.put("via", via);
833 
834 			maps.add(subjMap);
835 		}
836 		return maps;
837 	}
838 	
839 	public static String[] getChainGroupIds(GrouperSession s,Membership list) 
840 		throws MemberNotFoundException,GroupNotFoundException{
841 		Set chainIds = new LinkedHashSet();
842 		Member chainMember;
843 		Set chain = list.getChildMemberships();
844 		String[] chainGroupIds={};
845 		Group via = list.getViaGroup();
846 		if(via ==null && (chain==null ||chain.size()==0)) return chainGroupIds;
847 		if (via !=null) chainIds.add(via.getUuid());
848 		Membership gl;
849 		Membership mv;
850 		Iterator it = chain.iterator();
851 		while(it.hasNext()) {
852 			try {
853 				gl =(Membership) it.next();
854 				//gl=mv.toList(s);
855 			    chainMember = gl.getMember();
856 			
857 			chainIds.add(chainMember.getSubjectId());
858 			}catch(NullPointerException npe) {
859 				//chainGroupIds[j] = "!";
860 			}
861 		}
862 		chainGroupIds = (String[])chainIds.toArray(chainGroupIds);
863 		return chainGroupIds;
864 	}
865 	
866 	
867 	/**
868 	 * Given a GroupeGroup or GrouperStem id, an array of subjects and an array of 
869 	 * privileges, grant the privileges to each subject for the GrouperStem or 
870 	 * GrouperGroup
871 	 * 
872 	 * @param s GrouperSession for authenticated user
873 	 * @param stemOrGroupId GrouperGroup or GrouperStem id
874 	 * @param members array of Subjects
875 	 * @param privileges array of privileges
876 	 * @param forStems indicates GrouperStem
877 	 */
878 	public static void assignPrivileges(GrouperSession s, String stemOrGroupId,
879 			Subject[] members, String[] privileges, boolean forStems) 
880 		throws SchemaException,MemberAddException,InsufficientPrivilegeException,MemberNotFoundException,
881 			GrantPrivilegeException{
882 		assignPrivileges(s,stemOrGroupId,members,privileges,forStems,FieldFinder.find("members"));
883 	}
884 	
885 	/**
886 	 * Given a GroupeGroup or GrouperStem id, an array of subjects and an array of 
887 	 * privileges, grant the privileges to each subject for the GrouperStem or 
888 	 * GrouperGroup
889 	 * 
890 	 * @param s GrouperSession for authenticated user
891 	 * @param stemOrGroupId GrouperGroup or GrouperStem id
892 	 * @param members array of Subjects
893 	 * @param privileges array of privileges
894 	 * @param forStems indicates GrouperStem
895 	 */
896 	public static void assignPrivileges(GrouperSession s, String stemOrGroupId,
897 			Subject[] members, String[] privileges, boolean forStems,Field field) 
898 		throws SchemaException,MemberAddException,InsufficientPrivilegeException,MemberNotFoundException,
899 			GrantPrivilegeException{
900 		Group group = null;
901 		Stem stem = null;
902 		Subject subject;
903 		GroupOrStem  groupOrStem=GroupOrStem.findByID(s,stemOrGroupId);
904 		
905 			stem = groupOrStem.getStem();
906 			group = groupOrStem.getGroup();
907 		boolean circular = false;
908 		for (int i = 0; i < members.length; i++) {
909 			subject = members[i];
910 			for (int j = 0; j < privileges.length; j++) {
911 				try {
912 					if ("member".equals(privileges[j].toLowerCase()) && !group.hasImmediateMember(subject,field)) {
913 						if(group.toSubject().equals(subject) && field.getName().equals("members")) {
914 							circular=true;
915 						}else{
916 							group.addMember(subject,field);						
917 						}
918 					} else if (groupOrStem.isStem()) {
919 						stem.grantPriv(subject,Privilege.getInstance(privileges[j]));
920 
921 					} else if(!"member".equals(privileges[j].toLowerCase())){
922 						group.grantPriv(subject,Privilege.getInstance(privileges[j]));
923 
924 					}
925 				} catch (GrantPrivilegeException e) {
926 					//@TODO Expect different type of Exception in future
927 					if (e.getMessage()==null || e.getMessage().indexOf("membership already exists") == -1)
928 						throw e;
929 				} 
930 			}
931 		}
932 		if(circular) {
933 			throw new IllegalArgumentException("Circular membership");
934 		}
935 
936 	}
937 
938 	
939 	/**
940 	 * Given the UI browsing mode return a Map where each key is a valid stem
941 	 * for browsing. The Map is used to filter out stems which would lead to a 
942 	 * dead end.<p/>
943 	 * In a future version, this code should be factored into a new Class with interface
944 	 * so that new browse modes can be defined and implemented.
945 	 * 
946 	 * @param s GrouperSession for authenticated user
947 	 * @param browseMode - UI browse mode
948 	 * @return Map where keys are valid stems
949 	 */
950 	/*public static Map getValidStems(GrouperSession s, String browseMode) {
951 		Map stems = new HashMap();
952 		List groups = null;
953 		GrouperAccess accessImpl = s.access();
954 		GrouperNaming namingImpl = s.naming();
955 		if ("".equals(browseMode)) {
956 			GrouperMember member = null;
957 			try {
958 				member = GrouperMember.load(s, s.subject().getId(), s.subject()
959 						.getType().getName());
960 			} catch (SubjectNotFoundException e) {
961 				throw new RuntimeException(e);
962 			}
963 			groups = member.listVals();
964 
965 		} else if ("Create".equals(browseMode)) {
966 			groups = namingImpl.has(s, Grouper.PRIV_CREATE);
967 			List stemmable = namingImpl.has(s, Grouper.PRIV_STEM);
968 			groups.addAll(stemmable);
969 		} else if ("Manage".equals(browseMode)) {
970 			groups = accessImpl.has(s, Grouper.PRIV_ADMIN);
971 			List others = accessImpl.has(s, Grouper.PRIV_UPDATE);
972 			groups.addAll(others);
973 			others = accessImpl.has(s, Grouper.PRIV_READ);
974 			groups.addAll(others);
975 			List creatable = namingImpl.has(s, Grouper.PRIV_CREATE);
976 			List stemmable = namingImpl.has(s, Grouper.PRIV_STEM);
977 			groups.addAll(creatable);
978 			groups.addAll(stemmable);
979 		} else if ("Join".equals(browseMode)) {
980 			groups = accessImpl.has(s, Grouper.PRIV_OPTIN);
981 		} else if ("All".equals(browseMode)) {
982 			//return new HashMap();
983 			groups = accessImpl.has(s, Grouper.PRIV_VIEW);
984 			//@TODO add OPTINS?
985 		}
986 		GrouperGroup group;
987 		GrouperList grouperList;
988 		String groupKey;
989 		String stem;
990 		int pos = 0;
991 		String partStem;
992 		String gkey;
993 		String name;
994 		
995 		for (int i = 0; i < groups.size(); i++) {
996 			grouperList = (GrouperList) groups.get(i);
997 			name = grouperList.group().name();
998 
999 			if (!stems.containsKey(name)) {
1000 				stems.put(name, Boolean.TRUE);
1001 
1002 				pos = 0;
1003 				while (name.indexOf(HIER_DELIM, pos) > -1) {
1004 					pos = name.indexOf(HIER_DELIM, pos);
1005 					partStem = name.substring(0, pos);
1006 					pos++;
1007 					stems.put(partStem, Boolean.TRUE);
1008 
1009 				}
1010 			}
1011 		}
1012 		return stems;
1013 	}*/
1014 
1015 	
1016 	/**
1017 	 * Is s.subject() the system user?
1018 	 * 
1019 	 * @param s GrouperSession for authenticated user
1020 	 * @return boolean
1021 	 */
1022 	public static boolean isSuperUser(GrouperSession s) {
1023 		return s.getSubject().getId().equals("GrouperSystem")||Boolean.TRUE.equals(UIThreadLocal.get("isActiveWheelGroupMember"));
1024 	}
1025 
1026 	/**
1027 	 * Given a Subject id and SubjectType return a Subject - or null if one
1028 	 * not found
1029 	 * 
1030 	 * @param subjectId Subject id
1031 	 * @param subjectType Subject type
1032 	 * @return Subject
1033 	 */
1034 	public static Subject getSubjectFromIdAndType(String subjectId,
1035 			String subjectType) {
1036 		try {
1037 			return SubjectFinder.findById(subjectId, subjectType);
1038 		} catch (Exception e) {
1039 		}
1040 		return null;
1041 
1042 	}
1043 
1044 	/**
1045 	 * Given a GrouperGroup id return the GrouperGroup
1046 	 * 
1047 	 * @param s GrouperSession for authenticated user
1048 	 * @param id GrouperGroup id
1049 	 * @return GrouperGroup
1050 	 */
1051 	public static Group groupLoadById(GrouperSession s, String id) throws GroupNotFoundException{
1052 
1053 		Group group = null;
1054 
1055 		group = GroupFinder.findByUuid(s, id);
1056 		
1057 		return group;
1058 
1059 	}
1060 
1061 	/**
1062 	 * Return an array of all access privileges + member
1063 	 * 
1064 	 * @param s GrouperSession for authenticated user
1065 	 * @return array of privilege names
1066 	 */
1067 	public static String[] getGroupPrivsWithMember(GrouperSession s) {
1068 		return groupPrivsWithMember;
1069 	}
1070 	
1071 	/**
1072 	 * Return an array of all access privileges
1073 	 * 
1074 	 * @param s GrouperSession for authenticated user
1075 	 * @return array of privilege names
1076 	 */
1077 	public static String[] getGroupPrivs(GrouperSession s) {
1078 		return groupPrivs;
1079 	}
1080 
1081 	/**
1082 	 * Return an array of all naming privileges
1083 	 * @param s GrouperSession for authenticated user
1084 	 * @return array of privilege names
1085 	 */
1086 	public static String[] getStemPrivs(GrouperSession s) {
1087 		return stemPrivs;
1088 	}
1089 	
1090 	/**
1091 	 * Return a Collection of all naming privileges
1092 	 * @param bundle ResourceBundle to lookup display name
1093 	 * @return Collection of Maps of privilege names and display names
1094 	 */
1095 	public static Collection getStemPrivsWithLabels(ResourceBundle bundle) {
1096 		List<Map<String,String>> privs = new ArrayList<Map<String,String>>();
1097 		
1098 		String displayName=null;
1099 		for(int i=0;i<stemPrivs.length;i++){
1100 			Map priv = new HashMap();
1101 			displayName=stemPrivs[i];
1102 			try {
1103 				displayName=bundle.getString("priv." + stemPrivs[i]);
1104 			}catch(MissingResourceException mre){}
1105 			priv.put("value", stemPrivs[i]);
1106 			priv.put("label", displayName);
1107 			privs.add(priv);
1108 		}
1109 		return privs;
1110 	}
1111 	
1112 	 /**
1113    * Return a Collection of all access privileges
1114    * @param bundle ResourceBundle to lookup display name
1115    * @return Collection of Maps of privilege names and display names
1116    */
1117   public static Collection getGroupPrivsWithLabels(ResourceBundle bundle) {
1118     List<Map<String,String>> privs = new ArrayList<Map<String,String>>();
1119     
1120     String displayName=null;
1121     for(int i=0;i<groupPrivs.length;i++){
1122       Map priv = new HashMap();
1123       displayName=groupPrivs[i];
1124       try {
1125         displayName=bundle.getString("priv." + groupPrivs[i]);
1126       }catch(MissingResourceException mre){}
1127       priv.put("value", groupPrivs[i]);
1128       priv.put("label", displayName);
1129       privs.add(priv);
1130     }
1131     return privs;
1132   }
1133 
1134 	
1135 	/**
1136 	 * Given a simple query and scoping stem search for matching groups and return as List
1137 	 * @param s GrouperSession for authenticated user
1138 	 * @param query to search for
1139 	 * @param from stem which scopes search
1140 	 * @param attr name of attribute to search
1141 	 * @return List of groups matched
1142 	 */
1143 	public static List searchGroupsByAttribute(GrouperSession s, String query, String from,String attr) throws QueryException,StemNotFoundException{
1144 
1145 		GrouperQuery q = GrouperQuery.createQuery(s,new GroupAttributeFilter(attr,query,StemFinder.findByName(s,from, true)));
1146 		Set res = q.getGroups();
1147 		return new ArrayList(res);
1148 		
1149 	}
1150 	
1151 	
1152 	/**
1153 	 * Given a simple query and scoping stem search for matching groups and return as List
1154 	 * @param s GrouperSession for authenticated user
1155 	 * @param query to search for
1156 	 * @param from stem which scopes search
1157 	 * @param searchInDisplayNameOrExtension name=displayName / extemsion=displayExtension
1158 	 * @param searchInNameOrExtension name=name / extemsion=extension
1159 	 * @return List of groups matched
1160 	 */
1161 	public static List searchGroups(GrouperSession s, String query, String from,String searchInDisplayNameOrExtension,String searchInNameOrExtension) 
1162 	throws StemNotFoundException,QueryException{
1163 
1164 		if(searchInDisplayNameOrExtension==null && searchInNameOrExtension==null) {
1165 			GrouperQuery q = GrouperQuery.createQuery(s,new GroupAnyAttributeFilter(query,StemFinder.findByName(s,from)));
1166 			Set res = q.getGroups();
1167 			return new ArrayList(res);
1168 		}
1169 		
1170 		List displayResults = null;
1171 		List nonDisplayResults=null; 
1172 		String attr = null;
1173 		if(!"".equals(searchInDisplayNameOrExtension)) {
1174 			if("name".equals(searchInDisplayNameOrExtension)) {
1175 				attr="displayName";
1176 			}else{
1177 				attr="displayExtension";
1178 			}
1179 			displayResults = searchGroupsByAttribute(s,query,from,attr);	
1180 		}
1181 		if(!"".equals(searchInNameOrExtension)) {
1182 			if("name".equals(searchInNameOrExtension)) {
1183 				attr="name";
1184 			}else{
1185 				attr="extension";
1186 			}
1187 			nonDisplayResults = searchGroupsByAttribute(s,query,from,attr);	
1188 		}
1189 		if(displayResults==null && nonDisplayResults==null) return new ArrayList();
1190 		if(displayResults==null && nonDisplayResults!=null) return nonDisplayResults;
1191 		if(displayResults!=null && nonDisplayResults==null) return displayResults;
1192 		Object obj;
1193 		for(int i=0;i<nonDisplayResults.size();i++) {
1194 			obj = nonDisplayResults.get(i);
1195 			if(!displayResults.contains(obj)) displayResults.add(obj);
1196 		}
1197 			
1198 		return displayResults;
1199 		
1200 	}
1201 
1202   /**
1203    * Given simple query, scoping stem and ui browseMode return list of
1204    * matching groups, pruned to give results relevant to browseMode.<p/>
1205    * The browseMode filtering needs to be factored into a new Class with interface
1206    * so that new browse modes can be added easily
1207    * 
1208    * @param s GrouperSession for authenticated user
1209    * @param query to search for
1210    * @param from Stem which scopes search
1211    * @param searchInDisplayNameOrExtension name=displayName / extension=displayExtension
1212    * @param searchInNameOrExtension name=name / extension=extension
1213    * @param browseMode UI browse mode to filter results by
1214    * @return List of GrouperGroups matched
1215    */
1216   public static List<Group> searchGroups(GrouperSession s, String query,
1217       String from, String searchInDisplayNameOrExtension,
1218       String searchInNameOrExtension,String browseMode) throws Exception{
1219     List<Group> groups = searchGroupsHelper(s, query, from, searchInDisplayNameOrExtension, searchInNameOrExtension, browseMode);
1220     return groups;
1221   }
1222 	
1223 	/**
1224 	 * Given simple query, scoping stem and ui browseMode return list of
1225 	 * matching groups, pruned to give results relevant to browseMode.<p/>
1226 	 * The browseMode filtering needs to be factored into a new Class with interface
1227 	 * so that new browse modes can be added easily
1228 	 * 
1229 	 * @param s GrouperSession for authenticated user
1230 	 * @param query to search for
1231 	 * @param from Stem which scopes search
1232 	 * @param searchInDisplayNameOrExtension name=displayName / extension=displayExtension
1233 	 * @param searchInNameOrExtension name=name / extension=extension
1234 	 * @param browseMode UI browse mode to filter results by
1235 	 * @return List of GrouperGroups matched
1236 	 */
1237 	private static List<Group> searchGroupsHelper(GrouperSession s, String query,
1238 			String from, String searchInDisplayNameOrExtension,
1239 			String searchInNameOrExtension,String browseMode) throws Exception{
1240 		String type = null;
1241 		List res = searchGroups(s, query, from,searchInDisplayNameOrExtension,searchInNameOrExtension);
1242 		if (res != null)
1243 			return res;
1244 		List returnRes = new ArrayList();
1245 		Set allowedSet = null;
1246 		if ("All".equals(browseMode)) {
1247 			return res;
1248 		} else if ("".equals(browseMode)) {
1249 			allowedSet = GrouperHelper.getMembershipsSet(s);
1250 		} else if ("Manage".equals(browseMode)) {
1251 			allowedSet = GrouperHelper.getGroupsForPrivileges(s,
1252 					new String[] { "admin", "update",
1253 							"read" });
1254 		} else if ("Join".equals(browseMode)) {
1255 			allowedSet = GrouperHelper.getGroupsForPrivileges(s,
1256 					new String[] { "optin" });
1257 		}
1258 		if (allowedSet != null) {
1259 			Map allowed = new HashMap();
1260 			Iterator it = allowedSet.iterator();
1261 			Group group;
1262 			while (it.hasNext()) {
1263 				group = (Group) it.next();
1264 				allowed.put(group.getUuid(),Boolean.TRUE);
1265 			}
1266 			
1267 			for (int i = 0; i < res.size(); i++) {
1268 				group = (Group) res.get(i);
1269 				if (allowed.containsKey(group.getUuid()))
1270 					returnRes.add(group);
1271 			}
1272 		}
1273 		return returnRes;
1274 	}
1275 
1276 	/*
1277 	 * public static List getNestedStemChildren(GrouperSession s,String stem) {
1278 	 * return Group.getNestedChildren(s,stem); }
1279 	 */
1280 
1281 	/**
1282 	 * Given a simple query and scoping stem and attribute, search for matching stems and return as List
1283 	 * @param s GrouperSession for authenticated user
1284 	 * @param query to search for
1285 	 * @param from stem which scopes search
1286 	 * @param attr name of attribute to search
1287 	 * @return List of stems matched
1288 	 */
1289 	public static List searchStemsByAttribute(GrouperSession s, String query, String from,String attr) {
1290 			
1291 			return new ArrayList();
1292 			/*String type = null;
1293 
1294 			GrouperQuery grouperQuery = new GrouperQuery(s);
1295 			
1296 
1297 			if (from == null && !grouperQuery.stemAttr(attr,query)) {
1298 				List empty = new ArrayList();
1299 				return empty;
1300 			}
1301 			if (from != null && !grouperQuery.stemAttr(from,attr,query)) {
1302 				List empty = new ArrayList();
1303 				return empty;
1304 			}
1305 
1306 			List res = grouperQuery.getStems();
1307 			return res;*/
1308 		
1309 	}
1310 	
1311 	
1312 	/**
1313 	 * Given a simple query and scoping stem search for matching stems and return as List
1314 	 * @param s GrouperSession for authenticated user
1315 	 * @param query to search for
1316 	 * @param from stem which scopes search
1317 	 * @param searchInDisplayNameOrExtension name=displayName / extemsion=displayExtension
1318 	 * @param searchInNameOrExtension name=name / extemsion=extension
1319 	 * @return List of stems matched
1320 	 */
1321 	public static List searchStems(GrouperSession s, String query, String from,String searchInDisplayNameOrExtension,String searchInNameOrExtension) throws StemNotFoundException,QueryException{
1322 		GrouperQuery q = GrouperQuery.createQuery(s,new StemNameAnyFilter(query,StemFinder.findByName(s,from)));
1323 		Set res = q.getStems();
1324 		List displayResults = new ArrayList(res);
1325 		/*List nonDisplayResults=null; 
1326 		String attr = null;
1327 		if(!"".equals(searchInDisplayNameOrExtension)) {
1328 			if("name".equals(searchInDisplayNameOrExtension)) {
1329 				attr="displayName";
1330 			}else{
1331 				attr="displayExtension";
1332 			}
1333 			displayResults = searchStemsByAttribute(s,query,from,attr);	
1334 		}
1335 		if(!"".equals(searchInNameOrExtension)) {
1336 			if("name".equals(searchInNameOrExtension)) {
1337 				attr="name";
1338 			}else{
1339 				attr="extension";
1340 			}
1341 			nonDisplayResults = searchStemsByAttribute(s,query,from,attr);	
1342 		}
1343 		if(displayResults==null && nonDisplayResults==null) return new ArrayList();
1344 		if(displayResults==null && nonDisplayResults!=null) return nonDisplayResults;
1345 		if(displayResults!=null && nonDisplayResults==null) return displayResults;
1346 		Object obj;
1347 		for(int i=0;i<nonDisplayResults.size();i++) {
1348 			obj = nonDisplayResults.get(i);
1349 			if(!displayResults.contains(obj)) displayResults.add(obj);
1350 		}
1351 		*/
1352 		return displayResults;
1353 		
1354 		
1355 	}
1356 
1357 	/**
1358 	 * Given a GrouperSession s, determine all the GrouperGroups s.subject()
1359 	 * is a member of and return a Set of GrouperGroups
1360 	 * 
1361 	 * @param s GrouperSession for authenticated user
1362 	 * @return Set of GrouperGroups
1363 	 */
1364 	public static Set<Group> getMembershipsSet(GrouperSession s) {
1365 		return getMembershipsSet(s, 0, 100000, null);
1366 
1367 	}
1368 	
1369 	
1370 	/**
1371 	 * Given a GrouperSession s, determine all the GrouperGroups s.subject()
1372 	 * is a member of and return a Map where the keys are GrouperGroup keys
1373 	 * 
1374 	 * @param s GrouperSession for authenticated user
1375 	 * @return Map where keys are GrouperGroup keys
1376 	 */
1377 	public static Map getMemberships(GrouperSession s) {
1378 		Map memberships = null;
1379 							   
1380 
1381 		memberships = new HashMap();
1382 		Member member = null;
1383 		try {
1384 			member = MemberFinder.findBySubject(s, s.getSubject());
1385 		} catch (Exception e) {
1386 			throw new RuntimeException(e);
1387 		}
1388 		Set vals = member.getGroups();
1389 		Group group;
1390 		Iterator it = vals.iterator();
1391 		while(it.hasNext()){
1392 			
1393 			group = (Group) it.next();
1394 			memberships.put(group.getUuid(), Boolean.TRUE);
1395 		}
1396 
1397 		return memberships;
1398 	}
1399 	
1400 	
1401 	/**
1402 	 * Given a GrouperSession s, return a subset of Groups where
1403 	 * s.subject is a member, determined by start and pageSize.<p/>
1404 	 * totalCount is a dubious means to return a second value to allow the UI
1405 	 * to page results
1406 	 * 
1407 	 * @param s GrouperSession for authenticated user
1408 	 * @param start where subset begins
1409 	 * @param pageSize no of groups to return
1410 	 * @param totalCount number of overall results
1411 	 * @return Set - subset of groups
1412 	 */
1413 	public static Set<Group> getMembershipsSet(GrouperSession s, int start,
1414 			int pageSize, StringBuffer totalCount) {
1415 		Set memberships = new LinkedHashSet();
1416 		Member member = null;
1417 		try {
1418 			member = MemberFinder.findBySubject(s, s.getSubject());
1419 		} catch (Exception e) {
1420 			throw new RuntimeException(e);
1421 		}
1422 		Set vals = member.getGroups();
1423 		
1424 		Group group;
1425 		int end = start + pageSize;
1426 		if (end > vals.size())
1427 			end = vals.size();
1428 		if (totalCount != null) {
1429 			totalCount.setLength(0);
1430 			totalCount.append("" + vals.size());
1431 		}
1432 		
1433 		Iterator it = vals.iterator();
1434 		while(it.hasNext()){
1435 			
1436 			group = (Group) it.next();
1437 			memberships.add(group);
1438 		}
1439 		return memberships;
1440 	}
1441 
1442 	/**
1443 	 * Given a GrouperSession s, and an array of privileges, get all groups
1444 	 * where s.subject() has atleast one of the privileges
1445 	 * 
1446 	 * @param s GrouperSession for authenticated user
1447 	 * @param privs privileges to test
1448 	 * @return Set of Grouper Groups 
1449 	 */
1450 	public static Set<Group> getGroupsForPrivileges(GrouperSession s, String[] privs) throws MemberNotFoundException{
1451 
1452 		Set<Group> groups = getGroupsForPrivileges(s, privs, 0, 100000, null);
1453 		
1454 		return groups;
1455 	}
1456 
1457 		
1458 	/**
1459 	 * Given a GrouperSession s, and an array of privileges, get subset of groups
1460 	 * where s.subject() has atleast one of the privileges, determined by start and pageSize<p/>
1461 	 * resultCount is a dubious means to return a second value to allow the UI
1462 	 * to page results
1463 	 * 
1464 	 * @param s GrouperSession for authenticated user
1465 	 * @param privs privileges to test
1466 	 * @param start of subset
1467 	 * @param pageSize number of GrouperGroups to return
1468 	 * @param resultCount overall number of GrouperGroups
1469 	 * @return Set - subset of GrouperGroups
1470 	 */
1471 	public static Set<Group> getGroupsForPrivileges(GrouperSession s, String[] privs,
1472 			int start, int pageSize, StringBuffer resultCount) throws MemberNotFoundException{
1473 		
1474 		Set groupSet = new LinkedHashSet();
1475 		
1476 		Set allSet = new LinkedHashSet();
1477 		
1478 		
1479 		Member member = MemberFinder.findBySubject(s,s.getSubject());
1480 		for (int i = 0; i < privs.length; i++) {
1481 			allSet.addAll(getGroupsWhereMemberHasPriv(member,privs[i]));
1482 		}
1483 
1484 		int end = start + pageSize;
1485 		if (end > allSet.size())
1486 			end = allSet.size();
1487 		if (resultCount != null) {
1488 			resultCount.setLength(0);
1489 			resultCount.append("" + allSet.size());
1490 		}
1491 		
1492 		Iterator it = allSet.iterator();
1493 		Group group = null;
1494 		Object obj;
1495 		while(it.hasNext()){
1496 				obj = it.next();
1497 				if(obj instanceof Group) {
1498 				  groupSet.add(obj);
1499 				}
1500 		}
1501 		return groupSet;
1502 	}
1503 
1504 	/**
1505 	 * Given a GrouperSession s, and an array of privileges, get all stems
1506 	 * where s.subject() has atleast one of the privileges
1507 	 * 
1508 	 * @param s GrouperSession for authenticated user
1509 	 * @param privs privileges to test
1510 	 * @return Set of GrouperStems
1511 	 */
1512 	public static Set getStemsForPrivileges(GrouperSession s, String[] privs) throws MemberNotFoundException{
1513 
1514 		Set groups = null;//Cache.instance().getSet(s,sb.toString());
1515 		if (groups != null)
1516 			return null;
1517 
1518 		groups = getStemsForPrivileges(s, privs, 0, 100000, null);
1519 		//Cache.instance().put(s,sb.toString(),groups);
1520 		return groups;
1521 
1522 	}
1523 
1524 	/**
1525 	 * Given a GrouperSession s, and an array of privileges, get subset of stems
1526 	 * where s.subject() has atleast one of the privileges, determined by start and pageSize<p/>
1527 	 * resultCount is a dubious means to return a second value to allow the UI
1528 	 * to page results
1529 	 * 
1530 	 * @param s GrouperSession for authenticated user
1531 	 * @param privs privileges to test
1532 	 * @param start where subset begins
1533 	 * @param pageSize number of GrouperStems to return
1534 	 * @param resultCount overall number of GrouperStems
1535 	 * @return Set of stems where session subject has one or more of Naming privileges specified by privs
1536 	 */
1537 	public static Set getStemsForPrivileges(GrouperSession s, String[] privs,
1538 			int start, int pageSize, StringBuffer resultCount) throws MemberNotFoundException{
1539 
1540 		
1541 		Set stemSet = new LinkedHashSet();
1542 		Set allSet = new LinkedHashSet();
1543 		
1544 		Member member = MemberFinder.findBySubject(s,s.getSubject());
1545 		for (int i = 0; i < privs.length; i++) {
1546 			allSet.addAll(getGroupsOrStemsWhereMemberHasPriv(member,privs[i]));
1547 		}
1548 		int end = start + pageSize;
1549 		if (end > allSet.size())
1550 			end = allSet.size();
1551 		if (resultCount != null) {
1552 			resultCount.setLength(0);
1553 			resultCount.append("" + allSet.size());
1554 		}
1555 		
1556 		Iterator it = allSet.iterator();
1557 		Stem stem = null;
1558 		while(it.hasNext()){
1559 			stem = (Stem) it.next();
1560 			stemSet.add(stem);
1561 		}
1562 		return stemSet;
1563 	}
1564 	
1565 	
1566 	/**
1567 	 * Given a GrouperStem delete it and any children
1568 	 * TODO remove - redundant
1569 	 * @param s GrouperSession for authenticated user
1570 	 * @param stem GrouperStem to delete
1571 	 * @return boolean indicating success
1572 	 * @throws Exception
1573 	 */
1574 	private static boolean stemDelete(GrouperSession s, Stem stem)
1575 			throws Exception {
1576 		if (stem == null || !stem.hasStem(s.getSubject())) {
1577 			return false;
1578 		}
1579 		String stemStr = stem.getName() + HIER_DELIM;
1580 		//@TODO: when searching scoped by stem fix
1581 		List children = new ArrayList();//getNestedStemChildren(s,stemStr);
1582 		if (children.size() > 100)
1583 			throw new Exception("Too many children (" + children.size()
1584 					+ ") - must be <=100");
1585 		Object[] res;
1586 		Group g = null;
1587 		boolean deleted = true;
1588 		GrouperSession sysSession = null;
1589 		try {
1590 			sysSession = GrouperSession.start(SubjectFinder.findById("GrouperSystem"));
1591 		} catch (Exception e) {
1592 			throw new RuntimeException(e);
1593 		}
1594 		for (int i = 0; i < children.size(); i++) {
1595 			res = (Object[]) children.get(i);
1596 			g = (Group) res[1];
1597 			if (!groupDelete(sysSession, GroupOrStem.findByGroup(s,g))) {
1598 				sysSession.stop();
1599 				return false;
1600 			}
1601 		}
1602 
1603 		sysSession.stop();
1604 		return groupDelete(s, GroupOrStem.findByStem(s,stem));
1605 	}
1606 	
1607 	/**
1608 	 * Given a GrouperGroup or GroupeStem delete it. GroupeStem must not have any children.
1609 	 * 
1610 	 * @param s GrouperSession for authenticated user
1611 	 * @param groupOrStem GrouperGroup or GrouperStem to delete
1612 	 * @return boolean indicating success
1613 	 */
1614 	public static boolean groupDelete(GrouperSession s, GroupOrStem groupOrStem) 
1615 		throws InsufficientPrivilegeException,MemberNotFoundException,
1616 		SubjectNotFoundException,MemberDeleteException,SessionException{
1617 		Group group = groupOrStem.getGroup();
1618 		Stem stem = groupOrStem.getStem();
1619 		boolean deleted = true;
1620 		if (groupOrStem == null)
1621 			return false;
1622 		if (groupOrStem.isStem()) {
1623 			if(!stem.hasStem(s.getSubject())) {
1624 
1625 				return false;
1626 			}
1627 			try {
1628 				//Stem.delete(s, stem);
1629 			} catch (Exception e) {
1630 				deleted = false;
1631 			}
1632 			return deleted;
1633 		} else {
1634 			
1635 			if (!group.hasAdmin(s.getSubject())) {
1636 				return false;
1637 			}
1638 		}
1639 
1640 		Set memberships = group.getMemberships();//Eff?
1641 		Member member;
1642 		Iterator it = memberships.iterator();
1643 		while(it.hasNext()) {
1644 			member = (Member) it.next();
1645 			try {
1646 				group.deleteMember(member.getSubject());
1647 				//group.listDelVal(member);
1648 			} catch (RuntimeException e) {
1649 				if (!"List value does not exist".equals(e.getMessage()))
1650 					throw e;
1651 			}
1652 		}
1653 
1654 		/*
1655 		 * members = group.listVals();
1656 		 * 
1657 		 * for(int i=0;i <members.size();i++) { member = ((GrouperList)
1658 		 * members.get(i)).member(); try { group.listDelVal(member);
1659 		 * }catch(RuntimeException e) { if(!"List value does not
1660 		 * exist".equals(e.getMessage())) throw e; }
1661 		 *  }
1662 		 */
1663 		GrouperSession sysSession = null;
1664 		try {
1665 			sysSession = GrouperSession.start(SubjectFinder.findById("GrouperSystem"));
1666 		} catch (Exception e) {
1667 			throw new RuntimeException(e);
1668 		}
1669 
1670 		Member groupAsMember = null;
1671 		try {
1672 			groupAsMember = MemberFinder.findBySubject(s, SubjectFinder.findById(group.getUuid(), "group"));
1673 		} catch (Exception e) {
1674 			throw new RuntimeException(e);
1675 		}
1676 		/*for (int j = 0; j < listNames.length; j++) {
1677 			String list = listNames[j];
1678 			memberships = groupAsMember.;
1679 			GrouperGroup memberOf;
1680 			for (int i = 0; i < memberships.size(); i++) {
1681 				memberOf = (GrouperGroup) ((GrouperList) memberships.get(i))
1682 						.group();
1683 				//memberOf =
1684 				// (GrouperGroup)GrouperGroup.loadByKey(s,memberOf.key());
1685 				String type = memberOf.type();
1686 				memberOf.listDelVal(groupAsMember, list);
1687 			}
1688 		}*/
1689 		sysSession.stop();
1690 
1691 		try {
1692 			//Group.delete(s, group);
1693 		} catch (Exception e) {
1694 			deleted = false;
1695 		}
1696 		return deleted;
1697 	}
1698 
1699 	/**
1700 	 * Given a PersonalStem create stem in correct location - depends on
1701 	 * configuration. PersonalStem is an Interface and new implemetations may be
1702 	 * 'plugged' into the UI
1703 	 * 
1704 	 * @param s GrouperSession for authenticated user
1705 	 * @param ps PersonalStem
1706 	 * @return GrouperStem created
1707 	 * @throws Exception
1708 	 */
1709 	public static Stem createIfAbsentPersonalStem(GrouperSession s,
1710 			PersonalStem ps) throws Exception {
1711 		if (s == null)
1712 			return null;
1713 		GrouperSession sysSession = null;
1714 		try {
1715 			sysSession = GrouperSession.start(SubjectFinder.findById("GrouperSystem"));
1716 		} catch (Exception e) {
1717 			throw new RuntimeException(e);
1718 		}
1719 
1720 		String stemName = ps.getPersonalStemId(s.getSubject());
1721 		String parentName=ps.getPersonalStemRoot(s.getSubject());
1722 		Stem parent = null;
1723 		String childName = null;
1724 		if(NS_ROOT.equals(parentName)||"".equals(parentName)) {
1725 			parent = StemFinder.findRootStem(sysSession);
1726 			childName=stemName;
1727 		}else{
1728 			try{
1729 				childName=parentName + HIER_DELIM + stemName;
1730 				parent = StemFinder.findByName(sysSession,parentName);
1731 				
1732 			}catch(StemNotFoundException e){
1733 				throw new IllegalStateException("Cannot find parent stem for personal stem: " + childName);
1734 			}
1735 		}
1736 		
1737 		Stem stem = null;
1738 		
1739 		try{
1740 			stem=StemFinder.findByName(sysSession, childName);
1741 		}catch(Exception e){}
1742 		
1743 		if (stem == null) {
1744 			
1745 			stem = parent.addChildStem(stemName,ps.getPersonalStemDisplayName(s
1746 					.getSubject()));
1747 			
1748 			stem.setDescription(ps.getPersonalStemDescription(s
1749 					.getSubject()));
1750 			stem.store();
1751 
1752 			stem.grantPriv(s.getSubject(),Privilege.getInstance("create"));
1753 			stem.grantPriv(s.getSubject(),Privilege.getInstance("stemAdmin"));
1754 			sysSession.stop();
1755 		}
1756 		return stem;
1757 	}
1758 	
1759 	/**
1760 	 * Query Subject API for sources and determine which ones return 'people'
1761 	 * @return List of Sources
1762 	 * @throws Exception
1763 	 */
1764 	public static synchronized List getPersonSources() throws Exception {
1765 		if (personSources != null)
1766 			return personSources;
1767 		personSources = new ArrayList();
1768 		SourceManager sm = SourceManager.getInstance();
1769 		Collection c = sm.getSources();
1770 		Iterator it = c.iterator();
1771 		Source source = null;
1772 		Iterator typesIterator = null;
1773 		String subjectType;
1774 		while (it.hasNext()) {
1775 			source = (Source) it.next();
1776 			Set subjectTypes = source.getSubjectTypes();
1777 			typesIterator = subjectTypes.iterator();
1778 			while (typesIterator.hasNext()) {
1779 				subjectType = (String) ((SubjectType) typesIterator.next())
1780 						.getName();
1781 				if (subjectType.equals("person"))
1782 					personSources.add(source);
1783 			}
1784 		}
1785 		return personSources;
1786 	}
1787 	
1788 	/**
1789 	 * API lets you get all memberships - this filters them for a specific group
1790 	 * @param s
1791 	 * @param subject
1792 	 * @param group
1793 	 * @return List with one item for each different way subject is a member of the specified list for the specified group
1794 	 * @throws MemberNotFoundException
1795 	 * @throws GroupNotFoundException
1796 	 * @throws SchemaException
1797 	 * @throws CompositeNotFoundException
1798 	 */
1799 	
1800 	public static List getAllWaysInWhichSubjectIsMemberOFGroup(GrouperSession s,Subject subject,Group group,Field field) 
1801 		throws MemberNotFoundException,GroupNotFoundException,SchemaException,CompositeNotFoundException{
1802 		List ways = new ArrayList();
1803 		Member member = MemberFinder.findBySubject(s,subject);
1804 		Set memberships = member.getMemberships(field);
1805 		Membership gl;
1806 		Iterator it = memberships.iterator();
1807 		while(it.hasNext()) {
1808 			gl = (Membership) it.next();
1809 			//gl.setSession(s);
1810 			if(gl.getGroup().getUuid().equals(group.getUuid())) {
1811 				ways.add(gl);
1812 				/*if(group.hasComposite() && field.getName().equals("members")) {
1813 					fixCompositeMembership(s,gl,subject,group,field);
1814 				}*/
1815 			}
1816 		}
1817 		return ways;
1818 	}
1819 	
1820 	/*public static void fixCompositeMembership(GrouperSession s,Membership m,Subject subject,Group group,Field field) {
1821 		
1822 			String x="";
1823 			
1824 			if(group.hasComposite() && field.getName().equals("members")) {
1825 				List compositeWays = new ArrayList();
1826 				Composite comp = CompositeFinder.isOwner(group);
1827 				
1828 				compositeWays.addAll(getAllWaysInWhichSubjectIsMemberOFGroup(s,subject,comp.getLeftGroup(),field));
1829 				compositeWays.addAll(getAllWaysInWhichSubjectIsMemberOFGroup(s,subject,comp.getRightGroup(),field));
1830 				Membership pm = null;
1831 				try {
1832 					pm=MembershipFinder.findImmediateMembership(s,group,subject,field);
1833 				}catch (MembershipNotFoundException e) {
1834 					return compositeWays;
1835 				}
1836 				Membership m;
1837 				for(int i=0;i<compositeWays.size();i++) {
1838 					m=null;
1839 					m = (Membership)compositeWays.get(i);
1840 					try {
1841 						if(m.getVia()==null) {
1842 							m.via_id=comp;
1843 						}
1844 					}catch(OwnerNotFoundException e) {
1845 						m.via_id=group;
1846 					}
1847 					
1848 					try {
1849 						if(m.getParentMembership()==null) {
1850 							//m.parent_membership=pm;
1851 						}
1852 					}catch(MembershipNotFoundException e) {
1853 						//m.parent_membership=pm;
1854 					}
1855 				}
1856 				return compositeWays;
1857 			
1858 		
1859 	}}*/
1860 	
1861 	/**
1862 	 * Returns indirect privileges for member on the group or stem
1863 	 * @param s
1864 	 * @param groupOrStem
1865 	 * @param member
1866 	 * @return Map keyed on privilege name forindirect privileges for member on the group or stem, and how derived
1867 	 */
1868 	public static Map getExtendedHas(GrouperSession s,GroupOrStem groupOrStem,Member member) throws SchemaException{
1869 		return getExtendedHas(s,groupOrStem,member,FieldFinder.find("members"));
1870 	}
1871 	
1872 	/**
1873 	 * Returns indirect privileges for member on the group or stem
1874 	 * @param s
1875 	 * @param groupOrStem
1876 	 * @param member
1877 	 * @return Map keyed on privilege name for indirect privileges for member on the group or stem, and how derived
1878 	 */
1879 	public static Map getExtendedHas(GrouperSession s,GroupOrStem groupOrStem,Member member,Field field) throws SchemaException{
1880 		Map map  =getAllHas(s,groupOrStem,member,field);
1881 		
1882 		map.remove("subject");
1883 		map.remove("effectivePrivs");
1884 		return map;
1885 		
1886 	}
1887 	
1888 	/**
1889 	 * Returns indirect privileges for member on the group or stem - but not how derived
1890 	 * @param s
1891 	 * @param groupOrStem
1892 	 * @param member
1893 	 * @return Map keyed on name of privs which are indirectly assigned
1894 	 */
1895 	public static Map getEffectiveHas(GrouperSession s,GroupOrStem groupOrStem,Member member,Field field) throws SchemaException{
1896 		Map map  =getAllHas(s,groupOrStem,member,field);
1897 
1898 		return (Map)map.get("effectivePrivs");
1899 		
1900 	}
1901 	
1902 	/**
1903 	 * Returns direct privileges for member on group or stem
1904 	 * @param s
1905 	 * @param groupOrStem
1906 	 * @param member
1907 	 * @return Map keyed on name of privs which are directly assigned
1908 	 */
1909 	public static Map getImmediateHas(GrouperSession s,GroupOrStem groupOrStem,Member member) throws SchemaException{
1910 		Map map = getAllHas(s,groupOrStem,member);
1911 		
1912 		return (Map)map.get("subject");
1913 		
1914 	}
1915 	
1916 	/**
1917 	 * Returns direct privileges for member on group or stem
1918 	 * @param s
1919 	 * @param groupOrStem
1920 	 * @param member
1921 	 * @param field
1922 	 * @return Map keyed on name of privs which are directly assigned
1923 	 * @throws SchemaException
1924 	 */
1925 	public static Map getImmediateHas(GrouperSession s,GroupOrStem groupOrStem,Member member,Field field) throws SchemaException{
1926 		Map map = getAllHas(s,groupOrStem,member,field);
1927 		
1928 		return (Map)map.get("subject");
1929 		
1930 	}
1931 	
1932 	/**
1933 	 * Returns all privileges, direct and indirect, that member has for group or stem
1934 	 * @param s
1935 	 * @param groupOrStem
1936 	 * @param member
1937 	 * @return Map keyed on privilege names - whether direct or indirect
1938 	 * @throws SchemaException
1939 	 */
1940 	
1941 	public static Map getAllHas(GrouperSession s,GroupOrStem groupOrStem,Member member) throws SchemaException{
1942 		return getAllHas(s,groupOrStem,member,FieldFinder.find("members"));
1943 	}
1944 	
1945 	/**
1946 	 * Returns all privileges, direct and indirect, that member has for group or stem
1947 	 * @param s
1948 	 * @param groupOrStem
1949 	 * @param member
1950 	 * @return Map keyed on privilege names - whether direct or indirect
1951 	 * @throws SchemaException
1952 	 */
1953 	public static Map getAllHas(GrouperSession s,GroupOrStem groupOrStem,Member member,Field field) throws SchemaException{
1954 		Set allPrivs = null;
1955 		Map effectivePrivs = new HashMap();
1956 		Map effectiveMemberships = new HashMap();
1957 		if(groupOrStem.isGroup()) {
1958 			allPrivs = member.getPrivs(groupOrStem.getGroup());
1959 			try {
1960 				effectiveMemberships = getEffectiveMembershipsForGroupAndSubject(s,groupOrStem.getGroup(),member.getSubject(),field);
1961 			}catch(Exception e){}
1962 		}else{
1963 			allPrivs = member.getPrivs(groupOrStem.getStem());
1964 		}
1965 		 
1966 		Map results = new LinkedHashMap();
1967 		Map privs;
1968 		AccessPrivilege priv = null;
1969 		NamingPrivilege nPriv=null;
1970 		String key="subject";
1971 		results.put(key,new HashMap());
1972 		List tmpList = new ArrayList();
1973 		Iterator it = allPrivs.iterator();
1974 		boolean isEffective = false;
1975 		if(groupOrStem.isGroup() && member.isImmediateMember(groupOrStem.getGroup(),field)) {
1976 			privs = new HashMap();
1977 			privs.put("member",Boolean.TRUE);
1978 			results.put("subject",privs);
1979 		}
1980 		
1981 		while(it.hasNext()) {
1982 			if(groupOrStem.isGroup()) {
1983 				priv = (AccessPrivilege)it.next();
1984 				
1985 				if(member.getSubjectId().equals(priv.getOwner().getId())) {
1986 					key="subject";
1987 					isEffective = false;
1988 				}else{
1989 					key=priv.getOwner().getId();
1990 					isEffective = true;
1991 				}
1992 				privs = (Map)results.get(key);
1993 				if(privs==null) {
1994 					privs=new HashMap();
1995 					results.put(key,privs);
1996 				}
1997 					if(isEffective) {
1998 						try{
1999 							privs.put("group",group2Map(s,GroupFinder.findByUuid(s,priv.getOwner().getId())));
2000 							privs.put(priv.getName(),Boolean.TRUE);
2001 							if(effectiveMemberships.containsKey(priv.getOwner())) {
2002 								privs.put("member",Boolean.TRUE);
2003 								effectiveMemberships.remove(priv.getOwner());
2004 							}
2005 						}catch(GroupNotFoundException e){}
2006 						effectivePrivs.put(priv.getName(),Boolean.TRUE);
2007 					}
2008 					
2009 				
2010 				privs.put(priv.getName()
2011 						,Boolean.TRUE);
2012 			}else{
2013 				nPriv = (NamingPrivilege)it.next();
2014 				
2015 				if(member.getSubjectId().equals(nPriv.getOwner().getId())) {
2016 					key="subject";
2017 					isEffective = false;
2018 				}else{
2019 					key=nPriv.getOwner().getId();
2020 					isEffective = true;
2021 				}
2022 					privs = (Map)results.get(key);
2023 					if(privs==null) {
2024 						privs=new HashMap();
2025 						results.put(key,privs);
2026 					}
2027 						if(isEffective) {
2028 							try{
2029 								if(effectiveMemberships.containsKey(nPriv.getOwner())) {
2030 									privs.put("member",Boolean.TRUE);
2031 									effectiveMemberships.remove(nPriv.getOwner());
2032 								}
2033 								privs.put("group",group2Map(s,GroupFinder.findByUuid(s,nPriv.getOwner().getId())));
2034 							}catch(GroupNotFoundException e){}
2035 							effectivePrivs.put(nPriv.getName(),Boolean.TRUE);
2036 						}
2037 						
2038 					
2039 					privs.put(nPriv.getName(),Boolean.TRUE);
2040 			}
2041 		}
2042 		Map.Entry entry;
2043 		it = effectiveMemberships.entrySet().iterator();
2044 		Group effGroup;
2045 		while(it.hasNext()) {
2046 			entry = (Map.Entry)it.next();
2047 			effGroup = (Group)entry.getKey();
2048 			privs=(Map)results.get(effGroup.getUuid());
2049 			if(privs==null) {
2050 				privs=new HashMap();
2051 				privs.put("group",group2Map(s,effGroup));
2052 				privs.put("member",Boolean.TRUE);
2053 				results.put(effGroup.getUuid(),privs);
2054 			}
2055 			
2056 		}
2057 		results.put("effectivePrivs",effectivePrivs);
2058 		return results;
2059 		
2060 	}
2061 	
2062 	/**
2063 	 * Given a Group and Subject return the effective memberships keyed on
2064 	 * the via group
2065 	 * @param s
2066 	 * @param group
2067 	 * @param subject
2068 	 * @param field
2069 	 * @return Map keyed on via groups
2070 	 * @throws Exception
2071 	 */
2072 	public static Map getEffectiveMembershipsForGroupAndSubject(GrouperSession s,Group group,Subject subject,Field field) throws Exception{
2073 		Member member = MemberFinder.findBySubject(s,subject);
2074 		Map res = new HashMap();
2075 		Set memberships = member.getEffectiveMemberships(field);
2076 		Membership m;
2077 		Iterator it = memberships.iterator();
2078 		while(it.hasNext()){
2079 			m = (Membership)it.next();
2080 			if(m.getGroup().equals(group)) res.put(m.getViaGroup(),m);
2081 		}
2082 		
2083 		return res;
2084 	}
2085 	
2086 	/**
2087 	 * Given priv name return subjects with that privilege for group
2088 	 * @param group
2089 	 * @param privilege
2090 	 * @return Set of subjects with specified privilege for specified group
2091 	 */
2092 	public static Set getSubjectsWithPriv(Group group,String privilege) {
2093 		if(privilege.equals("admin")) return group.getAdmins();
2094 		if(privilege.equals("update")) return group.getUpdaters();
2095 		if(privilege.equals("read")) return group.getReaders();
2096 		if(privilege.equals("view")) return group.getViewers();
2097 		if(privilege.equals("optin")) return group.getOptins();
2098     if(privilege.equals("optout")) return group.getOptouts();
2099     if(privilege.equals("groupAttrRead")) return group.getGroupAttrReaders();
2100     if(privilege.equals("groupAttrUpdate")) return group.getGroupAttrUpdaters();
2101 		return new HashSet();
2102 	}
2103 	
2104 	/**
2105 	 * Given a privilege return all the groups or stems where member has that privilege
2106 	 * @param member
2107 	 * @param privilege
2108 	 * @return Set of groups where specified member has the specified privilege
2109 	 */
2110 	public static Set getGroupsOrStemsWhereMemberHasPriv(Member member,String privilege) {
2111 		if(privilege.equals("admin")) return member.hasAdmin();
2112 		if(privilege.equals("update")) return member.hasUpdate();
2113 		if(privilege.equals("read")) return member.hasRead();
2114 		if(privilege.equals("view")) return member.hasView();
2115 		if(privilege.equals("optin")) return member.hasOptin();
2116 		if(privilege.equals("optout")) return member.hasOptout();
2117     if(privilege.equals("groupAttrRead")) return member.hasGroupAttrRead();
2118     if(privilege.equals("groupAttrUpdate")) return member.hasGroupAttrUpdate();
2119 		if(privilege.equals("create")) return member.hasCreate();
2120 		if(privilege.equals("stemAdmin")) return member.hasStemAdmin();
2121     if(privilege.equals("stemAttrRead")) return member.hasStemAttrRead();
2122     if(privilege.equals("stemAttrUpdate")) return member.hasStemAttrUpdate();
2123 		return new HashSet();
2124 	}
2125 	
2126 	/**
2127 	 * Given a privilege return all the groups where member has that privilege
2128 	 * @param member
2129 	 * @param privilege
2130 	 * @return Set of groups where specified member has the specified privilege
2131 	 */
2132 	public static Set getGroupsWhereMemberHasPriv(Member member,String privilege) {
2133 		if(privilege.equals("admin")) return member.hasAdmin();
2134 		if(privilege.equals("update")) return member.hasUpdate();
2135 		if(privilege.equals("read")) return member.hasRead();
2136 		if(privilege.equals("view")) return member.hasView();
2137 		if(privilege.equals("optin")) return member.hasOptin();
2138 		if(privilege.equals("optout")) return member.hasOptout();
2139     if(privilege.equals("groupAttrRead")) return member.hasGroupAttrRead();
2140     if(privilege.equals("groupAttrUpdate")) return member.hasGroupAttrUpdate();
2141 		return new HashSet();
2142 	}
2143 	
2144 	/**
2145 	 * Given a privilege return all the stems where member has that privilege
2146 	 * @param member
2147 	 * @param privilege
2148 	 * @return Set of groups where specified member has the specified privilege
2149 	 */
2150 	public static Set getStemsWhereMemberHasPriv(Member member,String privilege) {
2151 
2152 		if(privilege.equals("create")) return member.hasCreate();
2153 		if(privilege.equals("stemAdmin")) return member.hasStemAdmin();
2154     if(privilege.equals("stemAttrRead")) return member.hasStemAttrRead();
2155     if(privilege.equals("stemAttrUpdate")) return member.hasStemAttrUpdate();
2156 		return new HashSet();
2157 	}
2158 	
2159 	/**
2160 	 * Given priv name return subjects with that privilege for stem
2161 	 * @param stem
2162 	 * @param privilege
2163 	 * @return Set of subjects with a specified Nmaing privilege for a specified stem
2164 	 */
2165 	public static Set getSubjectsWithPriv(Stem stem,String privilege) {
2166 		if(privilege.equals("stemAdmin")) return stem.getStemAdmins();
2167 		if(privilege.equals("create")) return stem.getCreators();
2168     if(privilege.equals("stemAttrRead")) return stem.getStemAttrReaders();
2169     if(privilege.equals("stemAttrUpdate")) return stem.getStemAttrUpdaters();
2170 		return new HashSet();
2171 	}
2172 	
2173 	/**
2174 	 * Determine if a given subject has been granted an Access privilege through direct assignment
2175 	 * @param s
2176 	 * @param subject
2177 	 * @param group
2178 	 * @param privilege
2179 	 * @return whether the specified subject has a specified privilege directly assigned for a specified group
2180 	 * @throws MemberNotFoundException
2181 	 */
2182 	public static boolean hasSubjectImmPrivForGroup(GrouperSession s,Subject subject,Group group,String privilege) throws MemberNotFoundException,SchemaException{
2183 		Map privs = getImmediateHas(s,GroupOrStem.findByGroup(s,group),MemberFinder.findBySubject(s,subject));
2184 		return privs.containsKey(privilege);
2185 	}
2186 	
2187 	/**
2188 	 * Determine if a given subject has been granted a Naming privilege through direct assignment
2189 	 * @param s
2190 	 * @param subject
2191 	 * @param stem
2192 	 * @param privilege
2193 	 * @return whether the specified subject has a specified privilege directly assigned for a specified stem
2194 	 * @throws MemberNotFoundException
2195 	 */
2196 	public static boolean hasSubjectImmPrivForStem(GrouperSession s,Subject subject,Stem stem,String privilege) throws MemberNotFoundException,SchemaException{
2197 		Map privs = getImmediateHas(s,GroupOrStem.findByStem(s,stem),MemberFinder.findBySubject(s,subject));
2198 		return privs.containsKey(privilege);
2199 	}
2200 	
2201 	/**
2202 	 * Return the path by which this Membership is derived
2203 	 * @param s
2204 	 * @param m
2205 	 * @return List where each element represents a link in the chain of the membership
2206 	 * @throws GroupNotFoundException
2207 	 * @throws MembershipNotFoundException
2208 	 * @throws MemberNotFoundException
2209 	 * @throws SchemaException
2210 	 */
2211 
2212 	public static List getChain(GrouperSession s,Membership m)throws GroupNotFoundException,MembershipNotFoundException,
2213 	MemberNotFoundException,SchemaException,SubjectNotFoundException{
2214 		List chain = new ArrayList();
2215 		Group via = null;
2216 		Composite comp=null;
2217 		Membership pm=null;
2218 		try {
2219 			via = m.getViaGroup();
2220 		}catch(GroupNotFoundException e) {
2221 			//Should be an immediate member, but check for composite
2222 			return chain;
2223 		}
2224 		try {
2225 			comp = CompositeFinder.findAsOwner(via);
2226 		}catch(Exception me) {
2227 			
2228 		}
2229 		Map groupMap=null;
2230 		if(comp==null) {
2231 			groupMap=GrouperHelper.group2Map(s,via);
2232 		}else{
2233 			groupMap=GrouperHelper.getCompositeMap(s,comp);
2234 		}
2235 		Map viaMap = groupMap;
2236 		groupMap.put("listField","members");
2237 		chain.add(groupMap);
2238 		pm = null;
2239 		Group g=null;
2240 		try {
2241 			pm=m.getParentMembership();
2242 		}catch(MembershipNotFoundException e) {
2243 			
2244 		}
2245 		
2246 		while(pm!=null) {
2247 			if(!pm.getMember().getSubjectId().equals(via.getUuid())) {
2248 				g = GroupFinder.findByUuid(s,pm.getMember().getSubjectId());
2249 				groupMap=GrouperHelper.group2Map(s,g);
2250 				groupMap.put("listField",pm.getList().getName());
2251 				chain.add(groupMap);	
2252 			}else{
2253 				viaMap.put("listField",pm.getList().getName());
2254 			}
2255 			try {
2256 			pm=pm.getParentMembership();
2257 			}catch(MembershipNotFoundException e){break;}
2258 		}
2259 		return chain;
2260 	}
2261 	
2262 	
2263 	/**
2264 	 * 	Given a composite return a Map for use in Tiles
2265 	 * @param grouperSession
2266 	 * @param comp
2267 	 * @return a Map representing a Composite, for use in Tiles / JSTL
2268 	 * @throws GroupNotFoundException
2269 	 * @throws MemberNotFoundException
2270 	 * @throws SchemaException
2271 	 */
2272 
2273 	public static Map getCompositeMap(GrouperSession grouperSession,Composite comp)
2274 		throws GroupNotFoundException,MemberNotFoundException,SchemaException,SubjectNotFoundException{
2275 		return getCompositeMap(grouperSession,comp,null);
2276 	
2277 	}
2278 	
2279 	/**
2280 	 * Given a composite return a Map for use in Tiles. If a Subject is passed
2281 	 * then the number of ways the Subject is a member of the left / right groups 
2282 	 * is calculated
2283 	 * @param grouperSession
2284 	 * @param comp
2285 	 * @param subj
2286 	 * @return a Map representing the Composite and Membership infor for specified subject
2287 	 * @throws GroupNotFoundException
2288 	 * @throws MemberNotFoundException
2289 	 * @throws SchemaException
2290 	 */
2291 
2292 	public static Map getCompositeMap(GrouperSession grouperSession,Composite comp,Subject subj)
2293 		throws GroupNotFoundException,MemberNotFoundException,SchemaException,SubjectNotFoundException{
2294 		Map compMap = ObjectAsMap.getInstance("Composite", comp);
2295 		compMap.put("leftGroup",new GroupAsMap(comp.getLeftGroup(),grouperSession));
2296 		Map membershipMap=null;
2297 		if(subj !=null) {
2298 			membershipMap = getMembershipAndCount(grouperSession,comp.getLeftGroup(),subj);
2299 			if(comp.getLeftGroup().hasComposite()&& membershipMap !=null) {
2300 				membershipMap.put("viaGroup",compMap);
2301 			}
2302 			((Map)compMap.get("leftGroup")).put("membership",membershipMap);
2303 		}
2304 		compMap.put("rightGroup",new GroupAsMap(comp.getRightGroup(),grouperSession));
2305 		if(subj !=null) {
2306 			membershipMap = getMembershipAndCount(grouperSession,comp.getRightGroup(),subj);
2307 			if(comp.getRightGroup().hasComposite()&& membershipMap !=null) {
2308 				membershipMap.put("viaGroup",compMap);
2309 			}
2310 			((Map)compMap.get("rightGroup")).put("membership",membershipMap);
2311 		}
2312 		compMap.put("compositeType",comp.getType().toString());
2313 		compMap.put("owner",new GroupAsMap(comp.getOwnerGroup(),grouperSession));
2314 		compMap.put("id",comp.getOwnerGroup().getUuid());
2315 		return compMap;
2316 	}
2317 	
2318 	private static Map getMembershipAndCount(GrouperSession s,Group group,Subject subject) throws MemberNotFoundException,SchemaException,SubjectNotFoundException {
2319 		Set memberships = null;
2320 		//memberships = MembershipFinder.findMembershipsNoPrivsNoSession(group,MemberFinder.findBySubject(s,subject),FieldFinder.find("members"));
2321 		memberships=group.getMemberships(FieldFinder.find("members"));
2322 		
2323 		if(memberships.size()==0) return null;
2324 		Iterator it = memberships.iterator();
2325 		Membership m = null;
2326 		Membership selectedM = null;
2327 		int count=0;
2328 		while(it.hasNext()) {
2329 			m=(Membership)it.next();
2330 			if(SubjectHelper.eq(m.getMember().getSubject(),subject)) {
2331 				selectedM=m;
2332 				count++;
2333 			}
2334 		}
2335 		if(selectedM==null) return null;
2336 		Map mMap = ObjectAsMap.getInstance("MembershipAsMap",selectedM);
2337 		mMap.put("noWays",new Integer(count));
2338 		return mMap;
2339 	}
2340 	
2341 	/**
2342 	 * Trims down input so that the 'same' membership does not occur twice
2343 	 * @param memberships
2344 	 * @param type
2345 	 * @param count - keeps track of the number of times a membership occurred
2346 	 * @param sources - keeps track of different sources providing subjects
2347 	 * @return List with one item per subject, but also update specified Map with count of how many memberships a member has
2348 	 * @throws MemberNotFoundException
2349 	 * @throws GroupNotFoundException
2350 	 */
2351 	public static List<Membership> getOneMembershipPerSubjectOrGroup(Set memberships,String type,Map count,Map sources,int membersFilterLimit) 
2352 		throws MemberNotFoundException,GroupNotFoundException{
2353 		//won't pass back values but will give 'unique' list
2354 		if(count==null) count=new HashMap();
2355 		List res = new ArrayList();
2356 		Iterator it = memberships.iterator();
2357 		Membership m;
2358 		String id=null;
2359 		Integer curCount;
2360 		Object obj;
2361 		while(it.hasNext()) {
2362 			obj=it.next();
2363 			if(!(obj instanceof Membership)) {
2364 				res.add(obj);
2365 				continue;
2366 			}
2367 			m = (Membership)obj;
2368 			if("subject".equals(type)){
2369 				id = m.getGroup().getUuid();
2370 			}else if("group".equals(type)) {
2371 				//id =m.getMember().getSubjectId();
2372 				id=m.getMemberUuid();
2373 				
2374 			}else{
2375 				throw new IllegalArgumentException("type must be 'subject' or 'group'");
2376 			}
2377 			curCount=(Integer)count.get(id);
2378 			if(curCount==null) {
2379 				curCount = new Integer(1);
2380 				res.add(m);
2381 			}else{
2382 				curCount = new Integer(curCount.intValue()+1);
2383 			}
2384 			count.put(id,curCount);
2385 			if(memberships.size() < membersFilterLimit) sources.put(m.getMember().getSubjectSource().getId(), m.getMember().getSubjectSource().getName());
2386 		}
2387 		return res;
2388 	}
2389 	
2390 	/**
2391 	 * Given a trimmed list of memberships which are now Maps, add noWays -> number of
2392 	 * direct and indirect memberships
2393 	 * @param membershipMaps
2394 	 * @param type
2395 	 * @param count
2396 	 * @throws GroupNotFoundException
2397 	 * @throws MemberNotFoundException
2398 	 */
2399 	public static void setMembershipCountPerSubjectOrGroup(List membershipMaps,String type,Map count)
2400 		throws GroupNotFoundException,MemberNotFoundException{
2401 		if(count==null) return;
2402 		MembershipAsMap mMap;
2403 		Map gMap;
2404 		//Map sMap;
2405 		
2406 		String id;
2407 		Integer curCount;
2408 		Membership m=null;
2409 		for(int i=0;i<membershipMaps.size();i++) {
2410 			mMap = (MembershipAsMap)membershipMaps.get(i);
2411 			gMap = (Map)mMap.get("group");
2412 			//sMap = (Map)mMap.get("subject");
2413 		
2414 			if("subject".equals(type)){
2415 				id = (String)gMap.get("id");
2416 			}else if("group".equals(type)) {
2417 				//id = (String)sMap.get("memberUuid");
2418 				m=(Membership)mMap.getWrappedObject();
2419 				id=m.getMemberUuid();
2420 			}else{
2421 				throw new IllegalArgumentException("type must be 'subject' or 'group'");
2422 			}
2423 			curCount = (Integer)count.get(id);
2424 			if(curCount!=null) {
2425 				mMap.put("noWays",curCount);
2426 			}
2427 			
2428 		}
2429 		
2430 	}
2431 	
2432 	/**
2433 	 * Checks key groups.create.grant.all to determine pre-selected privs to
2434 	 * be checked in the UI. If not set, checks default assignments in the Grouper API
2435 	 * @param mediaBundle
2436 	 * @return Map keyed on Access privilege names
2437 	 */
2438 
2439 	public static Map getDefaultAccessPrivsForUI(ResourceBundle mediaBundle){
2440 		String privStr = null;
2441 		try {
2442 			privStr = mediaBundle.getString("groups.create.grant.all");
2443 		}catch(Exception e){}
2444 		if(privStr==null || "".equals(privStr)) return getDefaultAccessPrivsForGrouperAPI();
2445 		Map privs = new HashMap();
2446 		if("none".equals(privStr)) return privs;
2447 		String[] privArr = privStr.split(" ");
2448 		for(int i=0;i<privArr.length;i++) {
2449 			privs.put(privArr[i],Boolean.TRUE);
2450 		}
2451 		return privs;
2452 	}
2453 	
2454 	/**
2455 	 * Queries GrouperConfig - grouper.properties - to determine which Access
2456 	 * privs are granted to GrouperAll on group creation
2457 	 * @return Map keyed on default Access privilege names
2458 	 */
2459 	public static Map getDefaultAccessPrivsForGrouperAPI() {
2460 		Map privs = new HashMap();
2461     String priv;
2462 		
2463 		for(int i=0;i<groupPrivs.length;i++){
2464       priv = groupPrivs[i];
2465 
2466 			if("true".equals(GrouperConfig.getProperty("groups.create.grant.all." + priv))){
2467 				privs.put(priv,Boolean.TRUE);
2468 			}
2469 		}
2470 		return privs;
2471 	}
2472 	
2473 	
2474 	/**
2475 	 * Use to get SubjectPrivilegeMaps rather than SubjectMaps. Relevant UI now
2476 	 * uses these objects which can be used for more fine-grained template resolution
2477 	 * @param s
2478 	 * @param subjects
2479 	 * @param group
2480 	 * @param privilege
2481 	 * @return List of SubjectPrivilegeAsMap's for given subjects, group and privilege
2482 	 */
2483 	public static List subjects2SubjectPrivilegeMaps(GrouperSession s,Collection subjects,Group group, String privilege) {
2484 		return subjects2SubjectPrivilegeMaps(s,subjects,GroupOrStem.findByGroup(s,group),privilege);
2485 	}
2486 	
2487 	/**
2488 	 * Use to get SubjectPrivilegeMaps rather than SubjectMaps. Relevant UI now
2489 	 * uses these objects which can be used for more fine-grained template resolution
2490 	 * @param s
2491 	 * @param subjects
2492 	 * @param stem
2493 	 * @param privilege
2494 	 * @return List of SubjectPrivilegeAsMap's for given subjects, stem and privilege
2495 	 */
2496 	public static List subjects2SubjectPrivilegeMaps(GrouperSession s,Collection subjects,Stem stem, String privilege) {
2497 		return subjects2SubjectPrivilegeMaps(s,subjects,GroupOrStem.findByStem(s,stem),privilege);	
2498 	}
2499 	
2500 	/**
2501 	 * Use to get SubjectPrivilegeMaps rather than SubjectMaps. Relevant UI now
2502 	 * uses these objects which can be used for more fine-grained template resolution
2503 	 * @param s
2504 	 * @param subjects
2505 	 * @param groupOrStem
2506 	 * @param privilege
2507 	 * @return List of SubjectPrivilegeAsMap's for given subjects, GroupOrStem and privilege
2508 	 */
2509 	public static List subjects2SubjectPrivilegeMaps(GrouperSession s,Collection subjects,GroupOrStem groupOrStem, String privilege) {
2510 		List res = new ArrayList();
2511 		Subject subject;
2512 		Iterator it = subjects.iterator();
2513 		while(it.hasNext()) {
2514 			subject = (Subject)it.next();
2515 			res.add(ObjectAsMap.getInstance("SubjectPrivilegeAsMap", subject,s,groupOrStem,privilege));
2516 		}
2517 		return res;
2518 	}
2519 	
2520 	/**
2521 	 * Use to get SubjectPrivilegeMaps rather than SubjectMaps. Relevant UI now
2522 	 * uses these objects which can be used for more fine-grained template resolution
2523 	 * @param s
2524 	 * @param groupsOrStems
2525 	 * @param subject
2526 	 * @param privilege
2527 	 * @return List of SubjectPrivilegeAsMap's for given subject, GroupOrStems and privilege
2528 	 */
2529 	public static List subjects2SubjectPrivilegeMaps(GrouperSession s,Collection groupsOrStems,Subject subject, String privilege) {
2530 		List res = new ArrayList();
2531 		GroupOrStem groupOrStem;
2532 		Iterator it = groupsOrStems.iterator();
2533 		Object obj;
2534 		while(it.hasNext()) {
2535 			obj = it.next();
2536 			if(obj instanceof Group){
2537 				res.add(ObjectAsMap.getInstance("SubjectPrivilegeAsMap", subject,s,GroupOrStem.findByGroup(s,(Group)obj),privilege));
2538 			}else{
2539 				res.add(ObjectAsMap.getInstance("SubjectPrivilegeAsMap", subject,s,GroupOrStem.findByStem(s,(Stem)obj),privilege));
2540 			}
2541 		}
2542 		return res;
2543 	}
2544 	
2545 	/**
2546 	 * Use to get MembershipMaps rather than SubjectMaps. Relevant UI now
2547 	 * uses these objects which can be used for more fine-grained template resolution
2548 	 * @param s
2549 	 * @param memberships
2550 	 * @return List of Memberships as Maps
2551 	 */
2552 	public static List memberships2Maps(GrouperSession s,Collection memberships) {
2553 		return memberships2Maps(s,memberships,false);
2554 	
2555 	}
2556 	
2557 	/**
2558 	 * Use to get MembershipMaps rather than SubjectMaps. Relevant UI now
2559 	 * uses these objects which can be used for more fine-grained template resolution
2560 	 * @param s
2561 	 * @param memberships
2562 	 * @param withParents
2563 	 * @return List of Memberships as Maps
2564 	 */
2565 	public static List memberships2Maps(GrouperSession s,Collection memberships,boolean withParents) {
2566 		List res = new ArrayList();
2567 		Membership membership;
2568 		Iterator it = memberships.iterator();
2569 		while(it.hasNext()) {
2570 			membership = (Membership)it.next();
2571 			//TODO check if withParent is needed
2572 			res.add(ObjectAsMap.getInstance("MembershipAsMap",membership)); 
2573 		}
2574 		return res;
2575 	}
2576 	
2577 	
2578 	/**
2579 	 * For a given subject determine all the custom list fields they appear in
2580 	 * @param s
2581 	 * @param subject
2582 	 * @return List of field names the subject is a member of
2583 	 * @throws Exception
2584 	 */
2585 	public static List getListFieldsForSubject(GrouperSession s,Subject subject) throws Exception{
2586 		Set lists = FieldFinder.findAllByType(FieldType.LIST);
2587 		List res = new ArrayList();
2588 		Iterator it = lists.iterator();
2589 		Field field;
2590 		Set memberships;
2591 		while(it.hasNext()) {
2592 			field = (Field)it.next();
2593 			if(!"members".equals(field.getName())) {
2594 				memberships = MemberFinder.findBySubject(s,subject).getMemberships(field);
2595 				if(memberships.size()>0) {
2596 					res.add(field.getName());
2597 				}
2598 			}
2599 		}
2600 		accumulateFields(res);
2601 		return res;
2602 	}
2603 	
2604 	public static Map listOfFieldsToMap(List fields) {
2605 		Map map = new HashMap();
2606 		String name;
2607 		for(int i=0;i<fields.size();i++) {
2608 			name=(String)fields.get(i);
2609 			
2610 			map.put(name,Boolean.TRUE);
2611 		}
2612 		return map;	
2613 	}
2614 	
2615 	/**
2616 	 * For a group id, for all its types, return fields of type LIST which the session user can write
2617 	 * @param s
2618 	 * @param groupId
2619 	 * @return List of list fields for group
2620 	 * @throws Exception
2621 	 */
2622 	public static List getWritableListFieldsForGroup(GrouperSession s,String groupId) throws Exception{
2623 		Group g = GroupFinder.findByUuid(s,groupId);
2624 		return getWritableListFieldsForGroup(s,g);
2625 	}
2626 	
2627 	/**
2628 	 * For a group id, for all its types, return fields of type LIST which the session user can write
2629 	 * @param s
2630 	 * @param g
2631 	 * @return List of list fields for group
2632 	 * @throws Exception
2633 	 */
2634 	public static List getWritableListFieldsForGroup(GrouperSession s,Group g) throws Exception{
2635 		List writable = getListFieldsForGroup(s,g);
2636 		Field field;
2637 		String name;
2638 		Iterator it = writable.iterator();
2639 		while(it.hasNext()) {
2640 			name=(String)it.next();
2641 			field=FieldFinder.find(name);
2642 			if(!g.canReadField(field)) it.remove();
2643 		}
2644 		accumulateFields(writable);
2645 		return writable;
2646 	}
2647 	
2648 	/**
2649 	 * For a group id, for all its types, return fields of type LIST which the session user can read or write
2650 	 * @param s
2651 	 * @param groupId
2652 	 * @return List of list fields for group
2653 	 * @throws Exception
2654 	 */
2655 	public static List getReadableListFieldsForGroup(GrouperSession s,String groupId) throws Exception{
2656 		Group g = GroupFinder.findByUuid(s,groupId);
2657 		return getReadableListFieldsForGroup(s,g);
2658 	}
2659 	
2660 	/**
2661 	 * For a group id, for all its types, return fields of type LIST which the session user can read or write
2662 	 * @param s
2663 	 * @param g
2664 	 * @return List of list fields for group
2665 	 * @throws Exception
2666 	 */
2667 	public static List getReadableListFieldsForGroup(GrouperSession s,Group g) throws Exception{
2668 		List readable = getListFieldsForGroup(s,g);
2669 		Field field;
2670 		String name;
2671 		Iterator it = readable.iterator();
2672 		while(it.hasNext()) {
2673 			name=(String)it.next();
2674 			field=FieldFinder.find(name);
2675 			if(!g.canReadField(field)&& !g.canWriteField(field)) it.remove();
2676 		}
2677 		accumulateFields(readable);
2678 		return readable;
2679 	}
2680 	
2681 	/**
2682 	 * For a group id, for all its types, return fields of type LIST
2683 	 * @param s
2684 	 * @param groupId
2685 	 * @return List of list fields for group
2686 	 * @throws Exception
2687 	 */
2688 	public static List getListFieldsForGroup(GrouperSession s,String groupId) throws Exception{
2689 		Group g = GroupFinder.findByUuid(s,groupId);
2690 		return getListFieldsForGroup(s,g);
2691 	}
2692 	
2693 	
2694 	/**
2695 	 * For a group, for all its types, return fields of type LIST
2696 	 * @param s
2697 	 * @param g
2698 	 * @return List of list fields for group
2699 	 */
2700 	public static List getListFieldsForGroup(GrouperSession s,Group g) throws SchemaException{
2701 		List lists = new ArrayList();
2702 		Set types = g.getTypes();
2703 		Iterator it = types.iterator();
2704 		Set fields;
2705 		Field field;
2706 		Iterator fieldsIt;
2707 		GroupType type;
2708 		while(it.hasNext()) {
2709 			type = (GroupType)it.next();
2710 			fields=type.getFields();
2711 			fieldsIt=fields.iterator();
2712 			while(fieldsIt.hasNext()) {
2713 				field = (Field)fieldsIt.next();
2714 				if(field.getType().equals(FieldType.LIST)&& !"members".equals(field.getName())) {
2715 					if(canRead(s,field,g)) {
2716 						lists.add(field.getName());
2717 					}
2718 				}
2719 			}
2720 		}
2721 		accumulateFields(lists);
2722 		return lists;
2723 	}
2724 	
2725 	/**
2726 	 * For a group, for all its types, return fields user can read / write
2727 	 * @param s
2728 	 * @param g
2729 	 * @param priv read / write
2730 	 * @return Map keyed on field names
2731 	 */
2732 	public static Map getFieldsForGroup(GrouperSession s,Group g,String priv) throws SchemaException{
2733 		Map fieldsMap = new HashMap();
2734 		Set types = g.getTypes();
2735 		Iterator it = types.iterator();
2736 		Set fields;
2737 		Field field;
2738 		Iterator fieldsIt;
2739 		GroupType type;
2740 		while(it.hasNext()) {
2741 			type = (GroupType)it.next();
2742 			fields=type.getFields();
2743 			fieldsIt=fields.iterator();
2744 			while(fieldsIt.hasNext()) {
2745 				field = (Field)fieldsIt.next();
2746 				if(("read".equals(priv) && canRead(s,field,g))
2747 						||("write".equals(priv) && canWrite(s,field,g))) {
2748 						fieldsMap.put(field.getName(),Boolean.TRUE);
2749 				}
2750 			}
2751 		}
2752 		accumulateFields(fieldsMap.keySet());
2753 		return fieldsMap;
2754 	}
2755 	
2756 	
2757 	/**
2758 	 * Can the current user read this field?
2759 	 * Should probably remove, API support is there now
2760 	 * @param s
2761 	 * @param field
2762 	 * @param g
2763 	 * @return whether session subject can read specified field for specified group
2764 	 * @throws SchemaException
2765 	 */
2766 	
2767 	public static boolean canRead(GrouperSession s,Field field,Group g) throws SchemaException{
2768 		return g.canReadField(field);
2769 	}
2770 	
2771 	/**
2772 	 * Can the current write read this field?
2773 	 * Should probably remove, API support is there now
2774 	 * @param s
2775 	 * @param field
2776 	 * @param g
2777 	 * @return whether session subject can write specified field for specified group
2778 	 * @throws SchemaException
2779 	 */
2780 	
2781 	public static boolean canWrite(GrouperSession s,Field field,Group g) throws SchemaException{
2782 		return g.canWriteField(field);
2783 		
2784 	}
2785 	
2786 	
2787 	private static String noSearchFields="";//:name:displayName:extension:displayExtension:";
2788 	
2789 	/**
2790 	 * Retrieve list of attributes which can be searched
2791 	 * @return List of searchable fields
2792 	 * @throws SchemaException
2793 	 */
2794 	public static  List getSearchableFields(ResourceBundle bundle) throws SchemaException{
2795 		List res = new ArrayList();
2796 		List<String> names=new ArrayList();
2797 		
2798 		for (int i=0;i<searchableGroupFields.length;i++) {
2799 			Map map = new HashMap();
2800 			map.put("name",searchableGroupFields[i]);
2801 			map.put("displayName",bundle.getString("field.displayName." + searchableGroupFields[i]));
2802 			res.add(map);
2803 			names.add(searchableGroupFields[i]);
2804 		}
2805 		
2806 		
2807 		for (AttributeDefName legacyAttribute : GroupTypeFinder.internal_findAllLegacyAttributes()) {
2808 		  String name = legacyAttribute.getLegacyAttributeName(true);
2809 			if(noSearchFields.indexOf(":" + name + ":") == -1) {
2810 				names.add(name);
2811 				res.add(ObjectAsMap.getInstance("FieldAsMap",legacyAttribute));
2812 			}
2813 		}
2814 		accumulateFields(names);
2815 		return res;
2816 	}
2817 	
2818 	private static void accumulateFields(Collection<String> fields) {
2819 		Set<String> accumulated = (Set<String>)UIThreadLocal.get("accumulatedFields");
2820 		if(accumulated==null) {
2821 			accumulated = new HashSet<String>();
2822 			UIThreadLocal.put("accumulatedFields", accumulated);
2823 		}
2824 		accumulated.addAll(fields);
2825 	}
2826 	
2827 	/**
2828 	 * When we query fields we 'accumulate' them so we can check if tere are any new ones. If there are
2829 	 * we refresh the session list
2830 	 * @param fieldList Map of FieldAsMaps from the HttpSession
2831 	 * @throws SchemaException
2832 	 */
2833 	public static void fixSessionFields(Map fieldList) throws SchemaException{
2834 		Set<String> accumulated = (Set<String>)UIThreadLocal.get("accumulatedFields");
2835 		if(accumulated==null) {
2836 			return;
2837 		}
2838 		for(String fieldName : accumulated) {
2839 			if(!fieldList.containsKey(fieldName)) {
2840 				Map newFields = GrouperHelper.getFieldsAsMap();
2841 				fieldList.clear();
2842 				fieldList.putAll(newFields);
2843 				break;
2844 			}
2845 		}
2846 	}
2847 	
2848 	/**
2849 	 * Retrieve Map of attributes which can be searched
2850 	 * @return Map of searchable fields
2851 	 * @throws SchemaException
2852 	 */
2853 	public static  Map getFieldsAsMap() throws SchemaException{
2854 
2855 		Set fields = FieldFinder.findAll();
2856 		Iterator it = fields.iterator();
2857 		Field field;
2858 		Map fieldMap;
2859 		Map map = new LinkedHashMap();
2860 		ResourceBundle bundle = GrouperUiFilter.retrieveSessionNavResourceBundle();
2861 		while(it.hasNext()) {
2862 			field = (Field) it.next();
2863 			fieldMap=ObjectAsMap.getInstance("FieldAsMap",field);
2864 			map.put(field.getName(),fieldMap);
2865 		}
2866 		
2867 		for (AttributeDefName legacyAttribute : GroupTypeFinder.internal_findAllLegacyAttributes()) {
2868 		  map.put(legacyAttribute.getName(), ObjectAsMap.getInstance("FieldAsMap", legacyAttribute));
2869 		}
2870 		
2871 		String[] primaryFields = new String[] {"extension","displayExtension","name","displayName","description"};
2872 		for (int i=0;i<primaryFields.length;i++) {
2873 			Map dummyField = new HashMap();
2874 			dummyField.put("displayName", bundle.getString("field.displayName." + primaryFields[i]));
2875 			map.put(primaryFields[i], dummyField);
2876 		}
2877 		Map any = new HashMap();
2878 		any.put("displayName",bundle.getString("field.displayName._any"));
2879 		map.put("_any",any);
2880 		Map stemMap=new HashMap();
2881 		stemMap.put("extension","extension");
2882 		stemMap.put("displayExtension","displayExtension");
2883 		stemMap.put("name","name");
2884 		stemMap.put("displayName","displayName");
2885 		stemMap.put("description","description");
2886 		try {
2887 			stemMap.put("extension",bundle.getString("stems.edit.name"));
2888 		}catch(Exception e){}
2889 		try {
2890 			stemMap.put("displayExtension",bundle.getString("stems.edit.display-name"));
2891 		}catch(Exception e){}
2892 		try {
2893 			stemMap.put("name",bundle.getString("stems.edit.full-name"));
2894 		}catch(Exception e){}
2895 		try {
2896 			stemMap.put("displayName",bundle.getString("stems.edit.full-display-name"));
2897 		}catch(Exception e){}
2898 		try {
2899 			stemMap.put("description",bundle.getString("stems.edit.description"));
2900 		}catch(Exception e){}
2901 			map.put("stems",stemMap);
2902 		return map;
2903 	}
2904 	
2905 	
2906 	/**
2907 	 * Returns whether the user associated with the active GrouperSession can edit
2908 	 * any cuustom attribute associate with the supplied group
2909 	 * @param group
2910 	 * @return whether the user associated with the active GrouperSession can edit
2911 	 * any cuustom attribute associate with the supplied group
2912 	 * @throws SchemaException
2913 	 */
2914 	public static boolean canUserEditAnyCustomAttribute(Group group) throws SchemaException{
2915 		Map<String, AttributeAssign> assignmentsMap = group.internal_getGroupTypeAssignments();
2916 		
2917 		for (String groupTypeName : assignmentsMap.keySet()) {
2918 			GroupType legacyGroupType = GroupTypeFinder.find(groupTypeName, true);
2919 			AttributeAssign groupTypeAssignment = assignmentsMap.get(groupTypeName);
2920 
2921 			try {
2922   			AttributeDef attributeDef = legacyGroupType.internal_getAttributeDefForAttributes();
2923   
2924   			if (attributeDef != null) {
2925           Set<AttributeDefName> attrs = GrouperDAOFactory.getFactory().getAttributeDefName().findByAttributeDef(attributeDef.getId());
2926           for (AttributeDefName attr : attrs) {
2927             if (attr.getLegacyAttributeName(false) != null) {
2928               groupTypeAssignment.getAttributeDelegate().assertCanUpdateAttributeDefName(attr);
2929               return true;
2930             }
2931           }
2932   			}  			
2933 			} catch (InsufficientPrivilegeException e) {
2934 			  // don't have access
2935 			} catch (AttributeDefNotFoundException e) {
2936 			  // don't have access
2937 			}
2938 		}
2939 		
2940 		return false;
2941 	}
2942 	
2943 	private static String[] searchableStemFields=new String[] {"displayExtension","extension","displayName","name"};
2944 	private static String[] searchableGroupFields=new String[] {"displayExtension","extension","displayName","name"};
2945 	
2946 	/**
2947 	 * Returns a list of Maps representing name / displayNames for stem fields
2948 	 * Stems don't have fields in the way Groups do. This approach allows for similar
2949 	 * code for advanced group and stem searching
2950 	 * @param bundle
2951 	 * @return a list of Maps representing name / displayNames for stem fields
2952 	 */
2953 	public static List getSearchableStemFields(ResourceBundle bundle) {
2954 		List res = new ArrayList();
2955 		for (int i=0;i<searchableStemFields.length;i++) {
2956 			Map map = new HashMap();
2957 			map.put("name",searchableStemFields[i]);
2958 			map.put("displayName",bundle.getString("field.stem.displayName." + searchableStemFields[i]));
2959 			res.add(map);
2960 		}
2961 		return res;
2962 	}
2963 	
2964 	/**
2965 	 * Filter groups according to privileges of session subject and whether 
2966 	 * provided subject has any privileges for this group
2967 	 * @param s
2968 	 * @param groups
2969 	 * @param subject
2970 	 * @return filtered List
2971 	 */
2972 	public static List filterGroupsForSubject(GrouperSession s,List groups,Subject subject) {
2973 		List ok = new ArrayList();
2974 		Group group;
2975 		for (int i=0;i<groups.size();i++) {
2976 			group = (Group)groups.get(i);
2977 			if(group.hasAdmin(s.getSubject())) {
2978 				if(group.hasMember(subject)||
2979 						group.hasView(subject)||
2980 						group.hasAdmin(subject)||
2981 						group.hasUpdate(subject)||
2982 						group.hasRead(subject)||
2983 						group.hasOptin(subject)||
2984             group.hasOptout(subject) ||
2985             group.hasGroupAttrRead(subject) ||
2986             group.hasGroupAttrUpdate(subject)
2987 						) {
2988 					ok.add(group);
2989 				}
2990 			}
2991 		}
2992 		
2993 		return ok;
2994 	
2995 	}
2996 	
2997 	/**
2998 	 * Supplement group maps with privilege info for provided subject 
2999 	 * assuming subject has any privileges for this group
3000 	 * @param s
3001 	 * @param groups
3002 	 * @param subject
3003 	 * @return a List of embellished groups
3004 	 */
3005 	public static List embellishGroupMapsWithSubjectPrivs(GrouperSession s,List groups,Subject subject) throws Exception{
3006 		
3007 		GroupAsMap group;
3008 		Map privs=null;
3009 		Member member = MemberFinder.findBySubject(s,subject);
3010 		GroupOrStem gs = null;
3011 		
3012 		for (int i=0;i<groups.size();i++) {
3013 			group = (GroupAsMap)groups.get(i);
3014 			gs=GroupOrStem.findByGroup(s, (Group)group.getWrappedObject());
3015 			privs=getAllHas(s,gs,member);
3016 			group.put("subjectPrivs", privs);
3017 			group.put("privsSubject", subject.getId());
3018 		}
3019 		
3020 		return groups;
3021 	
3022 	}
3023 	
3024 	/**
3025 	 * Rather than force a client to  call getMember which involves a SQL query
3026 	 * expose the memberUuid where that is sufficient
3027 	 * @param m
3028 	 * @return memberUuid
3029 	 */
3030 	public static String getMemberUuid(Membership m) {
3031 		return m.getMemberUuid();
3032 	}
3033 	
3034 
3035 	public static boolean isRoot(GrouperSession s) {
3036 		return PrivilegeHelper.isRoot(s);
3037 	}
3038 	
3039 	public static GrouperSession getRootGrouperSession(GrouperSession s) {
3040 		return s.internal_getRootSession();	
3041 	}
3042 	
3043 	public static boolean isDirect(LazySubject ls) {
3044 		Membership ms = ls.getMembership();
3045 		//This is a hack, but will have to look at ramifications
3046 		//later
3047 		if(ms==null) return false;
3048 		return ms.getDepth()==0;
3049 	}
3050 	
3051 	public static boolean hasOtherReadableFields(Group g, String fieldName) {
3052 		Field f = null;
3053 		try {
3054 			f=FieldFinder.find(fieldName);
3055 		}catch(SchemaException e) {
3056 			throw new RuntimeException(e);
3057 		}
3058 		Set<GroupType> types=g.getTypes();
3059 		int count=0;
3060 		for(GroupType type : types) {
3061 			Set<Field> fields = type.getFields();
3062 			for(Field field : fields) {
3063 				try {
3064 					if(!field.equals(f) && field.isGroupListField() && g.canReadField(field)) {
3065 						count++;
3066 					}
3067 				}catch(SchemaException e) {
3068 					LOG.error(e);
3069 				}
3070 			}
3071 		}
3072 		return count > 0 || !f.getName().equals("members");
3073 	}
3074 
3075   /*public static List query(String sql) throws Exception{
3076   	Connection con = null;
3077   	try {
3078   		  List results = new ArrayList();
3079   	      Session hs = HibernateDAO.getSession();
3080   	      
3081   	      con = hs.connection();
3082   	      Statement stmt = con.createStatement();
3083   	      ResultSet rs = stmt.executeQuery(sql);
3084   	      Object obj;
3085   	      while(rs.next()) {
3086   	    	  obj = rs.getObject(1);
3087   	    	  results.add(obj);
3088   	      }
3089   	      return results;
3090   	    }
3091   	    catch (Exception e) {
3092   	      throw new QueryException("error finding groups: " +
3093   e.getMessage(), e);
3094   	    }finally {
3095   	    	try {
3096   	    		con.close();
3097   	    	}catch(Exception e){}
3098   	    }
3099 
3100   }*/
3101 
3102   /**
3103    * Return true if the following parameter values would allow a subject to 
3104    * copy the specified stem to another location.
3105    * @param stem
3106    * @param canCopy This is false if there's a security group limiting the subjects
3107    * that can copy stems and this subject is not in the group.
3108    * @return boolean
3109    */
3110   public static boolean canCopyStem(Stem stem, boolean canCopy) {
3111     if (!canCopy || stem.isRootStem()) {
3112       return false;
3113     }
3114 
3115     return true;
3116   }
3117 
3118   /**
3119    * Returns true if the following parameter values would allow a subject to 
3120    * move the specified stem to another location.
3121    * @param stem
3122    * @param canMove This is false if there's a security group limiting the subjects
3123    * that can move stems and this subject is not in the group.
3124    * @param privs The naming privileges that the subject has on the stem.
3125    * @return boolean
3126    */
3127   public static boolean canMoveStem(Stem stem, boolean canMove, Set<Privilege> privs) {
3128     if (!canMove || stem.isRootStem()) {
3129       return false;
3130     }
3131 
3132     if (privs.contains(NamingPrivilege.STEM_ADMIN)) {
3133       return true;
3134     }
3135 
3136     return false;
3137   }
3138 
3139   /**
3140    * Returns true if the following parameter values would allow a subject to 
3141    * copy a stem to the specified stem.
3142    * @param canCopy This is false if there's a security group limiting the subjects
3143    * that can copy stems and this subject is not in the group.
3144    * @param privs The naming privileges that the subject has on the specified stem.
3145    * @return boolean
3146    */
3147   public static boolean canCopyOtherStemToStem(Stem stem, boolean canCopy,
3148       Set<Privilege> privs) {
3149     if (!canCopy) {
3150       return false;
3151     }
3152 
3153     if (privs.contains(NamingPrivilege.STEM_ADMIN)) {
3154       return true;
3155     }
3156 
3157     return false;
3158   }
3159 
3160   /**
3161    * Returns true if the following parameters would allow a subject to 
3162    * move a stem to the specified stem.
3163    * @param canMove This is false if there's a security group limiting the subjects
3164    * that can move stems and this subject is not in the group.
3165    * @param privs The naming privileges that the subject has on the specified stem.
3166    * @return boolean
3167    */
3168   public static boolean canMoveOtherStemToStem(Stem stem, boolean canMove,
3169       Set<Privilege> privs) {
3170     if (!canMove) {
3171       return false;
3172     }
3173 
3174     if (privs.contains(NamingPrivilege.STEM_ADMIN)) {
3175       return true;
3176     }
3177 
3178     return false;
3179   }
3180 
3181   /**
3182    * Returns true if the following parameters would allow a subject to 
3183    * copy a group to the specified stem.
3184    * @param stem
3185    * @param privs The naming privileges that the subject has on the stem.
3186    * @return boolean
3187    */
3188   public static boolean canCopyGroupToStem(Stem stem, Set<Privilege> privs) {
3189     if (stem.isRootStem()) {
3190       return false;
3191     }
3192 
3193     if (privs.contains(NamingPrivilege.CREATE)) {
3194       return true;
3195     }
3196 
3197     return false;
3198   }
3199 
3200   /**
3201    * Returns true if the following parameters would allow a subject to
3202    * move a group to the specified stem.
3203    * @param stem
3204    * @param privs The naming privileges that the subject has on the stem.
3205    * @return boolean
3206    */
3207   public static boolean canMoveGroupToStem(Stem stem, Set<Privilege> privs) {
3208     if (stem.isRootStem()) {
3209       return false;
3210     }
3211 
3212     if (privs.contains(NamingPrivilege.CREATE)) {
3213       return true;
3214     }
3215 
3216     return false;
3217   }
3218 
3219   /**
3220    * Copy a group
3221    * @param group
3222    * @param destinationStem
3223    * @param selections
3224    * @return
3225    */
3226   public static Group copyGroup(Group group, Stem destinationStem, String[] selections) {
3227 
3228     List<String> selectionsList = new LinkedList<String>();
3229     if (selections != null) {
3230       for (int i = 0; i < selections.length; i++) {
3231         selectionsList.add(selections[i]);
3232       }
3233     }
3234 
3235     GroupCopy groupCopy = new GroupCopy(group, destinationStem);
3236 
3237     // set options for copy
3238     if (selectionsList.contains("copyPrivilegesOfGroup")) {
3239       groupCopy.copyPrivilegesOfGroup(true);
3240     } else {
3241       groupCopy.copyPrivilegesOfGroup(false);
3242     }
3243 
3244     if (selectionsList.contains("copyGroupAsPrivilege")) {
3245       groupCopy.copyGroupAsPrivilege(true);
3246     } else {
3247       groupCopy.copyGroupAsPrivilege(false);
3248     }
3249 
3250     if (selectionsList.contains("copyListMembersOfGroup")) {
3251       groupCopy.copyListMembersOfGroup(true);
3252     } else {
3253       groupCopy.copyListMembersOfGroup(false);
3254     }
3255 
3256     if (selectionsList.contains("copyListGroupAsMember")) {
3257       groupCopy.copyListGroupAsMember(true);
3258     } else {
3259       groupCopy.copyListGroupAsMember(false);
3260     }
3261 
3262     if (selectionsList.contains("copyAttributes")) {
3263       groupCopy.copyAttributes(true);
3264     } else {
3265       groupCopy.copyAttributes(false);
3266     }
3267 
3268     Group newGroup = groupCopy.save();
3269 
3270     return newGroup;
3271   }
3272 
3273   /**
3274    * Move a group
3275    * @param group
3276    * @param destinationStem
3277    * @param selections
3278    */
3279   public static void moveGroup(Group group, Stem destinationStem, String[] selections) {
3280 
3281     List<String> selectionsList = new LinkedList<String>();
3282     if (selections != null) {
3283       for (int i = 0; i < selections.length; i++) {
3284         selectionsList.add(selections[i]);
3285       }
3286     }
3287 
3288     GroupMove groupMove = new GroupMove(group, destinationStem);
3289 
3290     // set options for move
3291     if (selectionsList.contains("assignAlternateName")) {
3292       groupMove.assignAlternateName(true);
3293     } else {
3294       groupMove.assignAlternateName(false);
3295     }
3296 
3297     groupMove.save();
3298   }
3299 
3300   /**
3301    * Copy a stem
3302    * @param stemToCopy
3303    * @param destinationStem
3304    * @param selections
3305    * @return
3306    */
3307   public static Stem copyStem(Stem stemToCopy, Stem destinationStem, String[] selections) {
3308 
3309     List<String> selectionsList = new LinkedList<String>();
3310     if (selections != null) {
3311       for (int i = 0; i < selections.length; i++) {
3312         selectionsList.add(selections[i]);
3313       }
3314     }
3315 
3316     StemCopy stemCopy = new StemCopy(stemToCopy, destinationStem);
3317 
3318     // set options
3319     if (selectionsList.contains("copyPrivilegesOfStem")) {
3320       stemCopy.copyPrivilegesOfStem(true);
3321     } else {
3322       stemCopy.copyPrivilegesOfStem(false);
3323     }
3324 
3325     if (selectionsList.contains("copyPrivilegesOfGroup")) {
3326       stemCopy.copyPrivilegesOfGroup(true);
3327     } else {
3328       stemCopy.copyPrivilegesOfGroup(false);
3329     }
3330 
3331     if (selectionsList.contains("copyGroupAsPrivilege")) {
3332       stemCopy.copyGroupAsPrivilege(true);
3333     } else {
3334       stemCopy.copyGroupAsPrivilege(false);
3335     }
3336 
3337     if (selectionsList.contains("copyListMembersOfGroup")) {
3338       stemCopy.copyListMembersOfGroup(true);
3339     } else {
3340       stemCopy.copyListMembersOfGroup(false);
3341     }
3342 
3343     if (selectionsList.contains("copyListGroupAsMember")) {
3344       stemCopy.copyListGroupAsMember(true);
3345     } else {
3346       stemCopy.copyListGroupAsMember(false);
3347     }
3348 
3349     if (selectionsList.contains("copyAttributes")) {
3350       stemCopy.copyAttributes(true);
3351     } else {
3352       stemCopy.copyAttributes(false);
3353     }
3354 
3355     Stem newStem = stemCopy.save();
3356 
3357     return newStem;
3358   }
3359 
3360   /**
3361    * Move a stem
3362    * @param stemToMove
3363    * @param destinationStem
3364    * @param selections
3365    */
3366   public static void moveStem(Stem stemToMove, Stem destinationStem, String[] selections) {
3367 
3368     List<String> selectionsList = new LinkedList<String>();
3369     if (selections != null) {
3370       for (int i = 0; i < selections.length; i++) {
3371         selectionsList.add(selections[i]);
3372       }
3373     }
3374 
3375     StemMove stemMove = new StemMove(stemToMove, destinationStem);
3376 
3377     // set options
3378     if (selectionsList.contains("assignAlternateName")) {
3379       stemMove.assignAlternateName(true);
3380     } else {
3381       stemMove.assignAlternateName(false);
3382     }
3383 
3384     stemMove.save();
3385   }
3386   
3387   public static String getMemberDisplayValue(Member member, ResourceBundle bundle) {
3388 	  String field="description";
3389 	  
3390 	  String value="unknown";
3391 	  try {
3392 		  field = bundle.getString("subject.display." + member.getSubjectSourceId());
3393 	  }catch (MissingResourceException e) {
3394 		  try {
3395 		  field = bundle.getString("subject.display.default");
3396 		  }catch(MissingResourceException ee) {
3397 			  
3398 		  }
3399 	  }
3400 	  try {
3401 	  value=member.getSubject().getAttributeValue(field);
3402 	  }catch(Exception e) {
3403 		  
3404 	  }
3405 	  if(value==null){
3406 		  value=member.getSubjectId().toString();
3407 	  }
3408 	  return value;
3409   }
3410 }
3411 
3412 
3413 
3414