[platform] get rid of some raw types in facets API and impl
[idea/community.git] / platform / lang-impl / src / com / intellij / facet / impl / FacetFinderImpl.java
1 /*
2  * Copyright 2000-2014 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
17 package com.intellij.facet.impl;
18
19 import com.intellij.facet.*;
20 import com.intellij.openapi.Disposable;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.module.Module;
23 import com.intellij.openapi.module.ModuleManager;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.util.Disposer;
26 import com.intellij.openapi.util.ModificationTracker;
27 import com.intellij.openapi.util.SimpleModificationTracker;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.psi.util.CachedValue;
30 import com.intellij.psi.util.CachedValueProvider;
31 import com.intellij.psi.util.CachedValuesManager;
32 import com.intellij.util.SmartList;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
35
36 import java.util.*;
37
38 public class FacetFinderImpl extends FacetFinder {
39   private static final Logger LOG = Logger.getInstance(FacetFinderImpl.class);
40   private final Map<FacetTypeId, AllFacetsOfTypeModificationTracker> myAllFacetTrackers = new HashMap<>();
41   private final Map<FacetTypeId, CachedValue<Map<VirtualFile, List<Facet>>>> myCachedMaps =
42     new HashMap<>();
43   private final Project myProject;
44   private final CachedValuesManager myCachedValuesManager;
45   private final ModuleManager myModuleManager;
46
47   public FacetFinderImpl(Project project) {
48     myProject = project;
49     myCachedValuesManager = CachedValuesManager.getManager(project);
50     myModuleManager = ModuleManager.getInstance(myProject);
51   }
52
53   @Override
54   public <F extends Facet<?>> ModificationTracker getAllFacetsOfTypeModificationTracker(FacetTypeId<F> type) {
55     AllFacetsOfTypeModificationTracker tracker = myAllFacetTrackers.get(type);
56     if (tracker == null) {
57       tracker = new AllFacetsOfTypeModificationTracker<>(myProject, type);
58       Disposer.register(myProject, tracker);
59       myAllFacetTrackers.put(type, tracker);
60     }
61     return tracker;
62   }
63
64   private <F extends Facet<?> & FacetRootsProvider> Map<VirtualFile, List<Facet>> getRootToFacetsMap(final FacetTypeId<F> type) {
65     CachedValue<Map<VirtualFile, List<Facet>>> cachedValue = myCachedMaps.get(type);
66     if (cachedValue == null) {
67       cachedValue = myCachedValuesManager.createCachedValue(() -> {
68         Map<VirtualFile, List<Facet>> map = computeRootToFacetsMap(type);
69         return CachedValueProvider.Result.create(map, getAllFacetsOfTypeModificationTracker(type));
70       }, false);
71       myCachedMaps.put(type, cachedValue);
72     }
73     final Map<VirtualFile, List<Facet>> value = cachedValue.getValue();
74     LOG.assertTrue(value != null);
75     return value;
76   }
77
78   @NotNull
79   private <F extends Facet&FacetRootsProvider> Map<VirtualFile, List<Facet>> computeRootToFacetsMap(final FacetTypeId<F> type) {
80     final Module[] modules = myModuleManager.getModules();
81     final HashMap<VirtualFile, List<Facet>> map = new HashMap<>();
82     for (Module module : modules) {
83       final Collection<F> facets = FacetManager.getInstance(module).getFacetsByType(type);
84       for (F facet : facets) {
85         for (VirtualFile root : facet.getFacetRoots()) {
86           List<Facet> list = map.get(root);
87           if (list == null) {
88             list = new SmartList<>();
89             map.put(root, list);
90           }
91           list.add(facet);
92         }
93       }
94     }
95     return map;
96   }
97
98   @Override
99   @Nullable
100   public <F extends Facet<?> & FacetRootsProvider> F findFacet(VirtualFile file, FacetTypeId<F> type) {
101     final List<F> list = findFacets(file, type);
102     return list.size() > 0 ? list.get(0) : null;
103   }
104
105   @Override
106   @NotNull
107   public <F extends Facet<?> & FacetRootsProvider> List<F> findFacets(VirtualFile file, FacetTypeId<F> type) {
108     final Map<VirtualFile, List<Facet>> map = getRootToFacetsMap(type);
109     if (!map.isEmpty()) {
110       while (file != null) {
111         @SuppressWarnings("unchecked")
112         List<F> list = (List<F>)((List)map.get(file));
113         if (list != null) {
114           return list;
115         }
116         file = file.getParent();
117       }
118     }
119     return Collections.emptyList();
120   }
121
122   private static class AllFacetsOfTypeModificationTracker<F extends Facet> extends SimpleModificationTracker implements Disposable, ProjectWideFacetListener<F> {
123     AllFacetsOfTypeModificationTracker(final Project project, final FacetTypeId<F> type) {
124       ProjectWideFacetListenersRegistry.getInstance(project).registerListener(type, this, this);
125     }
126
127     @Override
128     public void facetAdded(@NotNull final F facet) {
129       incModificationCount();
130     }
131
132     @Override
133     public void facetRemoved(@NotNull final F facet) {
134       incModificationCount();
135     }
136
137     @Override
138     public void facetConfigurationChanged(@NotNull final F facet) {
139       incModificationCount();
140     }
141
142     @Override
143     public void firstFacetAdded() {
144
145     }
146
147     @Override
148     public void beforeFacetRemoved(@NotNull F facet) {
149
150     }
151
152     @Override
153     public void allFacetsRemoved() {
154
155     }
156
157     @Override
158     public void dispose() {
159     }
160   }
161 }