-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmerge.go
72 lines (59 loc) · 1.69 KB
/
merge.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
package core
type MergeGroup struct {
SimpleDescriptor
createToMerge func() []Grouper
*GrouperLazyChildren[Descriptor]
}
func NewMergeGroup(desc DescriptorSpec, createToMerge func() []Grouper) (o *MergeGroup) {
o = &MergeGroup{SimpleDescriptor{desc}, createToMerge, NewGrouperLazyChildren[Descriptor](func() (merged []Descriptor, err error) {
merged, err = createChildren(o.createToMerge)
o.createToMerge = nil
return merged, err
})}
return o
}
func mergeAfter(toMerge []Grouper, target Grouper, start int) (result []Grouper) {
result = make([]Grouper, 1, len(toMerge)-start+1)
result[0] = target
name := target.Name()
for i := start; i < len(toMerge); i += 1 {
child, err := toMerge[i].GetChildByName(name)
if err == nil {
if group, ok := child.(Grouper); ok {
result = append(result, group)
}
}
}
return result
}
func createChildren(createToMerge func() []Grouper) (children []Descriptor, err error) {
toMerge := createToMerge()
children = make([]Descriptor, 0)
used := make(map[string]bool)
for i, c := range toMerge {
finished, err := c.VisitChildren(func(child Descriptor) (run bool, err error) {
name := child.Name()
if used[name] {
return true, nil
}
if group, ok := child.(Grouper); ok {
merged := mergeAfter(toMerge, group, i+1)
if len(merged) > 1 {
child = NewMergeGroup(group.DescriptorSpec(), func() []Grouper { return merged })
}
}
children = append(children, child)
used[name] = true
return true, nil
})
if err != nil {
return nil, err
}
if !finished {
return nil, err
}
}
return children, nil
}
// implemented by embedded GrouperLazyChildren & SimpleDescriptor
var _ Grouper = (*MergeGroup)(nil)