/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/sections/trunk/sections-app/src/java/org/sakaiproject/tool/section/jsf/backingbean/RosterBean.java $ * $Id: RosterBean.java 105080 2012-02-24 23:10:31Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2005, 2006, 2007, 2008 The 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.section.jsf.backingbean; import java.io.Serializable; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import javax.faces.application.Application; import javax.faces.component.UIColumn; import javax.faces.component.html.HtmlDataTable; import javax.faces.component.html.HtmlOutputText; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import javax.faces.model.SelectItem; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.myfaces.custom.sortheader.HtmlCommandSortHeader; import org.sakaiproject.jsf.spreadsheet.SpreadsheetDataFileWriterXls; import org.sakaiproject.jsf.spreadsheet.SpreadsheetUtil; import org.sakaiproject.section.api.coursemanagement.CourseSection; import org.sakaiproject.section.api.coursemanagement.EnrollmentRecord; import org.sakaiproject.section.api.coursemanagement.ParticipationRecord; import org.sakaiproject.section.api.coursemanagement.SectionEnrollments; import org.sakaiproject.tool.section.decorator.EnrollmentDecorator; import org.sakaiproject.tool.section.jsf.JsfUtil; /** * Controls the roster page. * * @author <a href="mailto:jholtzman@berkeley.edu">Josh Holtzman</a> * */ public class RosterBean extends CourseDependentBean implements Serializable { private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(RosterBean.class); private static final String CAT_COLUMN_PREFIX = "cat"; private String searchText; private int firstRow; private int enrollmentsSize; private boolean externallyManaged; private List<SelectItem> filterItems; private List<EnrollmentDecorator> enrollments; private List<String> categories; private List<EnrollmentRecord> siteStudents; public void init() { // Determine whether this course is externally managed externallyManaged = getSectionManager().isExternallyManaged(getCourse().getUuid()); // Get the section categories categories = getSectionManager().getSectionCategories(getSiteContext()); // Get the default search text if(StringUtils.trimToNull(searchText) == null) { searchText = JsfUtil.getLocalizedMessage("roster_search_text"); } // Get the site enrollments //List<EnrollmentRecord> siteStudents; if(searchText.equals(JsfUtil.getLocalizedMessage("roster_search_text"))) { siteStudents = getSectionManager().getSiteEnrollments(getSiteContext()); } else { siteStudents = getSectionManager().findSiteEnrollments(getSiteContext(), searchText); } // Get the section enrollments Set<String> studentUids = new HashSet<String>(); for(Iterator iter = siteStudents.iterator(); iter.hasNext();) { ParticipationRecord record = (ParticipationRecord)iter.next(); studentUids.add(record.getUser().getUserUid()); } SectionEnrollments sectionEnrollments = getSectionManager().getSectionEnrollmentsForStudents(getSiteContext(), studentUids); // Construct the list of filter items filterItems = new ArrayList<SelectItem>(); filterItems.add(new SelectItem("", JsfUtil.getLocalizedMessage("filter_all_sections"))); filterItems.add(new SelectItem("MY", JsfUtil.getLocalizedMessage("filter_my_category_sections", new String[] {""}))); for(Iterator<String> iter = categories.iterator(); iter.hasNext();) { String cat = iter.next(); filterItems.add(new SelectItem(cat, JsfUtil.getLocalizedMessage("filter_my_category_sections", new String[] {getCategoryName(cat)}))); } // If this is a TA, and we're filtering, get the TA's participation records List<CourseSection> assignedSections = null; if(StringUtils.trimToNull(getFilter()) != null) { assignedSections = findAssignedSections(); } // Construct the decorated enrollments for the UI decorateEnrollments(siteStudents, sectionEnrollments, assignedSections); } private void decorateEnrollments(List<EnrollmentRecord> siteStudents, SectionEnrollments sectionEnrollments, List<CourseSection> assignedSections) { List<EnrollmentDecorator> unpagedEnrollments = new ArrayList<EnrollmentDecorator>(); for(Iterator<EnrollmentRecord> studentIter = siteStudents.iterator(); studentIter.hasNext();) { EnrollmentRecord enrollment = studentIter.next(); // Build a map of categories to sections in which the student is enrolled Map<String, CourseSection> map = new HashMap<String, CourseSection>(); for(Iterator catIter = categories.iterator(); catIter.hasNext();) { String cat = (String)catIter.next(); CourseSection section = sectionEnrollments.getSection(enrollment.getUser().getUserUid(), cat); map.put(cat, section); } // Check to see whether this enrollment should be filtered out boolean includeStudent = false; if(StringUtils.trimToNull(getFilter()) == null) { includeStudent = true; } else { for(Iterator<Entry<String, CourseSection>> entryIter = map.entrySet().iterator(); entryIter.hasNext();) { Entry<String, CourseSection> entry = entryIter.next(); CourseSection section = entry.getValue(); // Some map entries won't have a section at all, since the student isn't in any section of that category if(section == null) { continue; } if("MY".equals(getFilter()) && assignedSections.contains(section)) { includeStudent = true; break; } else if(section.getCategory().equals(getFilter()) && assignedSections.contains(section)) { includeStudent = true; break; } } } if(includeStudent) { EnrollmentDecorator decorator = new EnrollmentDecorator(enrollment, map); unpagedEnrollments.add(decorator); } } // Sort the list Collections.sort(unpagedEnrollments, getComparator()); // Filter the list of enrollments enrollments = new ArrayList<EnrollmentDecorator>(); int lastRow; int maxDisplayedRows = getPrefs().getRosterMaxDisplayedRows(); if(maxDisplayedRows < 1 || firstRow + maxDisplayedRows > unpagedEnrollments.size()) { lastRow = unpagedEnrollments.size(); } else { lastRow = firstRow + maxDisplayedRows; } enrollments.addAll(unpagedEnrollments.subList(firstRow, lastRow)); enrollmentsSize = unpagedEnrollments.size(); } private List<CourseSection> findAssignedSections() { List<CourseSection> assignedSections = new ArrayList<CourseSection>(); for(Iterator<CourseSection> secIter = getSectionManager().getSections(getSiteContext()).iterator(); secIter.hasNext();) { CourseSection section = secIter.next(); List<ParticipationRecord> tas = getSectionManager().getSectionTeachingAssistants(section.getUuid()); for(Iterator<ParticipationRecord> taIter = tas.iterator(); taIter.hasNext();) { ParticipationRecord ta = taIter.next(); if(ta.getUser().getUserUid().equals(getUserUid())) { assignedSections.add(section); break; } } } return assignedSections; } private Comparator<EnrollmentDecorator> getComparator() { String sortColumn = getPrefs().getRosterSortColumn(); boolean sortAscending = getPrefs().isRosterSortAscending(); if("studentName".equals(sortColumn)) { return EnrollmentDecorator.getNameComparator(sortAscending); } else if("displayId".equals(sortColumn)) { return EnrollmentDecorator.getDisplayIdComparator(sortAscending); } else { return EnrollmentDecorator.getCategoryComparator(sortColumn, sortAscending); } } public HtmlDataTable getRosterDataTable() { return null; } public void setRosterDataTable(HtmlDataTable rosterDataTable) { Set usedCategories = getUsedCategories(); if (rosterDataTable.findComponent(CAT_COLUMN_PREFIX + "0") == null) { Application app = FacesContext.getCurrentInstance().getApplication(); // Add columns for each category. Be sure to create unique IDs // for all child components. int colpos = 0; for (Iterator iter = usedCategories.iterator(); iter.hasNext(); colpos++) { String category = (String)iter.next(); String categoryName = getCategoryName(category); UIColumn col = new UIColumn(); col.setId(CAT_COLUMN_PREFIX + colpos); HtmlCommandSortHeader sortHeader = new HtmlCommandSortHeader(); sortHeader.setId(CAT_COLUMN_PREFIX + "sorthdr_" + colpos); sortHeader.setRendererType("org.apache.myfaces.SortHeader"); sortHeader.setArrow(true); sortHeader.setColumnName(category); //sortHeader.setActionListener(app.createMethodBinding("#{rosterBean.sort}", new Class[] {ActionEvent.class})); HtmlOutputText headerText = new HtmlOutputText(); headerText.setId(CAT_COLUMN_PREFIX + "hdr_" + colpos); headerText.setValue(categoryName); sortHeader.getChildren().add(headerText); col.setHeader(sortHeader); HtmlOutputText contents = new HtmlOutputText(); contents.setId(CAT_COLUMN_PREFIX + "cell_" + colpos); contents.setValueBinding("value", app.createValueBinding("#{enrollment.categoryToSectionMap['" + category + "'].title}")); col.getChildren().add(contents); rosterDataTable.getChildren().add(col); } } } public void search(ActionEvent event) { // firstRow = 0; } public void clearSearch(ActionEvent event) { firstRow = 0; searchText = null; } public List getEnrollments() { return enrollments; } public int getEnrollmentsSize() { return enrollmentsSize; } public boolean isExternallyManaged() { return externallyManaged; } public String getSearchText() { return searchText; } public void setSearchText(String searchText) { if (StringUtils.trimToNull(searchText) == null) { searchText = JsfUtil.getLocalizedMessage("roster_search_text"); } if (!StringUtils.equals(searchText, this.searchText)) { if (log.isDebugEnabled()) log.debug("setSearchString " + searchText); this.searchText = searchText; setFirstRow(0); // clear the paging when we update the search } } public int getFirstRow() { return firstRow; } public void setFirstRow(int firstRow) { this.firstRow = firstRow; } public String getFilter() { return getPrefs().getRosterFilter(); } public void setFilter(String filter) { getPrefs().setRosterFilter(filter); } public List getFilterItems() { return filterItems; } public void export(ActionEvent event){ log.debug("export("); List<List<Object>> spreadsheetData = new ArrayList<List<Object>>(); Map<String, String> sectionTutors = new HashMap<String, String>(); // Get the section enrollments Set<String> studentUids = new HashSet<String>(); for(Iterator iter = siteStudents.iterator(); iter.hasNext();) { ParticipationRecord record = (ParticipationRecord)iter.next(); studentUids.add(record.getUser().getUserUid()); } SectionEnrollments sectionEnrollments = getSectionManager().getSectionEnrollmentsForStudents(getSiteContext(), studentUids); // Add the header row List<Object> header = new ArrayList<Object>(); header.add(JsfUtil.getLocalizedMessage("roster_table_header_name")); header.add(JsfUtil.getLocalizedMessage("roster_table_header_id")); int categories = 0; for (Iterator<String> iter = getUsedCategories().iterator(); iter.hasNext();){ String category = (String)iter.next(); String categoryName = getCategoryName(category); header.add(categoryName); categories++; } //SAK-20962 Show TA doesn't work with multiple section types boolean showTAs = false; if (categories == 1) { header.add(JsfUtil.getLocalizedMessage("roster_table_header_ta")); showTAs = true; } spreadsheetData.add(header); for(Iterator enrollmentIter = siteStudents.iterator(); enrollmentIter.hasNext();) { //EnrollmentDecorator enrollment = enrollmentIter.next(); ParticipationRecord record = (ParticipationRecord)enrollmentIter.next(); List<Object> row = new ArrayList<Object>(); row.add(record.getUser().getSortName()); row.add(record.getUser().getDisplayId()); for (Iterator iter = getUsedCategories().iterator(); iter.hasNext();){ String category = (String)iter.next(); CourseSection section = sectionEnrollments.getSection(record.getUser().getUserUid(), category); if(section!=null){ row.add(section.getTitle()); //SAK-20092 add the TA's if (showTAs) { if (sectionTutors.get(section.getUuid()) != null) { row.add(sectionTutors.get(section.getUuid())); } else { String ta = getSectionTutorsAsString(section.getUuid()); row.add(ta); sectionTutors.put(section.getUuid(), ta); } } }else{ row.add(""); if (showTAs) { row.add(""); } } } spreadsheetData.add(row); } String spreadsheetName = getDownloadFileName(getCourse().getTitle()); SpreadsheetUtil.downloadSpreadsheetData(spreadsheetData, spreadsheetName, new SpreadsheetDataFileWriterXls()); } private String getSectionTutorsAsString(String section) { List<ParticipationRecord> tas = getSectionManager().getSectionTeachingAssistants(section); StringBuilder sb = new StringBuilder(); for (int i =0; i < tas.size(); i++) { ParticipationRecord participant = tas.get(i); if (i > 0) { sb.append(", "); } sb.append(participant.getUser().getDisplayName()); } return sb.toString(); } protected String getDownloadFileName(String rawString) { String dateString = DateFormat.getDateInstance(DateFormat.SHORT).format(new Date()); return (rawString + "_" + dateString).replaceAll("[\\W&&[^\\u0080-\\uffff]]", "_"); } }