data extraction from openapi defintion
This commit is contained in:
parent
e616a7cb60
commit
590e9da904
79
generate.py
79
generate.py
@ -3,12 +3,13 @@ from Cheetah.Template import Template
|
||||
import glob
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
|
||||
from yaml.loader import SafeLoader
|
||||
from generateHelper import CsOperationNameConverter, OpenApiExtractRefType
|
||||
|
||||
parser = argparse.ArgumentParser(description="generate.py")
|
||||
parser.add_argument('--api', '-a',
|
||||
parser.add_argument('--apiDefinitionFile', '-a',
|
||||
help='API definition file. Default: openapi.yaml in the current folder.',
|
||||
required=False,
|
||||
default='./openapi.yaml')
|
||||
@ -20,35 +21,35 @@ with an additional .tmpl extension. Default: all template files recursively from
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
with open(args.api) as schemaFile:
|
||||
schema = yaml.load(schemaFile, Loader=SafeLoader)
|
||||
with open(args.apiDefinitionFile) as apiDefinitionFile:
|
||||
apiDefinition = yaml.load(apiDefinitionFile, Loader=SafeLoader)
|
||||
|
||||
|
||||
schema["GENERATED_SQL_COMMENT"] = """
|
||||
apiDefinition["GENERATED_SQL_COMMENT"] = """
|
||||
-- ----------------------------------------
|
||||
-- THIS FILE HAS BEEN GENERATED
|
||||
-- DO NOT EDIT MANUALLY
|
||||
-- ----------------------------------------
|
||||
"""
|
||||
schema["GENERATED_PYTHON_COMMENT"] = """
|
||||
apiDefinition["GENERATED_PYTHON_COMMENT"] = """
|
||||
# -----------------------------------------
|
||||
# THIS FILE HAS BEEN GENERATED
|
||||
# DO NOT EDIT MANUALLY
|
||||
# -----------------------------------------
|
||||
"""
|
||||
schema["GENERATED_YAML_COMMENT"] = """
|
||||
apiDefinition["GENERATED_YAML_COMMENT"] = """
|
||||
# -----------------------------------------
|
||||
# THIS FILE HAS BEEN GENERATED
|
||||
# DO NOT EDIT MANUALLY
|
||||
# -----------------------------------------
|
||||
"""
|
||||
schema["GENERATED_TS_COMMENT"] = """
|
||||
apiDefinition["GENERATED_TS_COMMENT"] = """
|
||||
// -----------------------------------------
|
||||
// THIS FILE HAS BEEN GENERATED
|
||||
// DO NOT EDIT MANUALLY
|
||||
// -----------------------------------------
|
||||
"""
|
||||
schema["GENERATED_CS_COMMENT"] = """
|
||||
apiDefinition["GENERATED_CS_COMMENT"] = """
|
||||
// -----------------------------------------
|
||||
// THIS FILE HAS BEEN GENERATED
|
||||
// DO NOT EDIT MANUALLY
|
||||
@ -56,34 +57,78 @@ schema["GENERATED_CS_COMMENT"] = """
|
||||
"""
|
||||
|
||||
packageName = os.environ["PACKAGE_NAME"]
|
||||
schema["env"] = { "packagename": packageName }
|
||||
apiDefinition["env"] = { "packagename": packageName }
|
||||
statementFinder = re.compile('STATEMENTBEGIN (.*) STATEMENTEND')
|
||||
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)
|
||||
}
|
||||
|
||||
operations = []
|
||||
for path in schema['paths'].values():
|
||||
for path in apiDefinition['paths'].values():
|
||||
for (method, operation) in path.items():
|
||||
#print(f"{method=}")
|
||||
#print(f"{CsOperationNameConverter(operation['operationId'])=}")
|
||||
# if 200 in
|
||||
content = operation['responses'][200]['content']['application/json']['schema']
|
||||
if ('type' in content) and (content['type'] == 'array'):
|
||||
isList = True
|
||||
typ = OpenApiExtractRefType(content['items']['$ref'])
|
||||
resultType = OpenApiExtractRefType(content['items']['$ref'])
|
||||
else:
|
||||
isList = False
|
||||
typ = OpenApiExtractRefType(content['$ref'])
|
||||
resultType = OpenApiExtractRefType(content['$ref'])
|
||||
#print(f"{content=}")
|
||||
#print(f"{typ=}")
|
||||
#print(f"{resultType=}")
|
||||
description = None
|
||||
statement = None
|
||||
if 'description' in operation:
|
||||
description = operation['description']
|
||||
statementFinderResult = statementFinder.search(description)
|
||||
if statementFinderResult:
|
||||
statement = statementFinderResult.group(1)
|
||||
if not statementChecker[method].match(statement):
|
||||
raise Exception(f"Invalid statement {statement} for method {method}")
|
||||
|
||||
inputType = None
|
||||
if 'requestBody' in operation:
|
||||
inputType = OpenApiExtractRefType(operation['requestBody']['content']['application/json']['schema']['$ref'])
|
||||
operations.append({
|
||||
'description': description,
|
||||
'method':method,
|
||||
'func':CsOperationNameConverter(operation['operationId']),
|
||||
'isList': isList,
|
||||
'type': typ
|
||||
'resultType': { 'apiName': resultType, 'csName': CsOperationNameConverter(resultType) } if resultType else {},
|
||||
'allSelector': operation['operationId'].endswith('all'),
|
||||
'byIdSelector': operation['operationId'].endswith('byid'),
|
||||
'statement': statement,
|
||||
'inputType': { 'apiName': inputType, 'csName': CsOperationNameConverter(inputType) } if inputType else {}
|
||||
})
|
||||
#print(f"{operations=}")
|
||||
schema["operations"] = operations
|
||||
print(f"{operations=}")
|
||||
apiDefinition["operations"] = operations
|
||||
|
||||
types = {}
|
||||
for (typeName, typeDefinition) in apiDefinition['components']['schemas'].items():
|
||||
#print(f"{typeName=}")
|
||||
typeProperties = []
|
||||
for itemName in typeDefinition['properties']:
|
||||
#print(f"{itemName=}")
|
||||
typeProperties.append({
|
||||
'sqlName': itemName,
|
||||
'csName': itemName.capitalize()
|
||||
})
|
||||
types[typeName] = {
|
||||
'sqlName': typeName,
|
||||
'csName': typeName.capitalize(),
|
||||
'properties': typeProperties
|
||||
}
|
||||
print(f"{types=}")
|
||||
apiDefinition['types'] = types
|
||||
|
||||
for f in glob.glob(args.template, recursive=True):
|
||||
print(f"process {f}")
|
||||
tmpl = Template(file=f, searchList=[schema])
|
||||
tmpl = Template(file=f, searchList=[apiDefinition])
|
||||
with open(f[:-5], 'w') as outFile:
|
||||
outFile.write(str(tmpl))
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
def capitalizeOnlyFirstLetter(i):
|
||||
return i[0].upper() + i[1:]
|
||||
|
||||
def JsNameConverter(i):
|
||||
return ''.join([x.capitalize() for x in i.split('_')])
|
||||
return ''.join([x.capitalize() for x in i.split('_')]) if i else i
|
||||
|
||||
def CsOperationNameConverter(i):
|
||||
return ''.join([x.capitalize() for x in i.split('.')])
|
||||
return ''.join([capitalizeOnlyFirstLetter(x) for x in i.split('.')]) if i else i
|
||||
|
||||
def OpenApiExtractRefType(i):
|
||||
e = i.split('/')
|
||||
|
71
openapi.yaml
71
openapi.yaml
@ -18,13 +18,26 @@ paths:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Test1"
|
||||
$ref: "#/components/schemas/test1"
|
||||
404:
|
||||
description: No test1 items available
|
||||
# post:
|
||||
# tags: [ "Regular" ]
|
||||
# operationId: Regular.test1insert
|
||||
# summary: Inserts an item into table test1
|
||||
# requestBody:
|
||||
# description: test1
|
||||
# content:
|
||||
# application/json:
|
||||
# schema:
|
||||
# $ref: "#/components/schemas/test1"
|
||||
# responses:
|
||||
# 201:
|
||||
# description: Your items has been inserted
|
||||
/pdb/v2/test1/{id}:
|
||||
get:
|
||||
tags: [ "Regular" ]
|
||||
operationId: Regular.test2byid
|
||||
operationId: Regular.test1byid
|
||||
summary: Returns one entry from table test1 by id
|
||||
parameters:
|
||||
- name: id
|
||||
@ -38,13 +51,49 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Test1"
|
||||
$ref: "#/components/schemas/test1"
|
||||
404:
|
||||
description: No such test1 item available
|
||||
/pdb/v2/test1/specificSelectName:
|
||||
get:
|
||||
tags: [ "Regular" ]
|
||||
operationId: Regular.test1specificSelectName
|
||||
summary: Returns entries from table test1 using a dedicated select statement
|
||||
description:
|
||||
STATEMENTBEGIN
|
||||
select txt
|
||||
from test1
|
||||
where nr = ?
|
||||
STATEMENTEND
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
|
||||
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
|
||||
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
|
||||
no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
|
||||
consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
|
||||
dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
|
||||
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem
|
||||
ipsum dolor sit amet.
|
||||
requestBody:
|
||||
description: specificSelectNameType
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/specificSelectNameType"
|
||||
responses:
|
||||
200:
|
||||
description: Here are your test1 items
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/specificResultType"
|
||||
404:
|
||||
description: No such test1 item available
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Test1:
|
||||
test1:
|
||||
description: A test1 item
|
||||
type: object
|
||||
required:
|
||||
@ -56,3 +105,17 @@ components:
|
||||
type: string
|
||||
nr:
|
||||
type: integer
|
||||
specificSelectNameType:
|
||||
description: Specific type to defintion select condition
|
||||
type: object
|
||||
required:
|
||||
- nr
|
||||
properties:
|
||||
nr:
|
||||
type: integer
|
||||
specificResultType:
|
||||
description: Specific result type to defintion select clause
|
||||
type: object
|
||||
properties:
|
||||
txt:
|
||||
type: string
|
||||
|
@ -17,18 +17,51 @@ namespace ${env['packagename']}.Implementations
|
||||
public class RegularApiImplementation : RegularApiController
|
||||
{
|
||||
#for $operation in $operations
|
||||
public override IActionResult ${operation['func']}() {
|
||||
return new ObjectResult();
|
||||
#if $operation['method'] == 'get'
|
||||
public override IActionResult ${operation['func']}( #slurp
|
||||
#if $operation['byIdSelector']
|
||||
INSERT CODE TO GET ID #slurp
|
||||
#elif $operation['inputType']
|
||||
[FromBody]$operation['inputType']['csName'] inputItem #slurp
|
||||
#end if
|
||||
) {
|
||||
// Statement:
|
||||
#if not $operation['statement']
|
||||
// SELECT
|
||||
#set $sep = ""
|
||||
#for $property in $types[$operation['resultType']['apiName']]['properties']
|
||||
// $sep$property['sqlName']
|
||||
#set $sep = ","
|
||||
#end for
|
||||
// FROM $types[$operation['resultType']['apiName']]['sqlName'];
|
||||
#else
|
||||
// $operation['statement']
|
||||
#end if
|
||||
#if $operation['inputType']
|
||||
// Input type mapping: $operation['inputType']['apiName'] -> $operation['inputType']['csName']
|
||||
#for $property in $types[$operation['inputType']['apiName']]['properties']
|
||||
// $property['sqlName'] -> $property['csName']
|
||||
#end for
|
||||
#end if
|
||||
// Model object to use: $operation['resultType']['apiName'] -> $operation['resultType']['csName']
|
||||
// Properties to map result:
|
||||
#for $property in $types[$operation['resultType']['apiName']]['properties']
|
||||
// $property['sqlName'] -> $property['csName']
|
||||
#end for
|
||||
#if $operation['isList']
|
||||
// result must be mapped in list
|
||||
#end if
|
||||
return new ObjectResult();
|
||||
}
|
||||
|
||||
#elif $operation['method'] == 'post'
|
||||
bla
|
||||
|
||||
#else
|
||||
#raise Exception('invalid method')
|
||||
#end if
|
||||
|
||||
#end for
|
||||
|
||||
public override IActionResult CyclesStartCycle([FromBody]MCycle mCycle) {
|
||||
return StatusCode(200, default(MCycle));
|
||||
}
|
||||
|
||||
public override IActionResult CyclesStopCycle([FromBody]CycleId cycleId) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user