summaryrefslogtreecommitdiffstats
path: root/ex1/src/main/java/reflection/api/ReflectionInvestigator.java
blob: 160102ac8950b9531c0e7df7978275cc45d600ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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<String> 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<String> 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();
    sb.append(classInfo.getName());
    var cursor = classInfo;
    while (cursor != null) {
      sb.append(cursor.getName() + " -> ");
      cursor = cursor.getSuperclass();
    }
    return sb.toString();
  }
}