001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/presence/trunk/presence-api/api/src/java/org/sakaiproject/presence/api/PresenceService.java $
003: * $Id: PresenceService.java 7844 2006-04-17 13:06:02Z ggolden@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.tool.roster;
021:
022: import java.io.IOException;
023: import java.io.OutputStream;
024: import java.text.DateFormat;
025: import java.text.SimpleDateFormat;
026: import java.util.ArrayList;
027: import java.util.Collections;
028: import java.util.Date;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Map;
032: import java.util.HashMap;
033:
034: import javax.faces.context.ExternalContext;
035: import javax.faces.context.FacesContext;
036: import javax.faces.event.ActionEvent;
037: import javax.faces.event.ValueChangeEvent;
038: import javax.faces.model.SelectItem;
039: import javax.servlet.http.HttpServletResponse;
040:
041: import org.apache.commons.logging.Log;
042: import org.apache.commons.logging.LogFactory;
043: import org.sakaiproject.api.app.profile.ProfileManager;
044: import org.sakaiproject.api.app.roster.Participant;
045: import org.sakaiproject.api.app.roster.RosterManager;
046: import org.sakaiproject.component.cover.ServerConfigurationService;
047: import org.sakaiproject.entity.api.Entity;
048: import org.sakaiproject.site.cover.SiteService;
049: import org.sakaiproject.site.api.Site;
050: import org.sakaiproject.tool.cover.ToolManager;
051: import org.sakaiproject.util.ResourceLoader;
052:
053: /**
054: * @author rshastri <a href="mailto:rshastri@iupui.edu ">Rashmi Shastri</a>
055: * @version $Id: RosterTool.java 1378 2005-08-25 16:25:41Z rshastri@iupui.edu $
056: */
057: public class RosterTool {
058: private final static Log Log = LogFactory.getLog(RosterTool.class);
059: private ResourceLoader msgs = new ResourceLoader(
060: "org.sakaiproject.tool.roster.bundle.Messages");
061:
062: private static final String DISPLAY_ROSTER_PRIVACY_MSG = "roster.privacy.display";
063: private static final String PARTICIPANT_ID = "participantId";
064:
065: private String idPhotoText = msgs.getString("show_id_photo");
066: private String customPhotoText = msgs.getString("show_pic");
067: private String title = msgs.getString("title_show_roster");
068:
069: protected RosterManager rosterManager;
070: protected ProfileManager profileManager;
071:
072: private DecoratedParticipant participant;
073:
074: private boolean showIdPhoto = false;
075: private boolean showCustomPhoto = false;
076: private boolean reloadRoster = true;
077: private String facet = "";
078: private int allUserCount = 0;
079: private List decoRoster = null;
080: private List rosterList = null;
081: private List menuItems = null;
082: private List roleStats = null;
083: private boolean rosterProcessed = false;
084:
085: // sort column
086: private boolean sortLastNameDescending = false;
087: private boolean sortUserIdDescending = false;
088: private boolean sortRoleDescending = false;
089: private boolean sortSectionsDescending = false;
090: private boolean sortLastNameAscending = false;
091: private boolean sortUserIdAscending = false;
092: private boolean sortRoleAscending = true; // default to sort by role
093: private boolean sortSectionsAscending = false;
094:
095: public static final String CSV_DELIM = ",";
096: public static final String SORT_ASC = "ascending";
097: public static final String SORT_DESC = "descending";
098:
099: private String selectedView = RosterManager.VIEW_NO_SECT;
100:
101: public RosterTool() {
102:
103: }
104:
105: public String processActionToggleIdPhotos() {
106: Log.debug("processActionToggleIdPhotos()");
107: if (showIdPhoto) {
108: setPhotoToggeling(msgs.getString("hide_id_photo"));
109: } else
110: // if the photo ids are already hidden the display the photos
111: {
112: setPhotoToggeling(msgs.getString("show_id_photo"));
113: }
114: return "main";
115: }
116:
117: public String processActionToggleCustomPhotos() {
118: Log.debug("processActionToggleCustomPhotos()");
119: if (showCustomPhoto) {
120: setPhotoToggeling(msgs.getString("hide_pic"));
121: } else
122: // if the photo ids are already hidden the display the photos
123: {
124: setPhotoToggeling(msgs.getString("show_pic"));
125: }
126: return "main";
127: }
128:
129: public String toggleUserIdSort() {
130: Log.debug("toggleUserIdSort()");
131: if (sortUserIdAscending) {
132: setSort(SORT_DESC, Participant.SORT_BY_ID);
133: } else {
134: setSort(SORT_ASC, Participant.SORT_BY_ID);
135: }
136: return "main";
137: }
138:
139: public String toggleLastNameSort() {
140: Log.debug("toggleLastNameSort()");
141: if (sortLastNameAscending) {
142: setSort(SORT_DESC, Participant.SORT_BY_LAST_NAME);
143: } else {
144: setSort(SORT_ASC, Participant.SORT_BY_LAST_NAME);
145: }
146: return "main";
147: }
148:
149: public String toggleRoleSort() {
150: Log.debug("toggleRoleSort()");
151: if (sortRoleAscending) {
152: setSort(SORT_DESC, Participant.SORT_BY_ROLE);
153: } else {
154: setSort(SORT_ASC, Participant.SORT_BY_ROLE);
155: }
156: return "main";
157: }
158:
159: public String toggleSectionsSort() {
160: Log.debug("toggleSectionsSort()");
161: if (sortSectionsAscending) {
162: setSort(SORT_DESC, Participant.SORT_BY_SECTIONS);
163: } else {
164: setSort(SORT_ASC, Participant.SORT_BY_SECTIONS);
165: }
166: return "main";
167: }
168:
169: private void sortRoster() {
170: if (sortRoleDescending)
171: setSort(SORT_DESC, Participant.SORT_BY_ROLE);
172: else if (sortRoleAscending)
173: setSort(SORT_ASC, Participant.SORT_BY_ROLE);
174: if (sortLastNameDescending)
175: setSort(SORT_DESC, Participant.SORT_BY_LAST_NAME);
176: else if (sortLastNameAscending)
177: setSort(SORT_ASC, Participant.SORT_BY_LAST_NAME);
178: else if (sortUserIdDescending)
179: setSort(SORT_DESC, Participant.SORT_BY_ID);
180: else if (sortUserIdAscending)
181: setSort(SORT_ASC, Participant.SORT_BY_ID);
182: else if (sortSectionsDescending)
183: setSort(SORT_DESC, Participant.SORT_BY_SECTIONS);
184: else if (sortSectionsAscending)
185: setSort(SORT_ASC, Participant.SORT_BY_SECTIONS);
186: }
187:
188: private void setSort(String sortOrder, String sortBy) {
189: sortLastNameDescending = false;
190: sortUserIdDescending = false;
191: sortRoleDescending = false;
192: sortSectionsDescending = false;
193: sortLastNameAscending = false;
194: sortUserIdAscending = false;
195: sortRoleAscending = false;
196: sortSectionsAscending = false;
197:
198: if (sortOrder.equals(SORT_ASC)) {
199: if (sortBy.equals(Participant.SORT_BY_ROLE)) {
200: sortRoleAscending = true;
201: rosterManager.sortParticipants(rosterList,
202: Participant.SORT_BY_ROLE, true);
203: this .decoRoster = getRoster(rosterList);
204: return;
205: }
206: if (sortBy.equals(Participant.SORT_BY_ID)) {
207: sortUserIdAscending = true;
208: rosterManager.sortParticipants(rosterList,
209: Participant.SORT_BY_ID, true);
210: this .decoRoster = getRoster(rosterList);
211: return;
212: }
213: if (sortBy.equals(Participant.SORT_BY_LAST_NAME)) {
214: sortLastNameAscending = true;
215: rosterManager.sortParticipants(rosterList,
216: Participant.SORT_BY_LAST_NAME, true);
217: this .decoRoster = getRoster(rosterList);
218: return;
219: }
220: if (sortBy.equals(Participant.SORT_BY_SECTIONS)) {
221: sortSectionsAscending = true;
222: rosterManager.sortParticipants(rosterList,
223: Participant.SORT_BY_SECTIONS, true);
224: this .decoRoster = getRoster(rosterList);
225: return;
226: }
227: } else
228:
229: {
230: if (sortBy.equals(Participant.SORT_BY_ROLE)) {
231: sortRoleDescending = true;
232: rosterManager.sortParticipants(rosterList,
233: Participant.SORT_BY_ROLE, false);
234: this .decoRoster = getRoster(rosterList);
235: return;
236: }
237: if (sortBy.equals(Participant.SORT_BY_ID)) {
238: sortUserIdDescending = true;
239: rosterManager.sortParticipants(rosterList,
240: Participant.SORT_BY_ID, false);
241: this .decoRoster = getRoster(rosterList);
242: return;
243: }
244: if (sortBy.equals(Participant.SORT_BY_LAST_NAME)) {
245: sortLastNameDescending = true;
246: rosterManager.sortParticipants(rosterList,
247: Participant.SORT_BY_LAST_NAME, false);
248: this .decoRoster = getRoster(rosterList);
249: return;
250: }
251: if (sortBy.equals(Participant.SORT_BY_SECTIONS)) {
252: sortSectionsDescending = true;
253: rosterManager.sortParticipants(rosterList,
254: Participant.SORT_BY_SECTIONS, false);
255: this .decoRoster = getRoster(rosterList);
256: return;
257: }
258: }
259: }
260:
261: public boolean isSortLastNameAscending() {
262: Log.debug("isSortLastNameAscending()");
263: return sortLastNameAscending;
264: }
265:
266: public boolean isSortLastNameDescending() {
267: Log.debug("isSortLastNameDescending()");
268: return sortLastNameDescending;
269: }
270:
271: public boolean isSortUserIdAscending() {
272: Log.debug("isSortUserIdAscending()");
273: return sortUserIdAscending;
274: }
275:
276: public boolean isSortUserIdDescending() {
277: Log.debug("isSortUserIdDescending()");
278: return sortUserIdDescending;
279: }
280:
281: public boolean isSortRoleAscending() {
282: Log.debug("isSortRoleAscending()");
283: return sortRoleAscending;
284: }
285:
286: public boolean isSortRoleDescending() {
287: Log.debug("isSortRoleDescending()");
288: return sortRoleDescending;
289: }
290:
291: public boolean isSortSectionsAscending() {
292: Log.debug("isSortSectionsAscending()");
293: return sortSectionsAscending;
294: }
295:
296: public boolean isSortSectionsDescending() {
297: Log.debug("isSortSectionsDescending()");
298: return sortSectionsDescending;
299: }
300:
301: public String processValueChangeForView(ValueChangeEvent vce) {
302: if (Log.isDebugEnabled())
303: Log.debug("processValueChangeForView(ValueChangeEvent "
304: + vce + ")");
305: String changeView = (String) vce.getNewValue();
306: if (changeView != null) {
307: if (!changeView.equalsIgnoreCase(selectedView)) {
308: // don't reload if changing from "View All Sections" or "View All My Sections" to "View No Sections"
309: if (!((changeView
310: .equalsIgnoreCase(RosterManager.VIEW_ALL_SECT) || changeView
311: .equalsIgnoreCase(RosterManager.VIEW_MY_SECT)) && selectedView
312: .equalsIgnoreCase(RosterManager.VIEW_NO_SECT))
313: && !(changeView
314: .equalsIgnoreCase(RosterManager.VIEW_NO_SECT) && (selectedView
315: .equalsIgnoreCase(RosterManager.VIEW_ALL_SECT) || selectedView
316: .equalsIgnoreCase(RosterManager.VIEW_ALL_SECT))))
317: reloadRoster = true;
318: }
319:
320: setSelectedView(changeView);
321: getRoster();
322: }
323: return "main";
324: }
325:
326: public boolean isShowCustomPhoto() {
327: Log.debug("isShowCustomPhoto()");
328: return (showCustomPhoto);
329: }
330:
331: public String getIdPhotoText() {
332: Log.debug("getIdPhotoText()");
333: return idPhotoText;
334: }
335:
336: public String getCustomPhotoText() {
337: Log.debug("getCustomPhotoText()");
338: return customPhotoText;
339: }
340:
341: public String processCancel() {
342: Log.debug("processCancel()");
343: return "main";
344: }
345:
346: public DecoratedParticipant getParticipant() {
347: Log.debug("getParticipant()");
348: return participant;
349: }
350:
351: public RosterManager getRosterManager() {
352: Log.debug("getRosterManager()");
353: return rosterManager;
354: }
355:
356: public void setRosterManager(RosterManager rosterManager) {
357: if (Log.isDebugEnabled()) {
358: Log.debug("setRosterManager(RosterManager " + rosterManager
359: + ")");
360: }
361: this .rosterManager = rosterManager;
362: }
363:
364: public ProfileManager getProfileManager() {
365: Log.debug("getProfileManager()");
366: return profileManager;
367: }
368:
369: public boolean isShowIdPhoto() {
370: Log.debug("isShowIdPhoto()");
371: return (showIdPhoto);
372: }
373:
374: public void setProfileManager(ProfileManager profileService) {
375:
376: if (Log.isDebugEnabled()) {
377: Log.debug("setProfileManager(ProfileManager "
378: + profileService + ")");
379: }
380: this .profileManager = profileService;
381: }
382:
383: public boolean isShowTool() {
384: Log.debug("isShowTool()");
385: return profileManager.isShowTool();
386: }
387:
388: public String getTitle() {
389: Log.debug("getTitle()");
390: return title;
391: }
392:
393: public String getFacet() {
394: Log.debug("getFacet()");
395: return facet;
396: }
397:
398: public String getSelectedView() {
399: Log.debug("getSelectedView()");
400: return selectedView;
401: }
402:
403: public void setSelectedView(String selected) {
404: Log.debug("setSelectedView(String " + selected + ")");
405: this .selectedView = selected;
406: }
407:
408: public boolean isRenderPhotoColumn() {
409: Log.debug("isRenderPhotoColumn()");
410: return (isShowIdPhoto() || isShowCustomPhoto());
411: }
412:
413: public boolean isRenderExportButton() {
414: return rosterManager.currentUserHasExportPerm()
415: && isRenderRoster();
416: }
417:
418: public boolean isRenderOfficialId() {
419: return rosterManager.currentUserHasViewOfficialIdPerm();
420: }
421:
422: public boolean isRenderSectionsColumn() {
423: if (selectedView.equals(RosterManager.VIEW_NO_SECT))
424: return false;
425:
426: return isRenderViewMenu();
427: }
428:
429: public boolean isRenderViewMenu() {
430: getViewMenuItems();
431: if (menuItems != null && !menuItems.isEmpty())
432: return true;
433:
434: return false;
435: }
436:
437: public boolean isRenderRoster() {
438: if (!rosterProcessed)
439: getRoster();
440:
441: return decoRoster != null && decoRoster.size() > 0;
442: }
443:
444: public boolean isRenderRosterUpdateInfo() {
445: return rosterManager.currentUserHasSiteUpdatePerm();
446: }
447:
448: public boolean isUserMayViewRoster() {
449: return rosterManager.currentUserHasViewAllPerm()
450: || rosterManager.currentUserHasViewSectionPerm();
451: }
452:
453: public List getRoster() {
454: Log.debug("getRoster()");
455: if (reloadRoster || decoRoster == null) {
456: rosterList = rosterManager.getRoster(selectedView);
457: sortRoster(); // allows us to maintain the previously selected sort view
458: reloadRoster = false;
459: rosterProcessed = true;
460: decoRoster = getRoster(rosterList);
461: }
462: return decoRoster;
463: }
464:
465: private List getRoster(List list) {
466: Log.debug("getAllUsers()");
467: decoRoster = new ArrayList();
468:
469: Map roleMap = new HashMap();
470: if (list == null || list.size() < 1) {
471: return null;
472: }
473:
474: this .allUserCount = list.size();
475: Iterator iter = list.iterator();
476:
477: while (iter.hasNext()) {
478: DecoratedParticipant dp = new DecoratedParticipant(
479: (Participant) iter.next());
480:
481: String dpTitle = dp.getParticipant().getRoleTitle();
482:
483: Long roleCount = (Long) roleMap.get(dpTitle) == null ? 0
484: : (Long) roleMap.get(dpTitle);
485: roleMap.put(dpTitle, ++roleCount);
486:
487: decoRoster.add(dp);
488:
489: }
490: this .roleStats = new ArrayList(roleMap.entrySet());
491:
492: return decoRoster;
493: }
494:
495: public List getRoleStats() {
496: return roleStats;
497: }
498:
499: public int getAllUserCount() {
500: Log.debug("getAllUserCount()");
501: return allUserCount;
502: }
503:
504: public void setViewMenuItems(List menuItems) {
505: this .menuItems = menuItems;
506: }
507:
508: /**
509: * Returns the list of items to populate the "View" menu
510: * @return
511: */
512: public List getViewMenuItems() {
513: if (menuItems != null)
514: return menuItems;
515:
516: List selectItemList = new ArrayList();
517:
518: List viewableSections = rosterManager
519: .getViewableSectionsForCurrentUser();
520:
521: if (viewableSections != null && !viewableSections.isEmpty()) {
522: Collections.sort(viewableSections); // display the sections in ABC order in menu
523:
524: selectItemList.add(new SelectItem(
525: RosterManager.VIEW_NO_SECT, msgs
526: .getString("roster_viewNoSections")));
527:
528: if (rosterManager.currentUserHasViewAllPerm()) {
529: selectItemList.add(new SelectItem(
530: RosterManager.VIEW_ALL_SECT, msgs
531: .getString("roster_viewAllSections")));
532: } else if (rosterManager.currentUserHasViewSectionPerm()) {
533: selectItemList
534: .add(new SelectItem(
535: RosterManager.VIEW_MY_SECT,
536: msgs
537: .getString("roster_viewAllMySections")));
538: }
539:
540: for (Iterator i = viewableSections.iterator(); i.hasNext();) {
541: String section = (String) i.next();
542: selectItemList.add(new SelectItem(section, section));
543: }
544: }
545:
546: menuItems = selectItemList;
547: return selectItemList;
548: }
549:
550: public String getDisplayedSection() {
551: if (selectedView.equals(RosterManager.VIEW_NO_SECT)
552: || selectedView.equals(RosterManager.VIEW_ALL_SECT)
553: || selectedView.equals(RosterManager.VIEW_MY_SECT))
554: return null;
555:
556: return selectedView;
557: }
558:
559: public String getPrintFriendlyTitle() {
560: try {
561: Site currentSite = SiteService.getSite(ToolManager
562: .getCurrentPlacement().getContext());
563: String siteTitle = currentSite.getTitle();
564: return msgs.getString("print_title_for") + " " + siteTitle;
565: } catch (Exception e) {
566: return msgs.getString("print_title");
567: }
568: }
569:
570: public String getPrintFriendlyUrl() {
571: String url = ServerConfigurationService.getToolUrl()
572: + Entity.SEPARATOR
573: + ToolManager.getCurrentPlacement().getId()
574: + Entity.SEPARATOR + "printFriendlyRoster";
575: return url;
576:
577: }
578:
579: /**
580: * Set variables for photo display
581: *
582: * @param option
583: */
584: private void setPhotoToggeling(String option) {
585: if (Log.isDebugEnabled()) {
586: Log.debug("setPhotoToggeling(String " + option + ")");
587: }
588: if (option != null
589: && option.equals(msgs.getString("show_id_photo")))// show official
590: {
591: this .idPhotoText = msgs.getString("hide_id_photo");
592: this .showIdPhoto = true;
593: this .customPhotoText = msgs.getString("show_pic");
594: this .showCustomPhoto = false;
595: this .title = msgs.getString("title_view_official");
596: this .facet = msgs.getString("facet_official");
597: } else if (option != null
598: && option.equals(msgs.getString("show_pic")))// show custom
599: {
600: this .idPhotoText = msgs.getString("show_id_photo");
601: this .customPhotoText = msgs.getString("hide_pic");
602: this .showIdPhoto = false;
603: this .showCustomPhoto = true;
604: this .title = msgs.getString("title_view_pictures");
605: this .facet = msgs.getString("facet_picture");
606: } else
607: // hide all
608: {
609: this .idPhotoText = msgs.getString("show_id_photo");
610: this .showIdPhoto = false;
611: this .customPhotoText = msgs.getString("show_pic");
612: this .showCustomPhoto = false;
613: this .title = msgs.getString("title_show_roster");
614: this .facet = "";
615: }
616:
617: }
618:
619: public String processActionDisplayProfile() {
620: Log.debug("processActionDisplayProfile()");
621: try {
622: ExternalContext context = FacesContext.getCurrentInstance()
623: .getExternalContext();
624: Map paramMap = context.getRequestParameterMap();
625: String participantId = (String) paramMap
626: .get(PARTICIPANT_ID);
627: participant = new DecoratedParticipant(rosterManager
628: .getParticipantById(participantId));
629: if (participant.getParticipant().getProfile() != null) {
630: if (participant.isDisplayCompleteProfile()) {
631: return "displayCompleteProfile";
632: }
633: if (participant.displayPublicProfile()) {
634: return "displayPublicProfile";
635: }
636: }
637: return "profileNotFound";
638: } catch (Exception e) {
639: Log.error(e.getMessage(), e);
640: return "profileNotFound";
641: }
642: }
643:
644: public class DecoratedParticipant {
645:
646: protected Participant decoratedParticipant;
647: protected boolean showCustomPhotoUnavailable = false;
648:
649: public DecoratedParticipant(Participant decParticipant) {
650: if (Log.isDebugEnabled()) {
651: Log.debug("DecoratedParticipant(Participant "
652: + decParticipant + ")");
653: }
654: this .decoratedParticipant = decParticipant;
655: }
656:
657: // User Profile: display a emplty url or no blocked profile
658: public boolean isShowCustomPhotoUnavailable() {
659: Log.debug("isShowCustomPhotoUnavailable()");
660: if (!showCustomPhoto) {
661: return false;
662: }
663: return isShowCustomPhotoUnavailableForSelectedProfile();
664: }
665:
666: public boolean isShowCustomPhotoUnavailableForSelectedProfile() {
667: Log
668: .debug("isShowCustomPhotoUnavailableForSelectedProfile()");
669: if (decoratedParticipant.getProfile() == null) {
670: return true;
671: }
672: if (!profileManager
673: .displayCompleteProfile(decoratedParticipant
674: .getProfile())) {
675: return true;
676: }
677:
678: if (decoratedParticipant.getProfile()
679: .isInstitutionalPictureIdPreferred() == null) {
680: return true;
681: }
682: if (!decoratedParticipant.getProfile()
683: .isInstitutionalPictureIdPreferred().booleanValue()
684: && (decoratedParticipant.getProfile()
685: .getPictureUrl() == null || decoratedParticipant
686: .getProfile().getPictureUrl().length() < 1)) {
687: return true;
688: }
689: return false;
690: }
691:
692: // User Profile : display a non empty url
693: public boolean isShowURLPhoto() {
694:
695: Log.debug("isShowURLPhoto()");
696: if (!showCustomPhoto) {
697: return false;
698: }
699: return isShowURLPhotoForSelectedProfile();
700: }
701:
702: public boolean isShowURLPhotoForSelectedProfile() {
703: Log.debug("isShowURLPhotoForSelectedProfile()");
704: if (decoratedParticipant.getProfile() == null) {
705: return false;
706: }
707: if (profileManager
708: .displayCompleteProfile(decoratedParticipant
709: .getProfile())
710: && decoratedParticipant.getProfile()
711: .getPictureUrl() != null
712: && decoratedParticipant.getProfile()
713: .getPictureUrl().length() > 0) {
714: return true;
715: }
716: return false;
717: }
718:
719: // User Profile : display id Photo
720: public boolean isShowCustomIdPhoto() {
721: Log.debug("isShowCustomIdPhoto()");
722: if (!showCustomPhoto) {
723: return false;
724: }
725: return isShowCustomIdPhotoForSelectedProfile();
726:
727: }
728:
729: public boolean isShowCustomIdPhotoForSelectedProfile() {
730: Log.debug("isShowCustomIdPhotoForSelectedProfile");
731: if (decoratedParticipant.getProfile() == null) {
732: return false;
733: }
734: if (decoratedParticipant.getProfile()
735: .isInstitutionalPictureIdPreferred() == null) {
736: return false;
737: }
738: if (profileManager
739: .displayCompleteProfile(decoratedParticipant
740: .getProfile())
741: && decoratedParticipant.getProfile()
742: .isInstitutionalPictureIdPreferred()
743: .booleanValue()) {
744: return true;
745: }
746: return false;
747: }
748:
749: public Participant getParticipant() {
750: Log.debug("getParticipant()");
751: return decoratedParticipant;
752: }
753:
754: public boolean isDisplayCompleteProfile() {
755: Log.debug("isDisplayCompleteProfile()");
756: return profileManager
757: .displayCompleteProfile(decoratedParticipant
758: .getProfile());
759: }
760:
761: // if only public profile should be displayed.
762: public boolean displayPublicProfile() {
763: Log.debug("displayPublicProfile()");
764: if (decoratedParticipant.getProfile() == null) {
765: return false;
766: }
767: if (profileManager
768: .displayCompleteProfile(decoratedParticipant
769: .getProfile())) {
770: return true;
771: }
772: if (decoratedParticipant.getProfile().getHidePublicInfo() == null) {
773: return false;
774: }
775: if (decoratedParticipant.getProfile().getHidePublicInfo()
776: .booleanValue() == true) {
777: return false;
778: }
779: if (decoratedParticipant.getProfile().getHidePrivateInfo() == null) {
780: return true;
781: }
782: if (decoratedParticipant.getProfile().getHidePrivateInfo()
783: .booleanValue() == true) {
784: return true;
785: }
786:
787: return false;
788: }
789: }
790:
791: /**
792: * Determine whether privacy message should be displayed. Will be shown if
793: * roster.privacy.display in sakai.properties is "true" and the user does not
794: * have roster.viewhidden permission
795: * @return
796: */
797: public boolean isRenderPrivacyMessage() {
798: String msgEnabled = ServerConfigurationService
799: .getString(DISPLAY_ROSTER_PRIVACY_MSG);
800: if (msgEnabled != null && msgEnabled.equalsIgnoreCase("true")
801: && !rosterManager.currentUserHasViewHiddenPerm()) {
802: return true;
803: }
804:
805: return false;
806: }
807:
808: /* Note: The CSV export code below was largely copied from
809: * Gradebook - org.sakai.tool.gradebook.ui.ExportBean */
810:
811: /**
812: * Export the current roster view to a csv file
813: * @param event
814: */
815: public void exportRosterCsv(ActionEvent event) {
816: writeAsCsv(getRosterAsCSV(isRenderSectionsColumn()),
817: getFileName());
818: }
819:
820: /**
821: * returns a comma-delimited string representation of the current roster view
822: * @param showSectionsCol
823: * @return
824: */
825: private String getRosterAsCSV(boolean showSectionsCol) {
826: if (rosterList == null || rosterList.isEmpty())
827: return "";
828:
829: StringBuffer sb = new StringBuffer();
830:
831: // Add the headers
832: sb.append(msgs.getString("export_name"));
833: sb.append(CSV_DELIM);
834: sb.append(msgs.getString("export_userId"));
835: sb.append(CSV_DELIM);
836: sb.append(msgs.getString("export_role"));
837: sb.append(CSV_DELIM);
838: if (showSectionsCol) {
839: sb.append(msgs.getString("export_sections"));
840: sb.append(CSV_DELIM);
841: }
842: sb.append("\n");
843:
844: // Add the data
845: for (Iterator rosterIter = rosterList.iterator(); rosterIter
846: .hasNext();) {
847: Participant participant = (Participant) rosterIter.next();
848: appendQuoted(sb, participant.getLastName() + ", "
849: + participant.getFirstName());
850: sb.append(CSV_DELIM);
851: sb.append(participant.getEid());
852: sb.append(CSV_DELIM);
853: sb.append(participant.getRoleTitle());
854: sb.append(CSV_DELIM);
855: if (showSectionsCol) {
856: appendQuoted(sb, participant.getSectionsForDisplay());
857: sb.append(CSV_DELIM);
858: }
859:
860: sb.append("\n");
861: }
862: return sb.toString();
863: }
864:
865: private StringBuffer appendQuoted(StringBuffer sb, String toQuote) {
866: if ((toQuote.indexOf(',') >= 0) || (toQuote.indexOf('"') >= 0)) {
867: String out = toQuote.replaceAll("\"", "\"\"");
868: sb.append("\"").append(out).append("\"");
869: } else {
870: sb.append(toQuote);
871: }
872: return sb;
873: }
874:
875: /**
876: * @param csvString
877: * @param fileName
878: */
879: private void writeAsCsv(String csvString, String fileName) {
880: FacesContext faces = FacesContext.getCurrentInstance();
881: HttpServletResponse response = (HttpServletResponse) faces
882: .getExternalContext().getResponse();
883: protectAgainstInstantDeletion(response);
884: response.setContentType("text/comma-separated-values");
885: response.setHeader("Content-disposition",
886: "attachment; filename=" + fileName + ".csv");
887: response.setContentLength(csvString.length());
888: OutputStream out = null;
889: try {
890: out = response.getOutputStream();
891: out.write(csvString.getBytes());
892: out.flush();
893: } catch (IOException e) {
894: Log.error(e);
895: e.printStackTrace();
896: } finally {
897: try {
898: if (out != null)
899: out.close();
900: } catch (IOException e) {
901: Log.error(e);
902: e.printStackTrace();
903: }
904: }
905: faces.responseComplete();
906: }
907:
908: /**
909: * Gets the filename for the export
910: *
911: * @return The appropriate filename for the export
912: */
913: private String getFileName() {
914: String prefix = msgs.getString("export_filename_prefix");
915: Date now = new Date();
916: DateFormat df = new SimpleDateFormat(msgs
917: .getString("export_filename_date_format"));
918: StringBuffer fileName = new StringBuffer(prefix);
919: String siteId = ToolManager.getCurrentPlacement().getContext();
920: if (siteId.trim() != null) {
921: siteId = siteId.replaceAll("\\s", "_"); // replace whitespace with '_'
922: fileName.append("_");
923: fileName.append(siteId);
924: }
925: fileName.append("_");
926: fileName.append(df.format(now));
927: return fileName.toString();
928: }
929:
930: /**
931: * Try to head off a problem with downloading files from a secure HTTPS
932: * connection to Internet Explorer.
933: *
934: * When IE sees it's talking to a secure server, it decides to treat all hints
935: * or instructions about caching as strictly as possible. Immediately upon
936: * finishing the download, it throws the data away.
937: *
938: * Unfortunately, the way IE sends a downloaded file on to a helper
939: * application is to use the cached copy. Having just deleted the file,
940: * it naturally isn't able to find it in the cache. Whereupon it delivers
941: * a very misleading error message like:
942: * "Internet Explorer cannot download roster from sakai.yoursite.edu.
943: * Internet Explorer was not able to open this Internet site. The requested
944: * site is either unavailable or cannot be found. Please try again later."
945: *
946: * There are several ways to turn caching off, and so to be safe we use
947: * several ways to turn it back on again.
948: *
949: * This current workaround should let IE users save the files to disk.
950: * Unfortunately, errors may still occur if a user attempts to open the
951: * file directly in a helper application from a secure web server.
952: *
953: * TODO Keep checking on the status of this.
954: */
955: public static void protectAgainstInstantDeletion(
956: HttpServletResponse response) {
957: response.reset(); // Eliminate the added-on stuff
958: response.setHeader("Pragma", "public"); // Override old-style cache control
959: response
960: .setHeader("Cache-Control",
961: "public, must-revalidate, post-check=0, pre-check=0, max-age=0"); // New-style
962: }
963:
964: }
|