diff --git a/cmd/modelgen/table.go b/cmd/modelgen/table.go index 97b796c2..f20d1e68 100644 --- a/cmd/modelgen/table.go +++ b/cmd/modelgen/table.go @@ -15,6 +15,24 @@ const TABLE_TEMPLATE = ` package {{ .PackageName }} +{{ if .Enums }} +type ( +{{ range .Enums }} +{{ $e := . }} +{{ $e.Alias }} {{ $e.Type }} +{{- end }} +) + +const ( +{{ range .Enums }} +{{ $e := . }} +{{ range .Sets }} +{{ $e.Alias }}{{ camelCase . }} {{ $e.Alias }} = {{ printVal . $e.Type }} +{{- end }} +{{- end }} +) +{{ end }} + // {{ .StructName }} defines an object in {{ .TableName }} table type {{ .StructName }} struct { {{ range .Fields }} {{ .Name }} {{ .Type }} {{ .Tag }} @@ -28,6 +46,14 @@ type TableTemplateData struct { PackageName string StructName string Fields []Field + Enums []Enum +} + +// Enum represents the enum schema type +type Enum struct { + Type string + Alias string + Sets []interface{} } // Field represents the field information @@ -65,12 +91,19 @@ func NewTableGenerator(pkg string, name string, table *ovsdb.TableSchema) Genera columnSchema := table.Columns[columnName] templateData.Fields = append(templateData.Fields, Field{ Name: FieldName(columnName), - Type: FieldType(columnSchema), + Type: FieldType(name, columnName, columnSchema), Tag: Tag(columnName), }) + if enum := FieldEnum(name, columnName, columnSchema); enum != nil { + templateData.Enums = append(templateData.Enums, *enum) + } } - tableTemplate := template.Must(template.New(name).Parse(TABLE_TEMPLATE)) + funcMap := template.FuncMap{ + "printVal": printVal, + "camelCase": camelCase, + } + tableTemplate := template.Must(template.New(name).Funcs(funcMap).Parse(TABLE_TEMPLATE)) return newGenerator(FileName(name), tableTemplate, templateData) } @@ -85,20 +118,34 @@ func StructName(tableName string) string { } // 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 strings.Title(tableName) + camelCase(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%s", strings.Title(tableName), camelCase(columnName)) + } return fmt.Sprintf("[]%s", AtomicType(column.TypeObj.Key.Type)) default: return AtomicType(column.Type) } } +func FieldEnum(tableName, columnName string, column *ovsdb.ColumnSchema) *Enum { + if column.TypeObj.Key.Enum == nil { + return nil + } + e := &Enum{} + e.Type = column.TypeObj.Key.Type + e.Alias = strings.Title(tableName) + camelCase(columnName) + e.Sets = column.TypeObj.Key.Enum + return e +} + // BasicType returns the string type of an AtomicType func AtomicType(atype string) string { switch atype { @@ -148,9 +195,13 @@ 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, } func camelCase(field string) string { @@ -183,3 +234,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 "" +} diff --git a/cmd/modelgen/table_test.go b/cmd/modelgen/table_test.go index cdcd7cb7..bc60f76e 100644 --- a/cmd/modelgen/table_test.go +++ b/cmd/modelgen/table_test.go @@ -14,7 +14,7 @@ func TestNewTableGenerator(t *testing.T) { "name": "AtomicDB", "version": "0.0.0", "tables": { - "atomicTable": { + "AtomicTable": { "columns": { "str": { "type": "string" @@ -24,7 +24,13 @@ func TestNewTableGenerator(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"]]}}} } } } @@ -35,12 +41,28 @@ func TestNewTableGenerator(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"` + "`" + ` } ` @@ -49,10 +71,11 @@ type test struct { if err != nil { t.Fatal(err) } - table := schema.Tables["atomicTable"] + fakeTable := "AtomicTable" + table := schema.Tables[fakeTable] gen := NewTableGenerator( "test", - "test", + fakeTable, &table, )