/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-qti/src/java/org/sakaiproject/tool/assessment/qti/helper/assessment/AssessmentHelperBase.java $
* $Id: AssessmentHelperBase.java 106463 2012-04-02 12:20:09Z david.horwitz@uct.ac.za $
***********************************************************************************
*
* Copyright (c) 2003, 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.qti.helper.assessment;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.tool.assessment.data.dao.assessment.AttachmentData;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentAccessControlIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentFeedbackIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.EvaluationModelIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.SecuredIPAddressIfc;
import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
import org.sakaiproject.tool.assessment.qti.asi.Assessment;
import org.sakaiproject.tool.assessment.qti.asi.Section;
import org.sakaiproject.tool.assessment.qti.helper.AuthoringHelper;
import org.sakaiproject.tool.assessment.qti.util.Iso8601DateFormat;
import org.sakaiproject.tool.assessment.qti.util.Iso8601TimeInterval;
import org.sakaiproject.tool.assessment.qti.util.XmlUtil;
import org.xml.sax.SAXException;
/**
* <p>Copyright: Copyright (c) 2005/p>
* <p>Organization: Sakai Project</p>
* @author Ed Smiley esmiley@stanford.edu
* @author based on some code by: Shastri, Rashmi <rshastri@iupui.edu>
* @version $Id: AssessmentHelperBase.java 106463 2012-04-02 12:20:09Z david.horwitz@uct.ac.za $
*/
public abstract class AssessmentHelperBase
implements AssessmentHelperIfc
{
private static Log log = LogFactory.getLog(AssessmentHelperBase.class);
abstract protected int getQtiVersion();
/**
* Read in assessment XML from input stream
*
* @param inputStream XML input stream
*
* @return assessment XML
*/
public Assessment readXMLDocument(
InputStream inputStream)
{
if (log.isDebugEnabled())
{
log.debug("readDocument(InputStream " + inputStream);
}
Assessment assessXml = null;
try
{
AuthoringHelper authoringHelper = new AuthoringHelper(getQtiVersion());
assessXml =
new Assessment(
authoringHelper.readXMLDocument(inputStream).getDocument());
}
catch (ParserConfigurationException e)
{
log.error(e.getMessage(), e);
}
catch (SAXException e)
{
log.error(e.getMessage(), e);
}
catch (IOException e)
{
log.error(e.getMessage(), e);
}
return assessXml;
}
/**
* Set feedback settings in XML
* @param assessmentXml
* @param feedback
*/
public void updateFeedbackModel(Assessment assessmentXml,
AssessmentFeedbackIfc feedback)
{
Integer feedbackDelivery = feedback.getFeedbackDelivery();
if (feedback.FEEDBACK_BY_DATE.equals(feedbackDelivery))
{
assessmentXml.setFieldentry("FEEDBACK_DELIVERY", "DATED");
}
else if (feedback.IMMEDIATE_FEEDBACK.equals(feedbackDelivery))
{
assessmentXml.setFieldentry("FEEDBACK_DELIVERY", "IMMEDIATE");
}
else if (feedback.FEEDBACK_ON_SUBMISSION.equals(feedbackDelivery))
{
assessmentXml.setFieldentry("FEEDBACK_DELIVERY", "ON_SUBMISSION");
}
else //feedback.NO_FEEDBACK
{
assessmentXml.setFieldentry("FEEDBACK_DELIVERY", "NONE");
}
Integer feedbackComponentOption = feedback.getFeedbackComponentOption();
if (feedback.SELECT_COMPONENTS.equals(feedbackComponentOption))
{
assessmentXml.setFieldentry("FEEDBACK_COMPONENT_OPTION", "SELECT_COMPONENTS");
}
else
{
assessmentXml.setFieldentry("FEEDBACK_COMPONENT_OPTION", "SHOW_TOTALSCORE_ONLY");
}
Integer feedbackAuthoring = feedback.getFeedbackAuthoring();
if (feedback.QUESTIONLEVEL_FEEDBACK.equals(feedbackAuthoring))
{
assessmentXml.setFieldentry("FEEDBACK_AUTHORING", "QUESTION");
}
else if (feedback.SECTIONLEVEL_FEEDBACK.equals(feedbackAuthoring))
{
assessmentXml.setFieldentry("FEEDBACK_AUTHORING", "SECTION");
}
else //feedback.BOTH_FEEDBACK
{
assessmentXml.setFieldentry("FEEDBACK_AUTHORING", "BOTH");
}
assessmentXml.setFieldentry("FEEDBACK_SHOW_QUESTION",
qtiBooleanString(feedback.getShowQuestionText()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_RESPONSE",
qtiBooleanString(feedback.
getShowStudentResponse()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_CORRECT_RESPONSE",
qtiBooleanString(feedback.
getShowCorrectResponse()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_STUDENT_SCORE",
qtiBooleanString(feedback.getShowStudentScore()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_STUDENT_QUESTIONSCORE",
qtiBooleanString(feedback.getShowStudentQuestionScore()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_ITEM_LEVEL",
qtiBooleanString(feedback.
getShowQuestionLevelFeedback()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_SELECTION_LEVEL",
qtiBooleanString(feedback.
getShowSelectionLevelFeedback()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_GRADER_COMMENT",
qtiBooleanString(feedback.getShowGraderComments()));
assessmentXml.setFieldentry("FEEDBACK_SHOW_STATS",
qtiBooleanString(feedback.getShowStatistics()));
}
/**
* Set evaluation settings in XML.
* @param assessmentXml
* @param evaluationModel
*/
public void updateEvaluationModel(Assessment assessmentXml,
EvaluationModelIfc evaluationModel)
{
// debugging
log.debug("EvaluationModelIfc.ANONYMOUS_GRADING: " +
EvaluationModelIfc.ANONYMOUS_GRADING);
log.debug("evaluationModel.getAnonymousGrading(): " +
evaluationModel.getAnonymousGrading());
log.debug("EvaluationModelIfc.TO_SELECTED_GRADEBOOK.toString(): " +
EvaluationModelIfc.TO_SELECTED_GRADEBOOK.toString());
log.debug("evaluationModel.getToGradeBook(): " +
evaluationModel.getToGradeBook());
log.debug("EvaluationModelIfc.HIGHEST_SCORE: " +
EvaluationModelIfc.HIGHEST_SCORE);
log.debug("evaluationModel.getScoringType(): " +
evaluationModel.getScoringType());
// anonymous grading
if (EvaluationModelIfc.ANONYMOUS_GRADING.equals(evaluationModel.
getAnonymousGrading()))
{
assessmentXml.setFieldentry("ANONYMOUS_GRADING", "True");
}
else
{
assessmentXml.setFieldentry("ANONYMOUS_GRADING", "False");
}
// graadebook options
if (EvaluationModelIfc.TO_SELECTED_GRADEBOOK.toString().
equals(evaluationModel.getToGradeBook()))
{
assessmentXml.setFieldentry("GRADEBOOK_OPTIONS", "SELECTED");
}
else if (EvaluationModelIfc.TO_DEFAULT_GRADEBOOK.toString().
equals(evaluationModel.getToGradeBook()))
{
assessmentXml.setFieldentry("GRADEBOOK_OPTIONS", "DEFAULT");
}
//SAK-7162
if (EvaluationModelIfc.NOT_TO_GRADEBOOK.toString().
equals(evaluationModel.getToGradeBook()))
{
assessmentXml.setFieldentry("GRADEBOOK_OPTIONS", "NONE");
}
//highest or last
if (EvaluationModelIfc.HIGHEST_SCORE.equals(evaluationModel.getScoringType()))
{
assessmentXml.setFieldentry("GRADE_SCORE", "HIGHEST_SCORE");
}
// not implementing average for now
else if (EvaluationModelIfc.AVERAGE_SCORE.equals(evaluationModel.
getScoringType()))
{
assessmentXml.setFieldentry("GRADE_SCORE", "AVERAGE_SCORE");
}
else if (EvaluationModelIfc.LAST_SCORE.equals(evaluationModel.
getScoringType()))
{
assessmentXml.setFieldentry("GRADE_SCORE", "LAST_SCORE");
}
}
/**
* Set the assessment description.
* @param description assessment description
* @param assessmentXml the xml
*/
public void setDescriptiveText(String description, Assessment assessmentXml)
{
String xpath =
"questestinterop/assessment/presentation_material/flow_mat/material/mattext";
List list = assessmentXml.selectNodes(xpath);
try
{
// If nothing is entered into description field,
// description will be "" from mysql but it will be null from oracle
// we need to set it to "" if it is null (SAK-5950)
if (description == null) {
log.debug("description is null");
description = "";
}
description = XmlUtil.convertStrforCDATA(description);
assessmentXml.update(xpath, description);
}
catch (Exception ex)
{
log.error(ex.getMessage(), ex);
}
}
/**
* Set access control settings in XML.
* @param assessmentXml
* @param accessControl
*/
public void updateAccessControl(Assessment assessmentXml,
AssessmentAccessControlIfc accessControl)
{
// DATES
Date dueDate = accessControl.getDueDate();
Date startDate = accessControl.getStartDate();
Date scoreDate = accessControl.getScoreDate();
Date restractDate = accessControl.getRetractDate();
Date feedbackDate = accessControl.getFeedbackDate();
assessmentXml.setFieldentry("END_DATE", formatDate(dueDate));
assessmentXml.setFieldentry("FEEDBACK_DELIVERY_DATE",
formatDate(feedbackDate));
assessmentXml.setFieldentry("RETRACT_DATE", formatDate(restractDate));
assessmentXml.setFieldentry("START_DATE", formatDate(startDate));
//MAX_ATTEMPTS
Integer submissionsAllowed = accessControl.getSubmissionsAllowed();
// set if unlimited
Boolean unlimitedSubmissions = accessControl.getUnlimitedSubmissions();
boolean unlimited = false;
if (unlimitedSubmissions != null)
{
unlimited = unlimitedSubmissions.booleanValue();
}
if (unlimited)
{
submissionsAllowed = accessControl.UNLIMITED_SUBMISSIONS_ALLOWED;
}
assessmentXml.setFieldentry("MAX_ATTEMPTS",
submissionsAllowed.toString());
// OTHER CONTROLS
Integer autoSubmit = accessControl.getAutoSubmit();
Integer bookmarking = accessControl.getBookMarkingItem();
Integer itemNavigation = accessControl.getItemNavigation();
Integer itemNumbering = accessControl.getItemNumbering();
Integer assessmentFormat = accessControl.getAssessmentFormat();
Integer markForReview = accessControl.getMarkForReview();
Integer lateHandling = accessControl.getLateHandling();
Integer retryAllowed = accessControl.getRetryAllowed();
Integer submissionsSaved = accessControl.getSubmissionsSaved();
Integer timeLimit = accessControl.getTimeLimit();
String submissionMessage = accessControl.getSubmissionMessage();
String finalPageUrl = accessControl.getFinalPageUrl();
String password = accessControl.getPassword();
String releaseTo = accessControl.getReleaseTo();
String userName = accessControl.getUsername();
assessmentXml.setFieldentry("AUTO_SUBMIT", qtiBooleanString(autoSubmit));
// getTimedAssessment() does not always tell us
if (timeLimit != null && timeLimit.intValue() != 0)
{
setDuration(timeLimit, assessmentXml);
}
// submissions
if (submissionMessage != null)
{
String wrappedSubmissionMessage = XmlUtil.convertStrforCDATA(submissionMessage);
assessmentXml.setFieldentry("SUBMISSION_MESSAGE", wrappedSubmissionMessage, true);
}
if (finalPageUrl != null)
{
assessmentXml.setFieldentry("FINISH_URL", finalPageUrl);
}
if (accessControl.BY_QUESTION.equals(assessmentFormat))
{
assessmentXml.setFieldentry("QUESTION_LAYOUT", "I");
}
else if (accessControl.BY_PART.equals(assessmentFormat))
{
assessmentXml.setFieldentry("QUESTION_LAYOUT", "S");
}
else if (accessControl.BY_ASSESSMENT.equals(assessmentFormat))
{
assessmentXml.setFieldentry("QUESTION_LAYOUT", "A");
}
if (accessControl.LINEAR_ACCESS.equals(itemNavigation))
{
assessmentXml.setFieldentry("NAVIGATION", "LINEAR");
}
else if (accessControl.RANDOM_ACCESS.equals(itemNavigation))
{
assessmentXml.setFieldentry("NAVIGATION", "RANDOM");
}
if (accessControl.CONTINUOUS_NUMBERING.equals(itemNumbering))
{
assessmentXml.setFieldentry("QUESTION_NUMBERING", "CONTINUOUS");
}
else if (accessControl.RESTART_NUMBERING_BY_PART.equals(itemNumbering))
{
assessmentXml.setFieldentry("QUESTION_NUMBERING", "RESTART");
}
if (accessControl.MARK_FOR_REVIEW.equals(markForReview))
{
assessmentXml.setFieldentry("MARK_FOR_REVIEW", "True");
}
else if (accessControl.NOT_MARK_FOR_REVIEW.equals(markForReview))
{
assessmentXml.setFieldentry("MARK_FOR_REVIEW", "False");
}
if (accessControl.ACCEPT_LATE_SUBMISSION.equals(lateHandling))
{
assessmentXml.setFieldentry("LATE_HANDLING", "True");
}
else if (accessControl.NOT_ACCEPT_LATE_SUBMISSION.equals(lateHandling))
{
assessmentXml.setFieldentry("LATE_HANDLING", "False");
}
if (password != null)
{
assessmentXml.setFieldentry("PASSWORD", password);
}
if (releaseTo != null)
{
assessmentXml.setFieldentry("ASSESSMENT_RELEASED_TO", releaseTo);
}
if (userName != null)
{
assessmentXml.setFieldentry("USERID", userName);
}
}
/**
* If there is IP address set put IP addresses into allowed IP field in XML.
* @param assessmentXml the XML
* @param securedIPAddressSet the Set
*/
public void updateIPAddressSet(Assessment assessmentXml,
Set securedIPAddressSet)
{
if (securedIPAddressSet==null || securedIPAddressSet.size()==0)
{
return;
}
Iterator iter = securedIPAddressSet.iterator();
StringBuilder ipAddressesbuf = new StringBuilder();
while (iter.hasNext())
{
SecuredIPAddressIfc sip = (SecuredIPAddressIfc) iter.next();
String ipAddress = sip.getIpAddress();
//ipAddresses += ipAddress + "\n";
ipAddressesbuf.append(ipAddress + "\n");
}
String ipAddresses = ipAddressesbuf.toString();
assessmentXml.setFieldentry("ALLOW_IP", ipAddresses);
}
/**
* If there are attachments set put them into ATTACHMENT field in XML.
* @param assessmentXml the XML
* @param securedIPAddressSet the Set
*/
public void updateAttachmentSet(Assessment assessmentXml, Set attachmentSet)
{
Iterator iter = attachmentSet.iterator();
AttachmentData attachmentData = null;
StringBuffer attachment = new StringBuffer();
while (iter.hasNext())
{
attachmentData = (AttachmentData) iter.next();
attachment.append(attachmentData.getResourceId().replaceAll(" ", ""));
attachment.append("|");
attachment.append(attachmentData.getFilename());
attachment.append("|");
attachment.append(attachmentData.getMimeType());
attachment.append("\n");
}
assessmentXml.setFieldentry("ATTACHMENT", attachment.toString());
}
/**
* Look up and set metadata fields
* @param assessmentXml
* @param assessment
*/
public void updateMetaData(Assessment assessmentXml,
AssessmentFacade assessment)
{
String[] editKeys =
{
"templateInfo_isInstructorEditable",
"assessmentAuthor_isInstructorEditable",
"assessmentCreator_isInstructorEditable",
"description_isInstructorEditable",
"dueDate_isInstructorEditable",
"retractDate_isInstructorEditable",
"anonymousRelease_isInstructorEditable",
"authenticatedRelease_isInstructorEditable",
"ipAccessType_isInstructorEditable",
"passwordRequired_isInstructorEditable",
"lockedBrowser_isInstructorEditable",
"timedAssessment_isInstructorEditable",
"timedAssessmentAutoSubmit_isInstructorEditable",
"itemAccessType_isInstructorEditable",
"displayChunking_isInstructorEditable",
"displayNumbering_isInstructorEditable",
"submissionModel_isInstructorEditable",
"lateHandling_isInstructorEditable",
"markForReview_isInstructorEditable",
"automaticSubmission_isInstructorEditable",
"autoSave_isInstructorEditable",
"submissionMessage_isInstructorEditable",
"finalPageURL_isInstructorEditable",
"feedbackType_isInstructorEditable",
"feedbackAuthoring_isInstructorEditable",
"feedbackComponents_isInstructorEditable",
"testeeIdentity_isInstructorEditable",
"toGradebook_isInstructorEditable",
"recordedScore_isInstructorEditable",
"bgColor_isInstructorEditable",
"bgImage_isInstructorEditable",
"metadataAssess_isInstructorEditable",
"metadataParts_isInstructorEditable",
"metadataQuestions_isInstructorEditable",
};
String key;
String value;
for (int i = 0; i < editKeys.length; i++)
{
setField(assessmentXml, assessment, editKeys[i]);
}
// item metadata
setField(assessmentXml, assessment, "hasMetaDataForQuestions",
"COLLECT_ITEM_METADATA");
}
/**
*
* @param assessmentXml
* @param assessment
* @param translationKey
* @param key
*/
private void setField(Assessment assessmentXml, AssessmentFacade assessment,
String key, String translationKey)
{
String value = assessment.getAssessmentMetaDataByLabel(key);
log.debug("setField(Assessment assessmentXml, AssessmentFacade assessment, String key, String translationKey)");
log.debug("key: " + key);
log.debug("value: " + value);
if (value == null)
{
assessmentXml.setFieldentry(translationKey, "false");
return;
}
assessmentXml.setFieldentry(translationKey, value);
}
/**
*
* @param assessmentXml
* @param assessment
* @param key
*/
private void setField(Assessment assessmentXml, AssessmentFacade assessment,
String key)
{
setField(assessmentXml, assessment, key, key);
}
/**
* format Iso8601 Date
* @param date Date object
* @return Iso8601 date string or "" if not set
*/
private String formatDate(Date date)
{
if (date == null)
{
return "";
}
Iso8601DateFormat iso = new Iso8601DateFormat();
return iso.format(date);
}
/**
* Map Boolean to text string
* @param b Boolean
* @return "True"|"False"
*/
public String qtiBooleanString(Boolean b)
{
if (b != null && b.booleanValue())
{
return "True";
}
return "False";
}
/**
* Map Integer to text string
* @param i Integer
* @return "True"|"False"
*/
public String qtiBooleanString(Integer i)
{
if (i != null && i.intValue() != 0)
{
return "True";
}
return "False";
}
/**
* get section XML by title
*
* @param assessment section XML
* @param sectionTitle title
*
* @return section XML
*/
public Section getSectionByTitle(
Assessment assessment, String sectionTitle)
{
if (log.isDebugEnabled())
{
log.debug(
"getSectionByTitle( )");
}
Section sectionXml = null;
Collection secs = assessment.getSections();
if (secs == null) {
return sectionXml;
}
Iterator iter = secs.iterator();
if ( (secs != null) && (secs.size() > 0) && (sectionTitle != null))
{
for (int i = 0; i < secs.size(); i++)
{
while (iter.hasNext())
{
sectionXml = (Section) iter.next();
String title =
sectionXml.selectSingleValue("section/@title", "attribute");
if ( (title != null) && title.equals(sectionTitle))
{
break;
}
}
}
}
return sectionXml;
}
/** Set the assessment duration.
* @param duration assessment duration in seconds
* @param assessmentXml the xml
*/
public void setDuration(Integer duration, Assessment assessmentXml)
{
String xpath = "questestinterop/assessment/duration";
List list = assessmentXml.selectNodes(xpath);
try
{
Iso8601TimeInterval isoTime =
new Iso8601TimeInterval(1000 * duration.longValue());
assessmentXml.update(xpath, isoTime.toString());
}
catch (Exception ex)
{
log.error(ex.getMessage(), ex);
}
}
}