Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java,v diff -u -r1.50 -r1.51 --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java 29 Oct 2014 21:33:17 -0000 1.50 +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/service/AssessmentServiceImpl.java 29 Apr 2015 01:31:17 -0000 1.51 @@ -44,6 +44,9 @@ import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.gradebook.service.IGradebookService; import org.lamsfoundation.lams.learning.service.ILearnerService; @@ -58,6 +61,8 @@ 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.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; import org.lamsfoundation.lams.tool.ToolContentImport102Manager; import org.lamsfoundation.lams.tool.ToolContentManager; import org.lamsfoundation.lams.tool.ToolOutput; @@ -101,14 +106,15 @@ import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.JsonUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.audit.IAuditService; /** * @author Andrey Balan */ public class AssessmentServiceImpl implements IAssessmentService, ToolContentManager, ToolSessionManager, - ToolContentImport102Manager { + ToolContentImport102Manager, ToolRestManager{ private static Logger log = Logger.getLogger(AssessmentServiceImpl.class.getName()); private AssessmentDAO assessmentDao; @@ -1846,4 +1852,185 @@ public void setUserService(IUserManagementService userService) { this.userService = userService; } + + // ****************** REST methods ************************* + + /** + * Rest call to create a new Assessment content. Required fields in toolContentJSON: "title", "instructions", + * "questions", "firstName", "lastName", "lastName", "questions" and "references". + * + * The questions entry should be a JSONArray containing JSON objects, which in turn must contain "questionTitle", + * "questionText", "displayOrder" (Integer), "type" (Integer). If the type is Multiple Choice, Numerical or Matching + * Pairs then a JSONArray "answers" is required. + * + * The answers entry should be JSONArray containing JSON objects, which in turn must contain "answerText" or + * "answerFloat", "displayOrder" (Integer), "grade" (Integer). + * + * The references entry should be a JSONArray containing JSON objects, which in turn must contain "displayOrder" (Integer), + * "questionDisplayOrder" (Integer - to match to the question). It may also have "defaultGrade" (Integer) and "randomQuestion" (Boolean) + */ + @SuppressWarnings("unchecked") + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) + throws JSONException { + + Date updateDate = new Date(); + + Assessment assessment = new Assessment(); + assessment.setContentId(toolContentID); + assessment.setTitle(toolContentJSON.getString(RestTags.TITLE)); + assessment.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); + assessment.setCreated(updateDate); + + assessment.setReflectOnActivity(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + assessment.setReflectInstructions(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, (String) null)); + assessment.setAllowGradesAfterAttempt(JsonUtil.opt(toolContentJSON, "allowGradesAfterAttempt", Boolean.FALSE)); + assessment.setAllowHistoryResponses(JsonUtil.opt(toolContentJSON, "allowHistoryResponses", Boolean.FALSE)); + assessment.setAllowOverallFeedbackAfterQuestion(JsonUtil.opt(toolContentJSON, + "allowOverallFeedbackAfterQuestion", Boolean.FALSE)); + assessment.setAllowQuestionFeedback(JsonUtil.opt(toolContentJSON, "allowQuestionFeedback", Boolean.FALSE)); + assessment.setAllowRightAnswersAfterQuestion(JsonUtil.opt(toolContentJSON, "allowRightAnswersAfterQuestion", + Boolean.FALSE)); + assessment.setAllowWrongAnswersAfterQuestion(JsonUtil.opt(toolContentJSON, "allowWrongAnswersAfterQuestion", + Boolean.FALSE)); + assessment.setAttemptsAllowed(JsonUtil.opt(toolContentJSON, "attemptsAllows", 1)); + assessment.setDefineLater(false); + assessment.setDisplaySummary(JsonUtil.opt(toolContentJSON, "displaySummary", Boolean.FALSE)); + assessment.setNotifyTeachersOnAttemptCompletion(JsonUtil.opt(toolContentJSON, + "notifyTeachersOnAttemptCompletion", Boolean.FALSE)); + assessment.setNumbered(JsonUtil.opt(toolContentJSON, "numbered", Boolean.TRUE)); + assessment.setPassingMark(JsonUtil.opt(toolContentJSON, "passingMark", 0)); + assessment.setQuestionsPerPage(JsonUtil.opt(toolContentJSON, "questionsPerPage", 0)); + assessment.setReflectInstructions(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, "")); + assessment.setReflectOnActivity(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + assessment.setShuffled(JsonUtil.opt(toolContentJSON, "shuffled", Boolean.FALSE)); + assessment.setSubmissionDeadline(JsonUtil.opt(toolContentJSON, "submissionDeadline", (Date) null)); + assessment.setTimeLimit(JsonUtil.opt(toolContentJSON, "timeLimit", 0)); + assessment + .setUseSelectLeaderToolOuput(JsonUtil.opt(toolContentJSON, "useSelectLeaderToolOuput", Boolean.FALSE)); + + if (toolContentJSON.has("overallFeedback")) { + throw new JSONException("Assessment Tool does not support Overall Feedback for REST Authoring. " + + toolContentJSON); + } + + AssessmentUser assessmentUser = getUserByIDAndContent(userID.longValue(), toolContentID); + if (assessmentUser == null) { + assessmentUser = new AssessmentUser(); + assessmentUser.setFirstName(toolContentJSON.getString("firstName")); + assessmentUser.setLastName(toolContentJSON.getString("lastName")); + assessmentUser.setLoginName(toolContentJSON.getString("loginName")); + assessmentUser.setAssessment(assessment); + } + assessment.setCreatedBy(assessmentUser); + + // **************************** Set the question bank ********************* + JSONArray questions = toolContentJSON.getJSONArray("questions"); + Set newQuestionSet = assessment.getQuestions(); // the Assessment constructor will set up the collection + for (int i = 0; i < questions.length(); i++) { + JSONObject questionJSONData = (JSONObject) questions.get(i); + AssessmentQuestion question = new AssessmentQuestion(); + short type = (short) questionJSONData.getInt("type"); + question.setType(type); + question.setTitle(questionJSONData.getString(RestTags.QUESTION_TITLE)); + question.setQuestion(questionJSONData.getString(RestTags.QUESTION_TEXT)); + question.setCreateBy(assessmentUser); + question.setCreateDate(updateDate); + question.setSequenceId(questionJSONData.getInt(RestTags.DISPLAY_ORDER)); + + question.setAllowRichEditor(JsonUtil.opt(questionJSONData, RestTags.ALLOW_RICH_TEXT_EDITOR, Boolean.FALSE)); + question.setAnswerRequired(JsonUtil.opt(questionJSONData, "answerRequired", Boolean.FALSE)); + question.setCaseSensitive(JsonUtil.opt(questionJSONData, "caseSensitive", Boolean.FALSE)); + question.setCorrectAnswer(JsonUtil.opt(questionJSONData, "correctAnswer", Boolean.FALSE)); + question.setDefaultGrade(JsonUtil.opt(questionJSONData, "defaultGrade", 1)); + question.setFeedback(JsonUtil.opt(questionJSONData, "feedback", (String) null)); + question.setFeedbackOnCorrect(JsonUtil.opt(questionJSONData, "feedbackOnCorrect", (String) null)); + question.setFeedbackOnIncorrect(JsonUtil.opt(questionJSONData, "feedbackOnIncorrect", (String) null)); + question.setFeedbackOnPartiallyCorrect(JsonUtil.opt(questionJSONData, "feedbackOnPartiallyCorrect", + (String) null)); + question.setGeneralFeedback(JsonUtil.opt(questionJSONData, "generalFeedback", "")); + question.setMaxWordsLimit(JsonUtil.opt(questionJSONData, "maxWordsLimit", 0)); + question.setMinWordsLimit(JsonUtil.opt(questionJSONData, "minWordsLimit", 0)); + question.setMultipleAnswersAllowed(JsonUtil.opt(questionJSONData, "multipleAnswersAllowed", Boolean.FALSE)); + question.setPenaltyFactor(Float.parseFloat(JsonUtil.opt(questionJSONData, "penaltyFactor", "0.0"))); + // question.setUnits(units); Needed for numerical type question + + if (type == AssessmentConstants.QUESTION_TYPE_MATCHING_PAIRS + || type == AssessmentConstants.QUESTION_TYPE_MULTIPLE_CHOICE + || type == AssessmentConstants.QUESTION_TYPE_NUMERICAL) { + + if (!questionJSONData.has(RestTags.ANSWERS)) + throw new JSONException("REST Authoring is missing answers for a question of type " + type + + ". Data:" + toolContentJSON); + + Set optionList = new LinkedHashSet(); + JSONArray optionsData = (JSONArray) questionJSONData.getJSONArray(RestTags.ANSWERS); + for (int j = 0; j < optionsData.length(); j++) { + JSONObject answerData = (JSONObject) optionsData.get(j); + AssessmentQuestionOption option = new AssessmentQuestionOption(); + option.setSequenceId(answerData.getInt(RestTags.DISPLAY_ORDER)); + option.setGrade(Float.parseFloat(answerData.getString("grade"))); + option.setAcceptedError(Float.parseFloat(JsonUtil.opt(answerData, "acceptedError", "0.0"))); + option.setFeedback(JsonUtil.opt(answerData, "feedback", (String) null)); + option.setOptionString(JsonUtil.opt(answerData, RestTags.ANSWER_TEXT, (String) null)); + option.setOptionFloat(Float.parseFloat(JsonUtil.opt(answerData, "answerFloat", "0.0"))); + // option.setQuestion(question); can't find the use for this field yet! + optionList.add(option); + } + question.setOptions(optionList); + } + + checkType(question.getType()); + newQuestionSet.add(question); + } + + // **************************** Now set up the references to the questions in the bank ********************* + JSONArray references = toolContentJSON.getJSONArray("references"); + Set newReferenceSet = assessment.getQuestionReferences(); // the Assessment constructor will set up the + // collection + for (int i = 0; i < references.length(); i++) { + JSONObject referenceJSONData = (JSONObject) references.get(i); + QuestionReference reference = new QuestionReference(); + reference.setType((short) 0); + reference.setDefaultGrade(JsonUtil.opt(referenceJSONData, "defaultGrade", 1)); + reference.setSequenceId(referenceJSONData.getInt(RestTags.DISPLAY_ORDER)); + AssessmentQuestion matchingQuestion = matchQuestion(newQuestionSet, + referenceJSONData.getInt("questionDisplayOrder")); + if (matchingQuestion == null) { + throw new JSONException("Unable to find matching question for displayOrder " + + referenceJSONData.get("questionDisplayOrder") + ". Data:" + toolContentJSON); + } + reference.setQuestion(matchingQuestion); + reference.setRandomQuestion(JsonUtil.opt(referenceJSONData, "randomQuestion", Boolean.FALSE)); + reference.setTitle(null); + newReferenceSet.add(reference); + } + + saveOrUpdateAssessment(assessment); + + } + + // find the question that matches this sequence id - used by the REST calls only. + AssessmentQuestion matchQuestion(Set newReferenceSet, Integer displayOrder) { + if ( displayOrder != null ) { + for ( AssessmentQuestion question : newReferenceSet ) { + if ( displayOrder.equals(question.getSequenceId()) ) + return question; + } + } + return null; + } + // TODO Implement REST support for all types and then remove checkType method + void checkType(short type) throws JSONException { + if (type != AssessmentConstants.QUESTION_TYPE_ESSAY) { + throw new JSONException( + "Assessment Tool does not support REST Authoring for anything but Essay Type. Found type " + type); + } + // public static final short QUESTION_TYPE_MULTIPLE_CHOICE = 1; + // public static final short QUESTION_TYPE_MATCHING_PAIRS = 2; + // public static final short QUESTION_TYPE_SHORT_ANSWER = 3; + // public static final short QUESTION_TYPE_NUMERICAL = 4; + // public static final short QUESTION_TYPE_TRUE_FALSE = 5; + // public static final short QUESTION_TYPE_ORDERING = 7; + } } Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/ResourceServiceImpl.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/ResourceServiceImpl.java,v diff -u -r1.78 -r1.79 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/ResourceServiceImpl.java 16 Apr 2015 02:07:14 -0000 1.78 +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/ResourceServiceImpl.java 29 Apr 2015 01:35:13 -0000 1.79 @@ -70,6 +70,7 @@ 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.rest.RestTags; import org.lamsfoundation.lams.rest.ToolRestManager; import org.lamsfoundation.lams.tool.ToolContentImport102Manager; import org.lamsfoundation.lams.tool.ToolContentManager; @@ -1362,17 +1363,17 @@ Resource resource = new Resource(); resource.setContentId(toolContentID); - resource.setTitle(toolContentJSON.getString("title")); - resource.setInstructions(toolContentJSON.getString("instructions")); + resource.setTitle(toolContentJSON.getString(RestTags.TITLE)); + resource.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); resource.setCreated(updateDate); resource.setAllowAddFiles(JsonUtil.opt(toolContentJSON, "allowAddFiles", Boolean.FALSE)); resource.setAllowAddUrls(JsonUtil.opt(toolContentJSON, "allowAddUrls", Boolean.FALSE)); - resource.setLockWhenFinished(JsonUtil.opt(toolContentJSON, "lockWhenFinished", Boolean.FALSE)); + resource.setLockWhenFinished(JsonUtil.opt(toolContentJSON, RestTags.LOCK_WHEN_FINISHED, Boolean.FALSE)); resource.setMiniViewResourceNumber(JsonUtil.opt(toolContentJSON, "minViewResourceNumber", 0)); - resource.setNotifyTeachersOnAssigmentSumbit(JsonUtil.opt(toolContentJSON, "notifyTeachersOnAssigmentSumbit", Boolean.FALSE)); - resource.setReflectOnActivity(JsonUtil.opt(toolContentJSON, "reflectOnActivity", Boolean.FALSE)); - resource.setReflectInstructions(JsonUtil.opt(toolContentJSON, "reflectInstructions", (String)null)); + resource.setNotifyTeachersOnAssigmentSumbit(JsonUtil.opt(toolContentJSON, "notifyTeachersOnAssigmentSubmit", Boolean.FALSE)); + resource.setReflectOnActivity(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + resource.setReflectInstructions(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, (String)null)); resource.setRunAuto(JsonUtil.opt(toolContentJSON, "runAuto", Boolean.FALSE)); resource.setContentInUse(false); @@ -1403,7 +1404,7 @@ item.setComplete(false); item.setCreateByAuthor(true); item.setHide(false); - item.setOrderId(i+1); + item.setOrderId(itemData.getInt(RestTags.DISPLAY_ORDER)); item.setDescription(JsonUtil.opt(itemData, "description", (String)null)); item.setFileName(JsonUtil.opt(itemData, "name", (String)null)); @@ -1428,15 +1429,15 @@ } // TODO files - need to save it somehow, validate the file size, etc. Needed for websites, files & LO + if ( item.getFileName() != null || item.getFileUuid() != null ) + throw new JSONException("Only URLS supported via REST interface currently - files and learning objects are not supported."); + itemList.add(item); } resource.setResourceItems(itemList); saveOrUpdateResource(resource); - // ******************************* - // TODO - investigate - // file attachments } } \ No newline at end of file Index: lams_tool_leader/.classpath =================================================================== RCS file: /usr/local/cvsroot/lams_tool_leader/.classpath,v diff -u -r1.1 -r1.2 --- lams_tool_leader/.classpath 8 Jan 2014 20:13:46 -0000 1.1 +++ lams_tool_leader/.classpath 29 Apr 2015 01:35:10 -0000 1.2 @@ -20,5 +20,6 @@ + Index: lams_tool_leader/src/java/org/lamsfoundation/lams/tool/leaderselection/service/LeaderselectionService.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_leader/src/java/org/lamsfoundation/lams/tool/leaderselection/service/LeaderselectionService.java,v diff -u -r1.6 -r1.7 --- lams_tool_leader/src/java/org/lamsfoundation/lams/tool/leaderselection/service/LeaderselectionService.java 6 Jun 2014 16:42:47 -0000 1.6 +++ lams_tool_leader/src/java/org/lamsfoundation/lams/tool/leaderselection/service/LeaderselectionService.java 29 Apr 2015 01:35:10 -0000 1.7 @@ -24,12 +24,15 @@ package org.lamsfoundation.lams.tool.leaderselection.service; +import java.util.Date; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.SortedMap; import org.apache.log4j.Logger; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; import org.lamsfoundation.lams.contentrepository.AccessDeniedException; import org.lamsfoundation.lams.contentrepository.ICredentials; import org.lamsfoundation.lams.contentrepository.ITicket; @@ -44,6 +47,8 @@ import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; import org.lamsfoundation.lams.tool.ToolContentImport102Manager; import org.lamsfoundation.lams.tool.ToolContentManager; import org.lamsfoundation.lams.tool.ToolOutput; @@ -64,6 +69,7 @@ import org.lamsfoundation.lams.tool.leaderselection.util.LeaderselectionToolContentHandler; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.JsonUtil; /** * An implementation of the ILeaderselectionService interface. @@ -72,7 +78,7 @@ */ public class LeaderselectionService implements ToolSessionManager, ToolContentManager, ILeaderselectionService, - ToolContentImport102Manager { + ToolContentImport102Manager, ToolRestManager { private static Logger logger = Logger.getLogger(LeaderselectionService.class.getName()); @@ -562,4 +568,25 @@ public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { return getLeaderselectionOutputFactory().getSupportedDefinitionClasses(definitionType); } + + // ****************** REST methods ************************* + + /** Rest call to create a new Learner Selection content. Required fields in toolContentJSON: "title", "instructions". + */ + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) throws JSONException { + Date updateDate = new Date(); + + Leaderselection leaderselection = new Leaderselection(); + leaderselection.setToolContentId(toolContentID); + leaderselection.setTitle(toolContentJSON.getString(RestTags.TITLE)); + leaderselection.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); + leaderselection.setCreateBy(userID.longValue()); + leaderselection.setCreateDate(updateDate); + leaderselection.setUpdateDate(updateDate); + leaderselection.setContentInUse(false); + leaderselection.setDefineLater(false); + saveOrUpdateLeaderselection(leaderselection); + } + } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java,v diff -u -r1.56 -r1.57 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java 9 Mar 2015 15:08:20 -0000 1.56 +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java 29 Apr 2015 01:40:23 -0000 1.57 @@ -30,20 +30,26 @@ import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; +import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.gradebook.service.IGradebookService; import org.lamsfoundation.lams.learning.service.ILearnerService; @@ -53,6 +59,8 @@ 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.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; import org.lamsfoundation.lams.tool.ToolContentImport102Manager; import org.lamsfoundation.lams.tool.ToolContentManager; import org.lamsfoundation.lams.tool.ToolOutput; @@ -89,14 +97,15 @@ import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.ExcelCell; +import org.lamsfoundation.lams.util.JsonUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.audit.IAuditService; /** * @author Andrey Balan */ public class ScratchieServiceImpl implements IScratchieService, ToolContentManager, ToolSessionManager, - ToolContentImport102Manager { + ToolContentImport102Manager, ToolRestManager { private static Logger log = Logger.getLogger(ScratchieServiceImpl.class.getName()); private static final ExcelCell[] EMPTY_ROW = new ExcelCell[4]; @@ -1955,4 +1964,76 @@ public void setScratchieOutputFactory(ScratchieOutputFactory scratchieOutputFactory) { this.scratchieOutputFactory = scratchieOutputFactory; } + + // ****************** REST methods ************************* + + /** + * Rest call to create a new Scratchie content. Required fields in toolContentJSON: "title", "instructions", + * "questions". The questions entry should be JSONArray containing JSON objects, which in turn must contain + * "questionText", "displayOrder" (Integer) and a JSONArray "answers". The answers entry should be JSONArray + * containing JSON objects, which in turn must contain "answerText", "displayOrder" (Integer), "correct" (Boolean). + */ + @SuppressWarnings("unchecked") + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) + throws JSONException { + + Scratchie scratchie = new Scratchie(); + Date updateDate = new Date(); + + scratchie.setCreated(updateDate); + scratchie.setUpdated(updateDate); + scratchie.setDefineLater(false); + + scratchie.setContentId(toolContentID); + scratchie.setTitle(toolContentJSON.getString(RestTags.TITLE)); + scratchie.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); + + scratchie.setBurningQuestionsEnabled(JsonUtil.opt(toolContentJSON, "burningQuestionsEnabled", false)); + scratchie.setExtraPoint(JsonUtil.opt(toolContentJSON, "extraPoint", false)); + scratchie.setReflectOnActivity(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + scratchie.setReflectInstructions(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, (String) null)); + scratchie.setSubmissionDeadline(JsonUtil.opt(toolContentJSON, RestTags.SUBMISSION_DEADLINE, (Date) null)); + + // Scratchie Items + Set newItems = new LinkedHashSet(); + + JSONArray questions = toolContentJSON.getJSONArray(RestTags.QUESTIONS); + for (int i = 0; i < questions.length(); i++) { + JSONObject questionData = (JSONObject) questions.get(i); + + ScratchieItem item = new ScratchieItem(); + item.setCreateDate(updateDate); + item.setCreateByAuthor(true); + item.setOrderId(questionData.getInt(RestTags.DISPLAY_ORDER)); + item.setTitle(questionData.getString(RestTags.QUESTION_TITLE)); + item.setDescription(questionData.getString(RestTags.QUESTION_TEXT)); + newItems.add(item); + + // set options + Set newAnswers = new LinkedHashSet(); + + JSONArray answersData = (JSONArray) questionData.getJSONArray(RestTags.ANSWERS); + for (int j = 0; j < answersData.length(); j++) { + JSONObject answerData = (JSONObject) answersData.get(j); + ScratchieAnswer answer = new ScratchieAnswer(); + // Removes redundant new line characters from options left by CKEditor (otherwise it will break + // Javascript in monitor). Copied from AuthoringAction. + String answerDescription = answerData.getString(RestTags.ANSWER_TEXT); + answer.setDescription(answerDescription != null ? answerDescription.replaceAll("[\n\r\f]", "") : ""); + answer.setCorrect(answerData.getBoolean(RestTags.CORRECT)); + answer.setOrderId(answerData.getInt(RestTags.DISPLAY_ORDER)); + answer.setScratchieItem(item); + newAnswers.add(answer); + } + + item.setAnswers(newAnswers); + + } + + scratchie.setScratchieItems(newItems); + saveOrUpdateScratchie(scratchie); + + } + }