@@ -138,51 +138,51 @@ func (s *Set) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.TypeRef)
138
138
}
139
139
}
140
140
141
- // MustPrefixPattern is the same as PrefixPattern except it panics if parts can't be
142
- // turned into a SetPattern .
143
- func MustPrefixPattern (parts ... interface {}) * SetPattern {
144
- result , err := PrefixPattern (parts ... )
141
+ // MakePrefixMatcherOrDie is the same as PrefixMatcher except it panics if parts can't be
142
+ // turned into a SetMatcher .
143
+ func MakePrefixMatcherOrDie (parts ... interface {}) * SetMatcher {
144
+ result , err := PrefixMatcher (parts ... )
145
145
if err != nil {
146
146
panic (err )
147
147
}
148
148
return result
149
149
}
150
150
151
- // PrefixPattern creates a SetPattern that matches all field paths prefixed by the given list of pattern path parts.
151
+ // PrefixMatcher creates a SetMatcher that matches all field paths prefixed by the given list of pattern path parts.
152
152
// The pattern parts may any of:
153
153
//
154
- // - PathPattern - for wildcards, `MatchAnyPathElement()` can be used as well.
154
+ // - PathElementMatcher - for wildcards, `MatchAnyPathElement()` can be used as well.
155
155
// - PathElement - for any path element
156
156
// - value.FieldList - for associative list keys
157
157
// - value.Value - for scalar list elements
158
158
// - string - For field names
159
159
// - int - for array indices
160
- func PrefixPattern (parts ... interface {}) (* SetPattern , error ) {
161
- current := MatchAnySet () // match all field patch suffixes
160
+ func PrefixMatcher (parts ... interface {}) (* SetMatcher , error ) {
161
+ current := MatchAnySet () // match all field path suffixes
162
162
for i := len (parts ) - 1 ; i >= 0 ; i -- {
163
163
part := parts [i ]
164
- var pattern PathPattern
164
+ var pattern PathElementMatcher
165
165
switch t := part .(type ) {
166
- case PathPattern :
166
+ case PathElementMatcher :
167
167
pattern = t
168
168
case PathElement :
169
- pattern = PathPattern {PathElement : t }
169
+ pattern = PathElementMatcher {PathElement : t }
170
170
case * value.FieldList :
171
171
if len (* t ) == 0 {
172
172
return nil , fmt .Errorf ("associative list key type path elements must have at least one key (got zero)" )
173
173
}
174
- pattern = PathPattern {PathElement : PathElement {Key : t }}
174
+ pattern = PathElementMatcher {PathElement : PathElement {Key : t }}
175
175
case value.Value :
176
- pattern = PathPattern {PathElement : PathElement {Value : & t }}
176
+ pattern = PathElementMatcher {PathElement : PathElement {Value : & t }}
177
177
case string :
178
- pattern = PathPattern {PathElement : PathElement {FieldName : & t }}
178
+ pattern = PathElementMatcher {PathElement : PathElement {FieldName : & t }}
179
179
case int :
180
- pattern = PathPattern {PathElement : PathElement {Index : & t }}
180
+ pattern = PathElementMatcher {PathElement : PathElement {Index : & t }}
181
181
default :
182
182
return nil , fmt .Errorf ("unexpected type %T" , t )
183
183
}
184
- current = & SetPattern {
185
- Members : []* MemberSetPattern {{
184
+ current = & SetMatcher {
185
+ Members : []* SetMemberMatcher {{
186
186
Path : pattern ,
187
187
Child : current ,
188
188
}},
@@ -191,43 +191,80 @@ func PrefixPattern(parts ...interface{}) (*SetPattern, error) {
191
191
return current , nil
192
192
}
193
193
194
- // MatchAnyPathElement returns a PathPattern that matches any path element.
195
- func MatchAnyPathElement () PathPattern {
196
- return PathPattern {Wildcard : true }
194
+ // MatchAnyPathElement returns a PathElementMatcher that matches any path element.
195
+ func MatchAnyPathElement () PathElementMatcher {
196
+ return PathElementMatcher {Wildcard : true }
197
197
}
198
198
199
- // MatchAnySet returns a SetPattern that matches any set.
200
- func MatchAnySet () * SetPattern {
201
- return & SetPattern {Wildcard : true }
199
+ // MatchAnySet returns a SetMatcher that matches any set.
200
+ func MatchAnySet () * SetMatcher {
201
+ return & SetMatcher {Wildcard : true }
202
202
}
203
203
204
- // SetPattern defines a pattern that matches fields in a Set.
205
- // SetPattern is structured much like a Set but with wildcard support.
206
- type SetPattern struct {
204
+ // SetMatcher defines a pattern that matches fields in a Set.
205
+ // SetMatcher is structured much like a Set but with wildcard support.
206
+ type SetMatcher struct {
207
207
// Wildcard indicates that all members and children are included in the match.
208
208
// If set, the Members field is ignored.
209
209
Wildcard bool
210
210
// Members provides patterns to match the members of a Set.
211
- Members []* MemberSetPattern
211
+ Members []* SetMemberMatcher
212
+ }
213
+
214
+ // Merge merges two SetMatchers into a single SetMatcher that matches the field paths of both SetMatchers.
215
+ // During the merge, Members of s2 with the same PathElementMatcher as a member of s are merged into the member of s.
216
+ // All other members of s2 are appended to the resulting member list in their original relative order.
217
+ // When members are merged, the child SetMatchers are merged by calling this function recursively.
218
+ func (s * SetMatcher ) Merge (s2 * SetMatcher ) * SetMatcher {
219
+ if s .Wildcard || s2 .Wildcard {
220
+ return & SetMatcher {Wildcard : true }
221
+ }
222
+
223
+ // TODO: Optimize. This is O(n^2). In practice, usually a single member is being inserted at a time,
224
+ // but that's still O(n). Sorting would help a ton.
225
+ var unionedMembers []* SetMemberMatcher
226
+ for _ , m := range s .Members {
227
+ for _ , m2 := range s2 .Members {
228
+ if m .Path .PathElement .Equals (m2 .Path .PathElement ) && m .Path .Wildcard == m2 .Path .Wildcard {
229
+ unionedMembers = append (unionedMembers , & SetMemberMatcher {
230
+ Path : m .Path ,
231
+ Child : m .Child .Merge (m2 .Child ),
232
+ })
233
+ } else {
234
+ unionedMembers = append (unionedMembers , m )
235
+ }
236
+ }
237
+ }
238
+ for _ , m2 := range s2 .Members {
239
+ for _ , existing := range unionedMembers {
240
+ if ! m2 .Path .PathElement .Equals (existing .Path .PathElement ) {
241
+ unionedMembers = append (unionedMembers , m2 )
242
+ }
243
+ }
244
+ }
245
+
246
+ return & SetMatcher {
247
+ Members : unionedMembers ,
248
+ }
212
249
}
213
250
214
- // MemberSetPattern defines a pattern that matches the members of a Set.
215
- // MemberSetPattern is structured much like the elements of a SetNodeMap, but
251
+ // SetMemberMatcher defines a pattern that matches the members of a Set.
252
+ // SetMemberMatcher is structured much like the elements of a SetNodeMap, but
216
253
// with wildcard support.
217
- type MemberSetPattern struct {
254
+ type SetMemberMatcher struct {
218
255
// Path provides a pattern to match members of a Set.
219
256
// If Path is a wildcard, all members of a Set are included in the match.
220
257
// Otherwise, if any Path is Equal to a member of a Set, that member is
221
258
// included in the match and the children of that member are matched
222
259
// against the Child pattern.
223
- Path PathPattern
260
+ Path PathElementMatcher
224
261
225
262
// Child provides a pattern to use for the children of matched members of a Set.
226
- Child * SetPattern
263
+ Child * SetMatcher
227
264
}
228
265
229
- // PathPattern defined a match pattern for a PathElement.
230
- type PathPattern struct {
266
+ // PathElementMatcher defined a match pattern for a PathElement.
267
+ type PathElementMatcher struct {
231
268
// Wildcard indicates that all PathElements are matched by this pattern.
232
269
// If set, PathElement is ignored.
233
270
Wildcard bool
@@ -237,8 +274,8 @@ type PathPattern struct {
237
274
PathElement
238
275
}
239
276
240
- // FilterByPattern returns a Set with only the field paths that match the pattern .
241
- func (s * Set ) FilterByPattern (pattern * SetPattern ) * Set {
277
+ // FilterIncludeMatches returns a Set with only the field paths that match.
278
+ func (s * Set ) FilterIncludeMatches (pattern * SetMatcher ) * Set {
242
279
if pattern .Wildcard {
243
280
return s
244
281
}
@@ -254,7 +291,7 @@ func (s *Set) FilterByPattern(pattern *SetPattern) *Set {
254
291
}
255
292
return & Set {
256
293
Members : members ,
257
- Children : * s .Children .FilterByPattern (pattern ),
294
+ Children : * s .Children .FilterIncludeMatches (pattern ),
258
295
}
259
296
}
260
297
@@ -598,8 +635,8 @@ func (s *SetNodeMap) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.Ty
598
635
}
599
636
}
600
637
601
- // FilterByPattern returns a SetNodeMap with only the field paths that match the pattern.
602
- func (s * SetNodeMap ) FilterByPattern (pattern * SetPattern ) * SetNodeMap {
638
+ // FilterIncludeMatches returns a SetNodeMap with only the field paths that match the pattern.
639
+ func (s * SetNodeMap ) FilterIncludeMatches (pattern * SetMatcher ) * SetNodeMap {
603
640
if pattern .Wildcard {
604
641
return s
605
642
}
@@ -608,7 +645,7 @@ func (s *SetNodeMap) FilterByPattern(pattern *SetPattern) *SetNodeMap {
608
645
for _ , member := range s .members {
609
646
for _ , c := range pattern .Members {
610
647
if c .Path .Wildcard || c .Path .PathElement .Equals (member .pathElement ) {
611
- childSet := member .set .FilterByPattern (c .Child )
648
+ childSet := member .set .FilterIncludeMatches (c .Child )
612
649
if childSet .Size () > 0 {
613
650
out = append (out , setNode {
614
651
pathElement : member .pathElement ,
@@ -654,23 +691,23 @@ func (s *SetNodeMap) Leaves() *SetNodeMap {
654
691
}
655
692
656
693
// Filter defines an interface for excluding field paths from a set.
657
- // NewExcludeFilter can be used to create a filter that removes
658
- // excluded field paths.
659
- // NewPatternFilter can be used to create a filter that removes all fields except
660
- // the fields that match a field path pattern. PrefixPattern and MustPrefixPattern
694
+ // NewExcludeSetFilter can be used to create a filter that removes
695
+ // specific field paths and all of their children .
696
+ // NewIncludeMatcherFilter can be used to create a filter that removes all fields except
697
+ // the fields that match a field path pattern. PrefixMatcher and MakePrefixMatcherOrDie
661
698
// can be used to define field path patterns.
662
699
type Filter interface {
663
700
// Filter returns a filtered copy of the set.
664
701
Filter (* Set ) * Set
665
702
}
666
703
667
- // NewExcludeFilter returns a filter that removes field paths in the exclude set.
668
- func NewExcludeFilter (exclude * Set ) Filter {
704
+ // NewExcludeSetFilter returns a filter that removes field paths in the exclude set.
705
+ func NewExcludeSetFilter (exclude * Set ) Filter {
669
706
return excludeFilter {exclude }
670
707
}
671
708
672
- // NewExcludeFilterMap converts a map of APIVersion to exclude set to a map of APIVersion to exclude filters.
673
- func NewExcludeFilterMap (resetFields map [APIVersion ]* Set ) map [APIVersion ]Filter {
709
+ // NewExcludeFilterSetMap converts a map of APIVersion to exclude set to a map of APIVersion to exclude filters.
710
+ func NewExcludeFilterSetMap (resetFields map [APIVersion ]* Set ) map [APIVersion ]Filter {
674
711
result := make (map [APIVersion ]Filter )
675
712
for k , v := range resetFields {
676
713
result [k ] = excludeFilter {v }
@@ -686,16 +723,24 @@ func (t excludeFilter) Filter(set *Set) *Set {
686
723
return set .RecursiveDifference (t .excludeSet )
687
724
}
688
725
689
- // NewPatternFilter returns a filter that only includes field paths that match the pattern.
690
- // PrefixPattern and MustPrefixPattern can help create basic SetPatterns.
691
- func NewPatternFilter (pattern * SetPattern ) Filter {
692
- return patternFilter {pattern }
726
+ // NewIncludeMatcherFilter returns a filter that only includes field paths that match the pattern.
727
+ // PrefixMatcher and MakePrefixMatcherOrDie can help create basic SetPatterns.
728
+ func NewIncludeMatcherFilter (patterns ... * SetMatcher ) Filter {
729
+ if len (patterns ) == 0 {
730
+ return includeMatcherFilter {& SetMatcher {Wildcard : true }}
731
+ }
732
+ pattern := patterns [0 ]
733
+ for i := 1 ; i < len (patterns ); i ++ {
734
+ pattern = pattern .Merge (patterns [i ])
735
+ }
736
+
737
+ return includeMatcherFilter {pattern }
693
738
}
694
739
695
- type patternFilter struct {
696
- pattern * SetPattern
740
+ type includeMatcherFilter struct {
741
+ pattern * SetMatcher
697
742
}
698
743
699
- func (pf patternFilter ) Filter (set * Set ) * Set {
700
- return set .FilterByPattern (pf .pattern )
744
+ func (pf includeMatcherFilter ) Filter (set * Set ) * Set {
745
+ return set .FilterIncludeMatches (pf .pattern )
701
746
}
0 commit comments