forked from apache/ignite
/
BinaryFieldImpl.java
319 lines (232 loc) · 8.54 KB
/
BinaryFieldImpl.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
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
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.binary;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;
import java.util.UUID;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.binary.BinaryType;
import org.apache.ignite.internal.binary.streams.BinaryByteBufferInputStream;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.binary.BinaryField;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.nonNull;
/**
* Implementation of binary field descriptor.
*/
public class BinaryFieldImpl implements BinaryFieldEx {
/** Binary context that created this field. */
private final BinaryContext ctx;
/** Type ID. */
private final int typeId;
/** Well-known object schemas. */
@GridToStringExclude
private final BinarySchemaRegistry schemas;
/** Field name. */
private final String fieldName;
/** Pre-calculated field ID. */
private final int fieldId;
/**
* Constructor.
*
* @param ctx Binary context.
* @param typeId Type ID.
* @param schemas Schemas.
* @param fieldName Field name.
* @param fieldId Field ID.
*/
public BinaryFieldImpl(
BinaryContext ctx,
int typeId,
BinarySchemaRegistry schemas,
String fieldName,
int fieldId
) {
assert ctx != null;
assert typeId != 0;
assert schemas != null;
assert fieldId != 0;
this.ctx = ctx;
this.typeId = typeId;
this.schemas = schemas;
this.fieldName = fieldName;
this.fieldId = fieldId;
}
/** {@inheritDoc} */
@Override public String name() {
return fieldName;
}
/**
* @return Field ID.
*/
public int fieldId() {
return fieldId;
}
/** {@inheritDoc} */
@Override public boolean exists(BinaryObject obj) {
BinaryObjectExImpl obj0 = (BinaryObjectExImpl)obj;
return fieldOrder(obj0) != BinarySchema.ORDER_NOT_FOUND;
}
/** {@inheritDoc} */
@Override public <T> T value(BinaryObject obj) {
BinaryObjectExImpl obj0 = (BinaryObjectExImpl)obj;
int order = fieldOrder(obj0);
return order != BinarySchema.ORDER_NOT_FOUND ? (T)obj0.fieldByOrder(order) : null;
}
/** {@inheritDoc} */
@Override public int typeId() {
return typeId;
}
/** {@inheritDoc} */
@Override public boolean writeField(BinaryObject obj, ByteBuffer buf) {
BinaryObjectExImpl obj0 = (BinaryObjectExImpl)obj;
int order = fieldOrder(obj0);
return obj0.writeFieldByOrder(order, buf);
}
/** {@inheritDoc} */
@Override public <F> F readField(ByteBuffer buf) {
ByteOrder oldOrder = buf.order();
try {
buf.order(ByteOrder.LITTLE_ENDIAN);
int pos = buf.position();
byte hdr = buf.get();
Object val;
switch (hdr) {
case GridBinaryMarshaller.INT:
val = buf.getInt();
break;
case GridBinaryMarshaller.LONG:
val = buf.getLong();
break;
case GridBinaryMarshaller.BOOLEAN:
val = buf.get() != 0;
break;
case GridBinaryMarshaller.SHORT:
val = buf.getShort();
break;
case GridBinaryMarshaller.BYTE:
val = buf.get();
break;
case GridBinaryMarshaller.CHAR:
val = buf.getChar();
break;
case GridBinaryMarshaller.FLOAT:
val = buf.getFloat();
break;
case GridBinaryMarshaller.DOUBLE:
val = buf.getDouble();
break;
case GridBinaryMarshaller.STRING: {
int dataLen = buf.getInt();
byte[] data = new byte[dataLen];
buf.get(data);
val = new String(data, 0, dataLen, UTF_8);
break;
}
case GridBinaryMarshaller.DATE: {
long time = buf.getLong();
val = new Date(time);
break;
}
case GridBinaryMarshaller.TIMESTAMP: {
long time = buf.getLong();
int nanos = buf.getInt();
Timestamp ts = new Timestamp(time);
ts.setNanos(ts.getNanos() + nanos);
val = ts;
break;
}
case GridBinaryMarshaller.TIME: {
long time = buf.getLong();
val = new Time(time);
break;
}
case GridBinaryMarshaller.UUID: {
long most = buf.getLong();
long least = buf.getLong();
val = new UUID(most, least);
break;
}
case GridBinaryMarshaller.DECIMAL: {
int scale = buf.getInt();
int dataLen = buf.getInt();
byte[] data = new byte[dataLen];
buf.get(data);
boolean negative = data[0] < 0;
if (negative)
data[0] &= 0x7F;
BigInteger intVal = new BigInteger(data);
if (negative)
intVal = intVal.negate();
val = new BigDecimal(intVal, scale);
break;
}
case GridBinaryMarshaller.NULL:
val = null;
break;
default:
// Restore buffer position.
buf.position(pos);
val = BinaryUtils.unmarshal(BinaryByteBufferInputStream.create(buf), ctx, null);
break;
}
return (F)val;
}
finally {
buf.order(oldOrder);
}
}
/**
* Get relative field offset.
*
* @param obj Object.
* @return Field offset.
*/
public int fieldOrder(BinaryObjectExImpl obj) {
if (typeId != obj.typeId()) {
BinaryType expType = ctx.metadata(typeId);
BinaryType actualType = obj.type();
throw new BinaryObjectException("Failed to get field because type ID of passed object differs" +
" from type ID this " + BinaryField.class.getSimpleName() + " belongs to [expected=[typeId=" + typeId +
", typeName=" + (nonNull(expType) ? expType.typeName() : null) + "], actual=[typeId=" +
actualType.typeId() + ", typeName=" + actualType.typeName() + "], fieldId=" + fieldId +
", fieldName=" + fieldName + ", fieldType=" +
(nonNull(expType) ? expType.fieldTypeName(fieldName) : null) + ']');
}
int schemaId = obj.schemaId();
if (schemaId == 0)
return BinarySchema.ORDER_NOT_FOUND;
BinarySchema schema = schemas.schema(schemaId);
if (schema == null) {
schema = obj.createSchema();
schemas.addSchema(schemaId, schema);
}
assert schema != null;
return schema.order(fieldId);
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(BinaryFieldImpl.class, this);
}
}