/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/SubmissionStatusListener.java $ * $Id: SubmissionStatusListener.java 130512 2013-10-15 23:46:40Z ktsao@stanford.edu $ *********************************************************************************** * * Copyright (c) 2004, 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.assessment.ui.listener.evaluation; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; 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 javax.faces.event.AbortProcessingException; import javax.faces.event.ActionEvent; import javax.faces.event.ActionListener; import javax.faces.event.ValueChangeEvent; import javax.faces.event.ValueChangeListener; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedAssessmentData; import org.sakaiproject.tool.assessment.data.dao.grading.AssessmentGradingData; import org.sakaiproject.tool.assessment.data.dao.grading.StudentGradingSummaryData; import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentAccessControlIfc; import org.sakaiproject.tool.assessment.data.ifc.assessment.PublishedAssessmentIfc; import org.sakaiproject.tool.assessment.facade.AgentFacade; import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService; import org.sakaiproject.tool.assessment.services.GradingService; import org.sakaiproject.tool.assessment.ui.bean.evaluation.AgentResults; import org.sakaiproject.tool.assessment.ui.bean.evaluation.QuestionScoresBean; import org.sakaiproject.tool.assessment.ui.bean.evaluation.RetakeAssessmentBean; import org.sakaiproject.tool.assessment.ui.bean.evaluation.TotalScoresBean; import org.sakaiproject.tool.assessment.ui.bean.evaluation.SubmissionStatusBean; import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil; import org.sakaiproject.tool.assessment.util.BeanSort; import org.sakaiproject.tool.assessment.integration.helper.ifc.AgentHelper; import org.sakaiproject.tool.assessment.integration.context.IntegrationContextFactory; /** * <p>Description: Action Listener for displaying Submission Status for anonymnous grading</p> * @version $Id: SubmissionStatusListener.java 130512 2013-10-15 23:46:40Z ktsao@stanford.edu $ */ public class SubmissionStatusListener implements ActionListener, ValueChangeListener { private static Log log = LogFactory.getLog(SubmissionStatusListener.class); //private static EvaluationListenerUtil util; private static BeanSort bs; //private static ContextUtil cu; /** * Standard process action method. * @param ae ActionEvent * @throws AbortProcessingException */ public void processAction(ActionEvent ae) throws AbortProcessingException { //log.info("Submission Status LISTENER."); SubmissionStatusBean bean = (SubmissionStatusBean) ContextUtil.lookupBean("submissionStatus"); TotalScoresBean totalScoresBean = (TotalScoresBean) ContextUtil.lookupBean("totalScores"); // we probably want to change the poster to be consistent String publishedId = ContextUtil.lookupParam("publishedId"); //log.info("Got publishedId " + publishedId); // Reset the search field String defaultSearchString = ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.EvaluationMessages", "search_default_student_search_string"); bean.setSearchString(defaultSearchString); if (!submissionStatus(publishedId, bean, totalScoresBean, false)) { throw new RuntimeException("failed to call submissionStatus."); } } /** * Process a value change. */ public void processValueChange(ValueChangeEvent event) { log.debug("QuestionScore CHANGE LISTENER."); SubmissionStatusBean bean = (SubmissionStatusBean) ContextUtil.lookupBean("submissionStatus"); TotalScoresBean totalScoresBean = (TotalScoresBean) ContextUtil.lookupBean("totalScores"); QuestionScoresBean questionbean = (QuestionScoresBean) ContextUtil.lookupBean("questionScores"); // we probably want to change the poster to be consistent String publishedId = ContextUtil.lookupParam("publishedId"); String selectedvalue= (String) event.getNewValue(); if ((selectedvalue!=null) && (!selectedvalue.equals("")) ){ if (event.getComponent().getId().indexOf("sectionpicker") >-1 ) { bean.setSelectedSectionFilterValue(selectedvalue); // changed section pulldown totalScoresBean.setSelectedSectionFilterValue(selectedvalue); questionbean.setSelectedSectionFilterValue(selectedvalue); } } if (!submissionStatus(publishedId, bean, totalScoresBean, false)) { throw new RuntimeException("failed to call questionScores."); } } /** * This will populate the SubmissionStatusBean with the data associated with the * particular versioned assessment based on the publishedId. * * @todo Some of this code will change when we move this to Hibernate persistence. * @param publishedId String * @param bean SubmissionStatusBean * @return boolean */ public boolean submissionStatus( String publishedId, SubmissionStatusBean bean, TotalScoresBean totalScoresBean, boolean isValueChange) { log.debug("submissionStatus()"); try { TotalScoreListener totalScorelistener = new TotalScoreListener(); GradingService delegate = new GradingService(); if (ContextUtil.lookupParam("sortBy") != null && !ContextUtil.lookupParam("sortBy").trim().equals("")) bean.setSortType(ContextUtil.lookupParam("sortBy")); boolean sortAscending = true; if (ContextUtil.lookupParam("sortAscending") != null && !ContextUtil.lookupParam("sortAscending").trim().equals("")){ sortAscending = Boolean.valueOf(ContextUtil.lookupParam("sortAscending")).booleanValue(); bean.setSortAscending(sortAscending); log.debug("submissionStatus() :: sortAscending = " + sortAscending); } totalScoresBean.setSelectedSectionFilterValue(bean.getSelectedSectionFilterValue()); bean.setPublishedId(publishedId); // we are only interested in showing last submissions List scores = delegate.getLastSubmittedAssessmentGradingList(new Long(publishedId)); ArrayList agents = new ArrayList(); Iterator iter = scores.iterator(); if (!iter.hasNext()) { // this section has no students bean.setAgents(agents); bean.setAllAgents(agents); bean.setTotalPeople(Integer.toString(bean.getAgents().size())); return true; } Object next = iter.next(); //Date dueDate = null; // Collect a list of all the users in the scores list Map useridMap= totalScoresBean.getUserIdMap(TotalScoresBean.CALLED_FROM_SUBMISSION_STATUS_LISTENER); ArrayList agentUserIds = totalScorelistener.getAgentIds(useridMap); AgentHelper helper = IntegrationContextFactory.getInstance().getAgentHelper(); Map userRoles = helper.getUserRolesFromContextRealm(agentUserIds); // Okay, here we get the first result set, which has a summary of // information and a pointer to the graded assessment we should be // displaying. We get the graded assessment. AssessmentGradingData data = (AssessmentGradingData) next; PublishedAssessmentService pubService = new PublishedAssessmentService(); PublishedAssessmentIfc pub = (PublishedAssessmentIfc) pubService.getPublishedAssessment(data.getPublishedAssessmentId().toString()); if (pub != null) { bean.setAssessmentName(pub.getTitle()); } if (ContextUtil.lookupParam("roleSelection") != null) { bean.setRoleSelection(ContextUtil.lookupParam("roleSelection")); } if (bean.getSortType() == null) { bean.setSortType("agentEid"); } /* Dump the grading and agent information into AgentResults */ ArrayList students_submitted= new ArrayList(); iter = scores.iterator(); HashMap studentGradingSummaryDataMap = new HashMap(); RetakeAssessmentBean retakeAssessment = (RetakeAssessmentBean) ContextUtil.lookupBean("retakeAssessment"); while (iter.hasNext()) { AgentResults results = new AgentResults(); AssessmentGradingData gdata = (AssessmentGradingData) iter.next(); gdata.setItemGradingSet(new HashSet()); BeanUtils.copyProperties(results, gdata); results.setAssessmentGradingId(gdata.getAssessmentGradingId()); String agentid = gdata.getAgentId(); AgentFacade agent = new AgentFacade(agentid); results.setLastName(agent.getLastName()); results.setFirstName(agent.getFirstName()); results.setEmail(agent.getEmail()); if (results.getLastName() != null && results.getLastName().length() > 0) results.setLastInitial(results.getLastName().substring(0,1)); else if (results.getFirstName() != null && results.getFirstName().length() > 0) results.setLastInitial(results.getFirstName().substring(0,1)); else results.setLastInitial("A"); results.setIdString(agent.getIdString()); results.setAgentEid(agent.getEidString()); results.setAgentDisplayId(agent.getDisplayIdString()); results.setRole((String)userRoles.get(agentid)); results.setRetakeAllowed(getRetakeAllowed(agent.getIdString(), studentGradingSummaryDataMap, retakeAssessment)); if (useridMap.containsKey(agentid) ) { agents.add(results); students_submitted.add(agentid); } } retakeAssessment.setStudentGradingSummaryDataMap(studentGradingSummaryDataMap); ArrayList students_not_submitted= new ArrayList(); Iterator useridIterator = useridMap.keySet().iterator(); while (useridIterator.hasNext()) { String userid = (String) useridIterator.next(); if (!students_submitted.contains(userid)) { students_not_submitted.add(userid); } } prepareNotSubmittedAgentResult(students_not_submitted.iterator(), agents, userRoles, retakeAssessment, studentGradingSummaryDataMap); bs = new BeanSort(agents, bean.getSortType()); if ( (bean.getSortType()).equals("assessmentGradingId") ) { bs.toNumericSort(); } else { bs.toStringSort(); } if (sortAscending) { log.debug("TotalScoreListener: setRoleAndSortSection() :: sortAscending"); agents = (ArrayList)bs.sort(); } else { log.debug("TotalScoreListener: setRoleAndSortSection() :: !sortAscending"); agents = (ArrayList)bs.sortDesc(); } bean.setAgents(agents); bean.setAllAgents(agents); bean.setTotalPeople(Integer.toString(bean.getAgents().size())); } catch (RuntimeException e) { e.printStackTrace(); return false; } catch (IllegalAccessException e) { e.printStackTrace(); return false; } catch (InvocationTargetException e) { e.printStackTrace(); return false; } return true; } //add those students that have not submitted scores, need to display them // in the UI public void prepareNotSubmittedAgentResult(Iterator notsubmitted_iter, ArrayList agents, Map userRoles, RetakeAssessmentBean retakeAssessment, HashMap studentGradingSummaryDataMap){ while (notsubmitted_iter.hasNext()){ String studentid = (String) notsubmitted_iter.next(); AgentResults results = new AgentResults(); AgentFacade agent = new AgentFacade(studentid); results.setLastName(agent.getLastName()); results.setFirstName(agent.getFirstName()); results.setEmail(agent.getEmail()); if (results.getLastName() != null && results.getLastName().length() > 0) { results.setLastInitial(results.getLastName().substring(0,1)); } else if (results.getFirstName() != null && results.getFirstName().length() > 0) { results.setLastInitial(results.getFirstName().substring(0,1)); } else { results.setLastInitial("Anonymous"); } results.setIdString(agent.getIdString()); results.setAgentEid(agent.getEidString()); results.setAgentDisplayId(agent.getDisplayIdString()); results.setRole((String)userRoles.get(studentid)); results.setRetakeAllowed(getRetakeAllowed(agent.getIdString(), studentGradingSummaryDataMap, retakeAssessment)); retakeAssessment.setStudentGradingSummaryDataMap(studentGradingSummaryDataMap); agents.add(results); } } public boolean getRetakeAllowed(String agentId, HashMap studentGradingSummaryDataMap, RetakeAssessmentBean retakeAssessment) { TotalScoresBean totalScoresBean = (TotalScoresBean) ContextUtil.lookupBean("totalScores"); PublishedAssessmentData publishedAssessmentData = totalScoresBean.getPublishedAssessment(); PublishedAssessmentService pubService = new PublishedAssessmentService(); int totalSubmitted = (pubService.getTotalSubmission(agentId, publishedAssessmentData.getPublishedAssessmentId().toString())).intValue(); //List allAssessmentGradingList = gradingService.getAllAssessmentGradingByAgentId(publishedAssessmentData.getPublishedAssessmentId(), agentId); //int totalSubmitted = allAssessmentGradingList.size(); AssessmentAccessControlIfc assessmentAccessControl = publishedAssessmentData.getAssessmentAccessControl(); Date currentDate = new Date(); Date startDate = assessmentAccessControl.getStartDate(); Date dueDate = assessmentAccessControl.getDueDate(); GradingService gradingService = new GradingService(); List studentGradingSummaryDataList = gradingService.getStudentGradingSummaryData(publishedAssessmentData.getPublishedAssessmentId(), agentId); StudentGradingSummaryData studentGradingSummaryData = null; int numberRetake = 0; if (studentGradingSummaryDataList.size() != 0) { studentGradingSummaryData = (StudentGradingSummaryData) studentGradingSummaryDataList.get(0); studentGradingSummaryDataMap.put(agentId, studentGradingSummaryData); retakeAssessment.setStudentGradingSummaryData(studentGradingSummaryData); numberRetake = studentGradingSummaryData.getNumberRetake().intValue(); } else { retakeAssessment.setStudentGradingSummaryData(null); } boolean acceptLateSubmission = AssessmentAccessControlIfc.ACCEPT_LATE_SUBMISSION.equals(assessmentAccessControl.getLateHandling()); if (startDate == null || startDate.before(currentDate)) { if (dueDate != null && dueDate.before(currentDate)) { if (acceptLateSubmission) { // no submission at all, there will be one more last chance for student to submit // therefore, don't show the retake if (totalSubmitted == 0) { return false; } } // if there are submission(s) and already retake issued to the student, // if the student's acutalNumberRetake is the same as numberRetake issued by the instructor // we can display the retake link to allow the instructor to give out another chance to the student int actualNumberRetake = gradingService.getActualNumberRetake(publishedAssessmentData.getPublishedAssessmentId(), agentId); if (actualNumberRetake == numberRetake) { return true; } } else { int maxSubmissionsAllowed = 9999; if ((Boolean.FALSE).equals(assessmentAccessControl.getUnlimitedSubmissions())) { maxSubmissionsAllowed = assessmentAccessControl.getSubmissionsAllowed().intValue(); } if ((totalSubmitted >= maxSubmissionsAllowed + numberRetake)) { return true; } } } return false; } }