Index: lams_central/src/java/org/lamsfoundation/lams/authoring/template/Assessment.java =================================================================== diff -u -r8be457696d7f17c6da2e89704fe7e128f1f8ea91 -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_central/src/java/org/lamsfoundation/lams/authoring/template/Assessment.java (.../Assessment.java) (revision 8be457696d7f17c6da2e89704fe7e128f1f8ea91) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/template/Assessment.java (.../Assessment.java) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -23,6 +23,7 @@ package org.lamsfoundation.lams.authoring.template; +import java.io.IOException; import java.text.MessageFormat; import java.util.Comparator; import java.util.List; @@ -31,6 +32,7 @@ import java.util.TreeSet; import org.lamsfoundation.lams.rest.RestTags; +import org.lamsfoundation.lams.util.JsonUtil; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; @@ -57,6 +59,7 @@ boolean multipleAnswersAllowed = false; // only used if type == 1 Set answers = null; // only used if type == 1 String uuid = null; // used when QTI gets imported and it contains QB question UUID + List learningOutcomes; public void setType(short type) { this.type = type; @@ -122,6 +125,14 @@ this.multipleAnswersAllowed = multipleAnswersAllowed; } + public List getLearningOutcomes() { + return learningOutcomes; + } + + public void setLearningOutcomes(List learningOutcomes) { + this.learningOutcomes = learningOutcomes; + } + public String getUuid() { return uuid; } @@ -130,7 +141,7 @@ this.uuid = uuid; } - public ObjectNode getAsObjectNode(int displayOrder) { + public ObjectNode getAsObjectNode(int displayOrder) throws IOException { ObjectNode json = JsonNodeFactory.instance.objectNode(); json.put(RestTags.QUESTION_TITLE, title != null ? title : ""); json.put(RestTags.QUESTION_TEXT, text != null ? text : ""); @@ -151,6 +162,9 @@ } else { json.put("type", ASSESSMENT_QUESTION_TYPE_ESSAY); } + if (learningOutcomes != null && !learningOutcomes.isEmpty()) { + json.set(RestTags.LEARNING_OUTCOMES, JsonUtil.readArray(learningOutcomes)); + } return json; } Index: lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/LdTemplateController.java =================================================================== diff -u -r59044e7541aada72fb2b0c82589b55c61379106a -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/LdTemplateController.java (.../LdTemplateController.java) (revision 59044e7541aada72fb2b0c82589b55c61379106a) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/LdTemplateController.java (.../LdTemplateController.java) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -1462,6 +1462,8 @@ } assessment.setDefaultGrade(defaultGrade); + + assessment.setLearningOutcomes(question.getLearningOutcomes()); } return assessments; Index: lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/TBLTemplateController.java =================================================================== diff -u -r59044e7541aada72fb2b0c82589b55c61379106a -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/TBLTemplateController.java (.../TBLTemplateController.java) (revision 59044e7541aada72fb2b0c82589b55c61379106a) +++ lams_central/src/java/org/lamsfoundation/lams/authoring/template/web/TBLTemplateController.java (.../TBLTemplateController.java) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -22,10 +22,12 @@ */ package org.lamsfoundation.lams.authoring.template.web; +import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.Enumeration; import java.util.List; @@ -197,7 +199,6 @@ // Application Exercises - multiple exercises with gates between each exercise. There may also be a grouped // notebook after an exercise if indicated by the user. Each Application Exercise will have one or more questions. // Start a new row so that they group nicely together - int displayOrder = 1; int noticeboardCount = 0; if (data.useApplicationExercises) { @@ -253,8 +254,6 @@ activities.add(createNoticeboardActivity(maxUIID, order++, currentActivityPosition, aeNoticeboardContentId, data.contentFolderID, groupingUIID, null, null, notebookTitle)); } - - displayOrder++; } } @@ -283,7 +282,6 @@ data.getText("boilerplate.peerreview.instructions"), null, criterias); activities.add(createPeerReviewActivity(maxUIID, order++, currentActivityPosition, prtoolContentId, data.contentFolderID, groupingUIID, null, null, peerReviewTitle)); - displayOrder++; currentActivityPosition = calcPositionNextRight(currentActivityPosition); } } @@ -439,20 +437,23 @@ Integer questionDisplayOrder = Integer.valueOf(name.substring(questionOffset, optionIndex)); Integer optionDisplayOrder = Integer.valueOf(name.substring(optionIndex + 6)); processTestQuestion(name, null, null, questionDisplayOrder, null, optionDisplayOrder, - getTrimmedString(request, name, true)); + getTrimmedString(request, name, true), null); } else { int titleIndex = name.indexOf("title"); if (titleIndex > 0) { // question1title Integer questionDisplayOrder = Integer .valueOf(name.substring(questionOffset, titleIndex)); + // get all learning outcomes straight away instead of iterating over them + String[] learningOutcomes = request + .getParameterValues("question" + questionDisplayOrder + "learningOutcome"); processTestQuestion(name, null, getTrimmedString(request, name, false), - questionDisplayOrder, null, null, null); - } else if (name.indexOf("uuid") < 0) { + questionDisplayOrder, null, null, null, learningOutcomes); + } else if (name.indexOf("uuid") < 0 && name.indexOf("learningOutcome") < 0) { Integer questionDisplayOrder = Integer.valueOf(name.substring(questionOffset)); processTestQuestion(name, getTrimmedString(request, name, true), null, questionDisplayOrder, getTrimmedString(request, "question" + questionDisplayOrder + "uuid", false), - null, null); + null, null, null); } } } @@ -554,6 +555,7 @@ String questionTitle = getTrimmedString(request, assessmentPrefix + "title", true); String questionUuid = getTrimmedString(request, assessmentPrefix + "uuid", false); String markAsString = getTrimmedString(request, assessmentPrefix + "mark", false); + String[] learningOutcomes = request.getParameterValues(assessmentPrefix + "learningOutcome"); Assessment assessment = new Assessment(); if (questionText != null) { assessment.setTitle(questionTitle); @@ -598,6 +600,11 @@ } } } + + if (learningOutcomes != null && learningOutcomes.length > 0) { + assessment.setLearningOutcomes(Arrays.asList(learningOutcomes)); + } + applicationExercises.put(i, assessment); } } @@ -632,7 +639,7 @@ } void processTestQuestion(String name, String questionText, String questionTitle, Integer questionDisplayOrder, - String questionUuid, Integer optionDisplayOrder, String optionText) { + String questionUuid, Integer optionDisplayOrder, String optionText, String[] learningOutcomes) { ObjectNode question = testQuestions.get(questionDisplayOrder); if (question == null) { @@ -667,6 +674,15 @@ ((ArrayNode) question.get(RestTags.ANSWERS)).add(newOption); } + if (learningOutcomes != null && learningOutcomes.length > 0) { + try { + ArrayNode learningOutcomesJSON = JsonUtil.readArray(learningOutcomes); + question.set(RestTags.LEARNING_OUTCOMES, learningOutcomesJSON); + } catch (IOException e) { + log.error("Error while processing learning outcomes for question: " + + question.get(RestTags.QUESTION_TITLE)); + } + } } void updateCorrectAnswers(TreeMap correctAnswers) { Index: lams_central/web/authoring/template/tool/assessmentQTI.jsp =================================================================== diff -u -r4c2d1f37b92435907ec4ce23cb635a7cd9e4161e -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_central/web/authoring/template/tool/assessmentQTI.jsp (.../assessmentQTI.jsp) (revision 4c2d1f37b92435907ec4ce23cb635a7cd9e4161e) +++ lams_central/web/authoring/template/tool/assessmentQTI.jsp (.../assessmentQTI.jsp) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -17,6 +17,10 @@ <%@ include file="../tool/assessment.jsp" %> + + + + ${currentNumber + 1} Index: lams_central/web/authoring/template/tool/mcquestionQTI.jsp =================================================================== diff -u -r4c2d1f37b92435907ec4ce23cb635a7cd9e4161e -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_central/web/authoring/template/tool/mcquestionQTI.jsp (.../mcquestionQTI.jsp) (revision 4c2d1f37b92435907ec4ce23cb635a7cd9e4161e) +++ lams_central/web/authoring/template/tool/mcquestionQTI.jsp (.../mcquestionQTI.jsp) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -10,8 +10,13 @@
<%@ include file="../tool/mcquestion.jsp" %> + + + +
+ ${currentNumber + 1} Index: lams_common/src/java/org/lamsfoundation/lams/rest/RestTags.java =================================================================== diff -u -r4c5a620700d152367d81a3ad8cf1d0f0b94f86ac -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_common/src/java/org/lamsfoundation/lams/rest/RestTags.java (.../RestTags.java) (revision 4c5a620700d152367d81a3ad8cf1d0f0b94f86ac) +++ lams_common/src/java/org/lamsfoundation/lams/rest/RestTags.java (.../RestTags.java) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -63,5 +63,6 @@ public static String ANSWER_TEXT = "answerText"; public static String DISPLAY_ORDER = "displayOrder"; public static String CORRECT = "correct"; + public static String LEARNING_OUTCOMES = "learningOutcomes"; } Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml =================================================================== diff -u -r646ad3f8f14c7577e5a1e863f31dacca0c38e860 -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml (.../assessmentApplicationContext.xml) (revision 646ad3f8f14c7577e5a1e863f31dacca0c38e860) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/assessmentApplicationContext.xml (.../assessmentApplicationContext.xml) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -125,6 +125,9 @@ + + + Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== diff -u -r36716004da333fcc5eb3f776801e3e5278719fd7 -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision 36716004da333fcc5eb3f776801e3e5278719fd7) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java (.../AssessmentServiceImpl.java) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -69,6 +69,9 @@ import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.outcome.Outcome; +import org.lamsfoundation.lams.outcome.OutcomeMapping; +import org.lamsfoundation.lams.outcome.service.IOutcomeService; import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; @@ -183,6 +186,8 @@ private IQbService qbService; + private IOutcomeService outcomeService; + // ******************************************************************************* // Service method // ******************************************************************************* @@ -3357,6 +3362,10 @@ this.qbService = qbService; } + public void setOutcomeService(IOutcomeService outcomeService) { + this.outcomeService = outcomeService; + } + public AssessmentOutputFactory getAssessmentOutputFactory() { return assessmentOutputFactory; } @@ -3421,6 +3430,7 @@ * * @throws IOException */ + @SuppressWarnings("unchecked") @Override public void createRestToolContent(Integer userID, Long toolContentID, ObjectNode toolContentJSON) throws IOException { @@ -3619,6 +3629,28 @@ throw new IllegalArgumentException( "Implement other Question Bank modification levels in Assessment tool"); } + } else { + // only process learning outcomes when this is not a modification, i.e. it is a new question + ArrayNode learningOutcomesJSON = JsonUtil.optArray(questionJSONData, RestTags.LEARNING_OUTCOMES); + if (learningOutcomesJSON != null && learningOutcomesJSON.size() > 0) { + for (JsonNode learningOutcomeJSON : learningOutcomesJSON) { + String learningOutcomeText = learningOutcomeJSON.asText(); + learningOutcomeText = learningOutcomeText.strip(); + List learningOutcomes = userManagementService.findByProperty(Outcome.class, "name", + learningOutcomeText); + Outcome learningOutcome = null; + if (learningOutcomes.isEmpty()) { + learningOutcome = outcomeService.createOutcome(learningOutcomeText, userID); + } else { + learningOutcome = learningOutcomes.get(0); + } + + OutcomeMapping outcomeMapping = new OutcomeMapping(); + outcomeMapping.setOutcome(learningOutcome); + outcomeMapping.setQbQuestionId(qbQuestion.getQuestionId()); + userManagementService.save(outcomeMapping); + } + } } // Store it back into JSON so Scratchie can read it @@ -3634,7 +3666,7 @@ // all questions need to end up in user's private collection if (addToCollection) { - // qbService.addQuestionToCollection(collection.getUid(), qbQuestion.getQuestionId(), false); + qbService.addQuestionToCollection(collection.getUid(), qbQuestion.getQuestionId(), false); collectionUUIDs.add(uuid); } } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml =================================================================== diff -u -ra05bb8ff92c659cc340b037de664fd0d9b103c96 -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml (.../scratchieApplicationContext.xml) (revision a05bb8ff92c659cc340b037de664fd0d9b103c96) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml (.../scratchieApplicationContext.xml) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -120,6 +120,9 @@ + + + Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== diff -u -r7648a0e2d35287ebf58b7be0128f38369f986cc8 -rd9a9f033cd1e6050279d05ef7cbca24f243ecf6a --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 7648a0e2d35287ebf58b7be0128f38369f986cc8) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision d9a9f033cd1e6050279d05ef7cbca24f243ecf6a) @@ -62,6 +62,9 @@ import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.outcome.Outcome; +import org.lamsfoundation.lams.outcome.OutcomeMapping; +import org.lamsfoundation.lams.outcome.service.IOutcomeService; import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; @@ -114,6 +117,7 @@ import org.lamsfoundation.lams.util.excel.ExcelRow; import org.lamsfoundation.lams.util.excel.ExcelSheet; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -163,6 +167,8 @@ private ILearnerService learnerService; + private IOutcomeService outcomeService; + private ScratchieOutputFactory scratchieOutputFactory; // ******************************************************************************* @@ -2622,6 +2628,10 @@ this.qbService = qbService; } + public void setOutcomeService(IOutcomeService outcomeService) { + this.outcomeService = outcomeService; + } + @Override public String getMessage(String key) { return messageService.getMessage(key); @@ -2666,6 +2676,7 @@ * "questionText", "displayOrder" (Integer) and a ArrayNode "answers". The answers entry should be ArrayNode * containing JSON objects, which in turn must contain "answerText", "displayOrder" (Integer), "correct" (Boolean). */ + @SuppressWarnings("unchecked") @Override public void createRestToolContent(Integer userID, Long toolContentID, ObjectNode toolContentJSON) { @@ -2747,6 +2758,28 @@ } qbQuestion.setQbOptions(newOptions); + + // only process learning outcomes when this is not a modification, i.e. it is a new question + ArrayNode learningOutcomesJSON = JsonUtil.optArray(questionData, RestTags.LEARNING_OUTCOMES); + if (learningOutcomesJSON != null && learningOutcomesJSON.size() > 0) { + for (JsonNode learningOutcomeJSON : learningOutcomesJSON) { + String learningOutcomeText = learningOutcomeJSON.asText(); + learningOutcomeText = learningOutcomeText.strip(); + List learningOutcomes = userManagementService.findByProperty(Outcome.class, "name", + learningOutcomeText); + Outcome learningOutcome = null; + if (learningOutcomes.isEmpty()) { + learningOutcome = outcomeService.createOutcome(learningOutcomeText, userID); + } else { + learningOutcome = learningOutcomes.get(0); + } + + OutcomeMapping outcomeMapping = new OutcomeMapping(); + outcomeMapping.setOutcome(learningOutcome); + outcomeMapping.setQbQuestionId(qbQuestion.getQuestionId()); + userManagementService.save(outcomeMapping); + } + } } else if (collection != null && !collectionUUIDs.contains(uuid)) { addToCollection = true; }