fix dispose for libraries in project structure + directory-based storage fix: set...
[fedora-idea.git] / platform / lang-impl / src / com / intellij / openapi / roots / impl / ModuleOrderEntryImpl.java
blobe03a29d8ebba631e8f971b4fd2e578d69c203906
1 /*
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.openapi.roots.impl;
19 import com.intellij.ProjectTopics;
20 import com.intellij.openapi.module.Module;
21 import com.intellij.openapi.module.ModuleManager;
22 import com.intellij.openapi.module.impl.ModuleManagerImpl;
23 import com.intellij.openapi.project.ModuleListener;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.roots.*;
26 import com.intellij.openapi.util.Comparing;
27 import com.intellij.openapi.util.InvalidDataException;
28 import com.intellij.openapi.util.WriteExternalException;
29 import com.intellij.openapi.vfs.VirtualFile;
30 import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
31 import com.intellij.util.ArrayUtil;
32 import com.intellij.util.containers.HashSet;
33 import com.intellij.util.messages.MessageBusConnection;
34 import org.jdom.Element;
35 import org.jetbrains.annotations.NonNls;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
39 import java.util.List;
40 import java.util.Set;
42 /**
43 * @author dsl
45 public class ModuleOrderEntryImpl extends OrderEntryBaseImpl implements ModuleOrderEntry, WritableOrderEntry, ClonableOrderEntry {
46 @NonNls public static final String ENTRY_TYPE = "module";
47 @NonNls public static final String MODULE_NAME_ATTR = "module-name";
48 @NonNls private static final String EXPORTED_ATTR = "exported";
49 @NonNls private static final String SCOPE_ATTR = "scope";
51 private Module myModule;
52 private String myModuleName; // non-null if myProject is null
53 private boolean myExported = false;
54 @NotNull private DependencyScope myScope;
55 private MessageBusConnection myConnection;
57 ModuleOrderEntryImpl(Module module, RootModelImpl rootModel) {
58 super(rootModel);
59 myModule = module;
60 myScope = DependencyScope.COMPILE;
63 ModuleOrderEntryImpl(String moduleName, RootModelImpl rootModel) {
64 super(rootModel);
65 myModuleName = moduleName;
66 myModule = null;
67 myScope = DependencyScope.COMPILE;
70 ModuleOrderEntryImpl(Element element, RootModelImpl rootModel, ModuleManager moduleManager) throws InvalidDataException {
71 super(rootModel);
72 myExported = element.getAttributeValue(EXPORTED_ATTR) != null;
73 final String moduleName = element.getAttributeValue(MODULE_NAME_ATTR);
74 if (moduleName == null) {
75 throw new InvalidDataException();
78 myModule = moduleManager.findModuleByName(moduleName);
79 if (myModule == null) {
80 myModuleName = moduleName;
82 else {
83 myModuleName = null;
85 myScope = DependencyScope.readExternal(element);
88 private ModuleOrderEntryImpl(ModuleOrderEntryImpl that, RootModelImpl rootModel) {
89 super(rootModel);
90 final Module thatModule = that.myModule;
91 if (thatModule != null) {
92 if (!thatModule.isDisposed()) {
93 myModule = thatModule;
94 } else {
95 myModule = null;
96 myModuleName = thatModule.getUserData(ModuleManagerImpl.DISPOSED_MODULE_NAME);
99 else {
100 myModuleName = that.myModuleName;
102 myExported = that.myExported;
103 myScope = that.myScope;
104 addListeners();
107 private boolean myListenersAdded = false;
109 private void addListeners() {
110 myListenersAdded = true;
111 myConnection = getRootModel().getProject().getMessageBus().connect();
112 myConnection.subscribe(ProjectTopics.MODULES, new MyModuleListener());
115 @NotNull
116 public Module getOwnerModule() {
117 return getRootModel().getModule();
120 @NotNull
121 public VirtualFile[] getFiles(OrderRootType type) {
122 return getFiles(type, new HashSet<Module>());
125 @NotNull
126 VirtualFile[] getFiles(OrderRootType type, Set<Module> processed) {
127 if (myModule != null && !processed.contains(myModule) && !myModule.isDisposed()) {
128 processed.add(myModule);
129 if (myScope == DependencyScope.RUNTIME && type == OrderRootType.PRODUCTION_COMPILATION_CLASSES) {
130 return VirtualFile.EMPTY_ARRAY;
132 if (myScope == DependencyScope.TEST && type == OrderRootType.PRODUCTION_COMPILATION_CLASSES) {
133 return VirtualFile.EMPTY_ARRAY;
135 if (myScope == DependencyScope.PROVIDED && type == OrderRootType.CLASSES_AND_OUTPUT) {
136 return VirtualFile.EMPTY_ARRAY;
138 return ((ModuleRootManagerImpl)ModuleRootManager.getInstance(myModule)).getFilesForOtherModules(type, processed);
140 else {
141 return VirtualFile.EMPTY_ARRAY;
145 @NotNull
146 public String[] getUrls(OrderRootType rootType) {
147 return getUrls(rootType, new HashSet<Module>());
150 public String[] getUrls (OrderRootType rootType, Set<Module> processed) {
151 if (myModule != null && !processed.contains(myModule) && !myModule.isDisposed()) {
152 processed.add(myModule);
153 if (myScope == DependencyScope.RUNTIME && rootType == OrderRootType.PRODUCTION_COMPILATION_CLASSES) {
154 return ArrayUtil.EMPTY_STRING_ARRAY;
156 if (myScope == DependencyScope.TEST && rootType == OrderRootType.PRODUCTION_COMPILATION_CLASSES) {
157 return ArrayUtil.EMPTY_STRING_ARRAY;
159 if (myScope == DependencyScope.PROVIDED && rootType == OrderRootType.CLASSES_AND_OUTPUT) {
160 return ArrayUtil.EMPTY_STRING_ARRAY;
162 return ((ModuleRootManagerImpl)ModuleRootManager.getInstance(myModule)).getUrlsForOtherModules(rootType, processed);
164 else {
165 return ArrayUtil.EMPTY_STRING_ARRAY;
170 public boolean isValid() {
171 return !isDisposed() && getModule() != null;
174 public <R> R accept(RootPolicy<R> policy, R initialValue) {
175 return policy.visitModuleOrderEntry(this, initialValue);
178 public String getPresentableName() {
179 if (myModule != null) {
180 return myModule.getName();
182 else {
183 return myModuleName;
187 public boolean isSynthetic() {
188 return false;
191 @Nullable
192 public Module getModule() {
193 return getRootModel().getConfigurationAccessor().getModule(myModule, myModuleName);
196 public void writeExternal(Element rootElement) throws WriteExternalException {
197 final Element element = OrderEntryFactory.createOrderEntryElement(ENTRY_TYPE);
198 element.setAttribute(MODULE_NAME_ATTR, getModuleName());
199 if (myExported) {
200 element.setAttribute(EXPORTED_ATTR, "");
202 myScope.writeExternal(element);
203 rootElement.addContent(element);
206 public String getModuleName() {
207 if (myModule != null) {
208 return myModule.getName();
210 else {
211 return myModuleName;
215 public OrderEntry cloneEntry(RootModelImpl rootModel,
216 ProjectRootManagerImpl projectRootManager,
217 VirtualFilePointerManager filePointerManager) {
218 return new ModuleOrderEntryImpl(this, rootModel);
221 public void dispose() {
222 super.dispose();
223 if (myListenersAdded) {
224 myConnection.disconnect();
228 private void moduleAdded(Module module) {
229 if (Comparing.equal(myModuleName, module.getName())) {
230 setModule(module);
234 private void setModule(Module module) {
235 myModule = module;
236 myModuleName = null;
239 private void moduleRemoved(Module module) {
240 if (myModule == module) {
241 unsetModule(module);
245 private void unsetModule(Module module) {
246 myModuleName = module.getName();
247 myModule = null;
250 public boolean isExported() {
251 return myExported;
254 public void setExported(boolean value) {
255 getRootModel().assertWritable();
256 myExported = value;
259 @NotNull
260 public DependencyScope getScope() {
261 return myScope;
264 public void setScope(@NotNull DependencyScope scope) {
265 getRootModel().assertWritable();
266 myScope = scope;
269 private class MyModuleListener implements ModuleListener {
271 public MyModuleListener() {
274 public void moduleAdded(Project project, Module module) {
275 final ModuleOrderEntryImpl moduleOrderEntry = ModuleOrderEntryImpl.this;
276 moduleOrderEntry.moduleAdded(module);
279 public void beforeModuleRemoved(Project project, Module module) {
282 public void moduleRemoved(Project project, Module module) {
283 final ModuleOrderEntryImpl moduleOrderEntry = ModuleOrderEntryImpl.this;
284 moduleOrderEntry.moduleRemoved(module);
287 public void modulesRenamed(Project project, List<Module> modules) {
288 if (myModule != null) return;
289 for (Module module : modules) {
290 if (module.getName().equals(myModuleName)) {
291 setModule(module);
292 break;
298 protected void projectOpened() {
299 addListeners();
302 protected void moduleAdded() {
303 super.moduleAdded();
304 if (myModule == null) {
305 final Module module = ModuleManager.getInstance(getRootModel().getModule().getProject()).findModuleByName(myModuleName);
306 if (module != null) {
307 setModule(module);