blob: f87c1fe3a23f1373bf337bd68fbcfb50d34719d9 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.facet.impl;
import com.intellij.facet.*;
import com.intellij.openapi.util.SimpleModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.Module;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author nik
*/
public class FacetFinderImpl extends FacetFinder {
private static final Logger LOG = Logger.getInstance("#com.intellij.facet.impl.FacetFinderImpl");
private final Map<FacetTypeId, AllFacetsOfTypeModificationTracker> myAllFacetTrackers = new HashMap<FacetTypeId, AllFacetsOfTypeModificationTracker>();
private final Map<FacetTypeId, CachedValue<Map<VirtualFile, List<Facet>>>> myCachedMaps =
new HashMap<FacetTypeId, CachedValue<Map<VirtualFile, List<Facet>>>>();
private final Project myProject;
private final CachedValuesManager myCachedValuesManager;
private final ModuleManager myModuleManager;
public FacetFinderImpl(Project project) {
myProject = project;
myCachedValuesManager = CachedValuesManager.getManager(project);
myModuleManager = ModuleManager.getInstance(myProject);
}
@Override
public <F extends Facet> ModificationTracker getAllFacetsOfTypeModificationTracker(FacetTypeId<F> type) {
AllFacetsOfTypeModificationTracker tracker = myAllFacetTrackers.get(type);
if (tracker == null) {
tracker = new AllFacetsOfTypeModificationTracker<F>(myProject, type);
Disposer.register(myProject, tracker);
myAllFacetTrackers.put(type, tracker);
}
return tracker;
}
private <F extends Facet & FacetRootsProvider> Map<VirtualFile, List<Facet>> getRootToFacetsMap(final FacetTypeId<F> type) {
CachedValue<Map<VirtualFile, List<Facet>>> cachedValue = myCachedMaps.get(type);
if (cachedValue == null) {
cachedValue = myCachedValuesManager.createCachedValue(new CachedValueProvider<Map<VirtualFile, List<Facet>>>() {
@Override
public Result<Map<VirtualFile, List<Facet>>> compute() {
Map<VirtualFile, List<Facet>> map = computeRootToFacetsMap(type);
return Result.create(map, getAllFacetsOfTypeModificationTracker(type));
}
}, false);
myCachedMaps.put(type, cachedValue);
}
final Map<VirtualFile, List<Facet>> value = cachedValue.getValue();
LOG.assertTrue(value != null);
return value;
}
@NotNull
private <F extends Facet&FacetRootsProvider> Map<VirtualFile, List<Facet>> computeRootToFacetsMap(final FacetTypeId<F> type) {
final Module[] modules = myModuleManager.getModules();
final HashMap<VirtualFile, List<Facet>> map = new HashMap<VirtualFile, List<Facet>>();
for (Module module : modules) {
final Collection<F> facets = FacetManager.getInstance(module).getFacetsByType(type);
for (F facet : facets) {
for (VirtualFile root : facet.getFacetRoots()) {
List<Facet> list = map.get(root);
if (list == null) {
list = new SmartList<Facet>();
map.put(root, list);
}
list.add(facet);
}
}
}
return map;
}
@Override
@Nullable
public <F extends Facet & FacetRootsProvider> F findFacet(VirtualFile file, FacetTypeId<F> type) {
final List<F> list = findFacets(file, type);
return list.size() > 0 ? list.get(0) : null;
}
@Override
@NotNull
public <F extends Facet & FacetRootsProvider> List<F> findFacets(VirtualFile file, FacetTypeId<F> type) {
final Map<VirtualFile, List<Facet>> map = getRootToFacetsMap(type);
if (!map.isEmpty()) {
while (file != null) {
final List<F> list = (List<F>)((List)map.get(file));
if (list != null) {
return list;
}
file = file.getParent();
}
}
return Collections.<F>emptyList();
}
private static class AllFacetsOfTypeModificationTracker<F extends Facet> extends SimpleModificationTracker implements Disposable, ProjectWideFacetListener<F> {
public AllFacetsOfTypeModificationTracker(final Project project, final FacetTypeId<F> type) {
ProjectWideFacetListenersRegistry.getInstance(project).registerListener(type, this, this);
}
@Override
public void facetAdded(final F facet) {
incModificationCount();
}
@Override
public void facetRemoved(final F facet) {
incModificationCount();
}
@Override
public void facetConfigurationChanged(final F facet) {
incModificationCount();
}
@Override
public void firstFacetAdded() {
}
@Override
public void beforeFacetRemoved(F facet) {
}
@Override
public void allFacetsRemoved() {
}
@Override
public void dispose() {
}
}
}