/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/author/AuthorActionListener.java $ * $Id: AuthorActionListener.java 130641 2013-10-18 23:44:13Z ktsao@stanford.edu $ *********************************************************************************** * * Copyright (c) 2004, 2005, 2006, 2008, 2009 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.author; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.faces.event.AbortProcessingException; import javax.faces.event.ActionEvent; import javax.faces.event.ActionListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.section.api.SectionAwareness; import org.sakaiproject.site.api.Group; import org.sakaiproject.site.api.Site; import org.sakaiproject.authz.api.Member; import org.sakaiproject.authz.api.Role; import org.sakaiproject.site.cover.SiteService; import org.sakaiproject.tool.cover.ToolManager; import org.sakaiproject.tool.assessment.data.dao.assessment.AssessmentAccessControl; import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentAccessControlIfc; import org.sakaiproject.tool.assessment.facade.AgentFacade; import org.sakaiproject.tool.assessment.facade.AssessmentFacade; import org.sakaiproject.tool.assessment.facade.AssessmentFacadeQueries; import org.sakaiproject.tool.assessment.facade.AssessmentTemplateFacade; import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacade; import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacadeQueries; import org.sakaiproject.tool.assessment.services.GradingService; import org.sakaiproject.tool.assessment.services.assessment.AssessmentService; import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService; import org.sakaiproject.tool.assessment.shared.api.grading.GradingSectionAwareServiceAPI; import org.sakaiproject.tool.assessment.shared.impl.grading.GradingSectionAwareServiceImpl; import org.sakaiproject.tool.assessment.ui.bean.author.AuthorBean; import org.sakaiproject.tool.assessment.ui.bean.author.PublishedAssessmentSettingsBean; import org.sakaiproject.tool.assessment.ui.bean.authz.AuthorizationBean; import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil; import org.sakaiproject.tool.assessment.ui.listener.util.TimeUtil; import org.sakaiproject.util.FormattedText; import org.sakaiproject.util.ResourceLoader; // UVa: add ability to get the site information for site property query per SAK-2438 import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.site.api.Site; import org.sakaiproject.entity.api.ResourceProperties; /** * <p>Title: Samigo</p>2 * <p>Description: Sakai Assessment Manager</p> * @author Ed Smiley * @version $Id: AuthorActionListener.java 130641 2013-10-18 23:44:13Z ktsao@stanford.edu $ */ public class AuthorActionListener implements ActionListener { private static Log log = LogFactory.getLog(AuthorActionListener.class); private HashMap<String, ArrayList<String>> groupUsersIdMap = new HashMap<String, ArrayList<String>>(); private ArrayList<String> siteUsersIdList = new ArrayList<String>(); private String display_dateFormat= ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.GeneralMessages","output_data_picker_w_sec"); private SimpleDateFormat displayFormat = new SimpleDateFormat(display_dateFormat, new ResourceLoader().getLocale()); private TimeUtil tu = new TimeUtil(); // UVa, per SAK-2438 private ResourceProperties siteProperties = null; public AuthorActionListener() { } public void processAction(ActionEvent ae) throws AbortProcessingException { log.debug("*****Log: inside AuthorActionListener =debugging ActionEvent: " + ae); // get service and managed bean AssessmentService assessmentService = new AssessmentService(); PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService(); GradingService gradingService = new GradingService(); AuthorBean author = (AuthorBean) ContextUtil.lookupBean( "author"); author.setProtocol(ContextUtil.getProtocol()); //#1 - prepare active template list. Note that we only need the title. We don't need the // full template object - be cheap. String showAssessmentTypes = ServerConfigurationService.getString("samigo.showAssessmentTypes"); if ("false".equalsIgnoreCase(showAssessmentTypes)) { author.setShowTemplateList(Boolean.FALSE); } else { author.setShowTemplateList(Boolean.TRUE); } ArrayList templateList = assessmentService.getTitleOfAllActiveAssessmentTemplates(); // get the managed bean, author and set the list if (templateList.size()==1){ //<= only contains Default Template author.setShowTemplateList(false); } else{ // remove Default Template removeDefaultTemplate(templateList); author.setAssessmentTemplateList(templateList); } author.setAssessCreationMode("1"); prepareAssessmentsList(author, assessmentService, gradingService, publishedAssessmentService); // UVa: per SAK-2438, add a check for the site property 'samigo.editPubAssessment.restricted'. // If this site property exists (Admin user adds it per site), obey it. // Otherwise, use the global sakai-wide property by the same name. // String editPubAssessmentSiteProperty = "true"; // First, get the site object Site site = null; try { site = SiteService.getSite(ToolManager.getCurrentPlacement().getContext()); } catch (IdUnusedException ex) { // No site available } // Does a site property 'samigo.editPubAssessment.restricted' exist? boolean sitePropertyExists = false; if (site != null) { try { // get the site properties siteProperties = site.getProperties(); } catch (Exception e) { } if (siteProperties != null) { // get this property for this site String prop = siteProperties.getProperty("samigo.editPubAssessment.restricted"); if (prop != null) { sitePropertyExists = true; if (prop.toLowerCase().equals("false")) { // published assessment editting is not restricted author.setEditPubAssessmentRestricted(false); } else { // published assessment editting is restricted author.setEditPubAssessmentRestricted(true); } } else { sitePropertyExists = false; } } } // If a site property does not exist, go ahead and evaluate the global property if (!sitePropertyExists) { String s = ServerConfigurationService.getString("samigo.editPubAssessment.restricted"); if (s != null && s.toLowerCase().equals("false")) { author.setEditPubAssessmentRestricted(false); } else { author.setEditPubAssessmentRestricted(true); } } AuthorizationBean authorizationBean = (AuthorizationBean) ContextUtil.lookupBean("authorization"); author.setIsGradeable(authorizationBean.getGradeAnyAssessment() || authorizationBean.getGradeOwnAssessment()); author.setIsEditable(authorizationBean.getEditAnyAssessment() || authorizationBean.getEditOwnAssessment()); } public void prepareAssessmentsList(AuthorBean author, AssessmentService assessmentService, GradingService gradingService, PublishedAssessmentService publishedAssessmentService) { // #2 - prepare core assessment list author.setCoreAssessmentOrderBy(AssessmentFacadeQueries.TITLE); ArrayList assessmentList = assessmentService.getBasicInfoOfAllActiveAssessments( AssessmentFacadeQueries.TITLE, author.isCoreAscending()); Iterator iter = assessmentList.iterator(); while (iter.hasNext()) { AssessmentFacade assessmentFacade= (AssessmentFacade) iter.next(); assessmentFacade.setTitle(FormattedText.convertFormattedTextToPlaintext(assessmentFacade.getTitle())); try { String lastModifiedDateDisplay = tu.getDisplayDateTime(displayFormat, assessmentFacade.getLastModifiedDate()); assessmentFacade.setLastModifiedDateForDisplay(lastModifiedDateDisplay); } catch (Exception ex) { log.warn("Unable to format date: " + ex.getMessage()); } } // get the managed bean, author and set the list author.setAssessments(assessmentList); ArrayList publishedAssessmentList = publishedAssessmentService.getBasicInfoOfAllPublishedAssessments2( PublishedAssessmentFacadeQueries.TITLE, true, AgentFacade.getCurrentSiteId()); prepareAllPublishedAssessmentsList(author, gradingService, publishedAssessmentList); } public void prepareAllPublishedAssessmentsList(AuthorBean author, GradingService gradingService, ArrayList publishedAssessmentList) { try { Site site = SiteService.getSite(ToolManager.getCurrentPlacement().getContext()); Set siteStudentRoles = site.getRolesIsAllowed(SectionAwareness.STUDENT_MARKER); if(siteStudentRoles != null && !siteStudentRoles.isEmpty()) { for(Iterator iter = siteStudentRoles.iterator(); iter.hasNext();) { String role = (String) iter.next(); siteUsersIdList.addAll(site.getUsersHasRole(role)); } } Collection groups = site.getGroups(); Iterator iter = groups.iterator(); while (iter.hasNext()) { Group group = (Group) iter.next(); Set groupStudentRoles = group.getRolesIsAllowed(SectionAwareness.STUDENT_MARKER); ArrayList<String> groupUsersIdList = new ArrayList<String>(); if(groupStudentRoles != null && !groupStudentRoles.isEmpty()) { for(Iterator iter2 = groupStudentRoles.iterator(); iter2.hasNext();) { String role = (String) iter2.next(); groupUsersIdList.addAll(group.getUsersHasRole(role)); } if (groupUsersIdList.size() != 0) { String groupId = group.getId(); groupUsersIdMap.put(groupId, groupUsersIdList); } } } } catch (IdUnusedException e) { log.warn("IdUnusedException: " + e.getMessage()); } ArrayList dividedPublishedAssessmentList = getTakeableList(publishedAssessmentList, gradingService); //prepareActivePublishedAssessmentsList(author, (ArrayList) dividedPublishedAssessmentList.get(0)); prepareRetractWarningText(author, (ArrayList) dividedPublishedAssessmentList.get(1)); author.setPublishedAssessments(publishedAssessmentList); } /* public void prepareActivePublishedAssessmentsList(AuthorBean author, ArrayList<PublishedAssessmentFacade> activePublishedList) { author.setPublishedAssessments(activePublishedList); } */ public void prepareRetractWarningText(AuthorBean author, ArrayList inactivePublishedList) { author.setInactivePublishedAssessments(inactivePublishedList); boolean isAnyAssessmentRetractForEdit = false; Iterator iter = inactivePublishedList.iterator(); while (iter.hasNext()) { PublishedAssessmentFacade publishedAssessmentFacade = (PublishedAssessmentFacade) iter.next(); if (Integer.valueOf(3).equals(publishedAssessmentFacade.getStatus())) { isAnyAssessmentRetractForEdit = true; break; } } if (isAnyAssessmentRetractForEdit) { author.setIsAnyAssessmentRetractForEdit(true); } else { author.setIsAnyAssessmentRetractForEdit(false); } } private void removeDefaultTemplate(ArrayList templateList){ for (int i=0; i<templateList.size();i++){ AssessmentTemplateFacade a = (AssessmentTemplateFacade) templateList.get(i); if ((a.getAssessmentBaseId()).equals(new Long("1"))){ templateList.remove(a); return; } } } public ArrayList getTakeableList(ArrayList assessmentList, GradingService gradingService) { ArrayList list = new ArrayList(); ArrayList activeList = new ArrayList(); ArrayList inActiveList = new ArrayList(); String siteId = AgentFacade.getCurrentSiteId(); HashMap submissionCountHash = gradingService.getSiteSubmissionCountHash(siteId); HashMap inProgressCountHash = gradingService.getSiteInProgressCountHash(siteId); HashMap numberRetakeHash = gradingService.getSiteNumberRetakeHash(siteId); HashMap actualNumberRetake = gradingService.getSiteActualNumberRetakeHash(siteId); List needResubmitList = gradingService.getSiteNeedResubmitList(siteId); for (int i = 0; i < assessmentList.size(); i++) { PublishedAssessmentFacade f = (PublishedAssessmentFacade)assessmentList.get(i); f.setTitle(FormattedText.convertFormattedTextToPlaintext(f.getTitle())); Long publishedAssessmentId = f.getPublishedAssessmentId(); if (isActive(f, (HashMap) submissionCountHash.get(publishedAssessmentId), (HashMap) inProgressCountHash.get(publishedAssessmentId), (HashMap) numberRetakeHash.get(publishedAssessmentId), (HashMap) actualNumberRetake.get(publishedAssessmentId), needResubmitList)) { f.setActiveStatus(true); activeList.add(f); } else { f.setActiveStatus(false); inActiveList.add(f); } try { String lastModifiedDateDisplay = tu.getDisplayDateTime(displayFormat, f.getLastModifiedDate()); f.setLastModifiedDateForDisplay(lastModifiedDateDisplay); } catch (Exception ex) { log.warn("Unable to format date: " + ex.getMessage()); } } list.add(activeList); list.add(inActiveList); return list; } public boolean isActive(PublishedAssessmentFacade f, HashMap submissionCountHash, HashMap inProgressCountHash, HashMap numberRetakeHash, HashMap actualNumberRetakeHash, List needResubmitList) { boolean returnValue = false; //1. prepare our significant parameters Integer status = f.getStatus(); Date currentDate = new Date(); Date startDate = f.getStartDate(); Date retractDate = f.getRetractDate(); Date dueDate = f.getDueDate(); boolean acceptLateSubmission = AssessmentAccessControlIfc.ACCEPT_LATE_SUBMISSION.equals(f.getLateHandling()); int maxSubmissionsAllowed = 9999; if ((Boolean.FALSE).equals(f.getUnlimitedSubmissions())){ maxSubmissionsAllowed = f.getSubmissionsAllowed().intValue(); } ArrayList<String> userIdList = new ArrayList<String>(); if (f.getReleaseTo() != null && !("").equals(f.getReleaseTo())) { if (f.getReleaseTo().indexOf("Anonymous Users") >= 0) { if (submissionCountHash != null) { f.setSubmittedCount(submissionCountHash.size()); } else { f.setSubmittedCount(0); } if (inProgressCountHash != null) { f.setInProgressCount(inProgressCountHash.size()); } else { f.setInProgressCount(0); } if (dueDate != null && dueDate.before(currentDate)) { return false; } else { return true; } } else { if (AssessmentAccessControl.RELEASE_TO_SELECTED_GROUPS.equals(f.getReleaseTo())) { PublishedAssessmentSettingsBean publishedAssessmentSettingsBean = (PublishedAssessmentSettingsBean) ContextUtil.lookupBean("publishedSettings"); publishedAssessmentSettingsBean.setAssessmentId(f.getPublishedAssessmentId()); String [] groupsAuthorized = publishedAssessmentSettingsBean.getGroupsAuthorized(); for (int i = 0; i < groupsAuthorized.length; i++) { if (groupUsersIdMap.get(groupsAuthorized[i]) != null) { for (String userId : groupUsersIdMap.get(groupsAuthorized[i])) { userIdList.add(userId); } } } } else { userIdList = siteUsersIdList; } int submittedCounts = 0; int inProgressCounts = 0; if (userIdList != null) { Iterator iter = userIdList.iterator(); String userId = null; boolean isStillAvailable = false; while(iter.hasNext()) { userId = (String) iter.next(); int totalSubmitted = 0; int totalInProgress = 0; if (submissionCountHash != null && submissionCountHash.get(userId) != null){ totalSubmitted = ( (Integer) submissionCountHash.get(userId)).intValue(); if (totalSubmitted > 0) { submittedCounts++; } } if (inProgressCountHash != null && inProgressCountHash.get(userId) != null){ totalInProgress = ( (Integer) inProgressCountHash.get(userId)).intValue(); if (totalInProgress > 0) { inProgressCounts++; } } if (!returnValue) { isStillAvailable = isStillAvailable(totalSubmitted, numberRetakeHash, actualNumberRetakeHash, userId, currentDate, dueDate, acceptLateSubmission, maxSubmissionsAllowed); if (isStillAvailable) { returnValue = true; } } } } else { returnValue = true; } f.setSubmittedCount(submittedCounts); f.setInProgressCount(inProgressCounts); if ((submittedCounts + inProgressCounts) > 0) { f.setHasAssessmentGradingData(true); } else { f.setHasAssessmentGradingData(false); } } if (!Integer.valueOf(1).equals(status)) { returnValue = false; } if (startDate != null && startDate.after(currentDate)) { returnValue = false; } if (retractDate != null && retractDate.before(currentDate)) { returnValue = false; } if (needResubmitList.contains(f.getPublishedAssessmentId())) { returnValue = true; } } else { // should not come to here. but if this happens returnValue = false; } return returnValue; } private boolean isStillAvailable(int totalSubmitted, HashMap numberRetakeHash, HashMap actualNumberRetakeHash, String userId, Date currentDate, Date dueDate, boolean acceptLateSubmission, int maxSubmissionsAllowed) { boolean isStillAvailable = false; boolean hasSubmittedAtLeastOnce = false; int numberRetake = 0; if (numberRetakeHash != null && numberRetakeHash.get(userId) != null) { numberRetake = ((Integer) numberRetakeHash.get(userId)).intValue(); } //2. time to go through all the criteria if (dueDate != null && dueDate.before(currentDate)) { if (acceptLateSubmission) { if (totalSubmitted == 0) { return true; } } int actualNumberRetake = 0; if (actualNumberRetakeHash != null && actualNumberRetakeHash.get(userId) != null) { actualNumberRetake = ((Integer) actualNumberRetakeHash.get(userId)).intValue(); } if (actualNumberRetake < numberRetake) { isStillAvailable = true; } } else { if (totalSubmitted < maxSubmissionsAllowed + numberRetake) { isStillAvailable = true; } } return isStillAvailable; } }