/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/LinearAccessDeliveryActionListener.java $
* $Id: LinearAccessDeliveryActionListener.java 130878 2013-10-25 22:48:06Z 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.listener.delivery;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.event.api.Event;
import org.sakaiproject.event.api.LearningResourceStoreService;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.event.cover.NotificationService;
import org.sakaiproject.tool.assessment.api.SamigoApiFactory;
import org.sakaiproject.tool.assessment.data.dao.assessment.EventLogData;
import org.sakaiproject.tool.assessment.data.dao.grading.AssessmentGradingData;
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.GradingService;
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.delivery.DeliveryBean;
import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil;
import org.sakaiproject.tool.assessment.ui.web.session.SessionUtil;
public class LinearAccessDeliveryActionListener extends DeliveryActionListener
implements ActionListener
{
private static Log log = LogFactory.getLog(LinearAccessDeliveryActionListener.class);
private static ResourceBundle eventLogMessages = ResourceBundle.getBundle("org.sakaiproject.tool.assessment.bundle.EventLogMessages");
/**
* ACTION.
* @param ae
* @throws AbortProcessingException
*/
public void processAction(ActionEvent ae) throws
AbortProcessingException
{
log.debug("LinearAccessDeliveryActionListener.processAction() ");
// get managed bean
DeliveryBean delivery = (DeliveryBean) ContextUtil.lookupBean("delivery");
// set publishedId, note that id can be changed by isPreviewingMode()
String id = getPublishedAssessmentId(delivery);
String agent = getAgentString();
// Clear elapsed time, set not timed out
clearElapsedTime(delivery);
// get assessment from deliveryBean if id matches. otherwise, this is the 1st time
// that DeliveryActionListener is called, so pull it from DB
PublishedAssessmentFacade publishedAssessment = getPublishedAssessment(delivery, id);
// set show student score
setShowStudentScore(delivery, publishedAssessment);
setShowStudentQuestionScore(delivery, publishedAssessment);
setDeliverySettings(delivery, publishedAssessment);
if (ae != null && ae.getComponent().getId().startsWith("beginAssessment")) {
// #1. check password
if (!delivery.getSettings().getUsername().equals(""))
{
if ("passwordAccessError".equals(delivery.validatePassword())) {
return;
}
}
// #2. check IP
if (delivery.getSettings().getIpAddresses() != null && !delivery.getSettings().getIpAddresses().isEmpty())
{
if ("ipAccessError".equals(delivery.validateIP())) {
return;
}
}
// #3. secure delivery START phase
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_START, publishedAssessment, request );
if ( PhaseStatus.FAILURE == status ) {
return;
}
}
}
}
// itemGradingHash will end up with
// (Long publishedItemId, ArrayList itemGradingDatas) and
// (String "sequence"+itemId, Integer sequence) and
// (String "items", Long itemscount)
GradingService service = new GradingService();
PublishedAssessmentService pubService = new PublishedAssessmentService();
AssessmentGradingData ag = null;
// this returns a HashMap with (publishedItemId, itemGrading)
HashMap itemGradingHash = service.getLastItemGradingData(id, agent);
boolean isFirstTimeBegin = false;
if (itemGradingHash!=null && itemGradingHash.size()>0){
log.debug("itemGradingHash!=null && itemGradingHash.size()>0");
ag = setAssessmentGradingFromItemData(delivery, itemGradingHash, true);
setAttemptDateIfNull(ag);
}
else{
ag = service.getLastSavedAssessmentGradingByAgentId(id, agent);
if (ag == null) {
ag = createAssessmentGrading(publishedAssessment);
isFirstTimeBegin = true;
}
else {
setAttemptDateIfNull(ag);
}
}
delivery.setAssessmentGrading(ag);
log.debug("itemgrading size = " + ag.getItemGradingSet().size());
delivery.setAssessmentGradingId(delivery.getAssessmentGrading().getAssessmentGradingId());
//ag can't be null beyond this point and must have persisted to DB
// version 2.1.1 requirement
setFeedbackMode(delivery);
if (ae != null && ae.getComponent().getId().startsWith("beginAssessment")) {
setTimer(delivery, publishedAssessment, true, isFirstTimeBegin);
setStatus(delivery, pubService, Long.valueOf(id));
// If it comes from Begin Assessment button clicks, reset isNoQuestion to false
// because we want to always display the first page
// Otherwise, if isNoQuestion set to true in the last delivery and
// if the first part has no question, it will not be rendered
// See getPageContentsByQuestion() for more details
// Of course it is better to do this inside getPageContentsByQuestion()
// However, ae is not passed in getPageContentsByQuestion()
// and there are multiple places to modify if I want to get ae inside getPageContentsByQuestion()
delivery.setNoQuestions(false);
// ONC event log
EventLogService eventService = new EventLogService();
EventLogFacade eventLogFacade = new EventLogFacade();
String agentEid = AgentFacade.getEid();
//set event log data
EventLogData eventLogData = new EventLogData();
eventLogData.setAssessmentId(Long.valueOf(id));
eventLogData.setProcessId(delivery.getAssessmentGradingId());
eventLogData.setStartDate(new Date());
eventLogData.setTitle(publishedAssessment.getTitle());
eventLogData.setUserEid(agentEid);
String site_id= AgentFacade.getCurrentSiteId();
if(site_id == null) {
//take assessment via url
PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
site_id = publishedAssessmentService.getPublishedAssessmentOwner(Long.valueOf(delivery.getAssessmentId()));
}
eventLogData.setSiteId(site_id);
eventLogData.setErrorMsg(eventLogMessages.getString("no_submission"));
eventLogData.setEndDate(null);
eventLogData.setEclipseTime(null);
eventLogFacade.setData(eventLogData);
eventService.saveOrUpdateEventLog(eventLogFacade);
int action = delivery.getActionMode();
if (action == DeliveryBean.TAKE_ASSESSMENT) {
StringBuffer eventRef = new StringBuffer("publishedAssessmentId");
eventRef.append(delivery.getAssessmentId());
eventRef.append(", agentId=");
eventRef.append(getAgentString());
if (delivery.isTimeRunning()) {
eventRef.append(", elapsed=");
eventRef.append(delivery.getTimeElapse());
eventRef.append(", remaining=");
int timeRemaining = Integer.parseInt(delivery.getTimeLimit()) - Integer.parseInt(delivery.getTimeElapse());
eventRef.append(timeRemaining);
}
Event event = EventTrackingService.newEvent("sam.assessment.take", eventRef.toString(), true);
EventTrackingService.post(event);
registerIrss(delivery, event, false);
}
else if (action == DeliveryBean.TAKE_ASSESSMENT_VIA_URL) {
StringBuffer eventRef = new StringBuffer("publishedAssessmentId");
eventRef.append(delivery.getAssessmentId());
eventRef.append(", agentId=");
eventRef.append(getAgentString());
if (delivery.isTimeRunning()) {
eventRef.append(", elapsed=");
eventRef.append(delivery.getTimeElapse());
eventRef.append(", remaining=");
int timeRemaining = Integer.parseInt(delivery.getTimeLimit()) - Integer.parseInt(delivery.getTimeElapse());
eventRef.append(timeRemaining);
}
PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
String siteId = publishedAssessmentService.getPublishedAssessmentOwner(Long.valueOf(delivery.getAssessmentId()));
Event event = EventTrackingService.newEvent("sam.assessment.take", eventRef.toString(), siteId, true, NotificationService.NOTI_REQUIRED);
EventTrackingService.post(event);
registerIrss(delivery, event, true);
}
}
else {
setTimer(delivery, publishedAssessment, false, false);
}
// extend session time out
SessionUtil.setSessionTimeout(FacesContext.getCurrentInstance(), delivery, true);
log.debug("Set begin time " + delivery.getBeginTime());
log.debug("Set elapsed time " + delivery.getTimeElapse());
// overload itemGradingHash with the sequence in case renumbering is turned off.
overloadItemData(delivery, itemGradingHash, publishedAssessment);
// get the position of last question which has ben answered/viewed by the student
log.debug("before partIndex = " + delivery.getPartIndex());
log.debug("before questionIndex = " + delivery.getQuestionIndex());
setPosition(delivery);
log.debug("after partIndex = " + delivery.getPartIndex());
log.debug("after questionIndex = " + delivery.getQuestionIndex());
HashMap publishedAnswerHash = pubService.preparePublishedAnswerHash(publishedAssessment);
// get current page contents
delivery.setPageContents(getPageContents(publishedAssessment, delivery, itemGradingHash, publishedAnswerHash));
}
private void setPosition(DeliveryBean delivery) {
GradingService gradingService = new GradingService();
AssessmentGradingData assessmentGradingData = delivery.getAssessmentGrading();
log.debug("assessmentGradingData.getAssessmentGradingId() = " + assessmentGradingData.getAssessmentGradingId());
if (assessmentGradingData.getLastVisitedPart() != null && assessmentGradingData.getLastVisitedQuestion() != null) {
delivery.setPartIndex(assessmentGradingData.getLastVisitedPart().intValue());
delivery.setQuestionIndex(assessmentGradingData.getLastVisitedQuestion().intValue());
}
else {
// For backward compatible
ArrayList alist = gradingService.getLastItemGradingDataPosition(assessmentGradingData.getAssessmentGradingId(), assessmentGradingData.getAgentId());
int partIndex = ((Integer)alist.get(0)).intValue();
if (partIndex == 0) {
delivery.setPartIndex(0);
}
else {
delivery.setPartIndex(partIndex - 1);
}
delivery.setQuestionIndex(((Integer)alist.get(1)).intValue());
}
}
public void saveLastVisitedPosition(DeliveryBean delivery, int partNumber, int questionNumber) {
GradingService gradingService = new GradingService();
AssessmentGradingData assessmentGradingData = delivery.getAssessmentGrading();
assessmentGradingData.setStatus(2);
assessmentGradingData.setLastVisitedPart(partNumber);
assessmentGradingData.setLastVisitedQuestion(questionNumber);
gradingService.saveOrUpdateAssessmentGradingOnly(assessmentGradingData);
}
}