forked from json-iterator/java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBinding.java
More file actions
130 lines (117 loc) · 4.68 KB
/
Binding.java
File metadata and controls
130 lines (117 loc) · 4.68 KB
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
129
130
package com.jsoniter.spi;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.Map;
public class Binding {
// input
public final Class clazz;
public final TypeLiteral clazzTypeLiteral;
public Annotation[] annotations;
public Field field; // obj.XXX
public Method method; // obj.setXXX() or obj.getXXX()
public boolean valueCanReuse;
// input/output
public String name;
public Type valueType;
public TypeLiteral valueTypeLiteral;
// output
public String[] fromNames; // for decoder
public String[] toNames; // for encoder
public Decoder decoder;
public Encoder encoder;
public boolean asMissingWhenNotPresent;
public boolean asExtraWhenPresent;
public boolean isNullable = true;
public boolean isCollectionValueNullable = true;
public OmitValue defaultValueToOmit;
// then this property will not be unknown
// but we do not want to bind it anywhere
public boolean shouldSkip;
// attachment, used when generating code or reflection
public int idx;
public long mask;
public Binding(ClassInfo classInfo, Map<String, Type> lookup, Type valueType) {
this.clazz = classInfo.clazz;
this.clazzTypeLiteral = TypeLiteral.create(classInfo.type);
this.valueType = substituteTypeVariables(lookup, valueType);
this.valueTypeLiteral = TypeLiteral.create(this.valueType);
}
public String decoderCacheKey() {
return this.name + "@" + this.clazzTypeLiteral.getDecoderCacheKey();
}
public String encoderCacheKey() {
return this.name + "@" + this.clazzTypeLiteral.getEncoderCacheKey();
}
private static Type substituteTypeVariables(Map<String, Type> lookup, Type type) {
if (type instanceof TypeVariable) {
return translateTypeVariable(lookup, (TypeVariable) type);
}
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
Type[] args = pType.getActualTypeArguments();
for (int i = 0; i < args.length; i++) {
args[i] = substituteTypeVariables(lookup, args[i]);
}
return GenericsHelper.createParameterizedType(args, pType.getOwnerType(), pType.getRawType());
}
if (type instanceof GenericArrayType) {
GenericArrayType gaType = (GenericArrayType) type;
Type componentType = substituteTypeVariables(lookup, gaType.getGenericComponentType());
return GenericsHelper.createGenericArrayType(componentType);
}
return type;
}
private static Type translateTypeVariable(Map<String, Type> lookup, TypeVariable var) {
GenericDeclaration declaredBy = var.getGenericDeclaration();
if (!(declaredBy instanceof Class)) {
// if the <T> is not defined by class, there is no way to get the actual type
return Object.class;
}
Class clazz = (Class) declaredBy;
Type actualType = lookup.get(var.getName() + "@" + clazz.getCanonicalName());
if (actualType == null) {
// should not happen
return Object.class;
}
if (actualType instanceof TypeVariable) {
// translate to another variable, try again
return translateTypeVariable(lookup, (TypeVariable) actualType);
}
return actualType;
}
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
if (annotations == null) {
return null;
}
for (Annotation annotation : annotations) {
if (annotationClass.isAssignableFrom(annotation.getClass())) {
return (T) annotation;
}
}
return null;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Binding binding = (Binding) o;
if (clazz != null ? !clazz.equals(binding.clazz) : binding.clazz != null) return false;
if (method != null ? !method.equals(binding.method) : binding.method != null) return false;
return name != null ? name.equals(binding.name) : binding.name == null;
}
@Override
public int hashCode() {
int result = clazz != null ? clazz.hashCode() : 0;
result = 31 * result + (method != null ? method.hashCode() : 0);
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Binding{" +
"clazz=" + clazz +
", name='" + name + '\'' +
", valueType=" + valueType +
'}';
}
}