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   * @author mchyzer
18   * $Id: GuiSubject.java,v 1.2 2009-10-11 22:04:17 mchyzer Exp $
19   */
20  package edu.internet2.middleware.grouper.grouperUi.beans.api;
21  
22  import java.io.Serializable;
23  import java.util.HashMap;
24  import java.util.LinkedHashMap;
25  import java.util.LinkedHashSet;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.commons.lang.StringUtils;
30  
31  import edu.internet2.middleware.grouper.Group;
32  import edu.internet2.middleware.grouper.GroupFinder;
33  import edu.internet2.middleware.grouper.GrouperSession;
34  import edu.internet2.middleware.grouper.GrouperSourceAdapter;
35  import edu.internet2.middleware.grouper.Member;
36  import edu.internet2.middleware.grouper.MemberFinder;
37  import edu.internet2.middleware.grouper.SubjectFinder;
38  import edu.internet2.middleware.grouper.entity.EntitySourceAdapter;
39  import edu.internet2.middleware.grouper.grouperUi.beans.ui.GrouperRequestContainer;
40  import edu.internet2.middleware.grouper.grouperUi.beans.ui.TextContainer;
41  import edu.internet2.middleware.grouper.misc.GrouperObject;
42  import edu.internet2.middleware.grouper.subj.GrouperSubject;
43  import edu.internet2.middleware.grouper.subj.SubjectHelper;
44  import edu.internet2.middleware.grouper.subj.UnresolvableSubject;
45  import edu.internet2.middleware.grouper.ui.util.GrouperUiConfig;
46  import edu.internet2.middleware.grouper.ui.util.GrouperUiUtils;
47  import edu.internet2.middleware.grouper.util.GrouperEmailUtils;
48  import edu.internet2.middleware.grouper.util.GrouperUtil;
49  import edu.internet2.middleware.subject.Source;
50  import edu.internet2.middleware.subject.Subject;
51  import edu.internet2.middleware.subject.provider.SourceManager;
52  
53  
54  /**
55   * subject for gui has all attributes etc, and getter to be accessed from screen
56   */
57  @SuppressWarnings("serial")
58  public class GuiSubject extends GuiObjectBase implements Serializable {
59  
60    /**
61     * return source id two pipes and subject id
62     * @return the source id two pipes and subject id
63     */
64    public String getSourceIdSubjectId() {
65      if (this.subject == null) {
66        return null;
67      }
68      return this.subject.getSourceId() + "||" + this.subject.getId();
69    }
70    
71    /**
72     * 
73     * @see java.lang.Object#equals(java.lang.Object)
74     */
75    public boolean equals(Object other) {
76      if (this == other) {
77        return true;
78      }
79      if (!(other instanceof GuiSubject)) {
80        return false;
81      }
82      return SubjectHelper.eq(this.subject, ((GuiSubject)other).subject);
83    }
84  
85    /**
86     * @see java.lang.Object#hashCode()
87     */
88    public int hashCode() {
89      return SubjectHelper.hashcode(this.subject);
90    }
91  
92    /**
93     * get the member id of the subject or null if not there
94     * @return the member id if exists or null if not
95     */
96    public String getMemberId() {
97      
98      if (this.subject != null) {
99        GrouperSession grouperSession = GrouperSession.staticGrouperSession(false);
100       
101       //when converting json this is null, so dont do a query if just doing json beans
102       if (grouperSession != null) {
103         Member member = MemberFinder.findBySubject(grouperSession, this.getSubject(), false);
104         if (member != null) {
105           return member.getId();
106         }
107       }
108     }
109     return null;
110   }
111   
112   /**
113    * if the gui subject has an email address
114    * @return true if the subject has email
115    */
116   public boolean isHasEmailAttributeInSource() {
117     if (this.subject == null) {
118       return false;
119     }
120     //if there is an email attribute in the source, then this is true
121     return !StringUtils.isBlank(GrouperEmailUtils.emailAttributeNameForSource(this.subject.getSourceId()));
122   }
123 
124   /**
125    * get the email attribute value
126    * @return the email or null or blank if not there
127    */
128   public String getEmail() {
129     if (this.subject == null) {
130       return null;
131     }
132     String emailAttributeName = GrouperEmailUtils.emailAttributeNameForSource(this.subject.getSourceId());
133     if (StringUtils.isBlank(emailAttributeName)) {
134       return null;
135     }
136     return this.subject.getAttributeValue(emailAttributeName);
137   }
138   
139   /**
140    * 
141    * @param subjects
142    * @return subjects
143    */
144   public static Set<GuiSubject> convertFromSubjects(Set<Subject> subjects) {
145     return convertFromSubjects(subjects, null, -1);
146   }
147 
148 
149   /**
150    * 
151    * @param subjects
152    * @return gui subjects
153    */
154   public static Set<GuiSubject> convertFromSubjects(Set<Subject> subjects, String configMax, int defaultMax) {
155 
156     Set<GuiSubject> tempSubjects = new LinkedHashSet<GuiSubject>();
157     
158     Integer max = null;
159     
160     if (!StringUtils.isBlank(configMax)) {
161       max = GrouperUiConfig.retrieveConfig().propertyValueInt(configMax, defaultMax);
162     }
163     
164     int count = 0;
165     for (Subject subject : GrouperUtil.nonNull(subjects)) {
166       tempSubjects.add(new GuiSubject(subject));
167       if (max != null && ++count >= max) {
168         break;
169       }
170     }
171     
172     return tempSubjects;
173     
174   }
175 
176   /**
177    * see if group or not
178    * @return if group
179    */
180   public boolean isGroup() {
181     if (this.subject == null) {
182       return false;
183     }
184     return StringUtils.equals(SubjectFinder.internal_getGSA().getId(), this.subject.getSourceId());
185   }
186   
187   /** subject */
188   private Subject subject;
189 
190   /**
191    * e.g. &lt;a href="#"&gt;John Smith&lt;/a&gt;
192    * @return short link
193    */
194   public String getShortLink() {
195     this.initScreenLabels();
196     return this.screenLabelShort2html;
197   }
198   
199   /**
200    * e.g. &lt;a href="#"&gt;John Smith&lt;/a&gt;
201    * @return short link
202    */
203   public String getShortLinkWithIcon() {
204     this.initScreenLabels();
205     return this.screenLabelShort2htmlWithIcon;
206   }
207 
208   /**
209    * e.g. &lt;a href="#"&gt;John Smith&lt;/a&gt;
210    * @return short link
211    */
212   public String getScreenLabelShort2noLink() {
213     this.initScreenLabels();
214     return this.screenLabelShort2noLink;
215   }
216 
217   /**
218    * some source Id that isnt a normal grouper one
219    */
220   private static String sourceId = null;
221   
222   /**
223    * 
224    * @return a source id
225    */
226   public static String someSourceId() {
227     if (sourceId == null) {
228       synchronized (GuiSubject.class) {
229         if (sourceId == null) {
230           //pick one at random?
231           String theSourceId = "g:gsa";
232           
233           for (Source source : SourceManager.getInstance().getSources()) {
234             if (!"g:gsa".equals(source.getId())
235                 && !"grouperEntities".equals(source.getId())
236                 && !"grouperExternal".equals(source.getId())
237                 && !"g:isa".equals(source.getId())) {
238               theSourceId = source.getId();
239               break;
240             }
241           }
242           sourceId = theSourceId;
243           
244         }
245       }
246     }
247     return sourceId;
248   }
249   
250   /**
251    * init screen labels
252    */
253   private void initScreenLabels() {
254     
255     if (this.subject == null) {
256 
257       //unresolvable
258       this.subject = new UnresolvableSubject("", null, someSourceId());
259       
260     }
261     
262     if (this.screenLabelLong == null && this.screenLabelShort == null) {
263       
264       boolean convertToUnresolvableSubject = false;
265       String unresolvableSubjectString = TextContainer.retrieveFromRequest().getText().get("guiUnresolvableSubject");
266       
267       if (this.subject instanceof UnresolvableSubject) {
268         if (!StringUtils.equals(unresolvableSubjectString, ((UnresolvableSubject)this.subject).getUnresolvableString())) {
269           //we want to use the unresolvable string from the externalized text file in the UI
270           convertToUnresolvableSubject = true;
271         }
272         
273         //convert from lazy subject error to an unresolvable
274       } else if (this.subject != null && this.subject.getName() != null && this.subject.getName().contains(" entity not found")) {
275         convertToUnresolvableSubject = true;
276       }
277 
278       if (convertToUnresolvableSubject) {
279         
280         this.subject = new UnresolvableSubject(this.subject.getId(), this.subject.getTypeName(), this.subject.getSourceId(), unresolvableSubjectString);
281 
282       }
283 
284       boolean isUnresolvableGroup = false;
285       
286       
287       if (this.subject instanceof UnresolvableSubject) {
288         if (StringUtils.equals(GrouperSourceAdapter.groupSourceId(), this.subject.getSourceId())
289             || StringUtils.equals(EntitySourceAdapter.entitySourceId(), this.subject.getSourceId())) {
290           
291           isUnresolvableGroup = true;
292           
293           GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setSubjectId(this.subject.getId());
294           String extensionName = null;
295           if (StringUtils.equals(GrouperSourceAdapter.groupSourceId(), this.subject.getSourceId())) {
296             extensionName = TextContainer.retrieveFromRequest().getText().get("guiGroupCantView");
297           } else {
298             extensionName = TextContainer.retrieveFromRequest().getText().get("guiEntityCantView");
299           }
300           GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setSubjectId(null);
301 
302           //the user does not have view on this group or entity!
303           Map<String, Set<String>> subjectAttributes = this.subject.getAttributes();
304           subjectAttributes.put("displayExtension", GrouperUtil.toSet(StringUtils.abbreviate(extensionName, 33)));
305           subjectAttributes.put("displayName", GrouperUtil.toSet(extensionName));
306           ((UnresolvableSubject) this.subject).setDescription(extensionName);
307           ((UnresolvableSubject) this.subject).setAttributes(subjectAttributes);
308         }
309       }
310       
311       String screenLabel = GrouperUiUtils.convertSubjectToLabelLong(this.subject);
312             
313       this.screenLabelLong = screenLabel;
314       
315       screenLabel = GrouperUiUtils.convertSubjectToLabel(this.subject);
316       
317       int maxWidth = GrouperUiConfig.retrieveConfig().propertyValueInt("subject.maxChars", 100);
318       if (maxWidth == -1) {
319         this.screenLabelShort = screenLabel;
320       } else {
321         this.screenLabelShort = StringUtils.abbreviate(screenLabel, maxWidth);
322       }
323 
324       screenLabel = GrouperUiUtils.convertSubjectToLabelHtmlConfigured2(this.subject);
325       
326       maxWidth = GrouperUiConfig.retrieveConfig().propertyValueInt("subject2.maxChars", 40);
327       if (maxWidth == -1) {
328         this.screenLabelShort2 = screenLabel;
329       } else {
330         this.screenLabelShort2 = StringUtils.abbreviate(screenLabel, maxWidth);
331       }
332 
333       this.screenSubjectIcon2Html = GrouperUiUtils.convertSubjectToIconHtmlConfigured2(this.subject);
334 
335       boolean hasTooltip = this.subject != null
336         && !StringUtils.isBlank(this.subject.getDescription()) && !StringUtils.equals(this.subject.getName(), this.subject.getDescription());
337       
338       GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setShowTooltip(hasTooltip);
339       GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setGuiSubject(this);
340       
341       try {
342         
343         //"<a href=\"view-subject.html\" rel=\"tooltip\" data-html=\"true\" data-delay-show=\"200\" data-placement=\"right\" title=\"" + GrouperUtil.xmlEscape(subject.getDescription(), true)  + "\">" + this.screenLabelShort2 + "</a>";
344         //"<a href=\"view-subject.html\" data-html=\"true\" data-delay-show=\"200\" data-placement=\"right\">" + this.screenLabelShort2 + "</a>";
345         Group group = null;
346         
347         if (this.isGroup()) {
348           if (this.subject instanceof GrouperSubject) {
349             group = ((GrouperSubject)this.subject).internal_getGroup();
350           }
351           if (group == null) {
352             group = GroupFinder.findByUuid(GrouperSession.staticGrouperSession(), this.subject.getId(), false);
353           }
354           if (group == null) {
355             group = new Group();
356             group.setId(this.subject.getId());
357             String cantFindGroupName = this.subject.getAttributeValue("displayName");
358             String cantFindGroupExtension = this.subject.getAttributeValue("displayExtension");
359             group.setNameDb(cantFindGroupName);
360             group.setDisplayNameDb(cantFindGroupName);
361             group.setExtensionDb(cantFindGroupExtension);
362             group.setDisplayExtensionDb(cantFindGroupExtension);
363             group.setDescriptionDb(cantFindGroupName);
364           }
365         }
366         
367         if (group != null) {
368           GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setGuiGroup(new GuiGroup(group));
369           this.screenLabelShort2html = TextContainer.retrieveFromRequest().getText().get("guiGroupShortLink");
370         } else {
371           
372           this.screenLabelShort2html = TextContainer.retrieveFromRequest().getText().get("guiSubjectShortLink");
373         }
374         
375         GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setShowIcon(true);
376 
377         if (group != null) {
378           this.screenLabelLongWithIcon = TextContainer.retrieveFromRequest().getText().get("guiGroupLongLinkWithIcon");
379         } else {
380           this.screenLabelLongWithIcon = TextContainer.retrieveFromRequest().getText().get("guiSubjectLongLinkWithIcon");
381         }
382         
383 
384         if (group != null) {
385           this.screenLabelShort2htmlWithIcon = TextContainer.retrieveFromRequest().getText().get("guiGroupShortLink");
386         } else {
387           this.screenLabelShort2htmlWithIcon = TextContainer.retrieveFromRequest().getText().get("guiSubjectShortLink");
388         }
389         
390         if (group != null) {
391           this.screenLabelShort2noLinkWithIcon = TextContainer.retrieveFromRequest().getText().get("guiGroupShort");
392         } else {
393           this.screenLabelShort2noLinkWithIcon = TextContainer.retrieveFromRequest().getText().get("guiSubjectShort");
394         }
395         
396         GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setShowIcon(false);
397 
398         if (group != null) {
399           this.screenLabelShort2noLink = TextContainer.retrieveFromRequest().getText().get("guiGroupShort");
400         } else {
401           this.screenLabelShort2noLink = TextContainer.retrieveFromRequest().getText().get("guiSubjectShort");
402         }
403 
404       } finally {
405 
406         GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setGuiSubject(null);
407         GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setShowTooltip(false);
408         GrouperRequestContainer.retrieveFromRequestOrCreate().getCommonRequestContainer().setShowIcon(false);
409 
410       }
411 
412     }
413   }
414 
415   /**
416    * short screen label for ui v2
417    * @return label
418    */
419   public String getScreenLabelShort2() {
420     this.initScreenLabels();
421     return this.screenLabelShort2;
422   }
423 
424   /**
425    * span for subject-specific icon for ui v2; e.g. '&lt;i class="fa fa-group"&gt;&lt;/i&gt; '
426    * @return label
427    */
428   public String getScreenSubjectIcon2Html() {
429     this.initScreenLabels();
430     return this.screenSubjectIcon2Html;
431   }
432 
433   /**
434    * construct with subject
435    * @param subject1
436    */
437   public GuiSubject(Subject subject1) {
438     this.subject = subject1;
439   }
440   
441   /**
442    * get screen label
443    * @return screen label
444    */
445   public String getScreenLabel() {
446     this.initScreenLabels();
447     return this.screenLabelShort;
448   }
449   
450   /**
451    * get screen label
452    * @return screen label
453    */
454   public String getScreenLabelLong() {
455     this.initScreenLabels();
456     return this.screenLabelLong;
457   }
458   
459   /** attributes in string - string format */
460   private Map<String, String> attributes = null;
461   /**
462    * long screen label
463    */
464   private String screenLabelLong = null;
465   /**
466    * long screen label with icon
467    */
468   private String screenLabelLongWithIcon = null;
469 
470   /**
471    * long screen label with icon
472    * @return screen label
473    */
474   public String getScreenLabelLongWithIcon() {
475     this.initScreenLabels();
476     return this.screenLabelLongWithIcon;
477   }
478 
479   /**
480    * short screen label
481    */
482   private String screenLabelShort = null;
483 
484   /**
485    * new short label in v2
486    */
487   private String screenLabelShort2 = null;
488   
489   /**
490    * new short label in v2 with html tooltip and link
491    */
492   private String screenLabelShort2html = null;
493 
494   /**
495    * new subject icon in v2
496    */
497   private String screenSubjectIcon2Html = null;
498 
499   /**
500    * new short label in v2 with html tooltip and link and icon
501    */
502   private String screenLabelShort2htmlWithIcon = null;
503   
504   /**
505    * new short label in v2 with no link, but with icon
506    */
507   private String screenLabelShort2noLinkWithIcon = null;
508 
509   /**
510    * new short label in v2 with no link or icon
511    */
512   private String screenLabelShort2noLink = null;
513 
514   
515   /**
516    * subject
517    * @return the subject
518    */
519   public Subject getSubject() {
520     return this.subject;
521   }
522   
523   /**
524    * attribute names for this subject
525    * @return the attribute names for this subject
526    */
527   public Set<String> getAttributeNamesNonInternal() {
528     Set<String> attributeNames = new LinkedHashSet<String>();
529     if (this.subject != null) {
530       String emailAttributeName = GrouperEmailUtils.emailAttributeNameForSource(this.subject.getSourceId());
531   
532       for (String attributeName : GrouperUtil.nonNull(this.getAttributes().keySet())) {
533         if (!StringUtils.equalsIgnoreCase("name", attributeName)
534             && !StringUtils.equalsIgnoreCase("description", attributeName)
535             && !StringUtils.equalsIgnoreCase("subjectId", attributeName)
536             && !StringUtils.equalsIgnoreCase(emailAttributeName, attributeName)) {
537           attributeNames.add(attributeName);
538         }
539       }
540     }
541     return attributeNames;
542   }
543   
544   /**
545    * attribute names for this subject to show in the expanded view
546    * @return the attribute names for this subject
547    */
548   public Set<String> getAttributeNamesExpandedView() {
549     Set<String> attributeNames = new LinkedHashSet<String>();
550     if (this.subject != null) {
551       String orderCommaSeparated = GrouperUiConfig.retrieveConfig().propertyValueString("subject2.attributes.order.expanded." + this.subject.getSourceId());
552       if (GrouperUtil.isBlank(orderCommaSeparated)) {
553         orderCommaSeparated = GrouperUiConfig.retrieveConfig().propertyValueString("subject2.attributes.order.expanded.default");
554       }
555       
556       // still empty, return them all to preserve previous behavior
557       if (GrouperUtil.isBlank(orderCommaSeparated)) {
558         return getAttributeNamesNonInternal();
559       }
560       
561       attributeNames.addAll(GrouperUtil.splitTrimToSet(orderCommaSeparated, ","));
562     }
563     return attributeNames;
564   }
565   
566   
567   /**
568    * attribute names for this subject to show in the non-expanded view
569    * @return the attribute names for this subject
570    */
571   public Set<String> getAttributeNamesNonExpandedView() {
572     Set<String> attributeNames = new LinkedHashSet<String>();
573     if (this.subject != null) {
574       String orderCommaSeparated = GrouperUiConfig.retrieveConfig().propertyValueString("subject2.attributes.order.nonexpanded." + this.subject.getSourceId());
575       if (GrouperUtil.isBlank(orderCommaSeparated)) {
576         orderCommaSeparated = GrouperUiConfig.retrieveConfig().propertyValueString("subject2.attributes.order.nonexpanded.default", "subjectId,email,name,description");
577       }
578       
579       if (!GrouperUtil.isBlank(orderCommaSeparated)) {
580 
581         // GRP-1558: default subject display shows "email" attribute, which source might not have
582         if (orderCommaSeparated.contains(",email,")) {
583 
584           if (!this.getAttributes().containsKey("email")) {
585             String emailAttribute = GrouperEmailUtils.emailAttributeNameForSource(this.subject.getSourceId());
586             if (!StringUtils.isBlank(emailAttribute)) {
587               orderCommaSeparated = GrouperUtil.replace(orderCommaSeparated, ",email,", "," + emailAttribute + ",");
588             } else {
589               orderCommaSeparated = GrouperUtil.replace(orderCommaSeparated, ",email,", ",");
590             }
591           }
592         }
593         
594         attributeNames.addAll(GrouperUtil.splitTrimToSet(orderCommaSeparated, ","));
595       }
596     }
597     return attributeNames;
598   }
599 
600   /**
601    * dynamic map of attribute name to attribute label
602    */
603   private Map<String, String> attributeLabelMap = new HashMap<String, String>() {
604 
605     /**
606      * @see java.util.HashMap#get(java.lang.Object)
607      */
608     @Override
609     public String get(Object attributeName) {
610       
611       String sourceId = GuiSubject.this.getSubject().getSourceId();
612       String sourceTextId = GrouperUiUtils.convertSourceIdToTextId(sourceId);
613       
614       String emailAttribute = GrouperEmailUtils.emailAttributeNameForSource(GuiSubject.this.subject.getSourceId());
615       
616       // subjectViewLabel__sourceTextId__attributeName
617       String key = "subjectViewLabel__" + sourceTextId + "__" + attributeName;
618       
619       if ("sourceId".equals(attributeName)) {
620         key = "subjectViewLabelSourceId";
621       } else if ("sourceName".equals(attributeName)) {
622         key = "subjectViewLabelSourceName";
623       } else if ("memberId".equals(attributeName)) {
624         key = "subjectViewLabelMemberId";
625       } else if ("subjectId".equals(attributeName)) {
626         key = "subjectViewLabelId";
627       } else if ("name".equals(attributeName)) {
628         key = "subjectViewLabelName";
629       } else if ("description".equals(attributeName)) {
630         key = "subjectViewLabelDescription";
631       } else if (!GrouperUtil.isBlank(emailAttribute) && emailAttribute.equals(attributeName)) {
632         key = "subjectViewLabelEmail";
633       }
634       
635       String value = TextContainer.textOrNull(key);
636       
637       if (StringUtils.isBlank(value)) {
638         return ((String)attributeName) + ":";
639       }
640       return value;
641       
642     }
643 
644   };
645 
646   
647   /**
648    * attribute label for this attribute if configured
649    * first get the text id for the source, then look in the externalized text
650    * for a label for the attribute, if not there, just use the attribute name
651    * @return the attribute label for this attribute
652    */
653   public Map<String, String> getAttributeLabel() {
654     
655     return this.attributeLabelMap;
656     
657   }
658   
659   /**
660    * Gets a map attribute names and value. The map's key
661    * contains the attribute name and the map's value
662    * contains a Set of attribute value(s).  Note, this only does single valued attributes
663    * @return the map of attributes
664    */
665   @SuppressWarnings({ "cast", "unchecked" })
666   public Map<String, String> getAttributes() {
667     if (this.attributes == null) {
668       Map<String, String> result = new LinkedHashMap<String, String>();
669       
670       if (this.subject != null) {
671         for (String key : (Set<String>)(Object)GrouperUtil.nonNull(this.subject.getAttributes()).keySet()) {
672           Object value = this.subject.getAttributes().get(key);
673           if (value instanceof String) {
674             //if a string
675             result.put(key, (String)value);
676           } else if (value instanceof Set) {
677             //if set of one string, then add it
678             if (((Set<?>)value).size() == 1) {
679               result.put(key, (String)((Set<?>)value).iterator().next());
680             } else if (((Set<?>)value).size() > 1) {
681               //put commas in between?  not sure what else to do here
682               result.put(key, GrouperUtil.setToString((Set<?>)value));
683             }
684           }
685         }
686       }
687       
688       result.put("memberId", getMemberId());
689       result.put("sourceId", this.subject.getSourceId());
690       result.put("sourceName", this.subject.getSource().getName());
691       result.put("subjectId", this.subject.getId());
692       result.put("name", this.subject.getName());
693       result.put("description", this.subject.getDescription());
694       
695       this.attributes = result;
696     }
697     return this.attributes;
698   }
699 
700   /**
701    * 
702    * @return long label if different than the short one
703    */
704   public String getScreenLabelLongIfDifferent() {
705     this.initScreenLabels();
706     if (this.isNeedsTooltip()) {
707       return this.screenLabelLong;
708     }
709     return null;
710   }
711 
712   /**
713    * get short screen label 
714    * @return short screen label
715    */
716   public boolean isNeedsTooltip() {
717     this.initScreenLabels();
718     return !StringUtils.equals(this.screenLabelLong, this.screenLabelShort);
719   }
720 
721 
722   /**
723    * e.g. &lt;a href="#"&gt;John Smith&lt;/a&gt;
724    * @return short link
725    */
726   public String getScreenLabelShort2noLinkWithIcon() {
727     this.initScreenLabels();
728     return this.screenLabelShort2noLinkWithIcon;
729   }
730 
731 
732   /**
733    * 
734    * @param subject
735    * @param attrName
736    * @return the value
737    */
738   public static String attributeValue(Subject subject, String attrName) {
739     if (StringUtils.equalsIgnoreCase("screenLabel", attrName)) {
740       return GrouperUiUtils.convertSubjectToLabel(subject);
741     }
742     if (subject == null) { 
743       return null;
744     }
745     if (StringUtils.equalsIgnoreCase("subjectId", attrName)) {
746       return subject.getId();
747     }
748     if (StringUtils.equalsIgnoreCase("name", attrName)) {
749       return subject.getName();
750     }
751     if (StringUtils.equalsIgnoreCase("description", attrName)) {
752       return subject.getDescription();
753     }
754     if (StringUtils.equalsIgnoreCase("typeName", attrName)) {
755       return subject.getType().getName();
756     }
757     if (StringUtils.equalsIgnoreCase("sourceId", attrName)) {
758       return subject.getSource().getId();
759     }
760     if (StringUtils.equalsIgnoreCase("sourceName", attrName)) {
761       return subject.getSource().getName();
762     }
763     //TODO switch this to attribute values comma separated
764     return subject.getAttributeValue(attrName);
765   }
766 
767   /**
768    * cant get grouper object
769    */
770   @Override
771   public GrouperObject getGrouperObject() {
772     return null;
773   }
774 
775   /**
776    * if this is a subject
777    */
778   @Override
779   public boolean isSubjectType() {
780     return true;
781   }
782 
783   /**
784    * path colon separated not applicable
785    */
786   @Override
787   public String getPathColonSpaceSeparated() {
788     return "";
789   }
790 
791   /**
792    * not applicable
793    */
794   @Override
795   public String getNameColonSpaceSeparated() {
796     return this.getScreenLabelShort2noLink();
797   }
798 
799   /**
800    * not applicable
801    */
802   @Override
803   public String getTitle() {
804     return "";
805   }
806   
807 }