-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathResultSetImpl.java
More file actions
323 lines (272 loc) · 11.2 KB
/
ResultSetImpl.java
File metadata and controls
323 lines (272 loc) · 11.2 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
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
package com.redislabs.redisgraph.impl.resultset;
import com.redislabs.redisgraph.Header;
import com.redislabs.redisgraph.Record;
import com.redislabs.redisgraph.RedisGraph;
import com.redislabs.redisgraph.ResultSet;
import com.redislabs.redisgraph.Statistics;
import com.redislabs.redisgraph.exceptions.JRedisGraphRunTimeException;
import com.redislabs.redisgraph.graph_entities.*;
import com.redislabs.redisgraph.impl.graph_cache.GraphCache;
import redis.clients.jedis.util.SafeEncoder;
import redis.clients.jedis.exceptions.JedisDataException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
public class ResultSetImpl implements ResultSet {
private final Header header;
private final Statistics statistics;
private final List<Record> results ;
private int position = 0;
private final RedisGraph redisGraph;
private final GraphCache cache;
/**
* @param rawResponse the raw representation of response is at most 3 lists of objects.
* The last list is the statistics list.
* @param redisGraph the graph connection
* @param cache the graph local cache
*/
public ResultSetImpl(List<Object> rawResponse, RedisGraph redisGraph, GraphCache cache) {
this.redisGraph = redisGraph;
this.cache = cache;
// If a run-time error occurred, the last member of the rawResponse will be a JedisDataException.
if (rawResponse.get(rawResponse.size()-1) instanceof JedisDataException) {
throw new JRedisGraphRunTimeException((Throwable) rawResponse.get(rawResponse.size() - 1));
}
if (rawResponse.size() != 3) {
header = parseHeader(new ArrayList<>());
results = new ArrayList<>();
statistics = rawResponse.isEmpty() ? parseStatistics(new ArrayList<Objects>()) :
parseStatistics(rawResponse.get(rawResponse.size() - 1)) ;
} else {
header = parseHeader((List<List<Object>>) rawResponse.get(0));
results = parseResult((List<List<Object>>) rawResponse.get(1));
statistics = parseStatistics(rawResponse.get(2));
}
}
/**
*
* @param rawResultSet - raw result set representation
* @return parsed result set
*/
private List<Record> parseResult(List<List<Object>> rawResultSet) {
List<Record> results = new ArrayList<>();
if (rawResultSet == null || rawResultSet.isEmpty()) {
return results;
} else {
//go over each raw result
for (List<Object> row : rawResultSet) {
List<Object> parsedRow = new ArrayList<>(row.size());
//go over each object in the result
for (int i = 0; i < row.size(); i++) {
//get raw representation of the object
List<Object> obj = (List<Object>) row.get(i);
//get object type
Header.ResultSetColumnTypes objType = header.getSchemaTypes().get(i);
//deserialize according to type and
switch (objType) {
case COLUMN_NODE:
parsedRow.add(deserializeNode(obj));
break;
case COLUMN_RELATION:
parsedRow.add(deserializeEdge(obj));
break;
case COLUMN_SCALAR:
parsedRow.add(deserializeScalar(obj));
break;
default:
parsedRow.add(null);
break;
}
}
//create new record from deserialized objects
Record record = new RecordImpl(header.getSchemaNames(), parsedRow);
results.add(record);
}
}
return results;
}
/**
*
* @param rawStatistics raw statistics representation
* @return parsed statistics
*/
private StatisticsImpl parseStatistics(Object rawStatistics) {
return new StatisticsImpl((List<byte[]>) rawStatistics);
}
/**
*
* @param rawHeader - raw header representation
* @return parsed header
*/
private HeaderImpl parseHeader(List<List<Object>> rawHeader) {
return new HeaderImpl(rawHeader);
}
@Override
public Statistics getStatistics() {
return statistics;
}
@Override
public Header getHeader() {
return header;
}
@Override
public List<Record> getResults() {
return results;
}
/**
* @param rawNodeData - raw node object in the form of list of object
* rawNodeData.get(0) - id (long)
* rawNodeData.get(1) - a list y which contains the labels of this node. Each entry is a label id from the type of long
* rawNodeData.get(2) - a list which contains the properties of the node.
* @return Node object
*/
private Node deserializeNode(List<Object> rawNodeData) {
Node node = new Node();
deserializeGraphEntityId(node, rawNodeData.get(0));
List<Long> labelsIndices = (List<Long>) rawNodeData.get(1);
for (Long labelIndex : labelsIndices) {
String label = cache.getLabel(labelIndex.intValue(), redisGraph);
node.addLabel(label);
}
deserializeGraphEntityProperties(node, (List<List<Object>>) rawNodeData.get(2));
return node;
}
/**
* @param graphEntity graph entity
* @param rawEntityId raw representation of entity id to be set to the graph entity
*/
private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityId) {
long id = (Long) rawEntityId;
graphEntity.setId(id);
}
/**
* @param rawEdgeData - a list of objects
* rawEdgeData[0] - edge id
* rawEdgeData[1] - edge relationship type
* rawEdgeData[2] - edge source
* rawEdgeData[3] - edge destination
* rawEdgeData[4] - edge properties
* @return Edge object
*/
private Edge deserializeEdge(List<Object> rawEdgeData) {
Edge edge = new Edge();
deserializeGraphEntityId(edge, rawEdgeData.get(0));
String relationshipType = cache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue(),
redisGraph);
edge.setRelationshipType(relationshipType);
edge.setSource( (long) rawEdgeData.get(2));
edge.setDestination( (long) rawEdgeData.get(3));
deserializeGraphEntityProperties(edge, (List<List<Object>>) rawEdgeData.get(4));
return edge;
}
/**
* @param entity graph entity for adding the properties to
* @param rawProperties raw representation of a list of graph entity properties. Each entry is a list (rawProperty)
* is a raw representation of property, as follows:
* rawProperty.get(0) - property key
* rawProperty.get(1) - property type
* rawProperty.get(2) - property value
*/
private void deserializeGraphEntityProperties(GraphEntity entity, List<List<Object>> rawProperties) {
for (List<Object> rawProperty : rawProperties) {
Property<Object> property = new Property<>();
property.setName(cache.getPropertyName(((Long) rawProperty.get(0)).intValue(),
redisGraph));
//trimmed for getting to value using deserializeScalar
List<Object> propertyScalar = rawProperty.subList(1, rawProperty.size());
property.setValue(deserializeScalar(propertyScalar));
entity.addProperty(property);
}
}
/**
* @param rawScalarData - a list of object. list[0] is the scalar type, list[1] is the scalar value
* @return value of the specific scalar type
*/
private Object deserializeScalar(List<Object> rawScalarData) {
ResultSetScalarTypes type = getValueTypeFromObject(rawScalarData.get(0));
Object obj = rawScalarData.get(1);
switch (type) {
case VALUE_NULL:
return null;
case VALUE_BOOLEAN:
return Boolean.parseBoolean(SafeEncoder.encode((byte[]) obj));
case VALUE_DOUBLE:
return Double.parseDouble(SafeEncoder.encode((byte[]) obj));
case VALUE_INTEGER:
return (Long) obj;
case VALUE_STRING:
return SafeEncoder.encode((byte[]) obj);
case VALUE_ARRAY:
return deserializeArray(obj);
case VALUE_NODE:
return deserializeNode((List<Object>) obj);
case VALUE_EDGE:
return deserializeEdge((List<Object>) obj);
case VALUE_PATH:
return deserializePath(obj);
case VALUE_UNKNOWN:
default:
return obj;
}
}
private Path deserializePath(Object rawScalarData) {
List<List<Object>> array = (List<List<Object>>) rawScalarData;
List<Node> nodes = (List<Node>) deserializeScalar(array.get(0));
List<Edge> edges = (List<Edge>) deserializeScalar(array.get(1));
return new Path(nodes, edges);
}
private List<Object> deserializeArray(Object rawScalarData) {
List<List<Object>> array = (List<List<Object>>) rawScalarData;
List<Object> res = new ArrayList<>(array.size());
for (List<Object> arrayValue : array) {
res.add(deserializeScalar(arrayValue));
}
return res;
}
/**
* Auxiliary function to retrieve scalar types
*
* @param rawScalarType
* @return scalar type
*/
private ResultSetScalarTypes getValueTypeFromObject(Object rawScalarType) {
return ResultSetScalarTypes.getValue(((Long) rawScalarType).intValue());
}
@Override
public boolean hasNext() {
return position < results.size();
}
@Override
public Record next() {
if (!hasNext())
throw new NoSuchElementException();
return results.get(position++);
}
@Override
public int size() {
return results.size();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ResultSetImpl)) return false;
ResultSetImpl resultSet = (ResultSetImpl) o;
return Objects.equals(getHeader(), resultSet.getHeader()) &&
Objects.equals(getStatistics(), resultSet.getStatistics()) &&
Objects.equals(results, resultSet.results);
}
@Override
public int hashCode() {
return Objects.hash(getHeader(), getStatistics(), results);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ResultSetImpl{");
sb.append("header=").append(header);
sb.append(", statistics=").append(statistics);
sb.append(", results=").append(results);
sb.append('}');
return sb.toString();
}
}