Index: sam/component/src/java/org/sakaiproject/tool/assessment/qti/helper/AuthoringHelper.java
===================================================================
--- sam/component/src/java/org/sakaiproject/tool/assessment/qti/helper/AuthoringHelper.java (revision 18192)
+++ sam/component/src/java/org/sakaiproject/tool/assessment/qti/helper/AuthoringHelper.java (working copy)
@@ -26,6 +26,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
@@ -45,16 +47,20 @@
import org.xml.sax.SAXException;
import org.sakaiproject.tool.assessment.data.dao.assessment.ItemMetaData;
+import org.sakaiproject.tool.assessment.data.dao.questionpool.QuestionPoolItemData;
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.AssessmentMetaDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.EvaluationModelIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemDataIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.SectionDataIfc;
+import org.sakaiproject.tool.assessment.data.ifc.questionpool.QuestionPoolItemIfc;
import org.sakaiproject.tool.assessment.data.ifc.shared.TypeIfc;
+import org.sakaiproject.tool.assessment.data.model.Tree;
import org.sakaiproject.tool.assessment.facade.AgentFacade;
import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
import org.sakaiproject.tool.assessment.facade.ItemFacade;
+import org.sakaiproject.tool.assessment.facade.QuestionPoolFacade;
import org.sakaiproject.tool.assessment.facade.SectionFacade;
import org.sakaiproject.tool.assessment.qti.asi.Assessment;
import org.sakaiproject.tool.assessment.qti.asi.Item;
@@ -65,6 +71,7 @@
import org.sakaiproject.tool.assessment.qti.helper.section.SectionHelperIfc;
import org.sakaiproject.tool.assessment.qti.util.XmlStringBuffer;
import org.sakaiproject.tool.assessment.services.ItemService;
+import org.sakaiproject.tool.assessment.services.QuestionPoolService;
import org.sakaiproject.tool.assessment.services.assessment.AssessmentService;
import org.sakaiproject.tool.assessment.qti.util.XmlUtil;
import java.util.Set;
@@ -453,7 +460,8 @@
public AssessmentFacade createImportedAssessment(Document document)
{
AssessmentFacade assessment = null;
-
+ AssessmentService assessmentService = new AssessmentService();
+
try
{
// we need to know who we are
@@ -461,7 +469,6 @@
// create the assessment
ExtractionHelper exHelper = new ExtractionHelper(this.qtiVersion);
- AssessmentService assessmentService = new AssessmentService();
ItemService itemService = new ItemService();
Assessment assessmentXml = new Assessment(document);
Map assessmentMap = exHelper.mapAssessment(assessmentXml);
@@ -575,7 +582,129 @@
return assessment;
}
+
/**
+ * Import an assessment XML document in QTI format, extract & persist the data.
+ * import process assumes assessment structure, not objectbank or itembank
+ * @param document the assessment XML document in QTI format
+ * @return a persisted assessment
+ */
+ public QuestionPoolFacade createImportedQuestionPool(Document document)
+ {
+ QuestionPoolFacade questionpool = new QuestionPoolFacade();
+ QuestionPoolService questionPoolService = new QuestionPoolService();
+
+ try
+ {
+ // identify user to assign as question pool owner
+ String me = AgentFacade.getAgentString();
+
+ // create the questionpool as an assessment
+ ExtractionHelper exHelper = new ExtractionHelper(this.qtiVersion);
+ ItemService itemService = new ItemService();
+ Assessment assessmentXml = new Assessment(document);
+ Map assessmentMap = exHelper.mapAssessment(assessmentXml);
+ String title = (String) assessmentMap.get("title");
+
+ // save questionpool with required info only at this point
+ questionpool.setOwnerId(me);
+ questionpool.setTitle(title);
+ questionpool.setLastModifiedById(me);
+ questionpool.setAccessTypeId(QuestionPoolFacade.ACCESS_DENIED); // set as default
+ questionpool = questionPoolService.savePool(questionpool);
+ // update the remaining questionpool properties
+ exHelper.updateQuestionPool(questionpool, assessmentMap);
+
+ // now make sure we have a unique name for the question pool
+ String baseId = questionpool.getQuestionPoolId().toString();
+ boolean isUnique=questionPoolService.poolIsUnique(baseId,title,"0");
+
+ // if the title is not unique, increment with a number per renameDuplicate()
+ if (!isUnique) {
+
+ synchronized (title)
+ {
+ log.debug("Questionpool "+ title + " is not unique.");
+ int count = 0; // alternate exit condition
+
+ while (!isUnique)
+ {
+ title = exHelper.renameDuplicate(title);
+ log.debug("renameDuplicate(title): " + title);
+ questionpool.setTitle(title);
+ //recheck to confirm that new title is not a duplicate too
+ isUnique = questionPoolService.poolIsUnique(baseId,title,"0");
+ if (count++ > 99) break;// exit condition in case bug is introduced
+ }
+ }
+ }
+
+
+ // process each section and each item within assessment each section
+ List sectionList = exHelper.getSectionXmlList(assessmentXml);
+ int sectionListSize = sectionList.size();
+ int sec = sectionListSize-1;
+ log.debug("sections=" + sectionListSize);
+
+ // initialize setQuestionPoolItems so items can be added
+ Set itemSet = new HashSet();
+ questionpool.setQuestionPoolItems(itemSet);
+
+ // use case for single section
+ // most common for Respondus & BB migrations
+ if (sectionListSize == 1)
+ {
+ Section sectionXml = (Section) sectionList.get(sec);
+ Map sectionMap = exHelper.mapSection(sectionXml);
+ // for single section, do not create subpool
+
+ List itemList = exHelper.getItemXmlList(sectionXml);
+ for (int itm = 0; itm < itemList.size(); itm++) // for each item
+ {
+ log.debug("items=" + itemList.size());
+ Item itemXml = (Item) itemList.get(itm);
+ Map itemMap = exHelper.mapItem(itemXml);
+
+ ItemFacade item = new ItemFacade();
+ exHelper.updateItem(item, itemMap);
+ // make sure required fields are set
+ item.setCreatedBy(me);
+ item.setCreatedDate(questionpool.getLastModified());
+ item.setLastModifiedBy(me);
+ item.setLastModifiedDate(questionpool.getLastModified());
+ item.setStatus(ItemDataIfc.ACTIVE_STATUS);
+ itemService.saveItem(item);
+
+ // QuestionPoolItemData is used for later Sakai versions
+ //QuestionPoolItemData questionPoolItem = new QuestionPoolItemData();
+ //questionPoolItem.setQuestionPoolId(questionpool.getQuestionPoolId());
+ //questionPoolItem.setItemId(item.getItemIdString());
+ //questionpool.addQuestionPoolItem((QuestionPoolItemIfc) questionPoolItem);
+ questionPoolService.addItemToPool(item.getItemIdString(),questionpool.getQuestionPoolId());
+
+
+ } // ... end for each item
+
+ }
+ // need error message if more than one section, for now
+
+
+ // update the questionpoool with all sections and items
+ questionPoolService.savePool(questionpool);
+
+ return questionpool;
+ }
+ catch (Exception e)
+ {
+ log.error(e.getMessage(), e);
+ Tree tree = null;
+ questionPoolService.deletePool(questionpool.getQuestionPoolId(), AgentFacade.getAgentString(), tree);
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ /**
* @deprecated
* Import an item XML document in QTI format, extract & persist the data.
* @param document the item XML document in QTI format
Index: sam/component/src/java/org/sakaiproject/tool/assessment/qti/helper/ExtractionHelper.java
===================================================================
--- sam/component/src/java/org/sakaiproject/tool/assessment/qti/helper/ExtractionHelper.java (revision 18192)
+++ sam/component/src/java/org/sakaiproject/tool/assessment/qti/helper/ExtractionHelper.java (working copy)
@@ -55,6 +55,7 @@
import org.sakaiproject.tool.assessment.data.ifc.shared.TypeIfc;
import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
import org.sakaiproject.tool.assessment.facade.ItemFacade;
+import org.sakaiproject.tool.assessment.facade.QuestionPoolFacade;
import org.sakaiproject.tool.assessment.facade.SectionFacade;
import org.sakaiproject.tool.assessment.qti.asi.ASIBaseClass;
import org.sakaiproject.tool.assessment.qti.asi.Assessment;
@@ -945,7 +946,34 @@
}
}
+
/**
+ * Update questionpool from the extracted properties.
+ * Note: you need to do a save when you are done.
+ * @param questionpool, which will be persisted
+ * @param assessmentMap, the extracted properties
+ */
+ public void updateQuestionPool(QuestionPoolFacade questionpool,
+ Map assessmentMap)
+ {
+
+ String title = ((String)assessmentMap.get("title"));
+ questionpool.setDescription((String)assessmentMap.get("description"));
+ //questionpool.setLastModifiedById("Sakai Import");
+ questionpool.setLastModified(new Date());
+ // note: currently dateCreated field not in use
+ //questionpool.setDateCreated(new Date());
+ questionpool.setOrganizationName((String)assessmentMap.get("ASSESSMENT_ORGANIZATIONNAME"));
+ questionpool.setObjectives((String)assessmentMap.get("ASSESSMENT_OBJECTIVES"));
+ questionpool.setKeywords((String)assessmentMap.get("ASSESSMENT_KEYWORDS"));
+ questionpool.setRubric((String)assessmentMap.get("ASSESSMENT_RUBRICS"));
+ questionpool.setIntellectualPropertyId((Long)assessmentMap.get("INTELLECTUALPROPERTYID"));
+
+ log.debug("QPOOL ASSESSMENT updating metadata information");
+
+ }
+
+ /**
* Update section from the extracted properties.
* Note: you need to do a save when you are done.
* @param section the section, which will be persisted
Index: sam/component/src/java/org/sakaiproject/tool/assessment/services/qti/QTIService.java
===================================================================
--- sam/component/src/java/org/sakaiproject/tool/assessment/services/qti/QTIService.java (revision 18192)
+++ sam/component/src/java/org/sakaiproject/tool/assessment/services/qti/QTIService.java (working copy)
@@ -29,6 +29,7 @@
import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
import org.sakaiproject.tool.assessment.facade.ItemFacade;
+import org.sakaiproject.tool.assessment.facade.QuestionPoolFacade;
import org.sakaiproject.tool.assessment.qti.constants.QTIVersion;
import org.sakaiproject.tool.assessment.qti.helper.AuthoringHelper;
@@ -70,7 +71,34 @@
}
}
+
/**
+ * Import an assessment XML document in QTI format, extract & persist the data.
+ * import process assumes assessment structure, not objectbank or itembank
+ * based on usage in other potential migration systems, Respondus, BlackBoard, etc.
+ * QTI version 2.x will probably focus on content packaging for question pools
+ * @param document the assessment XML document in QTI format
+ * @param qtiVersion QTIVersion.VERSION_1_2;
+ * @return a persisted assessment
+ */
+ public QuestionPoolFacade createImportedQuestionPool(Document document, int qtiVersion)
+ {
+ testQtiVersion(qtiVersion);
+
+ try
+ {
+ AuthoringHelper helper = new AuthoringHelper(qtiVersion);
+ return helper.createImportedQuestionPool(document);
+
+ }
+ catch (Exception ex)
+ {
+ throw new QTIServiceException(ex);
+ }
+ }
+
+
+ /**
* Import an item XML document in QTI format, extract & persist the data.
* @param document the item XML document in QTI format
* @param qtiVersion either QTIVersion.VERSION_1_2 or QTIVersion.VERSION_2_0;
Index: sam/tool/src/java/org/sakaiproject/tool/assessment/bundle/AuthorImportExport.properties
===================================================================
--- sam/tool/src/java/org/sakaiproject/tool/assessment/bundle/AuthorImportExport.properties (revision 18192)
+++ sam/tool/src/java/org/sakaiproject/tool/assessment/bundle/AuthorImportExport.properties (working copy)
@@ -16,6 +16,7 @@
import_a=Import Assessment
import_p=Import Part
import_q=Import Question
+import_qp=Import Pool
import_action=Import
import_cancel_action=Cancel
choose_file=Choose a file:
Index: sam/tool/src/java/org/sakaiproject/tool/assessment/bundle/QuestionPoolMessages.properties
===================================================================
--- sam/tool/src/java/org/sakaiproject/tool/assessment/bundle/QuestionPoolMessages.properties (revision 18192)
+++ sam/tool/src/java/org/sakaiproject/tool/assessment/bundle/QuestionPoolMessages.properties (working copy)
@@ -174,12 +174,12 @@
t_addSubpool=Add Subpool
t_addQuestion=Add Question
t_addNewPool=Add New Pool
-t_addSubpool=Add Subpool
t_editPool=Edit Pool
t_editQuestion=Edit Question
t_copyPool=Copy Pool
t_movePool=Move Pool
t_removePool=RemovePool
+t_importPool=Import Pool
t_copyQuestion=Copy Question
t_moveQuestion=Move Question
t_exportQuestion=Export Question
Index: sam/tool/src/java/org/sakaiproject/tool/assessment/ui/bean/qti/XMLImportBean.java
===================================================================
--- sam/tool/src/java/org/sakaiproject/tool/assessment/ui/bean/qti/XMLImportBean.java (revision 18192)
+++ sam/tool/src/java/org/sakaiproject/tool/assessment/ui/bean/qti/XMLImportBean.java (working copy)
@@ -29,18 +29,21 @@
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
+import java.io.File;
import org.w3c.dom.Document;
import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
import org.sakaiproject.tool.assessment.facade.AssessmentFacadeQueries;
import org.sakaiproject.tool.assessment.facade.AssessmentTemplateFacade;
+import org.sakaiproject.tool.assessment.facade.QuestionPoolFacade;
import org.sakaiproject.tool.assessment.qti.constants.QTIVersion;
import org.sakaiproject.tool.assessment.services.assessment.AssessmentService;
import org.sakaiproject.tool.assessment.services.qti.QTIService;
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.ItemAuthorBean;
+import org.sakaiproject.tool.assessment.ui.bean.questionpool.QuestionPoolBean;
import org.sakaiproject.tool.assessment.qti.util.XmlUtil;
/**
@@ -58,6 +61,7 @@
private AuthorBean authorBean;
private AssessmentBean assessmentBean;
private ItemAuthorBean itemAuthorBean;
+ private QuestionPoolBean questionPoolBean;
private ResourceBundle rb = ResourceBundle.getBundle("org.sakaiproject.tool.assessment.bundle.AuthorImportExport");
public XMLImportBean()
@@ -172,6 +176,7 @@
AssessmentFacadeQueries.TITLE,true);
//
authorBean.setAssessments(list);
+
}
/**
@@ -217,5 +222,75 @@
{
this.itemAuthorBean = itemAuthorBean;
}
+
+ /**
+ * Value change on upload
+ * @param e the event
+ */
+ public void importPoolFromQti(ValueChangeEvent e)
+ {
+ String uploadFile = (String) e.getNewValue();
+ try
+ {
+ processAsPoolFile(uploadFile);
+ }
+ catch (Exception ex)
+ {
+ FacesMessage message = new FacesMessage( rb.getString("import_err") + ex );
+ FacesContext.getCurrentInstance().addMessage(null, message);
+ }
+ }
+
+
+ /**
+ * Process uploaded QTI XML
+ * assessment as question pool
+ */
+ private void processAsPoolFile(String uploadFile)
+ {
+ itemAuthorBean.setTarget(ItemAuthorBean.FROM_QUESTIONPOOL); // save to questionpool
+
+ // Get the file name
+ String fileName = uploadFile;
+
+ // Create a questionpool based on the uploaded assessment file
+ QuestionPoolFacade questionPool = createImportedQuestionPool(fileName, qtiVersion);
+
+ // remove uploaded file
+ try{
+ //System.out.println("****filename="+fileName);
+ File upload = new File(fileName);
+ upload.delete();
+ }
+ catch(Exception e){
+ System.out.println(e.getMessage());
+ }
+ }
+
+ /**
+ * Create questionpool from uploaded QTI assessment XML
+ * @param fullFileName file name and path
+ * @param qti QTI version
+ * @return
+ */
+ private QuestionPoolFacade createImportedQuestionPool(String fullFileName, int qti)
+ {
+ //trim = true so that xml processing instruction at top line, even if not.
+ Document document = XmlUtil.readDocument(fullFileName, true);
+ QTIService qtiService = new QTIService();
+ return qtiService.createImportedQuestionPool(document, qti);
+ }
+
+
+ public QuestionPoolBean getQuestionPoolBean()
+ {
+ return questionPoolBean;
+ }
+
+ public void setQuestionPoolBean(QuestionPoolBean questionPoolBean)
+ {
+ this.questionPoolBean = questionPoolBean;
+ }
+
}
Index: sam/tool/src/webapp/jsf/qti/importPool.jsp
===================================================================
--- sam/tool/src/webapp/jsf/qti/importPool.jsp (revision 0)
+++ sam/tool/src/webapp/jsf/qti/importPool.jsp (revision 0)
@@ -0,0 +1,79 @@
+<%@ page contentType="text/html;charset=utf-8" pageEncoding="utf-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
+<%@ taglib uri="http://www.sakaiproject.org/samigo" prefix="samigo" %>
+<%@ taglib uri="http://java.sun.com/upload" prefix="corejsf" %>
+
+
+
+
+
+
+
+ <%-- activates the valueChangeListener --%>
+