-
Notifications
You must be signed in to change notification settings - Fork 1
/
additionner.go
176 lines (167 loc) · 4.23 KB
/
additionner.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package scimpatch
import (
"github.com/scim2/filter-parser/v2"
)
type additionner struct{}
var additionnerInstance *additionner
func (r *additionner) Direct(scopedMap map[string]interface{}, scopedAttr string, value interface{}) (map[string]interface{}, bool) {
switch newValue := value.(type) {
case []map[string]interface{}:
oldSlice, ok := scopedMap[scopedAttr]
if !ok {
scopedMap[scopedAttr] = newValue
return scopedMap, true
}
oldMaps, ok := areEveryItemsMap(oldSlice)
if !ok {
// WARN: unexpected current value
scopedMap[scopedAttr] = newValue
return scopedMap, true
}
changed := false
for _, newMap := range newValue {
found := false
for _, oldMap := range oldMaps {
if eqMap(newMap, oldMap) {
found = true
break
}
}
if !found {
oldMaps = append(oldMaps, newMap)
changed = true
}
}
if changed {
scopedMap[scopedAttr] = oldMaps
}
return scopedMap, changed
case map[string]interface{}:
oldMap, ok := scopedMap[scopedAttr].(map[string]interface{})
if ok {
changed := false
scopedMap[scopedAttr], changed = mergeMap(oldMap, newValue)
return scopedMap, changed
}
scopedMap[scopedAttr] = value
return scopedMap, true
case []interface{}:
oldSlice, ok := scopedMap[scopedAttr].([]interface{})
if !ok {
scopedMap[scopedAttr] = newValue
return scopedMap, true
}
changed := false
if oldMaps, ok := areEveryItemsMap(oldSlice); ok {
if newMaps, ok := areEveryItemsMap(newValue); ok {
for _, newMap := range newMaps {
found := false
for _, oldMap := range oldMaps {
if eqMap(newMap, oldMap) {
found = true
break
}
}
if !found {
oldMaps = append(oldMaps, newMap)
changed = true
}
}
if changed {
scopedMap[scopedAttr] = oldMaps
}
return scopedMap, changed
}
} else {
for _, newItem := range newValue {
found := false
for _, oldItem := range oldSlice {
if newItem == oldItem {
found = true
break
}
}
if !found {
changed = true
oldSlice = append(oldSlice, newItem)
}
}
if changed {
scopedMap[scopedAttr] = oldSlice
}
}
return scopedMap, changed
case interface{}:
if oldValue, ok := scopedMap[scopedAttr]; !ok || oldValue != newValue {
scopedMap[scopedAttr] = value
return scopedMap, true
}
}
return scopedMap, false
}
func (r *additionner) ByValueForItem(scopedSlice []interface{}, value interface{}) ([]interface{}, bool) {
changed := false
found := false
for _, oldValue := range scopedSlice {
if oldValue == value {
found = true
break
}
}
if !found {
changed = true
scopedSlice = append(scopedSlice, value)
}
return scopedSlice, changed
}
func (r *additionner) ByValueExpressionForItem(scopedMaps []map[string]interface{}, expr filter.Expression, value interface{}) ([]map[string]interface{}, bool) {
switch newValue := value.(type) {
case map[string]interface{}:
changed := false
newValues := []map[string]interface{}{}
for _, oldValue := range scopedMaps {
if !isMatchExpression(oldValue, expr) {
newValues = append(newValues, oldValue)
} else {
if !eqMap(oldValue, newValue) {
var merger map[string]interface{}
merger, changed = mergeMap(oldValue, newValue)
newValues = append(newValues, merger)
} else {
newValues = append(newValues, oldValue)
}
}
}
return newValues, changed
default:
// unexpected input
return scopedMaps, false
}
}
func (r *additionner) ByValueExpressionForAttribute(scopedMaps []map[string]interface{}, expr filter.Expression, subAttr string, value interface{}) ([]map[string]interface{}, bool) {
changed := false
newValues := []map[string]interface{}{}
found := false
for _, oldValue := range scopedMaps {
if !isMatchExpression(oldValue, expr) {
newValues = append(newValues, oldValue)
} else {
found = true
oldAttrValue, ok := oldValue[subAttr]
if !ok || oldAttrValue != value {
changed = true
oldValue[subAttr] = value
newValues = append(newValues, oldValue)
} else {
newValues = append(newValues, oldValue)
}
}
}
if !found {
changed = true
newMap := toMap(expr)
newMap[subAttr] = value
newValues = append(newValues, newMap)
}
return newValues, changed
}