/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/bean/delivery/DeliveryBean.java $
* $Id: DeliveryBean.java 132168 2013-12-03 20:25:29Z ktsao@stanford.edu $
***********************************************************************************
*
* Copyright (c) 2004, 2005, 2006, 2007, 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.bean.delivery;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.event.cover.NotificationService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SitePage;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.tool.api.Placement;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.assessment.api.SamigoApiFactory;
import org.sakaiproject.tool.assessment.data.dao.assessment.EventLogData;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedAssessmentData;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedItemData;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedItemText;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedSectionData;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedSecuredIPAddress;
import org.sakaiproject.tool.assessment.data.dao.grading.AssessmentGradingData;
import org.sakaiproject.tool.assessment.data.dao.grading.ItemGradingData;
import org.sakaiproject.tool.assessment.data.dao.grading.MediaData;
import org.sakaiproject.tool.assessment.data.exception.SamigoDataAccessException;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentAccessControlIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentBaseIfc;
import org.sakaiproject.tool.assessment.data.ifc.shared.TypeIfc;
import org.sakaiproject.tool.assessment.facade.AgentFacade;
import org.sakaiproject.tool.assessment.facade.EventLogFacade;
import org.sakaiproject.tool.assessment.facade.PublishedAssessmentFacade;
import org.sakaiproject.tool.assessment.services.FinFormatException;
import org.sakaiproject.tool.assessment.services.GradingService;
import org.sakaiproject.tool.assessment.services.SaLengthException;
import org.sakaiproject.tool.assessment.services.assessment.EventLogService;
import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService;
import org.sakaiproject.tool.assessment.shared.api.assessment.SecureDeliveryServiceAPI;
import org.sakaiproject.tool.assessment.shared.api.assessment.SecureDeliveryServiceAPI.Phase;
import org.sakaiproject.tool.assessment.shared.api.assessment.SecureDeliveryServiceAPI.PhaseStatus;
import org.sakaiproject.tool.assessment.ui.bean.shared.PersonBean;
import org.sakaiproject.tool.assessment.ui.bean.util.Validator;
import org.sakaiproject.tool.assessment.ui.listener.delivery.BeginDeliveryActionListener;
import org.sakaiproject.tool.assessment.ui.listener.delivery.DeliveryActionListener;
import org.sakaiproject.tool.assessment.ui.listener.delivery.LinearAccessDeliveryActionListener;
import org.sakaiproject.tool.assessment.ui.listener.delivery.SubmitToGradingActionListener;
import org.sakaiproject.tool.assessment.ui.listener.select.SelectActionListener;
import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil;
import org.sakaiproject.tool.assessment.ui.listener.util.TimeUtil;
import org.sakaiproject.tool.assessment.ui.model.delivery.TimedAssessmentGradingModel;
import org.sakaiproject.tool.assessment.ui.queue.delivery.TimedAssessmentQueue;
import org.sakaiproject.tool.assessment.ui.web.session.SessionUtil;
import org.sakaiproject.tool.assessment.util.MimeTypesLocator;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.tool.cover.ToolManager;
import org.sakaiproject.util.ResourceLoader;
/**
*
* @author casong
* @author esmiley@stanford.edu added agentState
* $Id: DeliveryBean.java 132168 2013-12-03 20:25:29Z ktsao@stanford.edu $
*
* Used to be org.navigoproject.ui.web.asi.delivery.XmlDeliveryForm.java
*/
public class DeliveryBean
implements Serializable
{
private static Log log = LogFactory.getLog(DeliveryBean.class);
private String assessmentId;
private String assessmentTitle;
private ArrayList markedForReview;
private ArrayList blankItems;
private ArrayList markedForReviewIdents;
private ArrayList blankItemIdents;
private boolean reviewMarked;
private boolean reviewAll;
private boolean reviewBlank;
private boolean displayMardForReview;
private int itemIndex;
private int size;
private String action;
private Date beginTime;
private String endTime;
private String currentTime;
private String multipleAttempts;
private String timeOutSubmission;
private String submissionTicket;
private String timeElapse;
private String username;
private int sectionIndex;
private boolean previous;
private String duration;
private String url;
private String confirmation;
private String outcome;
//Settings
private String questionLayout;
private String navigation;
private String numbering;
private String feedback;
private String noFeedback;
private String statistics;
private String creatorName;
private FeedbackComponent feedbackComponent;
private String feedbackComponentOption;
private boolean feedbackOnDate;
private String errorMessage;
private SettingsDeliveryBean settings;
private java.util.Date dueDate;
private java.util.Date retractDate;
private boolean statsAvailable;
private boolean submitted;
private boolean graded;
private String graderComment;
private String rawScore;
private String grade;
private java.util.Date submissionDate;
private java.util.Date submissionTime;
private String image;
private boolean hasImage;
private String instructorMessage;
private String courseName;
private String timeLimit;
private int timeLimit_hour;
private int timeLimit_minute;
private ContentsDeliveryBean tableOfContents;
private String submissionId;
private String submissionMessage;
private String instructorName;
private ContentsDeliveryBean pageContents;
private int submissionsRemaining;
private int totalSubmissions;
private boolean forGrade;
private String password;
private int numberRetake;
private int actualNumberRetake;
private HashMap itemContentsMap;
// For paging
private int partIndex;
private int questionIndex;
private boolean next_page;
private boolean reload = true;
// daisy added these for SelectActionListener
private boolean notTakeable = true;
private boolean pastDue;
private long subTime;
private long raw;
private String takenHours;
private String takenMinutes;
private AssessmentGradingData adata;
private PublishedAssessmentFacade publishedAssessment;
private java.util.Date feedbackDate;
private String feedbackDelivery;
private String showScore;
private boolean hasTimeLimit;
private boolean isMoreThanOneQuestion;
private Integer scoringType;
// daisyf added for servlet Login.java, to support anonymous login with
// publishedUrl
private boolean anonymousLogin = false;
private String contextPath;
private boolean initAgentAccessString = false;
// daisyf added this for timed assessment for SAK-6990, to check if mutiple windows were open
// during timed assessment
private String timerId=null;
/** Use serialVersionUID for interoperability. */
private final static long serialVersionUID = -1090852048737428722L;
private boolean showStudentScore;
private boolean showStudentQuestionScore;
// SAM-387
// esmiley added to track if timer has been started in timed assessments
private boolean timeRunning;
// SAM-535
// esmiley added to track JavaScript
private String javaScriptEnabledCheck;
//cwen
private String siteId;
private boolean beginAssessment;
// this instance tracks if the Agent is taking a test via URL, as well as
// current agent string (if assigned). SAK-1927: esmiley
private AgentFacade deliveryAgent;
private String display_dayDateFormat= ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.GeneralMessages","output_day_date_no_sec");
private SimpleDateFormat dayDisplayFormat = new SimpleDateFormat(display_dayDateFormat, new ResourceLoader().getLocale());
private String display_dateFormat= ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.GeneralMessages","output_date_no_sec");
private SimpleDateFormat displayFormat = new SimpleDateFormat(display_dateFormat, new ResourceLoader().getLocale());
private boolean noQuestions = false;
// this assessmentGradingId is used to generate seed in getSeed(...) of DeliveryActaionListener.java
// We need this because the assessmentGradingData in delivery bean might not be the one we want to display
// especially for review assessment and grade assessment. In other word, if student has started taking another assessment,
// the assessmentGradingData in deliver bean will be the newly created one. Then, of course, the assessmentGradingId
// will be the new id which is not what we want in review assessment or grade assessment
private Long assessmentGradingId;
private boolean fromTableOfContents;
private int fileUploadSizeMax;
private boolean studentRichText;
private boolean isAnyInvalidFinInput;
private String redrawAnchorName;
// If set to true, delivery of the assessment is blocked.
// This attribute is set to true if a secure delivery module is selected for the assessment and the security
// check fails. If a module is selected, but is no longer installed or is disabled then the check is bypassed
// and this attribute remains false.
private boolean blockDelivery = false;
// HTML fragment injected by the secure delivery module selected. Nothing is injected if no module has
// been selected or if the selected module is no longer installed or disabled.
private String secureDeliveryHTMLFragment;
private boolean isFromPrint;
private static String ACCESSBASE = ServerConfigurationService.getAccessUrl();
private static String RECPATH = ServerConfigurationService.getString("samigo.recommendations.path");
private static ResourceBundle eventLogMessages = ResourceBundle.getBundle("org.sakaiproject.tool.assessment.bundle.EventLogMessages");
/**
* Creates a new DeliveryBean object.
*/
public DeliveryBean()
{
deliveryAgent = new AgentFacade();
}
/**
*
*
* @return
*/
public int getItemIndex()
{
return this.itemIndex;
}
/**
*
*
* @param itemIndex
*/
public void setItemIndex(int itemIndex)
{
this.itemIndex = itemIndex;
}
/**
*
*
* @return
*/
public int getSize()
{
return this.size;
}
/**
*
*
* @param size
*/
public void setSize(int size)
{
this.size = size;
}
/**
*
*
* @return
*/
public String getAssessmentId()
{
return assessmentId;
}
/**
*
*
* @param assessmentId
*/
public void setAssessmentId(String assessmentId)
{
this.assessmentId = assessmentId;
}
/**
*
*
* @return
*/
public ArrayList getMarkedForReview()
{
return markedForReview;
}
/**
*
*
* @param markedForReview
*/
public void setMarkedForReview(ArrayList markedForReview)
{
this.markedForReview = markedForReview;
}
/**
*
*
* @return
*/
public boolean getReviewMarked()
{
return this.reviewMarked;
}
/**
*
*
* @param reviewMarked
*/
public void setReviewMarked(boolean reviewMarked)
{
this.reviewMarked = reviewMarked;
}
/**
*
*
* @return
*/
public boolean getReviewAll()
{
return this.reviewAll;
}
/**
*
*
* @param reviewAll
*/
public void setReviewAll(boolean reviewAll)
{
this.reviewAll = reviewAll;
}
/**
*
*
* @return
*/
public String getAction()
{
return this.action;
}
/**
*
*
* @param action
*/
public void setAction(String action)
{
this.action = action;
}
/**
*
*
* @return
*/
public Date getBeginTime()
{
return beginTime;
}
/**
*
*
* @param beginTime
*/
public void setBeginTime(Date beginTime)
{
this.beginTime = beginTime;
}
/**
*
*
* @return
*/
public String getEndTime()
{
return endTime;
}
/**
*
*
* @param endTime
*/
public void setEndTime(String endTime)
{
this.endTime = endTime;
}
/**
*
*
* @return
*/
public String getCurrentTime()
{
return this.currentTime;
}
/**
*
*
* @param currentTime
*/
public void setCurrentTime(String currentTime)
{
this.currentTime = currentTime;
}
/**
*
*
* @return
*/
public String getMultipleAttempts()
{
return this.multipleAttempts;
}
/**
*
*
* @param multipleAttempts
*/
public void setMultipleAttempts(String multipleAttempts)
{
this.multipleAttempts = multipleAttempts;
}
/**
*
*
* @return
*/
public String getTimeOutSubmission()
{
return this.timeOutSubmission;
}
/**
*
*
* @param timeOutSubmission
*/
public void setTimeOutSubmission(String timeOutSubmission)
{
this.timeOutSubmission = timeOutSubmission;
}
/**
*
*
* @return
*/
public java.util.Date getSubmissionTime()
{
return submissionTime;
}
/**
*
*
* @param submissionTime
*/
public void setSubmissionTime(java.util.Date submissionTime)
{
this.submissionTime = submissionTime;
}
/**
*
*
* @return
*/
public String getTimeElapse()
{
return timeElapse;
}
/**
*
*
* @param timeElapse
*/
public void setTimeElapse(String timeElapse)
{
try{
if (timeElapse!=null && !("").equals(timeElapse)
&& getTimeLimit()!=null && !("").equals(getTimeLimit())){
double limit = (new Double(getTimeLimit())).doubleValue();
double elapsed = (new Double(timeElapse)).doubleValue();
if (limit > elapsed)
this.timeElapse = timeElapse;
else
this.timeElapse = getTimeLimit();
setTimeElapseDouble((new Double(timeElapse)).doubleValue());
}
}
catch (Exception e){
log.warn("setTimeElapse error:"+e.getMessage());
}
}
/**
*
*
* @return
*/
public String getSubmissionTicket()
{
return submissionTicket;
}
/**
*
*
* @param submissionTicket
*/
public void setSubmissionTicket(String submissionTicket)
{
this.submissionTicket = submissionTicket;
}
/**
*
*
* @return
*/
public int getDisplayIndex()
{
return this.itemIndex + 1;
}
/**
*
*
* @return
*/
public String getUsername()
{
return username;
}
/**
*
*
* @param username
*/
public void setUsername(String username)
{
this.username = username;
}
/**
*
*
* @return
*/
public String getAssessmentTitle()
{
return assessmentTitle;
}
/**
*
*
* @param assessmentTitle
*/
public void setAssessmentTitle(String assessmentTitle)
{
this.assessmentTitle = assessmentTitle;
}
/**
*
*
* @return
*/
public ArrayList getBlankItems()
{
return this.blankItems;
}
/**
*
*
* @param blankItems
*/
public void setBlankItems(ArrayList blankItems)
{
this.blankItems = blankItems;
}
/**
*
*
* @return
*/
public boolean getReviewBlank()
{
return reviewBlank;
}
/**
*
*
* @param reviewBlank
*/
public void setReviewBlank(boolean reviewBlank)
{
this.reviewBlank = reviewBlank;
}
/**
*
*
* @return
*/
public ArrayList getMarkedForReviewIdents()
{
return markedForReviewIdents;
}
/**
*
*
* @param markedForReviewIdents
*/
public void setMarkedForReviewIdents(ArrayList markedForReviewIdents)
{
this.markedForReviewIdents = markedForReviewIdents;
}
/**
*
*
* @return
*/
public ArrayList getBlankItemIdents()
{
return blankItemIdents;
}
/**
*
*
* @param blankItemIdents
*/
public void setBlankItemIdents(ArrayList blankItemIdents)
{
this.blankItemIdents = blankItemIdents;
}
/**
*
*
* @return
*/
public int getSectionIndex()
{
return this.sectionIndex;
}
/**
*
*
* @param sectionIndex
*/
public void setSectionIndex(int sectionIndex)
{
this.sectionIndex = sectionIndex;
}
/**
*
*
* @return
*/
public boolean getPrevious()
{
return previous;
}
/**
*
*
* @param previous
*/
public void setPrevious(boolean previous)
{
this.previous = previous;
}
//Settings
public String getQuestionLayout()
{
return questionLayout;
}
/**
*
*
* @param questionLayout
*/
public void setQuestionLayout(String questionLayout)
{
this.questionLayout = questionLayout;
}
/**
*
*
* @return
*/
public String getNavigation()
{
return navigation;
}
/**
*
*
* @param navigation
*/
public void setNavigation(String navigation)
{
this.navigation = navigation;
}
/**
*
*
* @return
*/
public String getNumbering()
{
return numbering;
}
/**
*
*
* @param numbering
*/
public void setNumbering(String numbering)
{
this.numbering = numbering;
}
/**
*
*
* @return
*/
public String getFeedback()
{
return feedback;
}
/**
*
*
* @param feedback
*/
public void setFeedback(String feedback)
{
this.feedback = feedback;
}
/**
*
*
* @return
*/
public String getNoFeedback()
{
return noFeedback;
}
/**
*
*
* @param noFeedback
*/
public void setNoFeedback(String noFeedback)
{
this.noFeedback = noFeedback;
}
/**
*
*
* @return
*/
public String getStatistics()
{
return statistics;
}
/**
*
*
* @param statistics
*/
public void setStatistics(String statistics)
{
this.statistics = statistics;
}
/**
*
*
* @return
*/
public FeedbackComponent getFeedbackComponent()
{
return feedbackComponent;
}
/**
*
*
* @param feedbackComponent
*/
public void setFeedbackComponent(FeedbackComponent feedbackComponent)
{
this.feedbackComponent = feedbackComponent;
}
public String getFeedbackComponentOption()
{
return feedbackComponentOption;
}
public void setFeedbackComponentOption(String feedbackComponentOption)
{
this.feedbackComponentOption = feedbackComponentOption;
}
/**
* Types of feedback in FeedbackComponent:
*
* SHOW CORRECT SCORE
* SHOW STUDENT SCORE
* SHOW ITEM LEVEL
* SHOW SECTION LEVEL
* SHOW GRADER COMMENT
* SHOW STATS
* SHOW QUESTION
* SHOW RESPONSE
**/
/**
* @return
*/
public SettingsDeliveryBean getSettings()
{
// SAM-1438 - We occasionally see the settings bean as null during
// submission, within a JSF phase of deliverAssessment.jsp but it is
// generally not reproducible. This block protects against the bug
// by loading up the settings for this assessment. They are not assigned
// to the local settings variable as to avoid changing any more behavior
// than is needed. This is effectively a failsafe and diagnostic that
// should not really be necessary.
if (settings == null) {
Session session = SessionManager.getCurrentSession();
StringBuilder sb = new StringBuilder(400);
sb.append("SAM-1438 - Delivery settings bean is null.\n");
if (session != null) {
sb.append(" - User EID : ").append(session.getUserEid()).append("\n");
sb.append(" - User ID : ").append(session.getUserId()).append("\n");
sb.append(" - Session ID: ").append(session.getId()).append("\n");
} else {
sb.append(" - Session is null. Cannot determine user.\n");
}
sb.append(" - Published Assessment ID: ");
if (publishedAssessment == null) {
sb.append("<null>\n");
}
else {
sb.append(publishedAssessment.getPublishedAssessmentId()).append("\n");
sb.append(" - Assessment Title : ").append(publishedAssessment.getTitle()).append("\n");
sb.append(" - Assessment Site ID : ").append(publishedAssessment.getOwnerSiteId());
BeginDeliveryActionListener listener = new BeginDeliveryActionListener();
listener.populateBeanFromPub(this, publishedAssessment);
}
log.warn(sb.toString());
}
return settings;
}
/**
* @param bean
*/
public void setSettings(SettingsDeliveryBean settings)
{
this.settings = settings;
}
/**
* @return
*/
public String getErrorMessage()
{
return errorMessage;
}
/**
* @param string
*/
public void setErrorMessage(String string)
{
errorMessage = string;
}
/**
* @return
*/
public String getDuration()
{
return duration;
}
/**
* @param string
*/
public void setDuration(String string)
{
duration = string;
}
/**
* @return
*/
public String getCreatorName()
{
return creatorName;
}
/**
* @param string
*/
public void setCreatorName(String string)
{
creatorName = string;
}
public java.util.Date getDueDate()
{
return dueDate;
}
public String getDueDateString()
{
String dateString = "";
if (dueDate == null) {
return dateString;
}
try {
TimeUtil tu = new TimeUtil();
dateString = tu.getDisplayDateTime(displayFormat, dueDate);
}
catch (Exception ex) {
// we will leave it as an empty string
log.warn("Unable to format date.");
ex.printStackTrace();
}
return dateString;
}
public String getDayDueDateString()
{
String dateString = "";
if (dueDate == null) {
return dateString;
}
try {
TimeUtil tu = new TimeUtil();
dateString = tu.getDisplayDateTime(dayDisplayFormat, dueDate);
}
catch (Exception ex) {
// we will leave it as an empty string
log.warn("Unable to format date.");
ex.printStackTrace();
}
return dateString;
}
public void setDueDate(java.util.Date dueDate)
{
this.dueDate = dueDate;
}
public java.util.Date getRetractDate()
{
return retractDate;
}
public void setRetractDate(java.util.Date retractDate)
{
this.retractDate = retractDate;
}
public boolean isStatsAvailable()
{
return statsAvailable;
}
public void setStatsAvailable(boolean statsAvailable)
{
this.statsAvailable = statsAvailable;
}
public boolean isSubmitted()
{
return submitted;
}
public void setSubmitted(boolean submitted)
{
this.submitted = submitted;
}
public boolean isGraded()
{
return graded;
}
public void setGraded(boolean graded)
{
this.graded = graded;
}
public boolean getFeedbackOnDate()
{
return feedbackOnDate;
}
public void setFeedbackOnDate(boolean feedbackOnDate)
{
this.feedbackOnDate = feedbackOnDate;
}
public String getGraderComment()
{
if (graderComment == null)
{
return "";
}
return graderComment;
}
public void setGraderComment(String newComment)
{
graderComment = newComment;
}
public String getRawScore()
{
return rawScore;
}
public String getRoundedRawScore() {
try {
String newscore= ContextUtil.getRoundedValue(rawScore, 2);
return Validator.check(newscore, "N/A");
}
catch (Exception e) {
// encountered some weird number format/locale
return Validator.check(rawScore, "0");
}
}
public String getRoundedRawScoreViaURL() {
if (adata.getFinalScore() != null){
rawScore = adata.getFinalScore().toString();
}
else {
rawScore = "0";
}
try {
String newscore= ContextUtil.getRoundedValue(rawScore, 2);
return Validator.check(newscore, "N/A");
}
catch (Exception e) {
// encountered some weird number format/locale
return Validator.check(rawScore, "0");
}
}
public void setRawScore(String rawScore)
{
this.rawScore = rawScore;
}
public long getRaw()
{
return raw;
}
public void setRaw(long raw)
{
this.raw = raw;
}
public String getGrade()
{
return grade;
}
public void setGrade(String grade)
{
this.grade = grade;
}
public java.util.Date getSubmissionDate()
{
return submissionDate;
}
public String getSubmissionDateString()
{
String dateString = "";
if (submissionDate== null) {
return dateString;
}
try {
TimeUtil tu = new TimeUtil();
dateString = tu.getDisplayDateTime(displayFormat, submissionDate);
}
catch (Exception ex) {
// we will leave it as an empty string
log.warn("Unable to format date.");
ex.printStackTrace();
}
return dateString;
}
public void setSubmissionDate(java.util.Date submissionDate)
{
this.submissionDate = submissionDate;
}
public String getImage()
{
return image;
}
public void setImage(String image)
{
this.image = image;
}
public boolean isHasImage()
{
return hasImage;
}
public void setHasImage(boolean hasImage)
{
this.hasImage = hasImage;
}
public String getInstructorMessage()
{
return instructorMessage;
}
public void setInstructorMessage(String instructorMessage)
{
this.instructorMessage = instructorMessage;
}
public String getCourseName()
{
return courseName;
}
public void setCourseName(String courseName)
{
this.courseName = courseName;
}
public String getTimeLimit()
{
return timeLimit;
}
public void setTimeLimit(String timeLimit)
{
this.timeLimit = timeLimit;
}
public int getTimeLimit_hour()
{
return timeLimit_hour;
}
public void setTimeLimit_hour(int timeLimit_hour)
{
this.timeLimit_hour = timeLimit_hour;
}
public int getTimeLimit_minute()
{
return timeLimit_minute;
}
public void setTimeLimit_minute(int timeLimit_minute)
{
this.timeLimit_minute = timeLimit_minute;
}
/**
* Bean with table of contents information and
* a list of all the sections in the assessment
* which in turn has a list of all the item contents.
* @return table of contents
*/
public ContentsDeliveryBean getTableOfContents()
{
return tableOfContents;
}
/**
* Bean with table of contents information and
* a list of all the sections in the assessment
* which in turn has a list of all the item contents.
* @param tableOfContents table of contents
*/
public void setTableOfContents(ContentsDeliveryBean tableOfContents)
{
this.tableOfContents = tableOfContents;
}
/**
* Bean with a list of all the sections in the current page
* which in turn has a list of all the item contents for the page.
*
* This is like the table of contents, but the selections are restricted to
* that on one page.
*
* Since these properties are on a page delivery basis--if:
* 1. there is only one item per page the list of items will
* contain one item and the list of parts will return one part, or if--
*
* 2. there is one part per page the list of items will be that
* for that part only and there will only be one part, however--
*
* 3. if it is all parts and items on a single page there
* will be a list of all parts and items.
*
* @return ContentsDeliveryBean
*/
public ContentsDeliveryBean getPageContents()
{
return pageContents;
}
/**
* Bean with a list of all the sections in the current page
* which in turn has a list of all the item contents for the page.
*
* Since these properties are on a page delivery basis--if:
* 1. there is only one item per page the list of items will
* contain one item and the list of parts will return one part, or if--
*
* 2. there is one part per page the list of items will be that
* for that part only and there will only be one part, however--
*
* 3. if it is all parts and items on a single page there
* will be a list of all parts and items.
*
* @param pageContents ContentsDeliveryBean
*/
public void setPageContents(ContentsDeliveryBean pageContents)
{
this.pageContents = pageContents;
}
public String getSubmissionId()
{
return submissionId;
}
public void setSubmissionId(String submissionId)
{
this.submissionId = submissionId;
}
public String getSubmissionMessage()
{
return submissionMessage;
}
public void setSubmissionMessage(String submissionMessage)
{
this.submissionMessage = submissionMessage;
}
public int getSubmissionsRemaining()
{
return submissionsRemaining;
}
public void setSubmissionsRemaining(int submissionsRemaining)
{
this.submissionsRemaining = submissionsRemaining;
}
public int getTotalSubmissions()
{
return totalSubmissions;
}
public void setTotalSubmissions(int totalSubmissions)
{
this.totalSubmissions = totalSubmissions;
}
public String getInstructorName()
{
return instructorName;
}
public void setInstructorName(String instructorName)
{
this.instructorName = instructorName;
}
public boolean getForGrade()
{
return forGrade;
}
public void setForGrade(boolean newfor)
{
forGrade = newfor;
}
public String submitForGradeFromTimer()
{
return submitForGrade(true);
}
public String submitForGrade()
{
return submitForGrade(false);
}
private String submitForGrade(boolean isFromTimer) {
try{
if (this.actionMode == PREVIEW_ASSESSMENT) {
return "editAssessment";
}
EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.submit.click_sub", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), siteId, true, NotificationService.NOTI_REQUIRED));
String nextAction = checkBeforeProceed(true, isFromTimer);
log.debug("***** next Action="+nextAction);
EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.submit.checked", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), siteId, true, NotificationService.NOTI_REQUIRED));
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
setForGrade(true);
SessionUtil.setSessionTimeout(FacesContext.getCurrentInstance(), this, false);
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener = new SubmitToGradingActionListener();
// submission remaining and totalSubmissionPerAssessmentHash is updated inside
// SubmitToGradingListener
try {
listener.processAction(null);
}
catch (FinFormatException e) {
log.debug(e.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
catch (SamigoDataAccessException e) {
e.printStackTrace();
FacesContext context = FacesContext.getCurrentInstance();
String err = (String) ContextUtil.getLocalizedString(
"org.sakaiproject.tool.assessment.bundle.AuthorMessages",
"saveanswer_exception_error");
context.addMessage(null, new FacesMessage(err));
return "takeAssessment";
}
// We don't need to call completeItemGradingData to create new ItemGradingData for linear access
// because each ItemGradingData is created when it is viewed/answered
if (!"1".equals(navigation)) {
GradingService gradingService = new GradingService();
gradingService.completeItemGradingData(adata);
}
String returnValue="submitAssessment";
if (!isFromTimer) {
if (this.actionMode == TAKE_ASSESSMENT_VIA_URL) // this is for accessing via published url
{
returnValue="anonymousThankYou";
PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
String siteId = publishedAssessmentService.getPublishedAssessmentOwner(adata.getPublishedAssessmentId());
EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.submit.via_url", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), siteId, true, NotificationService.NOTI_REQUIRED));
}
else {
EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.submit", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), true));
}
}
else {
if (this.actionMode == TAKE_ASSESSMENT_VIA_URL) // this is for accessing via published url
{
returnValue="anonymousThankYou";
PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
String siteId = publishedAssessmentService.getPublishedAssessmentOwner(adata.getPublishedAssessmentId());
EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.timer_submit.url", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), siteId, true, NotificationService.NOTI_REQUIRED));
}
else {
EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.timer_submit", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), true));
}
}
forGrade = false;
SelectActionListener l2 = new SelectActionListener();
l2.processAction(null);
reload = true;
// finish within time limit, clean timedAssessment from queue
removeTimedAssessmentFromQueue();
// finish secure delivery
setSecureDeliveryHTMLFragment( "" );
setBlockDelivery( false );
SecureDeliveryServiceAPI secureDelivery = SamigoApiFactory.getInstance().getSecureDeliveryServiceAPI();
if ( secureDelivery.isSecureDeliveryAvaliable() ) {
String moduleId = publishedAssessment.getAssessmentMetaDataByLabel( SecureDeliveryServiceAPI.MODULE_KEY );
if ( moduleId != null && ! SecureDeliveryServiceAPI.NONE_ID.equals( moduleId ) ) {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
PhaseStatus status = secureDelivery.validatePhase(moduleId, Phase.ASSESSMENT_FINISH, publishedAssessment, request );
setSecureDeliveryHTMLFragment(
secureDelivery.getHTMLFragment(moduleId, publishedAssessment, request, Phase.ASSESSMENT_FINISH, status, new ResourceLoader().getLocale() ) );
}
}
EventLogService eventService = new EventLogService();
EventLogFacade eventLogFacade = new EventLogFacade();
List eventLogDataList = eventService.getEventLogData(adata.getAssessmentGradingId());
EventLogData eventLogData= (EventLogData) eventLogDataList.get(0);
eventLogData.setErrorMsg(eventLogMessages.getString("no_error"));
Date endDate = new Date();
eventLogData.setEndDate(endDate);
if(endDate != null && eventLogData.getStartDate() != null) {
double minute= 1000*60;
int eclipseTime = (int)Math.ceil(((endDate.getTime() - eventLogData.getStartDate().getTime())/minute));
eventLogData.setEclipseTime(Integer.valueOf(eclipseTime));
} else {
eventLogData.setEclipseTime(null);
eventLogData.setErrorMsg(eventLogMessages.getString("error_take"));
}
eventLogFacade.setData(eventLogData);
eventService.saveOrUpdateEventLog(eventLogFacade);
return returnValue;
}catch(Exception e) {
EventLogService eventService = new EventLogService();
EventLogFacade eventLogFacade = new EventLogFacade();
EventLogData eventLogData = null;
List eventLogDataList = eventService.getEventLogData(adata.getAssessmentGradingId());
if(eventLogDataList != null && eventLogDataList.size() > 0) {
eventLogData= (EventLogData) eventLogDataList.get(0);
eventLogData.setErrorMsg(eventLogMessages.getString("error_submit"));
eventLogData.setEndDate(new Date());
}
eventLogFacade.setData(eventLogData);
eventService.saveOrUpdateEventLog(eventLogFacade);
return null;
}
}
public String confirmSubmit()
{
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
if (adata != null) {
EventTrackingService.post(EventTrackingService.newEvent("sam.submit.from_last_page", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), siteId, true, NotificationService.NOTI_REQUIRED));
}
else {
EventTrackingService.post(EventTrackingService.newEvent("sam.submit.from_last_page", "siteId=" + AgentFacade.getCurrentSiteId() + ", adata is null", siteId, true, NotificationService.NOTI_REQUIRED));
}
}
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
setForGrade(false);
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener =
new SubmitToGradingActionListener();
try {
listener.processAction(null);
}
catch (FinFormatException fine) {
log.debug(fine.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
catch (SamigoDataAccessException e) {
e.printStackTrace();
FacesContext context = FacesContext.getCurrentInstance();
String err = (String) ContextUtil.getLocalizedString(
"org.sakaiproject.tool.assessment.bundle.AuthorMessages",
"saveanswer_exception_error");
context.addMessage(null, new FacesMessage(err));
return "takeAssessment";
}
}
DeliveryActionListener l2 = new DeliveryActionListener();
l2.processAction(null);
return "confirmsubmit";
}
public String confirmSubmitTOC()
{
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
if (adata != null) {
EventTrackingService.post(EventTrackingService.newEvent("sam.submit.from_toc", "siteId=" + AgentFacade.getCurrentSiteId() + ", submissionId=" + adata.getAssessmentGradingId(), siteId, true, NotificationService.NOTI_REQUIRED));
}
else {
EventTrackingService.post(EventTrackingService.newEvent("sam.submit.from_toc", "siteId=" + AgentFacade.getCurrentSiteId() + ", adata is null", siteId, true, NotificationService.NOTI_REQUIRED));
}
}
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
setForGrade(false);
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener =
new SubmitToGradingActionListener();
try {
listener.processAction(null);
}
catch (FinFormatException e) {
log.debug(e.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
}
setFromTableOfContents(true);
DeliveryActionListener l2 = new DeliveryActionListener();
l2.processAction(null);
setContinue(false);
return "confirmsubmit";
}
public String saveAndExit()
{
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
FacesContext context = FacesContext.getCurrentInstance();
SessionUtil.setSessionTimeout(context, this, false);
log.debug("***DeliverBean.saveAndEXit face context =" + context);
forGrade = false;
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener =
new SubmitToGradingActionListener();
try {
listener.processAction(null);
}
catch (FinFormatException e) {
log.debug(e.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
catch (SamigoDataAccessException e) {
e.printStackTrace();
String err = (String) ContextUtil.getLocalizedString(
"org.sakaiproject.tool.assessment.bundle.AuthorMessages",
"saveanswer_exception_error");
context.addMessage(null, new FacesMessage(err));
return "takeAssessment";
}
}
String returnValue = "saveForLaterWarning";
if (this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{ // if this is access via url, display quit message
log.debug("**anonymous login, go to quit");
returnValue = "anonymousQuit";
}
SelectActionListener l2 = new SelectActionListener();
l2.processAction(null);
reload = true;
// quit within time limit, clean timedAssessment from queue,
// removeTimedAssessmentFromQueue();
return returnValue;
}
public String next_page()
{
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
forGrade = false;
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener =
new SubmitToGradingActionListener();
try {
listener.processAction(null);
}
catch (FinFormatException e) {
log.debug(e.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
catch (SamigoDataAccessException e) {
e.printStackTrace();
FacesContext context = FacesContext.getCurrentInstance();
String err = (String) ContextUtil.getLocalizedString(
"org.sakaiproject.tool.assessment.bundle.AuthorMessages",
"saveanswer_exception_error");
context.addMessage(null, new FacesMessage(err));
return "takeAssessment";
}
}
if (getSettings().isFormatByPart())
{
partIndex++;
}
if (getSettings().isFormatByQuestion())
{
questionIndex++;
}
DeliveryActionListener l2 = new DeliveryActionListener();
l2.processAction(null);
if ("1".equals(navigation) && this.actionMode != PREVIEW_ASSESSMENT) {
LinearAccessDeliveryActionListener linearAccessDeliveryActionListener = new LinearAccessDeliveryActionListener();
linearAccessDeliveryActionListener.saveLastVisitedPosition(this, partIndex, questionIndex);
}
reload = false;
return "takeAssessment";
}
public String same_page()
{
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
forGrade = false;
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener =
new SubmitToGradingActionListener();
try {
listener.processAction(null);
}
catch (FinFormatException e) {
log.debug(e.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
}
DeliveryActionListener l2 = new DeliveryActionListener();
l2.processAction(null);
reload = false;
return "takeAssessment";
}
public String save_work()
{
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
forGrade = false;
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener =
new SubmitToGradingActionListener();
try {
listener.processAction(null);
}
catch (FinFormatException e) {
log.debug(e.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
catch (SamigoDataAccessException e) {
e.printStackTrace();
FacesContext context = FacesContext.getCurrentInstance();
String err = (String) ContextUtil.getLocalizedString(
"org.sakaiproject.tool.assessment.bundle.AuthorMessages",
"saveanswer_exception_error");
context.addMessage(null, new FacesMessage(err));
return "takeAssessment";
}
}
DeliveryActionListener l2 = new DeliveryActionListener();
l2.processAction(null);
reload = false;
return "takeAssessment";
}
public String previous()
{
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
if (getSettings().isFormatByPart())
{
partIndex--;
questionIndex = 0;
}
if (getSettings().isFormatByQuestion())
{
questionIndex--;
}
forGrade = false;
if (this.actionMode == TAKE_ASSESSMENT
|| this.actionMode == TAKE_ASSESSMENT_VIA_URL)
{
syncTimeElapsedWithServer();
SubmitToGradingActionListener listener =
new SubmitToGradingActionListener();
try {
listener.processAction(null);
}
catch (FinFormatException e) {
log.debug(e.getMessage());
return "takeAssessment";
}
catch (SaLengthException sae) {
log.debug(sae.getMessage());
return "takeAssessment";
}
}
DeliveryActionListener l2 = new DeliveryActionListener();
l2.processAction(null);
reload = false;
return "takeAssessment";
}
public String confirmSubmitPrevious()
{
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
forGrade = false;
syncTimeElapsedWithServer();
DeliveryActionListener l2 = new DeliveryActionListener();
l2.processAction(null);
return "takeAssessment";
}
// this is the PublishedAccessControl.finalPageUrl
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public String getConfirmation()
{
return confirmation;
}
public void setConfirmation(String confirmation)
{
this.confirmation = confirmation;
}
/**
* if required, assessment password
* @return password
*/
public String getPassword()
{
return password;
}
/**
* if required, assessment password
* @param string assessment password
*/
public void setPassword(String string)
{
password = string;
}
public String validatePassword()
{
log.debug("**** username=" + username);
log.debug("**** password=" + password);
log.debug("**** setting username=" + getSettings().getUsername());
log.debug("**** setting password=" + getSettings().getPassword());
if (password == null || username == null)
{
return "passwordAccessError";
}
if (password.equals(getSettings().getPassword()) &&
username.equals(getSettings().getUsername()))
{
// in post 2.1, clicking at Begin Assessment takes users to the
// 1st question.
return "takeAssessment";
}
else
{
return "passwordAccessError";
}
}
public String validateIP()
{
String thisIp = ( (javax.servlet.http.HttpServletRequest) FacesContext.
getCurrentInstance().getExternalContext().getRequest()).
getRemoteAddr();
Iterator addresses = getSettings().getIpAddresses().iterator();
while (addresses.hasNext())
{
String next = ( (PublishedSecuredIPAddress) addresses.next()).
getIpAddress();
if (next != null && next.indexOf("*") > -1)
{
next = next.substring(0, next.indexOf("*"));
}
if (next == null || next.trim().equals("") ||
thisIp.trim().startsWith(next.trim()))
{
// in post 2.1, clicking at Begin Assessment takes users to the
// 1st question.
return "takeAssessment";
}
}
return "ipAccessError";
}
public String validate()
{
try
{
String results = "takeAssessment";
EventLogService eventService = new EventLogService();
EventLogFacade eventLogFacade = new EventLogFacade();
EventLogData eventLogData = new EventLogData();
// #1. check password
if (!getSettings().getUsername().equals(""))
{
results = validatePassword();
log.debug("*** checked password="+results);
if("passwordAccessError".equals(results)) {
updatEventLog("error_pw_access");
}
}
// #2. check IP
if (!"passwordAccessError".equals(results) &&
getSettings().getIpAddresses() != null &&
!getSettings().getIpAddresses().isEmpty())
{
results = validateIP();
log.debug("*** checked password & IP="+results);
if(("ipAccessError").equals(results)) {
updatEventLog("error_ip_access");
}
}
// secure delivery START phase
// should occur before timer check, so that timer will be stopped if access is denied
setSecureDeliveryHTMLFragment( "" );
setBlockDelivery( false );
SecureDeliveryServiceAPI secureDelivery = SamigoApiFactory.getInstance().getSecureDeliveryServiceAPI();
if ( "takeAssessment".equals(results) && secureDelivery.isSecureDeliveryAvaliable() ) {
String moduleId = publishedAssessment.getAssessmentMetaDataByLabel( SecureDeliveryServiceAPI.MODULE_KEY );
if ( moduleId != null && ! SecureDeliveryServiceAPI.NONE_ID.equals( moduleId ) ) {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
PhaseStatus status = secureDelivery.validatePhase(moduleId, Phase.ASSESSMENT_START, publishedAssessment, request );
setSecureDeliveryHTMLFragment(
secureDelivery.getHTMLFragment(moduleId, publishedAssessment, request, Phase.ASSESSMENT_START, status, new ResourceLoader().getLocale() ) );
setBlockDelivery( PhaseStatus.FAILURE == status );
if ( PhaseStatus.SUCCESS == status ) {
results = "takeAssessment";
}
else {
results = "secureDeliveryError";
updatEventLog("error_secure_delivery");
}
}
}
// if results != "takeAssessment", stop the clock if it is a timed assessment
// Trouble was the timer was started by DeliveryActionListener before validate() is being run.
// So, we need to remove the timer thread as soon as we realized that the validation fails.
if (!("takeAssessment".equals(results)) && adata!=null) {
TimedAssessmentQueue queue = TimedAssessmentQueue.getInstance();
TimedAssessmentGradingModel timedAG = (TimedAssessmentGradingModel)queue.
get(adata.getAssessmentGradingId());
if (timedAG != null){
String agTimerId = timedAG.getTimerId();
if (agTimerId != null && agTimerId.equals(timerId)){
// SAK-6990: it is only safe to removed if u are sure that timedAG is started by your beginAssessment.jsp
// we added a hidden field timerId on beginAssessment.jsp. Upon successful security check, a timedAG
// will be created that carried this timerId. If user open another browser to take the same timed
// assessment. If the security check of the new one fails, it won't stop the clock for existing one.
queue.remove(timedAG);
timeRunning = false;
}
}
return results;
}
// check before proceed
String nextAction = checkBeforeProceed();
log.debug("***** next Action="+nextAction);
if (!("safeToProceed").equals(nextAction)){
return nextAction;
}
// #3. results="" => no security checking required
if ("".equals(results))
{
// in post 2.1, clicking at Begin Assessment takes users to the
// 1st question.
return "takeAssessment";
}
return results;
} catch (Exception e)
{
log.error("accessError" + e.getMessage());
EventLogService eventService = new EventLogService();
EventLogFacade eventLogFacade = new EventLogFacade();
EventLogData eventLogData = null;
List eventLogDataList = eventService.getEventLogData(adata.getAssessmentGradingId());
if(eventLogDataList != null && eventLogDataList.size() > 0) {
eventLogData= (EventLogData) eventLogDataList.get(0);
eventLogData.setErrorMsg(eventLogMessages.getString("error_access"));
}
eventLogFacade.setData(eventLogData);
eventService.saveOrUpdateEventLog(eventLogFacade);
return "accessError";
}
}
public void updatEventLog(String errorMsg)
{
EventLogService eventService = new EventLogService();
EventLogFacade eventLogFacade = new EventLogFacade();
EventLogData eventLogData = new EventLogData();
eventLogData.setAssessmentId(publishedAssessment.getPublishedAssessmentId());
eventLogData.setStartDate(new Date());
String agentEid = AgentFacade.getEid();
//ONC-3500
if(agentEid == null || "".equals(agentEid)){
agentEid= "N/A";
}
eventLogData.setUserEid(agentEid);
eventLogData.setTitle(publishedAssessment.getTitle());
String site_id= AgentFacade.getCurrentSiteId();
if(site_id == null) {
//take assessment via url
PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
site_id = publishedAssessmentService.getPublishedAssessmentOwner(publishedAssessment.getPublishedAssessmentId());
}
eventLogData.setSiteId(site_id);
eventLogData.setProcessId(null);
eventLogData.setEndDate(null);
eventLogData.setEclipseTime(null);
eventLogData.setErrorMsg(eventLogMessages.getString(errorMsg));
eventLogFacade.setData(eventLogData);
eventService.saveOrUpdateEventLog(eventLogFacade);
}
public String pvalidate()
{
// in post 2.1, clicking at Begin Assessment takes users to the
// 1st question.
return "takeAssessment";
}
// Skipped paging methods
public int getPartIndex()
{
return partIndex;
}
public void setPartIndex(int newindex)
{
partIndex = newindex;
}
public int getQuestionIndex()
{
return questionIndex;
}
public void setQuestionIndex(int newindex)
{
questionIndex = newindex;
}
public boolean getContinue()
{
return next_page;
}
public void setContinue(boolean docontinue)
{
next_page = docontinue;
}
public boolean getReload()
{
return reload;
}
public void setReload(boolean doreload)
{
reload = doreload;
}
// Store for paging
public AssessmentGradingData getAssessmentGrading()
{
return adata;
}
public void setAssessmentGrading(AssessmentGradingData newdata)
{
adata = newdata;
}
private byte[] getMediaStream(String mediaLocation)
{
FileInputStream mediaStream = null;
FileInputStream mediaStream2 = null;
byte[] mediaByte = new byte[0];
try
{
int i;
int size = 0;
mediaStream = new FileInputStream(mediaLocation);
if (mediaStream != null)
{
while ( (i = mediaStream.read()) != -1)
{
size++;
}
}
mediaStream2 = new FileInputStream(mediaLocation);
mediaByte = new byte[size];
if (mediaStream2 != null) {
mediaStream2.read(mediaByte, 0, size);
}
}
catch (FileNotFoundException ex)
{
log.error("file not found=" + ex.getMessage());
}
catch (IOException ex)
{
log.error("io exception=" + ex.getMessage());
}
finally
{
if (mediaStream != null) {
try
{
mediaStream.close();
}
catch (IOException ex1)
{
log.warn(ex1.getMessage());
}
}
if (mediaStream2 != null) {
try
{
mediaStream2.close();
}
catch (IOException ex1)
{
log.warn(ex1.getMessage());
}
}
}
return mediaByte;
}
/**
* This method is used by jsf/delivery/deliveryFileUpload.jsp
* <corejsf:upload
* target="/jsf/upload_tmp/assessment#{delivery.assessmentId}/
* question#{question.itemData.itemId}/admin"
* valueChangeListener="#{delivery.addMediaToItemGrading}" />
*/
public void addMediaToItemGrading(javax.faces.event.ValueChangeEvent e)
{
if (isTimeRunning() && timeExpired())
setOutcome("timeExpired");
String mediaLocation = (String) e.getNewValue();
String action = addMediaToItemGrading(mediaLocation);
syncTimeElapsedWithServer();
log.debug("****time passed after fileupload before loading of next question"+getTimeElapse());
setTimeElapseAfterFileUpload(getTimeElapse());
setOutcome(action);
}
/**
* This method is used by jsf/delivery/deliverAudioRecording.jsp and
* is called by addMediaToItemGrading(javax.faces.event.ValueChangeEvent e)
*
* @param mediaLocation the media location
* @return the action string
*/
public String addMediaToItemGrading(String mediaLocation)
{
log.debug("****"+mediaLocation+" "+(new Date()));
if (!mediaIsValid()) {
reload = true;
return "takeAssessment";
}
GradingService gradingService = new GradingService();
//PublishedAssessmentService publishedService = new PublishedAssessmentService();
HashMap itemHash = getPublishedItemHash();
PersonBean person = (PersonBean) ContextUtil.lookupBean("person");
String agent = person.getId();
// 2. format of the media location is: assessmentXXX/questionXXX/agentId/myfile
// 3. get the questionId (which is the PublishedItemData.itemId)
//int assessmentIndex = mediaLocation.indexOf("assessment");
int questionIndex = mediaLocation.indexOf("question");
int agentIndex = mediaLocation.indexOf("/", questionIndex + 8);
int myfileIndex = mediaLocation.lastIndexOf("/");
//cwen
if(agentIndex < 0 )
{
agentIndex = mediaLocation.indexOf("\\", questionIndex + 8);
}
//String pubAssessmentId = mediaLocation.substring(assessmentIndex + 10, questionIndex - 1);
String questionId = mediaLocation.substring(questionIndex + 8, agentIndex);
log.debug("***3a. addMediaToItemGrading, questionId =" + questionId);
log.debug("***3b. addMediaToItemGrading, assessmentId =" + assessmentId);
if (agent == null){
String agentId = mediaLocation.substring(agentIndex, myfileIndex -1);
log.debug("**** agentId="+agentId);
agent = agentId;
}
log.debug("***3c. addMediaToItemGrading, agent =" + agent);
// 4. prepare itemGradingData and attach it to assessmentGarding
PublishedItemData item = (PublishedItemData)itemHash.get(new Long(questionId));
log.debug("***4a. addMediaToItemGrading, itemText(0) =" +
item.getItemTextArray().get(0));
// there is only one text in audio question
PublishedItemText itemText = (PublishedItemText) item.
getItemTextArraySorted().get(0);
ItemGradingData itemGradingData = getItemGradingData(questionId);
boolean newItemGradingData = false;
if (itemGradingData == null)
{
newItemGradingData = true;
itemGradingData = new ItemGradingData();
itemGradingData.setAssessmentGradingId(adata.getAssessmentGradingId());
itemGradingData.setPublishedItemId(item.getItemId());
itemGradingData.setPublishedItemTextId(itemText.getId());
itemGradingData.setSubmittedDate(new Date());
itemGradingData.setAgentId(agent);
itemGradingData.setOverrideScore( Double.valueOf(0));
}
itemGradingData.setAutoScore(Double.valueOf(0));
setAssessmentGrading(adata);
// 5. save ItemGradingData alone 'cos assessmentGrading score won't be changed
// we don't need to update every itemGrading in assessmentGrading
gradingService.saveItemGrading(itemGradingData);
//if media is uploaded, create media record and attach to itemGradingData
saveMedia(agent, mediaLocation, itemGradingData, gradingService);
// 8. do whatever need doing
DeliveryActionListener dlistener = new DeliveryActionListener();
// false => do not reset the entire current delivery.pageContents.
// we will do it ourselves and only update the question that this media
// is attached to
dlistener.processAction(null, false);
if (newItemGradingData)
attachToItemContentBean(itemGradingData, questionId);
reload = true;
return "takeAssessment"; // which doesn't exists to force it to reload
}
public void saveMedia(String agent, String mediaLocation, ItemGradingData itemGradingData,
GradingService gradingService){
// 1. create a media record
File media = new File(mediaLocation);
byte[] mediaByte = getMediaStream(mediaLocation);
String mimeType = MimeTypesLocator.getInstance().getContentType(media);
boolean SAVETODB = getSaveToDb();
log.debug("**** SAVETODB=" + SAVETODB);
MediaData mediaData = null;
log.debug("***6a. addMediaToItemGrading, itemGradinDataId=" +
itemGradingData.getItemGradingId());
// 1b. get filename
String fullname = media.getName().trim();
int underscore_index = fullname.lastIndexOf("_");
int dot_index = fullname.lastIndexOf(".");
String filename = fullname.substring(0,underscore_index);
if (dot_index >= 0) {
filename = filename + fullname.substring(dot_index);
}
log.debug("**** filename="+filename);
String updatedFilename = gradingService.getFileName(itemGradingData.getItemGradingId(), agent, filename);
log.debug("**** updatedFilename="+updatedFilename);
if (SAVETODB)
{ // put the byte[] in
mediaData = new MediaData(itemGradingData, mediaByte,
Long.valueOf(mediaByte.length + ""),
mimeType, "description", null,
updatedFilename, false, false, Integer.valueOf(1),
agent, new Date(),
agent, new Date(), null);
}
else
{ // put the location in
mediaData = new MediaData(itemGradingData, null,
Long.valueOf(mediaByte.length + ""),
mimeType, "description", mediaLocation,
updatedFilename, false, false, Integer.valueOf(1),
agent, new Date(),
agent, new Date(), null);
}
Long mediaId = gradingService.saveMedia(mediaData);
log.debug("mediaId=" + mediaId);
log.debug("***6c. addMediaToItemGrading, media.itemGradinDataId=" +
( (ItemGradingData) mediaData.getItemGradingData()).
getItemGradingId());
log.debug("***6d. addMediaToItemGrading, mediaId=" + mediaData.getMediaId());
// 2. store mediaId in itemGradingRecord.answerText
log.debug("***7. addMediaToItemGrading, adata=" + adata);
itemGradingData.setAnswerText(mediaId + "");
gradingService.saveItemGrading(itemGradingData);
// 3. if saveToDB, remove file from file system
try{
if (SAVETODB) {
boolean success = media.delete();
if (!success){
log.warn("Error: media.delete() failed for mediaId =" + mediaId);
}
}
}
catch(Exception e){
log.warn(e.getMessage());
}
}
public boolean mediaIsValid()
{
boolean returnValue =true;
// check if file is too big
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext external = context.getExternalContext();
Long fileSize = (Long)((ServletContext)external.getContext()).getAttribute("TEMP_FILEUPLOAD_SIZE");
Long maxSize = (Long)((ServletContext)external.getContext()).getAttribute("FILEUPLOAD_SIZE_MAX");
//log.info("**** filesize is ="+fileSize);
//log.info("**** maxsize is ="+maxSize);
((ServletContext)external.getContext()).removeAttribute("TEMP_FILEUPLOAD_SIZE");
if (fileSize!=null){
float fileSize_float = fileSize.floatValue()/1024;
int tmp = Math.round(fileSize_float * 10.0f);
fileSize_float = (float)tmp / 10.0f;
float maxSize_float = maxSize.floatValue()/1024;
int tmp0 = Math.round(maxSize_float * 10.0f);
maxSize_float = (float)tmp0 / 10.0f;
String err1=(String)ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.DeliveryMessages", "file_upload_error");
String err2=(String)ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.DeliveryMessages", "file_uploaded");
String err3=(String)ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.DeliveryMessages", "max_size_allowed");
String err4=(String)ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.DeliveryMessages", "upload_again");
String err = err2 + fileSize_float + err3 + maxSize_float + err4;
context.addMessage("file_upload_error",new FacesMessage(err1));
context.addMessage("file_upload_error",new FacesMessage(err));
returnValue = false;
}
return returnValue;
}
public boolean getNotTakeable()
{
return notTakeable;
}
public void setNotTakeable(boolean notTakeable)
{
this.notTakeable = notTakeable;
}
public boolean getPastDue()
{
return pastDue;
}
public void setPastDue(boolean pastDue)
{
this.pastDue = pastDue;
}
public long getSubTime()
{
return subTime;
}
public void setSubTime(long newSubTime)
{
subTime = newSubTime;
}
public String getSubmissionHours()
{
return takenHours;
}
public void setSubmissionHours(String newHours)
{
takenHours = newHours;
}
public String getSubmissionMinutes()
{
return takenMinutes;
}
public void setSubmissionMinutes(String newMinutes)
{
takenMinutes = newMinutes;
}
public PublishedAssessmentFacade getPublishedAssessment()
{
return publishedAssessment;
}
public void setPublishedAssessment(PublishedAssessmentFacade
publishedAssessment)
{
this.publishedAssessment = publishedAssessment;
}
public java.util.Date getFeedbackDate()
{
return feedbackDate;
}
public String getFeedbackDateString()
{
String dateString = "";
if (feedbackDate== null) {
return dateString;
}
try {
TimeUtil tu = new TimeUtil();
dateString = tu.getDisplayDateTime(displayFormat, feedbackDate);
}
catch (Exception ex) {
// we will leave it as an empty string
log.warn("Unable to format date.");
ex.printStackTrace();
}
return dateString;
}
public void setFeedbackDate(java.util.Date feedbackDate)
{
this.feedbackDate = feedbackDate;
}
public String getFeedbackDelivery()
{
return feedbackDelivery;
}
public void setFeedbackDelivery(String feedbackDelivery)
{
this.feedbackDelivery = feedbackDelivery;
}
public String getShowScore()
{
return showScore;
}
public void setShowScore(String showScore)
{
this.showScore = showScore;
}
public boolean getHasTimeLimit()
{
return hasTimeLimit;
}
public void setHasTimeLimit(boolean hasTimeLimit)
{
this.hasTimeLimit = hasTimeLimit;
}
public String getOutcome()
{
return outcome;
}
public void setOutcome(String outcome)
{
this.outcome = outcome;
}
public String doit()
{
return outcome;
}
public boolean getAnonymousLogin()
{
return anonymousLogin;
}
public void setAnonymousLogin(boolean anonymousLogin)
{
this.anonymousLogin = anonymousLogin;
}
public ItemGradingData getItemGradingData(String publishedItemId)
{
ItemGradingData selected = null;
if (adata != null)
{
Set items = adata.getItemGradingSet();
if (items != null)
{
Iterator iter = items.iterator();
while (iter.hasNext())
{
ItemGradingData itemGradingData = (ItemGradingData) iter.next();
String itemPublishedId = itemGradingData.getPublishedItemId().
toString();
if ( (publishedItemId).equals(itemPublishedId))
{
log.debug("*** addMediaToItemGrading, same : found it");
selected = itemGradingData;
}
else
{
log.debug("*** addMediaToItemGrading, not the same");
}
}
log.debug("*** addMediaToItemGrading, publishedItemId =" +
publishedItemId);
if (selected != null)
{
log.debug(
"*** addMediaToItemGrading, itemGradingData.publishedItemId =" +
selected.getPublishedItemId().toString());
}
}
}
return selected;
}
public String getContextPath()
{
return contextPath;
}
public void setContextPath(String contextPath)
{
this.contextPath = contextPath;
}
public boolean isShowStudentScore()
{
return showStudentScore;
}
public void setShowStudentScore(boolean showStudentScore)
{
this.showStudentScore = showStudentScore;
}
public boolean isShowStudentQuestionScore()
{
return showStudentQuestionScore;
}
public void setShowStudentQuestionScore(boolean param)
{
this.showStudentQuestionScore = param;
}
public boolean isTimeRunning()
{
return timeRunning;
}
public void setTimeRunning(boolean timeRunning)
{
this.timeRunning = timeRunning;
}
/**
* Used for a JavaScript enable check.
*/
public String getJavaScriptEnabledCheck()
{
return this.javaScriptEnabledCheck;
}
/**
* Used for a JavaScript enable check.
*/
public void setJavaScriptEnabledCheck(String javaScriptEnabledCheck)
{
this.javaScriptEnabledCheck = javaScriptEnabledCheck;
}
//cwen
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
siteId = null;
Placement currentPlacement = ToolManager.getCurrentPlacement();
if(currentPlacement != null)
siteId = currentPlacement.getContext();
return siteId;
}
public String getAgentAccessString()
{
return deliveryAgent.getAgentInstanceString();
}
public void setAgentAccessString(String agentString)
{
deliveryAgent.setAgentInstanceString(agentString);
}
public boolean getSaveToDb(){
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext external = context.getExternalContext();
String saveToDb = (String)((ServletContext)external.getContext()).getAttribute("FILEUPLOAD_SAVE_MEDIA_TO_DB");
if (("true").equals(saveToDb))
return true;
else
return false;
}
public void attachToItemContentBean(ItemGradingData itemGradingData, String questionId){
ArrayList list = new ArrayList();
list.add(itemGradingData);
//find out sectionId from questionId
log.debug("**** attachToItemContentBean, questionId="+questionId);
/*
PublishedAssessmentService publishedService = new
PublishedAssessmentService();
PublishedItemData publishedItem = publishedService.
loadPublishedItem(questionId);
*/
PublishedItemData publishedItem = (PublishedItemData) getPublishedItemHash().get(new Long(questionId));
PublishedSectionData publishedSection = (PublishedSectionData) publishedItem.getSection();
String sectionId = publishedSection.getSectionId().toString();
SectionContentsBean partSelected = null;
//get all partContents
ArrayList parts = getPageContents().getPartsContents();
for (int i=0; i<parts.size(); i++){
SectionContentsBean part = (SectionContentsBean)parts.get(i);
log.debug("**** question's sectionId"+sectionId);
log.debug("**** partId"+part.getSectionId());
if (sectionId.equals(part.getSectionId())){
partSelected = part;
break;
}
}
//locate the itemContentBean - the hard way, sigh...
ArrayList items = new ArrayList();
if (partSelected!=null)
items = partSelected.getItemContents();
for (int j=0; j<items.size(); j++){
ItemContentsBean item = (ItemContentsBean)items.get(j);
if ((publishedItem.getItemId()).equals(item.getItemData().getItemId())){ // comparing itemId not object
item.setItemGradingDataArray(list);
break;
}
}
}
// delivery action
public static final int TAKE_ASSESSMENT = 1;
public static final int PREVIEW_ASSESSMENT = 2;
public static final int REVIEW_ASSESSMENT = 3;
public static final int GRADE_ASSESSMENT = 4;
public static final int TAKE_ASSESSMENT_VIA_URL = 5;
private int actionMode;
private String actionString;
public void setActionString(String actionString){
this.actionString = actionString;
// the follwoing two values will be evaluated when reviewing assessment
// based on PublishedFeedback settings
setFeedback("false");
setNoFeedback("true");
if (("previewAssessment").equals(actionString)){
setActionMode(PREVIEW_ASSESSMENT);
}
else if (("reviewAssessment").equals(actionString)){
setActionMode(REVIEW_ASSESSMENT);
}
else if (("gradeAssessment").equals(actionString)){
setFeedback("true");
setNoFeedback("false");
setActionMode(GRADE_ASSESSMENT);
}
else if (("takeAssessment").equals(actionString)){
setActionMode(TAKE_ASSESSMENT);
}
else if (("takeAssessmentViaUrl").equals(actionString)){
setActionMode(TAKE_ASSESSMENT_VIA_URL);
}
}
public String getActionString(){
return actionString;
}
private void setActionMode(int actionMode){
this.actionMode = actionMode;
}
public int getActionMode(){
return actionMode;
}
private long time=0;
public void setLastTimer(long time){
this.time = time;
}
public long getLastTimer(){
return time;
}
public boolean getBeginAssessment(){
return beginAssessment;
}
public void setBeginAssessment(boolean beginAssessment){
this.beginAssessment = beginAssessment;
}
public boolean timeExpired(){
if (adata == null) {
return false;
}
boolean timeExpired = false;
TimedAssessmentQueue queue = TimedAssessmentQueue.getInstance();
TimedAssessmentGradingModel timedAG = (TimedAssessmentGradingModel)queue.
get(adata.getAssessmentGradingId());
if (timedAG != null){
// if server already submit the assessment, this happen if JScript latency is very long
// and assessment passed the time left + latency buffer
// in this case, we will display the time expired message.
if (timedAG.getSubmittedForGrade()){
timeExpired = true;
queue.remove(timedAG);
}
}
else{
// null => not only does the assessment miss the latency buffer, it also missed the
// transaction buffer
timeExpired = true;
}
return timeExpired;
}
private void removeTimedAssessmentFromQueue(){
TimedAssessmentQueue queue = TimedAssessmentQueue.getInstance();
TimedAssessmentGradingModel timedAG = (TimedAssessmentGradingModel)queue.
get(adata.getAssessmentGradingId());
if (timedAG != null){
queue.remove(timedAG);
timeRunning = false;
}
}
public void syncTimeElapsedWithServer(){
if (("takeAssessment").equals(actionString) || ("takeAssessmentViaUrl").equals(actionString)){
TimedAssessmentQueue queue = TimedAssessmentQueue.getInstance();
TimedAssessmentGradingModel timedAG = queue.get(adata.getAssessmentGradingId());
if (timedAG != null){
int timeElapsed = Math.round((new Date().getTime() - adata.getAttemptDate().getTime())/1000.0f);
log.debug("***setTimeElapsed="+timeElapsed);
adata.setTimeElapsed( Integer.valueOf(timeElapsed));
GradingService gradingService = new GradingService();
gradingService.saveOrUpdateAssessmentGrading(adata);
setTimeElapse(adata.getTimeElapsed().toString());
}
}
else{
// if we are in other mode, timer need not be accurate
// Anyway, we don't have adata, so we haven't been using the TimerTask to keep track of it.
}
}
public void syncTimeElapsedWithServerLinear(){
if (("takeAssessment").equals(actionString) || ("takeAssessmentViaUrl").equals(actionString)){
TimedAssessmentQueue queue = TimedAssessmentQueue.getInstance();
TimedAssessmentGradingModel timedAG = queue.get(adata.getAssessmentGradingId());
if (timedAG != null){
int timeElapsed = Math.round((new Date().getTime() - adata.getAttemptDate().getTime())/1000.0f);
adata.setTimeElapsed(Integer.valueOf(timeElapsed));
GradingService gradingService = new GradingService();
gradingService.saveOrUpdateAssessmentGradingOnly(adata);
setTimeElapse(adata.getTimeElapsed().toString());
}
}
else{
// if we are in other mode, timer need not be accurate
// Anyway, we don't have adata, so we haven't been using the TimerTask to keep track of it.
}
}
private String timeElapseAfterFileUpload;
public String getTimeElapseAfterFileUpload()
{
return timeElapseAfterFileUpload;
}
public void setTimeElapseAfterFileUpload(String timeElapseAfterFileUpload)
{
this.timeElapseAfterFileUpload = timeElapseAfterFileUpload;
if (timeElapseAfterFileUpload!=null && !("").equals(timeElapseAfterFileUpload))
setTimeElapseAfterFileUploadDouble(( Double.valueOf(timeElapseAfterFileUpload)).doubleValue());
}
private double timeElapseDouble=0;
public double getTimeElapseDouble()
{
return timeElapseDouble;
}
public void setTimeElapseDouble(double timeElapseDouble)
{
this.timeElapseDouble = timeElapseDouble;
}
private double timeElapseAfterFileUploadDouble;
public double getTimeElapseAfterFileUploadDouble()
{
return timeElapseAfterFileUploadDouble;
}
public void setTimeElapseAfterFileUploadDouble(double timeElapseAfterFileUploadDouble)
{
this.timeElapseAfterFileUploadDouble = timeElapseAfterFileUploadDouble;
}
private String protocol;
public String getProtocol(){
return protocol;
}
public void setProtocol(String protocol){
this.protocol = protocol;
}
private long timeStamp;
public long getTimeStamp(){
return timeStamp;
}
public void setTimeStamp(long timeStamp){
this.timeStamp=timeStamp;
}
private HashMap publishedItemHash = new HashMap();
public HashMap getPublishedItemHash(){
if (this.publishedItemHash.size() ==0){
PublishedAssessmentService pubService = new PublishedAssessmentService();
this.publishedItemHash = pubService.preparePublishedItemHash(getPublishedAssessment());
}
return this.publishedItemHash;
}
public void setPublishedItemHash(HashMap publishedItemHash){
this.publishedItemHash = publishedItemHash;
}
private HashMap publishedItemTextHash = new HashMap();
public HashMap getPublishedItemTextHash(){
if (this.publishedItemTextHash.size() == 0){
PublishedAssessmentService pubService = new PublishedAssessmentService();
this.publishedItemTextHash = pubService.preparePublishedItemTextHash(getPublishedAssessment());
}
return this.publishedItemTextHash;
}
public void setPublishedItemTextHash(HashMap publishedItemTextHash){
this.publishedItemTextHash = publishedItemTextHash;
}
private HashMap publishedAnswerHash = new HashMap();
public HashMap getPublishedAnswerHash(){
if (this.publishedAnswerHash.size() == 0){
PublishedAssessmentService pubService = new PublishedAssessmentService();
this.publishedAnswerHash = pubService.preparePublishedAnswerHash(getPublishedAssessment());
}
return this.publishedAnswerHash;
}
public void setPublishedAnswerHash(HashMap publishedAnswerHash){
this.publishedAnswerHash = publishedAnswerHash;
}
public boolean getIsMoreThanOneQuestion() {
log.debug("getIsMoreThanOneQuestion() starts");
ArrayList partsContents = this.pageContents.getPartsContents();
if (partsContents.size() == 1) {
String size = ((SectionContentsBean) partsContents.get(0)).getItemContentsSize();
log.debug("ItemContentsSize = " + size);
if ("1".equals(size)) {
log.debug("isMoreThanOneQuestion set to false");
isMoreThanOneQuestion = false;
}
}
else {
log.debug("isMoreThanOneQuestion set to true");
isMoreThanOneQuestion = true;
}
return isMoreThanOneQuestion;
}
private List attachmentList;
public List getAttachmentList() {
return attachmentList;
}
public void setAttachmentList(List attachmentList)
{
this.attachmentList = attachmentList;
}
private boolean hasAttachment = false;
public boolean getHasAttachment(){
boolean hasAttachment = false;
if (attachmentList!=null && attachmentList.size() >0){
hasAttachment = true;
}
return hasAttachment;
}
public boolean getNoQuestions() {
return noQuestions;
}
public void setNoQuestions(boolean noQuestions)
{
this.noQuestions = noQuestions;
}
/**
*
* @param isSubmitForGrade
* @param isFromTimer
* @param isViaUrlLogin
* @return
*/
public String checkBeforeProceed(boolean isSubmitForGrade, boolean isFromTimer, boolean isViaUrlLogin){
// public method, who know if publishedAssessment is set, so check
// to be sure
if (getPublishedAssessment() == null){
return "error";
}
if (this.actionMode == PREVIEW_ASSESSMENT) {
return "safeToProceed";
}
GradingService service = new GradingService();
AssessmentGradingData assessmentGrading=null;
if (adata!=null){
assessmentGrading = service.load(adata.getAssessmentGradingId().toString(), false);
}
PublishedAssessmentService pubService = new PublishedAssessmentService();
int totalSubmitted = (pubService.getTotalSubmission(AgentFacade.getAgentString(),
getPublishedAssessment().getPublishedAssessmentId().toString())).intValue();
log.debug("***totalSubmitted="+totalSubmitted);
// log.debug("check 0");
if (isRemoved()){
return "isRemoved";
}
log.debug("check 1");
// check 0: check for start date
if (!isAvailable()){
return ("assessmentNotAvailable");
}
log.debug("check 2");
// check 2: is it still available?
if (!isFromTimer && isRetracted(isSubmitForGrade)){
return "isRetracted";
}
log.debug("check 3");
// check 3: is it still available?
if (isRetractedForEdit()){
return "isRetractedForEdit";
}
log.debug("check 4");
// check 4: check for multiple window & browser trick
if (assessmentGrading!=null && !checkDataIntegrity(assessmentGrading)){
return ("discrepancyInData");
}
log.debug("check 5");
// check 5: if workingassessment has been submiited?
// this is to prevent student submit assessment and use a 2nd window to
// continue working on the submitted work.
if (assessmentGrading!=null && getAssessmentHasBeenSubmitted(assessmentGrading)){
return "assessmentHasBeenSubmitted";
}
log.debug("check 6");
// check 6: is it need to resubmit? If yes, we don't check on submission number, dates, or time.
if (isNeedResubmit()){
return "safeToProceed";
}
GradingService gradingService = new GradingService();
int numberRetake = gradingService.getNumberRetake(publishedAssessment.getPublishedAssessmentId(), AgentFacade.getAgentString());
log.debug("check 7");
// check 7: any submission attempt left?
if (!getHasSubmissionLeft(totalSubmitted, numberRetake)){
return "noSubmissionLeft";
}
log.debug("check 8");
// check 8: accept late submission?
boolean acceptLateSubmission = AssessmentAccessControlIfc.
ACCEPT_LATE_SUBMISSION.equals(publishedAssessment.getAssessmentAccessControl().getLateHandling());
// check 7: has dueDate arrived? if so, does it allow late submission?
// If it is a timed assessment and "No Late Submission" and not during a Retake, always go through. Because in this case the
// assessment will be auto-submitted anyway - when time is up or when current date reaches due date (if the time limited is
// longer than due date,) for either case, we want to redirect to the normal "submision successful page" after submitting.
if (pastDueDate()){
// If Accept Late and there is no submission yet, go through
if (acceptLateSubmission && totalSubmitted == 0) {
log.debug("Accept Late Submission && totalSubmitted == 0");
}
else {
log.debug("take from bean: actualNumberRetake =" + actualNumberRetake);
// Not during a Retake
if (actualNumberRetake == numberRetake) {
// When taking the assessment via URL (from LoginServlet), if pass due date, throw an error
if (isViaUrlLogin) {
return "noLateSubmission";
}
// If No Late, this is a timed assessment, and not during a Retake, go through (see above reason)
else if (!acceptLateSubmission && this.isTimedAssessment()) {
log.debug("No Late Submission && timedAssessment");
}
else {
log.debug("noLateSubmission");
return "noLateSubmission";
}
}
// During a Retake
else if (actualNumberRetake == numberRetake - 1) {
log.debug("actualNumberRetake == numberRetake - 1: through Retake");
}
// Should not come to here
else {
log.error("Should NOT come to here - wrong actualNumberRetake or numberRetake");
}
}
}
log.debug("check9");
// check 9: is timed assessment? and time has expired?
if (isTimeRunning() && timeExpired()){
return "timeExpired";
}
else return "safeToProceed";
}
public String checkFromViaUrlLogin(){
return checkBeforeProceed(false, false, true);
}
public String checkBeforeProceed(){
return checkBeforeProceed(false, false);
}
public String checkBeforeProceed(boolean isSubmitForGrade, boolean isFromTimer){
return checkBeforeProceed(isSubmitForGrade, isFromTimer, false);
}
private boolean getHasSubmissionLeft(int totalSubmitted, int numberRetake){
boolean hasSubmissionLeft = false;
int maxSubmissionsAllowed = 9999;
if ( (Boolean.FALSE).equals(publishedAssessment.getAssessmentAccessControl().getUnlimitedSubmissions())){
maxSubmissionsAllowed = publishedAssessment.getAssessmentAccessControl().getSubmissionsAllowed().intValue();
if ("takeAssessmentViaUrl".equals(actionString) && !anonymousLogin && settings == null) {
SettingsDeliveryBean settingsDeliveryBean = new SettingsDeliveryBean();
settingsDeliveryBean.setAssessmentAccessControl(publishedAssessment);
settingsDeliveryBean.setMaxAttempts(maxSubmissionsAllowed);
settings = settingsDeliveryBean;
}
}
if (totalSubmitted < maxSubmissionsAllowed + numberRetake){
hasSubmissionLeft = true;
}
return hasSubmissionLeft;
}
private boolean isAvailable(){
boolean isAvailable = true;
Date currentDate = new Date();
Date startDate = publishedAssessment.getAssessmentAccessControl().getStartDate();
if (startDate != null && startDate.after(currentDate)){
isAvailable = false;
}
return isAvailable;
}
private boolean pastDueDate(){
boolean pastDue = true;
Date currentDate = new Date();
Date dueDate = publishedAssessment.getAssessmentAccessControl().getDueDate();
if (dueDate == null || dueDate.after(currentDate)){
pastDue = false;
}
return pastDue;
}
private boolean isRetracted(boolean isSubmitForGrade){
boolean isRetracted = true;
Date currentDate = new Date();
Date retractDate = null;
if (isSubmitForGrade) {
PublishedAssessmentService pubService = new PublishedAssessmentService();
PublishedAssessmentData publishedAssessmentData = pubService.getBasicInfoOfPublishedAssessment(getPublishedAssessment().getPublishedAssessmentId().toString());
retractDate = publishedAssessmentData.getRetractDate();
}
else {
retractDate = publishedAssessment.getAssessmentAccessControl().getRetractDate();
}
if (retractDate == null || retractDate.after(currentDate)){
isRetracted = false;
}
return isRetracted;
}
private boolean isRemoved(){
Integer status = publishedAssessment.getStatus();
if (status.equals(AssessmentBaseIfc.DEAD_STATUS)) {
return true;
}
return false;
}
private boolean isRetractedForEdit(){
Integer status = publishedAssessment.getStatus();
if (status.equals(AssessmentBaseIfc.RETRACT_FOR_EDIT_STATUS)) {
return true;
}
return false;
}
private boolean isNeedResubmit(){
if (adata == null) {
return false;
}
Integer status = adata.getStatus();
if (status.equals(AssessmentGradingData.ASSESSMENT_UPDATED_NEED_RESUBMIT)) {
return true;
}
return false;
}
private boolean checkDataIntegrity(AssessmentGradingData assessmentGrading){
// get assessmentGrading from DB, this is to avoid same assessment being
// opened in the differnt browser
if (assessmentGrading !=null){
long DBdate = 0;
if (assessmentGrading.getSubmittedDate()!=null){
DBdate = assessmentGrading.getSubmittedDate().getTime();
}
String browserDateString = ContextUtil.lookupParam("lastSubmittedDate1");
if (browserDateString == null){
browserDateString = ContextUtil.lookupParam("lastSubmittedDate2");
}
// SAK-7106:jsf doesn't like id with same name even though there is a rendering condition there
// so we have to use 2 differnt id and check it this way instead.
long browserDate=0;
try{
if (browserDateString!=null){
browserDate = Long.parseLong(browserDateString);
}
else {
return true;
}
}
catch(Exception e){
log.warn(e.getMessage());
}
log.debug("last modified date in DB="+DBdate);
log.debug("last modified date in browser="+browserDate);
log.debug("date is equal="+(DBdate==browserDate));
return (DBdate==browserDate);
}
else return true;
}
private boolean getAssessmentHasBeenSubmitted(AssessmentGradingData assessmentGrading){
// get assessmentGrading from DB, this is to avoid same assessment being
// opened in the differnt browser
if (assessmentGrading !=null){
return assessmentGrading.getForGrade().booleanValue();
}
else return false;
}
public String getPortal(){
return ServerConfigurationService.getString("portalPath");
}
public String getSelectURL(){
Session session = SessionManager.getCurrentSession();
String returnUrl = (String)session.getAttribute("LESSONBUILDER_RETURNURL_SAMIGO");
if (returnUrl != null)
return returnUrl;
StringBuilder url = new StringBuilder(ServerConfigurationService.getString("portalPath"));
url.append("/site/");
PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
String currentSiteId = publishedAssessmentService.getPublishedAssessmentSiteId(getAssessmentId());
url.append(currentSiteId);
url.append("/page/");
url.append(getCurrentPageId(currentSiteId));
return url.toString();
}
public String getTimerId()
{
return timerId;
}
public void setTimerId(String timerId)
{
this.timerId = timerId;
}
private Site getCurrentSite(String id) {
Site site = null;
//Placement placement = ToolManager.getCurrentPlacement();
//String currentSiteId = placement.getContext();
try {
site = SiteService.getSite(id);
} catch (IdUnusedException e) {
log.error(e.getMessage());
e.printStackTrace();
}
return site;
}
private String getCurrentPageId(String id) {
Site currentSite = getCurrentSite(id);
if (currentSite == null) {
return "";
}
SitePage page = null;
String toolId = null;
try {
// get page
List pageList = currentSite.getPages();
for (int i = 0; i < pageList.size(); i++) {
page = (SitePage) pageList.get(i);
List pageToolList = page.getTools();
//toolId = ((ToolConfiguration) pageToolList.get(0)).getTool().getId();
// gopalrc - Jan 2008 - issue with null tool
if (pageToolList.get(0)==null && ((ToolConfiguration) pageToolList.get(0)).getTool()==null) {
continue;
}
toolId = ((ToolConfiguration) pageToolList.get(0)).getToolId();
if (toolId.equalsIgnoreCase("sakai.samigo")) {
return page.getId();
}
}
} catch (Exception e) {
log.warn(e.getMessage());
}
return "";
}
public Long getAssessmentGradingId()
{
return assessmentGradingId;
}
public void setFromTableOfContents(boolean fromTableOfContents)
{
this.fromTableOfContents = fromTableOfContents;
}
public boolean getFromTableOfContents()
{
return fromTableOfContents;
}
public void setAssessmentGradingId(Long assessmentGradingId)
{
this.assessmentGradingId = assessmentGradingId;
}
// This is for SAK-9505
// Preview is fixed for SAK-11474
// If not during preview, dueDate is not null, Late Submission is not allowed, and not during a retake
// we reset the time limit to the smaller one of
// 1. assessment "time limit" and 2. the difference of due date and current.
public String updateTimeLimit(String timeLimit) {
boolean acceptLateSubmission = AssessmentAccessControlIfc.
ACCEPT_LATE_SUBMISSION.equals(publishedAssessment.getAssessmentAccessControl().getLateHandling());
GradingService gradingService = new GradingService();
numberRetake = gradingService.getNumberRetake(publishedAssessment.getPublishedAssessmentId(), AgentFacade.getAgentString());
log.debug("numberRetake = " + numberRetake);
actualNumberRetake = gradingService.getActualNumberRetake(publishedAssessment.getPublishedAssessmentId(), AgentFacade.getAgentString());
log.debug("actualNumberRetake =" + actualNumberRetake);
if (!("previewAssessment").equals(actionString) && actualNumberRetake >= numberRetake && beginTime != null) {
if (dueDate != null && !acceptLateSubmission) {
int timeBeforeDue = Math.round((dueDate.getTime() - beginTime.getTime())/1000.0f);
if (timeBeforeDue < Integer.parseInt(timeLimit)) {
return String.valueOf(timeBeforeDue);
}
}
if (retractDate != null) {
int timeBeforeRetract = Math.round((retractDate.getTime() - beginTime.getTime())/1000.0f);
if (timeBeforeRetract < Integer.parseInt(timeLimit)) {
return String.valueOf(timeBeforeRetract);
}
}
}
return timeLimit;
}
private boolean isTimedAssessment() {
if (this.getPublishedAssessment().getAssessmentAccessControl().getTimeLimit().equals(Integer.valueOf(0))) {
return false;
}
return true;
}
public String cleanRadioButton() {
// We get the id of the question
String radioId = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("radioId");
StringBuffer redrawAnchorName = new StringBuffer("p");
String tmpAnchorName = "";
ArrayList parts = this.pageContents.getPartsContents();
for (int i=0; i<parts.size(); i++) {
SectionContentsBean sectionContentsBean = (SectionContentsBean) parts.get(i);
String partSeq = sectionContentsBean.getNumber();
ArrayList items = sectionContentsBean.getItemContents();
for (int j=0; j<items.size(); j++) {
ItemContentsBean item = (ItemContentsBean)items.get(j);
//Just delete the checkbox of the current question
if (!item.getItemData().getItemId().toString().equals(radioId)) continue;
String itemSeq = item.getItemData().getSequence().toString();
redrawAnchorName.append(partSeq);
redrawAnchorName.append("q");
redrawAnchorName.append(itemSeq);
if (tmpAnchorName.equals("") || tmpAnchorName.compareToIgnoreCase(redrawAnchorName.toString()) > 0) {
tmpAnchorName = redrawAnchorName.toString();
}
if (item.getItemData().getTypeId().longValue() == TypeIfc.MULTIPLE_CHOICE.longValue() ||
item.getItemData().getTypeId().longValue() == TypeIfc.MULTIPLE_CORRECT_SINGLE_SELECTION.longValue() ||
item.getItemData().getTypeId().longValue() == TypeIfc.MULTIPLE_CHOICE_SURVEY.longValue()) {
item.setUnanswered(true);
for (int k=0; k<item.getSelectionArray().size(); k++) {
SelectionBean selection = (SelectionBean)item.getSelectionArray().get(k);
//selection.setResponse(false);
selection.setResponseFromCleanRadioButton();
}
ArrayList itemGradingData = new ArrayList();
Iterator iter = item.getItemGradingDataArray().iterator();
while (iter.hasNext())
{
ItemGradingData itemgrading = (ItemGradingData) iter.next();
if (itemgrading.getItemGradingId() != null
&& itemgrading.getItemGradingId().intValue() > 0) {
itemGradingData.add(itemgrading);
itemgrading.setPublishedAnswerId(null);
}
}
item.setItemGradingDataArray(itemGradingData);
}
if (item.getItemData().getTypeId().longValue() == TypeIfc.TRUE_FALSE.longValue()) {
item.setResponseId(null);
Iterator iter = item.getItemGradingDataArray().iterator();
if (iter.hasNext())
{
ItemGradingData data = (ItemGradingData) iter.next();
data.setPublishedAnswerId(null);
}
}
item.setReview(false);
item.setRationale("");
}
}
syncTimeElapsedWithServer();
// Set the anchor
setRedrawAnchorName(tmpAnchorName.toString());
return "takeAssessment";
}
/**
*
*
* @return
*/
public boolean getDisplayMardForReview()
{
return this.displayMardForReview;
}
/**
*
*
* @param reviewMarked
*/
public void setDisplayMardForReview(boolean displayMardForReview)
{
this.displayMardForReview = displayMardForReview;
}
public HashMap getItemContentsMap()
{
return this.itemContentsMap;
}
public void setItemContentsMap(HashMap itemContentsMap)
{
this.itemContentsMap = itemContentsMap;
}
public String getAutoSaveRepeatMilliseconds()
{
String s = ServerConfigurationService.getString("samigo.autoSave.repeat.milliseconds");
try {
Integer.parseInt(s);
}
catch (NumberFormatException ex) {
s = "-1";
}
log.debug("auto save every " + s + " milliseconds");
return s;
}
public void setFileUploadSizeMax(int fileUploadSizeMax)
{
this.fileUploadSizeMax = fileUploadSizeMax;
}
public int getFileUploadSizeMax()
{
return fileUploadSizeMax;
}
public boolean getStudentRichText()
{
String studentRichText = ServerConfigurationService.getString("samigo.studentRichText", "true");
return Boolean.parseBoolean(studentRichText);
}
public void setDisplayFormat()
{
display_dateFormat= ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.GeneralMessages","output_date_no_sec");
displayFormat = new SimpleDateFormat(display_dateFormat, new ResourceLoader().getLocale());
}
public Integer getScoringType()
{
return scoringType;
}
public void setScoringType(Integer scoringType)
{
this.scoringType = scoringType;
}
public String getSecureDeliveryHTMLFragment() {
return this.secureDeliveryHTMLFragment;
}
public void setSecureDeliveryHTMLFragment(String secureDeliveryHTMLFragment) {
this.secureDeliveryHTMLFragment = secureDeliveryHTMLFragment;
}
public boolean isBlockDelivery() {
return blockDelivery;
}
public void setBlockDelivery(boolean blockDelivery) {
this.blockDelivery = blockDelivery;
}
public boolean getIsFromPrint()
{
return isFromPrint;
}
public void setIsFromPrint(boolean isFromPrint)
{
this.isFromPrint = isFromPrint;
}
public boolean getIsAnyInvalidFinInput()
{
return isAnyInvalidFinInput;
}
public void setIsAnyInvalidFinInput(boolean isAnyInvalidFinInput)
{
this.isAnyInvalidFinInput = isAnyInvalidFinInput;
}
public String getRedrawAnchorName()
{
return redrawAnchorName;
}
public void setRedrawAnchorName(String redrawAnchorName)
{
this.redrawAnchorName = redrawAnchorName;
}
public String getRecURL()
{
if (RECPATH == null || RECPATH.trim().equals("")) {
return "";
}
String recURL = ACCESSBASE + RECPATH;
return recURL;
}
}