Commit 256f3537 authored by Gábor Szalai's avatar Gábor Szalai
Browse files

OpenApi.py: multiple file at once


Signed-off-by: Gábor Szalai's avatarGabor Szalai <gabor.szalai@ericsson.com>
parent ef965cf1
......@@ -4,6 +4,24 @@ import os
import pprint
import re
# Data structure used during conversion
# modules - map of the module_name:module_data
# module_data - map of the detailed data of one module:
# * import: list of the impoted modules
# * functions: list of the encoder functions to be generated
# * type_tree: list of the type definitions
# * extra_lists: list of the extra record of's and encoder functions
# Global variable, they always the reference to the actually processed module.
# modules
# module_data
# type_tree
# module_name
# ident_level
# ident_c
# saved_stdout
# Reserved word list. Used to sanitaze the type and field names.
ttcn_keywords=[ # Reserved words
"action","activate","address","alive","all","alt","altstep","and","and4b","any","anytype",
......@@ -128,28 +146,29 @@ def get_module(ref):
# If the generation of encoder function or array definiton is missed these functions
# should be updated to find the missing references.
#
def process_path(data,module_data):
def process_path(data):
for m in data:
#print("process_path ", m, " " , data[m])
if m == "parameters":
for p in data[m]:
process_used_schem_name(p,module_data)
process_used_schem_name(p)
else:
if "parameters" in data[m]:
for p in data[m]["parameters"]:
process_used_schem_name(p,module_data)
process_used_schem_name(p)
if "requestBody" in data[m]:
process_used_schem_name(data[m]["requestBody"],module_data)
process_used_schem_name(data[m]["requestBody"])
if "responses" in data[m]:
for r in data[m]["responses"]:
process_used_schem_name(data[m]["responses"][r],module_data)
process_used_schem_name(data[m]["responses"][r])
if "callbacks" in data[m]:
for c in data[m]["callbacks"]:
for p in data[m]["callbacks"][c]:
process_path(data[m]["callbacks"][c][p],module_data)
process_path(data[m]["callbacks"][c][p])
def process_schema(schema,module_data):
def process_schema(schema):
global module_data
if "$ref" in schema:
refmodule,refstr=get_module(schema["$ref"])
if refmodule!= '':
......@@ -161,29 +180,31 @@ def process_schema(schema,module_data):
if schema["type"] == "array" :
if "$ref" in schema["items"] :
refmodule,refstr=get_module(schema["items"]["$ref"]) # This direct code generation should be moved out from here.
print("// " + refmodule + " type record of " + refstr + " " +refstr + "_list")
print(f'// external function f_enc_{refstr}_list(in {refstr}_list pdu) return octetstring ')
print('// with { extension "prototype(convert) encode(JSON)" }')
print("")
print(f'// external function f_dec_{refstr}_list(in octetstring stream, out {refstr}_list pdu) return integer ')
print('// with { extension "prototype(backtrack) decode(JSON)" }')
print("")
if not (refmodule,refstr) in module_data['extra_lists']:
module_data['extra_lists'].append((refmodule,refstr))
# print("// " + refmodule + " type record of " + refstr + " " +refstr + "_list")
# print(f'// external function f_enc_{refstr}_list(in {refstr}_list pdu) return octetstring ')
# print('// with { extension "prototype(convert) encode(JSON)" }')
# print("")
# print(f'// external function f_dec_{refstr}_list(in octetstring stream, out {refstr}_list pdu) return integer ')
# print('// with { extension "prototype(backtrack) decode(JSON)" }')
# print("")
if schema["type"] == "object" :
if "properties" in schema:
if "jsonData" in schema["properties"]:
process_schema(schema["properties"]["jsonData"],module_data)
process_schema(schema["properties"]["jsonData"])
def process_used_schem_name(data,module_data):
def process_used_schem_name(data):
#print("process_used_schem_name", data)
if "content" in data:
for ct in data["content"]:
#print("ct ", ct)
if "schema" in data["content"][ct]:
#print("schema ", data["content"][ct]["schema"])
process_schema(data["content"][ct]["schema"],module_data)
process_schema(data["content"][ct]["schema"])
if "schema" in data:
process_schema(data["schema"],module_data)
process_schema(data["schema"])
# Processes one schema definition and build the data structure needed for code generation.
# The processed data is appended to the type_tree list.
......@@ -468,112 +489,167 @@ def add_bool(self, node):
Constructor.add_constructor(u'tag:yaml.org,2002:bool', add_bool)
f=open(sys.argv[1])
module_name = os.path.splitext(os.path.basename(sys.argv[1]))[0]
# Processes the content of one yaml file
# Fills the module_data.
# The code is not generated here.
# doc - loaded yaml file
# The global variable should be set
def process_one_module(doc):
print("Processing " + module_name)
if "components" in doc:
if "schemas" in doc["components"]:
schemas=doc["components"]["schemas"]
for name in schemas:
# The type name suffix 'Rm' is used for a nullable type alias
# Generate the nullable structure but use the reference to the original type
if (name[-2:] == "Rm" ) and (name[:-2] in schemas ):
type_tree.append({'fields': [{'name': 'null_val',
'nullable': False,
'type': 'JSON_generic_val.JSON_null_val'},
{'name': 'val',
'nullable': False,
'type': clean_name(name[:-2],True),
'variant': []}],
'name': clean_name(name,True),
'nullable': True,
'type': 'union',
'variant': ['JSON: as value']})
addImport("JSON_Generic")
elif name == "NullValue": # Special type, used for nullable enums
type_tree.append({'type': 'JSON_generic_val.JSON_null_val','name':'NullValue','nullable': True})
else:
# Normal type schema processing.
data=schemas[name]
type_builder(clean_name(name,True),data,type_tree)
if "responses" in doc["components"]:
#print(doc["components"]["responses"])
for r in doc["components"]["responses"]:
#print(r)
process_used_schem_name(doc["components"]["responses"][r])
if 'paths' in doc:
for p in doc["paths"]:
#print(p)
process_path(doc["paths"][p])
print("Processing completed")
# Generates the code of one module
# The global variable should be set
def generate_one_module():
global ident_level
print("Generating code for " + module_name)
fout = open(module_name + ".ttcn",'wt')
sys.stdout = fout
sys.stdout = open(module_name + ".ttcn",'wt')
print("module " + module_name + " {")
print("")
for i in module_data['extra_lists']:
refmodule, refstr = i
print("// " + refmodule + " type record of " + refstr + " " +refstr + "_list")
print(f'// external function f_enc_{refstr}_list(in {refstr}_list pdu) return octetstring ')
print('// with { extension "prototype(convert) encode(JSON)" }')
print("")
print(f'// external function f_dec_{refstr}_list(in octetstring stream, out {refstr}_list pdu) return integer ')
print('// with { extension "prototype(backtrack) decode(JSON)" }')
print("")
for i in module_data['import']:
print(f' import from {i} all')
print("")
print("module " + module_name + " {")
print("")
for fs in module_data['functions']:
f=clean_name(fs,True,".")
if "." in f:
pre="// "
else:
pre=""
print(pre+f'external function f_enc_{f}(in {f} pdu) return octetstring ')
print(pre+'with { extension "prototype(convert) encode(JSON)" }')
print("")
print(pre+f'external function f_dec_{f}(in octetstring stream, out {f} pdu) return integer ')
print(pre+'with { extension "prototype(backtrack) decode(JSON)" }')
print("")
print("")
#pprint.pprint(type_tree)
for t in type_tree:
print(ident_c*ident_level, "type ",end="",sep="")
# ident_level+=1
print_type(t,"", top=True)
variants=[]
gather_variants(t,"",variants)
if variants != []:
print(" with {")
ident_level+=1
for v in variants:
print(ident_c*ident_level, "variant ",end="",sep="")
if v["spec"] != "":
print("(",v["spec"],") ",end="",sep="")
print('"',v["var"],'"',sep="")
ident_level-=1
print(ident_c*ident_level, "}",sep="")
else:
print("")
# ident_level-=1
print("")
print("")
doc=yaml.load(f)
print("")
print('')
print('} with {')
print(' encode "JSON"')
print('}')
sys.stdout = saved_stdout
fout.close
print("Code generation completed")
schemas=[]
type_tree=[]
# Main code starts here:
module_data={'import' : [], "functions" : []}
buff=""
# global variables
saved_stdout = sys.stdout
module_data = {}
type_tree= []
modules = {}
ident_level=1
ident_c=" "
module_name = ""
if "components" in doc:
if "schemas" in doc["components"]:
schemas=doc["components"]["schemas"]
for name in schemas:
# The type name suffix 'Rm' is used for a nullable type alias
# Generate the nullable structure but use the reference to the original type
if (name[-2:] == "Rm" ) and (name[:-2] in schemas ):
type_tree.append({'fields': [{'name': 'null_val',
'nullable': False,
'type': 'JSON_generic_val.JSON_null_val'},
{'name': 'val',
'nullable': False,
'type': clean_name(name[:-2],True),
'variant': []}],
'name': clean_name(name,True),
'nullable': True,
'type': 'union',
'variant': ['JSON: as value']})
addImport("JSON_Generic")
elif name == "NullValue": # Special type, used for nullable enums
type_tree.append({'type': 'JSON_generic_val.JSON_null_val','name':'NullValue','nullable': True})
else:
# Normal type schema processing.
data=schemas[name]
type_builder(clean_name(name,True),data,type_tree)
if "responses" in doc["components"]:
#print(doc["components"]["responses"])
for r in doc["components"]["responses"]:
#print(r)
process_used_schem_name(doc["components"]["responses"][r],module_data)
if 'paths' in doc:
for p in doc["paths"]:
#print(p)
process_path(doc["paths"][p],module_data)
for i in module_data['import']:
print(f' import from {i} all')
print("")
for fs in module_data['functions']:
f=clean_name(fs,True,".")
if "." in f:
pre="// "
else:
pre=""
print(pre+f'external function f_enc_{f}(in {f} pdu) return octetstring ')
print(pre+'with { extension "prototype(convert) encode(JSON)" }')
print("")
print(pre+f'external function f_dec_{f}(in octetstring stream, out {f} pdu) return integer ')
print(pre+'with { extension "prototype(backtrack) decode(JSON)" }')
print("")
for filename in sys.argv[1:]:
print("")
#pprint.pprint(type_tree)
for t in type_tree:
print(ident_c*ident_level, "type ",end="",sep="")
# ident_level+=1
print_type(t,"", top=True)
variants=[]
gather_variants(t,"",variants)
if variants != []:
print(" with {")
ident_level+=1
for v in variants:
print(ident_c*ident_level, "variant ",end="",sep="")
if v["spec"] != "":
print("(",v["spec"],") ",end="",sep="")
print('"',v["var"],'"',sep="")
ident_level-=1
print(ident_c*ident_level, "}",sep="")
else:
print("")
# ident_level-=1
print("")
#print(buff)
print("")
try:
f=open(filename)
except:
print("Can't open the file: ", filename)
pprint.pprint(sys.exc_info()[1])
quit()
print("File opened: " + filename)
module_name = os.path.splitext(os.path.basename(filename))[0]
print("")
print('')
print('} with {')
print(' encode "JSON"')
print('}')
ydoc=yaml.load(f)
# Already processed modules can add functions and type to the module
if module_name not in modules:
modules[module_name]={'import' : [], "functions" : [], "type_tree": [], "extra_lists":[]}
module_data=modules[module_name]
type_tree=module_data["type_tree"]
process_one_module(ydoc)
for module_name in modules:
module_data=modules[module_name]
type_tree=module_data["type_tree"]
generate_one_module()
#pprint.pprint(type_tree)
#pprint.pprint(module_data)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment