Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / k8s.io / client-go / util / jsonpath / jsonpath.go
1 /*
2 Copyright 2015 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 package jsonpath
18
19 import (
20         "bytes"
21         "fmt"
22         "io"
23         "reflect"
24         "strings"
25
26         "k8s.io/client-go/third_party/forked/golang/template"
27 )
28
29 type JSONPath struct {
30         name       string
31         parser     *Parser
32         stack      [][]reflect.Value // push and pop values in different scopes
33         cur        []reflect.Value   // current scope values
34         beginRange int
35         inRange    int
36         endRange   int
37
38         allowMissingKeys bool
39 }
40
41 // New creates a new JSONPath with the given name.
42 func New(name string) *JSONPath {
43         return &JSONPath{
44                 name:       name,
45                 beginRange: 0,
46                 inRange:    0,
47                 endRange:   0,
48         }
49 }
50
51 // AllowMissingKeys allows a caller to specify whether they want an error if a field or map key
52 // cannot be located, or simply an empty result. The receiver is returned for chaining.
53 func (j *JSONPath) AllowMissingKeys(allow bool) *JSONPath {
54         j.allowMissingKeys = allow
55         return j
56 }
57
58 // Parse parses the given template and returns an error.
59 func (j *JSONPath) Parse(text string) error {
60         var err error
61         j.parser, err = Parse(j.name, text)
62         return err
63 }
64
65 // Execute bounds data into template and writes the result.
66 func (j *JSONPath) Execute(wr io.Writer, data interface{}) error {
67         fullResults, err := j.FindResults(data)
68         if err != nil {
69                 return err
70         }
71         for ix := range fullResults {
72                 if err := j.PrintResults(wr, fullResults[ix]); err != nil {
73                         return err
74                 }
75         }
76         return nil
77 }
78
79 func (j *JSONPath) FindResults(data interface{}) ([][]reflect.Value, error) {
80         if j.parser == nil {
81                 return nil, fmt.Errorf("%s is an incomplete jsonpath template", j.name)
82         }
83
84         j.cur = []reflect.Value{reflect.ValueOf(data)}
85         nodes := j.parser.Root.Nodes
86         fullResult := [][]reflect.Value{}
87         for i := 0; i < len(nodes); i++ {
88                 node := nodes[i]
89                 results, err := j.walk(j.cur, node)
90                 if err != nil {
91                         return nil, err
92                 }
93
94                 // encounter an end node, break the current block
95                 if j.endRange > 0 && j.endRange <= j.inRange {
96                         j.endRange -= 1
97                         break
98                 }
99                 // encounter a range node, start a range loop
100                 if j.beginRange > 0 {
101                         j.beginRange -= 1
102                         j.inRange += 1
103                         for k, value := range results {
104                                 j.parser.Root.Nodes = nodes[i+1:]
105                                 if k == len(results)-1 {
106                                         j.inRange -= 1
107                                 }
108                                 nextResults, err := j.FindResults(value.Interface())
109                                 if err != nil {
110                                         return nil, err
111                                 }
112                                 fullResult = append(fullResult, nextResults...)
113                         }
114                         break
115                 }
116                 fullResult = append(fullResult, results)
117         }
118         return fullResult, nil
119 }
120
121 // PrintResults writes the results into writer
122 func (j *JSONPath) PrintResults(wr io.Writer, results []reflect.Value) error {
123         for i, r := range results {
124                 text, err := j.evalToText(r)
125                 if err != nil {
126                         return err
127                 }
128                 if i != len(results)-1 {
129                         text = append(text, ' ')
130                 }
131                 if _, err = wr.Write(text); err != nil {
132                         return err
133                 }
134         }
135         return nil
136 }
137
138 // walk visits tree rooted at the given node in DFS order
139 func (j *JSONPath) walk(value []reflect.Value, node Node) ([]reflect.Value, error) {
140         switch node := node.(type) {
141         case *ListNode:
142                 return j.evalList(value, node)
143         case *TextNode:
144                 return []reflect.Value{reflect.ValueOf(node.Text)}, nil
145         case *FieldNode:
146                 return j.evalField(value, node)
147         case *ArrayNode:
148                 return j.evalArray(value, node)
149         case *FilterNode:
150                 return j.evalFilter(value, node)
151         case *IntNode:
152                 return j.evalInt(value, node)
153         case *BoolNode:
154                 return j.evalBool(value, node)
155         case *FloatNode:
156                 return j.evalFloat(value, node)
157         case *WildcardNode:
158                 return j.evalWildcard(value, node)
159         case *RecursiveNode:
160                 return j.evalRecursive(value, node)
161         case *UnionNode:
162                 return j.evalUnion(value, node)
163         case *IdentifierNode:
164                 return j.evalIdentifier(value, node)
165         default:
166                 return value, fmt.Errorf("unexpected Node %v", node)
167         }
168 }
169
170 // evalInt evaluates IntNode
171 func (j *JSONPath) evalInt(input []reflect.Value, node *IntNode) ([]reflect.Value, error) {
172         result := make([]reflect.Value, len(input))
173         for i := range input {
174                 result[i] = reflect.ValueOf(node.Value)
175         }
176         return result, nil
177 }
178
179 // evalFloat evaluates FloatNode
180 func (j *JSONPath) evalFloat(input []reflect.Value, node *FloatNode) ([]reflect.Value, error) {
181         result := make([]reflect.Value, len(input))
182         for i := range input {
183                 result[i] = reflect.ValueOf(node.Value)
184         }
185         return result, nil
186 }
187
188 // evalBool evaluates BoolNode
189 func (j *JSONPath) evalBool(input []reflect.Value, node *BoolNode) ([]reflect.Value, error) {
190         result := make([]reflect.Value, len(input))
191         for i := range input {
192                 result[i] = reflect.ValueOf(node.Value)
193         }
194         return result, nil
195 }
196
197 // evalList evaluates ListNode
198 func (j *JSONPath) evalList(value []reflect.Value, node *ListNode) ([]reflect.Value, error) {
199         var err error
200         curValue := value
201         for _, node := range node.Nodes {
202                 curValue, err = j.walk(curValue, node)
203                 if err != nil {
204                         return curValue, err
205                 }
206         }
207         return curValue, nil
208 }
209
210 // evalIdentifier evaluates IdentifierNode
211 func (j *JSONPath) evalIdentifier(input []reflect.Value, node *IdentifierNode) ([]reflect.Value, error) {
212         results := []reflect.Value{}
213         switch node.Name {
214         case "range":
215                 j.stack = append(j.stack, j.cur)
216                 j.beginRange += 1
217                 results = input
218         case "end":
219                 if j.endRange < j.inRange { // inside a loop, break the current block
220                         j.endRange += 1
221                         break
222                 }
223                 // the loop is about to end, pop value and continue the following execution
224                 if len(j.stack) > 0 {
225                         j.cur, j.stack = j.stack[len(j.stack)-1], j.stack[:len(j.stack)-1]
226                 } else {
227                         return results, fmt.Errorf("not in range, nothing to end")
228                 }
229         default:
230                 return input, fmt.Errorf("unrecognized identifier %v", node.Name)
231         }
232         return results, nil
233 }
234
235 // evalArray evaluates ArrayNode
236 func (j *JSONPath) evalArray(input []reflect.Value, node *ArrayNode) ([]reflect.Value, error) {
237         result := []reflect.Value{}
238         for _, value := range input {
239
240                 value, isNil := template.Indirect(value)
241                 if isNil {
242                         continue
243                 }
244                 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice {
245                         return input, fmt.Errorf("%v is not array or slice", value.Type())
246                 }
247                 params := node.Params
248                 if !params[0].Known {
249                         params[0].Value = 0
250                 }
251                 if params[0].Value < 0 {
252                         params[0].Value += value.Len()
253                 }
254                 if !params[1].Known {
255                         params[1].Value = value.Len()
256                 }
257
258                 if params[1].Value < 0 {
259                         params[1].Value += value.Len()
260                 }
261
262                 sliceLength := value.Len()
263                 if params[1].Value != params[0].Value { // if you're requesting zero elements, allow it through.
264                         if params[0].Value >= sliceLength || params[0].Value < 0 {
265                                 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[0].Value, sliceLength)
266                         }
267                         if params[1].Value > sliceLength || params[1].Value < 0 {
268                                 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[1].Value-1, sliceLength)
269                         }
270                 }
271
272                 if !params[2].Known {
273                         value = value.Slice(params[0].Value, params[1].Value)
274                 } else {
275                         value = value.Slice3(params[0].Value, params[1].Value, params[2].Value)
276                 }
277                 for i := 0; i < value.Len(); i++ {
278                         result = append(result, value.Index(i))
279                 }
280         }
281         return result, nil
282 }
283
284 // evalUnion evaluates UnionNode
285 func (j *JSONPath) evalUnion(input []reflect.Value, node *UnionNode) ([]reflect.Value, error) {
286         result := []reflect.Value{}
287         for _, listNode := range node.Nodes {
288                 temp, err := j.evalList(input, listNode)
289                 if err != nil {
290                         return input, err
291                 }
292                 result = append(result, temp...)
293         }
294         return result, nil
295 }
296
297 func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (reflect.Value, error) {
298         t := value.Type()
299         var inlineValue *reflect.Value
300         for ix := 0; ix < t.NumField(); ix++ {
301                 f := t.Field(ix)
302                 jsonTag := f.Tag.Get("json")
303                 parts := strings.Split(jsonTag, ",")
304                 if len(parts) == 0 {
305                         continue
306                 }
307                 if parts[0] == node.Value {
308                         return value.Field(ix), nil
309                 }
310                 if len(parts[0]) == 0 {
311                         val := value.Field(ix)
312                         inlineValue = &val
313                 }
314         }
315         if inlineValue != nil {
316                 if inlineValue.Kind() == reflect.Struct {
317                         // handle 'inline'
318                         match, err := j.findFieldInValue(inlineValue, node)
319                         if err != nil {
320                                 return reflect.Value{}, err
321                         }
322                         if match.IsValid() {
323                                 return match, nil
324                         }
325                 }
326         }
327         return value.FieldByName(node.Value), nil
328 }
329
330 // evalField evaluates field of struct or key of map.
331 func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.Value, error) {
332         results := []reflect.Value{}
333         // If there's no input, there's no output
334         if len(input) == 0 {
335                 return results, nil
336         }
337         for _, value := range input {
338                 var result reflect.Value
339                 value, isNil := template.Indirect(value)
340                 if isNil {
341                         continue
342                 }
343
344                 if value.Kind() == reflect.Struct {
345                         var err error
346                         if result, err = j.findFieldInValue(&value, node); err != nil {
347                                 return nil, err
348                         }
349                 } else if value.Kind() == reflect.Map {
350                         mapKeyType := value.Type().Key()
351                         nodeValue := reflect.ValueOf(node.Value)
352                         // node value type must be convertible to map key type
353                         if !nodeValue.Type().ConvertibleTo(mapKeyType) {
354                                 return results, fmt.Errorf("%s is not convertible to %s", nodeValue, mapKeyType)
355                         }
356                         result = value.MapIndex(nodeValue.Convert(mapKeyType))
357                 }
358                 if result.IsValid() {
359                         results = append(results, result)
360                 }
361         }
362         if len(results) == 0 {
363                 if j.allowMissingKeys {
364                         return results, nil
365                 }
366                 return results, fmt.Errorf("%s is not found", node.Value)
367         }
368         return results, nil
369 }
370
371 // evalWildcard extracts all contents of the given value
372 func (j *JSONPath) evalWildcard(input []reflect.Value, node *WildcardNode) ([]reflect.Value, error) {
373         results := []reflect.Value{}
374         for _, value := range input {
375                 value, isNil := template.Indirect(value)
376                 if isNil {
377                         continue
378                 }
379
380                 kind := value.Kind()
381                 if kind == reflect.Struct {
382                         for i := 0; i < value.NumField(); i++ {
383                                 results = append(results, value.Field(i))
384                         }
385                 } else if kind == reflect.Map {
386                         for _, key := range value.MapKeys() {
387                                 results = append(results, value.MapIndex(key))
388                         }
389                 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String {
390                         for i := 0; i < value.Len(); i++ {
391                                 results = append(results, value.Index(i))
392                         }
393                 }
394         }
395         return results, nil
396 }
397
398 // evalRecursive visits the given value recursively and pushes all of them to result
399 func (j *JSONPath) evalRecursive(input []reflect.Value, node *RecursiveNode) ([]reflect.Value, error) {
400         result := []reflect.Value{}
401         for _, value := range input {
402                 results := []reflect.Value{}
403                 value, isNil := template.Indirect(value)
404                 if isNil {
405                         continue
406                 }
407
408                 kind := value.Kind()
409                 if kind == reflect.Struct {
410                         for i := 0; i < value.NumField(); i++ {
411                                 results = append(results, value.Field(i))
412                         }
413                 } else if kind == reflect.Map {
414                         for _, key := range value.MapKeys() {
415                                 results = append(results, value.MapIndex(key))
416                         }
417                 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String {
418                         for i := 0; i < value.Len(); i++ {
419                                 results = append(results, value.Index(i))
420                         }
421                 }
422                 if len(results) != 0 {
423                         result = append(result, value)
424                         output, err := j.evalRecursive(results, node)
425                         if err != nil {
426                                 return result, err
427                         }
428                         result = append(result, output...)
429                 }
430         }
431         return result, nil
432 }
433
434 // evalFilter filters array according to FilterNode
435 func (j *JSONPath) evalFilter(input []reflect.Value, node *FilterNode) ([]reflect.Value, error) {
436         results := []reflect.Value{}
437         for _, value := range input {
438                 value, _ = template.Indirect(value)
439
440                 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice {
441                         return input, fmt.Errorf("%v is not array or slice and cannot be filtered", value)
442                 }
443                 for i := 0; i < value.Len(); i++ {
444                         temp := []reflect.Value{value.Index(i)}
445                         lefts, err := j.evalList(temp, node.Left)
446
447                         //case exists
448                         if node.Operator == "exists" {
449                                 if len(lefts) > 0 {
450                                         results = append(results, value.Index(i))
451                                 }
452                                 continue
453                         }
454
455                         if err != nil {
456                                 return input, err
457                         }
458
459                         var left, right interface{}
460                         switch {
461                         case len(lefts) == 0:
462                                 continue
463                         case len(lefts) > 1:
464                                 return input, fmt.Errorf("can only compare one element at a time")
465                         }
466                         left = lefts[0].Interface()
467
468                         rights, err := j.evalList(temp, node.Right)
469                         if err != nil {
470                                 return input, err
471                         }
472                         switch {
473                         case len(rights) == 0:
474                                 continue
475                         case len(rights) > 1:
476                                 return input, fmt.Errorf("can only compare one element at a time")
477                         }
478                         right = rights[0].Interface()
479
480                         pass := false
481                         switch node.Operator {
482                         case "<":
483                                 pass, err = template.Less(left, right)
484                         case ">":
485                                 pass, err = template.Greater(left, right)
486                         case "==":
487                                 pass, err = template.Equal(left, right)
488                         case "!=":
489                                 pass, err = template.NotEqual(left, right)
490                         case "<=":
491                                 pass, err = template.LessEqual(left, right)
492                         case ">=":
493                                 pass, err = template.GreaterEqual(left, right)
494                         default:
495                                 return results, fmt.Errorf("unrecognized filter operator %s", node.Operator)
496                         }
497                         if err != nil {
498                                 return results, err
499                         }
500                         if pass {
501                                 results = append(results, value.Index(i))
502                         }
503                 }
504         }
505         return results, nil
506 }
507
508 // evalToText translates reflect value to corresponding text
509 func (j *JSONPath) evalToText(v reflect.Value) ([]byte, error) {
510         iface, ok := template.PrintableValue(v)
511         if !ok {
512                 return nil, fmt.Errorf("can't print type %s", v.Type())
513         }
514         var buffer bytes.Buffer
515         fmt.Fprint(&buffer, iface)
516         return buffer.Bytes(), nil
517 }