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
.util
;
19 import com
.intellij
.ProjectTopics
;
20 import com
.intellij
.openapi
.fileTypes
.FileType
;
21 import com
.intellij
.openapi
.module
.Module
;
22 import com
.intellij
.openapi
.module
.ModuleManager
;
23 import com
.intellij
.openapi
.module
.ModuleUtil
;
24 import com
.intellij
.openapi
.project
.Project
;
25 import com
.intellij
.openapi
.roots
.ModuleRootEvent
;
26 import com
.intellij
.openapi
.roots
.ModuleRootListener
;
27 import com
.intellij
.openapi
.roots
.ModuleRootManager
;
28 import com
.intellij
.openapi
.util
.MultiValuesMap
;
29 import com
.intellij
.openapi
.vfs
.VfsUtil
;
30 import com
.intellij
.openapi
.vfs
.VirtualFile
;
31 import com
.intellij
.util
.containers
.ContainerUtil
;
32 import com
.intellij
.util
.messages
.MessageBus
;
33 import com
.intellij
.util
.messages
.MessageBusConnection
;
34 import gnu
.trove
.THashMap
;
35 import org
.jetbrains
.annotations
.NotNull
;
36 import org
.jetbrains
.annotations
.Nullable
;
43 public class LogicalRootsManagerImpl
extends LogicalRootsManager
{
44 private Map
<Module
, MultiValuesMap
<LogicalRootType
, LogicalRoot
>> myRoots
= null;
45 private final MultiValuesMap
<LogicalRootType
, NotNullFunction
> myProviders
= new MultiValuesMap
<LogicalRootType
, NotNullFunction
>();
46 private final MultiValuesMap
<FileType
, LogicalRootType
> myFileTypes2RootTypes
= new MultiValuesMap
<FileType
, LogicalRootType
>();
47 private final ModuleManager myModuleManager
;
48 private final Project myProject
;
50 public LogicalRootsManagerImpl(final MessageBus bus
, final ModuleManager moduleManager
, final Project project
) {
51 myModuleManager
= moduleManager
;
54 final MessageBusConnection connection
= bus
.connect();
55 connection
.subscribe(ProjectTopics
.LOGICAL_ROOTS
, new LogicalRootListener() {
56 public void logicalRootsChanged() {
58 //updateCache(moduleManager);
61 connection
.subscribe(ProjectTopics
.PROJECT_ROOTS
, new ModuleRootListener() {
62 public void beforeRootsChange(ModuleRootEvent event
) {
65 public void rootsChanged(ModuleRootEvent event
) {
66 bus
.asyncPublisher(ProjectTopics
.LOGICAL_ROOTS
).logicalRootsChanged();
69 registerLogicalRootProvider(LogicalRootType
.SOURCE_ROOT
, new NotNullFunction
<Module
, List
<VirtualFileLogicalRoot
>>() {
71 public List
<VirtualFileLogicalRoot
> fun(final Module module
) {
72 return ContainerUtil
.map2List(ModuleRootManager
.getInstance(module
).getSourceRoots(), new Function
<VirtualFile
, VirtualFileLogicalRoot
>() {
73 public VirtualFileLogicalRoot
fun(final VirtualFile s
) {
74 return new VirtualFileLogicalRoot(s
);
81 private synchronized void clear() {
85 private synchronized Map
<Module
, MultiValuesMap
<LogicalRootType
, LogicalRoot
>> getRoots(final ModuleManager moduleManager
) {
86 if (myRoots
== null) {
87 myRoots
= new THashMap
<Module
, MultiValuesMap
<LogicalRootType
, LogicalRoot
>>();
89 final Module
[] modules
= moduleManager
.getModules();
90 for (Module module
: modules
) {
91 final MultiValuesMap
<LogicalRootType
, LogicalRoot
> map
= new MultiValuesMap
<LogicalRootType
, LogicalRoot
>();
92 for (Map
.Entry
<LogicalRootType
, Collection
<NotNullFunction
>> entry
: myProviders
.entrySet()) {
93 final Collection
<NotNullFunction
> functions
= entry
.getValue();
94 for (NotNullFunction function
: functions
) {
95 map
.putAll(entry
.getKey(), (List
<LogicalRoot
>) function
.fun(module
));
98 myRoots
.put(module
, map
);
106 public LogicalRoot
findLogicalRoot(@NotNull final VirtualFile file
) {
107 final Module module
= ModuleUtil
.findModuleForFile(file
, myProject
);
108 if (module
== null) return null;
110 LogicalRoot result
= null;
111 final List
<LogicalRoot
> list
= getLogicalRoots(module
);
112 for (final LogicalRoot root
: list
) {
113 final VirtualFile rootFile
= root
.getVirtualFile();
114 if (rootFile
!= null && VfsUtil
.isAncestor(rootFile
, file
, false)) {
123 public List
<LogicalRoot
> getLogicalRoots() {
124 return ContainerUtil
.concat(myModuleManager
.getModules(), new Function
<Module
, Collection
<?
extends LogicalRoot
>>() {
125 public Collection
<?
extends LogicalRoot
> fun(final Module module
) {
126 return getLogicalRoots(module
);
131 public List
<LogicalRoot
> getLogicalRoots(@NotNull final Module module
) {
132 final Map
<Module
, MultiValuesMap
<LogicalRootType
, LogicalRoot
>> roots
= getRoots(myModuleManager
);
133 final MultiValuesMap
<LogicalRootType
, LogicalRoot
> valuesMap
= roots
.get(module
);
134 if (valuesMap
== null) {
135 return Collections
.emptyList();
137 return new ArrayList
<LogicalRoot
>(valuesMap
.values());
140 public List
<LogicalRoot
> getLogicalRootsOfType(@NotNull final Module module
, @NotNull final LogicalRootType
... types
) {
141 return ContainerUtil
.concat(types
, new Function
<LogicalRootType
, Collection
<?
extends LogicalRoot
>>() {
142 public Collection
<?
extends LogicalRoot
> fun(final LogicalRootType s
) {
143 return getLogicalRootsOfType(module
, s
);
148 public <T
extends LogicalRoot
> List
<T
> getLogicalRootsOfType(@NotNull final Module module
, @NotNull final LogicalRootType
<T
> type
) {
149 final Map
<Module
, MultiValuesMap
<LogicalRootType
, LogicalRoot
>> roots
= getRoots(myModuleManager
);
150 final MultiValuesMap
<LogicalRootType
, LogicalRoot
> map
= roots
.get(module
);
152 return Collections
.emptyList();
155 Collection
<LogicalRoot
> collection
= map
.get(type
);
156 if (collection
== null) return Collections
.emptyList();
157 return new ArrayList
<T
>((Collection
<T
>)collection
);
161 public LogicalRootType
[] getRootTypes(@NotNull final FileType type
) {
162 final Collection
<LogicalRootType
> rootTypes
= myFileTypes2RootTypes
.get(type
);
163 if (rootTypes
== null) {
164 return new LogicalRootType
[0];
167 return rootTypes
.toArray(new LogicalRootType
[rootTypes
.size()]);
170 public void registerRootType(@NotNull final FileType fileType
, @NotNull final LogicalRootType
... rootTypes
) {
171 myFileTypes2RootTypes
.putAll(fileType
, rootTypes
);
174 public <T
extends LogicalRoot
> void registerLogicalRootProvider(@NotNull final LogicalRootType
<T
> rootType
, @NotNull NotNullFunction
<Module
, List
<T
>> provider
) {
175 myProviders
.put(rootType
, provider
);