a94fc12a25c155eb912fe2b17fab73f7a015775a
[idea/community.git] / python / educational / course-creator / src / com / jetbrains / edu / coursecreator / actions / CCFromCourseArchive.java
1 package com.jetbrains.edu.coursecreator.actions;
2
3 import com.google.gson.FieldNamingPolicy;
4 import com.google.gson.Gson;
5 import com.google.gson.GsonBuilder;
6 import com.google.gson.JsonSyntaxException;
7 import com.intellij.icons.AllIcons;
8 import com.intellij.ide.projectView.ProjectView;
9 import com.intellij.openapi.actionSystem.AnActionEvent;
10 import com.intellij.openapi.actionSystem.CommonDataKeys;
11 import com.intellij.openapi.application.ApplicationManager;
12 import com.intellij.openapi.command.CommandProcessor;
13 import com.intellij.openapi.diagnostic.Logger;
14 import com.intellij.openapi.editor.Document;
15 import com.intellij.openapi.fileChooser.FileChooser;
16 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
17 import com.intellij.openapi.fileEditor.FileDocumentManager;
18 import com.intellij.openapi.project.DumbAwareAction;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.util.TextRange;
21 import com.intellij.openapi.util.text.StringUtil;
22 import com.intellij.openapi.vfs.VirtualFile;
23 import com.intellij.openapi.vfs.VirtualFileManager;
24 import com.intellij.platform.templates.github.ZipUtil;
25 import com.jetbrains.edu.EduDocumentListener;
26 import com.jetbrains.edu.EduNames;
27 import com.jetbrains.edu.EduUtils;
28 import com.jetbrains.edu.courseFormat.*;
29 import com.jetbrains.edu.coursecreator.CCProjectService;
30 import com.jetbrains.edu.oldCourseFormat.OldCourse;
31 import org.jetbrains.annotations.NotNull;
32
33 import java.io.*;
34 import java.util.Map;
35
36 public class CCFromCourseArchive extends DumbAwareAction {
37   private static final Logger LOG = Logger.getInstance(CCFromCourseArchive.class.getName());
38
39   public CCFromCourseArchive() {
40     super("Unpack Course Archive", "Unpack Course Archive", AllIcons.FileTypes.Archive);
41   }
42
43   @Override
44   public void update(@NotNull AnActionEvent e) {
45     e.getPresentation().setEnabledAndVisible(false);
46     //CCProjectService.setCCActionAvailable(e);
47   }
48
49   @Override
50   public void actionPerformed(@NotNull AnActionEvent e) {
51     final Project project = e.getData(CommonDataKeys.PROJECT);
52     if (project == null) {
53       return;
54     }
55     unpackCourseArchive(project);
56   }
57
58   private static void unpackCourseArchive(final Project project) {
59     FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, true, true, true, false);
60
61     final VirtualFile virtualFile = FileChooser.chooseFile(descriptor, project, null);
62     if (virtualFile == null) {
63       return;
64     }
65     final String basePath = project.getBasePath();
66     if (basePath == null) return;
67     final CCProjectService service = CCProjectService.getInstance(project);
68     Reader reader = null;
69     try {
70       ZipUtil.unzip(null, new File(basePath), new File(virtualFile.getPath()), null, null, true);
71       reader = new InputStreamReader(new FileInputStream(new File(basePath, EduNames.COURSE_META_FILE)));
72       Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
73       Course course = gson.fromJson(reader, Course.class);
74       if (course == null || course.getLessons().isEmpty() || StringUtil.isEmptyOrSpaces(course.getLessons().get(0).getName())) {
75         try {
76           reader.close();
77         }
78         catch (IOException e) {
79           LOG.error(e.getMessage());
80         }
81         reader = new InputStreamReader(new FileInputStream(new File(basePath, EduNames.COURSE_META_FILE)));
82         OldCourse oldCourse = gson.fromJson(reader, OldCourse.class);
83         course = EduUtils.transformOldCourse(oldCourse);
84       }
85
86       service.setCourse(course);
87       project.getBaseDir().refresh(false, true);
88       int index = 1;
89       int taskIndex = 1;
90       for (Lesson lesson : course.getLessons()) {
91         final VirtualFile lessonDir = project.getBaseDir().findChild(EduNames.LESSON + String.valueOf(index));
92         lesson.setIndex(index);
93         if (lessonDir == null) continue;
94         for (Task task : lesson.getTaskList()) {
95           final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + String.valueOf(taskIndex));
96           task.setIndex(taskIndex);
97           task.setLesson(lesson);
98           if (taskDir == null) continue;
99           for (final Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
100             ApplicationManager.getApplication().runWriteAction(new Runnable() {
101               @Override
102               public void run() {
103                 createAnswerFile(project, taskDir, taskDir, entry);
104               }
105             });
106           }
107           taskIndex += 1;
108         }
109         index += 1;
110         taskIndex = 1;
111       }
112     }
113     catch (FileNotFoundException e) {
114       LOG.error(e.getMessage());
115     }
116     catch (IOException e) {
117       LOG.error(e.getMessage());
118     }
119     catch (JsonSyntaxException e) {
120       LOG.error(e.getMessage());
121     }
122     finally {
123       if (reader != null) {
124         try {
125           reader.close();
126         }
127         catch (IOException e) {
128           LOG.error(e.getMessage());
129         }
130       }
131     }
132     synchronize(project);
133   }
134
135   public static void createAnswerFile(@NotNull final Project project,
136                                       @NotNull final VirtualFile userFileDir,
137                                       @NotNull final VirtualFile answerFileDir,
138                                       @NotNull final Map.Entry<String, TaskFile> taskFileEntry) {
139     final String name = taskFileEntry.getKey();
140     final TaskFile taskFile = taskFileEntry.getValue();
141     VirtualFile file = userFileDir.findChild(name);
142     assert file != null;
143     String answerFileName = file.getNameWithoutExtension() + ".answer." + file.getExtension();
144     VirtualFile answerFile = answerFileDir.findChild(answerFileName);
145     if (answerFile != null) {
146       try {
147         answerFile.delete(project);
148       }
149       catch (IOException e) {
150         LOG.error(e);
151       }
152     }
153     try {
154       answerFile = userFileDir.createChildData(project, answerFileName);
155     }
156     catch (IOException e) {
157       LOG.error(e);
158     }
159     if (answerFile == null) return;
160
161     final Document originDocument = FileDocumentManager.getInstance().getDocument(file);
162     if (originDocument == null) {
163       return;
164     }
165     final Document document = FileDocumentManager.getInstance().getDocument(answerFile);
166     if (document == null) return;
167
168     CommandProcessor.getInstance().executeCommand(project, new Runnable() {
169       @Override
170       public void run() {
171         ApplicationManager.getApplication().runWriteAction(new Runnable() {
172           @Override
173           public void run() {
174             document.replaceString(0, document.getTextLength(), originDocument.getCharsSequence());
175           }
176         });
177       }
178     }, "Create answer document", "Create answer document");
179     EduDocumentListener listener = new EduDocumentListener(taskFile, false);
180     document.addDocumentListener(listener);
181     taskFile.sortAnswerPlaceholders();
182     for (int i = taskFile.getAnswerPlaceholders().size() - 1; i >= 0; i--) {
183       final AnswerPlaceholder answerPlaceholder = taskFile.getAnswerPlaceholders().get(i);
184       replaceAnswerPlaceholder(project, document, answerPlaceholder);
185     }
186     CommandProcessor.getInstance().executeCommand(project, new Runnable() {
187       @Override
188       public void run() {
189         ApplicationManager.getApplication().runWriteAction(new Runnable() {
190           @Override
191           public void run() {
192             FileDocumentManager.getInstance().saveDocument(document);
193           }
194         });
195       }
196     }, "x", "qwe");
197     document.removeDocumentListener(listener);
198   }
199
200   private static void replaceAnswerPlaceholder(@NotNull final Project project,
201                                                @NotNull final Document document,
202                                                @NotNull final AnswerPlaceholder answerPlaceholder) {
203     final int offset = answerPlaceholder.getRealStartOffset(document);
204     CommandProcessor.getInstance().executeCommand(project, new Runnable() {
205       @Override
206       public void run() {
207         ApplicationManager.getApplication().runWriteAction(new Runnable() {
208           @Override
209           public void run() {
210             final String text = document.getText(TextRange.create(offset, offset + answerPlaceholder.getLength()));
211             answerPlaceholder.setTaskText(text);
212             final VirtualFile hints = project.getBaseDir().findChild(EduNames.HINTS);
213             if (hints != null) {
214               final String hintFile = answerPlaceholder.getHint();
215               final VirtualFile virtualFile = hints.findChild(hintFile);
216               if (virtualFile != null) {
217                 final Document hintDocument = FileDocumentManager.getInstance().getDocument(virtualFile);
218                 if (hintDocument != null) {
219                   final String hintText = hintDocument.getText();
220                   answerPlaceholder.setHint(hintText);
221                 }
222               }
223             }
224
225             document.replaceString(offset, offset + answerPlaceholder.getLength(), answerPlaceholder.getPossibleAnswer());
226             FileDocumentManager.getInstance().saveDocument(document);
227           }
228         });
229       }
230     }, "x", "qwe");
231   }
232
233   private static void synchronize(@NotNull final Project project) {
234     VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
235     ProjectView.getInstance(project).refresh();
236   }
237
238 }