1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht.reflect.internal;
21
22 import org.grouplens.grapht.reflect.InjectionPoint;
23 import org.grouplens.grapht.util.ConstructorProxy;
24 import org.grouplens.grapht.util.Preconditions;
25 import org.grouplens.grapht.util.Types;
26
27 import javax.annotation.Nonnull;
28 import javax.annotation.Nullable;
29 import java.io.InvalidObjectException;
30 import java.io.ObjectInputStream;
31 import java.io.Serializable;
32 import java.lang.annotation.Annotation;
33 import java.lang.reflect.Constructor;
34 import java.lang.reflect.Type;
35 import java.util.Collection;
36
37
38
39
40
41
42
43 public class ConstructorParameterInjectionPoint implements InjectionPoint, Serializable {
44 private static final long serialVersionUID = -1L;
45
46
47 private final transient Constructor<?> constructor;
48 private final transient int paramIndex;
49 private final transient AnnotationHelper annotations;
50
51
52
53
54
55
56
57
58
59
60
61 public ConstructorParameterInjectionPoint(@Nonnull Constructor<?> ctor, int pIndex) {
62 Preconditions.notNull("constructor", ctor);
63 Preconditions.inRange(pIndex, 0, ctor.getParameterTypes().length);
64
65 constructor = ctor;
66 paramIndex = pIndex;
67 annotations = new AnnotationHelper(ctor.getParameterAnnotations()[pIndex]);
68 }
69
70
71
72
73 @Override @Nonnull
74 public Constructor<?> getMember() {
75 return constructor;
76 }
77
78
79
80
81
82 public int getParameterIndex() {
83 return paramIndex;
84 }
85
86 @Override
87 public boolean isNullable() {
88 return Types.hasNullableAnnotation(constructor.getParameterAnnotations()[paramIndex]);
89 }
90
91 @Override
92 public Type getType() {
93 return Types.box(constructor.getGenericParameterTypes()[paramIndex]);
94 }
95
96 @Override
97 public Class<?> getErasedType() {
98 return Types.box(constructor.getParameterTypes()[paramIndex]);
99 }
100
101 @Nullable
102 @Override
103 public Annotation getQualifier() {
104 return annotations.getQualifier();
105 }
106
107 @Nullable
108 @Override
109 public <A extends Annotation> A getAttribute(Class<A> atype) {
110 return annotations.getAttribute(atype);
111 }
112
113 @Nonnull
114 @Override
115 public Collection<Annotation> getAttributes() {
116 return annotations.getAttributes();
117 }
118
119 @Override
120 public boolean equals(Object o) {
121 if (!(o instanceof ConstructorParameterInjectionPoint)) {
122 return false;
123 }
124 ConstructorParameterInjectionPoint cp = (ConstructorParameterInjectionPoint) o;
125 return cp.constructor.equals(constructor) && cp.paramIndex == paramIndex;
126 }
127
128 @Override
129 public int hashCode() {
130 return constructor.hashCode() ^ (37 * 17 * paramIndex);
131 }
132
133 @Override
134 public String toString() {
135 StringBuilder sb = new StringBuilder();
136
137 sb.append("constructor ")
138 .append(constructor.getName())
139 .append("(");
140 if (paramIndex > 0) {
141 sb.append("..., ");
142 }
143 if (annotations.getQualifier() != null) {
144 sb.append(annotations.getQualifier())
145 .append(" ");
146 }
147 sb.append(constructor.getParameterTypes()[paramIndex].getName())
148 .append(" arg")
149 .append(paramIndex);
150 if (paramIndex < constructor.getParameterTypes().length) {
151 sb.append(", ...");
152 }
153 sb.append(")");
154
155 return sb.toString();
156 }
157
158 private Object writeReplace() {
159 return new SerialProxy(constructor, paramIndex);
160 }
161
162 private void readObject(ObjectInputStream stream) throws InvalidObjectException {
163 throw new InvalidObjectException("Serialization proxy required");
164 }
165
166 private static class SerialProxy implements Serializable {
167 private static final long serialVersionUID = 1L;
168
169 private final ConstructorProxy constructor;
170 private final int index;
171
172 public SerialProxy(Constructor ctor, int idx) {
173 constructor = ConstructorProxy.of(ctor);
174 index = idx;
175 }
176
177 private Object readResolve() throws InvalidObjectException {
178 try {
179 return new ConstructorParameterInjectionPoint(constructor.resolve(), index);
180 } catch (ClassNotFoundException e) {
181 InvalidObjectException ex =
182 new InvalidObjectException("no class for " + constructor.toString());
183 ex.initCause(e);
184 throw ex;
185 } catch (NoSuchMethodException e) {
186 InvalidObjectException ex =
187 new InvalidObjectException("cannot resolve " + constructor.toString());
188 ex.initCause(e);
189 throw ex;
190 }
191 }
192 }
193 }