added validation to answer files rename (part of EDU-341)
[idea/community.git] / python / educational / course-creator / src / com / jetbrains / edu / coursecreator / CCProjectService.java
1 /*
2  * Copyright 2000-2013 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.edu.coursecreator;
17
18 import com.intellij.openapi.actionSystem.AnActionEvent;
19 import com.intellij.openapi.components.PersistentStateComponent;
20 import com.intellij.openapi.components.ServiceManager;
21 import com.intellij.openapi.components.State;
22 import com.intellij.openapi.components.Storage;
23 import com.intellij.openapi.editor.Document;
24 import com.intellij.openapi.editor.Editor;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.util.io.FileUtil;
27 import com.intellij.openapi.util.io.FileUtilRt;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.ui.JBColor;
30 import com.intellij.util.xmlb.XmlSerializerUtil;
31 import com.jetbrains.edu.EduAnswerPlaceholderPainter;
32 import com.jetbrains.edu.EduDocumentListener;
33 import com.jetbrains.edu.EduNames;
34 import com.jetbrains.edu.EduUtils;
35 import com.jetbrains.edu.courseFormat.*;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
38
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42
43 @State(name = "CCProjectService",
44        storages = {
45          @Storage(file = "$PROJECT_CONFIG_DIR$/course_service.xml")
46        }
47 )
48 public class CCProjectService implements PersistentStateComponent<CCProjectService> {
49   private Course myCourse;
50
51   private static final Map<Document, EduDocumentListener> myDocumentListeners = new HashMap<Document, EduDocumentListener>();
52
53   @Nullable
54   public TaskFile getTaskFile(@NotNull final VirtualFile virtualFile) {
55     VirtualFile taskDir = virtualFile.getParent();
56     if (taskDir == null) {
57       return null;
58     }
59     String taskDirName = taskDir.getName();
60     if (!taskDirName.contains(EduNames.TASK)) {
61       return null;
62     }
63     VirtualFile lessonDir = taskDir.getParent();
64     if (lessonDir == null) {
65       return null;
66     }
67     String lessonDirName = lessonDir.getName();
68     if (!lessonDirName.contains(EduNames.LESSON)) {
69       return null;
70     }
71     Lesson lesson = myCourse.getLesson(lessonDirName);
72     if (lesson == null) {
73       return null;
74     }
75     Task task = lesson.getTask(taskDir.getName());
76     if (task == null) {
77       return null;
78     }
79     String fileName = getRealTaskFileName(virtualFile.getName());
80     return task.getTaskFile(fileName);
81   }
82
83   public void drawAnswerPlaceholders(@NotNull final VirtualFile virtualFile, @NotNull final Editor editor) {
84     TaskFile taskFile = getTaskFile(virtualFile);
85     if (taskFile == null) {
86       return;
87     }
88     List<AnswerPlaceholder> answerPlaceholders = taskFile.getAnswerPlaceholders();
89     for (AnswerPlaceholder answerPlaceholder : answerPlaceholders) {
90       EduAnswerPlaceholderPainter.drawAnswerPlaceholder(editor, answerPlaceholder, false, JBColor.BLUE);
91     }
92   }
93
94   public static void addDocumentListener(Document document, EduDocumentListener listener) {
95     myDocumentListeners.put(document, listener);
96   }
97
98   public static EduDocumentListener getListener(Document document) {
99     return myDocumentListeners.get(document);
100   }
101
102   public static void removeListener(Document document) {
103     myDocumentListeners.remove(document);
104   }
105
106   @Nullable
107   public Task getTask(VirtualFile file) {
108     if (myCourse == null || file == null) {
109       return null;
110     }
111     VirtualFile taskDir = file.getParent();
112     if (taskDir != null) {
113       String taskDirName = taskDir.getName();
114       if (taskDirName.contains(EduNames.TASK)) {
115         VirtualFile lessonDir = taskDir.getParent();
116         if (lessonDir != null) {
117           String lessonDirName = lessonDir.getName();
118           int lessonIndex = EduUtils.getIndex(lessonDirName, EduNames.LESSON);
119           List<Lesson> lessons = myCourse.getLessons();
120           if (!EduUtils.indexIsValid(lessonIndex, lessons)) {
121             return null;
122           }
123           Lesson lesson = lessons.get(lessonIndex);
124           int taskIndex = EduUtils.getIndex(taskDirName, EduNames.TASK);
125           List<Task> tasks = lesson.getTaskList();
126           if (!EduUtils.indexIsValid(taskIndex, tasks)) {
127             return null;
128           }
129           return tasks.get(taskIndex);
130         }
131       }
132     }
133     return null;
134   }
135
136   public boolean isAnswerFile(VirtualFile file) {
137     Task task = getTask(file);
138     String fileName = getRealTaskFileName(file.getName());
139     return task != null && fileName != null && task.isTaskFile(fileName);
140   }
141
142   public boolean isTaskFile(VirtualFile file) {
143     Task task = getTask(file);
144     return task != null && task.isTaskFile(file.getName());
145   }
146
147   @Nullable
148   public static String getRealTaskFileName(String name) {
149     String nameWithoutExtension = FileUtil.getNameWithoutExtension(name);
150     String extension = FileUtilRt.getExtension(name);
151     if (!nameWithoutExtension.endsWith(".answer")) {
152       return null;
153     }
154     int nameEnd = name.indexOf(".answer");
155     return name.substring(0, nameEnd) + "." + extension;
156   }
157
158   public static boolean setCCActionAvailable(@NotNull AnActionEvent e) {
159     final Project project = e.getProject();
160     if (project == null) {
161       return false;
162     }
163     if (getInstance(project).getCourse() == null) {
164       EduUtils.enableAction(e, false);
165       return false;
166     }
167     EduUtils.enableAction(e, true);
168     return true;
169   }
170
171   public Course getCourse() {
172     return myCourse;
173   }
174
175   public void setCourse(@NotNull final Course course) {
176     myCourse = course;
177   }
178
179   @Override
180   public CCProjectService getState() {
181     return this;
182   }
183
184   @Override
185   public void loadState(CCProjectService state) {
186     XmlSerializerUtil.copyBean(state, this);
187     myCourse.initCourse(true);
188   }
189
190   public static CCProjectService getInstance(@NotNull Project project) {
191     return ServiceManager.getService(project, CCProjectService.class);
192   }
193 }