package reflection.api; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; public class ReflectionInvestigator implements Investigator { private Object subjectInstance; private Class classInfo; public ReflectionInvestigator() {} @Override public void load(Object anInstanceOfSomething) { subjectInstance = anInstanceOfSomething; classInfo = subjectInstance.getClass(); } @Override public int getTotalNumberOfMethods() { return classInfo.getDeclaredMethods().length; } @Override public int getTotalNumberOfConstructors() { return classInfo.getConstructors().length; } @Override public int getTotalNumberOfFields() { return classInfo.getFields().length; } @Override public Set getAllImplementedInterfaces() { return Stream.of(classInfo.getInterfaces()) .map(info -> info.getName()) .collect(Collectors.toSet()); } @Override public int getCountOfConstantFields() { return Stream.of(classInfo.getFields()) .filter(f -> Modifier.isFinal(f.getModifiers())) .toArray() .length; } @Override public int getCountOfStaticMethods() { return Stream.of(classInfo.getMethods()) .filter(m -> Modifier.isStatic(m.getModifiers())) .toArray() .length; } @Override public boolean isExtending() { return classInfo.getSuperclass() != Object.class; } @Override public String getParentClassSimpleName() { return classInfo.getSuperclass().getSimpleName(); } @Override public boolean isParentClassAbstract() { return Modifier.isAbstract(classInfo.getSuperclass().getModifiers()); } @Override public Set getNamesOfAllFieldsIncludingInheritanceChain() { return Stream.of(classInfo.getFields()).map(f -> f.getName()).collect(Collectors.toSet()); } @Override public int invokeMethodThatReturnsInt(String methodName, Object... args) { try { return (int) classInfo.getMethod(methodName).invoke(subjectInstance, args); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { return 0; } } @Override public Object createInstance(int numberOfArgs, Object... args) { var ctors = classInfo.getDeclaredConstructors(); for (var ctor : ctors) { if (ctor.getGenericParameterTypes().length == numberOfArgs) { try { return ctor.newInstance(args); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { break; } } } return null; } @Override public Object elevateMethodAndInvoke(String name, Class[] parametersTypes, Object... args) { try { var method = classInfo.getMethod(name); method.setAccessible(true); return method.invoke(subjectInstance, args); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { return null; } } @Override public String getInheritanceChain(String delimiter) { var sb = new StringBuilder(); var cursor = classInfo; while (cursor != null) { sb.append(cursor.getName() + " -> "); cursor = cursor.getSuperclass(); } return sb.toString(); } }