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.
17 package com
.intellij
.facet
.impl
;
19 import com
.intellij
.facet
.*;
20 import com
.intellij
.facet
.impl
.ui
.FacetEditorContextBase
;
21 import com
.intellij
.facet
.impl
.ui
.FacetEditorImpl
;
22 import com
.intellij
.facet
.impl
.ui
.FacetTreeModel
;
23 import com
.intellij
.facet
.impl
.ui
.ProjectConfigurableContext
;
24 import com
.intellij
.facet
.ui
.FacetEditorContext
;
25 import com
.intellij
.openapi
.diagnostic
.Logger
;
26 import com
.intellij
.openapi
.module
.Module
;
27 import com
.intellij
.openapi
.options
.ConfigurationException
;
28 import com
.intellij
.openapi
.project
.Project
;
29 import com
.intellij
.openapi
.roots
.ModifiableRootModel
;
30 import com
.intellij
.openapi
.roots
.ui
.configuration
.FacetsProvider
;
31 import com
.intellij
.openapi
.roots
.ui
.configuration
.ModuleConfigurationState
;
32 import com
.intellij
.openapi
.roots
.ui
.configuration
.ModuleEditor
;
33 import com
.intellij
.openapi
.roots
.ui
.configuration
.ModulesConfigurator
;
34 import com
.intellij
.openapi
.roots
.ui
.configuration
.projectRoot
.LibrariesContainer
;
35 import com
.intellij
.openapi
.roots
.ui
.configuration
.projectRoot
.LibrariesContainerFactory
;
36 import com
.intellij
.openapi
.roots
.ui
.configuration
.projectRoot
.StructureConfigurableContext
;
37 import com
.intellij
.openapi
.util
.Disposer
;
38 import com
.intellij
.openapi
.util
.UserDataHolder
;
39 import com
.intellij
.openapi
.util
.UserDataHolderBase
;
40 import org
.jetbrains
.annotations
.NotNull
;
41 import org
.jetbrains
.annotations
.Nullable
;
48 public class ProjectFacetsConfigurator
implements FacetsProvider
, ModuleEditor
.ChangeListener
{
49 private static final Logger LOG
= Logger
.getInstance("#com.intellij.facet.impl.ProjectFacetsConfigurator");
50 private final Map
<Module
, ModifiableFacetModel
> myModels
= new HashMap
<Module
, ModifiableFacetModel
>();
51 private final Map
<Facet
, FacetEditorImpl
> myEditors
= new HashMap
<Facet
, FacetEditorImpl
>();
52 private final Map
<Module
, FacetTreeModel
> myTreeModels
= new HashMap
<Module
, FacetTreeModel
>();
53 private final Map
<FacetInfo
, Facet
> myInfo2Facet
= new HashMap
<FacetInfo
, Facet
>();
54 private final Map
<Facet
, FacetInfo
> myFacet2Info
= new HashMap
<Facet
, FacetInfo
>();
55 private final Map
<Module
, UserDataHolder
> mySharedModuleData
= new HashMap
<Module
, UserDataHolder
>();
56 private final Set
<Facet
> myFacetsToDispose
= new HashSet
<Facet
>();
57 private final Set
<Facet
> myChangedFacets
= new HashSet
<Facet
>();
58 private final Set
<Facet
> myCreatedFacets
= new HashSet
<Facet
>();
59 private final StructureConfigurableContext myContext
;
60 private final Project myProject
;
61 private UserDataHolderBase myProjectData
= new UserDataHolderBase();
63 public ProjectFacetsConfigurator(final StructureConfigurableContext context
, Project project
) {
68 public List
<Facet
> removeFacet(Facet facet
) {
69 FacetTreeModel treeModel
= getTreeModel(facet
.getModule());
70 FacetInfo facetInfo
= myFacet2Info
.get(facet
);
71 if (facetInfo
== null) return Collections
.emptyList();
73 final List
<Facet
> removed
= new ArrayList
<Facet
>();
74 List
<FacetInfo
> children
= treeModel
.getChildren(facetInfo
);
75 for (FacetInfo child
: children
) {
76 Facet childInfo
= myInfo2Facet
.get(child
);
77 if (childInfo
!= null) {
78 removed
.addAll(removeFacet(childInfo
));
82 treeModel
.removeFacetInfo(facetInfo
);
83 getOrCreateModifiableModel(facet
.getModule()).removeFacet(facet
);
84 myChangedFacets
.remove(facet
);
85 if (myCreatedFacets
.contains(facet
)) {
86 Disposer
.dispose(facet
);
88 final FacetEditorImpl facetEditor
= myEditors
.remove(facet
);
89 if (facetEditor
!= null) {
90 facetEditor
.disposeUIResources();
92 myFacet2Info
.remove(facet
);
93 myInfo2Facet
.remove(facetInfo
);
98 public Facet
createAndAddFacet(Module module
, FacetType
<?
, ?
> type
, String name
, final @Nullable FacetInfo underlyingFacet
) {
99 final Facet facet
= FacetManager
.getInstance(module
).createFacet(type
, name
, myInfo2Facet
.get(underlyingFacet
));
100 myCreatedFacets
.add(facet
);
102 getOrCreateModifiableModel(module
).addFacet(facet
);
106 public void addFacetInfo(final Facet facet
) {
107 final FacetInfo exiting
= myFacet2Info
.get(facet
);
108 if (exiting
!= null) {
109 LOG
.assertTrue(exiting
.getName().equals(facet
.getName()));
110 LOG
.assertTrue(exiting
.getFacetType().equals(facet
.getType()));
111 LOG
.assertTrue(exiting
.getConfiguration().equals(facet
.getConfiguration()));
115 FacetInfo info
= new FacetInfo(facet
.getType(), facet
.getName(), facet
.getConfiguration(), myFacet2Info
.get(facet
.getUnderlyingFacet()));
116 myFacet2Info
.put(facet
, info
);
117 myInfo2Facet
.put(info
, facet
);
118 getTreeModel(facet
.getModule()).addFacetInfo(info
);
121 public void addFacetInfos(final Module module
) {
122 final Facet
[] facets
= getFacetModel(module
).getSortedFacets();
123 for (Facet facet
: facets
) {
128 public void clearMaps() {
131 myTreeModels
.clear();
132 myInfo2Facet
.clear();
133 myFacet2Info
.clear();
134 myChangedFacets
.clear();
135 mySharedModuleData
.clear();
138 private boolean isNewFacet(Facet facet
) {
139 final ModifiableFacetModel model
= myModels
.get(facet
.getModule());
140 return model
!= null && model
.isNewFacet(facet
);
144 public ModifiableFacetModel
getOrCreateModifiableModel(final Module module
) {
145 ModifiableFacetModel model
= myModels
.get(module
);
147 model
= FacetManager
.getInstance(module
).createModifiableModel();
148 model
.addListener(new ModifiableFacetModel
.Listener() {
149 public void onChanged() {
150 fireFacetModelChanged(module
);
153 myModels
.put(module
, model
);
159 public FacetEditorImpl
getEditor(Facet facet
) {
160 return myEditors
.get(facet
);
164 public FacetEditorImpl
getOrCreateEditor(Facet facet
) {
165 FacetEditorImpl editor
= myEditors
.get(facet
);
166 if (editor
== null) {
167 final Facet underlyingFacet
= facet
.getUnderlyingFacet();
168 final FacetEditorContext parentContext
= underlyingFacet
!= null ?
getOrCreateEditor(underlyingFacet
).getContext() : null;
170 final FacetEditorContext context
= createContext(facet
, parentContext
);
171 editor
= new FacetEditorImpl(context
, facet
.getConfiguration());
172 editor
.getComponent();
174 myEditors
.put(facet
, editor
);
179 protected FacetEditorContext
createContext(final @NotNull Facet facet
, final @Nullable FacetEditorContext parentContext
) {
180 Module module
= facet
.getModule();
181 ModulesConfigurator modulesConfigurator
= myContext
.getModulesConfigurator();
182 ModuleEditor moduleEditor
= modulesConfigurator
.getModuleEditor(module
);
183 if (moduleEditor
== null) {
184 LOG
.error("ModuleEditor[" + module
.getName() + "]==null: disposed = " + module
.isDisposed() + ", is in model = "
185 + Arrays
.asList(modulesConfigurator
.getModules()).contains(module
));
188 final ModuleConfigurationState state
= moduleEditor
.createModuleConfigurationState();
189 return new MyProjectConfigurableContext(facet
, parentContext
, state
);
192 private UserDataHolder
getSharedModuleData(final Module module
) {
193 UserDataHolder dataHolder
= mySharedModuleData
.get(module
);
194 if (dataHolder
== null) {
195 dataHolder
= new UserDataHolderBase();
196 mySharedModuleData
.put(module
, dataHolder
);
202 public FacetModel
getFacetModel(Module module
) {
203 final ModifiableFacetModel model
= myModels
.get(module
);
207 return FacetManager
.getInstance(module
);
210 public void commitFacets() {
211 for (ModifiableFacetModel model
: myModels
.values()) {
215 for (Map
.Entry
<Facet
, FacetEditorImpl
> entry
: myEditors
.entrySet()) {
216 entry
.getValue().onFacetAdded(entry
.getKey());
220 for (Facet facet
: myChangedFacets
) {
221 Module module
= facet
.getModule();
222 if (!module
.isDisposed()) {
223 module
.getMessageBus().syncPublisher(FacetManager
.FACETS_TOPIC
).facetConfigurationChanged(facet
);
226 myChangedFacets
.clear();
229 public void resetEditors() {
230 for (FacetEditorImpl editor
: myEditors
.values()) {
235 public void applyEditors() throws ConfigurationException
{
236 for (Map
.Entry
<Facet
, FacetEditorImpl
> entry
: myEditors
.entrySet()) {
237 final FacetEditorImpl editor
= entry
.getValue();
238 if (editor
.isModified()) {
239 myChangedFacets
.add(entry
.getKey());
245 public boolean isModified() {
246 for (ModifiableFacetModel model
: myModels
.values()) {
247 if (model
.isModified()) {
251 for (FacetEditorImpl editor
: myEditors
.values()) {
252 if (editor
.isModified()) {
259 public FacetTreeModel
getTreeModel(Module module
) {
260 FacetTreeModel treeModel
= myTreeModels
.get(module
);
261 if (treeModel
== null) {
262 treeModel
= new FacetTreeModel();
263 myTreeModels
.put(module
, treeModel
);
268 public FacetInfo
getFacetInfo(final Facet facet
) {
269 return myFacet2Info
.get(facet
);
272 public Facet
getFacet(final FacetInfo facetInfo
) {
273 return myInfo2Facet
.get(facetInfo
);
276 public void disposeEditors() {
277 for (Facet facet
: myFacetsToDispose
) {
278 Disposer
.dispose(facet
);
280 myFacetsToDispose
.clear();
281 myCreatedFacets
.clear();
283 for (FacetEditorImpl editor
: myEditors
.values()) {
284 editor
.disposeUIResources();
286 myProjectData
= null;
290 public Facet
[] getAllFacets(final Module module
) {
291 return getFacetModel(module
).getAllFacets();
295 public <F
extends Facet
> Collection
<F
> getFacetsByType(final Module module
, final FacetTypeId
<F
> type
) {
296 return getFacetModel(module
).getFacetsByType(type
);
300 public <F
extends Facet
> F
findFacet(final Module module
, final FacetTypeId
<F
> type
, final String name
) {
301 return getFacetModel(module
).findFacet(type
, name
);
304 public void moduleStateChanged(final ModifiableRootModel moduleRootModel
) {
305 Module module
= moduleRootModel
.getModule();
306 Facet
[] allFacets
= getAllFacets(module
);
307 for (Facet facet
: allFacets
) {
308 FacetEditorImpl facetEditor
= myEditors
.get(facet
);
309 if (facetEditor
!= null) {
310 ((FacetEditorContextBase
)facetEditor
.getContext()).fireModuleRootsChanged(moduleRootModel
);
315 private void fireFacetModelChanged(Module module
) {
316 for (Facet facet
: getAllFacets(module
)) {
317 FacetEditorImpl facetEditor
= myEditors
.get(facet
);
318 if (facetEditor
!= null) {
319 ((FacetEditorContextBase
)facetEditor
.getContext()).fireFacetModelChanged(module
);
324 private UserDataHolder
getProjectData() {
325 if (myProjectData
== null) {
326 myProjectData
= new UserDataHolderBase();
328 return myProjectData
;
331 public List
<Facet
> removeAllFacets(final Module module
) {
332 List
<Facet
> facets
= new ArrayList
<Facet
>();
333 FacetModel facetModel
= getOrCreateModifiableModel(module
);
334 for (Facet facet
: facetModel
.getAllFacets()) {
335 if (!myCreatedFacets
.contains(facet
)) {
336 myFacetsToDispose
.add(facet
);
338 LOG
.assertTrue(facet
.getModule().equals(module
), module
+ " expected but " + facet
.getModule() + " found");
339 facets
.addAll(removeFacet(facet
));
341 mySharedModuleData
.remove(module
);
342 myModels
.remove(module
);
346 private class MyProjectConfigurableContext
extends ProjectConfigurableContext
{
347 private final LibrariesContainer myContainer
;
349 public MyProjectConfigurableContext(final Facet facet
, final FacetEditorContext parentContext
, final ModuleConfigurationState state
) {
350 super(facet
, ProjectFacetsConfigurator
.this.isNewFacet(facet
), parentContext
, state
,
351 ProjectFacetsConfigurator
.this.getSharedModuleData(facet
.getModule()), getProjectData());
352 myContainer
= LibrariesContainerFactory
.createContainer(facet
.getModule().getProject(), myContext
);
355 public LibrariesContainer
getContainer() {