forked from Rheisen/bconf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfield_set.go
129 lines (101 loc) · 2.92 KB
/
field_set.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package bconf
import "fmt"
type FieldSets []*FieldSet
type FieldSet struct {
fieldMap map[string]*Field
Key string
LoadConditions LoadConditions
Fields Fields
}
func (f *FieldSet) Clone() *FieldSet {
clone := *f
if len(f.LoadConditions) > 0 {
clone.LoadConditions = make([]LoadCondition, len(f.LoadConditions))
for index, value := range f.LoadConditions {
clone.LoadConditions[index] = value.Clone()
}
}
if len(f.Fields) > 0 {
clone.Fields = make([]*Field, len(f.Fields))
for index, field := range f.Fields {
newField := *field
clone.Fields[index] = &newField
}
}
if len(f.fieldMap) > 0 {
clone.fieldMap = make(map[string]*Field, len(f.fieldMap))
for key, field := range f.fieldMap {
newField := field.Clone()
clone.fieldMap[key] = newField
}
}
return &clone
}
// validate validates the configuration of the field set.
func (f *FieldSet) validate() []error {
errs := []error{}
if f.Key == "" {
errs = append(errs, fmt.Errorf("field-set key required"))
}
if len(f.LoadConditions) > 0 {
for _, loadCondition := range f.LoadConditions {
if loadConditionErrs := loadCondition.Validate(); len(loadConditionErrs) > 0 {
for _, err := range loadConditionErrs {
errs = append(errs, fmt.Errorf("load condition validation error: %w", err))
}
}
}
}
fieldKeys := map[string]struct{}{}
if len(f.Fields) > 0 {
for _, field := range f.Fields {
if _, found := fieldKeys[field.Key]; found {
errs = append(errs, fmt.Errorf("duplicate field key found: '%s'", field.Key))
continue
}
fieldKeys[field.Key] = struct{}{}
}
}
return errs
}
// initializeFieldMap transitions the FieldSet over from its configuration []*Field to a map[string]*Field.
func (f *FieldSet) initializeFieldMap() {
fieldMap := make(map[string]*Field, len(f.Fields))
for _, field := range f.Fields {
fieldMap[field.Key] = field
}
f.fieldMap = fieldMap
}
// generateFieldDefaults runs field default generators exactly once. Multiple calls will not regenerate field defaults.
func (f *FieldSet) generateFieldDefaults() []error {
errs := []error{}
if f.fieldMap != nil {
for key, field := range f.fieldMap {
if err := field.generateDefault(); err != nil {
errs = append(errs, fmt.Errorf("field '%s' default value generation error: %w", key, err))
}
}
}
return errs
}
// validateFields validates field configuration, and can only be run after field defaults have been generated.
func (f *FieldSet) validateFields() []error {
errs := []error{}
if f.fieldMap != nil {
for key, field := range f.fieldMap {
if fieldErrs := field.validate(); len(fieldErrs) > 0 {
for _, err := range fieldErrs {
errs = append(errs, fmt.Errorf("field '%s' validation error: %w", key, err))
}
}
}
}
return errs
}
func (f *FieldSet) fieldKeys() []string {
keys := []string{}
for _, field := range f.fieldMap {
keys = append(keys, field.Key)
}
return keys
}