Skip to content

Commit ce883f4

Browse files
author
Stephen Cobbe
committed
Added Map type.
1 parent 95f0db6 commit ce883f4

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

generator/java.stoneg.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
is_bytes_type,
3232
is_composite_type,
3333
is_list_type,
34+
is_map_type,
3435
is_nullable_type,
3536
is_numeric_type,
3637
is_primitive_type,
@@ -294,12 +295,14 @@ def add_subtype(data_type):
294295
return result
295296

296297

297-
def get_underlying_type(data_type, allow_lists=True):
298+
def get_underlying_type(data_type, allow_data_structures=True):
298299
assert isinstance(data_type, DataType), repr(data_type)
299300

300301
while True:
301-
if allow_lists and is_list_type(data_type):
302+
if allow_data_structures and is_list_type(data_type):
302303
data_type = data_type.data_type
304+
elif allow_data_structures and is_map_type(data_type):
305+
data_type = data_type.value_data_type
303306
elif is_nullable_type(data_type):
304307
data_type = data_type.data_type
305308
else:
@@ -744,6 +747,7 @@ def add_imports_for_route(self, route):
744747
'com.dropbox.core.v2.DbxDownloadStyleBuilder',
745748
'java.util.Collections',
746749
'java.util.List',
750+
'java.util.Map',
747751
)
748752

749753
def add_imports_for_route_builder(self, route):
@@ -834,6 +838,8 @@ def _add_imports_for_data_type(self, data_type):
834838

835839
if is_list_type(data_type) or is_nullable_type(data_type):
836840
self._add_imports_for_data_type(data_type.data_type)
841+
elif is_map_type(data_type):
842+
self._add_imports_for_data_type(data_type.value_data_type)
837843
elif is_timestamp_type(data_type):
838844
self.add_imports('com.dropbox.core.util.LangUtil')
839845

@@ -1088,6 +1094,9 @@ def java_serializer(self, data_type):
10881094
# TODO: also support passing collapsed to list serializer
10891095
return self.fmt('%s.list(%s)',
10901096
serializers_class, self.java_serializer(data_type.data_type))
1097+
elif is_map_type(data_type):
1098+
return self.fmt('%s.map(%s)',
1099+
serializers_class, self.java_serializer(data_type.value_data_type))
10911100
else:
10921101
return self.fmt('%s.%s()', serializers_class, camelcase(data_type.name))
10931102

@@ -1350,7 +1359,7 @@ def add_req(precondition, failure_reason):
13501359
if val is not None:
13511360
add_req(precondition % val, failure_reason % val)
13521361

