From 8476641225006b3188a341eb29aa79e3b196fe68 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 31 Mar 2017 16:01:27 +0300 Subject: [PATCH] fix unpack student course into teacher view --- .../actions/CCFromCourseArchive.java | 164 ++++++++---------- .../actions/stepik/CCGetCourseFromStepic.java | 62 +------ .../edu/learning/StudySerializationUtils.java | 59 ------- .../StudyProjectGenerator.java | 2 +- 4 files changed, 74 insertions(+), 213 deletions(-) diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCFromCourseArchive.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCFromCourseArchive.java index aa26e49c5bcc..381b6b99101e 100644 --- a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCFromCourseArchive.java +++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCFromCourseArchive.java @@ -1,16 +1,12 @@ package com.jetbrains.edu.coursecreator.actions; -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonSyntaxException; import com.intellij.icons.AllIcons; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; @@ -21,10 +17,9 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.platform.templates.github.ZipUtil; import com.jetbrains.edu.coursecreator.CCUtils; -import com.jetbrains.edu.learning.StudySerializationUtils; import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.core.EduDocumentListener; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder; @@ -32,15 +27,13 @@ import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.courseFormat.Lesson; import com.jetbrains.edu.learning.courseFormat.TaskFile; import com.jetbrains.edu.learning.courseFormat.tasks.Task; +import com.jetbrains.edu.learning.courseGeneration.StudyGenerator; +import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator; import org.jetbrains.annotations.NotNull; -import java.io.*; -import java.util.ArrayList; import java.util.Map; public class CCFromCourseArchive extends DumbAwareAction { - private static final Logger LOG = Logger.getInstance(CCFromCourseArchive.class.getName()); - public CCFromCourseArchive() { super("Unpack Course Archive", "Unpack Course Archive", AllIcons.FileTypes.Archive); } @@ -55,7 +48,8 @@ public class CCFromCourseArchive extends DumbAwareAction { } private static void unpackCourseArchive(final Project project) { - FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, true, true, true, false); + FileChooserDescriptor descriptor = + new FileChooserDescriptor(true, true, true, true, true, false); final VirtualFile virtualFile = FileChooser.chooseFile(descriptor, project, null); if (virtualFile == null) { @@ -63,60 +57,51 @@ public class CCFromCourseArchive extends DumbAwareAction { } final String basePath = project.getBasePath(); if (basePath == null) return; - Reader reader = null; - try { - ZipUtil.unzip(null, new File(basePath), new File(virtualFile.getPath()), null, null, true); - File courseMetaFile = new File(basePath, EduNames.COURSE_META_FILE); - reader = new InputStreamReader(new FileInputStream(courseMetaFile)); - Gson gson = new GsonBuilder() - .registerTypeAdapter(Course.class, new StudySerializationUtils.Json.CourseTypeAdapter(courseMetaFile)) - .registerTypeAdapter(Task.class, new StudySerializationUtils.Json.TaskAdapter()) - .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) - .create(); - Course course = gson.fromJson(reader, Course.class); - if (course == null) { - Messages.showErrorDialog("This course is incompatible with current version", "Failed to Unpack Course"); - return; - } + Course course = StudyProjectGenerator.getCourse(virtualFile.getPath()); + if (course == null) { + Messages.showErrorDialog("This course is incompatible with current version", "Failed to Unpack Course"); + return; + } + generateFromStudentCourse(project, course); + } - StudyTaskManager.getInstance(project).setCourse(course); - course.setCourseMode(CCUtils.COURSE_MODE); - project.getBaseDir().refresh(false, true); - int index = 1; - int taskIndex = 1; - for (Lesson lesson : course.getLessons()) { - final VirtualFile lessonDir = project.getBaseDir().findChild(EduNames.LESSON + String.valueOf(index)); - lesson.setIndex(index); - if (lessonDir == null) continue; - for (Task task : lesson.getTaskList()) { - final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + String.valueOf(taskIndex)); - task.setIndex(taskIndex); - task.setLesson(lesson); - if (taskDir == null) continue; - for (final Map.Entry entry : task.getTaskFiles().entrySet()) { - ApplicationManager.getApplication().runWriteAction(() -> createAnswerFile(project, taskDir, entry)); - } - taskIndex += 1; - } - index += 1; - taskIndex = 1; + public static void generateFromStudentCourse(Project project, Course course) { + StudyTaskManager.getInstance(project).setCourse(course); + course.setCourseMode(CCUtils.COURSE_MODE); + final VirtualFile baseDir = project.getBaseDir(); + final Application application = ApplicationManager.getApplication(); + + application.invokeAndWait(() -> application.runWriteAction(() -> { + final VirtualFile[] children = baseDir.getChildren(); + for (VirtualFile child : children) { + StudyUtils.deleteFile(child); } - course.initCourse(true); - } - catch (JsonSyntaxException | IOException e) { - LOG.error(e.getMessage()); - } - finally { - if (reader != null) { - try { - reader.close(); - } - catch (IOException e) { - LOG.error(e.getMessage()); + StudyGenerator.createCourse(course, baseDir); + })); + baseDir.refresh(false, true); + + int index = 1; + int taskIndex = 1; + for (Lesson lesson : course.getLessons()) { + final VirtualFile lessonDir = project.getBaseDir().findChild(EduNames.LESSON + String.valueOf(index)); + lesson.setIndex(index); + if (lessonDir == null) continue; + for (Task task : lesson.getTaskList()) { + final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + String.valueOf(taskIndex)); + task.setIndex(taskIndex); + task.setLesson(lesson); + if (taskDir == null) continue; + for (final Map.Entry entry : task.getTaskFiles().entrySet()) { + application.invokeAndWait(() -> application.runWriteAction(() -> createAnswerFile(project, taskDir, entry))); } + taskIndex += 1; } + index += 1; + taskIndex = 1; } + course.initCourse(true); + application.invokeAndWait(() -> StudyUtils.registerStudyToolWindow(course, project)); synchronize(project); } @@ -127,57 +112,44 @@ public class CCFromCourseArchive extends DumbAwareAction { final TaskFile taskFile = taskFileEntry.getValue(); VirtualFile file = userFileDir.findFileByRelativePath(name); assert file != null; - final Document originDocument = FileDocumentManager.getInstance().getDocument(file); - if (originDocument == null) { - return; - } final Document document = FileDocumentManager.getInstance().getDocument(file); if (document == null) return; - CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> document.replaceString(0, document.getTextLength(), originDocument.getCharsSequence())), "Create answer document", "Create answer document"); + CommandProcessor.getInstance().executeCommand(project,() -> ApplicationManager.getApplication().runWriteAction( + () -> document.replaceString(0, document.getTextLength(), document.getCharsSequence())), + "Create answer document", "Create answer document"); EduDocumentListener listener = new EduDocumentListener(taskFile, false); document.addDocumentListener(listener); taskFile.sortAnswerPlaceholders(); - for (int i = taskFile.getActivePlaceholders().size() - 1; i >= 0; i--) { - final AnswerPlaceholder answerPlaceholder = taskFile.getAnswerPlaceholders().get(i); - replaceAnswerPlaceholder(project, document, answerPlaceholder); + + for (AnswerPlaceholder placeholder : taskFile.getActivePlaceholders()) { + replaceAnswerPlaceholder(document, placeholder); } - CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> FileDocumentManager.getInstance().saveDocument(document)), "x", "qwe"); + for (AnswerPlaceholder placeholder : taskFile.getAnswerPlaceholders()) { + placeholder.setUseLength(false); + } + + CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction( + () -> FileDocumentManager.getInstance().saveDocument(document)),"Create answer document", "Create answer document"); document.removeDocumentListener(listener); } - private static void replaceAnswerPlaceholder(@NotNull final Project project, - @NotNull final Document document, - @NotNull final AnswerPlaceholder answerPlaceholder) { - final int offset = answerPlaceholder.getOffset(); - CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { - final String text = document.getText(TextRange.create(offset, offset + answerPlaceholder.getRealLength())); - answerPlaceholder.setTaskText(text); - answerPlaceholder.init(); - final VirtualFile hints = project.getBaseDir().findChild(EduNames.HINTS); - if (hints != null) { - final ArrayList result = new ArrayList<>(); - for (String hint : answerPlaceholder.getHints()) { - final VirtualFile virtualFile = hints.findChild(hint); - if (virtualFile != null) { - final Document hintDocument = FileDocumentManager.getInstance().getDocument(virtualFile); - if (hintDocument != null) { - final String hintText = hintDocument.getText(); - result.add(hintText); - } - } - } - answerPlaceholder.setHints(result); - } - document.replaceString(offset, offset + answerPlaceholder.getRealLength(), answerPlaceholder.getPossibleAnswer()); - answerPlaceholder.setUseLength(false); + private static void replaceAnswerPlaceholder(@NotNull final Document document, + @NotNull final AnswerPlaceholder placeholder) { + final int offset = placeholder.getOffset(); + final String text = document.getText(TextRange.create(offset, offset + placeholder.getRealLength())); + placeholder.setTaskText(text); + placeholder.init(); + String replacementText = placeholder.getPossibleAnswer(); + + CommandProcessor.getInstance().runUndoTransparentAction(() -> ApplicationManager.getApplication().runWriteAction(() -> { + document.replaceString(offset, offset + placeholder.getRealLength(), replacementText); FileDocumentManager.getInstance().saveDocument(document); - }), "Replace answer placeholder", "From Course Archive"); + })); } private static void synchronize(@NotNull final Project project) { VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); ProjectView.getInstance(project).refresh(); } - } \ No newline at end of file diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/stepik/CCGetCourseFromStepic.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/stepik/CCGetCourseFromStepic.java index d4b1d80d747b..7d6cde5ec4cd 100644 --- a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/stepik/CCGetCourseFromStepic.java +++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/stepik/CCGetCourseFromStepic.java @@ -1,37 +1,23 @@ package com.jetbrains.edu.coursecreator.actions.stepik; import com.intellij.ide.IdeView; -import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; -import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.coursecreator.actions.CCFromCourseArchive; import com.jetbrains.edu.coursecreator.stepik.CCStepicConnector; -import com.jetbrains.edu.learning.StudyTaskManager; -import com.jetbrains.edu.learning.StudyUtils; -import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.courseFormat.Course; -import com.jetbrains.edu.learning.courseFormat.Lesson; import com.jetbrains.edu.learning.courseFormat.RemoteCourse; -import com.jetbrains.edu.learning.courseFormat.TaskFile; -import com.jetbrains.edu.learning.courseFormat.tasks.Task; -import com.jetbrains.edu.learning.courseGeneration.StudyGenerator; import com.jetbrains.edu.learning.stepic.EduStepicConnector; import org.jetbrains.annotations.NotNull; -import java.util.Map; - -import static com.jetbrains.edu.coursecreator.actions.CCFromCourseArchive.createAnswerFile; - public class CCGetCourseFromStepic extends DumbAwareAction { public CCGetCourseFromStepic() { @@ -47,7 +33,7 @@ public class CCGetCourseFromStepic extends DumbAwareAction { } final String courseId = Messages.showInputDialog("Please, enter course id", "Get Course From Stepik", null); if (StringUtil.isNotEmpty(courseId)) { - ProgressManager.getInstance().run(new com.intellij.openapi.progress.Task.Modal(project, "Creating Course", true) { + ProgressManager.getInstance().run(new Task.Modal(project, "Creating Course", true) { @Override public void run(@NotNull final ProgressIndicator indicator) { createCourse(project, courseId); @@ -57,50 +43,12 @@ public class CCGetCourseFromStepic extends DumbAwareAction { } private static void createCourse(Project project, String courseId) { - final VirtualFile baseDir = project.getBaseDir(); final RemoteCourse info = CCStepicConnector.getCourseInfo(courseId); if (info == null) return; final Course course = EduStepicConnector.getCourse(project, info); - if (course != null) { + if (course == null) return; - ApplicationManager.getApplication().invokeAndWait(() -> ApplicationManager.getApplication().runWriteAction(() -> { - final VirtualFile[] children = baseDir.getChildren(); - for (VirtualFile child : children) { - StudyUtils.deleteFile(child); - } - StudyGenerator.createCourse(course, baseDir); - })); - - - StudyTaskManager.getInstance(project).setCourse(course); - course.setCourseMode(CCUtils.COURSE_MODE); - project.getBaseDir().refresh(false, true); - int index = 1; - int taskIndex = 1; - for (Lesson lesson : course.getLessons()) { - final VirtualFile lessonDir = project.getBaseDir().findChild(EduNames.LESSON + String.valueOf(index)); - lesson.setIndex(index); - if (lessonDir == null) continue; - for (Task task : lesson.getTaskList()) { - final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + String.valueOf(taskIndex)); - task.setIndex(taskIndex); - task.setLesson(lesson); - if (taskDir == null) continue; - for (final Map.Entry entry : task.getTaskFiles().entrySet()) { - ApplicationManager.getApplication() - .invokeAndWait(() -> ApplicationManager.getApplication().runWriteAction(() -> createAnswerFile(project, taskDir, entry))); - } - taskIndex += 1; - } - index += 1; - taskIndex = 1; - } - course.initCourse(true); - ApplicationManager.getApplication() - .invokeAndWait(() -> StudyUtils.registerStudyToolWindow(course, project)); - } - VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); - ProjectView.getInstance(project).refresh(); + CCFromCourseArchive.generateFromStudentCourse(project, course); } } \ No newline at end of file diff --git a/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java b/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java index 4558d4c5fc26..a330c93d2aea 100644 --- a/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java +++ b/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java @@ -5,12 +5,9 @@ import com.google.gson.reflect.TypeToken; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; -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; @@ -27,7 +24,6 @@ import org.jdom.Element; import org.jdom.output.XMLOutputter; import org.jetbrains.annotations.NotNull; -import java.io.File; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; @@ -460,61 +456,6 @@ public class StudySerializationUtils { private Json() { } - public static class CourseTypeAdapter implements JsonDeserializer { - - private final File myCourseFile; - - public CourseTypeAdapter(File courseFile) { - myCourseFile = courseFile; - } - - @Override - public Course deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonObject courseObject = json.getAsJsonObject(); - JsonArray lessons = courseObject.getAsJsonArray(LESSONS); - for (int lessonIndex = 1; lessonIndex <= lessons.size(); lessonIndex++) { - JsonObject lessonObject = lessons.get(lessonIndex - 1).getAsJsonObject(); - JsonArray tasks = lessonObject.getAsJsonArray(TASK_LIST); - for (int taskIndex = 1; taskIndex <= tasks.size(); taskIndex++) { - JsonObject taskObject = tasks.get(taskIndex - 1).getAsJsonObject(); - for (Map.Entry 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().refreshAndFindFileByIoFile(new File(filePath)); - if (resourceFile == null) { - continue; - } - Document document = FileDocumentManager.getInstance().getDocument(resourceFile); - if (document == null) { - continue; - } - JsonObject taskFileObject = taskFile.getValue().getAsJsonObject(); - JsonArray placeholders = taskFileObject.getAsJsonArray(PLACEHOLDERS); - for (JsonElement placeholder : placeholders) { - convertToAbsoluteOffset(document, placeholder); - if (placeholder.getAsJsonObject().getAsJsonObject(SUBTASK_INFOS) == null) { - convertToSubtaskInfo(placeholder.getAsJsonObject()); - removeIndexFromSubtaskInfos(placeholder.getAsJsonObject()); - } - } - } - } - } - return new GsonBuilder().registerTypeAdapter(Task.class, new TaskAdapter()).create().fromJson(json, Course.class); - } - - private static void convertToAbsoluteOffset(Document document, JsonElement placeholder) { - JsonObject placeholderObject = placeholder.getAsJsonObject(); - if (placeholderObject.getAsJsonPrimitive(OFFSET) != null) { - return; - } - int line = placeholderObject.getAsJsonPrimitive(LINE).getAsInt(); - int start = placeholderObject.getAsJsonPrimitive(START).getAsInt(); - int offset = document.getLineStartOffset(line) + start; - placeholderObject.addProperty(OFFSET, offset); - } - } - public static class StepicStepOptionsAdapter implements JsonDeserializer { @Override public StepicWrappers.StepOptions deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java b/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java index f57c22a5914a..285d8360148c 100644 --- a/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java +++ b/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java @@ -194,7 +194,7 @@ public class StudyProjectGenerator { } @Nullable - public Course getCourse(String zipFilePath) { + public static Course getCourse(String zipFilePath) { try { final JBZipFile zipFile = new JBZipFile(zipFilePath); final JBZipEntry entry = zipFile.getEntry(EduNames.COURSE_META_FILE);