diff --git a/103280/TS_103_280.schema.json b/103280/TS_103_280.schema.json index aa63f8183191f19ae988167b37237d9a34ca1a3f..405f1aad5ead2ead35d088635cd3d8d575662693 100644 --- a/103280/TS_103_280.schema.json +++ b/103280/TS_103_280.schema.json @@ -279,7 +279,8 @@ "required": [ "etsi280:start", "etsi280:end" - ] + ], + "additionalProperties": false }, "UDPPortRange": { "type": "object", @@ -294,7 +295,8 @@ "required": [ "etsi280:start", "etsi280:end" - ] + ], + "additionalProperties": false }, "Port": { "oneOf": [ @@ -361,7 +363,8 @@ "required": [ "etsi280:address", "etsi280:port" - ] + ], + "additionalProperties": false }, "IPAddressPortRange": { "type": "object", @@ -376,7 +379,8 @@ "required": [ "etsi280:address", "etsi280:portRange" - ] + ], + "additionalProperties": false }, "WGS84CoordinateDecimal": { "type": "object", @@ -391,7 +395,8 @@ "required": [ "etsi280:latitude", "etsi280:longitude" - ] + ], + "additionalProperties": false }, "WGS84CoordinateAngular": { "type": "object", @@ -406,7 +411,8 @@ "required": [ "etsi280:latitude", "etsi280:longitude" - ] + ], + "additionalProperties": false } } } diff --git a/utils/translate/ChoiceMapping.py b/utils/translate/ChoiceMapping.py index b477a3360e0a6a7b891f5854951eb4f37dce4b39..052bd45e3ceb987f0ebe18556f6afad2df9c6789 100644 --- a/utils/translate/ChoiceMapping.py +++ b/utils/translate/ChoiceMapping.py @@ -44,4 +44,6 @@ class ChoiceMapping(ComplexTypeMapping): if (content.model != 'choice'): log.debug("Not a choice, giving up") return None - return { 'oneOf' : ChoiceMapping.process_choice(content, xst.namespaces[''], self.ns_to_id_map)} + return { + 'oneOf' : ChoiceMapping.process_choice(content, xst.namespaces[''], self.ns_to_id_map) + } diff --git a/utils/translate/SequenceMapping.py b/utils/translate/SequenceMapping.py index 341ac51469a8b0f9ad5fd0c66ae9c45aac93f277..9932c4667e9178a387f7b0ccddc3fe29cd942d6e 100644 --- a/utils/translate/SequenceMapping.py +++ b/utils/translate/SequenceMapping.py @@ -26,7 +26,8 @@ class SequenceMapping(ComplexTypeMapping): mapped_type = { 'type' : 'object', 'properties' : {}, - 'required' : [] + 'required' : [], + 'additionalProperties' : False, } # Not going to try and do all of this automatically for now @@ -75,11 +76,17 @@ class SequenceMapping(ComplexTypeMapping): else: raise Exception(f"Unknown element type {c}") if (inner_choice): + for inner_thing in inner_choice: + inner_thing.pop('additionalProperties', None) + mapped_type.pop('additionalProperties', None) return { 'allOf' : [ mapped_type, - {'oneOf' : inner_choice} - ] + { + 'oneOf' : inner_choice + } + ], + 'unevaluatedProperties' : False } else: return mapped_type diff --git a/utils/translate_spec.py b/utils/translate_spec.py index e950b4ae12cbd09066593774f8b560a2805cce4d..f2008595106b4edd7c606e6af9a5250c4bc7f15b 100644 --- a/utils/translate_spec.py +++ b/utils/translate_spec.py @@ -83,9 +83,10 @@ if __name__ == "__main__": continue js = translate_schema(schema_tuple[1], ns_map, schema_locations) - # TODO - Special case, get rid of XML Dsig signature and insert JSON signature + # Special case, get rid of XML Dsig signature and insert JSON signature, and XML attrib pattern property if schema_tuple[0] == 'http://uri.etsi.org/03120/common/2019/10/Core': logging.info ("Modifying signature elements") + js['$defs']['HI1Message']['patternProperties'] = { "^@" : { "type" : "string"}} js['$defs']['HI1Message']['properties'].pop('xmldsig:Signature') js['$defs']['HI1Message']['properties']['Signature'] = json_signature_struct diff --git a/utils/xml_to_json.py b/utils/xml_to_json.py index 86f8ad7ec394603683a3ce6fccd7a4e16aad330d..3b8e6a107cfa254c3a6a9dbe6933dab076dd1544 100644 --- a/utils/xml_to_json.py +++ b/utils/xml_to_json.py @@ -80,6 +80,7 @@ coerce_to_int = [ 'task:Order', 'ErrorCode', 'Generation', + 'tp:Order' ] coerce_to_bool = [ @@ -115,6 +116,20 @@ def postprocessor (path, key, value): return key, {} return key, value +def recursively_fix_tpcriteria (d: dict): + if isinstance(d, dict): + if ("tp:Criteria" in d + and isinstance(d["tp:Criteria"], list) + and len(d["tp:Criteria"]) == 1 + ): + d["tp:Criteria"] = d["tp:Criteria"][0] + else: + for k,v in d.items(): + recursively_fix_tpcriteria(v) + elif isinstance(d, list): + for d_item in d: + recursively_fix_tpcriteria(d_item) + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbose', action='count', help='Verbose logging (can be specified multiple times)') @@ -141,4 +156,10 @@ if __name__ == "__main__": postprocessor=postprocessor )['HI1Message'] - print(json.dumps(d, indent=2)) + # HACK + # Needed because TrafficPolicy.xsd has two nested fields both called tp:Criteria + # but only the outer one needs to be coerced into a list + recursively_fix_tpcriteria(d) + out_str = json.dumps(d, indent=2) + + print(out_str)