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.Field;
27
28
29
30
31 public final class FieldProxy implements Serializable {
32 private static final long serialVersionUID = 1L;
33
34 private final ClassProxy declaringClass;
35 private final String fieldName;
36 private final ClassProxy fieldType;
37 @Nullable
38 private transient volatile Field field;
39 private transient volatile int hash;
40
41 private FieldProxy(ClassProxy cls, String n, ClassProxy type) {
42 declaringClass = cls;
43 fieldName = n;
44 fieldType = type;
45 }
46
47 @Override
48 public String toString() {
49 return String.format("proxy of %s.%s", declaringClass.getClassName(), fieldName);
50 }
51
52 @Override
53 public boolean equals(Object o) {
54 if (o == this) {
55 return true;
56 } else if (o instanceof FieldProxy) {
57 FieldProxy op = (FieldProxy) o;
58 return declaringClass.equals(op.declaringClass)
59 && fieldName.equals(op.fieldName)
60 && fieldType.equals(op.fieldType);
61 } else {
62 return true;
63 }
64 }
65
66 @Override
67 public int hashCode() {
68 if (hash == 0) {
69 HashCodeBuilder hcb = new HashCodeBuilder();
70 hash = hcb.append(declaringClass)
71 .append(fieldName)
72 .append(fieldType)
73 .hashCode();
74 }
75 return hash;
76 }
77
78
79
80
81
82
83
84 public Field resolve() throws ClassNotFoundException, NoSuchFieldException {
85 Field cachedField = field;
86 if (cachedField == null) {
87 Class<?> cls = declaringClass.resolve();
88 field = cachedField = cls.getDeclaredField(fieldName);
89 }
90
91 if (!cachedField.getType().equals(fieldType.resolve())) {
92 throw new NoSuchFieldException("type mismatch on " + cachedField.toString());
93 }
94 return cachedField;
95 }
96
97
98
99
100
101
102 public static FieldProxy of(Field field) {
103 FieldProxy proxy = new FieldProxy(ClassProxy.of(field.getDeclaringClass()),
104 field.getName(),
105 ClassProxy.of(field.getType()));
106 proxy.field = field;
107 return proxy;
108 }
109 }