-
Notifications
You must be signed in to change notification settings - Fork 0
/
reflect.go
114 lines (106 loc) · 3.33 KB
/
reflect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package twf
import (
"fmt"
"github.com/pkg/errors"
"github.com/tochk/twf/datastruct"
"reflect"
"strconv"
"strings"
)
// getSliceElementPtrType returns pointer to slice element
func getSliceElementPtrType(slice interface{}) (reflect.Type, error) {
s := reflect.TypeOf(slice)
if s.Kind() != reflect.Slice {
return nil, fmt.Errorf("twf.getSliceElementPtrType: expected slice, got %s", s.Kind().String())
}
s = s.Elem()
if s.Kind() != reflect.Struct {
return nil, fmt.Errorf("twf.getSliceElementPtrType: slice containts %s, expected struct", s.Kind().String())
}
s = reflect.PtrTo(s)
return s, nil
}
// getFieldDescription returns information of all fields in given struct
func getFieldDescription(s reflect.Type) ([]datastruct.Field, error) {
if s.Kind() != reflect.Ptr {
return nil, fmt.Errorf("twf.getFieldDescription: expected ptr to struct, got %s", s.Kind().String())
}
if s.Elem().Kind() != reflect.Struct {
return nil, fmt.Errorf("twf.getFieldDescription: expected ptr to struct, got ptr to %s", s.Elem().Kind().String())
}
s = s.Elem()
fields := make([]datastruct.Field, 0, s.NumField())
for i := 0; i < s.NumField(); i++ {
field := datastruct.Field{
Type: "text",
}
f := s.Field(i)
switch f.Type.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
field.Type = "number"
case reflect.Bool:
field.Type = "checkbox"
}
if t, ok := f.Tag.Lookup("twf"); !ok || t == "" {
return nil, errors.New("twf tag must be present and not be empty")
}
tagContent := strings.Split(f.Tag.Get("twf"), ",")
for _, e := range tagContent {
switch {
case strings.HasPrefix(e, "fk:"):
fkInfo := strings.Split(e[3:], ";")
if len(fkInfo) != 3 {
return nil, fmt.Errorf("twf.getFieldDescription: invalid fk info {%s}, fk must be {fk_slice_index;id;name}", e[3:])
}
fkID, err := strconv.Atoi(fkInfo[0])
if err != nil {
return nil, errors.Wrap(err, "twf.getFieldDescription: can't convert fk id to int")
}
field.FkInfo = &datastruct.FkInfo{
FksIndex: fkID,
ID: fkInfo[1],
Name: fkInfo[2],
}
field.Type = "select"
case strings.HasPrefix(e, "name:"):
field.Name = e[5:]
case strings.HasPrefix(e, "type:"):
field.Type = e[5:]
case strings.HasPrefix(e, "title:"):
field.Title = e[6:]
case strings.HasPrefix(e, "value:"):
field.Value = e[6:]
case strings.HasPrefix(e, "placeholder:"):
field.Placeholder = e[12:]
case e == "no_create":
field.NoCreate = true
case e == "no_edit":
field.NoEdit = true
case e == "required":
field.Required = true
case e == "not_show_on_table":
field.NotShowOnTable = true
case e == "process_parameters":
field.ProcessParameters = true
case e == "disabled":
field.Disabled = true
default:
return nil, fmt.Errorf("twf.getFieldDescription: unexpected parameter in twf tag: %s", e)
}
}
fields = append(fields, field)
}
return fields, nil
}
// getFieldValue returns value of the field. Returns <nil> if value is nil
func getFieldValue(field reflect.Value) interface{} {
if field.Kind() == reflect.Ptr {
if field.IsNil() {
return "<nil>"
} else {
return field.Elem().Interface()
}
}
return field.Interface()
}