package com.lightd.ideap.maven.navigation;
import com.intellij.navigation.ChooseByNameContributorEx;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScopes;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.indexing.FindSymbolParameters;
import com.intellij.util.indexing.IdFilter;
import com.lightd.ideap.maven.settings.MvnRunConfigurationSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class PomNavigationContributor implements ChooseByNameContributorEx, DumbAware {
private final Project project;
private final boolean showPomLocation;
private MavenProjectsManager projectsManager;
public PomNavigationContributor(Project project) {
this.project = project;
showPomLocation = MvnRunConfigurationSettings.getInstance().isShowPomLocation();
}
@Override
public void processNames(@NotNull final Processor<String> processor, @NotNull GlobalSearchScope scope, IdFilter filter) {
projectsManager = MavenProjectsManager.getInstance(project);
List<MavenProject> mavenProjects = projectsManager.getRootProjects();
if (mavenProjects.size() > 0) {
addProjectNames(processor, mavenProjects.get(0));
if (scope.isSearchInLibraries()) {
for (MavenId mavenId : getNotImportPoms(mavenProjects.get(0)).keySet()) {
processor.process(mavenId.getKey());
}
}
}
}
private void addProjectNames(final Processor<String> processor, MavenProject mavenProject) {
processor.process(mavenProject.getMavenId().getKey());
for (MavenProject subModule : projectsManager.getModules(mavenProject)) {
addProjectNames(processor, subModule);
}
}
@Override
public void processElementsWithName(@NotNull String name,
@NotNull final Processor<NavigationItem> processor,
@NotNull FindSymbolParameters parameters) {
final MinusculeMatcher matcher = NameUtil.buildMatcher(parameters.getCompletePattern(), NameUtil.MatchingCaseSensitivity.FIRST_LETTER);
if (!matcher.isStartMatch(name.substring(0, name.lastIndexOf(':')))) return;
String[] names = name.split(":");
MavenId mavenId = new MavenId(names[0], names[1], names[2]);
projectsManager = MavenProjectsManager.getInstance(project);
MavenProject p = projectsManager.findProject(mavenId);
PsiFileSystemItem pomFile = null;
if (p != null) {
pomFile = PsiManager.getInstance(project).findFile(p.getFile());
} else if (parameters.isSearchInLibraries()) {
Map<MavenId, PsiFile> notImportPoms = getNotImportPoms(projectsManager.getRootProjects().get(0));
pomFile = notImportPoms.get(mavenId);
}
if (pomFile != null) {
PomWrapper pomWrapper = new PomWrapper(pomFile, mavenId, project.getBasePath(), showPomLocation);
processor.process(pomWrapper);
}
}
@NotNull
@Override
public String[] getNames(Project project, boolean includeNonProjectItems) {
CommonProcessors.CollectProcessor<String> processor = new CommonProcessors.CollectProcessor<String>();
GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
processNames(processor, scope, IdFilter.getProjectIdFilter(project, includeNonProjectItems));
return ArrayUtil.toStringArray(processor.getResults());
}
@NotNull
@Override
public NavigationItem[] getItemsByName(String name, final String pattern, Project project, boolean includeNonProjectItems) {
CommonProcessors.CollectProcessor<NavigationItem> processor = new CommonProcessors.CollectProcessor<NavigationItem>();
processElementsWithName(name, processor, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems));
return processor.toArray(new NavigationItem[processor.getResults().size()]);
}
private Map<MavenId, PsiFile> getNotImportPoms(MavenProject mavenProject) {
GlobalSearchScope pomScope = GlobalSearchScopes.directoryScope(project, mavenProject.getDirectoryFile(), true);
PsiFile[] psiFiles = FilenameIndex.getFilesByName(project, "pom.xml", pomScope);
Map<MavenId, PsiFile> poms = new LinkedHashMap<MavenId, PsiFile>(psiFiles.length);
for (PsiFile psiFile : psiFiles) {
if (projectsManager.findProject(psiFile.getVirtualFile()) == null) {
MavenId mavenId = MavenDomUtil.describe(psiFile);
poms.put(mavenId, psiFile);
}
}
return poms;
}
}