EDU-707 PyCharm Edu 3 fatal error on the first attempt to open a course in the course...
[idea/community.git] / python / educational-core / course-creator / src / com / jetbrains / edu / coursecreator / CCProjectComponent.java
1 package com.jetbrains.edu.coursecreator;
2
3 import com.intellij.openapi.application.ApplicationManager;
4 import com.intellij.openapi.application.PathManager;
5 import com.intellij.openapi.components.AbstractProjectComponent;
6 import com.intellij.openapi.diagnostic.Logger;
7 import com.intellij.openapi.project.Project;
8 import com.intellij.openapi.util.io.FileUtil;
9 import com.intellij.openapi.util.io.FileUtilRt;
10 import com.intellij.openapi.vfs.LocalFileSystem;
11 import com.intellij.openapi.vfs.VirtualFile;
12 import com.intellij.openapi.vfs.VirtualFileManager;
13 import com.jetbrains.edu.learning.StudyTaskManager;
14 import com.jetbrains.edu.learning.StudyUtils;
15 import com.jetbrains.edu.learning.core.EduNames;
16 import com.jetbrains.edu.learning.courseFormat.Course;
17 import com.jetbrains.edu.learning.courseFormat.Lesson;
18 import com.jetbrains.edu.learning.courseFormat.Task;
19 import com.jetbrains.edu.learning.courseFormat.TaskFile;
20 import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
21 import org.jetbrains.annotations.NotNull;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Map;
28
29 public class CCProjectComponent extends AbstractProjectComponent {
30   private static final Logger LOG = Logger.getInstance(CCProjectComponent.class);
31   private final CCVirtualFileListener myTaskFileLifeListener = new CCVirtualFileListener();
32   private final Project myProject;
33
34   protected CCProjectComponent(Project project) {
35     super(project);
36     myProject = project;
37   }
38
39   public void migrateIfNeeded() {
40     Course studyCourse = StudyTaskManager.getInstance(myProject).getCourse();
41     if (studyCourse == null) {
42       Course oldCourse = CCProjectService.getInstance(myProject).getCourse();
43       if (oldCourse == null) {
44         return;
45       }
46       StudyTaskManager.getInstance(myProject).setCourse(oldCourse);
47       CCProjectService.getInstance(myProject).setCourse(null);
48       oldCourse.initCourse(true);
49       oldCourse.setCourseMode(CCUtils.COURSE_MODE);
50       File coursesDir = new File(PathManager.getConfigPath(), "courses");
51       File courseDir = new File(coursesDir, oldCourse.getName() + "-" + myProject.getName());
52       oldCourse.setCourseDirectory(courseDir.getPath());
53       StudyUtils.registerStudyToolWindow(oldCourse, myProject);
54       transformFiles(oldCourse, myProject);
55     }
56   }
57
58   private static void transformFiles(Course course, Project project) {
59     List<VirtualFile> files = getAllAnswerTaskFiles(course, project);
60     for (VirtualFile answerFile : files) {
61       ApplicationManager.getApplication().runWriteAction(() -> {
62         String answerName = answerFile.getName();
63         String nameWithoutExtension = FileUtil.getNameWithoutExtension(answerName);
64         String name = FileUtil.getNameWithoutExtension(nameWithoutExtension) + "." + FileUtilRt.getExtension(answerName);
65         VirtualFile parent = answerFile.getParent();
66         VirtualFile file = parent.findChild(name);
67         try {
68           if (file != null) {
69             file.delete(CCProjectComponent.class);
70           }
71           VirtualFile windowsDescrFile = parent.findChild(FileUtil.getNameWithoutExtension(name) + EduNames.WINDOWS_POSTFIX);
72           if (windowsDescrFile != null) {
73             windowsDescrFile.delete(CCProjectComponent.class);
74           }
75           answerFile.rename(CCProjectComponent.class, name);
76         }
77         catch (IOException e) {
78           LOG.error(e);
79         }
80       });
81     }
82   }
83
84
85   private static List<VirtualFile> getAllAnswerTaskFiles(@NotNull Course course, @NotNull Project project) {
86     List<VirtualFile> result = new ArrayList<>();
87     for (Lesson lesson : course.getLessons()) {
88       for (Task task : lesson.getTaskList()) {
89         for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
90           String name = entry.getKey();
91           String answerName = FileUtil.getNameWithoutExtension(name) + CCUtils.ANSWER_EXTENSION_DOTTED + FileUtilRt.getExtension(name);
92           String taskPath = FileUtil.join(project.getBasePath(), EduNames.LESSON + lesson.getIndex(), EduNames.TASK + task.getIndex());
93           VirtualFile taskFile = LocalFileSystem.getInstance().findFileByPath(FileUtil.join(taskPath, answerName));
94           if (taskFile == null) {
95             taskFile = LocalFileSystem.getInstance().findFileByPath(FileUtil.join(taskPath, EduNames.SRC, answerName));
96           }
97           if (taskFile != null) {
98             result.add(taskFile);
99           }
100         }
101       }
102     }
103     return result;
104   }
105
106   @NotNull
107   public String getComponentName() {
108     return "CCProjectComponent";
109   }
110
111   public void projectOpened() {
112     migrateIfNeeded();
113     VirtualFileManager.getInstance().addVirtualFileListener(myTaskFileLifeListener);
114     EduUsagesCollector.projectTypeOpened(CCUtils.COURSE_MODE);
115   }
116
117   public void projectClosed() {
118     VirtualFileManager.getInstance().removeVirtualFileListener(myTaskFileLifeListener);
119   }
120 }