Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add source info to type #29

Merged
merged 3 commits into from
Oct 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,25 @@ Usage: de.lisaplus.atlas.DoCodeGen [options]

* -m, --model
Path to JSON schema to parse
* -o, --outputBase
-o, --outputBase
Base directory for the output
-pmt, --print-main-types
don't do any code generation, simply loads the model and print the
main-types of it
Default: false
-pmta, --print-main-types-attrib
don't do any code generation, simply loads the model and print the
main-types of it
-pmti, --print-main-types-info
print with info header
Default: false
-pmts, --print-main-types-separator
separator to use for printing main types
-rt, --remove-tag
remove a tag from a specific type, f.e. -at User=unused
remove a tag from a specific type, f.e. -rt User=unused
Default: []
-rta, --remove-tag-all
remove a tag from all model types, f.e. -rta rest
Default: []
-w, --white-list
white listed type, multiple usage possible
Expand Down
5 changes: 5 additions & 0 deletions Releases.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.8.1
- add to types schemaPath and schemaFileName attributes (to finally detect what are the interesting main types of a model)
- add a isMainType function to model type
- add command line switches pro print only main types

## 0.8.0
- command line switches for type black- and white-lists
- command line switch to add tags to types
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sourceCompatibility = 1.8
def mainClass='de.lisaplus.atlas.DoCodeGen'

project.group = 'de.lisaplus.tools'
project.version = '0.7.5'
project.version = '0.8.1'

/*
* the following attributes need to be declared in $HOME/.gradle/gradle.properties
Expand Down
46 changes: 43 additions & 3 deletions src/main/groovy/de/lisaplus/atlas/DoCodeGen.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class DoCodeGen {
/**
* Base directory for the output
*/
@Parameter(names = [ '-o', '--outputBase' ], description = "Base directory for the output", required = true)
@Parameter(names = [ '-o', '--outputBase' ], description = "Base directory for the output")
String outputBaseDir

/**
Expand Down Expand Up @@ -73,6 +73,25 @@ class DoCodeGen {
@Parameter(names = ['-h','--help'], help = true)
boolean help = false

/**
* Simply print main types
*/
@Parameter(names = ['-pmt','--print-main-types'], description = "don't do any code generation, simply loads the model and print the main-types of it")
boolean printMainTypes = false

@Parameter(names = ['-pmts','--print-main-types-separator'], description = "separator to use for printing main types")
String printMainTypesSeparator

@Parameter(names = ['-pmti','--print-main-types-info'], description = "print with info header")
boolean printMainTypesInfo = false

/**
* an required type property to include into main types
*/
@Parameter(names = ['-pmta','--print-main-types-attrib'], description = "don't do any code generation, simply loads the model and print the main-types of it")
String mainTypeAttrib


/**
* List of type-name tag-text tuple, The tags will be merged after initialization with the object tree
*/
Expand Down Expand Up @@ -129,16 +148,18 @@ class DoCodeGen {
log.info("use model file: ${model}")
}

prepareOutputBaseDir(outputBaseDir)

IModelBuilder builder = model.toLowerCase().endsWith('.json') ? new JsonSchemaBuilder() :
model.toLowerCase().endsWith('.xsd') ? new XSDBuilder() : null
if (builder==null) {
log.error("unknown file type, currently only jscon schema and xsd are supported: ${model}")
System.exit(1)
}
dataModel = builder.buildModel(modelFile)
printMainTypesIfNeeded(dataModel,modelFile.getName())

adjustTagsForModel(dataModel)
prepareOutputBaseDir(outputBaseDir)

// convert extra generator parameter to a map
Map<String,String> extraParameters = getMapFromGeneratorParams(generator_parameters)
extraParameters['blackListed']=blackListed
Expand Down Expand Up @@ -166,6 +187,25 @@ class DoCodeGen {
}
}

void printMainTypesIfNeeded(Model dataModel, String fileName) {
if (printMainTypes) {
def mfn = fileName
String separator = printMainTypesSeparator ? printMainTypesSeparator : ' '
def attrib = mainTypeAttrib ? " - needed attrib: $mainTypeAttrib" : ''
def info = "mainTypes [$mfn$attrib]:"
def outStr = printMainTypesInfo ? info : ''
dataModel.types.each { type ->
if (type.isMainType(mfn)) {
if ((!mainTypeAttrib) || (type.hasPropertyWithName(mainTypeAttrib))) {
outStr = "${outStr}${separator}${type.name}"
}
}
}
println (outStr)
System.exit(0)
}
}

