diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCGetCourseFromStepic.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCGetCourseFromStepic.java index 1e8c547709ac..f8b62a2e58c4 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCGetCourseFromStepic.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCGetCourseFromStepic.java @@ -61,14 +61,14 @@ public class CCGetCourseFromStepic extends DumbAwareAction { private static void createCourse(Project project, String courseId) { final VirtualFile baseDir = project.getBaseDir(); - final CourseInfo info = CCStepicConnector.getCourseInfo(courseId); + final CourseInfo info = CCStepicConnector.getCourseInfo(project, courseId); if (info == null) return; final Course course = EduStepicConnector.getCourse(project, info); if (course != null) { - flushCourse(course); + flushCourse(project, course); - final File courseDirectory = StudyUtils.getCourseDirectory(course); + final File courseDirectory = StudyUtils.getCourseDirectory(project, course); ApplicationManager.getApplication().invokeAndWait(() -> ApplicationManager.getApplication().runWriteAction(() -> { final VirtualFile[] children = baseDir.getChildren(); for (VirtualFile child : children) { diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java index 9e5ecfed340a..87a4e51f3af0 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java @@ -66,7 +66,7 @@ public class CCPushCourse extends DumbAwareAction { final int lessonId = CCStepicConnector.postLesson(project, lesson, indicator); final List sections = info.getSections(); final Integer sectionId = sections.get(sections.size() - 1); - CCStepicConnector.postUnit(lessonId, lesson.getIndex(), sectionId); + CCStepicConnector.postUnit(project, lessonId, lesson.getIndex(), sectionId); } } } diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java index da28246d5f07..2122709f977e 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java @@ -84,7 +84,7 @@ public class CCPushLesson extends DumbAwareAction { final int lessonId = CCStepicConnector.postLesson(project, lesson, indicator); final List sections = info.getSections(); final Integer sectionId = sections.get(sections.size()-1); - CCStepicConnector.postUnit(lessonId, lesson.getIndex(), sectionId); + CCStepicConnector.postUnit(project, lessonId, lesson.getIndex(), sectionId); } }}); } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyCourseResourceManager.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyCourseResourceManager.java new file mode 100644 index 000000000000..546d2406bad2 --- /dev/null +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyCourseResourceManager.java @@ -0,0 +1,26 @@ +package com.jetbrains.edu.learning; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.courseFormat.Task; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class StudyCourseResourceManager { + + /** + * Gets text of resource file such as test input file or task text in needed format + * + * @param fileName name of resource file which should exist in task directory + * @param wrapHTML if it's necessary to wrap text with html tags + * @return text of resource file wrapped with html tags if necessary + */ + @Nullable + public String getResourceText(@NotNull final Project project, @NotNull final Task task, @NotNull final String fileName, boolean wrapHTML) { + VirtualFile taskDir = task.getTaskDir(project); + if (taskDir != null) { + return StudyUtils.getFileText(taskDir.getCanonicalPath(), fileName, wrapHTML, "UTF-8"); + } + return null; + } +} diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java index f546c900c152..3764d5cf34d3 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java @@ -148,7 +148,7 @@ public class StudyProjectComponent implements ProjectComponent { final Course course = EduStepicConnector.getCourse(myProject, info); if (course == null) return; - flushCourse(course); + flushCourse(myProject, course); course.initCourse(false); StudyLanguageManager manager = StudyUtils.getLanguageManager(course); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java index 574981ead8dd..6c04cd9b1c9b 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java @@ -13,6 +13,7 @@ import com.intellij.util.xmlb.XmlSerializer; import com.intellij.util.xmlb.annotations.Transient; import com.jetbrains.edu.learning.courseFormat.*; import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator; +import com.jetbrains.edu.learning.stepic.StepicUser; import com.jetbrains.edu.learning.ui.StudyToolWindow; import org.jdom.Element; import org.jdom.output.XMLOutputter; @@ -34,6 +35,7 @@ import java.util.Map; public class StudyTaskManager implements PersistentStateComponent, DumbAware { private static final Logger LOG = Logger.getInstance(StudyTaskManager.class); public static final int CURRENT_VERSION = 4; + private StepicUser myUser = new StepicUser(); private Course myCourse; public int VERSION = 4; @@ -197,6 +199,15 @@ public class StudyTaskManager implements PersistentStateComponent, Dumb myTurnEditingMode = turnEditingMode; } + @NotNull + public StepicUser getUser() { + return myUser; + } + + public void setUser(@NotNull final StepicUser user) { + myUser = user; + } + public boolean isEnableTestingFromSamples() { return myEnableTestingFromSamples; } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java index 6ac29a52f8de..99d184d14744 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java @@ -61,7 +61,6 @@ import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.*; import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator; import com.jetbrains.edu.learning.editor.StudyEditor; -import com.jetbrains.edu.learning.stepic.StepicUpdateSettings; import com.jetbrains.edu.learning.ui.StudyToolWindow; import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; import com.petebevin.markdown.MarkdownProcessor; @@ -628,12 +627,12 @@ public class StudyUtils { } @NotNull - public static File getCourseDirectory(Course course) { + public static File getCourseDirectory(@NotNull Project project, Course course) { final File courseDirectory; if (course.isAdaptive()) { courseDirectory = new File(StudyProjectGenerator.OUR_COURSES_DIR, StudyProjectGenerator.ADAPTIVE_COURSE_PREFIX + course.getName() - + "_" + StepicUpdateSettings.getInstance().getUser().getEmail()); + + "_" + StudyTaskManager.getInstance(project).getUser().getEmail()); } else { courseDirectory = new File(StudyProjectGenerator.OUR_COURSES_DIR, course.getName()); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java index b2ee1e17b4b3..bb51a047753a 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java @@ -23,7 +23,6 @@ import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.*; import com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector; import com.jetbrains.edu.learning.stepic.EduStepicConnector; -import com.jetbrains.edu.learning.stepic.StepicUpdateSettings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -105,7 +104,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun runAfterTaskCheckedActions(); final Course course = StudyTaskManager.getInstance(myProject).getCourse(); if (course != null && EduNames.STUDY.equals(course.getCourseMode())) { - if (StepicUpdateSettings.getInstance().getUser().getAccessToken() != null) { + if (StudyTaskManager.getInstance(myProject).getUser().getAccessToken() != null) { EduStepicConnector.postSolution(myTask, testsOutput.isSuccess(), myProject); } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java index 5029459a06c2..2b6f2ab6530c 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java @@ -14,6 +14,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -36,7 +37,6 @@ import com.jetbrains.edu.learning.editor.StudyEditor; import com.jetbrains.edu.learning.statistics.EduUsagesCollector; import com.jetbrains.edu.learning.stepic.CourseInfo; import com.jetbrains.edu.learning.stepic.EduStepicConnector; -import com.jetbrains.edu.learning.stepic.StepicUpdateSettings; import com.jetbrains.edu.learning.stepic.StepicUser; import org.apache.commons.codec.binary.Base64; import org.jetbrains.annotations.NotNull; @@ -57,6 +57,7 @@ public class StudyProjectGenerator { private static final String COURSE_DESCRIPTION = "description"; private static final String CACHE_NAME = "courseNames.txt"; private final List myListeners = ContainerUtil.newArrayList(); + @Nullable public StepicUser myUser; private List myCourses = new ArrayList<>(); private List myEnrolledCoursesIds = new ArrayList<>(); protected CourseInfo mySelectedCourseInfo; @@ -66,8 +67,7 @@ public class StudyProjectGenerator { } public boolean isLoggedIn() { - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); - return user.getAccessToken() != null; + return myUser != null && !StringUtil.isEmptyOrSpaces(myUser.getPassword()) && !StringUtil.isEmptyOrSpaces(myUser.getEmail()); } public void setEnrolledCoursesIds(@NotNull final List coursesIds) { @@ -88,13 +88,16 @@ public class StudyProjectGenerator { } public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir) { + if (myUser != null) { + StudyTaskManager.getInstance(project).setUser(myUser); + } final Course course = getCourse(project); if (course == null) { LOG.warn("Course is null"); Messages.showWarningDialog("Some problems occurred while creating the course", "Error in Course Creation"); return; } - final File courseDirectory = StudyUtils.getCourseDirectory(course); + final File courseDirectory = StudyUtils.getCourseDirectory(project, course); StudyTaskManager.getInstance(project).setCourse(course); ApplicationManager.getApplication().runWriteAction(() -> { StudyGenerator.createCourse(course, baseDir, courseDirectory, project); @@ -117,15 +120,12 @@ public class StudyProjectGenerator { } return getCourseFromStepic(project); } - else { - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); - if (user.getAccessToken() != null) { - final File adaptiveCourseFile = new File(new File(OUR_COURSES_DIR, ADAPTIVE_COURSE_PREFIX + - mySelectedCourseInfo.getName() + "_" + - user.getEmail()), EduNames.COURSE_META_FILE); - if (adaptiveCourseFile.exists()) { - return readCourseFromCache(adaptiveCourseFile, true); - } + else if (myUser != null) { + final File adaptiveCourseFile = new File(new File(OUR_COURSES_DIR, ADAPTIVE_COURSE_PREFIX + + mySelectedCourseInfo.getName() + "_" + + myUser.getEmail()), EduNames.COURSE_META_FILE); + if (adaptiveCourseFile.exists()) { + return readCourseFromCache(adaptiveCourseFile, true); } } return getCourseFromStepic(project); @@ -137,7 +137,7 @@ public class StudyProjectGenerator { return execCancelable(() -> { final Course course = EduStepicConnector.getCourse(project, mySelectedCourseInfo); if (course != null) { - flushCourse(course); + flushCourse(project, course); course.initCourse(false); } return course; @@ -216,8 +216,8 @@ public class StudyProjectGenerator { } } - public static void flushCourse(@NotNull final Course course) { - final File courseDirectory = StudyUtils.getCourseDirectory(course); + public static void flushCourse(@NotNull final Project project, @NotNull final Course course) { + final File courseDirectory = StudyUtils.getCourseDirectory(project, course); FileUtil.createDirectory(courseDirectory); flushCourseJson(course, courseDirectory); @@ -423,7 +423,7 @@ public class StudyProjectGenerator { myCourses = getCoursesFromCache(); } if (force || myCourses.isEmpty()) { - myCourses = execCancelable(() -> EduStepicConnector.getCourses(StepicUpdateSettings.getInstance().getUser())); + myCourses = execCancelable(() -> EduStepicConnector.getCourses(myUser)); flushCache(myCourses); } if (myCourses.isEmpty() || (myCourses.size() == 1 && myCourses.contains(CourseInfo.INVALID_COURSE))) { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java index 246a48fb1850..bd150917850c 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java @@ -43,11 +43,11 @@ public class CCStepicConnector { private CCStepicConnector() { } - public static CourseInfo getCourseInfo(String courseId) { + public static CourseInfo getCourseInfo(Project project, String courseId) { final String url = EduStepicNames.COURSES + "/" + courseId; try { final StepicWrappers.CoursesContainer coursesContainer = - EduStepicAuthorizedClient.getFromStepic(url, StepicWrappers.CoursesContainer.class); + EduStepicAuthorizedClient.getFromStepic(url, StepicWrappers.CoursesContainer.class, project); return coursesContainer.courses.get(0); } catch (IOException e) { @@ -69,7 +69,7 @@ public class CCStepicConnector { indicator.setText("Uploading course to " + EduStepicNames.STEPIC_URL); final HttpPost request = new HttpPost(EduStepicNames.STEPIC_API_URL + "/courses"); - final StepicUser currentUser = EduStepicAuthorizedClient.getCurrentUser(EduStepicAuthorizedClient.getHttpClient()); + final StepicUser currentUser = EduStepicAuthorizedClient.getCurrentUser(EduStepicAuthorizedClient.getHttpClient(project)); if (currentUser != null) { final List courseAuthors = course.getAuthors(); for (int i = 0; i < courseAuthors.size(); i++) { @@ -86,7 +86,7 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -98,12 +98,12 @@ public class CCStepicConnector { } final CourseInfo postedCourse = new Gson().fromJson(responseString, StepicWrappers.CoursesContainer.class).courses.get(0); course.setId(postedCourse.id); - final int sectionId = postModule(postedCourse.id, 1, String.valueOf(postedCourse.getName())); + final int sectionId = postModule(project, postedCourse.id, 1, String.valueOf(postedCourse.getName())); int position = 1; for (Lesson lesson : course.getLessons()) { indicator.checkCanceled(); final int lessonId = postLesson(project, lesson, indicator); - postUnit(lessonId, position, sectionId); + postUnit(project, lessonId, position, sectionId); position += 1; } ApplicationManager.getApplication().runReadAction(() -> postAdditionalFiles(project, postedCourse.id, indicator)); @@ -125,7 +125,7 @@ public class CCStepicConnector { }); if (!files.isEmpty()) { - final int sectionId = postModule(id, 2, EduNames.PYCHARM_ADDITIONAL); + final int sectionId = postModule(project, id, 2, EduNames.PYCHARM_ADDITIONAL); final Lesson lesson = new Lesson(); lesson.setName(EduNames.PYCHARM_ADDITIONAL); final Task task = new Task(); @@ -151,11 +151,11 @@ public class CCStepicConnector { lesson.addTask(task); lesson.setIndex(1); final int lessonId = postLesson(project, lesson, indicator); - postUnit(lessonId, 1, sectionId); + postUnit(project, lessonId, 1, sectionId); } } - public static void postUnit(int lessonId, int position, int sectionId) { + public static void postUnit(@NotNull final Project project, int lessonId, int position, int sectionId) { final HttpPost request = new HttpPost(EduStepicNames.STEPIC_API_URL + EduStepicNames.UNITS); final StepicWrappers.UnitWrapper unitWrapper = new StepicWrappers.UnitWrapper(); unitWrapper.unit = new StepicWrappers.Unit(); @@ -167,7 +167,7 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -182,7 +182,7 @@ public class CCStepicConnector { } } - private static int postModule(int courseId, int position, @NotNull final String title) { + private static int postModule(@NotNull final Project project, int courseId, int position, @NotNull final String title) { final HttpPost request = new HttpPost(EduStepicNames.STEPIC_API_URL + "/sections"); final StepicWrappers.Section section = new StepicWrappers.Section(); section.course = courseId; @@ -194,7 +194,7 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -226,7 +226,7 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -250,7 +250,7 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -262,7 +262,7 @@ public class CCStepicConnector { } final Lesson postedLesson = new Gson().fromJson(responseString, Course.class).getLessons().get(0); for (Integer step : postedLesson.steps) { - deleteTask(step); + deleteTask(step, project); } for (Task task : lesson.getTaskList()) { @@ -284,7 +284,7 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -308,11 +308,11 @@ public class CCStepicConnector { return -1; } - public static void deleteTask(@NotNull final Integer task) { + public static void deleteTask(@NotNull final Integer task, Project project) { final HttpDelete request = new HttpDelete(EduStepicNames.STEPIC_API_URL + EduStepicNames.STEP_SOURCES + task); ApplicationManager.getApplication().invokeLater(() -> { try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -337,7 +337,7 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final StatusLine line = response.getStatusLine(); final HttpEntity responseEntity = response.getEntity(); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java index 28ead09933d2..ef9e9e156ab1 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java @@ -67,7 +67,7 @@ public class EduAdaptiveStepicConnector { @Nullable public static Task getNextRecommendation(@NotNull Project project, @NotNull Course course) { try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final URI uri = new URIBuilder(EduStepicNames.STEPIC_API_URL + EduStepicNames.RECOMMENDATIONS_URL) .addParameter(EduNames.COURSE, String.valueOf(course.getId())) .build(); @@ -88,7 +88,8 @@ public class EduAdaptiveStepicConnector { final StepicWrappers.Recommendation recommendation = recomWrapper.recommendations[0]; final String lessonId = recommendation.lesson; final StepicWrappers.LessonContainer lessonContainer = EduStepicAuthorizedClient.getFromStepic(EduStepicNames.LESSONS + lessonId, - StepicWrappers.LessonContainer.class); + StepicWrappers.LessonContainer.class, + project); if (lessonContainer.lessons.size() == 1) { final Lesson realLesson = lessonContainer.lessons.get(0); course.getLessons().get(0).setId(Integer.parseInt(lessonId)); @@ -98,8 +99,8 @@ public class EduAdaptiveStepicConnector { if (taskFromStep != null) return taskFromStep; } - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); - postRecommendationReaction(lessonId, + final StepicUser user = StudyTaskManager.getInstance(project).getUser(); + postRecommendationReaction(project, lessonId, String.valueOf(user.getId()), -1); return getNextRecommendation(project, course); } @@ -136,29 +137,30 @@ public class EduAdaptiveStepicConnector { @Nullable private static Task getTask(@NotNull Project project, @NotNull String name, int stepId) throws IOException { - final StepicWrappers.StepSource step = getStep(stepId); + final StepicWrappers.StepSource step = getStep(project, stepId); final String stepType = step.block.name; if (stepType.equals(CODE_TASK_TYPE)) { return getCodeTaskFromStep(project, step.block, name, stepId); } else if (stepType.equals(CHOICE_TYPE_TEXT)) { - return getChoiceTaskFromStep(name, step.block, stepId); + return getChoiceTaskFromStep(project, name, step.block, stepId); } else if (stepType.startsWith(EduStepicConnector.PYCHARM_PREFIX)) { - return EduStepicConnector.createTask(stepId); + return EduStepicConnector.createTask(project, stepId); } return null; } - private static Task getChoiceTaskFromStep(@NotNull String lessonName, + private static Task getChoiceTaskFromStep(@NotNull Project project, + @NotNull String lessonName, @NotNull StepicWrappers.Step block, int stepId) { final Task task = new Task(lessonName); task.setStepId(stepId); task.setText(block.text); - final StepicWrappers.AdaptiveAttemptWrapper.Attempt attempt = getAttemptForStep(stepId); + final StepicWrappers.AdaptiveAttemptWrapper.Attempt attempt = getAttemptForStep(project, stepId); if (attempt != null) { final StepicWrappers.AdaptiveAttemptWrapper.Dataset dataset = attempt.dataset; if (dataset != null) { @@ -182,16 +184,16 @@ public class EduAdaptiveStepicConnector { } @Nullable - private static StepicWrappers.AdaptiveAttemptWrapper.Attempt getAttemptForStep(int id) { - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + private static StepicWrappers.AdaptiveAttemptWrapper.Attempt getAttemptForStep(@NotNull Project project, int id) { + final StepicUser user = StudyTaskManager.getInstance(project).getUser(); try { final List attempts = getAttempts(user, id); if (attempts != null && attempts.size() > 0) { final StepicWrappers.AdaptiveAttemptWrapper.Attempt attempt = attempts.get(0); - return attempt.isActive() ? attempt : createNewAttempt(id); + return attempt.isActive() ? attempt : createNewAttempt(project, id); } else { - return createNewAttempt(id); + return createNewAttempt(project, id); } } catch (URISyntaxException | IOException e) { @@ -200,8 +202,8 @@ public class EduAdaptiveStepicConnector { return null; } - private static StepicWrappers.AdaptiveAttemptWrapper.Attempt createNewAttempt(int id) throws IOException { - final String response = EduStepicConnector.postAttempt(id); + private static StepicWrappers.AdaptiveAttemptWrapper.Attempt createNewAttempt(@NotNull Project project, int id) throws IOException { + final String response = EduStepicConnector.postAttempt(project, id); final StepicWrappers.AdaptiveAttemptContainer attempt = new Gson().fromJson(response, StepicWrappers.AdaptiveAttemptContainer.class); return attempt.attempts.get(0); } @@ -235,14 +237,15 @@ public class EduAdaptiveStepicConnector { request.setConfig(requestConfig); } - public static boolean postRecommendationReaction(@NotNull String lessonId, + public static boolean postRecommendationReaction(@NotNull Project project, + @NotNull String lessonId, @NotNull String user, int reaction) { final HttpPost post = new HttpPost(EduStepicNames.STEPIC_API_URL + EduStepicNames.RECOMMENDATION_REACTIONS_URL); final String json = new Gson() .toJson(new StepicWrappers.RecommendationReactionWrapper(new StepicWrappers.RecommendationReaction(reaction, user, lessonId))); post.setEntity(new StringEntity(json, ContentType.APPLICATION_JSON)); - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); setTimeout(post); try { final CloseableHttpResponse execute = client.execute(post); @@ -271,10 +274,10 @@ public class EduAdaptiveStepicConnector { final Course course = StudyTaskManager.getInstance(project).getCourse(); if (course != null && editor != null && editor.getTaskFile() != null) { indicator.checkCanceled(); - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + final StepicUser user = StudyTaskManager.getInstance(project).getUser(); final boolean recommendationReaction = - postRecommendationReaction(String.valueOf(editor.getTaskFile().getTask().getLesson().getId()), + postRecommendationReaction(project, String.valueOf(editor.getTaskFile().getTask().getLesson().getId()), String.valueOf(user.getId()), reaction); if (recommendationReaction) { indicator.checkCanceled(); @@ -470,7 +473,7 @@ public class EduAdaptiveStepicConnector { public static Pair checkChoiceTask(@NotNull Project project, @NotNull Task task) { if (task.getSelectedVariants().isEmpty()) return Pair.create(false, "No variants selected"); - final StepicWrappers.AdaptiveAttemptWrapper.Attempt attempt = getAttemptForStep(task.getStepId()); + final StepicWrappers.AdaptiveAttemptWrapper.Attempt attempt = getAttemptForStep(project, task.getStepId()); if (attempt != null) { final int attemptId = attempt.id; @@ -480,10 +483,10 @@ public class EduAdaptiveStepicConnector { if (!isActiveAttempt) return Pair.create(false, "Your solution is out of date. Please try again"); final StepicWrappers.SubmissionToPostWrapper wrapper = new StepicWrappers.SubmissionToPostWrapper(String.valueOf(attemptId), createChoiceTaskAnswerArray(task)); - final Pair pair = doAdaptiveCheck(wrapper, attemptId); + final Pair pair = doAdaptiveCheck(project, wrapper, attemptId); if (!pair.getFirst()) { try { - createNewAttempt(task.getStepId()); + createNewAttempt(project, task.getStepId()); final Task updatedTask = getTask(project, task.getName(), task.getStepId()); if (updatedTask != null) { final List variants = updatedTask.getChoiceVariants(); @@ -514,7 +517,7 @@ public class EduAdaptiveStepicConnector { public static Pair checkCodeTask(@NotNull Project project, @NotNull Task task) { int attemptId = -1; try { - attemptId = getAttemptId(task); + attemptId = getAttemptId(project, task); } catch (IOException e) { LOG.warn(e.getMessage()); @@ -526,7 +529,7 @@ public class EduAdaptiveStepicConnector { final String answer = PYCHARM_COMMENT + editor.getDocument().getText(); final StepicWrappers.SubmissionToPostWrapper submissionToPost = new StepicWrappers.SubmissionToPostWrapper(String.valueOf(attemptId), language, answer); - return doAdaptiveCheck(submissionToPost, attemptId); + return doAdaptiveCheck(project, submissionToPost, attemptId); } } else { @@ -535,10 +538,11 @@ public class EduAdaptiveStepicConnector { return Pair.create(false, ""); } - private static Pair doAdaptiveCheck(@NotNull StepicWrappers.SubmissionToPostWrapper submission, + private static Pair doAdaptiveCheck(@NotNull Project project, + @NotNull StepicWrappers.SubmissionToPostWrapper submission, int attemptId) { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); + final StepicUser user = StudyTaskManager.getInstance(project).getUser(); StepicWrappers.ResultSubmissionWrapper wrapper = postResultsForCheck(client, submission); if (wrapper != null) { wrapper = getCheckResults(client, wrapper, attemptId, user.getId()); @@ -636,13 +640,13 @@ public class EduAdaptiveStepicConnector { return null; } - private static int getAttemptId(@NotNull Task task) throws IOException { + private static int getAttemptId(@NotNull final Project project, @NotNull Task task) throws IOException { final StepicWrappers.AdaptiveAttemptWrapper attemptWrapper = new StepicWrappers.AdaptiveAttemptWrapper(task.getStepId()); final HttpPost post = new HttpPost(EduStepicNames.STEPIC_API_URL + EduStepicNames.ATTEMPTS); post.setEntity(new StringEntity(new Gson().toJson(attemptWrapper))); - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); setTimeout(post); final CloseableHttpResponse httpResponse = client.execute(post); final int statusCode = httpResponse.getStatusLine().getStatusCode(); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java index de79476be1c0..c197c91e7f32 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java @@ -5,9 +5,12 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.net.ssl.CertificateManager; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.StudyUtils; import org.apache.http.*; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; @@ -45,24 +48,24 @@ public class EduStepicAuthorizedClient { } @NotNull - public static CloseableHttpClient getHttpClient() { + public static CloseableHttpClient getHttpClient(@NotNull final Project project) { if (ourClient != null) { return ourClient; } - final StepicUser stepicUser = StepicUpdateSettings.getInstance().getUser(); + final StepicUser stepicUser = StudyTaskManager.getInstance(project).getUser(); ourClient = initializeClient(stepicUser); if (ourClient == null) { final StepicUser user = login(stepicUser); if (user != null) { - StepicUpdateSettings.getInstance().setUser(user); + StudyTaskManager.getInstance(project).setUser(user); ourClient = initializeClient(stepicUser); } } return ourClient; } - public static T getFromStepic(String link, final Class container) throws IOException { - return EduStepicClient.getFromStepic(link, container, getHttpClient()); + public static T getFromStepic(String link, final Class container, @NotNull final Project project) throws IOException { + return EduStepicClient.getFromStepic(link, container, getHttpClient(project)); } /* @@ -101,7 +104,10 @@ public class EduStepicAuthorizedClient { else { final StepicUser authorizedUser = login(stepicUser); if (authorizedUser != null) { - StepicUpdateSettings.getInstance().setUser(authorizedUser); + final Project project = StudyUtils.getStudyProject(); + if (project != null) { + StudyTaskManager.getInstance(project).setUser(authorizedUser); + } return initializeClient(authorizedUser); } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java index 3af448d0da98..d41cca60dff3 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java @@ -9,6 +9,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.courseFormat.Lesson; import com.jetbrains.edu.learning.courseFormat.Task; @@ -203,7 +204,7 @@ public class EduStepicConnector { course.setLanguage(language); try { for (Integer section : info.sections) { - course.addLessons(getLessons(section)); + course.addLessons(getLessons(project, section)); } return course; } @@ -229,23 +230,23 @@ public class EduStepicConnector { return null; } - public static List getLessons(int sectionId) throws IOException { + public static List getLessons(@NotNull Project project, int sectionId) throws IOException { final StepicWrappers.SectionContainer sectionContainer = getFromStepic(EduStepicNames.SECTIONS + String.valueOf(sectionId), - StepicWrappers.SectionContainer.class); + StepicWrappers.SectionContainer.class, project); List unitIds = sectionContainer.sections.get(0).units; final List lessons = new ArrayList<>(); for (Integer unitId : unitIds) { StepicWrappers.UnitContainer - unit = getFromStepic(EduStepicNames.UNITS + "/" + String.valueOf(unitId), StepicWrappers.UnitContainer.class); + unit = getFromStepic(EduStepicNames.UNITS + "/" + String.valueOf(unitId), StepicWrappers.UnitContainer.class, project); int lessonID = unit.units.get(0).lesson; StepicWrappers.LessonContainer lessonContainer = getFromStepic(EduStepicNames.LESSONS + String.valueOf(lessonID), - StepicWrappers.LessonContainer.class); + StepicWrappers.LessonContainer.class, project); Lesson lesson = lessonContainer.lessons.get(0); lesson.taskList = new ArrayList<>(); for (int stepId : lesson.steps) { - final Task task = createTask(stepId); + final Task task = createTask(project, stepId); if (task != null) { lesson.addTask(task); } @@ -258,18 +259,20 @@ public class EduStepicConnector { return lessons; } - private static T getFromStepic(String link, final Class container) throws IOException{ - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); - final boolean isAuthorized = user.getAccessToken() != null; - if (isAuthorized) { - return EduStepicAuthorizedClient.getFromStepic(link, container, user); + private static T getFromStepic(String link, final Class container, @Nullable final Project project) throws IOException{ + if (project != null) { + final StepicUser user = StudyTaskManager.getInstance(project).getUser(); + final boolean isAuthorized = user.getAccessToken() != null; + if (isAuthorized) { + return EduStepicAuthorizedClient.getFromStepic(link, container, user); + } } return EduStepicClient.getFromStepic(link, container); } @Nullable - public static Task createTask(int stepicId) throws IOException { - final StepicWrappers.StepSource step = getStep(stepicId); + public static Task createTask(@NotNull Project project, int stepicId) throws IOException { + final StepicWrappers.StepSource step = getStep(project, stepicId); final StepicWrappers.Step block = step.block; if (!block.name.startsWith(PYCHARM_PREFIX)) { LOG.error("Got a block with non-pycharm prefix: " + block.name + " for step: " + stepicId); @@ -300,9 +303,9 @@ public class EduStepicConnector { return task; } - public static StepicWrappers.StepSource getStep(int step) throws IOException { + public static StepicWrappers.StepSource getStep(@NotNull Project project, int step) throws IOException { return getFromStepic(EduStepicNames.STEPS + String.valueOf(step), - StepicWrappers.StepContainer.class).steps.get(0); + StepicWrappers.StepContainer.class, project).steps.get(0); } public static void postSolution(@NotNull final Task task, boolean passed, @NotNull final Project project) { @@ -311,7 +314,7 @@ public class EduStepicConnector { } try { - final String response = postAttempt(task.getStepId()); + final String response = postAttempt(project, task.getStepId()); if (response.isEmpty()) return; final StepicWrappers.AttemptWrapper.Attempt attempt = new Gson().fromJson(response, StepicWrappers.AttemptContainer.class).attempts.get(0); @@ -335,16 +338,16 @@ public class EduStepicConnector { } } - postSubmission(passed, attempt, files); + postSubmission(passed, attempt, project, files); } catch (IOException e) { LOG.error(e.getMessage()); } } - public static String postAttempt(int id) throws IOException { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); - if (StepicUpdateSettings.getInstance().getUser().getAccessToken() == null) return ""; + public static String postAttempt(@NotNull Project project, int id) throws IOException { + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); + if (StudyTaskManager.getInstance(project).getUser().getAccessToken() == null) return ""; final HttpPost attemptRequest = new HttpPost(EduStepicNames.STEPIC_API_URL + EduStepicNames.ATTEMPTS); String attemptRequestBody = new Gson().toJson(new StepicWrappers.AttemptWrapper(id)); attemptRequest.setEntity(new StringEntity(attemptRequestBody, ContentType.APPLICATION_JSON)); @@ -361,12 +364,12 @@ public class EduStepicConnector { } private static void postSubmission(boolean passed, StepicWrappers.AttemptWrapper.Attempt attempt, - ArrayList files) throws IOException { + Project project, ArrayList files) throws IOException { final HttpPost request = new HttpPost(EduStepicNames.STEPIC_API_URL + EduStepicNames.SUBMISSIONS); String requestBody = new Gson().toJson(new StepicWrappers.SubmissionWrapper(attempt.id, passed ? "1" : "0", files)); request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(project); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java index bc6fcc98d668..607dcc6400d4 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java @@ -92,7 +92,7 @@ public class StepicStudyOptions implements StudyOptionsProvider { Project project = StudyUtils.getStudyProject(); if (project != null) { StudyTaskManager taskManager = StudyTaskManager.getInstance(project); - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + final StepicUser user = taskManager.getUser(); setLogin(user.getEmail()); setPassword(user.getPassword()); myEnableTestingFromSamples.setSelected(taskManager.isEnableTestingFromSamples()); @@ -116,7 +116,7 @@ public class StepicStudyOptions implements StudyOptionsProvider { taskManager.setEnableTestingFromSamples(isTestingFromSamplesEnabled()); } - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + final StepicUser user = taskManager.getUser(); final boolean isCredentialsModified = !getLogin().equals(user.getEmail()) || !getPassword().equals(user.getPassword()); if (isCredentialsModified) { final String login = getLogin(); @@ -132,14 +132,14 @@ public class StepicStudyOptions implements StudyOptionsProvider { myProject); if (stepicUser[0] != null && stepicUser[0].getAccessToken() != null) { - StepicUpdateSettings.getInstance().setUser(stepicUser[0]); + taskManager.setUser(stepicUser[0]); } else { throw new ConfigurationException("Unable to login"); } } else { - removeCredentials(); + removeCredentials(taskManager); } } } @@ -148,8 +148,8 @@ public class StepicStudyOptions implements StudyOptionsProvider { } } - private static void removeCredentials() { - StepicUpdateSettings.getInstance().setUser(new StepicUser()); + private static void removeCredentials(StudyTaskManager taskManager) { + taskManager.setUser(new StepicUser()); } @Nullable @@ -163,7 +163,7 @@ public class StepicStudyOptions implements StudyOptionsProvider { if (project == null) return false; final StudyTaskManager taskManager = StudyTaskManager.getInstance(project); - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + final StepicUser user = taskManager.getUser(); return !getLogin().equals(user.getEmail()) || !getPassword().equals(user.getPassword()) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicUpdateSettings.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicUpdateSettings.java index daa80c2ae446..241418d0f672 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicUpdateSettings.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicUpdateSettings.java @@ -5,12 +5,10 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.util.xmlb.XmlSerializerUtil; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @State(name = "StepicUpdateSettings", storages = @Storage("other.xml")) public class StepicUpdateSettings implements PersistentStateComponent { - private StepicUser myUser = new StepicUser(); public long LAST_TIME_CHECKED = 0; public StepicUpdateSettings() { @@ -39,13 +37,4 @@ public class StepicUpdateSettings implements PersistentStateComponent courses = myGenerator.getCourses(true); if (courses != null && myRefreshCourseList) { diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java index 40b306cb8d01..eba2f1d3bd04 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java @@ -27,7 +27,6 @@ import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator; import com.jetbrains.edu.learning.stepic.CourseInfo; import com.jetbrains.edu.learning.stepic.EduStepicConnector; -import com.jetbrains.edu.learning.stepic.StepicUpdateSettings; import com.jetbrains.edu.learning.ui.StudyNewProjectPanel; import com.jetbrains.python.configuration.PyConfigurableInterpreterList; import com.jetbrains.python.newProject.PyNewProjectSettings; @@ -189,8 +188,7 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator 0 && !enrolledCoursesIds.contains(course.getId())) { ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> { ProgressManager.getInstance().getProgressIndicator().setIndeterminate(true); - return StudyUtils.execCancelable(() -> EduStepicConnector.enrollToCourse(course.getId(), - StepicUpdateSettings.getInstance().getUser())); + return StudyUtils.execCancelable(() -> EduStepicConnector.enrollToCourse(course.getId(), myGenerator.myUser)); }, "Creating Course", true, ProjectManager.getInstance().getDefaultProject()); }