1353-
if is_list_type(data_type):
1362+
if is_list_type(data_type) or is_map_type(data_type):
13541363
add_req('not contain a {@code null} item', 'contains a {@code null} item')
13551364
elif is_string_type(data_type) and data_type.pattern is not None:
13561365
pattern = sanitize_pattern(data_type.pattern)
@@ -1714,7 +1723,7 @@ def get_spec_filenames(self, element):
17141723
@staticmethod
17151724
def requires_validation(data_type):
17161725
assert isinstance(data_type, DataType), repr(data_type)
1717-
if is_list_type(data_type):
1726+
if is_list_type(data_type) or is_map_type(data_type):
17181727
return True
17191728
elif is_numeric_type(data_type):
17201729
return any(r is not None for r in (
@@ -1947,6 +1956,9 @@ def java_class(self, stone_elem, boxed=False, generics=True):
19471956
generic_classes = []
19481957
if generics and is_list_type(data_type):
19491958
generic_classes = [self.java_class(data_type.data_type, boxed=True, generics=True)]
1959+
elif generics and is_map_type(data_type):
1960+
generic_classes = [self.java_class(data_type.key_data_type, boxed=True), self.java_class(
1961+
data_type.value_data_type, boxed=True, generics=True)]
19501962

19511963
type_map = _TYPE_MAP_BOXED if boxed else _TYPE_MAP_UNBOXED
19521964
return JavaClass(type_map[data_type.name], generics=generic_classes)
@@ -4077,6 +4089,14 @@ def generate_data_type_validation(self, data_type, value_name, description=None,
40774089
w.out('throw new IllegalArgumentException("An item in list%s is null");', description)
40784090
self.generate_data_type_validation(data_type.data_type, xn, 'an item in list%s' % description, level=level+1)
40794091

4092+
elif is_map_type(data_type):
4093+
xn = 'x' if level == 0 else 'x%d' % level
4094+
map_item_type = j.java_class(data_type.value_data_type, boxed=True, generics=True)
4095+
with w.block('for (%s %s : %s.values())', map_item_type, xn, value_name):
4096+
with w.block('if (%s == null)', xn):
4097+
w.out('throw new IllegalArgumentException("An item in map%s is null");', description)
4098+
self.generate_data_type_validation(data_type.value_data_type, xn, 'an item in map%s' % description, level=level+1)
4099+
40804100
elif is_numeric_type(data_type):
40814101
if data_type.min_value is not None:
40824102
java_value = w.java_value(data_type, data_type.min_value)
@@ -4328,6 +4348,7 @@ def generate_struct_equals(self, data_type):
43284348
'Timestamp': 'java.util.Date',
43294349
'Void': 'void',
43304350
'List': 'java.util.List',
4351+
'Map': 'java.util.Map',
43314352
}
43324353

43334354

@@ -4344,6 +4365,7 @@ def generate_struct_equals(self, data_type):
43444365
'Timestamp': 'java.util.Date',
43454366
'Void': 'Void',
43464367
'List': 'java.util.List',
4368+
'Map': 'java.util.Map',
43474369
}
43484370

43494371
_CATCH_ALL_DOC = """

src/main/java/com/dropbox/core/stone/StoneSerializers.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import java.text.ParseException;
55
import java.util.ArrayList;
66
import java.util.Date;
7+
import java.util.HashMap;
78
import java.util.List;
9+
import java.util.Map;
810

911
import com.fasterxml.jackson.core.JsonGenerationException;
1012
import com.fasterxml.jackson.core.JsonGenerator;
@@ -70,6 +72,9 @@ public static <T> StoneSerializer<List<T>> list(StoneSerializer<T> underlying) {
7072
return new ListSerializer<T>(underlying);
7173
}
7274

75+
public static <T> StoneSerializer<Map<String, T>> map(StoneSerializer<T> underlying) {
76+
return new MapSerializer<T>(underlying);
77+
}
7378

7479
private static final class LongSerializer extends StoneSerializer<Long> {
7580
public static final LongSerializer INSTANCE = new LongSerializer();
@@ -319,4 +324,33 @@ public List<T> deserialize(JsonParser p) throws IOException, JsonParseException
319324
return list;
320325
}
321326
}
327+
328+
private static final class MapSerializer<T> extends StoneSerializer<Map<String, T>> {
329+
private final StoneSerializer<T> underlying;
330+
331+
public MapSerializer(StoneSerializer<T> underlying) {
332+
this.underlying = underlying;
333+
}
334+
335+
@Override
336+
public void serialize(Map<String, T> value, JsonGenerator g) throws IOException, JsonGenerationException {
337+
g.writeString(value.toString());
338+
}
339+
340+
@Override
341+
public Map<String, T> deserialize(JsonParser p) throws IOException, JsonParseException {
342+
Map<String, T> map = new HashMap<String, T>();
343+
344+
expectStartObject(p);
345+
while (p.getCurrentToken() == JsonToken.FIELD_NAME) {
346+
String key = p.getCurrentName();
347+
p.nextToken();
348+
T val = underlying.deserialize(p);
349+
map.put(key, val);
350+
}
351+
expectEndObject(p);
352+
353+
return map;
354+
}
355+
}
322356
}

0 commit comments

Comments
 (0)