github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/jsonpath/jsonpath.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors All rights reserved. 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/kubernetes/third_party/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 39 func New(name string) *JSONPath { 40 return &JSONPath{ 41 name: name, 42 beginRange: 0, 43 inRange: 0, 44 endRange: 0, 45 } 46 } 47 48 // Parse parse the given template, return error 49 func (j *JSONPath) Parse(text string) (err error) { 50 j.parser, err = Parse(j.name, text) 51 return 52 } 53 54 // Execute bounds data into template and write the result 55 func (j *JSONPath) Execute(wr io.Writer, data interface{}) error { 56 fullResults, err := j.FindResults(data) 57 if err != nil { 58 return err 59 } 60 for ix := range fullResults { 61 if err := j.PrintResults(wr, fullResults[ix]); err != nil { 62 return err 63 } 64 } 65 return nil 66 } 67 68 func (j *JSONPath) FindResults(data interface{}) ([][]reflect.Value, error) { 69 if j.parser == nil { 70 return nil, fmt.Errorf("%s is an incomplete jsonpath template", j.name) 71 } 72 73 j.cur = []reflect.Value{reflect.ValueOf(data)} 74 nodes := j.parser.Root.Nodes 75 fullResult := [][]reflect.Value{} 76 for i := 0; i < len(nodes); i++ { 77 node := nodes[i] 78 results, err := j.walk(j.cur, node) 79 if err != nil { 80 return nil, err 81 } 82 83 //encounter an end node, break the current block 84 if j.endRange > 0 && j.endRange <= j.inRange { 85 j.endRange -= 1 86 break 87 } 88 //encounter a range node, start a range loop 89 if j.beginRange > 0 { 90 j.beginRange -= 1 91 j.inRange += 1 92 for k, value := range results { 93 j.parser.Root.Nodes = nodes[i+1:] 94 if k == len(results)-1 { 95 j.inRange -= 1 96 } 97 nextResults, err := j.FindResults(value.Interface()) 98 if err != nil { 99 return nil, err 100 } 101 fullResult = append(fullResult, nextResults...) 102 } 103 break 104 } 105 fullResult = append(fullResult, results) 106 } 107 return fullResult, nil 108 } 109 110 // PrintResults write the results into writer 111 func (j *JSONPath) PrintResults(wr io.Writer, results []reflect.Value) error { 112 for i, r := range results { 113 text, err := j.evalToText(r) 114 if err != nil { 115 return err 116 } 117 if i != len(results)-1 { 118 text = append(text, ' ') 119 } 120 if _, err = wr.Write(text); err != nil { 121 return err 122 } 123 } 124 return nil 125 } 126 127 // walk visits tree rooted at the given node in DFS order 128 func (j *JSONPath) walk(value []reflect.Value, node Node) ([]reflect.Value, error) { 129 switch node := node.(type) { 130 case *ListNode: 131 return j.evalList(value, node) 132 case *TextNode: 133 return []reflect.Value{reflect.ValueOf(node.Text)}, nil 134 case *FieldNode: 135 return j.evalField(value, node) 136 case *ArrayNode: 137 return j.evalArray(value, node) 138 case *FilterNode: 139 return j.evalFilter(value, node) 140 case *IntNode: 141 return j.evalInt(value, node) 142 case *FloatNode: 143 return j.evalFloat(value, node) 144 case *WildcardNode: 145 return j.evalWildcard(value, node) 146 case *RecursiveNode: 147 return j.evalRecursive(value, node) 148 case *UnionNode: 149 return j.evalUnion(value, node) 150 case *IdentifierNode: 151 return j.evalIdentifier(value, node) 152 default: 153 return value, fmt.Errorf("unexpected Node %v", node) 154 } 155 } 156 157 // evalInt evaluates IntNode 158 func (j *JSONPath) evalInt(input []reflect.Value, node *IntNode) ([]reflect.Value, error) { 159 result := make([]reflect.Value, len(input)) 160 for i := range input { 161 result[i] = reflect.ValueOf(node.Value) 162 } 163 return result, nil 164 } 165 166 // evalFloat evaluates FloatNode 167 func (j *JSONPath) evalFloat(input []reflect.Value, node *FloatNode) ([]reflect.Value, error) { 168 result := make([]reflect.Value, len(input)) 169 for i := range input { 170 result[i] = reflect.ValueOf(node.Value) 171 } 172 return result, nil 173 } 174 175 // evalList evaluates ListNode 176 func (j *JSONPath) evalList(value []reflect.Value, node *ListNode) ([]reflect.Value, error) { 177 var err error 178 curValue := value 179 for _, node := range node.Nodes { 180 curValue, err = j.walk(curValue, node) 181 if err != nil { 182 return curValue, err 183 } 184 } 185 return curValue, nil 186 } 187 188 // evalIdentifier evaluates IdentifierNode 189 func (j *JSONPath) evalIdentifier(input []reflect.Value, node *IdentifierNode) ([]reflect.Value, error) { 190 results := []reflect.Value{} 191 switch node.Name { 192 case "range": 193 j.stack = append(j.stack, j.cur) 194 j.beginRange += 1 195 results = input 196 case "end": 197 if j.endRange < j.inRange { //inside a loop, break the current block 198 j.endRange += 1 199 break 200 } 201 // the loop is about to end, pop value and continue the following execution 202 if len(j.stack) > 0 { 203 j.cur, j.stack = j.stack[len(j.stack)-1], j.stack[:len(j.stack)-1] 204 } else { 205 return results, fmt.Errorf("not in range, nothing to end") 206 } 207 default: 208 return input, fmt.Errorf("unrecongnized identifier %v", node.Name) 209 } 210 return results, nil 211 } 212 213 // evalArray evaluates ArrayNode 214 func (j *JSONPath) evalArray(input []reflect.Value, node *ArrayNode) ([]reflect.Value, error) { 215 result := []reflect.Value{} 216 for _, value := range input { 217 218 value, isNil := template.Indirect(value) 219 if isNil || (value.Kind() != reflect.Array && value.Kind() != reflect.Slice) { 220 return input, fmt.Errorf("%v is not array or slice", value.Type()) 221 } 222 params := node.Params 223 if !params[0].Known { 224 params[0].Value = 0 225 } 226 if params[0].Value < 0 { 227 params[0].Value += value.Len() 228 } 229 if !params[1].Known { 230 params[1].Value = value.Len() 231 } 232 233 if params[1].Value < 0 { 234 params[1].Value += value.Len() 235 } 236 237 sliceLength := value.Len() 238 if params[1].Value != params[0].Value { // if you're requesting zero elements, allow it through. 239 if params[0].Value >= sliceLength { 240 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[0].Value, sliceLength) 241 } 242 if params[1].Value > sliceLength { 243 return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[1].Value-1, sliceLength) 244 } 245 } 246 247 if !params[2].Known { 248 value = value.Slice(params[0].Value, params[1].Value) 249 } else { 250 value = value.Slice3(params[0].Value, params[1].Value, params[2].Value) 251 } 252 for i := 0; i < value.Len(); i++ { 253 result = append(result, value.Index(i)) 254 } 255 } 256 return result, nil 257 } 258 259 // evalUnion evaluates UnionNode 260 func (j *JSONPath) evalUnion(input []reflect.Value, node *UnionNode) ([]reflect.Value, error) { 261 result := []reflect.Value{} 262 for _, listNode := range node.Nodes { 263 temp, err := j.evalList(input, listNode) 264 if err != nil { 265 return input, err 266 } 267 result = append(result, temp...) 268 } 269 return result, nil 270 } 271 272 func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (reflect.Value, error) { 273 t := value.Type() 274 var inlineValue *reflect.Value 275 for ix := 0; ix < t.NumField(); ix++ { 276 f := t.Field(ix) 277 jsonTag := f.Tag.Get("json") 278 parts := strings.Split(jsonTag, ",") 279 if len(parts) == 0 { 280 continue 281 } 282 if parts[0] == node.Value { 283 return value.Field(ix), nil 284 } 285 if len(parts[0]) == 0 { 286 val := value.Field(ix) 287 inlineValue = &val 288 } 289 } 290 if inlineValue != nil { 291 if inlineValue.Kind() == reflect.Struct { 292 // handle 'inline' 293 match, err := j.findFieldInValue(inlineValue, node) 294 if err != nil { 295 return reflect.Value{}, err 296 } 297 if match.IsValid() { 298 return match, nil 299 } 300 } 301 } 302 return value.FieldByName(node.Value), nil 303 } 304 305 // evalField evaluates filed of struct or key of map. 306 func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.Value, error) { 307 results := []reflect.Value{} 308 // If there's no input, there's no output 309 if len(input) == 0 { 310 return results, nil 311 } 312 for _, value := range input { 313 var result reflect.Value 314 value, isNil := template.Indirect(value) 315 if isNil { 316 continue 317 } 318 319 if value.Kind() == reflect.Struct { 320 var err error 321 if result, err = j.findFieldInValue(&value, node); err != nil { 322 return nil, err 323 } 324 } else if value.Kind() == reflect.Map { 325 result = value.MapIndex(reflect.ValueOf(node.Value)) 326 } 327 if result.IsValid() { 328 results = append(results, result) 329 } 330 } 331 if len(results) == 0 { 332 return results, fmt.Errorf("%s is not found", node.Value) 333 } 334 return results, nil 335 } 336 337 // evalWildcard extract all contents of the given value 338 func (j *JSONPath) evalWildcard(input []reflect.Value, node *WildcardNode) ([]reflect.Value, error) { 339 results := []reflect.Value{} 340 for _, value := range input { 341 value, isNil := template.Indirect(value) 342 if isNil { 343 continue 344 } 345 346 kind := value.Kind() 347 if kind == reflect.Struct { 348 for i := 0; i < value.NumField(); i++ { 349 results = append(results, value.Field(i)) 350 } 351 } else if kind == reflect.Map { 352 for _, key := range value.MapKeys() { 353 results = append(results, value.MapIndex(key)) 354 } 355 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String { 356 for i := 0; i < value.Len(); i++ { 357 results = append(results, value.Index(i)) 358 } 359 } 360 } 361 return results, nil 362 } 363 364 // evalRecursive visit the given value recursively and push all of them to result 365 func (j *JSONPath) evalRecursive(input []reflect.Value, node *RecursiveNode) ([]reflect.Value, error) { 366 result := []reflect.Value{} 367 for _, value := range input { 368 results := []reflect.Value{} 369 value, isNil := template.Indirect(value) 370 if isNil { 371 continue 372 } 373 374 kind := value.Kind() 375 if kind == reflect.Struct { 376 for i := 0; i < value.NumField(); i++ { 377 results = append(results, value.Field(i)) 378 } 379 } else if kind == reflect.Map { 380 for _, key := range value.MapKeys() { 381 results = append(results, value.MapIndex(key)) 382 } 383 } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String { 384 for i := 0; i < value.Len(); i++ { 385 results = append(results, value.Index(i)) 386 } 387 } 388 if len(results) != 0 { 389 result = append(result, value) 390 output, err := j.evalRecursive(results, node) 391 if err != nil { 392 return result, err 393 } 394 result = append(result, output...) 395 } 396 } 397 return result, nil 398 } 399 400 // evalFilter filter array according to FilterNode 401 func (j *JSONPath) evalFilter(input []reflect.Value, node *FilterNode) ([]reflect.Value, error) { 402 results := []reflect.Value{} 403 for _, value := range input { 404 value, _ = template.Indirect(value) 405 406 if value.Kind() != reflect.Array && value.Kind() != reflect.Slice { 407 return input, fmt.Errorf("%v is not array or slice", value) 408 } 409 for i := 0; i < value.Len(); i++ { 410 temp := []reflect.Value{value.Index(i)} 411 lefts, err := j.evalList(temp, node.Left) 412 413 //case exists 414 if node.Operator == "exists" { 415 if len(lefts) > 0 { 416 results = append(results, value.Index(i)) 417 } 418 continue 419 } 420 421 if err != nil { 422 return input, err 423 } 424 425 var left, right interface{} 426 if len(lefts) != 1 { 427 return input, fmt.Errorf("can only compare one element at a time") 428 } 429 left = lefts[0].Interface() 430 431 rights, err := j.evalList(temp, node.Right) 432 if err != nil { 433 return input, err 434 } 435 if len(rights) != 1 { 436 return input, fmt.Errorf("can only compare one element at a time") 437 } 438 right = rights[0].Interface() 439 440 pass := false 441 switch node.Operator { 442 case "<": 443 pass, err = template.Less(left, right) 444 case ">": 445 pass, err = template.Greater(left, right) 446 case "==": 447 pass, err = template.Equal(left, right) 448 case "!=": 449 pass, err = template.NotEqual(left, right) 450 case "<=": 451 pass, err = template.LessEqual(left, right) 452 case ">=": 453 pass, err = template.GreaterEqual(left, right) 454 default: 455 return results, fmt.Errorf("unrecognized filter operator %s", node.Operator) 456 } 457 if err != nil { 458 return results, err 459 } 460 if pass { 461 results = append(results, value.Index(i)) 462 } 463 } 464 } 465 return results, nil 466 } 467 468 // evalToText translates reflect value to corresponding text 469 func (j *JSONPath) evalToText(v reflect.Value) ([]byte, error) { 470 iface, ok := template.PrintableValue(v) 471 if !ok { 472 return nil, fmt.Errorf("can't print type %s", v.Type()) 473 } 474 var buffer bytes.Buffer 475 fmt.Fprint(&buffer, iface) 476 return buffer.Bytes(), nil 477 }