/*
* Copyright 2015 Nokia Solutions and Networks
* Licensed under the Apache License, Version 2.0,
* see license.txt file for details.
*/
package org.robotframework.ide.eclipse.main.plugin.project.editor.libraries;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.rf.ide.core.executor.EnvironmentSearchPaths;
import org.rf.ide.core.executor.RobotRuntimeEnvironment;
import org.rf.ide.core.executor.RobotRuntimeEnvironment.RobotEnvironmentException;
import org.rf.ide.core.project.RobotProjectConfig;
import org.rf.ide.core.project.RobotProjectConfig.LibraryType;
import org.rf.ide.core.project.RobotProjectConfig.ReferencedLibrary;
import org.robotframework.ide.eclipse.main.plugin.RedWorkspace;
import org.robotframework.ide.eclipse.main.plugin.project.RedEclipseProjectConfig;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
public class PythonLibStructureBuilder {
private final RobotRuntimeEnvironment environment;
private final EnvironmentSearchPaths additionalSearchPaths;
public PythonLibStructureBuilder(final RobotRuntimeEnvironment environment, final RobotProjectConfig config,
final IProject project) {
this.environment = environment;
this.additionalSearchPaths = new RedEclipseProjectConfig(config).createEnvironmentSearchPaths(project);
}
public Collection<ILibraryClass> provideEntriesFromFile(final String path) throws RobotEnvironmentException {
return provideEntriesFromFile(path, null, false);
}
public Collection<ILibraryClass> provideEntriesFromFile(final String path, final String moduleName)
throws RobotEnvironmentException {
return provideEntriesFromFile(path, moduleName, true);
}
private Collection<ILibraryClass> provideEntriesFromFile(final String path, final String moduleName,
final boolean allowDuplicationOfFileAndClassName) {
final List<String> classes = environment.getClassesFromModule(new File(path), moduleName,
additionalSearchPaths);
final List<PythonClass> pythonClasses = classes.stream()
.map(name -> PythonClass.create(name, allowDuplicationOfFileAndClassName))
.collect(Collectors.toList());
return new LinkedHashSet<>(pythonClasses);
}
public static final class PythonClass implements ILibraryClass {
private final String qualifiedName;
private PythonClass(final String qualifiedName) {
this.qualifiedName = qualifiedName;
}
static PythonClass create(final String name, final boolean allowDuplicationOfFileAndClassName) {
final List<String> splitted = new ArrayList<>(Splitter.on('.').splitToList(name));
if (splitted.size() > 1) {
final String last = splitted.get(splitted.size() - 1);
final String beforeLast = splitted.get(splitted.size() - 2);
// ROBOT requires whole qualified name of class if it is defined with different name
// than module
// containing it in module
// FIXME check the comment above if its still apply
if (last.equals(beforeLast) && !allowDuplicationOfFileAndClassName) {
splitted.remove(splitted.size() - 1);
}
return new PythonClass(String.join(".", splitted));
} else {
return new PythonClass(name);
}
}
@Override
public String getQualifiedName() {
return qualifiedName;
}
@Override
public ReferencedLibrary toReferencedLibrary(final String fullLibraryPath) {
final IPath path = new Path(fullLibraryPath);
final IPath pathWithoutModuleName = fullLibraryPath.endsWith("__init__.py") ? path.removeLastSegments(2)
: path.removeLastSegments(1);
return ReferencedLibrary.create(LibraryType.PYTHON, qualifiedName,
RedWorkspace.Paths.toWorkspaceRelativeIfPossible(pathWithoutModuleName).toPortableString());
}
@Override
public boolean equals(final Object obj) {
return obj != null && PythonClass.class == obj.getClass()
&& Objects.equal(this.qualifiedName, ((PythonClass) obj).qualifiedName);
}
@Override
public int hashCode() {
return Objects.hashCode(qualifiedName);
}
}
}