156 lines
3.3 KiB
Go
156 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"go/format"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
|
|
"gopkg.in/alecthomas/kingpin.v2"
|
|
"gopkg.in/yaml.v2"
|
|
|
|
"github.com/serenize/snaker"
|
|
)
|
|
|
|
var (
|
|
flagPackageName = kingpin.Flag("pkg", "Output package name").Default("main").String()
|
|
flagForce = kingpin.Flag("force", "Force rebuild.").Short('f').Bool()
|
|
flagYamlDefFile = kingpin.Arg("path", "Input YAML definitions file path").ExistingFile()
|
|
)
|
|
|
|
type yamlDef struct {
|
|
Imports []string
|
|
Kinds map[string]*yamlTypeDef
|
|
}
|
|
|
|
type yamlTypeDef struct {
|
|
Extends []string
|
|
Fields map[string]string
|
|
}
|
|
|
|
func normalizeFieldId(t string) string {
|
|
switch t {
|
|
case "urn":
|
|
return "URN"
|
|
default:
|
|
return snaker.SnakeToCamel(t)
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
kingpin.Parse()
|
|
|
|
// Generate output file name from input file name
|
|
outputFileName := (*flagYamlDefFile)[0:len(*flagYamlDefFile)-len(filepath.Ext(*flagYamlDefFile))] + ".go"
|
|
|
|
// Get input file stat
|
|
inputStat, err := os.Stat(*flagYamlDefFile)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Does output file exist?
|
|
if !*flagForce {
|
|
if s, err := os.Stat(outputFileName); err == nil {
|
|
// Check output file time against input file time
|
|
if !inputStat.ModTime().After(s.ModTime()) {
|
|
// Output already up to date!
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Println(filepath.Base(*flagYamlDefFile))
|
|
|
|
// Read YAML def
|
|
ymlBytes, err := ioutil.ReadFile(*flagYamlDefFile)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Unmarshal YAML def
|
|
var ymlDef yamlDef
|
|
yaml.Unmarshal(ymlBytes, &ymlDef)
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
// Write package name
|
|
b.WriteString(fmt.Sprintf("package %s\n", *flagPackageName))
|
|
|
|
// Write imports
|
|
if ymlDef.Imports != nil && len(ymlDef.Imports) > 0 {
|
|
b.WriteString("import (\n")
|
|
for _, i := range ymlDef.Imports {
|
|
b.WriteString(fmt.Sprintf("%q", i))
|
|
}
|
|
b.WriteString(")\n")
|
|
}
|
|
|
|
// Write types
|
|
registeredTypes := make(map[string]interface{})
|
|
//var ensureType func(string)
|
|
generateType := func(name string, definition *yamlTypeDef) {
|
|
//id := snaker.SnakeToCamel(name)
|
|
|
|
/*for _, fieldType := range definition.Fields {
|
|
ensureType(fieldType)
|
|
}*/
|
|
|
|
b.WriteString(fmt.Sprintf("\ntype %s struct {\n", name))
|
|
|
|
// Extends (as configured)
|
|
for _, t := range definition.Extends {
|
|
b.WriteString(t + "\n")
|
|
}
|
|
|
|
// Fields (sorted alphabetically)
|
|
var keys []string
|
|
for k, _ := range definition.Fields {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, fieldName := range keys {
|
|
fieldType := definition.Fields[fieldName]
|
|
fieldId := normalizeFieldId(fieldName)
|
|
b.WriteString(fmt.Sprintf("%s %s `json:%q`\n", fieldId, fieldType, fieldName))
|
|
}
|
|
b.WriteString("}\n")
|
|
}
|
|
/*ensureType = func(name string) {
|
|
if _, ok := registeredTypes[name]; ok {
|
|
// already generated
|
|
return
|
|
}
|
|
|
|
typeDef, ok := ymlDef.Kinds[name]
|
|
if ok {
|
|
registeredTypes[name] = nil
|
|
generateType(name, typeDef)
|
|
}
|
|
}*/
|
|
|
|
var keys []string
|
|
for k, _ := range ymlDef.Kinds {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, name := range keys {
|
|
typeDef := ymlDef.Kinds[name]
|
|
if _, ok := registeredTypes[name]; !ok {
|
|
registeredTypes[name] = nil
|
|
generateType(name, typeDef)
|
|
}
|
|
}
|
|
|
|
// Write out formatted source code
|
|
//fmt.Println(string(b.Bytes()))
|
|
fb, err := format.Source(b.Bytes())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
ioutil.WriteFile(outputFileName, fb, 0644)
|
|
}
|