Rename educational plugins and update plugin's description
[idea/community.git] / python / educational-core / course-creator / src / com / jetbrains / edu / coursecreator / actions / CCCreateCourseArchive.java
1 package com.jetbrains.edu.coursecreator.actions;
2
3 import com.google.gson.Gson;
4 import com.google.gson.GsonBuilder;
5 import com.intellij.icons.AllIcons;
6 import com.intellij.ide.projectView.ProjectView;
7 import com.intellij.openapi.actionSystem.AnActionEvent;
8 import com.intellij.openapi.actionSystem.CommonDataKeys;
9 import com.intellij.openapi.application.ApplicationManager;
10 import com.intellij.openapi.diagnostic.Logger;
11 import com.intellij.openapi.project.DumbAwareAction;
12 import com.intellij.openapi.project.Project;
13 import com.intellij.openapi.ui.DialogWrapper;
14 import com.intellij.openapi.ui.Messages;
15 import com.intellij.openapi.util.io.FileUtil;
16 import com.intellij.openapi.vfs.VirtualFile;
17 import com.intellij.openapi.vfs.VirtualFileManager;
18 import com.intellij.util.containers.hash.HashMap;
19 import com.intellij.util.io.ZipUtil;
20 import com.jetbrains.edu.EduNames;
21 import com.jetbrains.edu.EduUtils;
22 import com.jetbrains.edu.courseFormat.Course;
23 import com.jetbrains.edu.courseFormat.Lesson;
24 import com.jetbrains.edu.courseFormat.Task;
25 import com.jetbrains.edu.courseFormat.TaskFile;
26 import com.jetbrains.edu.coursecreator.CCLanguageManager;
27 import com.jetbrains.edu.coursecreator.CCProjectService;
28 import com.jetbrains.edu.coursecreator.CCUtils;
29 import com.jetbrains.edu.coursecreator.ui.CreateCourseArchiveDialog;
30 import org.jetbrains.annotations.NotNull;
31
32 import java.io.*;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.zip.ZipOutputStream;
36
37 public class CCCreateCourseArchive extends DumbAwareAction {
38   private static final Logger LOG = Logger.getInstance(CCCreateCourseArchive.class.getName());
39   private String myZipName;
40   private String myLocationDir;
41
42   public void setZipName(String zipName) {
43     myZipName = zipName;
44   }
45
46   public void setLocationDir(String locationDir) {
47     myLocationDir = locationDir;
48   }
49
50   public CCCreateCourseArchive() {
51     super("Generate Course Archive", "Generate Course Archive", AllIcons.FileTypes.Archive);
52   }
53
54   @Override
55   public void update(@NotNull AnActionEvent e) {
56     CCProjectService.setCCActionAvailable(e);
57   }
58
59   @Override
60   public void actionPerformed(@NotNull AnActionEvent e) {
61     final Project project = e.getData(CommonDataKeys.PROJECT);
62     if (project == null) {
63       return;
64     }
65     createCourseArchive(project);
66   }
67
68   private void createCourseArchive(final Project project) {
69     final CCProjectService service = CCProjectService.getInstance(project);
70     final Course course = service.getCourse();
71     if (course == null) return;
72     CreateCourseArchiveDialog dlg = new CreateCourseArchiveDialog(project, this);
73     dlg.show();
74     if (dlg.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
75       return;
76     }
77     final VirtualFile baseDir = project.getBaseDir();
78     final List<Lesson> lessons = course.getLessons();
79
80     final Map<TaskFile, TaskFile> savedTaskFiles = new HashMap<TaskFile, TaskFile>();
81     for (Lesson lesson : lessons) {
82       final VirtualFile lessonDir = baseDir.findChild(EduNames.LESSON + String.valueOf(lesson.getIndex()));
83       if (lessonDir == null) continue;
84       for (Task task : lesson.getTaskList()) {
85         final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + String.valueOf(task.getIndex()));
86         if (taskDir == null) continue;
87         for (final Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
88           ApplicationManager.getApplication().runWriteAction(new Runnable() {
89             @Override
90             public void run() {
91               TaskFile taskFileCopy = new TaskFile();
92               TaskFile taskFile = entry.getValue();
93               TaskFile.copy(taskFile, taskFileCopy);
94               savedTaskFiles.put(taskFile, taskFileCopy);
95               EduUtils.createStudentFileFromAnswer(project, taskDir, taskDir, entry.getKey(), taskFile);
96             }
97           });
98         }
99       }
100     }
101     generateJson(project);
102     VirtualFileManager.getInstance().refreshWithoutFileWatcher(false);
103     packCourse(baseDir, course);
104     synchronize(project);
105     resetTaskFiles(savedTaskFiles);
106   }
107
108   private static void resetTaskFiles(Map<TaskFile, TaskFile> savedTaskFiles) {
109     for (Map.Entry<TaskFile, TaskFile> entry : savedTaskFiles.entrySet()) {
110       entry.getKey().setAnswerPlaceholders(entry.getValue().getAnswerPlaceholders());
111     }
112   }
113
114   private static void synchronize(@NotNull final Project project) {
115     VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
116     ProjectView.getInstance(project).refresh();
117   }
118
119   private void packCourse(@NotNull final VirtualFile baseDir, @NotNull final Course course) {
120     try {
121       final File zipFile = new File(myLocationDir, myZipName + ".zip");
122       ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
123       final CCLanguageManager manager = CCUtils.getStudyLanguageManager(course);
124       VirtualFile[] courseFiles = baseDir.getChildren();
125       for (VirtualFile file : courseFiles) {
126         ZipUtil.addFileOrDirRecursively(zos, null, new File(file.getPath()), file.getName(), new FileFilter() {
127           @Override
128           public boolean accept(File pathname) {
129             String name = pathname.getName();
130             String nameWithoutExtension = FileUtil.getNameWithoutExtension(pathname);
131             if (nameWithoutExtension.endsWith(".answer") || name.contains(EduNames.WINDOWS_POSTFIX) || name.contains(".idea")
132               || FileUtil.filesEqual(pathname, zipFile)) {
133               return false;
134             }
135             return manager != null && !manager.doNotPackFile(pathname);
136           }
137         }, null);
138       }
139       zos.close();
140       Messages.showInfoMessage("Course archive was saved to " + zipFile.getPath(), "Course Archive Was Created Successfully");
141     }
142     catch (IOException e1) {
143       LOG.error(e1);
144     }
145   }
146
147   @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
148   private static void generateJson(@NotNull final Project project) {
149     final CCProjectService service = CCProjectService.getInstance(project);
150     final Course course = service.getCourse();
151     final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
152     final String json = gson.toJson(course);
153     final File courseJson = new File(project.getBasePath(), EduNames.COURSE_META_FILE);
154     OutputStreamWriter outputStreamWriter = null;
155     try {
156       outputStreamWriter = new OutputStreamWriter(new FileOutputStream(courseJson), "UTF-8");
157       outputStreamWriter.write(json);
158     }
159     catch (Exception e) {
160       Messages.showErrorDialog(e.getMessage(), "Failed to Generate Json");
161       LOG.info(e);
162     }
163     finally {
164       try {
165         if (outputStreamWriter != null) {
166           outputStreamWriter.close();
167         }
168       }
169       catch (IOException e1) {
170         //close silently
171       }
172     }
173   }
174 }