[project-model] findModuleForPsiElement: check original file if PsiFile is supplied
[idea/community.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / configuration / classpath / AddLibraryDependencyAction.java
1 /*
2  * Copyright 2000-2010 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.classpath;
17
18 import com.intellij.facet.impl.ProjectFacetsConfigurator;
19 import com.intellij.ide.JavaUiBundle;
20 import com.intellij.openapi.roots.LibraryDependencyScopeSuggester;
21 import com.intellij.openapi.roots.LibraryOrderEntry;
22 import com.intellij.openapi.roots.ModifiableRootModel;
23 import com.intellij.openapi.roots.OrderEntry;
24 import com.intellij.openapi.roots.libraries.Library;
25 import com.intellij.openapi.roots.libraries.LibraryTable;
26 import com.intellij.openapi.roots.ui.configuration.libraries.LibraryEditingUtil;
27 import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesModifiableModel;
28 import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
29 import com.intellij.openapi.ui.Messages;
30 import com.intellij.openapi.ui.popup.PopupStep;
31 import com.intellij.util.PlatformIcons;
32 import com.intellij.util.ui.classpath.ChooseLibrariesFromTablesDialog;
33 import org.jetbrains.annotations.Nls;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
36
37 import java.util.List;
38 import java.util.function.Predicate;
39
40 class AddLibraryDependencyAction extends AddItemPopupAction<Library> {
41   private final StructureConfigurableContext myContext;
42
43   AddLibraryDependencyAction(ClasspathPanel classpathPanel,
44                              final int index,
45                              final @Nls(capitalization = Nls.Capitalization.Title) String title,
46                              final StructureConfigurableContext context) {
47     super(classpathPanel, index, title, PlatformIcons.LIBRARY_ICON);
48     myContext = context;
49   }
50
51   @Override
52   public boolean hasSubStep() {
53     return !hasLibraries() && LibraryEditingUtil.hasSuitableTypes(myClasspathPanel);
54   }
55
56   @Override
57   public PopupStep createSubStep() {
58     return LibraryEditingUtil.createChooseTypeStep(myClasspathPanel,
59                                                    libraryType -> new AddNewLibraryDependencyAction(myClasspathPanel, myContext, libraryType).execute());
60   }
61
62   @Override
63   public void run() {
64     if (hasLibraries()) {
65       super.run();
66     }
67     else {
68       new AddNewLibraryDependencyAction(myClasspathPanel, myContext, null).run();
69     }
70   }
71
72   private boolean hasLibraries() {
73     final Predicate<Library> condition = getNotAddedSuitableLibrariesCondition();
74     for (LibraryTable table : ChooseLibrariesFromTablesDialog.getLibraryTables(myClasspathPanel.getProject(), true)) {
75       final LibrariesModifiableModel model = myContext.myLevel2Providers.get(table.getTableLevel());
76       if (model != null) {
77         for (Library library : model.getLibraries()) {
78           if (condition.test(library)) {
79             return true;
80           }
81         }
82       }
83     }
84     return false;
85   }
86
87   private Predicate<Library> getNotAddedSuitableLibrariesCondition() {
88     ProjectFacetsConfigurator facetsConfigurator = myContext.getModulesConfigurator().getFacetsConfigurator();
89     return LibraryEditingUtil.getNotAddedSuitableLibrariesCondition(myClasspathPanel.getRootModel(), facetsConfigurator);
90   }
91
92   @Override
93   @Nullable
94   protected ClasspathTableItem<?> createTableItem(final Library item) {
95     // clear invalid order entry corresponding to added library if any
96     final ModifiableRootModel rootModel = myClasspathPanel.getRootModel();
97     final OrderEntry[] orderEntries = rootModel.getOrderEntries();
98     for (OrderEntry orderEntry : orderEntries) {
99       if (orderEntry instanceof LibraryOrderEntry) {
100         final LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)orderEntry;
101         if (item.equals(libraryOrderEntry.getLibrary())) {
102           return ClasspathTableItem.createLibItem(libraryOrderEntry, myContext);
103         }
104         String name = item.getName();
105         if (name != null && name.equals(libraryOrderEntry.getLibraryName())) {
106           if (orderEntry.isValid()) {
107             Messages.showErrorDialog(JavaUiBundle.message("classpath.message.library.already.added", item.getName()),
108                                      JavaUiBundle.message("classpath.title.adding.dependency"));
109             return null;
110           }
111           else {
112             rootModel.removeOrderEntry(orderEntry);
113           }
114         }
115       }
116     }
117     final LibraryOrderEntry orderEntry = rootModel.addLibraryEntry(item);
118     orderEntry.setScope(LibraryDependencyScopeSuggester.getDefaultScope(item));
119     return ClasspathTableItem.createLibItem(orderEntry, myContext);
120   }
121
122   @Override
123   protected ClasspathElementChooser<Library> createChooser() {
124     return new ExistingLibraryChooser();
125   }
126
127   class ExistingLibraryChooser implements ClasspathElementChooser<Library> {
128     @Override
129     @NotNull
130     public List<Library> chooseElements() {
131       ProjectStructureChooseLibrariesDialog dialog = new ProjectStructureChooseLibrariesDialog(myClasspathPanel, myContext,
132                                                                                                getNotAddedSuitableLibrariesCondition());
133       dialog.show();
134       return dialog.getSelectedLibraries();
135     }
136   }
137 }