2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.openapi.externalSystem.service.project;
18 import com.intellij.facet.Facet;
19 import com.intellij.facet.FacetModel;
20 import com.intellij.facet.FacetTypeId;
21 import com.intellij.facet.ModifiableFacetModel;
22 import com.intellij.openapi.application.ModalityState;
23 import com.intellij.openapi.externalSystem.model.project.LibraryData;
24 import com.intellij.openapi.module.ModifiableModuleModel;
25 import com.intellij.openapi.module.Module;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.roots.*;
28 import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
29 import com.intellij.openapi.roots.impl.ModifiableModelCommitter;
30 import com.intellij.openapi.roots.libraries.Library;
31 import com.intellij.openapi.roots.libraries.LibraryTable;
32 import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
33 import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
34 import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
35 import com.intellij.openapi.util.Disposer;
36 import com.intellij.openapi.vfs.VirtualFile;
37 import com.intellij.packaging.artifacts.ArtifactModel;
38 import com.intellij.packaging.artifacts.ModifiableArtifactModel;
39 import com.intellij.packaging.elements.ManifestFileProvider;
40 import com.intellij.packaging.elements.PackagingElementResolvingContext;
41 import com.intellij.packaging.impl.artifacts.DefaultManifestFileProvider;
42 import com.intellij.util.containers.ContainerUtil;
43 import com.intellij.util.graph.CachingSemiGraph;
44 import com.intellij.util.graph.Graph;
45 import com.intellij.util.graph.GraphGenerator;
46 import gnu.trove.THashMap;
47 import org.jetbrains.annotations.NotNull;
48 import org.jetbrains.annotations.Nullable;
52 import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.isRelated;
54 public abstract class AbstractIdeModifiableModelsProvider extends IdeModelsProviderImpl implements IdeModifiableModelsProvider {
55 private ModifiableModuleModel myModifiableModuleModel;
56 private Map<Module, ModifiableRootModel> myModifiableRootModels = new THashMap<Module, ModifiableRootModel>();
57 private Map<Module, ModifiableFacetModel> myModifiableFacetModels = new THashMap<Module, ModifiableFacetModel>();
58 private Map<Module, String> myProductionModulesForTestModules = new THashMap<Module, String>();
59 private Map<Library, Library.ModifiableModel> myModifiableLibraryModels = new IdentityHashMap<Library, Library.ModifiableModel>();
60 private ModifiableArtifactModel myModifiableArtifactModel;
61 private AbstractIdeModifiableModelsProvider.MyPackagingElementResolvingContext myPackagingElementResolvingContext;
62 private final ArtifactExternalDependenciesImporter myArtifactExternalDependenciesImporter;
64 public AbstractIdeModifiableModelsProvider(@NotNull Project project) {
66 myArtifactExternalDependenciesImporter = new ArtifactExternalDependenciesImporterImpl();
69 protected abstract ModifiableArtifactModel doGetModifiableArtifactModel();
71 protected abstract ModifiableModuleModel doGetModifiableModuleModel();
73 protected abstract ModifiableRootModel doGetModifiableRootModel(Module module);
75 protected abstract ModifiableFacetModel doGetModifiableFacetModel(Module module);
77 protected abstract Library.ModifiableModel doGetModifiableLibraryModel(Library library);
81 public abstract LibraryTable.ModifiableModel getModifiableProjectLibrariesModel();
85 public Module[] getModules() {
86 return getModifiableModuleModel().getModules();
89 protected void processExternalArtifactDependencies() {
90 myArtifactExternalDependenciesImporter.applyChanges(getModifiableArtifactModel(), getPackagingElementResolvingContext());
94 public PackagingElementResolvingContext getPackagingElementResolvingContext() {
95 if (myPackagingElementResolvingContext == null) {
96 myPackagingElementResolvingContext = new MyPackagingElementResolvingContext();
98 return myPackagingElementResolvingContext;
103 public OrderEntry[] getOrderEntries(@NotNull Module module) {
104 return getRootModel(module).getOrderEntries();
109 public Module newModule(@NotNull final String filePath, final String moduleTypeId) {
110 Module module = getModifiableModuleModel().newModule(filePath, moduleTypeId);
111 // set module type id explicitly otherwise it can not be set if there is an existing module (with the same filePath) and w/o 'type' attribute
112 module.setOption(Module.ELEMENT_TYPE, moduleTypeId);
118 public Library findIdeLibrary(@NotNull LibraryData libraryData) {
119 final LibraryTable.ModifiableModel libraryTable = getModifiableProjectLibrariesModel();
120 for (Library ideLibrary : libraryTable.getLibraries()) {
121 if (isRelated(ideLibrary, libraryData)) return ideLibrary;
128 public VirtualFile[] getContentRoots(Module module) {
129 return getRootModel(module).getContentRoots();
134 public VirtualFile[] getSourceRoots(Module module) {
135 return getRootModel(module).getSourceRoots();
140 public VirtualFile[] getSourceRoots(Module module, boolean includingTests) {
141 return getRootModel(module).getSourceRoots(includingTests);
146 public ModifiableModuleModel getModifiableModuleModel() {
147 if (myModifiableModuleModel == null) {
148 myModifiableModuleModel = doGetModifiableModuleModel();
150 return myModifiableModuleModel;
155 public ModifiableRootModel getModifiableRootModel(Module module) {
156 return (ModifiableRootModel)getRootModel(module);
160 private ModuleRootModel getRootModel(Module module) {
161 ModifiableRootModel result = myModifiableRootModels.get(module);
162 if (result == null) {
163 result = doGetModifiableRootModel(module);
164 myModifiableRootModels.put(module, result);
171 public ModifiableFacetModel getModifiableFacetModel(Module module) {
172 ModifiableFacetModel result = myModifiableFacetModels.get(module);
173 if (result == null) {
174 result = doGetModifiableFacetModel(module);
175 myModifiableFacetModels.put(module, result);
182 public ModifiableArtifactModel getModifiableArtifactModel() {
183 if (myModifiableArtifactModel == null) {
184 myModifiableArtifactModel = doGetModifiableArtifactModel();
186 return myModifiableArtifactModel;
191 public Library[] getAllLibraries() {
192 return getModifiableProjectLibrariesModel().getLibraries();
197 public Library getLibraryByName(String name) {
198 return getModifiableProjectLibrariesModel().getLibraryByName(name);
202 public Library createLibrary(String name) {
203 return getModifiableProjectLibrariesModel().createLibrary(name);
207 public void removeLibrary(Library library) {
208 getModifiableProjectLibrariesModel().removeLibrary(library);
212 public Library.ModifiableModel getModifiableLibraryModel(Library library) {
213 Library.ModifiableModel result = myModifiableLibraryModels.get(library);
214 if (result == null) {
215 result = doGetModifiableLibraryModel(library);
216 myModifiableLibraryModels.put(library, result);
223 public String[] getLibraryUrls(@NotNull Library library, @NotNull OrderRootType type) {
224 final Library.ModifiableModel model = myModifiableLibraryModels.get(library);
226 return model.getUrls(type);
228 return library.getUrls(type);
232 public ModalityState getModalityStateForQuestionDialogs() {
233 return ModalityState.NON_MODAL;
237 public ArtifactExternalDependenciesImporter getArtifactExternalDependenciesImporter() {
238 return myArtifactExternalDependenciesImporter;
243 public List<Module> getAllDependentModules(@NotNull Module module) {
244 final ArrayList<Module> list = new ArrayList<Module>();
245 final Graph<Module> graph = getModuleGraph(true);
246 for (Iterator<Module> i = graph.getOut(module); i.hasNext();) {
252 private Graph<Module> getModuleGraph(final boolean includeTests) {
253 return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<Module>() {
255 public Collection<Module> getNodes() {
256 return ContainerUtil.list(getModules());
260 public Iterator<Module> getIn(Module m) {
261 Module[] dependentModules = getModifiableRootModel(m).getModuleDependencies(includeTests);
262 return Arrays.asList(dependentModules).iterator();
267 private class MyPackagingElementResolvingContext implements PackagingElementResolvingContext {
268 private final ModulesProvider myModulesProvider = new MyModulesProvider();
269 private final MyFacetsProvider myFacetsProvider = new MyFacetsProvider();
270 private final ManifestFileProvider myManifestFileProvider = new DefaultManifestFileProvider(this);
273 public Project getProject() {
278 public ArtifactModel getArtifactModel() {
279 return AbstractIdeModifiableModelsProvider.this.getModifiableArtifactModel();
283 public ModulesProvider getModulesProvider() {
284 return myModulesProvider;
288 public FacetsProvider getFacetsProvider() {
289 return myFacetsProvider;
292 public Library findLibrary(@NotNull String level, @NotNull String libraryName) {
293 if (level.equals(LibraryTablesRegistrar.PROJECT_LEVEL)) {
294 return getLibraryByName(libraryName);
296 final LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTableByLevel(level, myProject);
297 return table != null ? table.getLibraryByName(libraryName) : null;
302 public ManifestFileProvider getManifestFileProvider() {
303 return myManifestFileProvider;
307 private class MyModulesProvider implements ModulesProvider {
309 public Module[] getModules() {
310 return AbstractIdeModifiableModelsProvider.this.getModules();
313 public Module getModule(String name) {
314 return AbstractIdeModifiableModelsProvider.this.findIdeModule(name);
317 public ModuleRootModel getRootModel(@NotNull Module module) {
318 return AbstractIdeModifiableModelsProvider.this.getModifiableRootModel(module);
321 public FacetModel getFacetModel(@NotNull Module module) {
322 return AbstractIdeModifiableModelsProvider.this.getModifiableFacetModel(module);
326 private class MyFacetsProvider implements FacetsProvider {
328 public Facet[] getAllFacets(Module module) {
329 return getModifiableFacetModel(module).getAllFacets();
333 public <F extends Facet> Collection<F> getFacetsByType(Module module, FacetTypeId<F> type) {
334 return getModifiableFacetModel(module).getFacetsByType(type);
337 public <F extends Facet> F findFacet(Module module, FacetTypeId<F> type, String name) {
338 return getModifiableFacetModel(module).findFacet(type, name);
343 public void commit() {
344 ((ProjectRootManagerEx)ProjectRootManager.getInstance(myProject)).mergeRootsChangesDuring(new Runnable() {
346 processExternalArtifactDependencies();
347 for (Library.ModifiableModel each : myModifiableLibraryModels.values()) {
350 getModifiableProjectLibrariesModel().commit();
352 Collection<ModifiableRootModel> rootModels = myModifiableRootModels.values();
353 ModifiableRootModel[] rootModels1 = rootModels.toArray(new ModifiableRootModel[rootModels.size()]);
354 for (ModifiableRootModel model : rootModels1) {
355 assert !model.isDisposed() : "Already disposed: " + model;
358 if (myModifiableModuleModel != null) {
359 ModifiableModelCommitter.multiCommit(rootModels1, myModifiableModuleModel);
361 for (ModifiableRootModel model : rootModels1) {
365 for (Map.Entry<Module, String> entry : myProductionModulesForTestModules.entrySet()) {
366 TestModuleProperties.getInstance(entry.getKey()).setProductionModuleName(entry.getValue());
369 for (Map.Entry<Module, ModifiableFacetModel> each : myModifiableFacetModels.entrySet()) {
370 if(!each.getKey().isDisposed()) {
371 each.getValue().commit();
374 if (myModifiableArtifactModel != null) {
375 myModifiableArtifactModel.commit();
382 public void dispose() {
383 for (ModifiableRootModel each : myModifiableRootModels.values()) {
384 if (each.isDisposed()) continue;
387 Disposer.dispose(getModifiableProjectLibrariesModel());
389 for (Library.ModifiableModel each : myModifiableLibraryModels.values()) {
390 Disposer.dispose(each);
393 if(myModifiableModuleModel != null) {
394 myModifiableModuleModel.dispose();
396 if (myModifiableArtifactModel != null) {
397 myModifiableArtifactModel.dispose();
400 myModifiableRootModels.clear();
401 myModifiableFacetModels.clear();
402 myModifiableLibraryModels.clear();
406 public void setTestModuleProperties(Module testModule, String productionModuleName) {
407 myProductionModulesForTestModules.put(testModule, productionModuleName);