play.classloading.ApplicationClasses Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
RePlay is a fork of the Play1 framework, created by Codeborne.
package play.classloading;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BinaryOperator;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.apache.commons.lang3.StringUtils.replace;
public class ApplicationClasses {
/**
* Cache of all compiled classes
*/
private Map classes;
private Map allClassesByNormalizedName;
private final Map, Object> assignableClasses = new HashMap<>(100);
private Map classes() {
if (classes == null) {
List> applicationClasses = new JavaClassesScanner().allClassesInProject();
classes = toMapIgnoringDuplicates(applicationClasses);
}
return classes;
}
private Map allClassesByNormalizedName() {
if (allClassesByNormalizedName == null) {
allClassesByNormalizedName = unmodifiableMap(normalizeByName(classes()));
}
return allClassesByNormalizedName;
}
private Map toMapIgnoringDuplicates(List> applicationClasses) {
BinaryOperator ignoreDuplicates = (old, _new) -> old;
return applicationClasses.stream().collect(toMap(cl -> cl.getName(), cl -> cl, ignoreDuplicates));
}
private Map normalizeByName(Map applicationClasses) {
Map byNormalizedName = new HashMap<>(applicationClasses.size());
for (Class clazz : applicationClasses.values()) {
byNormalizedName.put(clazz.getName().toLowerCase(), clazz);
if (clazz.getName().contains("$")) {
byNormalizedName.put(replace(clazz.getName().toLowerCase(), "$", "."), clazz);
}
}
return byNormalizedName;
}
public List> getAssignableClasses(Class aClass) {
if (aClass == null) {
return emptyList();
}
List> result = (List>) assignableClasses.get(aClass);
if (result == null) {
result = findAssignableClasses(aClass);
assignableClasses.put(aClass, result);
}
return result;
}
private List> findAssignableClasses(Class clazz) {
return unmodifiableList(classes().values().stream()
.filter(applicationClass -> isSubclass(applicationClass, clazz))
.map(applicationClass -> (Class) applicationClass)
.collect(toList()));
}
private boolean isSubclass(Class> subClass, Class> superClass) {
return superClass.isAssignableFrom(subClass) && !subClass.equals(superClass);
}
public Class> getClassIgnoreCase(String name) {
String nameLowerCased = name.toLowerCase();
return allClassesByNormalizedName().get(nameLowerCased);
}
/**
* Retrieve all application classes with a specific annotation.
*
* @param clazz
* The annotation class.
* @return A list of application classes.
*/
public List getAnnotatedClasses(Class extends Annotation> clazz) {
return classes().values().stream().filter(applicationClass ->
applicationClass != null && applicationClass.isAnnotationPresent(clazz))
.collect(toList());
}
@Override
public String toString() {
return String.format("%s classes", classes().size());
}
}