/**
* splits extra generator parameter to Map values
* expected entries looks like this: packageBase=de.sw.atlas
Expand Down
75 changes: 47 additions & 28 deletions src/main/groovy/de/lisaplus/atlas/builder/JsonSchemaBuilder.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class JsonSchemaBuilder implements IModelBuilder {
Model model = initModel(objectModel)
if (objectModel['definitions']) {
// multi type schema
loadSchemaTypes(objectModel,currentSchemaPath,model)
loadSchemaTypes(objectModel,modelFile.getName(),currentSchemaPath,model)
}
if (objectModel['allOf']) {
// single type schema
Expand Down Expand Up @@ -104,24 +104,26 @@ class JsonSchemaBuilder implements IModelBuilder {
typeName = string2Name(typeName)
Type newType = new Type()
newType.name = typeName
newType.schemaPath = currentSchemaPath
newType.schemaFileName = modelFileName
newType.description = strFromMap(objectModel,'description')
if (objectModel.allOf) {
// TODO - add allof Properties
objectModel.allOf.each { allOfElem ->
if (allOfElem.properties) {
newType.properties.addAll(getProperties(model,allOfElem,typeName,currentSchemaPath))
newType.properties.addAll(getProperties(model,allOfElem,typeName,modelFileName,currentSchemaPath))
}
else {
if (allOfElem.'$ref') {
RefType tmp = initRefType(allOfElem.'$ref',currentSchemaPath)
RefType tmp = initRefType(allOfElem.'$ref',modelFileName,currentSchemaPath)
newType.properties.addAll(tmp.type.properties)
newType.baseTypes.add(tmp.type.name)
}
}
}
}
else {
newType.properties = getProperties(model,objectModel,typeName,currentSchemaPath)
newType.properties = getProperties(model,objectModel,typeName,modelFileName,currentSchemaPath)
}
if (objectModel.'__tags') {
newType.tags=objectModel.'__tags'
Expand Down Expand Up @@ -150,25 +152,26 @@ class JsonSchemaBuilder implements IModelBuilder {
}
}


private Model loadSchemaTypes(def objectModel,String currentSchemaPath,Model model) {
private Model loadSchemaTypes(def objectModel, String schemaFileName,String currentSchemaPath,Model model) {
if (model==null)
model = initModel(objectModel)
objectModel.definitions.each { typeObj ->
def typeName = string2Name(typeObj.key)
Type newType = new Type()
newType.name = typeName
newType.schemaPath = currentSchemaPath
newType.schemaFileName = schemaFileName
newType.description = strFromMap(typeObj.value,'description')
newType.properties = []
if (typeObj.value.allOf) {
// TODO - add allof Properties
typeObj.value.allOf.each { allOfElem ->
if (allOfElem.properties) {
newType.properties.addAll(getProperties(model,allOfElem,typeName,currentSchemaPath))
newType.properties.addAll(getProperties(model,allOfElem,typeName,schemaFileName,currentSchemaPath))
}
else {
if (allOfElem.'$ref') {
RefType tmp = initRefType(allOfElem.'$ref',currentSchemaPath)
RefType tmp = initRefType(allOfElem.'$ref',schemaFileName,currentSchemaPath)
newType.properties.addAll(tmp.type.properties)
newType.baseTypes.add(tmp.type.name)
}
Expand All @@ -177,12 +180,12 @@ class JsonSchemaBuilder implements IModelBuilder {
}
else if (typeObj.value.'$ref') {
// this type refers to an external definition
RefType tmp = initRefType(typeObj.value.'$ref', currentSchemaPath)
RefType tmp = initRefType(typeObj.value.'$ref', schemaFileName, currentSchemaPath)
newType.properties.addAll(tmp.type.properties)
newType.baseTypes.add(tmp.type.name)
}
else {
newType.properties = getProperties(model,typeObj.value,typeName,currentSchemaPath)
newType.properties = getProperties(model,typeObj.value,typeName,schemaFileName,currentSchemaPath)
}
if (typeObj.value.'__tags') {
newType.tags=typeObj.value.'__tags'
Expand Down Expand Up @@ -226,10 +229,10 @@ class JsonSchemaBuilder implements IModelBuilder {
model.types.add(newType)
}

private List<Property> getProperties(Model model,def propertyParent,def parentName,String currentSchemaPath) {
private List<Property> getProperties(Model model,def propertyParent,def parentName,String schemaFileName, String currentSchemaPath) {
List<Property> propList = []
propertyParent.properties.each { propObj ->
propList.add(creeateSimpleProperty(model, parentName,currentSchemaPath,propObj))
propList.add(creeateSimpleProperty(model, parentName,schemaFileName,currentSchemaPath,propObj))
}
// Dirty hack for enabling the usage of mongoDB Index2d:
// For performing filtering on geo coordinates in Documents of the mongoDB (e.g. operation geoWithin), the Json
Expand All @@ -250,12 +253,12 @@ class JsonSchemaBuilder implements IModelBuilder {
return propList
}

private Property creeateSimpleProperty (Model model, def parentName,String currentSchemaPath,def propObj) {
private Property creeateSimpleProperty (Model model, def parentName,String schemaFileName,String currentSchemaPath, def propObj) {
def newProp = new Property()
newProp.name = string2Name(propObj.key, false)
newProp.description = propObj.value['description']
String key = makeCamelCase(propObj.key)
newProp.type = getPropertyType(model, propObj.value, parentName + string2Name(key), currentSchemaPath)
newProp.type = getPropertyType(model, propObj.value, parentName + string2Name(key),schemaFileName, currentSchemaPath)
if (newProp.type instanceof RefType) {
if (propObj.key.toLowerCase().endsWith('_id') || propObj.key.toLowerCase().endsWith('Id')) { // per convention
newProp.aggregationType = AggregationType.aggregation
Expand All @@ -276,39 +279,39 @@ class JsonSchemaBuilder implements IModelBuilder {
// implicit refs for normal types and array types differ
if (newProp.type.isArray) {
if (propObj.value.items.'__ref') {
newProp.implicitRef = initRefType(propObj.value.items.'__ref', currentSchemaPath)
newProp.implicitRef = initRefType(propObj.value.items.'__ref', schemaFileName, currentSchemaPath)
}
}
else {
if (propObj.value.'__ref') {
newProp.implicitRef = initRefType(propObj.value.'__ref', currentSchemaPath)
newProp.implicitRef = initRefType(propObj.value.'__ref', schemaFileName, currentSchemaPath)
}
}
if (propObj.value.'__ref') {
newProp.implicitRef = initRefType(propObj.value.'__ref', currentSchemaPath)
newProp.implicitRef = initRefType(propObj.value.'__ref', schemaFileName, currentSchemaPath)
}
if (propObj.value.'__tags') {
newProp.tags=propObj.value.'__tags'
}
return newProp
}

private BaseType getPropertyType(Model model,def propObjMap,def innerTypeBaseName,String currentSchemaPath) {
private BaseType getPropertyType(Model model,def propObjMap,def innerTypeBaseName, String schemaFileName,String currentSchemaPath) {
if (propObjMap.'$ref') {
// reference to an external type
return initRefType(propObjMap.'$ref',currentSchemaPath)
return initRefType(propObjMap.'$ref', schemaFileName,currentSchemaPath)
}
else if (! propObjMap.type) {
def errorMsg = "property object w/o any type: ${propObjMap}"
log.error(errorMsg)
throw new Exception(errorMsg)
}
else {
return getBaseTypeFromString(model,currentSchemaPath,propObjMap,innerTypeBaseName)
return getBaseTypeFromString(model,schemaFileName,currentSchemaPath,propObjMap,innerTypeBaseName)
}
}

private RefType initRefType(def refStr,String currentSchemaPath) {
private RefType initRefType(def refStr,String schemaFileName,String currentSchemaPath) {
if (!refStr) {
def errorMsg = "undefined refStr, so cancel init reference type"
log.error(errorMsg)
Expand All @@ -323,6 +326,10 @@ class JsonSchemaBuilder implements IModelBuilder {
if (refStr.startsWith(localDefStrBase)) {
def schemaTypeName = refStr.substring(localDefStrBase.length())
Type t = getLocalRefType(schemaTypeName)
if (!t.schemaPath) {
t.schemaPath = currentSchemaPath
t.schemaFileName = schemaFileName
}
if (t instanceof DummyType) {
// the needed type isn't already in the model created. later a update to the
// right references is needed
Expand All @@ -337,6 +344,10 @@ class JsonSchemaBuilder implements IModelBuilder {
// "$ref": "definitions.json#/address"
// "$ref": "http: //json-schema.org/geo" - HTTP not supported (eiko)
Type t = getExternalRefType(refStr,currentSchemaPath)
if (!t.schemaPath) {
t.schemaPath = currentSchemaPath
t.schemaFileName = schemaFileName
}
refType.type=t
refType.typeName=t.name
}
Expand Down Expand Up @@ -368,6 +379,8 @@ class JsonSchemaBuilder implements IModelBuilder {
tmpModel.types.each { type ->
if ((type.name!=null) && (type.name.toLowerCase()==desiredName)) {
extT2 = type
extT2.schemaPath = currentSchemaPath
extT2.schemaFileName = fileName
}
}
if (extT2==null) {
Expand All @@ -394,6 +407,10 @@ class JsonSchemaBuilder implements IModelBuilder {
Type tmpT = tmpModel.types.find {
! (it instanceof InnerType)
}
if (!tmpT.schemaPath) {
tmpT.schemaPath = currentSchemaPath
tmpT.schemaFileName = fileName
}
extT.refStr = refStr
extT.initFromType(tmpT)
// can be removed, because it's identical to the early init call (*1)
Expand Down Expand Up @@ -445,7 +462,7 @@ class JsonSchemaBuilder implements IModelBuilder {

}

private ComplexType initComplexType(Model model,def propertiesParent,def baseTypeName, String currentSchemaPath) {
private ComplexType initComplexType(Model model,def propertiesParent,def baseTypeName, String schemaFileName, String currentSchemaPath) {
if (!propertiesParent) {
def errorMsg = "undefined properties map, so cancel init complex type"
log.error(errorMsg)
Expand All @@ -454,13 +471,15 @@ class JsonSchemaBuilder implements IModelBuilder {
ComplexType complexType = new ComplexType()
Type newType = new InnerType()
newType.name = baseTypeName
newType.properties = getProperties(model,propertiesParent,baseTypeName,currentSchemaPath)
newType.schemaPath = currentSchemaPath
newType.schemaFileName = schemaFileName
newType.properties = getProperties(model,propertiesParent,baseTypeName,schemaFileName,currentSchemaPath)
complexType.type = newType
addNewType(newType,model)
return complexType
}

private BaseType getBaseTypeFromString(Model model,String currentSchemaPath,def propObjMap, def innerTypeBaseName, def isArrayAllowed=true) {
private BaseType getBaseTypeFromString(Model model,String schemaFileName, String currentSchemaPath,def propObjMap, def innerTypeBaseName, def isArrayAllowed=true) {
switch (propObjMap.type) {
case 'string':
if (propObjMap.format && propObjMap.format.toLowerCase()=="uuid") {
Expand Down Expand Up @@ -490,7 +509,7 @@ class JsonSchemaBuilder implements IModelBuilder {
return new UnsupportedType()
}
else
return initComplexType(model,propObjMap,innerTypeBaseName,currentSchemaPath)
return initComplexType(model,propObjMap,innerTypeBaseName,schemaFileName,currentSchemaPath)
case 'array':
/*
if (!isArrayAllowed) {
Expand All @@ -503,14 +522,14 @@ class JsonSchemaBuilder implements IModelBuilder {
// test - eiko
// BaseType ret = getBaseTypeFromString(model,currentSchemaPath,propObjMap.items,innerTypeBaseName+'Item',false)
if (propObjMap.items.type=='array') {
BaseType tmp = getBaseTypeFromString(model,currentSchemaPath,propObjMap.items,innerTypeBaseName+'Item')
BaseType tmp = getBaseTypeFromString(model,schemaFileName,currentSchemaPath,propObjMap.items,innerTypeBaseName+'Item')
ArrayType ret = new ArrayType()
ret.isArray = true
ret.baseType = tmp
return ret
}
else {
BaseType ret = getBaseTypeFromString(model,currentSchemaPath,propObjMap.items,innerTypeBaseName+'Item')
BaseType ret = getBaseTypeFromString(model,schemaFileName,currentSchemaPath,propObjMap.items,innerTypeBaseName+'Item')
ret.isArray = true
// the attrib has an _t_tags entry ...
if (propObjMap.'__tags') {
Expand All @@ -523,7 +542,7 @@ class JsonSchemaBuilder implements IModelBuilder {
}
}
else if (propObjMap.items['$ref']) {
BaseType ret = initRefType(propObjMap.items['$ref'],currentSchemaPath)
BaseType ret = initRefType(propObjMap.items['$ref'],schemaFileName,currentSchemaPath)
ret.isArray = true
return ret
}
Expand Down
Loading