Revert "prefer to use JDK utils in low-level classes, do not extend DynamicBundle...
[idea/community.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / configuration / GeneralProjectSettingsElement.java
1 /*
2  * Copyright 2000-2011 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.intellij.openapi.roots.ui.configuration;
17
18 import com.intellij.compiler.ModuleCompilerUtil;
19 import com.intellij.compiler.ModuleSourceSet;
20 import com.intellij.compiler.server.impl.BuildProcessCustomPluginsConfiguration;
21 import com.intellij.ide.IdeBundle;
22 import com.intellij.ide.JavaUiBundle;
23 import com.intellij.openapi.module.Module;
24 import com.intellij.openapi.module.ModuleManager;
25 import com.intellij.openapi.module.UnloadedModuleDescription;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.projectRoots.Sdk;
28 import com.intellij.openapi.roots.ModuleRootModel;
29 import com.intellij.openapi.roots.libraries.Library;
30 import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
31 import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
32 import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*;
33 import com.intellij.openapi.util.text.StringUtil;
34 import com.intellij.util.Chunk;
35 import com.intellij.util.containers.MultiMap;
36 import org.jetbrains.annotations.Nls;
37 import org.jetbrains.annotations.NonNls;
38 import org.jetbrains.annotations.NotNull;
39
40 import java.util.*;
41
42 public class GeneralProjectSettingsElement extends ProjectStructureElement {
43   public GeneralProjectSettingsElement(@NotNull StructureConfigurableContext context) {
44     super(context);
45   }
46
47   @NotNull
48   @Override
49   public @Nls(capitalization = Nls.Capitalization.Sentence) String getPresentableText() {
50     return IdeBundle.message("title.project");
51   }
52
53   @Override
54   public @Nls(capitalization = Nls.Capitalization.Sentence) String getPresentableName() {
55     return ProjectStructureConfigurable.getInstance(myContext.getProject()).getProjectConfig().getProjectName();
56   }
57
58   @Override
59   public @Nls(capitalization = Nls.Capitalization.Sentence) String getTypeName() {
60     return IdeBundle.message("title.project");
61   }
62
63   @Override
64   public void check(ProjectStructureProblemsHolder problemsHolder) {
65     final Project project = myContext.getProject();
66     if (containsModuleWithInheritedSdk()) {
67       ProjectSdksModel model = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
68       Sdk sdk = model.getProjectSdk();
69       if (sdk == null) {
70         PlaceInProjectStructureBase place = new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createProjectConfigurablePlace(), this);
71         problemsHolder.registerProblem(JavaUiBundle.message("project.roots.project.jdk.problem.message"), null,
72                                        ProjectStructureProblemType.error("project-sdk-not-defined"), place,
73                                        null);
74       }
75     }
76
77
78     List<Chunk<ModuleSourceSet>> sourceSetCycles = ModuleCompilerUtil.computeSourceSetCycles(myContext.getModulesConfigurator());
79
80     List<String> cycles = new ArrayList<>();
81
82     for (Chunk<ModuleSourceSet> chunk : sourceSetCycles) {
83       final Set<ModuleSourceSet> sourceSets = chunk.getNodes();
84       List<String> names = new ArrayList<>();
85       for (ModuleSourceSet sourceSet : sourceSets) {
86         String name = sourceSet.getDisplayName();
87         names.add(names.isEmpty() ? name : StringUtil.decapitalize(name));
88       }
89       cycles.add(StringUtil.join(names, ", "));
90     }
91     if (!cycles.isEmpty()) {
92       final PlaceInProjectStructureBase place =
93         new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createModulesPlace(), this);
94       final String message;
95       final String description;
96       if (cycles.size() > 1) {
97         message = JavaUiBundle.message("circular.dependencies.message");
98         @NonNls final String br = "<br>&nbsp;&nbsp;&nbsp;&nbsp;";
99         StringBuilder cyclesString = new StringBuilder();
100         for (int i = 0; i < cycles.size(); i++) {
101           cyclesString.append(br).append(i + 1).append(". ").append(cycles.get(i));
102         }
103         description = JavaUiBundle.message("module.circular.dependency.warning.description", cyclesString);
104       }
105       else {
106         message = JavaUiBundle.message("module.circular.dependency.warning.short", StringUtil.decapitalize(cycles.get(0)));
107         description = null;
108       }
109       problemsHolder.registerProblem(new ProjectStructureProblemDescription(message, description, place,
110                                                                             ProjectStructureProblemType
111                                                                               .warning("module-circular-dependency"),
112                                                                             Collections.emptyList()));
113     }
114   }
115
116   private boolean containsModuleWithInheritedSdk() {
117     for (Module module : myContext.getModules()) {
118       ModuleRootModel rootModel = myContext.getModulesConfigurator().getRootModel(module);
119       if (rootModel.isSdkInherited()) {
120         return true;
121       }
122     }
123     return false;
124   }
125
126   @Override
127   public List<ProjectStructureElementUsage> getUsagesInElement() {
128     List<ProjectStructureElementUsage> usages = new ArrayList<>();
129
130     Collection<UnloadedModuleDescription> unloadedModules = ModuleManager.getInstance(myContext.getProject()).getUnloadedModuleDescriptions();
131     if (!unloadedModules.isEmpty()) {
132       MultiMap<Module, UnloadedModuleDescription> dependenciesInUnloadedModules = new MultiMap<>();
133       for (UnloadedModuleDescription unloaded : unloadedModules) {
134         for (String moduleName : unloaded.getDependencyModuleNames()) {
135           Module depModule = myContext.getModulesConfigurator().getModuleModel().findModuleByName(moduleName);
136           if (depModule != null) {
137             dependenciesInUnloadedModules.putValue(depModule, unloaded);
138           }
139         }
140       }
141
142       for (Map.Entry<Module, Collection<UnloadedModuleDescription>> entry : dependenciesInUnloadedModules.entrySet()) {
143         usages.add(new UsagesInUnloadedModules(myContext, this, new ModuleProjectStructureElement(myContext, entry.getKey()),
144                                                entry.getValue()));
145       }
146
147       //currently we don't store dependencies on project libraries from unloaded modules in the model, so suppose that all the project libraries are used
148       for (Library library : myContext.getProjectLibrariesProvider().getModifiableModel().getLibraries()) {
149         usages.add(new UsagesInUnloadedModules(myContext, this, new LibraryProjectStructureElement(myContext, library), unloadedModules));
150       }
151     }
152
153     for (String libraryName : BuildProcessCustomPluginsConfiguration.getInstance(myContext.getProject()).getProjectLibraries()) {
154       Library library = myContext.getProjectLibrariesProvider().getModifiableModel().getLibraryByName(libraryName);
155       if (library != null) {
156         usages.add(new UsageInProjectSettings(myContext, new LibraryProjectStructureElement(myContext, library), "Build process configuration"));
157       }
158     }
159
160     return usages;
161   }
162
163   @Override
164   public String getId() {
165     return "project:general";
166   }
167
168   @Override
169   public boolean equals(Object obj) {
170     return obj instanceof GeneralProjectSettingsElement;
171   }
172
173   @Override
174   public int hashCode() {
175     return 0;
176   }
177 }