31
31
is_bytes_type ,
32
32
is_composite_type ,
33
33
is_list_type ,
34
+ is_map_type ,
34
35
is_nullable_type ,
35
36
is_numeric_type ,
36
37
is_primitive_type ,
@@ -294,12 +295,14 @@ def add_subtype(data_type):
294
295
return result
295
296
296
297
297
- def get_underlying_type (data_type ,allow_lists = True ):
298
+ def get_underlying_type (data_type ,allow_data_structures = True ):
298
299
assert isinstance (data_type ,DataType ),repr (data_type )
299
300
300
301
while True :
301
- if allow_lists and is_list_type (data_type ):
302
+ if allow_data_structures and is_list_type (data_type ):
302
303
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
303
306
elif is_nullable_type (data_type ):
304
307
data_type = data_type .data_type
305
308
else :
@@ -744,6 +747,7 @@ def add_imports_for_route(self, route):
744
747
'com.dropbox.core.v2.DbxDownloadStyleBuilder' ,
745
748
'java.util.Collections' ,
746
749
'java.util.List' ,
750
+ 'java.util.Map' ,
747
751
)
748
752
749
753
def add_imports_for_route_builder (self ,route ):
@@ -834,6 +838,8 @@ def _add_imports_for_data_type(self, data_type):
834
838
835
839
if is_list_type (data_type )or is_nullable_type (data_type ):
836
840
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 )
837
843
elif is_timestamp_type (data_type ):
838
844
self .add_imports ('com.dropbox.core.util.LangUtil' )
839
845
@@ -1088,6 +1094,9 @@ def java_serializer(self, data_type):
1088
1094
# TODO: also support passing collapsed to list serializer
1089
1095
return self .fmt ('%s.list(%s)' ,
1090
1096
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 ))
1091
1100
else :
1092
1101
return self .fmt ('%s.%s()' ,serializers_class ,camelcase (data_type .name ))
1093
1102
@@ -1350,7 +1359,7 @@ def add_req(precondition, failure_reason):
1350
1359
if val is not None :
1351
1360
add_req (precondition % val ,failure_reason % val )
1352
1361
1353
- if is_list_type (data_type ):
1362
+ if is_list_type (data_type )or is_map_type ( data_type ) :
1354
1363
add_req ('not contain a {@code null} item' ,'contains a {@code null} item' )
1355
1364
elif is_string_type (data_type )and data_type .pattern is not None :
1356
1365
pattern = sanitize_pattern (data_type .pattern )
@@ -1714,7 +1723,7 @@ def get_spec_filenames(self, element):
1714
1723
@staticmethod
1715
1724
def requires_validation (data_type ):
1716
1725
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 ) :
1718
1727
return True
1719
1728
elif is_numeric_type (data_type ):
1720
1729
return any (r is not None for r in (
@@ -1947,6 +1956,9 @@ def java_class(self, stone_elem, boxed=False, generics=True):
1947
1956
generic_classes = []
1948
1957
if generics and is_list_type (data_type ):
1949
1958
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 )]
1950
1962
1951
1963
type_map = _TYPE_MAP_BOXED if boxed else _TYPE_MAP_UNBOXED
1952
1964
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,
4077
4089
w .out ('throw new IllegalArgumentException("An item in list%s is null");' ,description )
4078
4090
self .generate_data_type_validation (data_type .data_type ,xn ,'an item in list%s' % description ,level = level + 1 )
4079
4091
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
+
4080
4100
elif is_numeric_type (data_type ):
4081
4101
if data_type .min_value is not None :
4082
4102
java_value = w .java_value (data_type ,data_type .min_value )
@@ -4328,6 +4348,7 @@ def generate_struct_equals(self, data_type):
4328
4348
'Timestamp' :'java.util.Date' ,
4329
4349
'Void' :'void' ,
4330
4350
'List' :'java.util.List' ,
4351
+ 'Map' :'java.util.Map' ,
4331
4352
}
4332
4353
4333
4354
@@ -4344,6 +4365,7 @@ def generate_struct_equals(self, data_type):
4344
4365
'Timestamp' :'java.util.Date' ,
4345
4366
'Void' :'Void' ,
4346
4367
'List' :'java.util.List' ,
4368
+ 'Map' :'java.util.Map' ,
4347
4369
}
4348
4370
4349
4371
_CATCH_ALL_DOC = """