package com.jetbrains.edu.learning;
import com.google.gson.*;
+import com.google.gson.reflect.TypeToken;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashMap;
import com.jetbrains.edu.learning.core.EduNames;
+import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
public static final String PLACEHOLDERS = "placeholders";
public static final String LINE = "line";
public static final String START = "start";
+ public static final String LENGTH = "length";
+ public static final String POSSIBLE_ANSWER = "possible_answer";
+ public static final String HINT = "hint";
+ public static final String ADDITIONAL_HINTS = "additional_hints";
public static final String OFFSET = "offset";
public static final String TEXT = "text";
public static final String LESSONS = "lessons";
private StudySerializationUtils() {
}
- public static class StudyUnrecognizedFormatException extends Exception {}
+ public static class StudyUnrecognizedFormatException extends Exception {
+ }
public static class Xml {
public final static String COURSE_ELEMENT = "courseElement";
public static final String MY_LINE = "myLine";
public static final String MY_START = "myStart";
public static final String MY_LENGTH = "myLength";
+ public static final String HINT = "hint";
public static final String AUTHOR_TITLED = "Author";
public static final String FIRST_NAME = "first_name";
public static final String SECOND_NAME = "second_name";
public static final String TASK_WINDOWS = "taskWindows";
public static final String RESOURCE_PATH = "resourcePath";
public static final String COURSE_DIRECTORY = "courseDirectory";
+ public static final String SUBTASK_INFO = "AnswerPlaceholderSubtaskInfo";
+ public static final String SUBTASK_INFOS = "subtaskInfos";
+ public static final String ADDITIONAL_HINTS = "additionalHints";
+ public static final String POSSIBLE_ANSWER = "possibleAnswer";
+ public static final String SELECTED = "selected";
+ public static final String TASK_TEXT = "taskText";
+ public static final String PLACEHOLDER_TEXT = "placeholderText";
private Xml() {
}
addChildWithName(initialState, MY_LENGTH, getChildWithName(placeholder, MY_INITIAL_LENGTH).getAttributeValue(VALUE));
}
}
-
}
}
element.removeContent();
return state;
}
+ public static Element convertToForthVersion(Element state) throws StudyUnrecognizedFormatException {
+ Element taskManagerElement = state.getChild(MAIN_ELEMENT);
+ Element courseElement = getChildWithName(taskManagerElement, COURSE).getChild(COURSE_TITLED);
+ for (Element lesson : getChildList(courseElement, LESSONS)) {
+ for (Element task : getChildList(lesson, TASK_LIST)) {
+ Map<String, Element> taskFiles = getChildMap(task, TASK_FILES);
+ for (Map.Entry<String, Element> entry : taskFiles.entrySet()) {
+ Element taskFileElement = entry.getValue();
+ for (Element placeholder : getChildList(taskFileElement, ANSWER_PLACEHOLDERS)) {
+ Element valueElement = new Element(SUBTASK_INFO);
+ addChildMap(placeholder, SUBTASK_INFOS, Collections.singletonMap(String.valueOf(0), valueElement));
+ for (String childName : ContainerUtil
+ .list(HINT, ADDITIONAL_HINTS, POSSIBLE_ANSWER, SELECTED, STATUS, TASK_TEXT)) {
+ Element child = getChildWithName(placeholder, childName);
+ valueElement.addContent(child.clone());
+ }
+ renameElement(getChildWithName(valueElement, TASK_TEXT), PLACEHOLDER_TEXT);
+ }
+ }
+ }
+ }
+
+ return state;
+ }
+
public static String addStatus(XMLOutputter outputter,
Map<String, String> placeholderTextToStatus,
String taskStatus,
return addChildWithName(parent, name, listElement);
}
+ public static Element addChildMap(Element parent, String name, Map<String, Element> value) {
+ Element mapElement = new Element(MAP);
+ for (Map.Entry<String, Element> entry : value.entrySet()) {
+ Element entryElement = new Element("entry");
+ mapElement.addContent(entryElement);
+ String key = entry.getKey();
+ entryElement.setAttribute("key", key);
+ Element valueElement = new Element("value");
+ valueElement.addContent(entry.getValue());
+ entryElement.addContent(valueElement);
+ }
+ return addChildWithName(parent, name, mapElement);
+ }
+
public static List<Element> getChildList(Element parent, String name) throws StudyUnrecognizedFormatException {
- Element listParent = getChildWithName(parent, name);
+ return getChildList(parent, name, false);
+ }
+
+ public static List<Element> getChildList(Element parent, String name, boolean optional) throws StudyUnrecognizedFormatException {
+ Element listParent = getChildWithName(parent, name, optional);
if (listParent != null) {
Element list = listParent.getChild(LIST);
if (list != null) {
}
public static Element getChildWithName(Element parent, String name) throws StudyUnrecognizedFormatException {
+ return getChildWithName(parent, name, false);
+ }
+
+ public static Element getChildWithName(Element parent, String name, boolean optional) throws StudyUnrecognizedFormatException {
for (Element child : parent.getChildren()) {
Attribute attribute = child.getAttribute(NAME);
if (attribute == null) {
return child;
}
}
+ if (optional) {
+ return null;
+ }
throw new StudyUnrecognizedFormatException();
}
public static <K, V> Map<K, V> getChildMap(Element element, String name) throws StudyUnrecognizedFormatException {
- Element mapParent = getChildWithName(element, name);
+ return getChildMap(element, name, false);
+ }
+
+ public static <K, V> Map<K, V> getChildMap(Element element, String name, boolean optional) throws StudyUnrecognizedFormatException {
+ Element mapParent = getChildWithName(element, name, optional);
if (mapParent != null) {
Element map = mapParent.getChild(MAP);
if (map != null) {
for (Map.Entry<String, JsonElement> taskFile : taskObject.getAsJsonObject(TASK_FILES).entrySet()) {
String name = taskFile.getKey();
String filePath = FileUtil.join(myCourseFile.getParent(), EduNames.LESSON + lessonIndex, EduNames.TASK + taskIndex, name);
- VirtualFile resourceFile = LocalFileSystem.getInstance().findFileByIoFile(new File(filePath));
+ VirtualFile resourceFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(filePath));
if (resourceFile == null) {
continue;
}
@Override
public TaskFile deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+ final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
JsonObject taskFileObject = json.getAsJsonObject();
JsonArray placeholders = taskFileObject.getAsJsonArray(PLACEHOLDERS);
for (JsonElement placeholder : placeholders) {
int start = placeholderObject.getAsJsonPrimitive(START).getAsInt();
if (line == -1) {
placeholderObject.addProperty(OFFSET, start);
- } else {
+ }
+ else {
Document document = EditorFactory.getInstance().createDocument(taskFileObject.getAsJsonPrimitive(TEXT).getAsString());
placeholderObject.addProperty(OFFSET, document.getLineStartOffset(line) + start);
}
+ final String hintString = placeholderObject.getAsJsonPrimitive(HINT).getAsString();
+ final JsonArray hintsArray = new JsonArray();
+
+ try {
+ final Type listType = new TypeToken<List<String>>() {}.getType();
+ final List<String> hints = gson.fromJson(hintString, listType);
+ if (hints != null && !hints.isEmpty()) {
+ for (int i = 0; i < hints.size(); i++) {
+ if (i == 0) {
+ placeholderObject.addProperty(HINT, hints.get(0));
+ continue;
+ }
+ hintsArray.add(hints.get(i));
+ }
+ placeholderObject.add(ADDITIONAL_HINTS, hintsArray);
+ }
+ else {
+ placeholderObject.addProperty(HINT, "");
+ }
+ }
+ catch (JsonParseException e) {
+ hintsArray.add(hintString);
+ }
}
- return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create().fromJson(json, TaskFile.class);
+
+ return gson.fromJson(json, TaskFile.class);
+ }
+ }
+
+ public static class StepicAnswerPlaceholderAdapter implements JsonSerializer<AnswerPlaceholder> {
+ @Override
+ public JsonElement serialize(AnswerPlaceholder src, Type typeOfSrc, JsonSerializationContext context) {
+ final List<String> hints = src.getHints();
+
+ final int length = src.getLength();
+ final int start = src.getOffset();
+ final String possibleAnswer = src.getPossibleAnswer();
+ int line = -1;
+
+ final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+ final JsonObject answerPlaceholder = new JsonObject();
+ answerPlaceholder.addProperty(LINE, line);
+ answerPlaceholder.addProperty(START, start);
+ answerPlaceholder.addProperty(LENGTH, length);
+ answerPlaceholder.addProperty(POSSIBLE_ANSWER, possibleAnswer);
+
+ final String jsonHints = gson.toJson(hints);
+ answerPlaceholder.addProperty(HINT, jsonHints);
+
+ return answerPlaceholder;
}
}
}