Skip to content

Commit bff8f3f

Browse files
Add StringMapConverter using FlexBuffers, test it.
1 parent ccee90c commit bff8f3f

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package io.objectbox.converter;
2+
3+
import io.objectbox.flatbuffers.ArrayReadWriteBuf;
4+
import io.objectbox.flatbuffers.FlexBuffers;
5+
import io.objectbox.flatbuffers.FlexBuffersBuilder;
6+
7+
import java.nio.ByteBuffer;
8+
import java.util.HashMap;
9+
import java.util.Map;
10+
import java.util.Map.Entry;
11+
12+
/**
13+
* Converts a String map entity property to a byte array database value using FlexBuffers.
14+
*/
15+
public class StringMapConverter implements PropertyConverter<Map<String, String>, byte[]> {
16+
@Override
17+
public byte[] convertToDatabaseValue(Map<String, String> map) {
18+
if (map == null) return null;
19+
20+
FlexBuffersBuilder builder = new FlexBuffersBuilder(
21+
new ArrayReadWriteBuf(),
22+
FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS
23+
);
24+
int mapStart = builder.startMap();
25+
26+
for (Entry<String, String> entry : map.entrySet()) {
27+
if (entry.getKey() == null || entry.getValue() == null) {
28+
throw new IllegalArgumentException("Map keys or values must not be null");
29+
}
30+
builder.putString(entry.getKey(), entry.getValue());
31+
}
32+
33+
builder.endMap(null, mapStart);
34+
ByteBuffer buffer = builder.finish();
35+
36+
byte[] out = new byte[buffer.limit()];
37+
buffer.get(out);
38+
return out;
39+
}
40+
41+
@Override
42+
public Map<String, String> convertToEntityProperty(byte[] databaseValue) {
43+
if (databaseValue == null) return null;
44+
45+
FlexBuffers.Map map = FlexBuffers.getRoot(new ArrayReadWriteBuf(databaseValue, databaseValue.length)).asMap();
46+
47+
// As recommended by docs, iterate keys and values vectors in parallel to avoid binary search of key vector.
48+
int entryCount = map.size();
49+
FlexBuffers.KeyVector keys = map.keys();
50+
FlexBuffers.Vector values = map.values();
51+
Map<String, String> resultMap = new HashMap<>(entryCount);
52+
for (int i = 0; i < entryCount; i++) {
53+
String key = keys.get(i).toString();
54+
String value = values.get(i).asString();
55+
resultMap.put(key, value);
56+
}
57+
58+
return resultMap;
59+
}
60+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.objectbox.converter;
2+
3+
import org.junit.Test;
4+
5+
import java.util.HashMap;
6+
import java.util.Map;
7+
8+
import javax.annotation.Nullable;
9+
10+
11+
import static org.junit.Assert.assertEquals;
12+
13+
public class StringMapConverterTest {
14+
15+
@Test
16+
public void works() {
17+
convertAndBackThenAssert(null);
18+
19+
convertAndBackThenAssert(new HashMap<>());
20+
21+
Map<String, String> mapWithValues = new HashMap<>();
22+
mapWithValues.put("Hello", "Grüezi");
23+
mapWithValues.put("💡", "Idea");
24+
convertAndBackThenAssert(mapWithValues);
25+
}
26+
27+
private void convertAndBackThenAssert(@Nullable Map<String, String> expected) {
28+
StringMapConverter converter = new StringMapConverter();
29+
byte[] converted = converter.convertToDatabaseValue(expected);
30+
31+
Map<String, String> actual = converter.convertToEntityProperty(converted);
32+
assertEquals(expected, actual);
33+
}
34+
}

0 commit comments

Comments
 (0)