package org.pitest.classpath;
import static org.pitest.functional.FCollection.flatMap;
import static org.pitest.functional.prelude.Prelude.and;
import static org.pitest.functional.prelude.Prelude.not;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.pitest.classinfo.ClassInfo;
import org.pitest.classinfo.ClassInfoSource;
import org.pitest.classinfo.ClassName;
import org.pitest.classinfo.NameToClassInfo;
import org.pitest.classinfo.Repository;
import org.pitest.classinfo.TestToClassMapper;
import org.pitest.functional.F;
import org.pitest.functional.FCollection;
import org.pitest.functional.Option;
import org.pitest.testapi.TestClassIdentifier;
/**
* Provides access to code and tests on the classpath
*/
public class CodeSource implements ClassInfoSource {
private final ProjectClassPaths classPath;
private final Repository classRepository;
private final TestClassIdentifier testIdentifier;
public CodeSource(final ProjectClassPaths classPath,
final TestClassIdentifier testIdentifier) {
this(classPath, new Repository(new ClassPathByteArraySource(
classPath.getClassPath())), testIdentifier);
}
CodeSource(final ProjectClassPaths classPath,
final Repository classRepository, final TestClassIdentifier testIdentifier) {
this.classPath = classPath;
this.classRepository = classRepository;
this.testIdentifier = testIdentifier;
}
public Collection<ClassInfo> getCode() {
return FCollection.flatMap(this.classPath.code(), nameToClassInfo())
.filter(not(isWithinATestClass()));
}
public Set<ClassName> getCodeUnderTestNames() {
final Set<ClassName> codeClasses = new HashSet<ClassName>();
FCollection.mapTo(getCode(), ClassInfo.toClassName(), codeClasses);
return codeClasses;
}
@SuppressWarnings("unchecked")
public List<ClassInfo> getTests() {
return flatMap(this.classPath.test(), nameToClassInfo()).filter(
and(isWithinATestClass(), isIncludedClass(),
not(ClassInfo.matchIfAbstract())));
}
public ClassPath getClassPath() {
return this.classPath.getClassPath();
}
public ProjectClassPaths getProjectPaths() {
return this.classPath;
}
public Option<ClassName> findTestee(final String className) {
final TestToClassMapper mapper = new TestToClassMapper(this.classRepository);
return mapper.findTestee(className);
}
public Collection<ClassInfo> getClassInfo(final Collection<ClassName> classes) {
return FCollection.flatMap(classes, nameToClassInfo());
}
// not used but keep to allow plugins to query bytecode
public Option<byte[]> fetchClassBytes(final ClassName clazz) {
return this.classRepository.querySource(clazz);
}
@Override
public Option<ClassInfo> fetchClass(final ClassName clazz) {
return this.classRepository.fetchClass(clazz);
}
private F<ClassName, Option<ClassInfo>> nameToClassInfo() {
return new NameToClassInfo(this.classRepository);
}
private F<ClassInfo, Boolean> isWithinATestClass() {
return new F<ClassInfo, Boolean>() {
@Override
public Boolean apply(final ClassInfo a) {
return CodeSource.this.testIdentifier.isATestClass(a);
}
};
}
private F<ClassInfo, Boolean> isIncludedClass() {
return new F<ClassInfo, Boolean>() {
@Override
public Boolean apply(final ClassInfo a) {
return CodeSource.this.testIdentifier.isIncluded(a);
}
};
}
}