Skip to content

Commit

Permalink
add json schema models code generator
Browse files Browse the repository at this point in the history
  • Loading branch information
akolomentsev committed Apr 20, 2018
1 parent e7827f7 commit 49ac17b
Show file tree
Hide file tree
Showing 25 changed files with 485 additions and 24 deletions.
1 change: 1 addition & 0 deletions codegen/jschema-models-gen/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/meta-info/
47 changes: 47 additions & 0 deletions codegen/jschema-models-gen/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apply from: rootProject.file('metainfo.gradle')

task generateTemplates(type: DependencyExec) {
group 'codegen'
generateCode.dependsOn it

def out = file("gen")
def templates = fileTree("templates").include("*.mustache")

inputs.file(templates)
outputs.dir(out)

sourceSets.main.java.srcDir out
idea.module.generatedSourceDirs += out

dependency "com.satori:satori-codegen-mustache-builder:$scaffoldingVersion"
main = "com.satori.codegen.mustache.builder.App"

args "--templates", templates.files.join(File.pathSeparator)
args "--pckg", pckg
args "--out", out

doFirst {
delete out
println "generating templates ...."
}

clean.doFirst {
delete out
}
}

// main dependencies
dependencies {
compile project(":libs-common-kotlin")
compile project(":codegen-utils")

compile "com.fasterxml.jackson.module:jackson-module-jsonSchema:$jacksonVersion"
compile "com.github.javaparser:javaparser-core:$javaparserVersion"
}

