/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/roster/trunk/roster-app/src/java/org/sakaiproject/tool/roster/RosterOverview.java $
* $Id: RosterOverview.java 51318 2008-08-24 05:28:47Z csev@umich.edu $
***********************************************************************************
*
* Copyright (c) 2007 Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.sakaiproject.tool.roster;
import java.text.Collator;
import java.text.ParseException;
import java.text.RuleBasedCollator;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.Map.Entry;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.api.app.roster.Participant;
import org.sakaiproject.api.app.roster.RosterFunctions;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterXls;
import org.sakaiproject.jsf.spreadsheet.SpreadsheetUtil;
import org.sakaiproject.jsf.util.LocaleUtil;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService;
public class RosterGroupMembership extends BaseRosterPageBean {
private static final Log log = LogFactory.getLog(RosterGroupMembership.class);
private static final String DISPLAY_ROSTER_PRIVACY_MSG = "roster.privacy.display";
// UI method calls
public boolean isGroupedBy() {
return filter.isGroupedBy();
}
@SuppressWarnings("unchecked")
public Collection<GroupedParticipants> getGroupedParticipants() {
List<GroupedParticipants> groupedParticipants = null;
Site site = null;
try {
site = filter.services.siteService.getSite(filter.getSiteReference().substring(6));
} catch (IdUnusedException e) {
log.error("Unable to find site for: " + getSiteReference() + " " + e.getMessage(), e);
return null;
}
if (site != null) {
groupedParticipants = new ArrayList<GroupedParticipants>();
Collection<Group> groups = (Collection<Group>) site.getGroups();
//Use a HashSet because we'll have to use .removeAll() on it many times
//.remove() is roughly constant time for a HashSet.
Set<Participant> unassignedParticipants = new HashSet<Participant>(
filter.services.rosterManager.getRoster()
);
for(Iterator<Group> groupIter = groups.iterator(); groupIter.hasNext();)
{
Group group = groupIter.next();
List<Participant> roster = filter.services.rosterManager.getRoster(group.getReference());
//remove each grouped participant from the 'unassignedParticipants' set
unassignedParticipants.removeAll(roster);
Collections.sort(roster, getComparator());
if (!prefs.sortAscending) {
Collections.reverse(roster);
}
groupedParticipants.add(new GroupedParticipants(group.getTitle(), roster, roster.size(), getRoleCountMessage(filter.findRoleCounts(roster))));
}
// if we have participants who are ungrouped, we add them here to a new one for rendering called "Unassigned"
if (!unassignedParticipants.isEmpty())
{
String unassigned = LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(), ServicesBean.MESSAGE_BUNDLE, "roster_group_unassigned");
List<Participant> unassignedList = new ArrayList<Participant>(unassignedParticipants);
Collections.sort(unassignedList, getComparator());
if (!prefs.sortAscending) {
Collections.reverse(unassignedList);
}
groupedParticipants.add(
new GroupedParticipants(
unassigned,
unassignedList,
unassignedParticipants.size(),
getRoleCountMessage(filter.findRoleCounts(unassignedParticipants))
)
);
}
Collections.sort(groupedParticipants, sortByGroup());
}
return groupedParticipants;
}
public class GroupedParticipants {
Collection<Participant> groupedParticipants = new ArrayList<Participant>();
String groupTitle;
int groupedParticipantCount;
String roleCountMessage;
public int getGroupedParticipantCount() {
return groupedParticipantCount;
}
public void setGroupedParticipantCount(int groupedParticipantCount) {
this.groupedParticipantCount = groupedParticipantCount;
}
public String getGroupTitle() {
return groupTitle;
}
public void setGroupTitle(String groupTitle) {
this.groupTitle = groupTitle;
}
public Collection<Participant> getGroupedParticipants() {
return groupedParticipants;
}
public void setGroupedParticipants(Collection<Participant> groupedParticipants) {
this.groupedParticipants = groupedParticipants;
}
public String getRoleCountMessage() {
return roleCountMessage;
}
public void setRoleCountMessage(String roleCountMessage) {
this.roleCountMessage = roleCountMessage;
}
public GroupedParticipants() {}
public GroupedParticipants(String groupTitle, Collection<Participant> groupedParticipants, int groupedParticipantCount, String roleCountMessage) {
this.groupTitle = groupTitle;
this.groupedParticipants = groupedParticipants;
this.groupedParticipantCount = groupedParticipantCount;
this.roleCountMessage = roleCountMessage;
}
}
private Comparator<GroupedParticipants> sortByGroup() {
Comparator<GroupedParticipants> groupComparator = new Comparator<GroupedParticipants>() {
Collator r_collator;
{
r_collator = Collator.getInstance();
try
{
r_collator = new RuleBasedCollator(((RuleBasedCollator)Collator.getInstance()).getRules().replaceAll("<'\u005f'", "<' '<'\u005f'"));
}
catch(ParseException e)
{
log.warn(this + " Cannot init RuleBasedCollator. Will use the default Collator instead.", e);
}
}
public int compare(GroupedParticipants one, GroupedParticipants another)
{
return r_collator.compare(one.getGroupTitle(), another.getGroupTitle());
}
};
return groupComparator;
}
private String getRoleCountMessage(SortedMap<String, Integer> roleCounts) {
if(roleCounts.size() == 0) return "";
StringBuilder sb = new StringBuilder();
sb.append("(");
for(Iterator<Entry<String, Integer>> iter = roleCounts.entrySet().iterator(); iter.hasNext();) {
Entry<String, Integer> entry = iter.next();
String[] params = new String[] {entry.getValue().toString(), entry.getKey()};
sb.append(getFormattedMessage("role_breakdown_fragment", params));
if (iter.hasNext()) {
sb.append(", ");
}
}
sb.append(")");
return sb.toString();
}
private String getFormattedMessage(String key, String[] params) {
String rawString = LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(), ServicesBean.MESSAGE_BUNDLE, key);
MessageFormat format = new MessageFormat(rawString);
return format.format(params);
}
public boolean isRenderModifyMembersInstructions() {
String siteRef = getSiteReference();
return filter.services.securityService.unlock(SiteService.SECURE_UPDATE_SITE, siteRef) ||
filter.services.securityService.unlock(SiteService.SECURE_UPDATE_SITE_MEMBERSHIP, siteRef);
}
/**
* Determine whether privacy message should be displayed. Will be shown if
* roster.privacy.display in sakai.properties is "true" and the user does
* not have roster.viewhidden permission
*
* @return
*/
public boolean isRenderPrivacyMessage() {
String msgEnabled = ServerConfigurationService.getString(DISPLAY_ROSTER_PRIVACY_MSG, Boolean.TRUE.toString());
if (Boolean.TRUE.toString().equalsIgnoreCase(msgEnabled)) {
return ! filter.services.securityService.unlock(RosterFunctions.ROSTER_FUNCTION_VIEWHIDDEN, getSiteReference());
} else {
return ! filter.services.securityService.unlock(RosterFunctions.ROSTER_FUNCTION_VIEWALL, getSiteReference());
}
}
public String getPageTitle() {
filter.services.eventTrackingService.post(filter.services.eventTrackingService.newEvent("roster.view",getSiteReference(),false));
return LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(),
ServicesBean.MESSAGE_BUNDLE, "title_group_membership");
}
public boolean isExportablePage() {
return filter.services.rosterManager.currentUserHasExportPerm();
}
public void export(ActionEvent event) {
List<List<Object>> spreadsheetData = new ArrayList<List<Object>>();
FacesContext facesContext = FacesContext.getCurrentInstance();
// Add the header row
List<Object> header = new ArrayList<Object>();
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_name"));
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_userId"));
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_role"));
header.add(LocaleUtil.getLocalizedString(facesContext, ServicesBean.MESSAGE_BUNDLE, "facet_groups"));
if (isGroupedBy())
{
for (Iterator<GroupedParticipants> gp = getGroupedParticipants().iterator(); gp.hasNext();)
{
GroupedParticipants gpList = gp.next();
List<Object> groupTitleRow = new ArrayList<Object>();
List<Object> blankRow = new ArrayList<Object>();
blankRow.add("");
spreadsheetData.add(blankRow);
groupTitleRow.add(gpList.getGroupTitle());
spreadsheetData.add(groupTitleRow);
spreadsheetData.add(blankRow);
spreadsheetData.add(header);
for(Iterator<Participant> participantIter = gpList.getGroupedParticipants().iterator(); participantIter.hasNext();) {
Participant participant = participantIter.next();
List<Object> row = new ArrayList<Object>();
row.add(participant.getUser().getSortName());
row.add(participant.getUser().getDisplayId());
row.add(participant.getRoleTitle());
row.add(participant.getGroupsString());
spreadsheetData.add(row);
}
}
}
else
{
spreadsheetData.add(header);
for(Iterator<Participant> participantIter = getParticipants().iterator(); participantIter.hasNext();) {
Participant participant = participantIter.next();
List<Object> row = new ArrayList<Object>();
row.add(participant.getUser().getSortName());
row.add(participant.getUser().getDisplayId());
row.add(participant.getRoleTitle());
row.add(participant.getGroupsString());
spreadsheetData.add(row);
}
}
String spreadsheetNameRaw = filter.getCourseFilterTitle();
if (isGroupedBy())
{
spreadsheetNameRaw = spreadsheetNameRaw + "_ByGroup";
}
else
{
spreadsheetNameRaw = spreadsheetNameRaw + "_Ungrouped";
}
String spreadsheetName = getDownloadFileName(spreadsheetNameRaw);
SpreadsheetUtil.downloadSpreadsheetData(spreadsheetData, spreadsheetName, new SpreadsheetDataFileWriterXls());
}
}