187 lines
7.5 KiB
Python
Raw Permalink Normal View History

2021-11-18 19:27:39 +01:00
import yaml
from Cheetah.Template import Template
import glob
import argparse
import os
2021-11-19 12:39:46 +01:00
import re
import json
2021-11-18 19:27:39 +01:00
from yaml.loader import SafeLoader
from generateHelper import CsOperationNameConverter, OpenApiExtractRefType, CsTypeConverter
2021-11-18 19:27:39 +01:00
parser = argparse.ArgumentParser(description="generate.py")
2021-11-19 12:39:46 +01:00
parser.add_argument('--apiDefinitionFile', '-a',
2021-11-18 19:27:39 +01:00
help='API definition file. Default: openapi.yaml in the current folder.',
required=False,
default='./openapi.yaml')
2021-12-02 11:59:10 +01:00
parser.add_argument('--errorDefinitionFile', '-e',
help='Error definition file. Default: serviceErrorCodes.yaml in the current folder.',
required=False,
default='./serviceErrorCodes.yaml')
2021-11-18 19:27:39 +01:00
parser.add_argument('--template', '-t',
help="""Template file, templates files must be named as the final output file
with an additional .tmpl extension. Default: all template files recursively from the current folder.""",
required=False,
default="**/*.tmpl")
args = parser.parse_args()
2021-11-19 12:39:46 +01:00
with open(args.apiDefinitionFile) as apiDefinitionFile:
apiDefinition = yaml.load(apiDefinitionFile, Loader=SafeLoader)
2021-12-02 11:59:10 +01:00
with open(args.errorDefinitionFile) as errorDefinitionFile:
errorDefinition = yaml.load(errorDefinitionFile, Loader=SafeLoader)
2021-11-18 19:27:39 +01:00
2021-11-19 12:39:46 +01:00
apiDefinition["GENERATED_SQL_COMMENT"] = """
2021-11-18 19:27:39 +01:00
-- ----------------------------------------
-- THIS FILE HAS BEEN GENERATED
-- DO NOT EDIT MANUALLY
-- ----------------------------------------
"""
2021-11-19 12:39:46 +01:00
apiDefinition["GENERATED_PYTHON_COMMENT"] = """
2021-11-18 19:27:39 +01:00
# -----------------------------------------
# THIS FILE HAS BEEN GENERATED
# DO NOT EDIT MANUALLY
# -----------------------------------------
"""
2021-11-19 12:39:46 +01:00
apiDefinition["GENERATED_YAML_COMMENT"] = """
2021-11-18 19:27:39 +01:00
# -----------------------------------------
# THIS FILE HAS BEEN GENERATED
# DO NOT EDIT MANUALLY
# -----------------------------------------
"""
2021-11-19 12:39:46 +01:00
apiDefinition["GENERATED_TS_COMMENT"] = """
2021-11-18 19:27:39 +01:00
// -----------------------------------------
// THIS FILE HAS BEEN GENERATED
// DO NOT EDIT MANUALLY
// -----------------------------------------
"""
2021-11-19 12:39:46 +01:00
apiDefinition["GENERATED_CS_COMMENT"] = """
2021-11-18 19:27:39 +01:00
// -----------------------------------------
// THIS FILE HAS BEEN GENERATED
// DO NOT EDIT MANUALLY
// -----------------------------------------
"""
2021-11-26 16:36:07 +01:00
os.environ["PACKAGE_NAME"]
apiDefinition["env"] = {
"packagename": os.environ["PACKAGE_NAME"],
"routeprefix": os.environ["ROUTE_PREFIX"]
}
statementFinder = re.compile('STATEMENTBEGIN(\s+)(.+)(\s+)STATEMENTEND', flags=re.DOTALL)
statementCleaner = re.compile('\s+')
2021-11-19 12:39:46 +01:00
statementChecker = {
'get': re.compile('^select', re.IGNORECASE),
'put': re.compile('^update', re.IGNORECASE),
'delete': re.compile('^delete', re.IGNORECASE),
'post': re.compile('^insert', re.IGNORECASE)
}
databaseTagFinder = re.compile('DATABASETAGBEGIN(\s+)(\S+)(\s+)DATABASETAGEND', flags=re.DOTALL)
bindingHintFinder = re.compile('BINDINGHINTBEGIN(\s+)(\S+)(\s+)BINDINGHINTEND', flags=re.DOTALL)
2021-11-18 19:27:39 +01:00
operations = []
2021-11-19 12:39:46 +01:00
for path in apiDefinition['paths'].values():
2021-11-18 19:27:39 +01:00
for (method, operation) in path.items():
print(f"{method=}")
print(f"{CsOperationNameConverter(operation['operationId'])=}")
2021-11-19 12:39:46 +01:00
# if 200 in
2021-11-18 19:27:39 +01:00
content = operation['responses'][200]['content']['application/json']['schema']
if ('type' in content) and (content['type'] == 'array'):
isList = True
2021-11-19 12:39:46 +01:00
resultType = OpenApiExtractRefType(content['items']['$ref'])
2021-11-18 19:27:39 +01:00
else:
isList = False
2021-11-19 12:39:46 +01:00
resultType = OpenApiExtractRefType(content['$ref'])
print(f"{content=}")
print(f"{resultType=}")
2021-11-19 12:39:46 +01:00
description = None
statement = None
bindingByStringReplacement = False
2021-11-19 12:39:46 +01:00
if 'description' in operation:
description = operation['description']
print(f"{description=}")
2021-11-19 12:39:46 +01:00
statementFinderResult = statementFinder.search(description)
if statementFinderResult:
statement = statementCleaner.sub(' ', statementFinderResult.group(2))
print(f"{statement=}")
2021-11-19 12:39:46 +01:00
if not statementChecker[method].match(statement):
raise Exception(f"Invalid statement {statement} for method {method}")
else:
print("no statement")
2021-12-06 17:46:58 +01:00
databaseTagFinderResult = databaseTagFinder.search(description)
if databaseTagFinderResult:
databaseTag = databaseTagFinderResult.group(2)
print(f"{databaseTag=}")
else:
print("no databasetag")
bindingHintFinderResult = bindingHintFinder.search(description)
if bindingHintFinderResult:
bindingHint = bindingHintFinderResult.group(2)
print(f"{bindingHint=}")
bindingByStringReplacement = bindingHint == 'stringreplacement'
print(f"{bindingByStringReplacement=}")
2021-11-19 12:39:46 +01:00
bodyInputType = {}
2021-11-19 12:39:46 +01:00
if 'requestBody' in operation:
bodyInputTypeName = OpenApiExtractRefType(operation['requestBody']['content']['application/json']['schema']['$ref'])
bodyInputType = { 'apiName': bodyInputTypeName, 'csName': CsOperationNameConverter(bodyInputTypeName) }
2021-11-25 14:49:08 +01:00
paramInputTypes = []
if 'parameters' in operation:
for paramsInputType in operation['parameters']:
if paramsInputType['schema']['type'] == 'array':
paramsInputType['type'] = CsTypeConverter(paramsInputType['schema']['items']['type'])
paramsInputType['isList'] = True
else:
paramsInputType['type'] = CsTypeConverter(paramsInputType['schema']['type'])
paramsInputType['isList'] = False
del paramsInputType['schema']
2021-11-25 14:49:08 +01:00
paramsInputType['csName'] = CsOperationNameConverter(paramsInputType['name'])
paramInputTypes.append(paramsInputType)
2021-11-18 19:27:39 +01:00
operations.append({
2021-11-19 12:39:46 +01:00
'description': description,
2021-11-18 19:27:39 +01:00
'method':method,
'func':CsOperationNameConverter(operation['operationId']),
'isList': isList,
2021-11-19 12:39:46 +01:00
'resultType': { 'apiName': resultType, 'csName': CsOperationNameConverter(resultType) } if resultType else {},
'allSelector': operation['operationId'].endswith('all'),
'byIdSelector': operation['operationId'].endswith('byid'),
'statement': statement,
2021-12-06 17:46:58 +01:00
'databaseTag': databaseTag,
'bodyInputType': bodyInputType,
'paramInputTypes': paramInputTypes,
'bindingByStringReplacement': bindingByStringReplacement
2021-11-19 12:39:46 +01:00
})
print(f"{operations=}")
2021-11-19 12:39:46 +01:00
apiDefinition["operations"] = operations
types = {}
for (typeName, typeDefinition) in apiDefinition['components']['schemas'].items():
print(f"{typeName=}")
2021-11-19 12:39:46 +01:00
typeProperties = []
for itemName in typeDefinition['properties']:
print(f"{itemName=}")
2021-11-19 12:39:46 +01:00
typeProperties.append({
'sqlName': itemName,
'csName': itemName.capitalize()
2021-11-18 19:27:39 +01:00
})
2021-11-19 12:39:46 +01:00
types[typeName] = {
'sqlName': typeName,
'csName': typeName.capitalize(),
'properties': typeProperties
}
print(f"{types=}")
2021-11-19 12:39:46 +01:00
apiDefinition['types'] = types
2021-11-18 19:27:39 +01:00
print(json.dumps(apiDefinition, indent=4))
2021-12-02 11:59:10 +01:00
print(json.dumps(errorDefinition, indent=4))
2021-11-18 19:27:39 +01:00
for f in glob.glob(args.template, recursive=True):
print(f"process {f}")
2021-12-02 11:59:10 +01:00
tmpl = Template(file=f, searchList=[apiDefinition, errorDefinition])
2021-11-18 19:27:39 +01:00
with open(f[:-5], 'w') as outFile:
outFile.write(str(tmpl))