71b0591cef6c20913ebf3c9fe8c8a4eafcdf9872
[idea/community.git] / java / idea-ui / src / com / intellij / ide / util / newProjectWizard / AddModuleWizard.java
1 // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.ide.util.newProjectWizard;
3
4 import com.intellij.ide.util.newProjectWizard.modes.ImportMode;
5 import com.intellij.ide.util.newProjectWizard.modes.WizardMode;
6 import com.intellij.ide.util.projectWizard.ModuleWizardStep;
7 import com.intellij.ide.util.projectWizard.ProjectBuilder;
8 import com.intellij.ide.util.projectWizard.WizardContext;
9 import com.intellij.ide.wizard.Step;
10 import com.intellij.openapi.project.Project;
11 import com.intellij.openapi.projectRoots.ProjectJdkTable;
12 import com.intellij.openapi.projectRoots.Sdk;
13 import com.intellij.openapi.projectRoots.SdkTypeId;
14 import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
15 import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
16 import com.intellij.projectImport.ProjectImportBuilder;
17 import com.intellij.projectImport.ProjectImportProvider;
18 import com.intellij.util.containers.ContainerUtil;
19 import org.jetbrains.annotations.NotNull;
20 import org.jetbrains.annotations.Nullable;
21 import org.jetbrains.annotations.TestOnly;
22
23 import java.awt.*;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.function.Function;
28
29 import static java.util.stream.Collectors.*;
30
31 public class AddModuleWizard extends AbstractProjectWizard {
32   private final List<ProjectImportProvider> myImportProviders;
33   private final ModulesProvider myModulesProvider;
34   private WizardMode myWizardMode;
35
36   /**
37    * @param project if null, the wizard will start creating new project, otherwise will add a new module to the existing project.
38    */
39   public AddModuleWizard(@Nullable Project project, String filePath, ProjectImportProvider... importProviders) {
40     super(getImportWizardTitle(project, importProviders), project, filePath);
41     myImportProviders = Arrays.asList(importProviders);
42     myModulesProvider = DefaultModulesProvider.createForProject(project);
43     initModuleWizard(project, filePath);
44   }
45
46   /**
47    * @param project if null, the wizard will start creating new project, otherwise will add a new module to the existing project.
48    */
49   public AddModuleWizard(Project project, Component dialogParent, String filePath, ProjectImportProvider... importProviders) {
50     super(getImportWizardTitle(project, importProviders), project, dialogParent);
51     myImportProviders = Arrays.asList(importProviders);
52     myModulesProvider = DefaultModulesProvider.createForProject(project);
53     initModuleWizard(project, filePath);
54   }
55
56   private static String getImportWizardTitle(Project project, ProjectImportProvider... providers) {
57     StringBuilder builder = new StringBuilder("Import ");
58     builder.append(project == null ? "Project" : "Module");
59     if (providers.length == 1) {
60       builder.append(" from ").append(providers[0].getName());
61     }
62     return builder.toString();
63   }
64
65   private void initModuleWizard(@Nullable final Project project, @Nullable final String defaultPath) {
66     myWizardContext.addContextListener(new WizardContext.Listener() {
67       @Override
68       public void buttonsUpdateRequested() {
69         updateButtons();
70       }
71
72       @Override
73       public void nextStepRequested() {
74         doNextAction();
75       }
76     });
77
78     myWizardMode = new ImportMode(myImportProviders);
79     StepSequence sequence = myWizardMode.getSteps(myWizardContext, DefaultModulesProvider.createForProject(project));
80     appendSteps(sequence);
81     for (ProjectImportProvider provider : myImportProviders) {
82       provider.getBuilder().setFileToImport(defaultPath);
83     }
84     if (myImportProviders.size() == 1) {
85       final ProjectImportBuilder builder = myImportProviders.get(0).getBuilder();
86       myWizardContext.setProjectBuilder(builder);
87       builder.setUpdate(getWizardContext().getProject() != null);
88     }
89     init();
90   }
91
92   private void appendSteps(@Nullable final StepSequence sequence) {
93     if (sequence != null) {
94       for (ModuleWizardStep step : sequence.getAllSteps()) {
95         addStep(step);
96       }
97     }
98   }
99
100   @Override
101   public StepSequence getSequence() {
102     return myWizardMode.getSteps(myWizardContext, myModulesProvider);
103   }
104
105   @Nullable
106   public static Sdk getMostRecentSuitableSdk(final WizardContext context) {
107     if (context.getProject() == null) {
108       List<Sdk> sdks = Arrays.asList(ProjectJdkTable.getInstance().getAllJdks());
109
110       ProjectBuilder builder = context.getProjectBuilder();
111       if (builder != null) {
112         sdks = ContainerUtil.filter(sdks, sdk -> builder.isSuitableSdkType(sdk.getSdkType()));
113       }
114
115       Map<SdkTypeId, List<Sdk>> sdksByType = sdks.stream().collect(groupingBy(Sdk::getSdkType, mapping(Function.identity(), toList())));
116       Map.Entry<SdkTypeId, List<Sdk>> pair = ContainerUtil.getFirstItem(sdksByType.entrySet());
117       if (pair != null) {
118         return pair.getValue().stream().max(pair.getKey().versionComparator()).orElse(null);
119       }
120     }
121
122     return null;
123   }
124
125   @NotNull
126   public WizardContext getWizardContext() {
127     return myWizardContext;
128   }
129
130   @Override
131   protected String getDimensionServiceKey() {
132     return "NewModule_or_Project.wizard";
133   }
134
135   /**
136    * Allows to ask current wizard to move to the desired step.
137    *
138    * @param filter  closure that allows to indicate target step - is called with each of registered steps and is expected
139    *                to return {@code true} for the step to go to
140    * @return        {@code true} if current wizard is navigated to the target step; {@code false} otherwise
141    */
142   public boolean navigateToStep(@NotNull com.intellij.util.Function<? super Step, Boolean> filter) {
143     for (int i = 0, myStepsSize = mySteps.size(); i < myStepsSize; i++) {
144       ModuleWizardStep step = mySteps.get(i);
145       if (filter.fun(step) != Boolean.TRUE) {
146         continue;
147       }
148
149       // Update current step.
150       myCurrentStep = i;
151       updateStep();
152       return true;
153     }
154     return false;
155   }
156
157   @TestOnly
158   public void commit() {
159     commitStepData(getCurrentStepObject());
160   }
161 }