/
ProtobufPropertyHelper.java
205 lines (185 loc) · 6.77 KB
/
ProtobufPropertyHelper.java
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package org.infinispan.objectfilter.impl.hql;
import org.hibernate.hql.ast.spi.EntityNamesResolver;
import org.infinispan.objectfilter.impl.logging.Log;
import org.infinispan.protostream.SerializationContext;
import org.infinispan.protostream.descriptors.Descriptor;
import org.infinispan.protostream.descriptors.EnumDescriptor;
import org.infinispan.protostream.descriptors.EnumValueDescriptor;
import org.infinispan.protostream.descriptors.FieldDescriptor;
import org.infinispan.protostream.descriptors.JavaType;
import org.jboss.logging.Logger;
import java.util.ArrayList;
import java.util.List;
/**
* @author anistor@redhat.com
* @since 7.0
*/
public final class ProtobufPropertyHelper extends ObjectPropertyHelper<Descriptor> {
private static final Log log = Logger.getMessageLogger(Log.class, ProtobufPropertyHelper.class.getName());
private final SerializationContext serializationContext;
public ProtobufPropertyHelper(EntityNamesResolver entityNamesResolver, SerializationContext serializationContext) {
super(entityNamesResolver);
this.serializationContext = serializationContext;
}
@Override
public Descriptor getEntityMetadata(String targetTypeName) {
return serializationContext.getMessageDescriptor(targetTypeName);
}
@Override
public List<?> mapPropertyNamePathToFieldIdPath(Descriptor messageDescriptor, String[] propertyPath) {
List<Integer> translatedPath = new ArrayList<>(propertyPath.length);
Descriptor md = messageDescriptor;
for (String prop : propertyPath) {
FieldDescriptor fd = md.findFieldByName(prop);
translatedPath.add(fd.getNumber());
if (fd.getJavaType() == JavaType.MESSAGE) {
md = fd.getMessageType();
} else {
md = null; // iteration is expected to stop here
}
}
return translatedPath;
}
@Override
public Class<?> getPrimitivePropertyType(String entityType, String[] propertyPath) {
FieldDescriptor field = getField(entityType, propertyPath);
switch (field.getJavaType()) {
case INT:
return Integer.class;
case LONG:
return Long.class;
case FLOAT:
return Float.class;
case DOUBLE:
return Double.class;
case BOOLEAN:
return Boolean.class;
case STRING:
return String.class;
case BYTE_STRING:
return byte[].class;
case ENUM:
return Integer.class;
}
return null;
}
/**
* @param entityType
* @param propertyPath
* @return the field descriptor or null if not found
* @throws IllegalStateException if the entity type is unknown
*/
private FieldDescriptor getField(String entityType, String[] propertyPath) {
Descriptor messageDescriptor;
try {
messageDescriptor = serializationContext.getMessageDescriptor(entityType);
} catch (Exception e) {
throw new IllegalStateException("Unknown entity name " + entityType);
}
int i = 0;
for (String p : propertyPath) {
FieldDescriptor field = messageDescriptor.findFieldByName(p);
if (field == null || ++i == propertyPath.length) {
return field;
}
if (field.getJavaType() == JavaType.MESSAGE) {
messageDescriptor = field.getMessageType();
} else {
break;
}
}
return null;
}
@Override
public boolean hasProperty(String entityType, String[] propertyPath) {
Descriptor messageDescriptor;
try {
messageDescriptor = serializationContext.getMessageDescriptor(entityType);
} catch (Exception e) {
throw new IllegalStateException("Unknown entity name " + entityType);
}
int i = 0;
for (String p : propertyPath) {
i++;
FieldDescriptor field = messageDescriptor.findFieldByName(p);
if (field == null) {
return false;
}
if (field.getJavaType() == JavaType.MESSAGE) {
messageDescriptor = field.getMessageType();
} else {
break;
}
}
return i == propertyPath.length;
}
@Override
public boolean hasEmbeddedProperty(String entityType, String[] propertyPath) {
Descriptor messageDescriptor;
try {
messageDescriptor = serializationContext.getMessageDescriptor(entityType);
} catch (Exception e) {
throw new IllegalStateException("Unknown entity name " + entityType);
}
for (String p : propertyPath) {
FieldDescriptor field = messageDescriptor.findFieldByName(p);
if (field == null) {
return false;
}
if (field.getJavaType() == JavaType.MESSAGE) {
messageDescriptor = field.getMessageType();
} else {
return false;
}
}
return true;
}
@Override
public boolean isRepeatedProperty(String entityType, String[] propertyPath) {
Descriptor messageDescriptor;
try {
messageDescriptor = serializationContext.getMessageDescriptor(entityType);
} catch (Exception e) {
throw new IllegalStateException("Unknown entity name " + entityType);
}
for (String p : propertyPath) {
FieldDescriptor field = messageDescriptor.findFieldByName(p);
if (field == null) {
break;
}
if (field.isRepeated()) {
return true;
}
if (field.getJavaType() != JavaType.MESSAGE) {
break;
}
messageDescriptor = field.getMessageType();
}
return false;
}
@Override
public Object convertToPropertyType(String entityType, List<String> propertyPath, String value) {
FieldDescriptor field = getField(entityType, propertyPath.toArray(new String[propertyPath.size()]));
//todo [anistor] this is just for remote query because enums are handled as integers for historical reasons.
if (field.getJavaType() == JavaType.BOOLEAN) {
try {
return Integer.parseInt(value) != 0;
} catch (NumberFormatException e) {
return super.convertToPropertyType(entityType, propertyPath, value);
}
} else if (field.getJavaType() == JavaType.ENUM) {
EnumDescriptor enumType = field.getEnumType();
EnumValueDescriptor enumValue;
try {
enumValue = enumType.findValueByNumber(Integer.parseInt(value));
} catch (NumberFormatException e) {
enumValue = enumType.findValueByName(value);
}
if (enumValue == null) {
throw log.getInvalidEnumLiteralException(value, enumType.getFullName());
}
return enumValue.getNumber();
}
return super.convertToPropertyType(entityType, propertyPath, value);
}
}