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<Library, Library.ModifiableModel> myModifiableLibraryModels = new IdentityHashMap<Library, Library.ModifiableModel>();
59 private ModifiableArtifactModel myModifiableArtifactModel;
60 private AbstractIdeModifiableModelsProvider.MyPackagingElementResolvingContext myPackagingElementResolvingContext;
61 private final ArtifactExternalDependenciesImporter myArtifactExternalDependenciesImporter;
63 public AbstractIdeModifiableModelsProvider(@NotNull Project project) {
65 myArtifactExternalDependenciesImporter = new ArtifactExternalDependenciesImporterImpl();
68 protected abstract ModifiableArtifactModel doGetModifiableArtifactModel();
70 protected abstract ModifiableModuleModel doGetModifiableModuleModel();
72 protected abstract ModifiableRootModel doGetModifiableRootModel(Module module);
74 protected abstract ModifiableFacetModel doGetModifiableFacetModel(Module module);
76 protected abstract Library.ModifiableModel doGetModifiableLibraryModel(Library library);
80 public abstract LibraryTable.ModifiableModel getModifiableProjectLibrariesModel();
84 public Module[] getModules() {
85 return getModifiableModuleModel().getModules();
88 protected void processExternalArtifactDependencies() {
89 myArtifactExternalDependenciesImporter.applyChanges(getModifiableArtifactModel(), getPackagingElementResolvingContext());
93 public PackagingElementResolvingContext getPackagingElementResolvingContext() {
94 if (myPackagingElementResolvingContext == null) {
95 myPackagingElementResolvingContext = new MyPackagingElementResolvingContext();
97 return myPackagingElementResolvingContext;
102 public OrderEntry[] getOrderEntries(@NotNull Module module) {
103 return getRootModel(module).getOrderEntries();
108 public Module newModule(@NotNull final String filePath, final String moduleTypeId) {
109 Module module = getModifiableModuleModel().newModule(filePath, moduleTypeId);
110 // 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
111 module.setOption(Module.ELEMENT_TYPE, moduleTypeId);
117 public Library findIdeLibrary(@NotNull LibraryData libraryData) {
118 final LibraryTable.ModifiableModel libraryTable = getModifiableProjectLibrariesModel();
119 for (Library ideLibrary : libraryTable.getLibraries()) {
120 if (isRelated(ideLibrary, libraryData)) return ideLibrary;
127 public VirtualFile[] getContentRoots(Module module) {
128 return getRootModel(module).getContentRoots();
133 public VirtualFile[] getSourceRoots(Module module) {
134 return getRootModel(module).getSourceRoots();
139 public VirtualFile[] getSourceRoots(Module module, boolean includingTests) {
140 return getRootModel(module).getSourceRoots(includingTests);
145 public ModifiableModuleModel getModifiableModuleModel() {
146 if (myModifiableModuleModel == null) {
147 myModifiableModuleModel = doGetModifiableModuleModel();
149 return myModifiableModuleModel;
154 public ModifiableRootModel getModifiableRootModel(Module module) {
155 return (ModifiableRootModel)getRootModel(module);
159 private ModuleRootModel getRootModel(Module module) {
160 ModifiableRootModel result = myModifiableRootModels.get(module);
161 if (result == null) {
162 result = doGetModifiableRootModel(module);
163 myModifiableRootModels.put(module, result);
170 public ModifiableFacetModel getModifiableFacetModel(Module module) {
171 ModifiableFacetModel result = myModifiableFacetModels.get(module);
172 if (result == null) {
173 result = doGetModifiableFacetModel(module);
174 myModifiableFacetModels.put(module, result);
181 public ModifiableArtifactModel getModifiableArtifactModel() {
182 if (myModifiableArtifactModel == null) {
183 myModifiableArtifactModel = doGetModifiableArtifactModel();
185 return myModifiableArtifactModel;
190 public Library[] getAllLibraries() {
191 return getModifiableProjectLibrariesModel().getLibraries();
196 public Library getLibraryByName(String name) {
197 return getModifiableProjectLibrariesModel().getLibraryByName(name);
201 public Library createLibrary(String name) {
202 return getModifiableProjectLibrariesModel().createLibrary(name);
206 public void removeLibrary(Library library) {
207 getModifiableProjectLibrariesModel().removeLibrary(library);
211 public Library.ModifiableModel getModifiableLibraryModel(Library library) {
212 Library.ModifiableModel result = myModifiableLibraryModels.get(library);
213 if (result == null) {
214 result = doGetModifiableLibraryModel(library);
215 myModifiableLibraryModels.put(library, result);
222 public String[] getLibraryUrls(@NotNull Library library, @NotNull OrderRootType type) {
223 final Library.ModifiableModel model = myModifiableLibraryModels.get(library);
225 return model.getUrls(type);
227 return library.getUrls(type);
231 public ModalityState getModalityStateForQuestionDialogs() {
232 return ModalityState.NON_MODAL;
236 public ArtifactExternalDependenciesImporter getArtifactExternalDependenciesImporter() {
237 return myArtifactExternalDependenciesImporter;
242 public List<Module> getAllDependentModules(@NotNull Module module) {
243 final ArrayList<Module> list = new ArrayList<Module>();
244 final Graph<Module> graph = getModuleGraph(true);
245 for (Iterator<Module> i = graph.getOut(module); i.hasNext();) {
251 private Graph<Module> getModuleGraph(final boolean includeTests) {
252 return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<Module>() {
254 public Collection<Module> getNodes() {
255 return ContainerUtil.list(getModules());
259 public Iterator<Module> getIn(Module m) {
260 Module[] dependentModules = getModifiableRootModel(m).getModuleDependencies(includeTests);
261 return Arrays.asList(dependentModules).iterator();
266 private class MyPackagingElementResolvingContext implements PackagingElementResolvingContext {
267 private final ModulesProvider myModulesProvider = new MyModulesProvider();
268 private final MyFacetsProvider myFacetsProvider = new MyFacetsProvider();
269 private final ManifestFileProvider myManifestFileProvider = new DefaultManifestFileProvider(this);
272 public Project getProject() {
277 public ArtifactModel getArtifactModel() {
278 return AbstractIdeModifiableModelsProvider.this.getModifiableArtifactModel();
282 public ModulesProvider getModulesProvider() {
283 return myModulesProvider;
287 public FacetsProvider getFacetsProvider() {
288 return myFacetsProvider;
291 public Library findLibrary(@NotNull String level, @NotNull String libraryName) {
292 if (level.equals(LibraryTablesRegistrar.PROJECT_LEVEL)) {
293 return getLibraryByName(libraryName);
295 final LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTableByLevel(level, myProject);
296 return table != null ? table.getLibraryByName(libraryName) : null;
301 public ManifestFileProvider getManifestFileProvider() {
302 return myManifestFileProvider;
306 private class MyModulesProvider implements ModulesProvider {
308 public Module[] getModules() {
309 return AbstractIdeModifiableModelsProvider.this.getModules();
312 public Module getModule(String name) {
313 return AbstractIdeModifiableModelsProvider.this.findIdeModule(name);
316 public ModuleRootModel getRootModel(@NotNull Module module) {
317 return AbstractIdeModifiableModelsProvider.this.getModifiableRootModel(module);
320 public FacetModel getFacetModel(@NotNull Module module) {
321 return AbstractIdeModifiableModelsProvider.this.getModifiableFacetModel(module);
325 private class MyFacetsProvider implements FacetsProvider {
327 public Facet[] getAllFacets(Module module) {
328 return getModifiableFacetModel(module).getAllFacets();
332 public <F extends Facet> Collection<F> getFacetsByType(Module module, FacetTypeId<F> type) {
333 return getModifiableFacetModel(module).getFacetsByType(type);
336 public <F extends Facet> F findFacet(Module module, FacetTypeId<F> type, String name) {
337 return getModifiableFacetModel(module).findFacet(type, name);
342 public void commit() {
343 ((ProjectRootManagerEx)ProjectRootManager.getInstance(myProject)).mergeRootsChangesDuring(new Runnable() {
345 processExternalArtifactDependencies();
346 for (Library.ModifiableModel each : myModifiableLibraryModels.values()) {
349 getModifiableProjectLibrariesModel().commit();
351 Collection<ModifiableRootModel> rootModels = myModifiableRootModels.values();
352 ModifiableRootModel[] rootModels1 = rootModels.toArray(new ModifiableRootModel[rootModels.size()]);
353 for (ModifiableRootModel model : rootModels1) {
354 assert !model.isDisposed() : "Already disposed: " + model;
357 if (myModifiableModuleModel != null) {
358 ModifiableModelCommitter.multiCommit(rootModels1, myModifiableModuleModel);
360 for (ModifiableRootModel model : rootModels1) {
365 for (Map.Entry<Module, ModifiableFacetModel> each : myModifiableFacetModels.entrySet()) {
366 if(!each.getKey().isDisposed()) {
367 each.getValue().commit();
370 if (myModifiableArtifactModel != null) {
371 myModifiableArtifactModel.commit();
378 public void dispose() {
379 for (ModifiableRootModel each : myModifiableRootModels.values()) {
380 if (each.isDisposed()) continue;
383 Disposer.dispose(getModifiableProjectLibrariesModel());
385 for (Library.ModifiableModel each : myModifiableLibraryModels.values()) {
386 Disposer.dispose(each);
389 if(myModifiableModuleModel != null) {
390 myModifiableModuleModel.dispose();
392 if (myModifiableArtifactModel != null) {
393 myModifiableArtifactModel.dispose();
396 myModifiableRootModels.clear();
397 myModifiableFacetModels.clear();
398 myModifiableLibraryModels.clear();