Skip to content

Commit 1756317

Browse files
committed
Use Jackson nodes to map the data to object
1 parent 01c0946 commit 1756317

5 files changed

Lines changed: 139 additions & 95 deletions

File tree

src/main/java/com/maxmind/maxminddb/Decoder.java

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,18 @@
55
import java.nio.ByteBuffer;
66
import java.nio.channels.FileChannel;
77
import java.nio.charset.Charset;
8-
import java.util.Arrays;
9-
import java.util.HashMap;
10-
import java.util.Map;
8+
9+
import com.fasterxml.jackson.databind.JsonNode;
10+
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import com.fasterxml.jackson.databind.node.ArrayNode;
12+
import com.fasterxml.jackson.databind.node.BigIntegerNode;
13+
import com.fasterxml.jackson.databind.node.BinaryNode;
14+
import com.fasterxml.jackson.databind.node.BooleanNode;
15+
import com.fasterxml.jackson.databind.node.DoubleNode;
16+
import com.fasterxml.jackson.databind.node.IntNode;
17+
import com.fasterxml.jackson.databind.node.LongNode;
18+
import com.fasterxml.jackson.databind.node.ObjectNode;
19+
import com.fasterxml.jackson.databind.node.TextNode;
1120

1221
public class Decoder {
1322
private final FileChannel in;
@@ -18,27 +27,30 @@ public class Decoder {
1827
boolean POINTER_TEST_HACK = false;
1928
private final long pointerBase;
2029

30+
private final ObjectMapper objectMapper;
31+
2132
class Result {
22-
private final Object obj;
23-
private long new_offset;
33+
private final JsonNode obj;
34+
private long offset;
2435
private final Type type;
2536

26-
Result(Object obj, Type t, long new_offset) {
37+
Result(JsonNode obj, Type t, long offset) {
2738
this.type = t;
2839
this.obj = obj;
29-
this.new_offset = new_offset;
40+
this.offset = offset;
41+
3042
}
3143

32-
Object getObject() {
44+
JsonNode getObject() {
3345
return this.obj;
3446
}
3547

3648
long getOffset() {
37-
return this.new_offset;
49+
return this.offset;
3850
}
3951

4052
void setOffset(long offset) {
41-
this.new_offset = offset;
53+
this.offset = offset;
4254
}
4355

4456
Type getType() {
@@ -49,6 +61,7 @@ Type getType() {
4961
public Decoder(FileChannel in, long pointerBase) {
5062
this.in = in;
5163
this.pointerBase = pointerBase;
64+
this.objectMapper = new ObjectMapper();
5265
}
5366

5467
// FIXME - Move most of this method to a switch statement
@@ -82,8 +95,7 @@ public Result decode(long offset) throws MaxMindDbException, IOException {
8295
if (this.POINTER_TEST_HACK) {
8396
return pointer;
8497
}
85-
Result result = this.decode(((Long) pointer.getObject())
86-
.longValue());
98+
Result result = this.decode((pointer.getObject().asLong()));
8799
result.setOffset(pointer.getOffset());
88100
return result;
89101
}
@@ -148,28 +160,28 @@ public Result decode(long offset) throws MaxMindDbException, IOException {
148160
long new_offset = offset + size;
149161
switch (type) {
150162
case UTF8_STRING:
151-
String s = this.decodeString(bytes);
163+
TextNode s = new TextNode(this.decodeString(bytes));
152164
return new Result(s, type, new_offset);
153165
case DOUBLE:
154-
double d = this.decodeDouble(bytes);
166+
DoubleNode d = this.decodeDouble(bytes);
155167
return new Result(d, type, new_offset);
156168
case BYTES:
157-
byte[] b = this.decodeBytes(bytes);
169+
BinaryNode b = new BinaryNode(this.decodeBytes(bytes));
158170
return new Result(b, type, new_offset);
159171
case UINT16:
160-
int i = Decoder.decodeUint16(bytes);
172+
IntNode i = Decoder.decodeUint16(bytes);
161173
return new Result(i, type, new_offset);
162174
case UINT32:
163-
long l = Decoder.decodeUint32(bytes);
175+
LongNode l = Decoder.decodeUint32(bytes);
164176
return new Result(l, type, new_offset);
165177
case INT32:
166-
int int32 = Decoder.decodeInt32(bytes);
178+
IntNode int32 = Decoder.decodeInt32(bytes);
167179
return new Result(int32, type, new_offset);
168180
case UINT64:
169-
BigInteger bi = Decoder.decodeUint64(bytes);
181+
BigIntegerNode bi = Decoder.decodeUint64(bytes);
170182
return new Result(bi, type, new_offset);
171183
case UINT128:
172-
BigInteger uint128 = Decoder.decodeUint128(bytes);
184+
BigIntegerNode uint128 = Decoder.decodeUint128(bytes);
173185
return new Result(uint128, type, new_offset);
174186
default:
175187
throw new MaxMindDbException("Unknown or unexpected type: "
@@ -216,7 +228,8 @@ private Result decodePointer(int ctrlByte, long offset) throws IOException {
216228
Log.debug("Pointer to", String.valueOf(pointer));
217229
}
218230

219-
return new Result(pointer, Type.POINTER, offset + pointerSize);
231+
return new Result(new LongNode(pointer), Type.POINTER, offset
232+
+ pointerSize);
220233
}
221234

222235
private String decodeString(byte[] bytes) {
@@ -228,32 +241,33 @@ private byte[] decodeBytes(byte[] bytes) {
228241
return bytes;
229242
}
230243

231-
static int decodeUint16(byte[] bytes) {
232-
return Decoder.decodeInt32(bytes);
244+
static IntNode decodeUint16(byte[] bytes) {
245+
return new IntNode(Util.decodeInteger(bytes));
233246
}
234247

235-
static int decodeInt32(byte[] bytes) {
236-
return Util.decodeInteger(bytes);
248+
static IntNode decodeInt32(byte[] bytes) {
249+
return new IntNode(Util.decodeInteger(bytes));
237250
}
238251

239-
static long decodeUint32(byte[] bytes) {
240-
return Util.decodeLong(bytes);
252+
static LongNode decodeUint32(byte[] bytes) {
253+
return new LongNode(Util.decodeLong(bytes));
241254
}
242255

243-
static BigInteger decodeUint64(byte[] bytes) {
244-
return new BigInteger(1, bytes);
256+
static BigIntegerNode decodeUint64(byte[] bytes) {
257+
return new BigIntegerNode(new BigInteger(1, bytes));
245258
}
246259

247-
static BigInteger decodeUint128(byte[] bytes) {
248-
return new BigInteger(1, bytes);
260+
static BigIntegerNode decodeUint128(byte[] bytes) {
261+
return new BigIntegerNode(new BigInteger(1, bytes));
249262
}
250263

251-
private double decodeDouble(byte[] bytes) {
252-
return new Double(new String(bytes, Charset.forName("US-ASCII")));
264+
private DoubleNode decodeDouble(byte[] bytes) {
265+
return new DoubleNode(new Double(new String(bytes,
266+
Charset.forName("US-ASCII"))));
253267
}
254268

255269
private Result decodeBoolean(long size, long offset) {
256-
boolean b = size == 0 ? false : true;
270+
BooleanNode b = size == 0 ? BooleanNode.FALSE : BooleanNode.TRUE;
257271

258272
return new Result(b, Type.BOOLEAN, offset);
259273
}
@@ -264,20 +278,20 @@ private Result decodeArray(long size, long offset)
264278
Log.debug("Array size", size);
265279
}
266280

267-
Object[] array = new Object[(int) size];
281+
ArrayNode array = this.objectMapper.createArrayNode();
268282

269-
for (int i = 0; i < array.length; i++) {
283+
for (int i = 0; i < size; i++) {
270284
Result r = this.decode(offset);
271285
offset = r.getOffset();
272286

273287
if (this.DEBUG) {
274288
Log.debug("Value " + i, r.getObject().toString());
275289
}
276-
array[i] = r.getObject();
290+
array.add(r.getObject());
277291
}
278292

279293
if (this.DEBUG) {
280-
Log.debug("Decoded array", Arrays.toString(array));
294+
Log.debug("Decoded array", array.toString());
281295
}
282296

283297
return new Result(array, Type.ARRAY, offset);
@@ -289,19 +303,19 @@ private Result decodeMap(long size, long offset) throws MaxMindDbException,
289303
Log.debug("Map size", size);
290304
}
291305

292-
Map<String, Object> map = new HashMap<String, Object>();
306+
ObjectNode map = this.objectMapper.createObjectNode();
293307

294308
for (int i = 0; i < size; i++) {
295309
Result keyResult = this.decode(offset);
296-
String key = (String) keyResult.getObject();
310+
String key = keyResult.getObject().asText();
297311
offset = keyResult.getOffset();
298312

299313
Result valueResult = this.decode(offset);
300-
Object value = valueResult.getObject();
314+
JsonNode value = valueResult.getObject();
301315
offset = valueResult.getOffset();
302316

303317
if (this.DEBUG) {
304-
Log.debug("Key " + i, key);
318+
Log.debug("Key " + i, key.toString());
305319
Log.debug("Value " + i, value.toString());
306320
}
307321
map.put(key, value);

src/main/java/com/maxmind/maxminddb/Metadata.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,37 @@
11
package com.maxmind.maxminddb;
22

33
import java.math.BigInteger;
4-
import java.util.Arrays;
5-
import java.util.Map;
4+
5+
import com.fasterxml.jackson.databind.JsonNode;
66

77
// XXX - if we make this public, add getters
88
class Metadata {
99
Integer binaryFormatMajorVersion;
1010
Integer binaryFormatMinorVersion;
1111
BigInteger buildEpoch;
1212
String databaseType;
13-
Map<String, Object> description;
13+
JsonNode description;
1414
Integer ipVersion;
1515
Long nodeCount;
1616
Long recordSize;
1717
int nodeByteSize;
1818
long searchTreeSize;
19-
String[] languages;
19+
JsonNode languages;
2020

2121
// XXX - think about how I want to construct this. Maybe look at how JSON
2222
// parsers deal with types
23-
public Metadata(Map<String, Object> metadata) {
24-
this.binaryFormatMajorVersion = (Integer) metadata
25-
.get("binary_format_major_version");
26-
this.binaryFormatMinorVersion = (Integer) metadata
27-
.get("binary_format_minor_version");
28-
this.buildEpoch = (BigInteger) metadata.get("build_epoch");
29-
this.databaseType = (String) metadata.get("database_type");
30-
Object[] langs = (Object[]) metadata.get("languages");
31-
this.languages = Arrays.copyOf(langs, langs.length, String[].class);
32-
this.description = (Map<String, Object>) metadata.get("description");
33-
this.ipVersion = (Integer) metadata.get("ip_version");
34-
this.nodeCount = (Long) metadata.get("node_count");
35-
this.recordSize = (Long) metadata.get("record_size");
23+
public Metadata(JsonNode metadata) {
24+
this.binaryFormatMajorVersion = metadata.get(
25+
"binary_format_major_version").asInt();
26+
this.binaryFormatMinorVersion = metadata.get(
27+
"binary_format_minor_version").asInt();
28+
this.buildEpoch = metadata.get("build_epoch").bigIntegerValue();
29+
this.databaseType = metadata.get("database_type").asText();
30+
this.languages = metadata.get("languages");
31+
this.description = metadata.get("description");
32+
this.ipVersion = metadata.get("ip_version").asInt();
33+
this.nodeCount = metadata.get("node_count").asLong();
34+
this.recordSize = metadata.get("record_size").asLong();
3635
this.nodeByteSize = (int) (this.recordSize / 4);
3736
this.searchTreeSize = this.nodeCount * this.nodeByteSize;
3837

src/main/java/com/maxmind/maxminddb/Reader.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import java.nio.ByteBuffer;
88
import java.nio.channels.FileChannel;
99
import java.util.Arrays;
10-
import java.util.Map;
1110

1211
public class Reader {
1312
private static int DATA_SECTION_SEPARATOR_SIZE = 16;
@@ -56,8 +55,7 @@ public Reader(File database) throws MaxMindDbException, IOException {
5655

5756
Decoder metadataDecoder = new Decoder(this.fc, 0);
5857

59-
this.metadata = new Metadata((Map<String, Object>) metadataDecoder
60-
.decode(start).getObject());
58+
this.metadata = new Metadata(metadataDecoder.decode(start).getObject());
6159

6260
this.decoder = new Decoder(this.fc, this.metadata.searchTreeSize
6361
+ DATA_SECTION_SEPARATOR_SIZE);

0 commit comments

Comments
 (0)