package org.erlide.engine.internal.services.search;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.erlide.engine.ErlangEngine;
import org.erlide.engine.internal.model.cache.ErlModelCache;
import org.erlide.engine.model.ErlElementKind;
import org.erlide.engine.model.ErlModelException;
import org.erlide.engine.model.IErlElement;
import org.erlide.engine.model.IParent;
import org.erlide.engine.model.erlang.ErlangIncludeFile;
import org.erlide.engine.model.erlang.SourceKind;
import org.erlide.engine.model.root.IErlExternal;
import org.erlide.engine.model.root.IErlModule;
import org.erlide.engine.model.root.IErlProject;
import org.erlide.engine.services.search.ModelSearcherService;
import org.erlide.engine.services.search.ModelUtilService;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class ModelSearcher implements ModelSearcherService {
private final ModelUtilService modelUtilService;
public ModelSearcher() {
modelUtilService = ErlangEngine.getInstance().getModelUtilService();
}
/*
* (non-Javadoc)
*
* @see
* org.erlide.engine.model.ModelSearcherService#findAllIncludedFiles(org
* .erlide.engine.model.erlang.IErlModule)
*/
@Override
public Collection<IErlModule> findAllIncludedFiles(final IErlModule module)
throws CoreException {
final List<IErlModule> checked = Lists.newArrayList();
return findAllIncludedFiles(module, checked);
}
public Collection<IErlModule> findAllIncludedFiles(final IErlModule module,
final List<IErlModule> checked) throws CoreException {
final Collection<IErlModule> result = Sets.newHashSet();
if (checked.contains(module)) {
return result;
}
checked.add(module);
final List<IErlModule> includedFilesForModule = ErlModelCache.getDefault()
.getIncludedFilesForModule(module);
if (includedFilesForModule != null && !includedFilesForModule.isEmpty()) {
return includedFilesForModule;
}
final Collection<ErlangIncludeFile> includedFiles = module.getIncludeFiles();
final IErlProject project = modelUtilService.getProject(module);
if (project == null) {
return result;
}
final Collection<IErlModule> includes = project.getIncludes();
includes.addAll(getLocalIncludes(module));
Collection<IErlModule> externalIncludes = null;
Collection<IErlModule> referencedIncludes = null;
Collection<IErlModule> modules = null;
for (final ErlangIncludeFile includeFile : includedFiles) {
final String includeFileName = includeFile.getFilenameLastPart();
if (findAllIncludedFilesAux(checked, result, includes, includeFileName)) {
continue;
}
if (referencedIncludes == null) {
referencedIncludes = Lists.newArrayList();
final Collection<IErlProject> referencedProjects = project
.getReferencedProjects();
for (final IErlProject referencedProject : referencedProjects) {
referencedIncludes.addAll(referencedProject.getIncludes());
}
}
if (findAllIncludedFilesAux(checked, result, referencedIncludes,
includeFileName)) {
continue;
}
if (externalIncludes == null) {
externalIncludes = project.getExternalIncludes();
}
if (findAllIncludedFilesAux(checked, result, externalIncludes,
includeFileName)) {
continue;
}
if (modules == null) {
modules = project.getModules();
}
findAllIncludedFilesAux(checked, result, modules, includeFileName);
}
ErlModelCache.getDefault().putIncludedFilesForModule(module, result);
return result;
}
private Collection<IErlModule> getLocalIncludes(final IErlModule module)
throws ErlModelException {
final List<IErlModule> result = Lists.newArrayList();
final IParent parent = module.getParent();
for (final IErlElement child : parent.getChildrenOfKind(ErlElementKind.MODULE)) {
if (child instanceof IErlModule
&& SourceKind.nameToModuleKind(child.getName()) == SourceKind.HRL) {
result.add((IErlModule) child);
}
}
return result;
}
private boolean findAllIncludedFilesAux(final List<IErlModule> checked,
final Collection<IErlModule> result, final Collection<IErlModule> includes,
final String includeFileName) throws CoreException {
for (final IErlModule include : includes) {
if (include.getName().equals(includeFileName)) {
if (include.getParent() instanceof IErlExternal) {
result.add(findExternalIncludeInOpenProjects(include));
} else {
result.add(include);
}
result.addAll(findAllIncludedFiles(include, checked));
return true;
}
}
return false;
}
public static IErlModule findExternalIncludeInOpenProjects(
final IErlModule externalInclude) throws CoreException {
final String filePath = externalInclude.getFilePath();
final Collection<IErlProject> projects = ErlangEngine.getInstance().getModel()
.getErlangProjects();
for (final IErlProject project : projects) {
final Collection<IErlModule> includes = project.getIncludes();
for (final IErlModule include : includes) {
if (include.getFilePath().equals(filePath)) {
return include;
}
}
}
return externalInclude;
}
}