fix unpack student course into teacher view

This commit is contained in:
Ekaterina Tuzova
2017-04-06 14:54:32 +03:00
parent 8c69681a98
commit 8476641225
4 changed files with 74 additions and 213 deletions
@@ -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<String, TaskFile> 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<String, TaskFile> 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<String> 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();
}
}
@@ -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<String, TaskFile> 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);
}
}
@@ -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<Course> {
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<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().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<StepicWrappers.StepOptions> {
@Override
public StepicWrappers.StepOptions deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
@@ -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);