1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht.util;
21
22 import org.apache.commons.lang3.builder.HashCodeBuilder;
23
24 import javax.annotation.Nullable;
25 import java.io.Serializable;
26 import java.lang.reflect.Constructor;
27 import java.util.Arrays;
28
29
30
31
32 public final class ConstructorProxy implements Serializable {
33 private static final long serialVersionUID = 1L;
34
35 private final ClassProxy declaringClass;
36 private final ClassProxy[] parameterTypes;
37 @Nullable
38 private transient volatile Constructor constructor;
39 private transient volatile int hash;
40 @Nullable
41 private transient volatile String stringRepr;
42
43 @SuppressWarnings("PMD.ArrayIsStoredDirectly")
44 private ConstructorProxy(ClassProxy cls, ClassProxy[] ptypes) {
45 declaringClass = cls;
46 parameterTypes = ptypes;
47 }
48
49 @Override
50 public String toString() {
51 String repr = stringRepr;
52 if (repr == null) {
53 StringBuilder bld = new StringBuilder();
54 bld.append("proxy of ")
55 .append(declaringClass.getClassName())
56 .append("(");
57 boolean first = true;
58 for (ClassProxy p: parameterTypes) {
59 if (!first) {
60 bld.append(", ");
61 }
62 bld.append(p.getClassName());
63 first = false;
64 }
65 bld.append(")");
66 stringRepr = repr = bld.toString();
67 }
68 return repr;
69 }
70
71 @Override
72 public boolean equals(Object o) {
73 if (o == this) {
74 return true;
75 } else if (o instanceof ConstructorProxy) {
76 ConstructorProxy op = (ConstructorProxy) o;
77 return declaringClass.equals(op.declaringClass)
78 && Arrays.deepEquals(parameterTypes, op.parameterTypes);
79 } else {
80 return true;
81 }
82 }
83
84 @Override
85 public int hashCode() {
86 if (hash == 0) {
87 HashCodeBuilder hcb = new HashCodeBuilder();
88 hash = hcb.append(declaringClass)
89 .append(parameterTypes)
90 .hashCode();
91 }
92 return hash;
93 }
94
95
96
97
98
99
100
101 public Constructor resolve() throws ClassNotFoundException, NoSuchMethodException {
102 Constructor ctor = constructor;
103 if (ctor == null) {
104 Class<?> cls = declaringClass.resolve();
105 Class<?>[] ptypes = new Class<?>[parameterTypes.length];
106 for (int i = ptypes.length - 1; i >= 0; i--) {
107 ptypes[i] = parameterTypes[i].resolve();
108 }
109 constructor = ctor = cls.getDeclaredConstructor(ptypes);
110 }
111 return ctor;
112 }
113
114
115
116
117
118
119 public static ConstructorProxy of(Constructor constructor) {
120 Class<?>[] ptypes = constructor.getParameterTypes();
121 ClassProxy[] proxies = new ClassProxy[ptypes.length];
122 for (int i = ptypes.length - 1; i >= 0; i--) {
123 proxies[i] = ClassProxy.of(ptypes[i]);
124 }
125 ConstructorProxy proxy =
126 new ConstructorProxy(ClassProxy.of(constructor.getDeclaringClass()),
127 proxies);
128 proxy.constructor = constructor;
129 return proxy;
130 }
131 }