/platform/lang-impl/src/com/intellij/facet/impl/FacetFinderImpl.java

https://bitbucket.org/nbargnesi/idea · Java · 149 lines · 114 code · 17 blank · 18 comment · 15 complexity · e6ec2e68fbd46ad376917548a45a73ff MD5 · raw file

  1. /*
  2. * Copyright 2000-2012 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.facet.impl;
  17. import com.intellij.facet.*;
  18. import com.intellij.openapi.vfs.VirtualFile;
  19. import com.intellij.openapi.util.ModificationTracker;
  20. import com.intellij.openapi.util.Disposer;
  21. import com.intellij.openapi.project.Project;
  22. import com.intellij.openapi.Disposable;
  23. import com.intellij.openapi.diagnostic.Logger;
  24. import com.intellij.openapi.module.ModuleManager;
  25. import com.intellij.openapi.module.Module;
  26. import com.intellij.psi.util.CachedValueProvider;
  27. import com.intellij.psi.util.CachedValuesManager;
  28. import com.intellij.psi.util.CachedValue;
  29. import com.intellij.util.SmartList;
  30. import org.jetbrains.annotations.Nullable;
  31. import org.jetbrains.annotations.NotNull;
  32. import java.util.*;
  33. /**
  34. * @author nik
  35. */
  36. public class FacetFinderImpl extends FacetFinder {
  37. private static final Logger LOG = Logger.getInstance("#com.intellij.facet.impl.FacetFinderImpl");
  38. private final Map<FacetTypeId, AllFacetsOfTypeModificationTracker> myAllFacetTrackers = new HashMap<FacetTypeId, AllFacetsOfTypeModificationTracker>();
  39. private final Map<FacetTypeId, CachedValue<Map<VirtualFile, List<Facet>>>> myCachedMaps =
  40. new HashMap<FacetTypeId, CachedValue<Map<VirtualFile, List<Facet>>>>();
  41. private final Project myProject;
  42. private final CachedValuesManager myCachedValuesManager;
  43. private final ModuleManager myModuleManager;
  44. public FacetFinderImpl(Project project) {
  45. myProject = project;
  46. myCachedValuesManager = CachedValuesManager.getManager(project);
  47. myModuleManager = ModuleManager.getInstance(myProject);
  48. }
  49. public <F extends Facet> ModificationTracker getAllFacetsOfTypeModificationTracker(FacetTypeId<F> type) {
  50. AllFacetsOfTypeModificationTracker tracker = myAllFacetTrackers.get(type);
  51. if (tracker == null) {
  52. tracker = new AllFacetsOfTypeModificationTracker<F>(myProject, type);
  53. Disposer.register(myProject, tracker);
  54. myAllFacetTrackers.put(type, tracker);
  55. }
  56. return tracker;
  57. }
  58. private <F extends Facet & FacetRootsProvider> Map<VirtualFile, List<Facet>> getRootToFacetsMap(final FacetTypeId<F> type) {
  59. CachedValue<Map<VirtualFile, List<Facet>>> cachedValue = myCachedMaps.get(type);
  60. if (cachedValue == null) {
  61. cachedValue = myCachedValuesManager.createCachedValue(new CachedValueProvider<Map<VirtualFile, List<Facet>>>() {
  62. public Result<Map<VirtualFile, List<Facet>>> compute() {
  63. Map<VirtualFile, List<Facet>> map = computeRootToFacetsMap(type);
  64. return Result.create(map, getAllFacetsOfTypeModificationTracker(type));
  65. }
  66. }, false);
  67. myCachedMaps.put(type, cachedValue);
  68. }
  69. final Map<VirtualFile, List<Facet>> value = cachedValue.getValue();
  70. LOG.assertTrue(value != null);
  71. return value;
  72. }
  73. @NotNull
  74. private <F extends Facet&FacetRootsProvider> Map<VirtualFile, List<Facet>> computeRootToFacetsMap(final FacetTypeId<F> type) {
  75. final Module[] modules = myModuleManager.getModules();
  76. final HashMap<VirtualFile, List<Facet>> map = new HashMap<VirtualFile, List<Facet>>();
  77. for (Module module : modules) {
  78. final Collection<F> facets = FacetManager.getInstance(module).getFacetsByType(type);
  79. for (F facet : facets) {
  80. for (VirtualFile root : facet.getFacetRoots()) {
  81. List<Facet> list = map.get(root);
  82. if (list == null) {
  83. list = new SmartList<Facet>();
  84. map.put(root, list);
  85. }
  86. list.add(facet);
  87. }
  88. }
  89. }
  90. return map;
  91. }
  92. @Nullable
  93. public <F extends Facet & FacetRootsProvider> F findFacet(VirtualFile file, FacetTypeId<F> type) {
  94. final List<F> list = findFacets(file, type);
  95. return list.size() > 0 ? list.get(0) : null;
  96. }
  97. @NotNull
  98. public <F extends Facet & FacetRootsProvider> List<F> findFacets(VirtualFile file, FacetTypeId<F> type) {
  99. final Map<VirtualFile, List<Facet>> map = getRootToFacetsMap(type);
  100. if (!map.isEmpty()) {
  101. while (file != null) {
  102. final List<F> list = (List<F>)((List)map.get(file));
  103. if (list != null) {
  104. return list;
  105. }
  106. file = file.getParent();
  107. }
  108. }
  109. return Collections.<F>emptyList();
  110. }
  111. private static class AllFacetsOfTypeModificationTracker<F extends Facet> extends ProjectWideFacetAdapter<F>
  112. implements ModificationTracker, Disposable {
  113. private long myModificationCount;
  114. public AllFacetsOfTypeModificationTracker(final Project project, final FacetTypeId<F> type) {
  115. ProjectWideFacetListenersRegistry.getInstance(project).registerListener(type, this, this);
  116. }
  117. public void facetAdded(final F facet) {
  118. myModificationCount++;
  119. }
  120. public void facetRemoved(final F facet) {
  121. myModificationCount++;
  122. }
  123. public void facetConfigurationChanged(final F facet) {
  124. myModificationCount++;
  125. }
  126. public void dispose() {
  127. }
  128. public long getModificationCount() {
  129. return myModificationCount;
  130. }
  131. }
  132. }