update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / ide / util / PackageUtil.java
blob265103648ca3d9ac8c3bb7fa42a20ce0dc2680b4
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.
16 package com.intellij.ide.util;
18 import com.intellij.ide.IdeBundle;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.command.CommandProcessor;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.module.Module;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.project.ProjectBundle;
25 import com.intellij.openapi.projectRoots.impl.ProjectRootUtil;
26 import com.intellij.openapi.roots.ModulePackageIndex;
27 import com.intellij.openapi.roots.ModuleRootManager;
28 import com.intellij.openapi.roots.OrderRootType;
29 import com.intellij.openapi.roots.ui.configuration.CommonContentEntriesEditor;
30 import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
31 import com.intellij.openapi.ui.Messages;
32 import com.intellij.openapi.util.Computable;
33 import com.intellij.openapi.vfs.VirtualFile;
34 import com.intellij.psi.*;
35 import com.intellij.util.ActionRunner;
36 import com.intellij.util.IncorrectOperationException;
37 import com.intellij.util.Processor;
38 import com.intellij.util.Query;
39 import org.jetbrains.annotations.NotNull;
40 import org.jetbrains.annotations.Nullable;
42 import java.io.File;
43 import java.io.IOException;
44 import java.util.ArrayList;
45 import java.util.List;
47 public class PackageUtil {
48 private static final Logger LOG = Logger.getInstance("com.intellij.ide.util.PackageUtil");
50 @Nullable
51 public static PsiDirectory findPossiblePackageDirectoryInModule(Module module, String packageName) {
52 PsiDirectory psiDirectory = null;
53 if (!"".equals(packageName)) {
54 PsiPackage rootPackage = findLongestExistingPackage(module.getProject(), packageName);
55 if (rootPackage != null) {
56 final PsiDirectory[] psiDirectories = getPackageDirectoriesInModule(rootPackage, module);
57 if (psiDirectories.length > 0) {
58 psiDirectory = psiDirectories[0];
62 if (psiDirectory == null) {
63 if (checkSourceRootsConfigured(module)) {
64 final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
65 for (VirtualFile sourceRoot : sourceRoots) {
66 final PsiDirectory directory = PsiManager.getInstance(module.getProject()).findDirectory(sourceRoot);
67 if (directory != null) {
68 psiDirectory = directory;
69 break;
74 return psiDirectory;
77 /**
78 * @deprecated
80 @Nullable
81 public static PsiDirectory findOrCreateDirectoryForPackage(Project project,
82 String packageName,
83 PsiDirectory baseDir,
84 boolean askUserToCreate) throws IncorrectOperationException {
86 PsiDirectory psiDirectory = null;
88 if (!"".equals(packageName)) {
89 PsiPackage rootPackage = findLongestExistingPackage(project, packageName);
90 if (rootPackage != null) {
91 int beginIndex = rootPackage.getQualifiedName().length() + 1;
92 packageName = beginIndex < packageName.length() ? packageName.substring(beginIndex) : "";
93 String postfixToShow = packageName.replace('.', File.separatorChar);
94 if (packageName.length() > 0) {
95 postfixToShow = File.separatorChar + postfixToShow;
97 psiDirectory = DirectoryChooserUtil.selectDirectory(project, rootPackage.getDirectories(), baseDir, postfixToShow);
98 if (psiDirectory == null) return null;
102 if (psiDirectory == null) {
103 PsiDirectory[] sourceDirectories = ProjectRootUtil.getRootDirectories(project, OrderRootType.SOURCES);
104 psiDirectory = DirectoryChooserUtil.selectDirectory(project, sourceDirectories, baseDir,
105 File.separatorChar + packageName.replace('.', File.separatorChar));
106 if (psiDirectory == null) return null;
109 String restOfName = packageName;
110 boolean askedToCreate = false;
111 while (restOfName.length() > 0) {
112 final String name = getLeftPart(restOfName);
113 PsiDirectory foundExistingDirectory = psiDirectory.findSubdirectory(name);
114 if (foundExistingDirectory == null) {
115 if (!askedToCreate && askUserToCreate) {
116 int toCreate = Messages.showYesNoDialog(project,
117 IdeBundle.message("prompt.create.non.existing.package", packageName),
118 IdeBundle.message("title.package.not.found"),
119 Messages.getQuestionIcon());
120 if (toCreate != 0) {
121 return null;
123 askedToCreate = true;
125 psiDirectory = createSubdirectory(psiDirectory, name, project);
127 else {
128 psiDirectory = foundExistingDirectory;
130 restOfName = cutLeftPart(restOfName);
132 return psiDirectory;
135 private static PsiDirectory createSubdirectory(final PsiDirectory oldDirectory,
136 final String name, Project project) throws IncorrectOperationException {
137 final PsiDirectory[] psiDirectory = new PsiDirectory[1];
138 final IncorrectOperationException[] exception = new IncorrectOperationException[1];
140 CommandProcessor.getInstance().executeCommand(project, new Runnable(){
141 public void run() {
142 psiDirectory[0] = ApplicationManager.getApplication().runWriteAction(new Computable<PsiDirectory>() {
143 public PsiDirectory compute() {
144 try {
145 return oldDirectory.createSubdirectory(name);
147 catch (IncorrectOperationException e) {
148 exception[0] = e;
149 return null;
154 }, IdeBundle.message("command.create.new.subdirectory"), null);
156 if (exception[0] != null) throw exception[0];
158 return psiDirectory[0];
161 public static PsiDirectory findOrCreateDirectoryForPackage(@NotNull Module module,
162 String packageName,
163 PsiDirectory baseDir,
164 boolean askUserToCreate) throws IncorrectOperationException {
165 final Project project = module.getProject();
166 PsiDirectory psiDirectory = null;
167 if (!"".equals(packageName)) {
168 PsiPackage rootPackage = findLongestExistingPackage(module, packageName);
169 if (rootPackage != null) {
170 int beginIndex = rootPackage.getQualifiedName().length() + 1;
171 packageName = beginIndex < packageName.length() ? packageName.substring(beginIndex) : "";
172 String postfixToShow = packageName.replace('.', File.separatorChar);
173 if (packageName.length() > 0) {
174 postfixToShow = File.separatorChar + postfixToShow;
176 PsiDirectory[] moduleDirectories = getPackageDirectoriesInModule(rootPackage, module);
177 psiDirectory = DirectoryChooserUtil.selectDirectory(project, moduleDirectories, baseDir, postfixToShow);
178 if (psiDirectory == null) return null;
182 if (psiDirectory == null) {
183 if (!checkSourceRootsConfigured(module)) return null;
184 final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
185 List<PsiDirectory> directoryList = new ArrayList<PsiDirectory>();
186 for (VirtualFile sourceRoot : sourceRoots) {
187 final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(sourceRoot);
188 if (directory != null) {
189 directoryList.add(directory);
192 PsiDirectory[] sourceDirectories = directoryList.toArray(new PsiDirectory[directoryList.size()]);
193 psiDirectory = DirectoryChooserUtil.selectDirectory(project, sourceDirectories, baseDir,
194 File.separatorChar + packageName.replace('.', File.separatorChar));
195 if (psiDirectory == null) return null;
198 String restOfName = packageName;
199 boolean askedToCreate = false;
200 while (restOfName.length() > 0) {
201 final String name = getLeftPart(restOfName);
202 PsiDirectory foundExistingDirectory = psiDirectory.findSubdirectory(name);
203 if (foundExistingDirectory == null) {
204 if (!askedToCreate && askUserToCreate) {
205 if (!ApplicationManager.getApplication().isUnitTestMode()) {
206 int toCreate = Messages.showYesNoDialog(project,
207 IdeBundle.message("prompt.create.non.existing.package", packageName),
208 IdeBundle.message("title.package.not.found"),
209 Messages.getQuestionIcon());
210 if (toCreate != 0) {
211 return null;
214 askedToCreate = true;
217 final PsiDirectory psiDirectory1 = psiDirectory;
218 try {
219 psiDirectory = ActionRunner.runInsideWriteAction(new ActionRunner.InterruptibleRunnableWithResult<PsiDirectory>() {
220 public PsiDirectory run() throws Exception {
221 return psiDirectory1.createSubdirectory(name);
225 catch(IncorrectOperationException e) {
226 throw e;
228 catch(IOException e) {
229 throw new IncorrectOperationException(e.toString(), e);
231 catch (Exception e) {
232 LOG.error(e);
235 else {
236 psiDirectory = foundExistingDirectory;
238 restOfName = cutLeftPart(restOfName);
240 return psiDirectory;
243 private static PsiDirectory[] getPackageDirectoriesInModule(PsiPackage rootPackage, Module module) {
244 final PsiManager manager = PsiManager.getInstance(module.getProject());
245 final String packageName = rootPackage.getQualifiedName();
246 final List<PsiDirectory> moduleDirectoryList = new ArrayList<PsiDirectory>();
247 ModulePackageIndex.getInstance(module).getDirsByPackageName(packageName, false).forEach(new Processor<VirtualFile>() {
248 public boolean process(final VirtualFile directory) {
249 moduleDirectoryList.add(manager.findDirectory(directory));
250 return true;
254 return moduleDirectoryList.toArray(new PsiDirectory[moduleDirectoryList.size()]);
257 private static PsiPackage findLongestExistingPackage(Project project, String packageName) {
258 PsiManager manager = PsiManager.getInstance(project);
259 String nameToMatch = packageName;
260 while (true) {
261 PsiPackage aPackage = JavaPsiFacade.getInstance(manager.getProject()).findPackage(nameToMatch);
262 if (aPackage != null && isWritablePackage(aPackage)) return aPackage;
263 int lastDotIndex = nameToMatch.lastIndexOf('.');
264 if (lastDotIndex >= 0) {
265 nameToMatch = nameToMatch.substring(0, lastDotIndex);
267 else {
268 return null;
273 private static boolean isWritablePackage(PsiPackage aPackage) {
274 PsiDirectory[] directories = aPackage.getDirectories();
275 for (PsiDirectory directory : directories) {
276 if (directory.isValid() && directory.isWritable()) {
277 return true;
280 return false;
283 private static PsiDirectory getWritableDirectory(Query<VirtualFile> vFiles, PsiManager manager) {
284 for (VirtualFile vFile : vFiles) {
285 PsiDirectory directory = manager.findDirectory(vFile);
286 if (directory != null && directory.isValid() && directory.isWritable()) {
287 return directory;
290 return null;
293 private static PsiPackage findLongestExistingPackage(Module module, String packageName) {
294 final PsiManager manager = PsiManager.getInstance(module.getProject());
296 String nameToMatch = packageName;
297 while (true) {
298 Query<VirtualFile> vFiles = ModulePackageIndex.getInstance(module).getDirsByPackageName(nameToMatch, false);
299 PsiDirectory directory = getWritableDirectory(vFiles, manager);
300 if (directory != null) return JavaDirectoryService.getInstance().getPackage(directory);
302 int lastDotIndex = nameToMatch.lastIndexOf('.');
303 if (lastDotIndex >= 0) {
304 nameToMatch = nameToMatch.substring(0, lastDotIndex);
306 else {
307 return null;
312 private static String getLeftPart(String packageName) {
313 int index = packageName.indexOf('.');
314 return index > -1 ? packageName.substring(0, index) : packageName;
317 private static String cutLeftPart(String packageName) {
318 int index = packageName.indexOf('.');
319 return index > -1 ? packageName.substring(index + 1) : "";
322 public static boolean checkSourceRootsConfigured(final Module module) {
323 VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
324 if (sourceRoots.length == 0) {
325 Messages.showErrorDialog(
326 module.getProject(),
327 ProjectBundle.message("module.source.roots.not.configured.error", module.getName()),
328 ProjectBundle.message("module.source.roots.not.configured.title")
331 ProjectSettingsService.getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), CommonContentEntriesEditor.NAME, false);
333 sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
334 if (sourceRoots.length == 0) {
335 return false;
338 return true;