001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/sam/trunk/component/src/java/org/sakaiproject/tool/assessment/qti/helper/AuthoringHelper.java $
003: * $Id: AuthoringHelper.java 9274 2006-05-10 22:50:48Z daisyf@stanford.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the"License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.tool.assessment.qti.helper;
021:
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.util.ArrayList;
025: import java.util.HashSet;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.Set;
030: import java.util.StringTokenizer;
031:
032: import javax.xml.parsers.DocumentBuilder;
033: import javax.xml.parsers.DocumentBuilderFactory;
034: import javax.xml.parsers.ParserConfigurationException;
035: import javax.xml.transform.TransformerException;
036:
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039: import org.sakaiproject.tool.assessment.data.dao.assessment.ItemMetaData;
040: import org.sakaiproject.tool.assessment.data.dao.questionpool.QuestionPoolItemData;
041: import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentAccessControlIfc;
042: import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentFeedbackIfc;
043: import org.sakaiproject.tool.assessment.data.ifc.assessment.AssessmentMetaDataIfc;
044: import org.sakaiproject.tool.assessment.data.ifc.assessment.EvaluationModelIfc;
045: import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemDataIfc;
046: import org.sakaiproject.tool.assessment.data.ifc.assessment.SectionDataIfc;
047: import org.sakaiproject.tool.assessment.data.ifc.questionpool.QuestionPoolItemIfc;
048: import org.sakaiproject.tool.assessment.data.ifc.shared.TypeIfc;
049: import org.sakaiproject.tool.assessment.data.model.Tree;
050: import org.sakaiproject.tool.assessment.facade.AgentFacade;
051: import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
052: import org.sakaiproject.tool.assessment.facade.ItemFacade;
053: import org.sakaiproject.tool.assessment.facade.QuestionPoolFacade;
054: import org.sakaiproject.tool.assessment.facade.SectionFacade;
055: import org.sakaiproject.tool.assessment.integration.helper.integrated.AgentHelperImpl;
056: import org.sakaiproject.tool.assessment.qti.asi.Assessment;
057: import org.sakaiproject.tool.assessment.qti.asi.Item;
058: import org.sakaiproject.tool.assessment.qti.asi.Section;
059: import org.sakaiproject.tool.assessment.qti.constants.QTIVersion;
060: import org.sakaiproject.tool.assessment.qti.helper.assessment.AssessmentHelperIfc;
061: import org.sakaiproject.tool.assessment.qti.helper.item.ItemHelperIfc;
062: import org.sakaiproject.tool.assessment.qti.helper.section.SectionHelperIfc;
063: import org.sakaiproject.tool.assessment.qti.util.XmlStringBuffer;
064: import org.sakaiproject.tool.assessment.qti.util.XmlUtil;
065: import org.sakaiproject.tool.assessment.services.ItemService;
066: import org.sakaiproject.tool.assessment.services.QuestionPoolService;
067: import org.sakaiproject.tool.assessment.services.assessment.AssessmentService;
068: import org.w3c.dom.Document;
069: import org.w3c.dom.Element;
070: import org.w3c.dom.Node;
071: import org.w3c.dom.NodeList;
072: import org.xml.sax.SAXException;
073:
074: /**
075: * <p>Copyright: Copyright (c) 2004</p>
076: * <p>Organization: Sakai Project</p>
077: * @author Ed Smiley esmiley@stanford.edu
078: * @author Shastri, Rashmi <rshastri@iupui.edu>
079: * @version $Id: AuthoringHelper.java 9274 2006-05-10 22:50:48Z daisyf@stanford.edu $
080: */
081: public class AuthoringHelper {
082: private static Log log = LogFactory.getLog(AuthoringHelper.class);
083: // private static final AuthoringXml ax = new AuthoringXml(QTIVersion.VERSION_1_2);
084: private AuthoringXml ax;
085:
086: private int qtiVersion;
087:
088: private AuthoringHelper() {
089:
090: }
091:
092: /**
093: * QTI versioned constructor
094: * @param qtiVersion either QTIVersion.VERSION_1_2 or QTIVersion.VERSION_2_0;
095: */
096: public AuthoringHelper(int qtiVersion) {
097: this .qtiVersion = qtiVersion;
098: if (!QTIVersion.isValid(qtiVersion)) {
099: throw new IllegalArgumentException(
100: "Version Codes supported: QTIVersion.VERSION_1_2, QTIVersion.VERSION_2_0");
101: }
102: ax = new AuthoringXml(qtiVersion);
103: }
104:
105: /**
106: * Get a published assessment in Document form.
107: *
108: * @param assessmentId the published assessment's Id
109: * @return the Document with the published assessment data
110: */
111: public Document getAssessment(String assessmentId) {
112:
113: InputStream is = ax.getTemplateInputStream(ax.ASSESSMENT);
114:
115: return getAssessment(assessmentId, is);
116: }
117:
118: /**
119: * Get an assessment in Document form.
120: *
121: * @param assessmentId the assessment's Id
122: * @param is a stream containing the unpopulated XML document
123: * @return the Document with the published assessment data
124: */
125: public Document getAssessment(String assessmentId, InputStream is) {
126: try {
127: String authors;
128: String objectives;
129: String keywords;
130: String rubrics;
131: String bgColor;
132: String bgImage;
133:
134: AssessmentService assessmentService = new AssessmentService();
135: QTIHelperFactory factory = new QTIHelperFactory();
136:
137: AssessmentFacade assessment = assessmentService
138: .getAssessment(assessmentId);
139: // convert assessment to document
140: AssessmentHelperIfc assessmentHelper = factory
141: .getAssessmentHelperInstance(this .qtiVersion);
142: Assessment assessmentXml = assessmentHelper
143: .readXMLDocument(is);
144: assessmentXml.setIdent(assessmentId);
145: assessmentXml.setTitle(assessment.getTitle());
146: assessmentHelper.setDescriptiveText(assessment
147: .getDescription(), assessmentXml);
148:
149: authors = assessment
150: .getAssessmentMetaDataByLabel(AssessmentMetaDataIfc.AUTHORS);
151: objectives = assessment
152: .getAssessmentMetaDataByLabel(AssessmentMetaDataIfc.OBJECTIVES);
153: keywords = assessment
154: .getAssessmentMetaDataByLabel(AssessmentMetaDataIfc.KEYWORDS);
155: rubrics = assessment
156: .getAssessmentMetaDataByLabel(AssessmentMetaDataIfc.RUBRICS);
157: bgColor = assessment
158: .getAssessmentMetaDataByLabel(AssessmentMetaDataIfc.BGCOLOR);
159: bgImage = assessment
160: .getAssessmentMetaDataByLabel(AssessmentMetaDataIfc.BGIMAGE);
161:
162: if (authors != null) {
163: assessmentXml.setFieldentry("AUTHORS", authors);
164: } else {
165: AgentHelperImpl helper = new AgentHelperImpl();
166: String createdBy = assessment.getCreatedBy();
167: String eid = helper.getEidById(createdBy);
168: if (eid != null) {
169: assessmentXml.setFieldentry("AUTHORS", eid);
170: } else {
171: log.debug("\n\nNO AUTHORS");
172: }
173: }
174:
175: if (objectives != null) {
176: assessmentXml.setFieldentry("ASSESSMENT_OBJECTIVES",
177: objectives);
178: }
179: if (keywords != null) {
180: assessmentXml.setFieldentry("ASSESSMENT_KEYWORDS",
181: keywords);
182: }
183: if (rubrics != null) {
184: assessmentXml.setFieldentry("ASSESSMENT_RUBRICS",
185: rubrics);
186: }
187: if (bgColor != null) {
188: assessmentXml.setFieldentry("BGCOLOR", bgColor);
189: }
190: if (bgImage != null) {
191: assessmentXml.setFieldentry("BGIMG", bgImage);
192: }
193:
194: // fieldentry properties
195: EvaluationModelIfc evaluationModel = assessment
196: .getEvaluationModel();
197: if (evaluationModel != null) {
198: assessmentHelper.updateEvaluationModel(assessmentXml,
199: evaluationModel);
200: }
201: AssessmentFeedbackIfc assessmentFeedback = assessment
202: .getAssessmentFeedback();
203: if (assessmentFeedback != null) {
204: assessmentHelper.updateFeedbackModel(assessmentXml,
205: assessmentFeedback);
206: }
207: AssessmentAccessControlIfc assessmentAccessControl = assessment
208: .getAssessmentAccessControl();
209: if (assessmentAccessControl != null) {
210: assessmentHelper.updateAccessControl(assessmentXml,
211: assessmentAccessControl);
212: }
213: Set securedIPAddressSet = (Set) assessment
214: .getSecuredIPAddressSet();
215: if (securedIPAddressSet != null) {
216: assessmentHelper.updateIPAddressSet(assessmentXml,
217: securedIPAddressSet);
218: }
219:
220: Set attachmentSet = (Set) assessment
221: .getAssessmentAttachmentSet();
222:
223: if (attachmentSet != null && attachmentSet.size() != 0) {
224: assessmentHelper.updateAttachmentSet(assessmentXml,
225: attachmentSet);
226: }
227:
228: assessmentHelper.updateMetaData(assessmentXml, assessment);
229:
230: // sections
231: factory = new QTIHelperFactory();
232: SectionHelperIfc sectionHelper = factory
233: .getSectionHelperInstance(this .qtiVersion);
234: List sectionList = assessment.getSectionArraySorted();
235: for (int i = 0; i < sectionList.size(); i++) {
236: SectionDataIfc section = (SectionDataIfc) sectionList
237: .get(i);
238: InputStream sis = ax.getTemplateInputStream(ax.SECTION);
239: Section sectionXml = sectionHelper.readXMLDocument(sis);
240: sectionXml.update(section);
241: addSection(assessmentXml, sectionXml);
242: }
243:
244: return assessmentXml.getDocument();
245: } catch (Exception e) {
246: log.error(e.getMessage(), e);
247: }
248: return null;
249: }
250:
251: /**
252: * Get an object bank of items in Document form.
253: *
254: * @param itemIds array of the the item ids
255: * @return the Document with the item bank data
256: */
257: public Document getItemBank(String[] itemIds) {
258: Document objectBank = XmlUtil.createDocument();
259:
260: Element root = objectBank.createElement("questestinterop");
261: Element ob = objectBank.createElement("objectbank");
262: String objectBankIdent = "object" + Math.random();
263: ob.setAttribute("ident", objectBankIdent);
264: for (int i = 0; i < itemIds.length; i++) {
265: Document itemDoc = getItem(itemIds[i]);
266: Element itemElement = itemDoc.getDocumentElement();
267: Node itemImport = objectBank.importNode(itemElement, true);
268: ob.appendChild(itemImport);
269: }
270: root.appendChild(ob);
271: objectBank.appendChild(root);
272:
273: return objectBank;
274: }
275:
276: /**
277: * Get an object bank of asessments (asi) in Document form.
278: *
279: * @param assessmentIds array of the the assessment ids
280: * @return the Document with the item bank data
281: */
282: public Document getAssessmentBank(String[] assessmentIds) {
283: Document objectBank = XmlUtil.createDocument();
284:
285: Element root = objectBank.createElement("questestinterop");
286: Element ob = objectBank.createElement("objectbank");
287: String objectBankIdent = "object" + Math.random();
288: ob.setAttribute("ident", objectBankIdent);
289: for (int i = 0; i < assessmentIds.length; i++) {
290: Document itemDoc = getAssessment(assessmentIds[i]);
291: Element itemElement = itemDoc.getDocumentElement();
292: Node itemImport = objectBank.importNode(itemElement, true);
293: ob.appendChild(itemImport);
294: }
295: root.appendChild(ob);
296: objectBank.appendChild(root);
297:
298: return objectBank;
299: }
300:
301: /**
302: * Get an item in Document form.
303: * @param itemId the item id
304: * @return the Document with the item data
305: */
306: public Document getItem(String itemId) {
307: Item itemXml = new Item(this .qtiVersion);
308: try {
309: ItemService itemService = new ItemService();
310: QTIHelperFactory factory = new QTIHelperFactory();
311: ItemHelperIfc itemHelper = factory
312: .getItemHelperInstance(this .qtiVersion);
313: ItemDataIfc item = itemService.getItem(itemId);
314: //TypeIfc type = item.getType();
315: Long type = item.getTypeId();
316:
317: if ((TypeIfc.MULTIPLE_CHOICE_SURVEY).equals(type))
318:
319: {
320: String scale = item
321: .getItemMetaDataByLabel(ItemMetaData.SCALENAME);
322: itemXml = itemHelper.readTypeSurveyItem(scale);
323: } else {
324: itemXml = itemHelper.readTypeXMLItem(type);
325: }
326: itemXml.setIdent(item.getItemIdString());
327: itemXml.update(item);
328: return itemXml.getDocument();
329:
330: } catch (Exception ex) {
331: log.error(ex);
332: return null;
333: }
334: }
335:
336: /**
337: *
338: * @param assessmentXml
339: * @param sectionXml
340: * @throws IOException
341: * @throws SAXException
342: * @throws ParserConfigurationException
343: */
344: private void addSection(Assessment assessmentXml, Section sectionXml)
345: throws IOException, SAXException,
346: ParserConfigurationException {
347: ax.addElement(assessmentXml.getDocument(),
348: "questestinterop/assessment", sectionXml.getDocument()
349: .getDocumentElement());
350: }
351:
352: /**
353: * Get an InputStream to an unpopulated section XML from file system.
354: * @return InputStream to an unpopulated section XML
355: */
356: public InputStream getBlankSectionTemplateFileStream() {
357: InputStream is = ax.getTemplateInputStream(ax.SECTION);
358: return is;
359: }
360:
361: /**
362: * Pull apart object bank into multiple assessments
363: * @param objectBank
364: * @return an array of AssesmentFacades
365: */
366: public AssessmentFacade[] createMultipleImportedAssessments(
367: Document objectBank) {
368: Document[] docs = getDocumentsFromObjectBankDoc(objectBank,
369: "assessment");
370: return createMultipleImportedAssessments(docs);
371: }
372:
373: /**
374: * Pull apart object bank based on elementName
375: * @param objectBank
376: * @param elementName e.g. "assessment", "item", etc.
377: * @return
378: */
379: private Document[] getDocumentsFromObjectBankDoc(
380: Document objectBank, String elementName) {
381: Document[] documents = null;
382: // Get the matching elements
383: NodeList nodeList = objectBank.getElementsByTagName("//"
384: + elementName);
385:
386: int numDocs = nodeList.getLength();
387: if (numDocs == 0) {
388: return null;
389: }
390:
391: documents = new Document[numDocs];
392: for (int i = 0; i < numDocs; i++) {
393: Node node = (Node) nodeList.item(i);
394: Document objectDoc = XmlUtil.createDocument();
395: Node importNode = objectDoc.importNode(node, true);
396: objectDoc.appendChild(importNode);
397: documents[i] = objectDoc;
398: }
399:
400: return documents;
401: }
402:
403: /**
404: * Import multiple assessment documents in QTI format, extract & persist.
405: * @param objectBank
406: * @return an array of AssesmentFacades
407: */
408: public AssessmentFacade[] createMultipleImportedAssessments(
409: Document[] documents) {
410: AssessmentFacade[] assessments = new AssessmentFacade[documents.length];
411: for (int i = 0; i < documents.length; i++) {
412: assessments[i] = createImportedAssessment(documents[i]);
413: }
414: return assessments;
415: }
416:
417: /**
418: * Import an assessment XML document in QTI format, extract & persist the data.
419: * @param document the assessment XML document in QTI format
420: * @return a persisted assessment
421: */
422: public AssessmentFacade createImportedAssessment(Document document) {
423: return createImportedAssessment(document, null);
424: }
425:
426: public AssessmentFacade createImportedAssessment(Document document,
427: String unzipLocation) {
428: return createImportedAssessment(document, unzipLocation, null);
429: }
430:
431: /**
432: * Import an assessment XML document in QTI format, extract & persist the data.
433: * @param document the assessment XML document in QTI format
434: * @return a persisted assessment
435: */
436: public AssessmentFacade createImportedAssessment(Document document,
437: String unzipLocation, String templateId) {
438: AssessmentFacade assessment = null;
439:
440: AssessmentService assessmentService = new AssessmentService();
441: try {
442: // we need to know who we are
443: String me = AgentFacade.getAgentString();
444:
445: // create the assessment
446: ExtractionHelper exHelper = new ExtractionHelper(
447: this .qtiVersion);
448: exHelper.setUnzipLocation(unzipLocation);
449: ItemService itemService = new ItemService();
450: Assessment assessmentXml = new Assessment(document);
451: Map assessmentMap = exHelper.mapAssessment(assessmentXml);
452: String description = (String) assessmentMap
453: .get("description");
454: String title = (String) assessmentMap.get("title");
455: assessment = assessmentService
456: .createAssessmentWithoutDefaultSection(title,
457: exHelper.makeFCKAttachment(description),
458: null, templateId);
459:
460: // now make sure we have a unique name for the assessment
461: String baseId = assessment.getAssessmentBaseId().toString();
462: boolean notUnique = !assessmentService
463: .assessmentTitleIsUnique(baseId, title, false);
464:
465: if (notUnique) {
466: synchronized (title) {
467: log
468: .debug("Assessment " + title
469: + " is not unique.");
470: int count = 0; // alternate exit condition
471:
472: while (notUnique) {
473: title = exHelper.renameDuplicate(title);
474: log.debug("renameDuplicate(title): " + title);
475: assessment.setTitle(title);
476: notUnique = !assessmentService
477: .assessmentTitleIsUnique(baseId, title,
478: false);
479: if (count++ > 99)
480: break;// exit condition in case bug is introduced
481: }
482: }
483: }
484:
485: // update the remaining assessment properties
486: exHelper.updateAssessment(assessment, assessmentMap);
487:
488: // make sure required fields are set
489: assessment.setCreatedBy(me);
490: assessment.setCreatedDate(assessment.getCreatedDate());
491: assessment.setLastModifiedBy(me);
492: assessment.setLastModifiedDate(assessment.getCreatedDate());
493: assessment.setTypeId(TypeIfc.QUIZ);
494: assessment.setStatus(new Integer(1));
495:
496: // process each section and each item within each section
497: List sectionList = exHelper
498: .getSectionXmlList(assessmentXml);
499: int sectionListSize = sectionList.size();
500: log.debug("sections=" + sectionListSize);
501:
502: for (int sec = 0; sec < sectionListSize; sec++) // for each section...
503: {
504: Section sectionXml = (Section) sectionList.get(sec);
505: Map sectionMap = exHelper.mapSection(sectionXml);
506: // create the assessment section
507: SectionFacade section = assessmentService.addSection(""
508: + assessment.getAssessmentId());
509: exHelper.updateSection(section, sectionMap);
510: // make sure we are the creator
511: section.setCreatedBy(me);
512: section.setCreatedDate(assessment.getCreatedDate());
513: section.setLastModifiedBy(me);
514: section
515: .setLastModifiedDate(assessment
516: .getCreatedDate());
517: section.setTypeId(TypeIfc.DEFAULT_SECTION);
518: section.setStatus(new Integer(1));
519: section.setSequence(new Integer(sec + 1));
520:
521: List itemList = exHelper.getItemXmlList(sectionXml);
522: for (int itm = 0; itm < itemList.size(); itm++) // for each item
523: {
524: log.debug("items=" + itemList.size());
525: Item itemXml = (Item) itemList.get(itm);
526: Map itemMap = exHelper.mapItem(itemXml);
527:
528: // lydia debugging
529: if (itemMap != null && itemMap.keySet() != null) {
530: Iterator iter = itemMap.keySet().iterator();
531:
532: while (iter.hasNext()) {
533:
534: String label = (String) iter.next();
535: String value = "";
536: if (itemMap.get(label) != null) {
537: value = (String) itemMap.get(label)
538: .toString();
539: log.debug("get Label: " + label
540: + ", Value: " + value);
541: }
542:
543: }
544: }
545: // end lydia
546:
547: ItemFacade item = new ItemFacade();
548: exHelper.updateItem(item, itemMap);
549: // make sure required fields are set
550: item.setCreatedBy(me);
551: item.setCreatedDate(assessment.getCreatedDate());
552: item.setLastModifiedBy(me);
553: item.setLastModifiedDate(assessment
554: .getCreatedDate());
555: item.setStatus(ItemDataIfc.ACTIVE_STATUS);
556: // assign the next sequence number
557: item.setSequence(new Integer(itm + 1));
558: // add item to section
559: item.setSection(section); // one to many
560: // update metadata with PARTID
561: item.addItemMetaData(ItemMetaData.PARTID, section
562: .getSectionId().toString());
563:
564: // Item Attachment
565: exHelper.makeItemAttachmentSet(item);
566:
567: section.addItem(item); // many to one
568: itemService.saveItem(item);
569: } // ... end for each item
570:
571: // Section Attachment
572: exHelper.makeSectionAttachmentSet(section, sectionMap);
573:
574: assessmentService.saveOrUpdateSection(section);
575: } // ... end for each section
576:
577: // and add ip address restriction, if any
578: String allowIp = assessment
579: .getAssessmentMetaDataByLabel("ALLOW_IP");
580: //log.info("allowIp: " + allowIp);
581:
582: if (allowIp != null
583: && !allowIp.trim().equalsIgnoreCase("null")) {
584: //log.info("NOT NULL: " + allowIp);
585: exHelper.makeSecuredIPAddressSet(assessment, allowIp);
586: }
587:
588: // Assessment Attachment
589: exHelper.makeAssessmentAttachmentSet(assessment);
590:
591: assessmentService.saveAssessment(assessment);
592: return assessment;
593: } catch (Exception e) {
594: log.error(e.getMessage(), e);
595: assessmentService.removeAssessment(assessment
596: .getAssessmentId().toString());
597: throw new RuntimeException(e);
598: }
599: }
600:
601: /**
602: * Import an assessment XML document in QTI format, extract & persist the data.
603: * import process assumes assessment structure, not objectbank or itembank
604: * @param document the assessment XML document in QTI format
605: * @return a persisted assessment
606: */
607: public QuestionPoolFacade createImportedQuestionPool(
608: Document document) {
609: QuestionPoolFacade questionpool = new QuestionPoolFacade();
610: QuestionPoolService questionPoolService = new QuestionPoolService();
611:
612: try {
613: // identify user to assign as question pool owner
614: String me = AgentFacade.getAgentString();
615:
616: // create the questionpool as an assessment
617: ExtractionHelper exHelper = new ExtractionHelper(
618: this .qtiVersion);
619: ItemService itemService = new ItemService();
620: Assessment assessmentXml = new Assessment(document);
621: Map assessmentMap = exHelper.mapAssessment(assessmentXml);
622: String title = (String) assessmentMap.get("title");
623:
624: // save questionpool with required info only at this point
625: questionpool.setOwnerId(me);
626: questionpool.setTitle(title);
627: questionpool.setLastModifiedById(me);
628: questionpool
629: .setAccessTypeId(QuestionPoolFacade.ACCESS_DENIED); // set as default
630: questionpool = questionPoolService.savePool(questionpool);
631: // update the remaining questionpool properties
632: exHelper.updateQuestionPool(questionpool, assessmentMap);
633:
634: // now make sure we have a unique name for the question pool
635: String baseId = questionpool.getQuestionPoolId().toString();
636: boolean isUnique = questionPoolService.poolIsUnique(baseId,
637: title, "0", me);
638:
639: // if the title is not unique, increment with a number per renameDuplicate()
640: if (!isUnique) {
641: synchronized (title) {
642: log.debug("Questionpool " + title
643: + " is not unique.");
644: int count = 0; // alternate exit condition
645:
646: while (!isUnique) {
647: title = exHelper.renameDuplicate(title);
648: log.debug("renameDuplicate(title): " + title);
649: questionpool.setTitle(title);
650: //recheck to confirm that new title is not a dplicate too
651: isUnique = questionPoolService.poolIsUnique(
652: baseId, title, "0", me);
653: if (count++ > 99)
654: break;// exit condition in case bug is introduced
655: }
656: }
657: }
658:
659: // process each section and each item within assessment each section
660: List sectionList = exHelper
661: .getSectionXmlList(assessmentXml);
662: int sectionListSize = sectionList.size();
663: int sec = sectionListSize - 1;
664: log.debug("sections=" + sectionListSize);
665:
666: // initialize setQuestionPoolItems so items can be added
667: Set itemSet = new HashSet();
668: questionpool.setQuestionPoolItems(itemSet);
669:
670: // use case for single section
671: // most common for Respondus & BB migrations
672: if (sectionListSize == 1) {
673: Section sectionXml = (Section) sectionList.get(sec);
674: Map sectionMap = exHelper.mapSection(sectionXml);
675: // for single section, do not create subpool
676:
677: List itemList = exHelper.getItemXmlList(sectionXml);
678: for (int itm = 0; itm < itemList.size(); itm++) // for each item
679: {
680: log.debug("items=" + itemList.size());
681: Item itemXml = (Item) itemList.get(itm);
682: Map itemMap = exHelper.mapItem(itemXml);
683:
684: ItemFacade item = new ItemFacade();
685: exHelper.updateItem(item, itemMap);
686: // make sure required fields are set
687: item.setCreatedBy(me);
688: item.setCreatedDate(questionpool.getLastModified());
689: item.setLastModifiedBy(me);
690: item.setLastModifiedDate(questionpool
691: .getLastModified());
692: item.setStatus(ItemDataIfc.ACTIVE_STATUS);
693: itemService.saveItem(item);
694:
695: QuestionPoolItemData questionPoolItem = new QuestionPoolItemData();
696: questionPoolItem.setQuestionPoolId(questionpool
697: .getQuestionPoolId());
698: questionPoolItem.setItemId(item.getItemIdString());
699: questionpool
700: .addQuestionPoolItem((QuestionPoolItemIfc) questionPoolItem);
701:
702: } // ... end for each item
703:
704: }
705: // need error message if more than one section, for now
706:
707: // update the questionpoool with all sections and items
708: questionPoolService.savePool(questionpool);
709:
710: return questionpool;
711: } catch (Exception e) {
712: log.error(e.getMessage(), e);
713: Tree tree = null;
714: questionPoolService.deletePool(questionpool
715: .getQuestionPoolId(), AgentFacade.getAgentString(),
716: tree);
717: throw new RuntimeException(e);
718: }
719: }
720:
721: /**
722: * @deprecated
723: * Import an item XML document in QTI format, extract & persist the data.
724: * @param document the item XML document in QTI format
725: * @return a persisted item
726: */
727: public ItemFacade createImportedItem(Document document) {
728: ItemFacade item = new ItemFacade();
729:
730: try {
731: // create the item
732: ExtractionHelper exHelper = new ExtractionHelper(
733: this .qtiVersion);
734: Item itemXml = new Item(document, QTIVersion.VERSION_1_2);
735: Map itemMap = exHelper.mapItem(itemXml);
736: exHelper.updateItem(item, itemMap);
737: ItemService itemService = new ItemService();
738: itemService.saveItem(item);
739: } catch (Exception e) {
740: log.error(e.getMessage(), e);
741: }
742:
743: return item;
744: }
745:
746: /**
747: * Create an XmlStringBuffer (base class for A,S,I XML classes)
748: *
749: * @param inputStream the input stram
750: *
751: * @return an XmlStringBuffer (this is the base class for A,S,I XML classes)
752: */
753: public XmlStringBuffer readXMLDocument(InputStream inputStream) {
754: Document document = null;
755: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
756: .newInstance();
757: // builderFactory.setNamespaceAware(true);
758: try {
759: DocumentBuilder documentBuilder = builderFactory
760: .newDocumentBuilder();
761: document = documentBuilder.parse(inputStream);
762: } catch (ParserConfigurationException e) {
763: log.error(e.getMessage(), e);
764: } catch (SAXException e) {
765: log.error(e.getMessage(), e);
766: } catch (IOException e) {
767: log.error(e.getMessage(), e);
768: }
769:
770: return new XmlStringBuffer(document);
771: }
772:
773: /**
774: * Helper method.
775: * @param inputStr
776: * @param delimiter
777: * @return
778: */
779: public ArrayList changeDelimitedStringtoArray(String inputStr,
780: String delimiter) {
781: ArrayList selectedList = new ArrayList();
782: if (inputStr != null && inputStr.trim().length() > 0) {
783: StringTokenizer st = new StringTokenizer(inputStr,
784: delimiter);
785: if (st != null) {
786:
787: while (st.hasMoreTokens()) {
788: selectedList.add(st.nextToken());
789: }
790: } else {
791: selectedList.add(inputStr);
792: }
793: }
794: return selectedList;
795: }
796:
797: public int getQtiVersion() {
798: return qtiVersion;
799: }
800:
801: public void setQtiVersion(int qtiVersion) {
802: this.qtiVersion = qtiVersion;
803: }
804: }
|