001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/sections/tags/sakai_2-4-1/sections-app/src/java/org/sakaiproject/tool/section/jsf/backingbean/RosterBean.java $
003: * $Id: RosterBean.java 19625 2006-12-16 01:28:41Z jholtzman@berkeley.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2005, 2006 The Regents of the University of California and The Regents of the University of Michigan
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.section.jsf.backingbean;
021:
022: import java.io.Serializable;
023: import java.util.ArrayList;
024: import java.util.Collections;
025: import java.util.Comparator;
026: import java.util.HashMap;
027: import java.util.HashSet;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Map;
031: import java.util.Set;
032: import java.util.Map.Entry;
033:
034: import javax.faces.application.Application;
035: import javax.faces.component.UIColumn;
036: import javax.faces.component.html.HtmlDataTable;
037: import javax.faces.component.html.HtmlOutputText;
038: import javax.faces.context.FacesContext;
039: import javax.faces.event.ActionEvent;
040: import javax.faces.model.SelectItem;
041:
042: import org.apache.commons.lang.StringUtils;
043: import org.apache.commons.logging.Log;
044: import org.apache.commons.logging.LogFactory;
045: import org.apache.myfaces.custom.sortheader.HtmlCommandSortHeader;
046: import org.sakaiproject.section.api.coursemanagement.CourseSection;
047: import org.sakaiproject.section.api.coursemanagement.EnrollmentRecord;
048: import org.sakaiproject.section.api.coursemanagement.ParticipationRecord;
049: import org.sakaiproject.section.api.coursemanagement.SectionEnrollments;
050: import org.sakaiproject.tool.section.decorator.EnrollmentDecorator;
051: import org.sakaiproject.tool.section.jsf.JsfUtil;
052:
053: /**
054: * Controls the roster page.
055: *
056: * @author <a href="mailto:jholtzman@berkeley.edu">Josh Holtzman</a>
057: *
058: */
059: public class RosterBean extends CourseDependentBean implements
060: Serializable {
061:
062: private static final long serialVersionUID = 1L;
063: private static final Log log = LogFactory.getLog(RosterBean.class);
064: private static final String CAT_COLUMN_PREFIX = "cat";
065:
066: private String searchText;
067: private int firstRow;
068: private int enrollmentsSize;
069: private boolean externallyManaged;
070: private List<SelectItem> filterItems;
071: private List<EnrollmentDecorator> enrollments;
072: private List<String> categories;
073:
074: public void init() {
075: // Determine whether this course is externally managed
076: externallyManaged = getSectionManager().isExternallyManaged(
077: getCourse().getUuid());
078:
079: // Get the section categories
080: categories = getSectionManager().getSectionCategories(
081: getSiteContext());
082:
083: // Get the default search text
084: if (StringUtils.trimToNull(searchText) == null) {
085: searchText = JsfUtil
086: .getLocalizedMessage("roster_search_text");
087: }
088:
089: // Get the site enrollments
090: List<EnrollmentRecord> siteStudents;
091: if (searchText.equals(JsfUtil
092: .getLocalizedMessage("roster_search_text"))) {
093: siteStudents = getSectionManager().getSiteEnrollments(
094: getSiteContext());
095: } else {
096: siteStudents = getSectionManager().findSiteEnrollments(
097: getSiteContext(), searchText);
098: }
099:
100: // Get the section enrollments
101: Set<String> studentUids = new HashSet<String>();
102: for (Iterator iter = siteStudents.iterator(); iter.hasNext();) {
103: ParticipationRecord record = (ParticipationRecord) iter
104: .next();
105: studentUids.add(record.getUser().getUserUid());
106: }
107: SectionEnrollments sectionEnrollments = getSectionManager()
108: .getSectionEnrollmentsForStudents(getSiteContext(),
109: studentUids);
110:
111: // Construct the list of filter items
112: filterItems = new ArrayList<SelectItem>();
113: filterItems.add(new SelectItem("", JsfUtil
114: .getLocalizedMessage("filter_all_sections")));
115: filterItems.add(new SelectItem("MY", JsfUtil
116: .getLocalizedMessage("filter_my_category_sections",
117: new String[] { "" })));
118: for (Iterator<String> iter = categories.iterator(); iter
119: .hasNext();) {
120: String cat = iter.next();
121: filterItems.add(new SelectItem(cat, JsfUtil
122: .getLocalizedMessage("filter_my_category_sections",
123: new String[] { getCategoryName(cat) })));
124: }
125:
126: // If this is a TA, and we're filtering, get the TA's participation records
127: List<CourseSection> assignedSections = null;
128: if (StringUtils.trimToNull(getFilter()) != null) {
129: assignedSections = findAssignedSections();
130: }
131:
132: // Construct the decorated enrollments for the UI
133: decorateEnrollments(siteStudents, sectionEnrollments,
134: assignedSections);
135: }
136:
137: private void decorateEnrollments(
138: List<EnrollmentRecord> siteStudents,
139: SectionEnrollments sectionEnrollments,
140: List<CourseSection> assignedSections) {
141: List<EnrollmentDecorator> unpagedEnrollments = new ArrayList<EnrollmentDecorator>();
142: for (Iterator<EnrollmentRecord> studentIter = siteStudents
143: .iterator(); studentIter.hasNext();) {
144: EnrollmentRecord enrollment = studentIter.next();
145:
146: // Build a map of categories to sections in which the student is enrolled
147: Map<String, CourseSection> map = new HashMap<String, CourseSection>();
148: for (Iterator catIter = categories.iterator(); catIter
149: .hasNext();) {
150: String cat = (String) catIter.next();
151: CourseSection section = sectionEnrollments.getSection(
152: enrollment.getUser().getUserUid(), cat);
153:
154: map.put(cat, section);
155: }
156:
157: // Check to see whether this enrollment should be filtered out
158: boolean includeStudent = false;
159: if (StringUtils.trimToNull(getFilter()) == null) {
160: includeStudent = true;
161: } else {
162: for (Iterator<Entry<String, CourseSection>> entryIter = map
163: .entrySet().iterator(); entryIter.hasNext();) {
164: Entry<String, CourseSection> entry = entryIter
165: .next();
166: CourseSection section = entry.getValue();
167: // Some map entries won't have a section at all, since the student isn't in any section of that category
168: if (section == null) {
169: continue;
170: }
171: if ("MY".equals(getFilter())
172: && assignedSections.contains(section)) {
173: includeStudent = true;
174: break;
175: } else if (section.getCategory()
176: .equals(getFilter())
177: && assignedSections.contains(section)) {
178: includeStudent = true;
179: break;
180: }
181: }
182: }
183:
184: if (includeStudent) {
185: EnrollmentDecorator decorator = new EnrollmentDecorator(
186: enrollment, map);
187: unpagedEnrollments.add(decorator);
188: }
189: }
190:
191: // Sort the list
192: Collections.sort(unpagedEnrollments, getComparator());
193:
194: // Filter the list of enrollments
195: enrollments = new ArrayList<EnrollmentDecorator>();
196: int lastRow;
197: int maxDisplayedRows = getPrefs().getRosterMaxDisplayedRows();
198: if (maxDisplayedRows < 1
199: || firstRow + maxDisplayedRows > unpagedEnrollments
200: .size()) {
201: lastRow = unpagedEnrollments.size();
202: } else {
203: lastRow = firstRow + maxDisplayedRows;
204: }
205: enrollments.addAll(unpagedEnrollments
206: .subList(firstRow, lastRow));
207: enrollmentsSize = unpagedEnrollments.size();
208: }
209:
210: private List<CourseSection> findAssignedSections() {
211: List<CourseSection> assignedSections = new ArrayList<CourseSection>();
212: for (Iterator<CourseSection> secIter = getSectionManager()
213: .getSections(getSiteContext()).iterator(); secIter
214: .hasNext();) {
215: CourseSection section = secIter.next();
216: List<ParticipationRecord> tas = getSectionManager()
217: .getSectionTeachingAssistants(section.getUuid());
218: for (Iterator<ParticipationRecord> taIter = tas.iterator(); taIter
219: .hasNext();) {
220: ParticipationRecord ta = taIter.next();
221: if (ta.getUser().getUserUid().equals(getUserUid())) {
222: assignedSections.add(section);
223: break;
224: }
225: }
226: }
227: return assignedSections;
228: }
229:
230: private Comparator<EnrollmentDecorator> getComparator() {
231: String sortColumn = getPrefs().getRosterSortColumn();
232: boolean sortAscending = getPrefs().isRosterSortAscending();
233:
234: if (sortColumn.equals("studentName")) {
235: return EnrollmentDecorator.getNameComparator(sortAscending);
236: } else if (sortColumn.equals("displayId")) {
237: return EnrollmentDecorator
238: .getDisplayIdComparator(sortAscending);
239: } else {
240: return EnrollmentDecorator.getCategoryComparator(
241: sortColumn, sortAscending);
242: }
243: }
244:
245: public HtmlDataTable getRosterDataTable() {
246: return null;
247: }
248:
249: public void setRosterDataTable(HtmlDataTable rosterDataTable) {
250: Set usedCategories = getUsedCategories();
251:
252: if (rosterDataTable.findComponent(CAT_COLUMN_PREFIX + "0") == null) {
253: Application app = FacesContext.getCurrentInstance()
254: .getApplication();
255:
256: // Add columns for each category. Be sure to create unique IDs
257: // for all child components.
258: int colpos = 0;
259: for (Iterator iter = usedCategories.iterator(); iter
260: .hasNext(); colpos++) {
261: String category = (String) iter.next();
262: String categoryName = getCategoryName(category);
263:
264: UIColumn col = new UIColumn();
265: col.setId(CAT_COLUMN_PREFIX + colpos);
266:
267: HtmlCommandSortHeader sortHeader = new HtmlCommandSortHeader();
268: sortHeader.setId(CAT_COLUMN_PREFIX + "sorthdr_"
269: + colpos);
270: sortHeader
271: .setRendererType("org.apache.myfaces.SortHeader");
272: sortHeader.setArrow(true);
273: sortHeader.setColumnName(category);
274: //sortHeader.setActionListener(app.createMethodBinding("#{rosterBean.sort}", new Class[] {ActionEvent.class}));
275:
276: HtmlOutputText headerText = new HtmlOutputText();
277: headerText.setId(CAT_COLUMN_PREFIX + "hdr_" + colpos);
278: headerText.setValue(categoryName);
279:
280: sortHeader.getChildren().add(headerText);
281: col.setHeader(sortHeader);
282:
283: HtmlOutputText contents = new HtmlOutputText();
284: contents.setId(CAT_COLUMN_PREFIX + "cell_" + colpos);
285: contents
286: .setValueBinding(
287: "value",
288: app
289: .createValueBinding("#{enrollment.categoryToSectionMap['"
290: + category
291: + "'].title}"));
292: col.getChildren().add(contents);
293: rosterDataTable.getChildren().add(col);
294: }
295: }
296: }
297:
298: public void search(ActionEvent event) {
299: // firstRow = 0;
300: }
301:
302: public void clearSearch(ActionEvent event) {
303: firstRow = 0;
304: searchText = null;
305: }
306:
307: public List getEnrollments() {
308: return enrollments;
309: }
310:
311: public int getEnrollmentsSize() {
312: return enrollmentsSize;
313: }
314:
315: public boolean isExternallyManaged() {
316: return externallyManaged;
317: }
318:
319: public String getSearchText() {
320: return searchText;
321: }
322:
323: public void setSearchText(String searchText) {
324: if (StringUtils.trimToNull(searchText) == null) {
325: searchText = JsfUtil
326: .getLocalizedMessage("roster_search_text");
327: }
328: if (!StringUtils.equals(searchText, this .searchText)) {
329: if (log.isDebugEnabled())
330: log.debug("setSearchString " + searchText);
331: this .searchText = searchText;
332: setFirstRow(0); // clear the paging when we update the search
333: }
334: }
335:
336: public int getFirstRow() {
337: return firstRow;
338: }
339:
340: public void setFirstRow(int firstRow) {
341: this .firstRow = firstRow;
342: }
343:
344: public String getFilter() {
345: return getPrefs().getRosterFilter();
346: }
347:
348: public void setFilter(String filter) {
349: getPrefs().setRosterFilter(filter);
350: }
351:
352: public List getFilterItems() {
353: return filterItems;
354: }
355: }
|