Skip to content

Commit

Permalink
Merge pull request #147 from halfcrazy/feat/modelgen-enum
Browse files Browse the repository at this point in the history
add enum support for modelgen
  • Loading branch information
dave-tucker committed Jun 10, 2021
2 parents 4ea26cc + 28ddaa6 commit 23dd150
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 32 deletions.
83 changes: 78 additions & 5 deletions modelgen/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,23 @@ const BASE_TABLE_TEMPLATE = `{{ template "header" . }}
package {{ index . "PackageName" }}
{{ if index . "Enums" }}
type (
{{ range index . "Enums" }}
{{ .Alias }} = {{ .Type }}
{{- end }}
)
const (
{{ range index . "Enums" }}
{{- $e := . }}
{{- range .Sets }}
{{ $e.Alias }}{{ camelCase . }} {{ $e.Alias }} = {{ printVal . $e.Type }}
{{- end }}
{{- end }}
)
{{ end }}
{{ template "preStructDefinitions" }}
{{ template "structComment" . }}
type {{ index . "StructName" }} struct {
Expand Down Expand Up @@ -53,6 +70,13 @@ const DEFAULT_EXTRA_FIELDS_TEMPLATE = `{{ define "extraFields" }}{{ end }}`
// DEFAULT_POST_TABLE_TEMPLATE is the default template for "postStructDefinitions"
const DEFAULT_POST_TABLE_TEMPLATE = `{{ define "postStructDefinitions" }}{{ end }}`

// Enum represents the enum schema type
type Enum struct {
Type string
Alias string
Sets []interface{}
}

// Field represents the field information
type Field struct {
Column string
Expand All @@ -72,6 +96,7 @@ func GetTableTemplateData(pkg, name string, table *ovsdb.TableSchema) map[string
data["PackageName"] = pkg
data["StructName"] = StructName(name)
Fields := []Field{}
Enums := []Enum{}

// First, add UUID
Fields = append(Fields,
Expand All @@ -95,18 +120,26 @@ func GetTableTemplateData(pkg, name string, table *ovsdb.TableSchema) map[string
Fields = append(Fields, Field{
Column: columnName,
Name: FieldName(columnName),
Type: FieldType(columnSchema),
Type: FieldType(name, columnName, columnSchema),
Tag: Tag(columnName),
})
if enum := FieldEnum(name, columnName, columnSchema); enum != nil {
Enums = append(Enums, *enum)
}
}
data["Fields"] = Fields
data["Enums"] = Enums
return data
}

// NewTableTemplate returns a new TableTemplate and the TableTemplate data map
// See BASE_TABLE_TEMPLATE to a detailed explanation of the possible ways this template can be expanded
func NewTableTemplate(pkg string, name string, table *ovsdb.TableSchema) (*template.Template, map[string]interface{}) {
main, err := template.New(name).Parse(BASE_TABLE_TEMPLATE)
funcMap := template.FuncMap{
"printVal": printVal,
"camelCase": camelCase,
}
main, err := template.New(name).Funcs(funcMap).Parse(BASE_TABLE_TEMPLATE)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -144,24 +177,44 @@ func FieldName(column string) string {

// StructName returns the name of the table struct
func StructName(tableName string) string {
return strings.ReplaceAll(tableName, "_", "")
return strings.Title(strings.ReplaceAll(tableName, "_", ""))
}

// EnumName returns the name of the enum field
func EnumName(tableName, columnName string) string {
return strings.Title(StructName(tableName)) + camelCase(columnName)
}

// FieldType returns the string representation of a column type
func FieldType(column *ovsdb.ColumnSchema) string {
func FieldType(tableName, columnName string, column *ovsdb.ColumnSchema) string {
switch column.Type {
case ovsdb.TypeEnum:
return AtomicType(column.TypeObj.Key.Type)
return EnumName(tableName, columnName)
case ovsdb.TypeMap:
return fmt.Sprintf("map[%s]%s", AtomicType(column.TypeObj.Key.Type),
AtomicType(column.TypeObj.Value.Type))
case ovsdb.TypeSet:
if FieldEnum(tableName, columnName, column) != nil {
return fmt.Sprintf("[]%s", EnumName(tableName, columnName))
}
return fmt.Sprintf("[]%s", AtomicType(column.TypeObj.Key.Type))
default:
return AtomicType(column.Type)
}
}

// FieldEnum returns the Enum if the column is an enum type
func FieldEnum(tableName, columnName string, column *ovsdb.ColumnSchema) *Enum {
if column.TypeObj.Key.Enum == nil {
return nil
}
return &Enum{
Type: column.TypeObj.Key.Type,
Alias: EnumName(tableName, columnName),
Sets: column.TypeObj.Key.Enum,
}
}

// BasicType returns the string type of an AtomicType
func AtomicType(atype string) string {
switch atype {
Expand Down Expand Up @@ -211,9 +264,15 @@ var initialisms = map[string]bool{
"SSL": true,
"STP": true,
"TCP": true,
"SCTP": true,
"UDP": true,
"UUID": true,
"VLAN": true,
"STT": true,
"DNAT": true,
"SNAT": true,
"ICMP": true,
"SLB": true,
}

func camelCase(field string) string {
Expand Down Expand Up @@ -246,3 +305,17 @@ func expandInitilaisms(s string) string {
}
return s
}

func printVal(v interface{}, t string) string {
switch t {
case "int":
return fmt.Sprintf(`%d`, v)
case "float64":
return fmt.Sprintf(`%f`, v)
case "bool":
return fmt.Sprintf(`%t`, v)
case "string":
return fmt.Sprintf(`"%s"`, v)
}
return ""
}
105 changes: 78 additions & 27 deletions modelgen/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ func TestNewTableTemplate(t *testing.T) {
},
"float": {
"type": "real"
}
},
"protocol": {
"type": {"key": {"type": "string",
"enum": ["set", ["tcp", "udp", "sctp"]]},
"min": 0, "max": 1}},
"event_type": {"type": {"key": {"type": "string",
"enum": ["set", ["empty_lb_backends"]]}}}
}
}
}
Expand All @@ -46,12 +52,26 @@ func TestNewTableTemplate(t *testing.T) {
package test
// test defines an object in test table
type test struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
type (
AtomicTableEventType = string
AtomicTableProtocol = string
)
const (
AtomicTableEventTypeEmptyLbBackends AtomicTableEventType = "empty_lb_backends"
AtomicTableProtocolTCP AtomicTableProtocol = "tcp"
AtomicTableProtocolUDP AtomicTableProtocol = "udp"
AtomicTableProtocolSCTP AtomicTableProtocol = "sctp"
)
// AtomicTable defines an object in atomicTable table
type AtomicTable struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
EventType AtomicTableEventType ` + "`" + `ovs:"event_type"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Protocol []AtomicTableProtocol ` + "`" + `ovs:"protocol"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
}
`,
},
Expand All @@ -70,17 +90,33 @@ type test struct {
package test
// test defines an object in test table
type test struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
OtherUUID string
OtherFloat float64
OtherInt int
OtherStr string
type (
AtomicTableEventType = string
AtomicTableProtocol = string
)
const (
AtomicTableEventTypeEmptyLbBackends AtomicTableEventType = "empty_lb_backends"
AtomicTableProtocolTCP AtomicTableProtocol = "tcp"
AtomicTableProtocolUDP AtomicTableProtocol = "udp"
AtomicTableProtocolSCTP AtomicTableProtocol = "sctp"
)
// AtomicTable defines an object in atomicTable table
type AtomicTable struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
EventType AtomicTableEventType ` + "`" + `ovs:"event_type"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Protocol []AtomicTableProtocol ` + "`" + `ovs:"protocol"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
OtherUUID string
OtherEventType AtomicTableEventType
OtherFloat float64
OtherInt int
OtherProtocol []AtomicTableProtocol
OtherStr string
}
`,
},
Expand All @@ -103,16 +139,30 @@ func {{ index . "TestName" }} () string {
package test
// test defines an object in test table
type test struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
type (
AtomicTableEventType = string
AtomicTableProtocol = string
)
const (
AtomicTableEventTypeEmptyLbBackends AtomicTableEventType = "empty_lb_backends"
AtomicTableProtocolTCP AtomicTableProtocol = "tcp"
AtomicTableProtocolUDP AtomicTableProtocol = "udp"
AtomicTableProtocolSCTP AtomicTableProtocol = "sctp"
)
// AtomicTable defines an object in atomicTable table
type AtomicTable struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
EventType AtomicTableEventType ` + "`" + `ovs:"event_type"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Protocol []AtomicTableProtocol ` + "`" + `ovs:"protocol"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
}
func TestFunc() string {
return "test"
return "AtomicTable"
}
`,
},
Expand Down Expand Up @@ -140,10 +190,11 @@ WRONG FORMAT

for _, tt := range test {
t.Run(fmt.Sprintf("Table Test: %s", tt.name), func(t *testing.T) {
table := schema.Tables["atomicTable"]
fakeTable := "atomicTable"
table := schema.Tables[fakeTable]
templ, data := NewTableTemplate(
"test",
"test",
fakeTable,
&table,
)
if tt.err {
Expand Down

0 comments on commit 23dd150

Please sign in to comment.