/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/author/ItemAddListener.java $
* $Id: ItemAddListener.java 122050 2013-04-02 13:32:36Z ottenhoff@longsight.com $
***********************************************************************************
*
* 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.author;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.tool.assessment.data.dao.assessment.Answer;
import org.sakaiproject.tool.assessment.data.dao.assessment.AnswerFeedback;
import org.sakaiproject.tool.assessment.data.dao.assessment.ItemMetaData;
import org.sakaiproject.tool.assessment.data.dao.assessment.ItemText;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedAnswer;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedAnswerFeedback;
import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedItemText;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AnswerFeedbackIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AnswerIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemAttachmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemFeedbackIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemMetaDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemTextIfc;
import org.sakaiproject.tool.assessment.services.FinFormatException;
import org.sakaiproject.tool.assessment.data.ifc.assessment.SectionDataIfc;
import org.sakaiproject.tool.assessment.facade.AgentFacade;
import org.sakaiproject.tool.assessment.facade.ItemFacade;
import org.sakaiproject.tool.assessment.facade.PublishedItemFacade;
import org.sakaiproject.tool.assessment.facade.SectionFacade;
import org.sakaiproject.tool.assessment.facade.TypeFacade;
import org.sakaiproject.tool.assessment.services.ItemService;
import org.sakaiproject.tool.assessment.services.PublishedItemService;
import org.sakaiproject.tool.assessment.services.QuestionPoolService;
import org.sakaiproject.tool.assessment.services.assessment.AssessmentService;
import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService;
import org.sakaiproject.tool.assessment.ui.bean.author.AnswerBean;
import org.sakaiproject.tool.assessment.ui.bean.author.AssessmentBean;
import org.sakaiproject.tool.assessment.ui.bean.author.AuthorBean;
import org.sakaiproject.tool.assessment.ui.bean.author.CalculatedQuestionAnswerIfc;
import org.sakaiproject.tool.assessment.ui.bean.author.CalculatedQuestionFormulaBean;
import org.sakaiproject.tool.assessment.ui.bean.author.CalculatedQuestionVariableBean;
import org.sakaiproject.tool.assessment.ui.bean.author.ItemAuthorBean;
import org.sakaiproject.tool.assessment.ui.bean.author.ItemBean;
import org.sakaiproject.tool.assessment.ui.bean.author.MatchItemBean;
import org.sakaiproject.tool.assessment.ui.bean.author.CalculatedQuestionBean;
import org.sakaiproject.tool.assessment.ui.bean.questionpool.QuestionPoolBean;
import org.sakaiproject.tool.assessment.ui.bean.questionpool.QuestionPoolDataBean;
import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil;
import org.sakaiproject.tool.assessment.util.TextFormat;
import org.sakaiproject.util.FormattedText;
import org.sakaiproject.tool.assessment.data.dao.assessment.FavoriteColChoices;
import org.sakaiproject.tool.assessment.data.dao.assessment.FavoriteColChoicesItem;
/**
* <p>Title: Samigo</p>
* <p>Description: Sakai Assessment Manager</p>
* <p>Organization: Sakai Project</p>
*/
public class ItemAddListener
implements ActionListener {
private static Log log = LogFactory.getLog(ItemAddListener.class);
//private static ContextUtil cu;
//private String scalename; // used for multiple choice Survey
private boolean error = false;
private boolean isPendingOrPool = false;
private boolean isEditPendingAssessmentFlow = true;
/**
* Standard process action method.
* @param ae ActionEvent
* @throws AbortProcessingException
*/
public void processAction(ActionEvent ae) throws AbortProcessingException {
//boolean correct=false;
log.debug("ItemAdd LISTENER.");
ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor");
ItemBean item = itemauthorbean.getCurrentItem();
String iText = ContextUtil.stringWYSIWYG(item.getItemText());
String iInstruction = ContextUtil.stringWYSIWYG(item.getInstruction());
String iType = item.getItemType();
String err="";
FacesContext context=FacesContext.getCurrentInstance();
// SAK-6050
// if((!iType.equals(TypeFacade.MATCHING.toString())&&((iText==null)||(iText.replaceAll("<.*?>", "").trim().equals(""))))|| (iType.equals(TypeFacade.MATCHING.toString()) && ((iInstruction==null)||(iInstruction.replaceAll("<.*?>", "").trim().equals(""))))){
if( (!iType.equals(TypeFacade.MATCHING.toString())&&((iText==null) ||(iText.toLowerCase().replaceAll("<^[^(img)]*?>", "").trim().equals(""))))|| (iType.equals(TypeFacade.MATCHING.toString()) && ((iInstruction==null)||(iInstruction.toLowerCase().replaceAll("<^[^(img)]*?>", "").trim().equals(""))))){
// Like Matching CaculatedQuestion will also use Instruction instead of itemText
if (!iType.equals(TypeFacade.CALCULATED_QUESTION.toString())) {
String emptyText_err = ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","emptyText_error");
context.addMessage(null,new FacesMessage(emptyText_err));
return;
}
}
if(iType.equals(TypeFacade.MULTIPLE_CHOICE.toString()))
checkMC(true);
if(iType.equals(TypeFacade.MULTIPLE_CORRECT.toString()))
checkMC(false);
if(iType.equals(TypeFacade.MULTIPLE_CORRECT_SINGLE_SELECTION.toString()))
checkMC(false);
if(iType.equals(TypeFacade.MATCHING.toString()))
{
ArrayList l=item.getMatchItemBeanList();
if (l==null || l.size()==0){
String noPairMatching_err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","noMatchingPair_error");
context.addMessage(null,new FacesMessage(noPairMatching_err));
error=true;
}
}
if(error)
return;
if(iType.equals(TypeFacade.MULTIPLE_CHOICE_SURVEY.toString()))
{
String scaleName = item.getScaleName();
if (scaleName == null){
err = ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","corrAnswer");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("surveyItem");
item.setPoolOutcome("surveyItem");
return;
}
}
if(iType.equals(TypeFacade.TRUE_FALSE.toString()))
{
String corrAnswer = item.getCorrAnswer();
if (corrAnswer == null){
err = ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","corrAnswer");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("trueFalseItem");
item.setPoolOutcome("trueFalseItem");
return;
}
}
if(iType.equals(TypeFacade.FILL_IN_BLANK.toString())){
if(isErrorFIB()){
err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","pool_missingBracket_error");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("fillInBlackItem");
item.setPoolOutcome("fillInBlackItem");
return;
}
}
if(iType.equals(TypeFacade.FILL_IN_NUMERIC.toString())){
if(isErrorFIN()){
err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","pool_missingBracket_error");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("fillInNumericItem");
item.setPoolOutcome("fillInNumericItem");
return;
}
}
if(iType.equals(TypeFacade.AUDIO_RECORDING.toString())){
try {
String timeAllowed = item.getTimeAllowed().trim();
int intTimeAllowed = Integer.parseInt(timeAllowed);
if (intTimeAllowed < 1) {
throw new RuntimeException();
}
}
catch (RuntimeException e){
err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","submissions_allowed_error");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("audioRecItem");
item.setPoolOutcome("audioRecItem");
return;
}
}
if (iType.equals(TypeFacade.MATRIX_CHOICES_SURVEY.toString())){
if (isRowEmpty()){
err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","row_field_empty");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("matrixChoicesSurveyItem");
item.setPoolOutcome("matrixChoicesSurveyItem");
return;
}
if (isColumnslessthan2()) {
err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","less_than_two_columns");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("matrixChoicesSurveyItem");
item.setPoolOutcome("matrixChoicesSurveyItem");
return;
}
}
// CALCULATED_QUESTION
if (iType.equals(TypeFacade.CALCULATED_QUESTION.toString())) {
// make sure any last minute updates to instructions are handles
// this also does the standard validations
CalculatedQuestionExtractListener extractListener = new CalculatedQuestionExtractListener();
List<String> errors = extractListener.validate(item);
if (errors.size() > 0) {
for (String curError : errors) {
context.addMessage(null, new FacesMessage(curError));
}
error = true;
}
if(error) {
item.setOutcome("calculatedQuestion");
item.setPoolOutcome("calculatedQuestion");
return;
}
// if no errors remove disabled variables and formulas before saving
CalculatedQuestionBean question = item.getCalculatedQuestion();
Iterator<CalculatedQuestionVariableBean> variableIter = question.getVariables().values().iterator();
while (variableIter.hasNext()) {
CalculatedQuestionVariableBean variable = variableIter.next();
if (!variable.getActive()) {
variableIter.remove();
}
}
Iterator<CalculatedQuestionFormulaBean> formulaIter = question.getFormulas().values().iterator();
while (formulaIter.hasNext()) {
CalculatedQuestionFormulaBean formula = formulaIter.next();
if (!formula.getActive()) {
formulaIter.remove();
}
}
}
try {
saveItem(itemauthorbean);
}
catch (FinFormatException e) {
err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","fin_invalid_characters_error");
context.addMessage(null,new FacesMessage(err));
item.setOutcome("fillInNumericItem");
item.setPoolOutcome("fillInNumericItem");
return;
}
item.setOutcome("editAssessment");
item.setPoolOutcome("editPool");
itemauthorbean.setItemTypeString("");
}
public void checkMC(boolean isSingleSelect){
ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor");
ItemBean item =itemauthorbean.getCurrentItem();
boolean correct=false;
int countAnswerText=0;
//String[] choiceLabels= {"A", "B", "C", "D", "E", "F","G", "H","I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
int indexLabel= 0;
// List label = new List();
Iterator iter = item.getMultipleChoiceAnswers().iterator();
boolean missingchoices=false;
StringBuilder missingLabelbuf = new StringBuilder();
//String missingLabel="";
String txt="";
String label="";
FacesContext context=FacesContext.getCurrentInstance();
int corrsize = item.getMultipleChoiceAnswers().size();
String[] corrChoices = new String[corrsize];
int counter=0;
boolean isCorrectChoice = false;
if(item.getMultipleChoiceAnswers()!=null){
while (iter.hasNext()) {
AnswerBean answerbean = (AnswerBean) iter.next();
String answerTxt=ContextUtil.stringWYSIWYG(answerbean.getText());
// if(answerTxt.replaceAll("<.*?>", "").trim().equals(""))
// SAK-6050
if(answerTxt.toLowerCase().replaceAll("<^[^(img)]*?>", "").trim().equals("")) {
answerbean.setText("");
}
label = answerbean.getLabel();
txt=answerbean.getText();
corrChoices[counter]=label;
isCorrectChoice = isCorrectChoice(item,label);
if(isCorrectChoice && ((txt==null) ||(txt.equals("")))){
error=true;
String empty_correct_err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","empty_correct_error");
context.addMessage(null,new FacesMessage(empty_correct_err+label));
}
if ((txt!=null)&& (!txt.equals(""))) {
countAnswerText++;
if(isCorrectChoice){
correct=true;
counter++;
}
if(!label.equals(AnswerBean.getChoiceLabels()[indexLabel])){
missingchoices= true;
if( "".equals(missingLabelbuf.toString()))
missingLabelbuf.append(" "+AnswerBean.getChoiceLabels()[indexLabel]);
else
missingLabelbuf.append(", "+AnswerBean.getChoiceLabels()[indexLabel]);
indexLabel++;
}
indexLabel++;
}
} // end of while
String missingLabel = missingLabelbuf.toString();
// Fixed for 7208
// Following the above logic, at this point, no matter the last choice (lable is corrChoices[counter])
// is a correct answer or not, it will be the last value in array corrChoice[].
// Therefore, make a call to isCorrectChoice() to see if it is indeed a correct choice
if (counter < corrChoices.length && !isCorrectChoice(item, corrChoices[counter])) {
corrChoices[counter] = null;
}
item.setCorrAnswers(corrChoices);
if(!error){
if(correct==false){
if(isSingleSelect){
String singleCorrect_error=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","singleCorrect_error");
context.addMessage(null,new FacesMessage(singleCorrect_error));
}
else{
String multiCorrect_error=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","multiCorrect_error");
context.addMessage(null,new FacesMessage(multiCorrect_error));
}
error=true;
} else if(countAnswerText<=1){
String answerList_err=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","answerList_error");
context.addMessage(null,new FacesMessage(answerList_err));
error=true;
}
else if(missingchoices){
String selectionError=ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages","missingChoices_error");
context.addMessage(null,new FacesMessage(selectionError+missingLabel));
error=true;
}
}
}
if(error){
item.setOutcome("multipleChoiceItem");
item.setPoolOutcome("multipleChoiceItem");
}
}
public boolean isErrorFIB() {
ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor");
ItemBean item =itemauthorbean.getCurrentItem();
int index=0;
boolean FIBerror=false;
// String err="";
boolean hasOpen=false;
int opencount=0;
int closecount=0;
boolean notEmpty=false;
int indexOfOpen=-1;
String text=item.getItemText();
while(index<text.length()){
char c=text.charAt(index);
if(c=='{'){
opencount++;
if(hasOpen){
FIBerror=true;
break;
}
else{
hasOpen=true;
indexOfOpen=index;
}
}
else if(c=='}'){
closecount++;
if(!hasOpen){
FIBerror=true;
break;
}
else{
if((notEmpty==true)&&(indexOfOpen+1 !=index)&&(!(text.substring(indexOfOpen+1,index).equals("</p><p>")))){
hasOpen=false;
notEmpty=false;
}
else{
//error for emptyString
FIBerror=true;
break;
}
}
}
else{
if((hasOpen==true)&&(!Character.isWhitespace(c))){
notEmpty=true;
}
}
index++;
}//end while
if((hasOpen==true)||(opencount<1)||(opencount!=closecount)||(FIBerror==true)){
return true;
}
else{
return false;
}
}
public boolean isErrorFIN() {
ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor");
ItemBean item =itemauthorbean.getCurrentItem();
int index=0;
boolean FINerror=false;
//String err="";
boolean hasOpen=false;
int opencount=0;
int closecount=0;
boolean notEmpty=false;
int indexOfOpen=-1;
String text=item.getItemText();
while(index<text.length()){
char c=text.charAt(index);
if(c=='{'){
opencount++;
if(hasOpen){
FINerror=true;
break;
}
else{
hasOpen=true;
indexOfOpen=index;
}
}
else if(c=='}'){
closecount++;
if(!hasOpen){
FINerror=true;
break;
}
else{
if((notEmpty==true)&&(indexOfOpen+1 !=index)&&(!(text.substring(indexOfOpen+1,index).equals("</p><p>")))){
hasOpen=false;
notEmpty=false;
}
else{
//error for emptyString
FINerror=true;
break;
}
}
}
else{
if((hasOpen==true)&&(!Character.isWhitespace(c))){
notEmpty=true;
}
}
index++;
}//end while
if((hasOpen==true)||(opencount<1)||(opencount!=closecount)||(FINerror==true)){
return true;
}
else{
return false;
}
}
public boolean isRowEmpty() {
ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor");
ItemBean item =itemauthorbean.getCurrentItem();
String text=item.getRowChoices();
if (text != null && text.trim().length() == 0)
return true;
else if (text == null)
return true;
return false;
}
public boolean isColumnslessthan2(){
ItemAuthorBean itemauthorbean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor");
ItemBean item =itemauthorbean.getCurrentItem();
String text=item.getColumnChoices();
String[] columns;
columns = text.split(System.getProperty("line.separator"));
if(columns.length < 2)
return true;
return false;
}
public void saveItem(ItemAuthorBean itemauthor) throws FinFormatException{
boolean update = false;
ItemBean bean = itemauthor.getCurrentItem();
ItemFacade item;
AuthorBean author = (AuthorBean) ContextUtil.lookupBean("author");
isEditPendingAssessmentFlow = author.getIsEditPendingAssessmentFlow();
log.debug("**** isEditPendingAssessmentFlow : " + isEditPendingAssessmentFlow);
String target = itemauthor.getTarget();
boolean isFromQuestionPool = false;
if (target != null && (target.equals(ItemAuthorBean.FROM_QUESTIONPOOL) && ! author.getIsEditPoolFlow())) {
isFromQuestionPool = true;
}
log.debug("**** isFromQuestionPool : " + isFromQuestionPool);
isPendingOrPool = isEditPendingAssessmentFlow || (isFromQuestionPool && ! author.getIsEditPoolFlow());
ItemService delegate;
if (isPendingOrPool) {
EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.revise", "siteId=" + AgentFacade.getCurrentSiteId() + ", itemId=" + itemauthor.getItemId(), true));
delegate = new ItemService();
}
else {
EventTrackingService.post(EventTrackingService.newEvent("sam.pubassessment.revise", "siteId=" + AgentFacade.getCurrentSiteId() + ", itemId=" + itemauthor.getItemId(), true));
delegate = new PublishedItemService();
}
// update not working yet, delete, then add
if ( (bean.getItemId() != null) && (!bean.getItemId().equals("0"))) {
update = true;
// if modify ,itemid shouldn't be null , or 0.
Long oldId = Long.valueOf(bean.getItemId());
if (isPendingOrPool) {
delegate.deleteItemContent(oldId, AgentFacade.getAgentString());
}
item = delegate.getItem(oldId,AgentFacade.getAgentString());
}
else{
if (isPendingOrPool) {
item = new ItemFacade();
}
else {
item = new PublishedItemFacade();
}
}
item.setScore(Double.valueOf(bean.getItemScore()));
item.setDiscount(Double.valueOf(bean.getItemDiscount()));
item.setHint("");
item.setStatus(ItemDataIfc.ACTIVE_STATUS);
item.setTypeId(Long.valueOf(bean.getItemType()));
item.setCreatedBy(AgentFacade.getAgentString());
item.setCreatedDate(new Date());
item.setLastModifiedBy(AgentFacade.getAgentString());
item.setLastModifiedDate(new Date());
if (bean.getInstruction() != null) {
// for matching and matrix Survey
item.setInstruction(bean.getInstruction());
}
// update hasRationale
if (bean.getRationale() != null) {
item.setHasRationale(Boolean.valueOf(bean.getRationale()));
}
else {
item.setHasRationale(Boolean.FALSE);
}
item.setPartialCreditFlag(Boolean.valueOf(bean.getPartialCreditFlag()));
// update maxNumAttempts for audio
if (bean.getNumAttempts() != null) {
item.setTriesAllowed(Integer.valueOf(bean.getNumAttempts()));
}
// save timeallowed for audio recording
if (bean.getTimeAllowed() != null) {
item.setDuration(Integer.valueOf(bean.getTimeAllowed()));
}
if (update && !isPendingOrPool) {
//prepare itemText, including answers
item.setItemTextSet(preparePublishedText(item, bean, delegate));
// prepare MetaData
item.setItemMetaDataSet(preparePublishedMetaData(item, bean));
// prepare feedback, because this is UPDATE
// if it's an empty string, we need to update feedback to an empty string
// not like below (below we don't ADD if the feedback is null or empty string)
if ((bean.getCorrFeedback() != null)) {
updateItemFeedback(item, ItemFeedbackIfc.CORRECT_FEEDBACK, stripPtags(bean.getCorrFeedback()));
}
if ((bean.getIncorrFeedback() != null)) {
updateItemFeedback(item, ItemFeedbackIfc.INCORRECT_FEEDBACK, stripPtags(bean.getIncorrFeedback()));
}
if ((bean.getGeneralFeedback() != null)) {
updateItemFeedback(item, ItemFeedbackIfc.GENERAL_FEEDBACK, stripPtags(bean.getGeneralFeedback()));
}
}
else {
//prepare itemText, including answers
if (item.getTypeId().equals(TypeFacade.MATCHING)) {
item.setItemTextSet(prepareTextForMatching(item, bean, itemauthor));
} else if(item.getTypeId().equals(TypeFacade.CALCULATED_QUESTION)) {
item.setItemTextSet(prepareTextForCalculatedQuestion(item, bean, itemauthor));
}
else if(item.getTypeId().equals(TypeFacade.MATRIX_CHOICES_SURVEY)) {
item.setItemTextSet(prepareTextForMatrixChoice(item, bean, itemauthor));
}
else {
item.setItemTextSet(prepareText(item, bean, itemauthor));
}
// prepare MetaData
item.setItemMetaDataSet(prepareMetaData(item, bean));
// prepare feedback, only store if feedbacks are not empty
if ( (bean.getCorrFeedback() != null) &&
(!bean.getCorrFeedback().equals(""))) {
item.setCorrectItemFeedback(stripPtags(bean.getCorrFeedback()));
}
if ( (bean.getIncorrFeedback() != null) &&
(!bean.getIncorrFeedback().equals(""))) {
item.setInCorrectItemFeedback(stripPtags(bean.getIncorrFeedback()));
}
if ( (bean.getGeneralFeedback() != null) &&
(!bean.getGeneralFeedback().equals(""))) {
item.setGeneralItemFeedback(stripPtags(bean.getGeneralFeedback()));
}
}
if (isFromQuestionPool) {
// Came from Pool manager
delegate.saveItem(item);
// added by daisyf, 10/10/06
updateAttachment(item.getItemAttachmentList(), itemauthor.getAttachmentList(),
(ItemDataIfc)item.getData(), true);
item = delegate.getItem(item.getItemId().toString());
QuestionPoolService qpdelegate = new QuestionPoolService();
if (!qpdelegate.hasItem(item.getItemIdString(),
Long.valueOf(itemauthor.getQpoolId()))) {
qpdelegate.addItemToPool(item.getItemIdString(),
Long.valueOf(itemauthor.getQpoolId()));
}
QuestionPoolBean qpoolbean = (QuestionPoolBean) ContextUtil.lookupBean("questionpool");
QuestionPoolDataBean contextCurrentPool = qpoolbean.getCurrentPool();
qpoolbean.buildTree();
/*
// Reset question pool bean
QuestionPoolFacade thepool= qpdelegate.getPool(new Long(itemauthor.getQpoolId()), AgentFacade.getAgentString());
qpoolbean.getCurrentPool().setNumberOfQuestions(thepool.getQuestionSize().toString());
*/
qpoolbean.startEditPoolAgain(itemauthor.getQpoolId());
QuestionPoolDataBean currentPool = qpoolbean.getCurrentPool();
currentPool.setDisplayName(contextCurrentPool.getDisplayName());
currentPool.setOrganizationName(contextCurrentPool.getOrganizationName());
currentPool.setDescription(contextCurrentPool.getDescription());
currentPool.setObjectives(contextCurrentPool.getObjectives());
currentPool.setKeywords(contextCurrentPool.getKeywords());
ArrayList addedQuestions = qpoolbean.getAddedQuestions();
if (addedQuestions == null) {
addedQuestions = new ArrayList();
}
addedQuestions.add(item.getItemId());
qpoolbean.setAddedPools(addedQuestions);
// return to edit pool
itemauthor.setOutcome("editPool");
}
// Came from Questionbank Authoring
else if (itemauthor.getTarget() != null && (itemauthor.getTarget().equals("sambank"))) {
delegate.saveItem(item);
itemauthor.setItemNo(item.getItemId().toString());
}
else {
// Came from Assessment Authoring
AssessmentService assessdelegate;
if (isEditPendingAssessmentFlow) {
assessdelegate = new AssessmentService();
}
else {
assessdelegate = new PublishedAssessmentService();
}
// add the item to the specified part, otherwise add to default
if (bean.getSelectedSection() != null) {
// need to do add a temp part first if assigned to a temp part SAK-2109
SectionFacade section;
if ("-1".equals(bean.getSelectedSection())) {
AssessmentBean assessmentBean = (AssessmentBean) ContextUtil.lookupBean("assessmentBean");
// add a new section
section = assessdelegate.addSection(assessmentBean.getAssessmentId());
}
else {
section = assessdelegate.getSection(bean.getSelectedSection());
}
item.setSection(section);
if (update) {
// if Modify, need to reorder if assgned to different section '
if ( (bean.getOrigSection() != null) &&
(!bean.getOrigSection().equals(bean.getSelectedSection()))) {
// if reassigned to different section
Integer oldSeq = item.getSequence();
item.setSequence( Integer.valueOf(section.getItemSet().size() + 1));
// reorder the sequences of items in the OrigSection
SectionFacade origsect= assessdelegate.getSection(bean.getOrigSection());
shiftItemsInOrigSection(delegate, origsect, oldSeq);
}
else {
// no action needed
}
}
if (!update) {
if ( (itemauthor.getInsertPosition() == null) ||
("".equals(itemauthor.getInsertPosition()))
|| !section.getSequence().toString().equals(itemauthor.getInsertToSection())) {
// if adding to the end
if (section.getItemSet() != null) {
item.setSequence(Integer.valueOf(section.getItemSet().size() + 1));
}
else {
// this is a new part, not saved yet
item.setSequence(Integer.valueOf(1));
}
}
else {
// if inserting or a question
String insertPos = itemauthor.getInsertPosition();
shiftSequences(delegate, section, Integer.valueOf(insertPos));
int insertPosInt = (Integer.valueOf(insertPos)).intValue() + 1;
item.setSequence(Integer.valueOf(insertPosInt));
// reset InsertPosition
itemauthor.setInsertPosition("");
}
}
if (itemauthor.getInsertToSection() != null) {
// reset insertToSection to null;
itemauthor.setInsertToSection(null);
}
if (author != null && author.getIsEditPoolFlow()) {
section.getData().setLastModifiedDate(item.getLastModifiedDate());
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
section.addSectionMetaData(SectionDataIfc.QUESTIONS_RANDOM_DRAW_DATE, df.format(item.getLastModifiedDate()));
assessdelegate.saveOrUpdateSection(section);
}
delegate.saveItem(item);
// added by daisyf, 10/10/06
updateAttachment(item.getItemAttachmentList(), itemauthor.getAttachmentList(),
(ItemDataIfc)item.getData(), isEditPendingAssessmentFlow);
item = delegate.getItem(item.getItemId().toString());
}
// prepare saving column choice to favorites (SAM_FAVORITECOLCHOICES_T and SAM_FAVORITECOLCHOICESITEM_T)
// and save
if (bean.getAddToFavorite()){
FavoriteColChoices favorite = new FavoriteColChoices();
favorite.setFavoriteName(bean.getFavoriteName().trim());
//find the agentId
favorite.setOwnerStringId(AgentFacade.getAgentString());
String[] temp = bean.getColumnChoices().split(System.getProperty("line.separator"));
//remove the empty string
List<String> stringList = new ArrayList<String>();
for(String string : temp) {
if(string != null && string.trim().length() > 0) {
stringList.add(string);
}
}
temp = stringList.toArray(new String[stringList.size()]);
for(int i=0; i<temp.length; i++){
FavoriteColChoicesItem favoriteChoiceItem = new FavoriteColChoicesItem(StringUtils.chomp(temp[i]),Integer.valueOf(i));
favoriteChoiceItem.setFavoriteChoice(favorite);
favorite.getFavoriteItems().add(favoriteChoiceItem);
}
delegate.saveFavoriteColumnChoices(favorite);
}
QuestionPoolService qpdelegate = new QuestionPoolService();
// removed the old pool-item mappings
if ( (bean.getOrigPool() != null) && (!bean.getOrigPool().equals(""))) {
qpdelegate.removeQuestionFromPool(item.getItemIdString(),
Long.valueOf(bean.getOrigPool()));
}
// if assign to pool, add the item to the pool
if ( (bean.getSelectedPool() != null) && !bean.getSelectedPool().equals("")) {
// if the item is already in the pool then do not add.
// This is a scenario where the item might already be in the pool:
// create an item in an assessemnt and assign it to p1
// copy item from p1 to p2.
// now the item is already in p2. and if you want to edit the original item in the assessment, and reassign it to p2, you will get a duplicate error.
if (!qpdelegate.hasItem(item.getItemIdString(),
Long.valueOf(bean.getSelectedPool()))) {
qpdelegate.addItemToPool(item.getItemIdString(),
Long.valueOf(bean.getSelectedPool()));
}
}
// #1a - goto editAssessment.jsp, so reset assessmentBean
AssessmentBean assessmentBean = (AssessmentBean) ContextUtil.lookupBean(
"assessmentBean");
AssessmentIfc assessment = assessdelegate.getAssessment(
Long.valueOf(assessmentBean.getAssessmentId()));
assessmentBean.setAssessment(assessment);
itemauthor.setOutcome("editAssessment");
}
// sorry, i need this for item attachment, used by SaveItemAttachmentListener.
itemauthor.setItemId(item.getItemId().toString());
}
/**
* for the current choice, loop through all answers and add unique matches to the list of valid matches for the choice.
* @param choicebean current choice
* @param matchItemBeanList
* @param item
* @param bean
* @return
*/
private ItemText selectAnswers(MatchItemBean choicebean, ArrayList<MatchItemBean> matchItemBeanList, ItemFacade item, ItemBean bean) {
// Create a list of valid answers to loop through. Ignore answers that are distractors
// or are controlled by another MatchItemBean
List<MatchItemBean> validAnswers = new ArrayList<MatchItemBean>();
Iterator<MatchItemBean>validAnswerIter = matchItemBeanList.iterator();
while (validAnswerIter.hasNext()) {
MatchItemBean validAnswer = validAnswerIter.next();
if (MatchItemBean.CONTROLLING_SEQUENCE_DEFAULT.equals(validAnswer.getControllingSequence())) {
validAnswers.add(validAnswer);
}
}
ItemText choicetext = new ItemText();
choicetext.setItem(item.getData()); // all set to the same
choicetext.setSequence(choicebean.getSequence());
choicetext.setText(stripPtags(choicebean.getChoice()));
// loop through matches for in validAnswers list and add all to this choice
Iterator<MatchItemBean>answeriter = validAnswers.iterator();
HashSet<Answer> answerSet = new HashSet<Answer>();
while (answeriter.hasNext()) {
Answer answer = null;
MatchItemBean answerbean = (MatchItemBean) answeriter.next();
if (answerbean.getSequence().equals(choicebean.getSequence()) ||
answerbean.getSequenceStr().equals(choicebean.getControllingSequence())) {
// correct answers
answer = new Answer(choicetext, stripPtags(answerbean
.getMatch()), answerbean.getSequence(), AnswerBean
.getChoiceLabels()[answerbean.getSequence()
.intValue() - 1], Boolean.TRUE, null, Double.valueOf(
bean.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
} else {
// incorrect answers
answer = new Answer(choicetext, stripPtags(answerbean
.getMatch()), answerbean.getSequence(), AnswerBean
.getChoiceLabels()[answerbean.getSequence()
.intValue() - 1], Boolean.FALSE, null, Double.valueOf(
bean.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
}
// record answers for all combination of pairs
HashSet<AnswerFeedback> answerFeedbackSet = new HashSet<AnswerFeedback>();
answerFeedbackSet.add(new AnswerFeedback(answer,
AnswerFeedbackIfc.CORRECT_FEEDBACK,
stripPtags(answerbean.getCorrMatchFeedback())));
answerFeedbackSet.add(new AnswerFeedback(answer,
AnswerFeedbackIfc.INCORRECT_FEEDBACK,
stripPtags(answerbean.getIncorrMatchFeedback())));
answer.setAnswerFeedbackSet(answerFeedbackSet);
answerSet.add(answer);
}
choicetext.setAnswerSet(answerSet);
return choicetext;
}
private HashSet prepareTextForMatching(ItemFacade item, ItemBean bean,
ItemAuthorBean itemauthor) {
ArrayList<MatchItemBean>matchItemBeanList = bean.getMatchItemBeanList();
HashSet<ItemText> textSet = new HashSet<ItemText>();
Iterator<MatchItemBean> choiceiter = matchItemBeanList.iterator();
while (choiceiter.hasNext()) {
MatchItemBean choicebean = choiceiter.next();
ItemText choicetext = selectAnswers(choicebean, matchItemBeanList, item, bean);
textSet.add(choicetext);
}
return textSet;
}
private String[] returnMatrixChoices(ItemBean bean,String str){
String[] result=null,temp=null;
if ("row".equals(str))
temp = bean.getRowChoices().split(System.getProperty("line.separator"));
else
temp = bean.getColumnChoices().split(System.getProperty("line.separator"));
//remove the empty string
List<String> stringList = new ArrayList<String>();
for(String string : temp) {
if(string != null && string.trim().length() > 0) {
stringList.add(string);
}
}
temp = stringList.toArray(new String[stringList.size()]);
result = new String[temp.length];
for (int i=0; i<temp.length;i++){
//remove new line
result[i] = StringUtils.chomp(temp[i]);
}
return result;
}
private HashSet prepareTextForMatrixChoice(ItemFacade item, ItemBean bean,
ItemAuthorBean itemauthor) {
// looping through row and column choices
String[] rowChoices = returnMatrixChoices(bean,"row");
String[] columnChoices = returnMatrixChoices(bean,"column");
bean.setInstruction(bean.getItemText());
item.getData().setInstruction(bean.getItemText());
HashSet textSet = new HashSet();
for(int i = 0; i<rowChoices.length;i++)
{
ItemText itemText = new ItemText();
itemText.setItem(item.getData());
itemText.setSequence(Long.valueOf(i+1));
itemText.setText(rowChoices[i]);
HashSet answerSet = new HashSet();
Answer answer = null;
for(int j=0; j< columnChoices.length;j++){
answer = new Answer(itemText,columnChoices[j],Long.valueOf(j+1),null, null, null, Double.valueOf(bean.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
answerSet.add(answer);
}
itemText.setAnswerSet(answerSet);
textSet.add(itemText);
}
return textSet;
}
private HashSet prepareText(ItemFacade item, ItemBean bean,
ItemAuthorBean itemauthor) throws FinFormatException {
HashSet textSet = new HashSet();
HashSet answerSet1 = new HashSet();
// ///////////////////////////////////////////////////////////
// 1. save Question Text for items with single Question Text
// (except matching)
// ///////////////////////////////////////////////////////////
ItemText text1 = new ItemText();
text1.setItem(item.getData());
text1.setSequence(Long.valueOf(1));
text1.setText(bean.getItemText());
// ///////////////////////////////////////////////////////////
//
// 2. save Answers
//
// ///////////////////////////////////////////////////////////
if (item.getTypeId().equals(TypeFacade.TRUE_FALSE)) {
// find correct answer
Answer newanswer = null;
for (int i = 0; i < bean.getAnswers().length; i++) {
String theanswer = bean.getAnswers()[i];
// String thelabel = bean.getAnswerLabels()[i]; // store
// thelabel as the answer text
if (theanswer.equals(bean.getCorrAnswer())) {
// label is null because we don't use labels in true/false
// questions
// labels are like a, b, c, or i, ii, iii, in multiple
// choice type
newanswer = new Answer(text1, theanswer, Long.valueOf(i + 1),
"", Boolean.TRUE, null, Double.valueOf(bean
.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
} else {
newanswer = new Answer(text1, theanswer, Long.valueOf(i + 1),
"", Boolean.FALSE, null, Double.valueOf(bean
.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
}
answerSet1.add(newanswer);
}
text1.setAnswerSet(answerSet1);
textSet.add(text1);
} else if (item.getTypeId().equals(TypeFacade.ESSAY_QUESTION)) {
// Storing the model answer essay as an Answer, and feedback in the
// Answerfeedback
String theanswer = bean.getCorrAnswer();
if (theanswer == null) {
theanswer = ""; // can be empty
}
// label is null because we don't use labels in essay questions
// theanswer is the model answer used as a sample for student
Answer modelanswer = new Answer(text1, theanswer, Long.valueOf(1),
null, Boolean.TRUE, null, Double.valueOf(bean.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
HashSet answerFeedbackSet1 = new HashSet();
answerFeedbackSet1.add(new AnswerFeedback(modelanswer,
"modelanswer", stripPtags(bean.getCorrFeedback())));
modelanswer.setAnswerFeedbackSet(answerFeedbackSet1);
answerSet1.add(modelanswer);
text1.setAnswerSet(answerSet1);
textSet.add(text1);
}
else if (item.getTypeId().equals(TypeFacade.MULTIPLE_CHOICE_SURVEY)) {
String scalename = bean.getScaleName();
String[] choices = getSurveyChoices(scalename);
for (int i = 0; i < choices.length; i++) {
Answer answer1 = new Answer(text1, choices[i], Long.valueOf(i + 1),
null, null, null, Double.valueOf(bean.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
answerSet1.add(answer1);
}
text1.setAnswerSet(answerSet1);
textSet.add(text1);
}
// not doing parsing in authoring
else if (item.getTypeId().equals(TypeFacade.FILL_IN_BLANK)) {
// this is for fill in blank
String entiretext = bean.getItemText();
String processedText [] = processFIBFINText(entiretext);
text1.setText(processedText[0]);;
Object[] fibanswers = getFIBanswers(processedText[1]).toArray();
for (int i = 0; i < fibanswers.length; i++) {
String oneanswer = (String) fibanswers[i];
Answer answer1 = new Answer(text1, oneanswer, Long.valueOf(i + 1),
null, Boolean.TRUE, null,
Double.valueOf(bean.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
answerSet1.add(answer1);
}
text1.setAnswerSet(answerSet1);
textSet.add(text1);
}
else if (item.getTypeId().equals(TypeFacade.FILL_IN_NUMERIC)) {
// this is for fill in numeric
String entiretext = bean.getItemText();
String processedText [] = processFIBFINText(entiretext);
text1.setText(processedText[0]);;
Object[] finanswers = getFINanswers(processedText[1]).toArray();
for (int i = 0; i < finanswers.length; i++) {
String oneanswer = (String) finanswers[i];
Answer answer1 = new Answer(text1, oneanswer, Long.valueOf(i + 1),
null, Boolean.TRUE, null,
Double.valueOf(bean.getItemScore()), Double.valueOf(0d), Double.valueOf(bean.getItemDiscount()));
answerSet1.add(answer1);
}
text1.setAnswerSet(answerSet1);
textSet.add(text1);
}
else if ((item.getTypeId().equals(TypeFacade.MULTIPLE_CHOICE))
|| (item.getTypeId().equals(TypeFacade.MULTIPLE_CORRECT))
|| (item.getTypeId().equals(TypeFacade.MULTIPLE_CORRECT_SINGLE_SELECTION))) {
// this is for both single/multiple correct multiple choice types
// for single choice
// String theanswer=bean.getCorrAnswer();
Iterator iter = bean.getMultipleChoiceAnswers().iterator();
Answer answer = null;
while (iter.hasNext()) {
AnswerBean answerbean = (AnswerBean) iter.next();
if (isCorrectChoice(bean, answerbean.getLabel().trim())) {
answer = new Answer(text1,
stripPtags(answerbean.getText()), answerbean
.getSequence(), answerbean.getLabel(),
Boolean.TRUE, null, Double.valueOf(bean.getItemScore()), Double.valueOf(100d), Double.valueOf(bean.getItemDiscount()));
} else {
if (item.getTypeId().equals(TypeFacade.MULTIPLE_CHOICE) && item.getPartialCreditFlag()){
Double pc = Double.valueOf(answerbean.getPartialCredit()); //--mustansar
if (pc == null) {
pc = Double.valueOf(0d);
}
answer = new Answer(text1,
stripPtags(answerbean.getText()),
answerbean.getSequence(),
answerbean.getLabel(),
Boolean.FALSE, null, Double.valueOf(bean.getItemScore()) ,
pc,
Double.valueOf(bean.getItemDiscount()));}
else {
answer = new Answer(text1,
stripPtags(answerbean.getText()),
answerbean.getSequence(),
answerbean.getLabel(),
Boolean.FALSE, null, Double.valueOf(bean.getItemScore()) ,
Double.valueOf(0d), //No partial Credit since it is not enabled the column is not null
Double.valueOf(bean.getItemDiscount()));
}
}
HashSet answerFeedbackSet1 = new HashSet();
answerFeedbackSet1.add(new AnswerFeedback(answer,
AnswerFeedbackIfc.GENERAL_FEEDBACK,
stripPtags(answerbean.getFeedback())));
answer.setAnswerFeedbackSet(answerFeedbackSet1);
answerSet1.add(answer);
}
text1.setAnswerSet(answerSet1);
textSet.add(text1);
}
// for file Upload and audio recording
else {
// no answers need to be added
textSet.add(text1);
}
/////////////////////////////////////////////////////////////
//END
/////////////////////////////////////////////////////////////
return textSet;
}
/**
* prepareTextForCalculatedqQestion takes the formulas and variables that are
* stored in CalculatedQuestionFormulaBeans and CalculatedQuestionVariableBeans
* and translates them into ItemTextIfc and AnswerIfc objects. The only difference
* between the formula and the variable is what information is actually kept in
* the answer.text field. ItemText has the name of the formula or variable in ItemTextIfc.text
* AnswerIfc.text stores either a formula as (formula string)|(tolerance),(decimal places) or a
* variable as (min)|(max),(decimal places).
* <p>Unlike matching answers, answerfeedback is not kept here; only the feedback associated with the entire
* question is persisted.
* @param item
* @param bean
* @param itemauthor
* @return
*/
private Set<ItemText> prepareTextForCalculatedQuestion(ItemFacade item, ItemBean bean,
ItemAuthorBean itemauthor) {
CalculatedQuestionBean calcBean = bean.getCalculatedQuestion();
Set<ItemText> textSet = new HashSet<ItemText>();
double score = Double.valueOf(bean.getItemScore());
double partialCredit = 0d;
double discount = Double.valueOf(bean.getItemDiscount());
String grade = null;
// Variables and formulas are very similar, and both have entries in the
// sam_itemtext_t table. Because of the way the data is structured, every
// answer stored in sam_answer_t is a possible match to every ItemText
// stored in sam_itemtext_t. If there is one variable and one formula,
// there are 2 entries in sam_itemtext_t and 4 entries in sam_answer_t.
// 2 variables and 2 formulas has 4 entries in sam_itemtext_t and 16 entries
// in sam_answer_t. This is required for the current design (which makes
// more sense for other question types; we're just trying to work within
// that structure. We loop through each formula and variable to create
// an entry in sam_itemtext_t (ItemText choiceText). Then for each
// choicetext, we loop through all variables and formulas to create the
// answer objects.
List<CalculatedQuestionAnswerIfc> list = new ArrayList<CalculatedQuestionAnswerIfc>();
list.addAll(calcBean.getFormulas().values());
list.addAll(calcBean.getVariables().values());
// loop through all variables and formulas to create ItemText objects
for (CalculatedQuestionAnswerIfc varFormula : list) {
ItemText choiceText = new ItemText();
choiceText.setItem(item.getData());
choiceText.setText(varFormula.getName());
Long sequence = varFormula.getSequence();
choiceText.setSequence(sequence);
HashSet<Answer> answerSet = new HashSet<Answer>();
// loop through all variables and formulas to create all answers for the ItemText object
for (CalculatedQuestionAnswerIfc curVarFormula : list) {
String match = curVarFormula.getMatch();
Long curSequence = curVarFormula.getSequence();
boolean isCorrect = curSequence.equals(sequence);
String choiceLabel = curVarFormula.getName();
Answer answer = new Answer(choiceText, match, curSequence, choiceLabel,
isCorrect, grade, score, partialCredit, discount);
answerSet.add(answer);
}
choiceText.setAnswerSet(answerSet);
textSet.add(choiceText);
}
return textSet;
}
private Set preparePublishedText(ItemFacade item, ItemBean bean, ItemService delegate) throws FinFormatException{
if (item.getTypeId().equals(TypeFacade.TRUE_FALSE)) {
preparePublishedTextForTF(item, bean);
}
else if (item.getTypeId().equals(TypeFacade.ESSAY_QUESTION)) {
preparePublishedTextForEssay(item, bean);
}
else if (item.getTypeId().equals(TypeFacade.MULTIPLE_CHOICE_SURVEY)) {
preparePublishedTextForSurvey(item, bean, delegate);
}
else if (item.getTypeId().equals(TypeFacade.FILL_IN_BLANK)) {
preparePublishedTextForFIBFIN(item, bean, delegate, true);
}
else if (item.getTypeId().equals(TypeFacade.FILL_IN_NUMERIC)) {
preparePublishedTextForFIBFIN(item, bean, delegate, false);
}
else if ( (item.getTypeId().equals(TypeFacade.MULTIPLE_CHOICE)) ||
(item.getTypeId().equals(TypeFacade.MULTIPLE_CORRECT)) ||
(item.getTypeId().equals(TypeFacade.MULTIPLE_CORRECT_SINGLE_SELECTION))) {
preparePublishedTextForMC(item, bean, delegate);
}
else if (item.getTypeId().equals(TypeFacade.MATCHING)) {
preparePublishedTextForMatching(item, bean, delegate);
}
else if (item.getTypeId().equals(TypeFacade.CALCULATED_QUESTION)) {
preparePublishedTextForCalculatedQueston(item, bean, delegate);
}
else if(item.getTypeId().equals(TypeFacade.MATRIX_CHOICES_SURVEY)) {
preparePublishedTextForMatrixSurvey(item,bean,delegate);
}
// for file Upload and audio recording
else {
// no answers need to be added
preparePublishedTextForOthers(item, bean);
}
Set textSet = item.getItemTextSet();
return textSet;
}
private void preparePublishedTextForTF(ItemFacade item, ItemBean bean) {
Set answerSet = null;
AnswerIfc answer = null;
ItemTextIfc text = null;
Set textSet = item.getItemTextSet();
Iterator iter = textSet.iterator();
while (iter.hasNext()) {
text = (ItemTextIfc) iter.next();
text.setText(bean.getItemText());
answerSet = text.getAnswerSet();
Iterator answerIter = answerSet.iterator();
while (answerIter.hasNext()) {
answer = (AnswerIfc) answerIter.next();
answer.setScore(Double.valueOf(bean.getItemScore()));
answer.setDiscount(Double.valueOf(bean.getItemDiscount()));
if (answer.getText().equals(bean.getCorrAnswer())) {
answer.setIsCorrect(Boolean.TRUE);
}
else {
answer.setIsCorrect(Boolean.FALSE);
}
}
}
}
private void preparePublishedTextForEssay(ItemFacade item, ItemBean bean) {
Set answerSet = null;
AnswerIfc answer = null;
ItemTextIfc text = null;
Set textSet = item.getItemTextSet();
Iterator iter = textSet.iterator();
while (iter.hasNext()) {
text = (ItemTextIfc) iter.next();
text.setText(bean.getItemText());
answerSet = text.getAnswerSet();
Iterator answerIter = answerSet.iterator();
// Storing the model answer essay as an Answer, and feedback in the Answerfeedback
while (answerIter.hasNext()) {
answer = (AnswerIfc) answerIter.next();
answer.setScore(Double.valueOf(bean.getItemScore()));
String theanswer = bean.getCorrAnswer();
if (theanswer == null) {
theanswer = ""; // can be empty
}
answer.setText(theanswer);
Set answerFeedbackSet = answer.getAnswerFeedbackSet();
Iterator answerFeedbackIter = answerFeedbackSet.iterator();
while (answerFeedbackIter.hasNext()) {
AnswerFeedbackIfc answerFeedback = (AnswerFeedbackIfc) answerFeedbackIter.next();
answerFeedback.setText(stripPtags(bean.getCorrFeedback()));
}
}
}
}
private void preparePublishedTextForSurvey(ItemFacade item, ItemBean bean, ItemService delegate) {
String scalename = bean.getScaleName();
String[] choices = getSurveyChoices(scalename);
Set answerSet = new HashSet();
Set textSet = item.getItemTextSet();
ItemTextIfc text = null;
Iterator iter = textSet.iterator();
while (iter.hasNext()) {
text = (ItemTextIfc) iter.next();
text.setText(bean.getItemText());
answerSet = text.getAnswerSet();
// For survey type, we erase all the existing ones. Because there is no benefit do update and then add/delete like FIB, FIN, or MC
delegate.deleteSet(answerSet);
for (int i = 0; i < choices.length; i++) {
AnswerIfc answer = new PublishedAnswer(text, choices[i], Long.valueOf(i + 1),
null, null, null, Double.valueOf(bean.getItemScore()), null, Double.valueOf(bean.getItemDiscount()));
answerSet.add(answer);
}
text.setAnswerSet(answerSet);
textSet.add(text);
}
}
private void preparePublishedTextForFIBFIN(ItemFacade item, ItemBean bean, ItemService delegate, boolean isFIB) throws FinFormatException{
Set answerSet = null;
Set textSet = item.getItemTextSet();
ItemTextIfc text = null;
String entiretext = bean.getItemText();
String processedText [] = processFIBFINText(entiretext);
String updatedText = processedText[0];
log.debug(" new text without answer is = " + updatedText);
Iterator iter = textSet.iterator();
while (iter.hasNext()) {
text = (ItemTextIfc) iter.next();
text.setText(updatedText);
Object[] answers;
if (isFIB) {
answers = getFIBanswers(entiretext).toArray();
}
else {
answers = getFINanswers(entiretext).toArray();
}
int newAnswersSize = answers.length;
int i = 0;
HashSet toBeRemovedSet = new HashSet();
answerSet = text.getAnswerSet();
Iterator answerIter = answerSet.iterator();
while (answerIter.hasNext()) {
AnswerIfc answer = (AnswerIfc) answerIter.next();
answer.setScore(Double.valueOf(bean.getItemScore()));
i = answer.getSequence().intValue();
if (i <= newAnswersSize) {
String oneanswer = (String) answers[i - 1];
answer.setText(oneanswer);
} else {
toBeRemovedSet.add(answer);
}
}
if (answerSet.size() < newAnswersSize) {
for (int j = answerSet.size(); j < newAnswersSize; j++) {
String oneanswer = (String) answers[j];
AnswerIfc answer = new PublishedAnswer(text, oneanswer,
Long.valueOf(j + 1), null, Boolean.TRUE, null,
Double.valueOf(bean.getItemScore()), null, Double.valueOf(bean.getItemDiscount()));
answerSet.add(answer);
}
}
answerSet.removeAll(toBeRemovedSet);
delegate.deleteSet(toBeRemovedSet);
}
}
private void preparePublishedTextForMC(ItemFacade item, ItemBean bean, ItemService delegate) {
Set answerSet = null;
Set textSet = item.getItemTextSet();
ItemTextIfc text = null;
Iterator iter = textSet.iterator();
while (iter.hasNext()) {
text = (ItemTextIfc) iter.next();
text.setText(bean.getItemText());
ArrayList newAnswerList = bean.getMultipleChoiceAnswers();
HashMap newAnswerMap = new HashMap();
Iterator newAnswerIter = newAnswerList.iterator();
while (newAnswerIter.hasNext()) {
AnswerBean answerBean = (AnswerBean) newAnswerIter.next();
newAnswerMap.put(answerBean.getSequence(), answerBean);
}
int newAnswersSize = newAnswerList.size();
int i = 0;
HashSet toBeRemovedSet = new HashSet();
AnswerBean answerBean = null;
answerSet = text.getAnswerSet();
Iterator answerIter = answerSet.iterator();
while (answerIter.hasNext()) {
AnswerIfc answer = (AnswerIfc) answerIter.next();
answer.setDiscount(Double.valueOf(bean.getItemDiscount()));
i = answer.getSequence().intValue();
if (i <= newAnswersSize) {
answer.setScore(Double.valueOf(bean.getItemScore()));
answerBean = (AnswerBean) newAnswerMap.get(Long.valueOf(String.valueOf(i)));
String oneAnswer = stripPtags(answerBean.getText());
answer.setPartialCredit(Double.valueOf(answerBean.getPartialCredit()));
String oneLabel = answerBean.getLabel();
log.debug("oneAnswer = " + oneAnswer);
log.debug("oneLabel = " + oneLabel);
answer.setText(oneAnswer);
answer.setLabel(oneLabel);
if (isCorrectChoice(bean, oneLabel.trim())) {
answer.setIsCorrect(Boolean.TRUE);
}
else {
answer.setIsCorrect(Boolean.FALSE);
}
Set answerFeedbackSet = answer.getAnswerFeedbackSet();
Iterator answerFeedbackIter = answerFeedbackSet.iterator();
while (answerFeedbackIter.hasNext()) {
AnswerFeedbackIfc answerFeedback = (AnswerFeedbackIfc) answerFeedbackIter.next();
answerFeedback.setText(stripPtags(answerBean.getFeedback()));
}
} else {
toBeRemovedSet.add(answer);
}
}
if (answerSet.size() < newAnswersSize) {
for (int j = answerSet.size() + 1; j < newAnswersSize + 1; j++) {
answerBean = (AnswerBean) newAnswerMap.get(Long.valueOf(String.valueOf(j)));
String oneAnswer = stripPtags(answerBean.getText());
String oneLabel = answerBean.getLabel();
AnswerIfc answer = null;
if (isCorrectChoice(bean, answerBean.getLabel().trim())) {
answer = new PublishedAnswer(text, oneAnswer,
Long.valueOf(j), oneLabel, Boolean.TRUE, null,
Double.valueOf(bean.getItemScore()), Double.valueOf(100d), Double.valueOf(bean.getItemDiscount()));
}
else {
answer = new PublishedAnswer(text, oneAnswer,
Long.valueOf(j), oneLabel, Boolean.FALSE, null,
Double.valueOf(bean.getItemScore()), Double.valueOf(answerBean.getPartialCredit()), Double.valueOf(bean.getItemDiscount()));
}
HashSet answerFeedbackSet = new HashSet();
answerFeedbackSet.add(new PublishedAnswerFeedback(answer,
AnswerFeedbackIfc.GENERAL_FEEDBACK,
stripPtags(answerBean.getFeedback())));
answer.setAnswerFeedbackSet(answerFeedbackSet);
answerSet.add(answer);
}
}
answerSet.removeAll(toBeRemovedSet);
delegate.deleteSet(toBeRemovedSet);
}
}
private void preparePublishedTextForCalculatedQueston(ItemFacade item, ItemBean bean, ItemService delegate) {
Set<ItemTextIfc> itemTextSet = item.getItemTextSet();
CalculatedQuestionBean calcBean = bean.getCalculatedQuestion();
double score = Double.valueOf(bean.getItemScore());
double partialCredit = 0d;
double discount = Double.valueOf(bean.getItemDiscount());
String grade = null;
// Variables and formulas are very similar, and both have entries in the
// sam_itemtext_t table. Because of the way the data is structured, every
// answer stored in sam_answer_t is a possible match to every ItemText
// stored in sam_itemtext_t. If there is one variable and one formula,
// there are 2 entries in sam_itemtext_t and 4 entries in sam_answer_t.
// 2 variables and 2 formulas has 4 entries in sam_itemtext_t and 16 entries
// in sam_answer_t. This is required for the current design (which makes
// more sense for other question types; we're just trying to work within
// that structure. We loop through each formula and variable to create
// an entry in sam_itemtext_t (ItemText choiceText). Then for each
// choicetext, we loop through all variables and formulas to create the
// answer objects.
List<CalculatedQuestionAnswerIfc> list = new ArrayList<CalculatedQuestionAnswerIfc>();
list.addAll(calcBean.getFormulas().values());
list.addAll(calcBean.getVariables().values());
// loop through all variables and formulas to create ItemText objects
for (CalculatedQuestionAnswerIfc varFormula : list) {
ItemTextIfc choiceText = null;
for (ItemTextIfc itemText : itemTextSet) {
if (itemText.getSequence().equals(varFormula.getSequence())) {
choiceText = itemText;
}
}
if (choiceText == null) {
choiceText = new PublishedItemText();
choiceText.setItem(item.getData());
choiceText.setSequence(varFormula.getSequence());
itemTextSet.add(choiceText);
}
choiceText.setText(varFormula.getName());
Long sequence = choiceText.getSequence();
Set<AnswerIfc> answerSet = choiceText.getAnswerSet();
if (answerSet == null) {
answerSet = new HashSet<AnswerIfc>();
choiceText.setAnswerSet(answerSet);
}
// loop through all variables and formulas to create all answers for the ItemText object
for (CalculatedQuestionAnswerIfc curVarFormula : list) {
String match = curVarFormula.getMatch();
Long curSequence = curVarFormula.getSequence();
boolean isCorrect = curSequence.equals(sequence);
String choiceLabel = AnswerBean.getChoiceLabels()[curSequence.intValue()];
boolean foundAnswer = false;
for (AnswerIfc curAnswer : answerSet) {
if (curAnswer.getSequence().equals(sequence)) {
curAnswer.setText(varFormula.getMatch());
foundAnswer = true;
break;
}
}
if (!foundAnswer) {
AnswerIfc answer = new PublishedAnswer(choiceText, match, curSequence, choiceLabel,
isCorrect, grade, score, partialCredit, discount);
answerSet.add(answer);
}
}
}
// If we're saving fewer variables/formulas than are currently in the
// itemtext/answer list, we need to delete the extra ones.
// ASSUMPTION - that sequences in sam_itemtext_t and sam_answer_t have no gaps. If
// there are 3 entries in sam_itemtext_t, they are numbered 1, 2, and 3
// (not 1, 2, 4 for example). This assumption should be verified
if (list.size() < itemTextSet.size()) {
Set<ItemTextIfc> toBeRemovedTextSet = new HashSet<ItemTextIfc>();
Set<AnswerIfc> toBeRemovedAnswerSet = new HashSet<AnswerIfc>();
for (ItemTextIfc curItemText : itemTextSet) {
Set<AnswerIfc> answerSet = curItemText.getAnswerSet();
for (AnswerIfc curAnswer : answerSet) {
if (curAnswer.getSequence() > list.size()) {
toBeRemovedAnswerSet.add(curAnswer);
}
}
answerSet.removeAll(toBeRemovedAnswerSet);
delegate.deleteSet(toBeRemovedAnswerSet);
if (curItemText.getSequence() > list.size()) {
toBeRemovedTextSet.add(curItemText);
}
}
itemTextSet.removeAll(toBeRemovedTextSet);
delegate.deleteSet(toBeRemovedTextSet);
}
}
private void preparePublishedTextForMatching(ItemFacade item,
ItemBean bean, ItemService delegate) {
Set textSet = item.getItemTextSet();
Iterator textIter = textSet.iterator();
HashMap itemTextMap = new HashMap();
while (textIter.hasNext()) {
ItemTextIfc itemText = (ItemTextIfc) textIter.next();
itemTextMap.put(itemText.getSequence(), itemText);
}
// looping through matchItemBean
ArrayList matchItemBeanList = bean.getMatchItemBeanList();
Iterator choiceIter = matchItemBeanList.iterator();
Set answerSet = null;
ItemTextIfc itemText = null;
AnswerIfc answer = null;
MatchItemBean choiceBean = null;
MatchItemBean matchBean = null;
Long choiceSequence = null;
Long matchSequence = null;
while (choiceIter.hasNext()) {
choiceBean = (MatchItemBean) choiceIter.next();
choiceSequence = choiceBean.getSequence();
if (itemTextMap.get(choiceSequence) == null) {
// new - add it in
itemText = new PublishedItemText();
itemText.setItem(item.getData());
itemText.setSequence(choiceBean.getSequence());
itemText.setText(stripPtags(choiceBean.getChoice()));
} else {
itemText = (ItemTextIfc) itemTextMap.get(choiceSequence);
itemText.setText(choiceBean.getChoice());
}
HashMap answerMap = new HashMap();
answerSet = itemText.getAnswerSet();
if (answerSet != null) {
Iterator answerIter = answerSet.iterator();
while (answerIter.hasNext()) {
answer = (AnswerIfc) answerIter.next();
answerMap.put(answer.getSequence(), answer);
}
}
else {
answerSet = new HashSet();
itemText.setAnswerSet(answerSet);
textSet.add(itemText);
}
Iterator matchIter = matchItemBeanList.iterator();
while (matchIter.hasNext()) {
matchBean = (MatchItemBean) matchIter.next();
matchSequence = matchBean.getSequence();
if (answerMap.get(matchSequence) == null) {
// new - add it in
if (matchBean.getSequence()
.equals(choiceBean.getSequence())) {
answer = new PublishedAnswer(itemText,
stripPtags(matchBean.getMatch()), matchBean
.getSequence(), AnswerBean
.getChoiceLabels()[matchBean
.getSequence().intValue() - 1],
Boolean.TRUE, null, new Double(bean.getItemScore()), null, Double.valueOf(bean.getItemDiscount()));
} else {
answer = new PublishedAnswer(itemText,
stripPtags(matchBean.getMatch()), matchBean
.getSequence(), AnswerBean
.getChoiceLabels()[matchBean
.getSequence().intValue() - 1],
Boolean.FALSE, null, new Double(bean.getItemScore()), null, Double.valueOf(bean.getItemDiscount()));
}
// record answers for all combination of pairs
HashSet answerFeedbackSet = new HashSet();
answerFeedbackSet.add(new PublishedAnswerFeedback(answer,
AnswerFeedbackIfc.CORRECT_FEEDBACK,
stripPtags(matchBean.getCorrMatchFeedback())));
answerFeedbackSet.add(new PublishedAnswerFeedback(answer,
AnswerFeedbackIfc.INCORRECT_FEEDBACK,
stripPtags(matchBean.getIncorrMatchFeedback())));
answer.setAnswerFeedbackSet(answerFeedbackSet);
answerSet.add(answer);
} else {
answer = (AnswerIfc) answerMap.get(matchSequence);
answer.setScore(Double.valueOf(bean.getItemScore()));
String oneAnswer = stripPtags(matchBean.getMatch());
String oneLabel = AnswerBean.getChoiceLabels()[matchSequence
.intValue() - 1];
log.debug("oneAnswer = " + oneAnswer);
log.debug("oneLabel = " + oneLabel);
answer.setText(oneAnswer);
answer.setLabel(oneLabel);
if (choiceSequence.longValue() == matchSequence.longValue()) {
answer.setIsCorrect(Boolean.TRUE);
} else {
answer.setIsCorrect(Boolean.FALSE);
}
Set answerFeedbackSet = answer.getAnswerFeedbackSet();
Iterator answerFeedbackIter = answerFeedbackSet.iterator();
String feedback = "";
while (answerFeedbackIter.hasNext()) {
AnswerFeedbackIfc answerFeedback = (AnswerFeedbackIfc) answerFeedbackIter
.next();
if (answerFeedback.getTypeId().equals(AnswerFeedbackIfc.CORRECT_FEEDBACK)) {
answerFeedback.setText(stripPtags(matchBean.getCorrMatchFeedback()));
}
else if (answerFeedback.getTypeId().equals(AnswerFeedbackIfc.INCORRECT_FEEDBACK)) {
answerFeedback.setText(stripPtags(matchBean.getIncorrMatchFeedback()));
}
}
}
}
}
int oldSize = textSet.size();
int newSize = matchItemBeanList.size();
if (oldSize > newSize) {
HashSet toBeRemovedTextSet = new HashSet();
HashSet toBeRemovedAnswerSet = new HashSet();
// Need to remove from answer too
for (int i = 1; i < newSize + 1; i++) {
ItemTextIfc text = (ItemTextIfc) itemTextMap.get(Long.valueOf(i));
answerSet = text.getAnswerSet();
if (answerSet != null) {
Iterator answerIter = answerSet.iterator();
while (answerIter.hasNext()) {
answer = (AnswerIfc) answerIter.next();
for (int j = newSize + 1; j < oldSize + 1; j++) {
if (answer.getSequence().intValue() == j) {
toBeRemovedAnswerSet.add(answer);
}
}
}
answerSet.removeAll(toBeRemovedAnswerSet);
delegate.deleteSet(toBeRemovedAnswerSet);
}
}
for (int i = newSize + 1; i < oldSize + 1; i++) {
ItemTextIfc text = (ItemTextIfc) itemTextMap.get(Long.valueOf(i));
toBeRemovedTextSet.add(text);
}
textSet.removeAll(toBeRemovedTextSet);
delegate.deleteSet(toBeRemovedTextSet);
}
}
private void preparePublishedTextForOthers(ItemFacade item, ItemBean bean) {
ItemTextIfc text = null;
Set textSet = item.getItemTextSet();
Iterator iter = textSet.iterator();
while (iter.hasNext()) {
text = (ItemTextIfc) iter.next();
text.setText(bean.getItemText());
}
}
protected HashSet prepareMetaData(ItemFacade item, ItemBean bean) {
HashSet set = new HashSet();
if (bean.getKeyword() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.KEYWORD, TextFormat.convertPlaintextToFormattedTextNoHighUnicode(log, bean.getKeyword())));
}
if (bean.getRubric() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.RUBRIC, TextFormat.convertPlaintextToFormattedTextNoHighUnicode(log, bean.getRubric())));
}
if (bean.getObjective() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.OBJECTIVE, TextFormat.convertPlaintextToFormattedTextNoHighUnicode(log, bean.getObjective())));
}
// Randomize property got left out, added in metadata
if (bean.getRandomized() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.RANDOMIZE, bean.getRandomized()));
}
// MSMC property got left out, added in metadata
if (bean.getMcmsPartialCredit() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.MCMS_PARTIAL_CREDIT, bean.getMcmsPartialCredit()));
}
// 2/19/06 use PREDEFINED_SCALE to be in sync with what we are using
// for import/export
if (bean.getScaleName() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.PREDEFINED_SCALE, bean.getScaleName()));
}
// save settings for case sensitive for FIB. Default=false
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.CASE_SENSITIVE_FOR_FIB, Boolean
.toString(bean.getCaseSensitiveForFib())));
// save settings for mutually exclusive for FIB. Default=false
// first check to see if it's a valid mutually exclusive mutiple
// answers FIB
boolean wellformatted = false;
if (bean.getMutuallyExclusiveForFib()) {
wellformatted = isValidMutualExclusiveFIB(bean);
}
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.MUTUALLY_EXCLUSIVE_FOR_FIB, Boolean
.toString(wellformatted)));
// sam-939
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.FORCE_RANKING, Boolean
.toString(bean.getForceRanking())));
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.ADD_COMMENT_MATRIX, Boolean
.toString(bean.getAddComment())));
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.MX_SURVEY_QUESTION_COMMENTFIELD, bean.getCommentField()));
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.MX_SURVEY_RELATIVE_WIDTH, Integer.toString( bean.getRelativeWidth())));
// Do we need Mutually exclusive for numeric responses, what about
// questions like
// the Square root of 4 is {2|-2} and {2|-2}.
// save settings for mutually exclusive for FIN. Default=false
// first check to see if it's a valid mutually exclusive mutiple
// answers FIN
/*
* boolean wellformattedFIN = false;
*
* set.add(new ItemMetaData(item.getData(),
* ItemMetaDataIfc.MUTUALLY_EXCLUSIVE_FOR_FIN,
* Boolean.toString(wellformattedFIN)));
*
*/
// save part id
if (bean.getSelectedSection() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.PARTID, bean.getSelectedSection()));
}
// save pool id
if (bean.getSelectedPool() != null) {
set.add(new ItemMetaData(item.getData(),
ItemMetaDataIfc.POOLID, bean.getSelectedPool()));
}
// save timeallowed for audio recording
/*
* // save them in ItemFacade if (bean.getTimeAllowed()!=null){
* set.add(new ItemMetaData(item.getData(),
* ItemMetaDataIfc.TIMEALLOWED, bean.getTimeAllowed())); }
*/
// save timeallowed for audio recording
/*
* // save them in ItemFacade if (bean.getNumAttempts()!=null){
* set.add(new ItemMetaData(item.getData(),
* ItemMetaDataIfc.NUMATTEMPTS, bean.getNumAttempts())); }
*/
return set;
}
protected Set preparePublishedMetaData(ItemFacade item, ItemBean bean) {
Set itemMetaDataSet = item.getItemMetaDataSet();
Iterator iter = itemMetaDataSet.iterator();
while (iter.hasNext()) {
ItemMetaDataIfc itemMetaData = (ItemMetaDataIfc) iter.next();
if (itemMetaData.getLabel().equals(ItemMetaDataIfc.KEYWORD)){
itemMetaData.setEntry(TextFormat.convertPlaintextToFormattedTextNoHighUnicode(log, bean.getKeyword()));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.RUBRIC)){
itemMetaData.setEntry(TextFormat.convertPlaintextToFormattedTextNoHighUnicode(log, bean.getKeyword()));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.OBJECTIVE)){
itemMetaData.setEntry(TextFormat.convertPlaintextToFormattedTextNoHighUnicode(log, bean.getObjective()));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.RANDOMIZE)){
itemMetaData.setEntry(bean.getRandomized());
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.PREDEFINED_SCALE)){
itemMetaData.setEntry(bean.getScaleName());
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.CASE_SENSITIVE_FOR_FIB)){
itemMetaData.setEntry(Boolean.toString(bean.getCaseSensitiveForFib()));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.KEYWORD)){
itemMetaData.setEntry(bean.getKeyword());
}else if(itemMetaData.getLabel().equals(ItemMetaDataIfc.MCMS_PARTIAL_CREDIT)){
itemMetaData.setEntry(bean.getMcmsPartialCredit());
}
// save settings for mutually exclusive for FIB. Default=false
// first check to see if it's a valid mutually exclusive mutiple
// answers FIB
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.MUTUALLY_EXCLUSIVE_FOR_FIB)){
boolean wellformatted = false;
if (bean.getMutuallyExclusiveForFib()) {
wellformatted = isValidMutualExclusiveFIB(bean);
}
itemMetaData.setEntry(Boolean
.toString(wellformatted));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.PARTID)){
itemMetaData.setEntry(bean.getSelectedSection());
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.POOLID)){
itemMetaData.setEntry(bean.getSelectedPool());
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.FORCE_RANKING)){
itemMetaData.setEntry(Boolean.toString(bean.getForceRanking()));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.MX_SURVEY_RELATIVE_WIDTH)){
itemMetaData.setEntry(Integer.toString(bean.getRelativeWidth()));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.ADD_COMMENT_MATRIX)){
itemMetaData.setEntry(Boolean.toString(bean.getAddComment()));
}
else if (itemMetaData.getLabel().equals(ItemMetaDataIfc.MX_SURVEY_QUESTION_COMMENTFIELD)){
itemMetaData.setEntry(bean.getCommentField());
}
}
return itemMetaDataSet;
}
private void preparePublishedTextForMatrixSurvey(ItemFacade item,
ItemBean bean, ItemService delegate){
Set textSet = item.getItemTextSet();
Iterator textIter = textSet.iterator();
HashMap itemTextMap = new HashMap();
while (textIter.hasNext()) {
ItemTextIfc itemText = (ItemTextIfc) textIter.next();
itemTextMap.put(itemText.getSequence(), itemText);
}
}
private static ArrayList getFIBanswers(String entiretext) {
String fixedText = entiretext.replaceAll(" ", " "); // replace   to " " (instead of "") just want to reserve the original input
String[] tokens = fixedText.split("[\\}][^\\{]*[\\{]");
ArrayList list = new ArrayList();
if (tokens.length==1) {
String[] afteropen= tokens[0].split("\\{");
if (afteropen.length>1) {
// must have text in between {}
String[] lastpart = afteropen[1].split("\\}");
String answer = FormattedText.convertFormattedTextToPlaintext(lastpart[0].replaceAll("<.*?>", ""));
list.add(answer);
}
}
else {
for (int i = 0; i < tokens.length; i++) {
if (i == 0) {
String[] firstpart = tokens[i].split("\\{");
if (firstpart.length>1) {
String answer = FormattedText.convertFormattedTextToPlaintext(firstpart[1].replaceAll("<.*?>", ""));
list.add(answer);
}
}
else if (i == (tokens.length - 1)) {
String[] lastpart = tokens[i].split("\\}");
String answer = FormattedText.convertFormattedTextToPlaintext(lastpart[0].replaceAll("<.*?>", ""));
list.add(answer);
}
else {
String answer = FormattedText.convertFormattedTextToPlaintext(tokens[i].replaceAll("<.*?>", ""));
list.add(answer);
}
}
} // token.length>1
return list;
}
private static ArrayList getFINanswers(String entiretext) throws FinFormatException {
String fixedText = entiretext.replaceAll(" ", " "); // replace   to " " (instead of "") just want to reserve the original input
String[] tokens = fixedText.split("[\\}][^\\{]*[\\{]");
ArrayList list = new ArrayList();
if (tokens.length==1) {
String[] afteropen= tokens[0].split("\\{");
if (afteropen.length>1) {
// must have text in between {}
String[] lastpart = afteropen[1].split("\\}");
list.add(lastpart[0]);
}
}
else {
for (int i = 0; i < tokens.length; i++) {
if (i == 0) {
String[] firstpart = tokens[i].split("\\{");
if (firstpart.length>1) {
list.add(firstpart[1]);
}
}
else if (i == (tokens.length - 1)) {
String[] lastpart = tokens[i].split("\\}");
list.add(lastpart[0]);
}
else {
list.add(tokens[i]);
}
}
} // token.length>1
return list;
}
/*
private static boolean isValidFINAnswer(String answer){
String processedAnswer = "";
if (answer.indexOf("|") == -1) {
processedAnswer = answer.replaceAll(" ", "").replaceAll(",", ".");
// Test if it is a valid Double
try {
Double.parseDouble(processedAnswer);
}
catch (NumberFormatException e) {
return false;
}
return true;
}
String[] tokens = answer.split("\\|");
if (tokens.length != 2) {
return false;
}
for (int i = 0; i < 2; i++) {
String tmpAnswer = tokens[i].replaceAll(" ", "").replaceAll(",", ".");
// Test if it is a valid Double
try {
Double.parseDouble(tmpAnswer);
}
catch (NumberFormatException e) {
return false;
}
}
return true;
}
*/
/**
** returns if the multile choice label is the correct choice,
** bean.getCorrAnswers() returns a string[] of labels
** bean.getCorrAnswer() returns a string of label
**/
public boolean isCorrectChoice(ItemBean bean, String label) {
boolean returnvalue = false;
if (TypeFacade.MULTIPLE_CHOICE.toString().equals(bean.getItemType())) {
String corranswer = ContextUtil.lookupParam("itemForm:selectedRadioBtn");
if (corranswer.equals(label)) {
returnvalue = true;
}
else {
returnvalue = false;
}
}
else {
ArrayList corranswersList = ContextUtil.paramArrayValueLike(
"mccheckboxes");
Iterator iter = corranswersList.iterator();
while (iter.hasNext()) {
String currentcorrect = (String) iter.next();
if (currentcorrect.trim().equals(label)) {
returnvalue = true;
break;
}
else {
returnvalue = false;
}
}
}
return returnvalue;
}
/**
** shift sequence number down when inserting or reordering
**/
public void shiftSequences(ItemService delegate, SectionFacade sectfacade, Integer currSeq) {
Set itemset = sectfacade.getItemFacadeSet();
Iterator iter = itemset.iterator();
while (iter.hasNext()) {
ItemFacade itemfacade = (ItemFacade) iter.next();
Integer itemfacadeseq = itemfacade.getSequence();
if (itemfacadeseq.compareTo(currSeq) > 0) {
itemfacade.setSequence(Integer.valueOf(itemfacadeseq.intValue() + 1));
delegate.saveItem(itemfacade);
}
}
}
private void shiftItemsInOrigSection(ItemService delegate, SectionFacade sectfacade, Integer currSeq){
Set itemset = sectfacade.getItemFacadeSet();
// should be size-1 now.
Iterator iter = itemset.iterator();
while (iter.hasNext()) {
ItemFacade itemfacade = (ItemFacade) iter.next();
Integer itemfacadeseq = itemfacade.getSequence();
if (itemfacadeseq.compareTo(currSeq) > 0 ){
itemfacade.setSequence( Integer.valueOf(itemfacadeseq.intValue()-1) );
delegate.saveItem(itemfacade);
}
}
}
private String stripPtags(String origtext) {
// interim solution for the wywisyg bug. This will strip off the first <p> and last </p> if both exists.
String newanswer = origtext;
if ((origtext!= null)&& (origtext.startsWith("<p")) && (origtext.endsWith("</p>")) ){
newanswer = origtext.substring(origtext.indexOf(">") + 1, origtext.lastIndexOf("</p>"));
return newanswer.trim();
}
else {
return newanswer;
}
}
private boolean isValidMutualExclusiveFIB(ItemBean bean){
// all answer sets have to be identical, case insensitive
String entiretext = bean.getItemText();
String processedText [] = processFIBFINText(entiretext);
log.debug("processedText[1]=" + processedText[1]);
Object[] fibanswers = getFIBanswers(processedText[1]).toArray();
List blanklist = new ArrayList();
for (int i = 0; i < fibanswers.length; i++) {
log.debug("fibanswers[" + i + "]=" + fibanswers[i]);
String oneanswer = (String) fibanswers[i];
String[] oneblank = oneanswer.split("\\|");
Set oneblankset = new HashSet();
for (int j = 0; j < oneblank.length; j++) {
oneblankset.add(oneblank[j].trim().toLowerCase());
}
blanklist.add(oneblankset);
}
// now check if there are at leastF 2 sets, and make sure they are identically, all should contain only lowercase strings.
boolean invalid= false;
if (blanklist.size()<=1){
invalid = true;
}
else {
for (int i = 1; i < blanklist.size(); i++) {
if (!(blanklist.get(0).equals(blanklist.get(i)))){
invalid = true;
break;
}
}
}
return !invalid;
}
private void updateAttachment(List oldList, List newList, ItemDataIfc item, boolean pendingOrPool){
if ((oldList == null || oldList.size() == 0 ) && (newList == null || newList.size() == 0)) return;
List list = new ArrayList();
HashMap map = getAttachmentIdHash(oldList);
for (int i=0; i<newList.size(); i++){
ItemAttachmentIfc a = (ItemAttachmentIfc)newList.get(i);
if (map.get(a.getAttachmentId())!=null){
// exist already, remove it from map
map.remove(a.getAttachmentId());
}
else{
// new attachments
a.setItem(item);
list.add(a);
}
}
// save new ones
AssessmentService service;
if (pendingOrPool) {
service = new AssessmentService();
}
else {
service = new PublishedAssessmentService();
}
service.saveOrUpdateAttachments(list);
// remove old ones
Set set = map.keySet();
Iterator iter = set.iterator();
while (iter.hasNext()){
Long attachmentId = (Long)iter.next();
service.removeItemAttachment(attachmentId.toString());
}
}
private HashMap getAttachmentIdHash(List list){
HashMap map = new HashMap();
for (int i=0; i<list.size(); i++){
ItemAttachmentIfc a = (ItemAttachmentIfc)list.get(i);
map.put(a.getAttachmentId(), a);
}
return map;
}
private void updateItemFeedback(ItemFacade item, String feedbackTypeId, String feedbackText) {
Set itemFeedbackSet = item.getItemFeedbackSet();
if ((itemFeedbackSet == null || itemFeedbackSet.size() == 0)) {
item.addItemFeedback(feedbackTypeId, feedbackText);
}
else {
Iterator iter = itemFeedbackSet.iterator();
while (iter.hasNext()) {
ItemFeedbackIfc itemFeedback = (ItemFeedbackIfc) iter.next();
if (itemFeedback.getTypeId().equals(feedbackTypeId)) {
itemFeedback.setText(feedbackText);
}
}
}
}
private String [] getSurveyChoices(String scalename) {
String[] choices = new String[2];
// label is null because we don't use labels in survey
if (ItemMetaDataIfc.SURVEY_YES.equals(scalename)) {
choices = new String[2];
choices[0] = "st_yes";
choices[1] = "st_no";
}
if (ItemMetaDataIfc.SURVEY_AGREE.equals(scalename)) {
choices = new String[2];
choices[0] = "st_disagree";
choices[1] = "st_agree";
}
if (ItemMetaDataIfc.SURVEY_UNDECIDED.equals(scalename)) {
choices = new String[3];
choices[0] = "st_disagree";
choices[1] = "st_undecided";
choices[2] = "st_agree";
}
if (ItemMetaDataIfc.SURVEY_AVERAGE.equals(scalename)) {
choices = new String[3];
choices[0] = "st_below_average";
choices[1] = "st_average";
choices[2] = "st_above_average";
}
if (ItemMetaDataIfc.SURVEY_STRONGLY_AGREE.equals(scalename)) {
choices = new String[5];
choices[0] = "st_strongly_disagree";
choices[1] = "st_disagree";
choices[2] = "st_undecided";
choices[3] = "st_agree";
choices[4] = "st_strongly_agree";
}
if (ItemMetaDataIfc.SURVEY_EXCELLENT.equals(scalename)) {
choices = new String[5];
choices[0] = "st_unacceptable";
choices[1] = "st_below_average";
choices[2] = "st_average";
choices[3] = "st_above_average";
choices[4] = "st_excellent";
}
if (ItemMetaDataIfc.SURVEY_5.equals(scalename)) {
choices = new String[5];
choices[0] = "1";
choices[1] = "2";
choices[2] = "3";
choices[3] = "4";
choices[4] = "5";
}
if (ItemMetaDataIfc.SURVEY_10.equals(scalename)) {
choices = new String[10];
choices[0] = "1";
choices[1] = "2";
choices[2] = "3";
choices[3] = "4";
choices[4] = "5";
choices[5] = "6";
choices[6] = "7";
choices[7] = "8";
choices[8] = "9";
choices[9] = "10";
}
return choices;
}
private String [] processFIBFINText(String entiretext) {
String[] processedText = new String[2];
Pattern pattern1 = Pattern.compile("[\\{][^\\}]*[\\}]");
Matcher matcher1 = pattern1.matcher(entiretext);
StringBuilder textStringBuilder1 = new StringBuilder();
String tmpString1 = null;
int index1 = 0;
while (matcher1.find()) {
String group = matcher1.group();
textStringBuilder1.append(entiretext.substring(index1, matcher1.start()));
tmpString1 = group.replaceAll("<.*?>", "");
textStringBuilder1.append(tmpString1);
index1 = matcher1.end();
}
textStringBuilder1.append(entiretext.substring(index1));
String modifiedText = textStringBuilder1.toString();
//String[] tmpString = modifiedText.split("(<([a-z]\\w*)\\b[^>]*>(.*?)</\\1\\s*>)|(<([a-z]\\w*)\\b[^>]*/>)");
Pattern pattern2 = Pattern.compile("(<([a-z]\\w*)\\b[^>]*>(.*?)</\\1\\s*>)|(<([a-z]\\w*)\\b[^>]*/>)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher matcher2 = pattern2.matcher(modifiedText);
int index2 = 0;
StringBuilder textStringBuilder2 = new StringBuilder();
StringBuilder textStringBuilder3 = new StringBuilder();
String tmpString2 = null;
while (matcher2.find()) {
String group = matcher2.group();
log.debug("group" + group);
tmpString2 = modifiedText.substring(index2, matcher2.start());
log.debug("tmpString2" + tmpString2);
if (tmpString2 != null) {
textStringBuilder2.append(tmpString2.replaceAll("[\\{][^\\}]*[\\}]", "{}"));
textStringBuilder3.append(tmpString2);
log.debug("textStringBuilder2=" + textStringBuilder2);
log.debug("textStringBuilder3=" + textStringBuilder3);
}
textStringBuilder2.append(group);
index2 = matcher2.end();
log.debug("index2=" + index2);
}
tmpString2 = modifiedText.substring(index2);
if (tmpString2 != null) {
textStringBuilder2.append(tmpString2.replaceAll("[\\{][^\\}]*[\\}]", "{}"));
textStringBuilder3.append(tmpString2);
log.debug("textStringBuilder2=" + textStringBuilder2);
log.debug("textStringBuilder3=" + textStringBuilder3);
}
processedText[0] = textStringBuilder2.toString();
processedText[1] = textStringBuilder3.toString();
return processedText;
}
}