/*
* Copyright 2003-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.workbench.dialogs.project.newproject;
import com.intellij.ide.startup.StartupManagerEx;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.platform.ProjectBaseDirectory;
import jetbrains.mps.ide.newSolutionDialog.NewModuleUtil;
import jetbrains.mps.ide.projectPane.ProjectPane;
import jetbrains.mps.migration.global.ProjectMigrationUtil;
import jetbrains.mps.project.MPSExtentions;
import jetbrains.mps.project.MPSProject;
import jetbrains.mps.project.MPSProjectVersion;
import jetbrains.mps.project.SModuleOperations;
import jetbrains.mps.project.Solution;
import jetbrains.mps.project.StandaloneMPSProject;
import jetbrains.mps.smodel.Language;
import jetbrains.mps.smodel.SModelInternal;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.util.annotation.ToRemove;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.EditableSModel;
import java.io.File;
public class ProjectFactory {
private ProjectOptions myOptions;
private Project myCreatedProject;
private Language myCreatedLanguage;
private Solution myCreatedSolution;
public ProjectFactory(ProjectOptions options) {
myOptions = options;
}
/**
* @deprecated parameter {@code currentProject} is not used any more.
* Use {@link ProjectFactory#ProjectFactory(jetbrains.mps.workbench.dialogs.project.newproject.ProjectOptions)} constructor instead
*/
@Deprecated
@ToRemove(version = 2017.1)
public ProjectFactory(Project currentProject, ProjectOptions options) {
this(options);
}
public Project createProject() throws ProjectNotCreatedException {
final String[] error = new String[]{null};
ProgressManager.getInstance().run(new Task.Modal(null, "Creating Project", false) {
@Override
public void run(@NotNull() ProgressIndicator indicator) {
indicator.setIndeterminate(true);
error[0] = createDirs();
if (error[0] != null) {
return;
}
String suffix;
if (myOptions.getStorageScheme().equals(StorageScheme.DIRECTORY_BASED)) {
suffix = Project.DIRECTORY_STORE_FOLDER;
} else {
suffix = myOptions.getProjectName() + MPSExtentions.DOT_MPS_PROJECT;
}
final String projectFilePath = myOptions.getProjectPath() + File.separator + suffix;
//MPS-22895 need to run in EDT
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
try {
myCreatedProject = ProjectManagerEx.getInstanceEx().newProject(myOptions.getProjectName(), projectFilePath, true, false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, indicator.getModalityState());
}
});
if (error[0] != null) {
throw new ProjectNotCreatedException(error[0]);
}
boolean doNotSave = ApplicationManagerEx.getApplicationEx().isDoNotSave();
try {
ApplicationManagerEx.getApplicationEx().doNotSave(false);
myCreatedProject.save();
} finally {
ApplicationManagerEx.getApplicationEx().doNotSave(doNotSave);
}
//noinspection ConstantConditions
final MPSProject mpsProject = myCreatedProject.getComponent(MPSProject.class);
assert mpsProject != null;
StartupManager.getInstance(myCreatedProject).registerPostStartupActivity(() -> mpsProject.getModelAccess().executeCommand(() -> {
if (myOptions.getCreateNewLanguage()) {
myCreatedLanguage = NewModuleUtil.createLanguage(myOptions.getLanguageNamespace(), myOptions.getLanguagePath(), mpsProject);
}
if (myOptions.getCreateNewSolution()) {
myCreatedSolution = NewModuleUtil.createSolution(myOptions.getSolutionNamespace(), myOptions.getSolutionPath(), mpsProject);
}
if (myCreatedSolution != null && myCreatedLanguage != null) {
myCreatedSolution.save();
if (myOptions.getCreateModel()) {
EditableSModel model = SModuleOperations.createModelWithAdjustments(
myCreatedSolution.getModuleReference().getModuleName() + ".sandbox",
myCreatedSolution.getModelRoots().iterator().next());
((SModelInternal) model).addLanguage(MetaAdapterFactory.getLanguage(myCreatedLanguage.getModuleReference()));
model.save();
}
}
if (myOptions.getCreateNewSolution() || myOptions.getCreateNewLanguage()) {
((StandaloneMPSProject) mpsProject).update();
}
}));
return myCreatedProject;
}
public void activate() {
if (myCreatedProject == null) {
return;
}
myCreatedProject.getComponent(MPSProjectVersion.class).setVersion(MPSProjectVersion.CURRENT);
ProjectMigrationUtil.skipMigrationsOnProjectCreation(myCreatedProject);
ProjectBaseDirectory.getInstance(myCreatedProject).setBaseDir(myCreatedProject.getBaseDir());
ProjectManagerEx projectManager = ProjectManagerEx.getInstanceEx();
boolean opened = projectManager.openProject(myCreatedProject);
if (opened) {
StartupManagerEx startupManager = StartupManagerEx.getInstanceEx(myCreatedProject);
// extra .invokeLater() was added here (copied from IDEA platform) see: https://youtrack.jetbrains.com/issue/IDEA-158859
Runnable projectPaneActivator =
() -> ApplicationManager.getApplication().invokeLater(ProjectPane.getInstance(myCreatedProject)::activate, ModalityState.NON_MODAL);
if (startupManager.postStartupActivityPassed()) {
startupManager.runWhenProjectIsInitialized(projectPaneActivator);
} else {
startupManager.registerPostStartupActivity(projectPaneActivator);
}
}
}
@Nullable
private String createDirs() {
File projectDirFile = new File(myOptions.getProjectPath());
if (!(projectDirFile.exists())) {
if (!projectDirFile.mkdirs()) {
return "Couldn't create project directory";
}
}
if (myOptions.getCreateNewLanguage()) {
File languageDirFile = new File(myOptions.getLanguagePath());
if (!(languageDirFile.exists())) {
if (!languageDirFile.mkdirs()) {
return "Couldn't create language directory";
}
}
}
if (myOptions.getCreateNewSolution()) {
String path = myOptions.getSolutionPath() + File.separator + myOptions.getSolutionNamespace() + MPSExtentions.DOT_SOLUTION;
File solutionDescriptorFile = new File(path);
File dir = solutionDescriptorFile.getParentFile();
if (!(dir.exists())) {
if (!dir.mkdirs()) {
return "Couldn't create solution directory";
}
}
}
return null;
}
public static class ProjectNotCreatedException extends Exception {
public ProjectNotCreatedException(String message) {
super(message);
}
}
}