// test dependencies
dependencies {
testCompile project(":libs-testlib")
testCompile "ch.qos.logback:logback-classic:$logbackVersion"
testCompile "org.codehaus.groovy:groovy-all:$groovyVersion"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//auto generated
//don't modify


package com.satori.codegen.jschema.models.gen;

import java.util.ArrayList;

public class FileModel {

public final FileModel _root;
public TypeModel type;
public final ArrayList<String> imports = new ArrayList<String>();
public String packageName;

public FileModel() {
_root = this;
}

public void addImportsItem(String _item) {
imports.add(_item);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

package com.satori.codegen.jschema.models.gen;

import java.io.Writer;


/**
* auto generated
* don't modify
*
*/
public class FileTemplate {


public static void render0(Writer _os, String _model, boolean _last)
throws Exception
{
_os.write("import ");
_os.write(_model);
_os.write(";\n");
}

public static void render(Writer _os, FileModel _model)
throws Exception
{
_os.write("// auto generated\n// don't modify\npackage ");
_os.write(_model.packageName);
_os.write(";\n\n\nimport com.fasterxml.jackson.annotation.*;\n\n");
for(int _i=0; _i< _model.imports.size(); _i+=1){
render0(_os, _model.imports.get(_i), (_i+1) >= _model.imports.size());
}
_os.write("\n");
TypeTemplate.render(_os, _model.type);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//auto generated
//don't modify


package com.satori.codegen.jschema.models.gen;

import java.util.ArrayList;

public class TypeModel {

public final TypeModel _root;
public boolean isStatic;
public final ArrayList<TypesItem> types = new ArrayList<TypesItem>();
public String className;
public final ArrayList<PropertiesItem> properties = new ArrayList<PropertiesItem>();

public TypeModel() {
_root = this;
}

public TypesItem addTypesItem() {
TypesItem _item = new TypesItem(_root, this);
types.add(_item);
return _item;
}

public PropertiesItem addPropertiesItem() {
PropertiesItem _item = new PropertiesItem(_root, this);
properties.add(_item);
return _item;
}

public class PropertiesItem {

public final TypeModel _root;
public final TypeModel _parent;
public String varName;
public String schemaName;
public String type;

public PropertiesItem(TypeModel _root, TypeModel _parent) {
this._root = _root;
this._parent = _parent;
}

}

public class TypesItem {

public final TypeModel _root;
public final TypeModel _parent;
public TypeModel type;

public TypesItem(TypeModel _root, TypeModel _parent) {
this._root = _root;
this._parent = _parent;
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

package com.satori.codegen.jschema.models.gen;

import java.io.Writer;


/**
* auto generated
* don't modify
*
*/
public class TypeTemplate {


public static void render0(Writer _os, TypeModel.PropertiesItem _model, boolean _last)
throws Exception
{
_os.write(" @JsonProperty(\"");
_os.write(_model.schemaName);
_os.write("\")\n public ");
_os.write(_model.type);
_os.write(" ");
_os.write(_model.varName);
_os.write(";\n");
}

public static void render1(Writer _os, TypeModel.TypesItem _model, boolean _last)
throws Exception
{
_os.write(" ");
TypeTemplate.render(_os, _model.type);
_os.write("\n");
}

public static void render(Writer _os, TypeModel _model)
throws Exception
{
_os.write("@JsonInclude(JsonInclude.Include.NON_DEFAULT)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic ");
if( _model.isStatic ) {
_os.write("static");
}
_os.write(" class ");
_os.write(_model.className);
_os.write(" {\n");
for(int _i=0; _i< _model.properties.size(); _i+=1){
render0(_os, _model.properties.get(_i), (_i+1) >= _model.properties.size());
}
_os.write("\n");
for(int _i=0; _i< _model.types.size(); _i+=1){
render1(_os, _model.types.get(_i), (_i+1) >= _model.types.size());
}
_os.write("}");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.satori.codegen.jschema.models.gen

import com.satori.libs.common.kotlin.json.*

object App : IJsonContext by DefaultJsonContext {
@JvmStatic
fun main(vararg args: String) {
println(MetaInfo)
println("java version: ${System.getProperty("java.version")}")

val cfg = jsonObject {
val itor = args.iterator()
while (true) {
val name = if (itor.hasNext()) itor.next() else break
val value = if (itor.hasNext()) itor.next() else throw Exception("argument value is missing")
if (!name.startsWith("--")) throw Exception("argument '$name' should start with '--'")
field(name, value)
}
}.scope { toValue<AppConfig>() }

val env = ICodeGenEnv.Default(cfg)
ModelsCodeGen.run(env)
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.satori.codegen.jschema.models.gen

import com.fasterxml.jackson.annotation.*

@JsonInclude(JsonInclude.Include.NON_DEFAULT)
class AppConfig {
@JsonProperty("--pckg")
var pckg: String = ""

@JsonProperty("--schema")
var schema: String? = null

@JsonProperty("--out")
var out: String = ""

@JsonProperty("--name")
var name: String? = null

@JsonProperty("--prefix")
var prefix: String = ""
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@file:JvmName("Example")

package com.satori.codegen.jschema.models.gen

import java.io.*

fun main(args: Array<String>) {

File("core/.tests-data").deleteRecursively()

val cfg = AppConfig().apply {
pckg = javaClass.`package`.name
schema = "core/codegen/schema.json"
out = "core/.tests-data"
}

val env = ICodeGenEnv.Default(cfg)
ModelsCodeGen.run(env)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.satori.codegen.jschema.models.gen

import com.fasterxml.jackson.module.jsonSchema.*
import com.satori.codegen.utils.*
import com.satori.libs.common.kotlin.json.*
import java.nio.file.*

interface ICodeGenEnv : IJsonContext {
val cfg: AppConfig
val schema: JsonSchema
val fmt: ICodeFormatter
get() = CodeFormatter

fun path(pckg: String, fileName: String): Path {
val pckgDir = pckg.replace(".", "/")
return Paths.get("${cfg.out}/$pckgDir/$fileName")
}

class Default(cfg: AppConfig) : ICodeGenEnv {
override val mapper = DefaultJsonContext.mapper
override val cfg = cfg
override val schema = loadSchema(cfg.schema
?: throw Exception("missing '--schema' argument"))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.satori.codegen.jschema.models.gen

import com.fasterxml.jackson.module.jsonSchema.*
import com.fasterxml.jackson.module.jsonSchema.types.*

class ModelsCodeGen(env: ICodeGenEnv) : ICodeGenEnv by env {

fun run() {
val model = FileModel()

if (schema !is ObjectSchema) {
println("schema is no an object")
return
}

val className = fmt.className(cfg.name ?: throw Exception("--name not specified"))
model.packageName = cfg.pckg

model.type = TypeModel().also {
it.className = className
processProperties(it, schema)
}



writeJavaClass(className) {
FileTemplate.render(it, model)
}
}

fun processProperties(model: TypeModel, schema: ObjectSchema) {
for ((k, v) in schema.properties) {
model.addPropertiesItem().apply {
this.schemaName = k
this.varName = fmt.varName(k)
this.type = typeForSchema(k, v)
}
if (v.isObjectSchema) {
model.addTypesItem().apply {
type = TypeModel().also {
it.isStatic = true
it.className = fmt.className(k)
processProperties(it, v.asObjectSchema())
}
}
}
}
}

fun typeForSchema(propName: String, schema: JsonSchema): String {
if (schema.isStringSchema) return "String"
if (schema.isBooleanSchema) return "Boolean"
if (schema.isIntegerSchema) return "Integer"
if (schema.isNumberSchema) return "Double"
if (schema.isAnySchema) return "JsonNode"
if (schema.isObjectSchema) return fmt.className(propName)
throw Exception("type '$schema' not supported")
}

companion object {

fun run(env: ICodeGenEnv) {
ModelsCodeGen(env).run()
}

}
}
Loading

0 comments on commit 49ac17b

Please sign in to comment.