github.com/tomwright/dasel@v1.27.3/node_query_multiple.go (about) 1 package dasel 2 3 import ( 4 "fmt" 5 "reflect" 6 ) 7 8 // QueryMultiple uses the given selector to query the current node for every match 9 // possible and returns all of the end nodes. 10 func (n *Node) QueryMultiple(selector string) ([]*Node, error) { 11 n.Selector.Remaining = selector 12 13 if err := buildFindMultipleChain(n); err != nil { 14 return nil, err 15 } 16 17 return lastNodes(n), nil 18 } 19 20 // lastNodes returns a list of all of the last nodes. 21 func lastNodes(n *Node) []*Node { 22 if len(n.NextMultiple) == 0 { 23 return []*Node{n} 24 } 25 var res []*Node 26 for _, nextNode := range n.NextMultiple { 27 res = append(res, lastNodes(nextNode)...) 28 } 29 return res 30 } 31 32 func buildFindMultipleChain(n *Node) error { 33 if isFinalSelector(n.Selector.Remaining) { 34 // We've reached the end 35 return nil 36 } 37 38 var err error 39 40 // Parse the selector. 41 nextSelector, err := ParseSelector(n.Selector.Remaining) 42 if err != nil { 43 return fmt.Errorf("failed to parse selector: %w", err) 44 } 45 46 // Populate the value for the new node. 47 n.NextMultiple, err = findNodes(nextSelector, n, false) 48 if err != nil { 49 return fmt.Errorf("could not find multiple value: %w", err) 50 } 51 52 for _, next := range n.NextMultiple { 53 // Add the back reference 54 if next.Previous == nil { 55 // This can already be set in some cases - SEARCH. 56 next.Previous = n 57 } 58 59 if err := buildFindMultipleChain(next); err != nil { 60 return err 61 } 62 } 63 64 return nil 65 } 66 67 func findNodesPropertyWork(selector Selector, previousValue reflect.Value, createIfNotExists bool, value reflect.Value) ([]*Node, error) { 68 switch value.Kind() { 69 case reflect.Map: 70 node := &Node{ 71 Value: nilValue(), 72 Selector: selector, 73 } 74 for _, key := range value.MapKeys() { 75 if fmt.Sprint(key.Interface()) == selector.Property { 76 node.Value = value.MapIndex(key) 77 return []*Node{node}, nil 78 } 79 } 80 if createIfNotExists { 81 return []*Node{node}, nil 82 } 83 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 84 85 case reflect.Struct: 86 node := &Node{ 87 Value: nilValue(), 88 Selector: selector, 89 } 90 fieldV := value.FieldByName(selector.Property) 91 if fieldV.IsValid() { 92 node.Value = fieldV 93 return []*Node{node}, nil 94 } 95 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 96 97 case reflect.Ptr: 98 return findNodesPropertyWork(selector, previousValue, createIfNotExists, derefValue(value)) 99 } 100 101 return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value} 102 } 103 104 // findNodesProperty finds the value for the given node using the property selector 105 // information. 106 func findNodesProperty(selector Selector, previousValue reflect.Value, createIfNotExists bool) ([]*Node, error) { 107 if !isValid(previousValue) { 108 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 109 } 110 111 if selector.Property == "-" { 112 res, err := findNodesPropertyKeys(selector, previousValue, createIfNotExists) 113 return res, err 114 } 115 116 return findNodesPropertyWork(selector, previousValue, createIfNotExists, unwrapValue(previousValue)) 117 } 118 119 func findNodesPropertyKeysWork(selector Selector, previousValue reflect.Value, createIfNotExists bool, value reflect.Value) ([]*Node, error) { 120 results := make([]*Node, 0) 121 122 switch value.Kind() { 123 case reflect.Slice: 124 for i := 0; i < value.Len(); i++ { 125 sel := selector.Copy() 126 sel.Type = "INDEX" 127 sel.Index = i 128 results = append(results, &Node{ 129 Value: reflect.ValueOf(fmt.Sprint(i)), 130 Selector: sel, 131 }) 132 } 133 return results, nil 134 135 case reflect.Map: 136 for _, key := range value.MapKeys() { 137 sel := selector.Copy() 138 sel.Type = "PROPERTY" 139 sel.Property = key.String() 140 results = append(results, &Node{ 141 Value: reflect.ValueOf(key.String()), 142 Selector: sel, 143 }) 144 } 145 return results, nil 146 147 case reflect.Struct: 148 valueType := value.Type() 149 for i := 0; i < value.NumField(); i++ { 150 field := valueType.Field(i) 151 sel := selector.Copy() 152 sel.Type = "PROPERTY" 153 sel.Property = field.Name 154 results = append(results, &Node{ 155 Value: reflect.ValueOf(field.Name), 156 Selector: sel, 157 }) 158 } 159 return results, nil 160 161 case reflect.Ptr: 162 return findNodesPropertyKeysWork(selector, previousValue, createIfNotExists, derefValue(value)) 163 } 164 165 return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value} 166 } 167 168 func findNodesPropertyKeys(selector Selector, previousValue reflect.Value, createIfNotExists bool) ([]*Node, error) { 169 if !isValid(previousValue) { 170 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 171 } 172 if createIfNotExists { 173 return nil, &UnsupportedSelector{Selector: selector.Raw} 174 } 175 return findNodesPropertyKeysWork(selector, previousValue, createIfNotExists, unwrapValue(previousValue)) 176 } 177 178 // findNodesIndex finds the value for the given node using the index selector 179 // information. 180 func findNodesIndex(selector Selector, previousValue reflect.Value, createIfNotExists bool) ([]*Node, error) { 181 if !isValid(previousValue) { 182 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 183 } 184 185 value := unwrapValue(previousValue) 186 187 if value.Kind() == reflect.Slice { 188 node := &Node{ 189 Value: nilValue(), 190 Selector: selector, 191 } 192 valueLen := value.Len() 193 if selector.Index >= 0 && selector.Index < valueLen { 194 node.Value = value.Index(selector.Index) 195 return []*Node{node}, nil 196 } 197 if createIfNotExists { 198 return []*Node{node}, nil 199 } 200 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 201 } 202 203 return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value} 204 } 205 206 // findNextAvailableIndexNodes finds the value for the given node using the index selector 207 // information. 208 func findNextAvailableIndexNodes(selector Selector, previousValue reflect.Value, createIfNotExists bool) ([]*Node, error) { 209 if !createIfNotExists { 210 // Next available index isn't supported unless it's creating the item. 211 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 212 } 213 return []*Node{ 214 { 215 Value: nilValue(), 216 Selector: selector, 217 }, 218 }, nil 219 } 220 221 // processFindDynamicItems is used by findNodesDynamic. 222 func processFindDynamicItems(selector Selector, object reflect.Value, key string) (bool, error) { 223 // Loop through each condition. 224 allConditionsMatched := true 225 for _, c := range selector.Conditions { 226 // If the object doesn't match any checks, return a ValueNotFound. 227 228 var found bool 229 var err error 230 switch cond := c.(type) { 231 case *KeyEqualCondition: 232 found, err = cond.Check(reflect.ValueOf(key)) 233 default: 234 found, err = cond.Check(object) 235 } 236 237 if err != nil { 238 return false, err 239 } 240 if !found { 241 allConditionsMatched = false 242 break 243 } 244 } 245 if allConditionsMatched { 246 return true, nil 247 } 248 return false, nil 249 } 250 251 func findNodesDynamicWork(selector Selector, previousValue reflect.Value, createIfNotExists bool, value reflect.Value) ([]*Node, error) { 252 switch value.Kind() { 253 case reflect.Slice: 254 results := make([]*Node, 0) 255 for i := 0; i < value.Len(); i++ { 256 object := value.Index(i) 257 found, err := processFindDynamicItems(selector, object, fmt.Sprint(i)) 258 if err != nil { 259 return nil, err 260 } 261 if found { 262 selector.Type = "INDEX" 263 selector.Index = i 264 results = append(results, &Node{ 265 Value: object, 266 Selector: selector, 267 }) 268 } 269 } 270 if len(results) > 0 { 271 return results, nil 272 } 273 if createIfNotExists { 274 selector.Type = "NEXT_AVAILABLE_INDEX" 275 return []*Node{ 276 { 277 Value: nilValue(), 278 Selector: selector, 279 }, 280 }, nil 281 } 282 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 283 284 case reflect.Map: 285 results := make([]*Node, 0) 286 for _, key := range value.MapKeys() { 287 object := value.MapIndex(key) 288 found, err := processFindDynamicItems(selector, object, key.String()) 289 if err != nil { 290 return nil, err 291 } 292 if found { 293 selector.Type = "PROPERTY" 294 selector.Property = key.String() 295 results = append(results, &Node{ 296 Value: object, 297 Selector: selector, 298 }) 299 } 300 } 301 if len(results) > 0 { 302 return results, nil 303 } 304 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 305 306 case reflect.Struct: 307 results := make([]*Node, 0) 308 valueType := value.Type() 309 for i := 0; i < value.NumField(); i++ { 310 field := valueType.Field(i) 311 object := value.Field(i) 312 found, err := processFindDynamicItems(selector, object, field.Name) 313 if err != nil { 314 return nil, err 315 } 316 if found { 317 selector.Type = "PROPERTY" 318 selector.Property = field.Name 319 results = append(results, &Node{ 320 Value: object, 321 Selector: selector, 322 }) 323 } 324 } 325 if len(results) > 0 { 326 return results, nil 327 } 328 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 329 330 case reflect.Ptr: 331 return findNodesDynamicWork(selector, previousValue, createIfNotExists, derefValue(value)) 332 } 333 334 return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value} 335 } 336 337 // findNodesDynamic finds the value for the given node using the dynamic selector 338 // information. 339 func findNodesDynamic(selector Selector, previousValue reflect.Value, createIfNotExists bool) ([]*Node, error) { 340 if !isValid(previousValue) { 341 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 342 } 343 return findNodesDynamicWork(selector, previousValue, createIfNotExists, unwrapValue(previousValue)) 344 } 345 346 func findNodesSearchRecursiveSubNode(selector Selector, subNode *Node, key string, createIfNotExists bool) ([]*Node, error) { 347 subResults, err := findNodesSearchRecursive(selector, subNode, createIfNotExists, false) 348 if err != nil { 349 return nil, fmt.Errorf("could not find nodes search recursive: %w", err) 350 } 351 352 // Loop through each condition. 353 allConditionsMatched := true 354 sliceConditionLoop: 355 for _, c := range selector.Conditions { 356 var found bool 357 var err error 358 359 switch cond := c.(type) { 360 case *KeyEqualCondition: 361 found, err = cond.Check(reflect.ValueOf(key)) 362 default: 363 found, err = cond.Check(subNode.Value) 364 } 365 if err != nil || !found { 366 allConditionsMatched = false 367 break sliceConditionLoop 368 } 369 } 370 371 results := make([]*Node, 0) 372 373 if allConditionsMatched { 374 results = append(results, subNode) 375 } 376 if len(subResults) > 0 { 377 results = append(results, subResults...) 378 } 379 380 return results, nil 381 } 382 383 func findNodesSearchRecursiveWork(selector Selector, previousNode *Node, createIfNotExists bool, firstNode bool, value reflect.Value) ([]*Node, error) { 384 results := make([]*Node, 0) 385 386 switch value.Kind() { 387 case reflect.Slice: 388 for i := 0; i < value.Len(); i++ { 389 object := value.Index(i) 390 391 subNode := &Node{ 392 Previous: previousNode, 393 Value: object, 394 Selector: selector.Copy(), 395 } 396 subNode.Selector.Type = "INDEX" 397 subNode.Selector.Index = i 398 399 newResults, err := findNodesSearchRecursiveSubNode(selector, subNode, fmt.Sprint(subNode.Selector.Index), createIfNotExists) 400 if err != nil { 401 return nil, err 402 } 403 results = append(results, newResults...) 404 } 405 406 case reflect.Map: 407 for _, key := range value.MapKeys() { 408 object := value.MapIndex(key) 409 410 subNode := &Node{ 411 Previous: previousNode, 412 Value: object, 413 Selector: selector.Copy(), 414 } 415 subNode.Selector.Type = "PROPERTY" 416 subNode.Selector.Property = fmt.Sprint(key.Interface()) 417 418 newResults, err := findNodesSearchRecursiveSubNode(selector, subNode, subNode.Selector.Property, createIfNotExists) 419 if err != nil { 420 return nil, err 421 } 422 results = append(results, newResults...) 423 } 424 425 case reflect.Struct: 426 valueType := value.Type() 427 for i := 0; i < value.NumField(); i++ { 428 field := valueType.Field(i) 429 object := value.Field(i) 430 431 subNode := &Node{ 432 Previous: previousNode, 433 Value: object, 434 Selector: selector.Copy(), 435 } 436 subNode.Selector.Type = "PROPERTY" 437 subNode.Selector.Property = field.Name 438 439 newResults, err := findNodesSearchRecursiveSubNode(selector, subNode, subNode.Selector.Property, createIfNotExists) 440 if err != nil { 441 return nil, err 442 } 443 results = append(results, newResults...) 444 } 445 446 case reflect.Ptr: 447 return findNodesSearchRecursiveWork(selector, previousNode, createIfNotExists, firstNode, derefValue(value)) 448 } 449 450 return results, nil 451 } 452 453 // findNodesSearchRecursive iterates through the value of the previous node and creates a new node for each element. 454 // If any of those nodes match the checks they are returned. 455 func findNodesSearchRecursive(selector Selector, previousNode *Node, createIfNotExists bool, firstNode bool) ([]*Node, error) { 456 if !isValid(previousNode.Value) { 457 if selector.Type != "SEARCH_OPTIONAL" { 458 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 459 } 460 } 461 return findNodesSearchRecursiveWork(selector, previousNode, createIfNotExists, firstNode, unwrapValue(previousNode.Value)) 462 } 463 464 // findNodesSearch finds all available nodes by recursively searching the previous value. 465 func findNodesSearch(selector Selector, previousNode *Node, createIfNotExists bool) ([]*Node, error) { 466 res, err := findNodesSearchRecursive(selector, previousNode, createIfNotExists, true) 467 if err != nil { 468 return nil, err 469 } 470 if len(res) == 0 { 471 return nil, &ValueNotFound{ 472 Selector: selector.Current, 473 PreviousValue: previousNode.Value, 474 } 475 } 476 return res, nil 477 } 478 479 func findNodesAnyIndexWork(selector Selector, previousValue reflect.Value, value reflect.Value) ([]*Node, error) { 480 switch value.Kind() { 481 case reflect.Slice: 482 results := make([]*Node, 0) 483 for i := 0; i < value.Len(); i++ { 484 object := value.Index(i) 485 selector.Type = "INDEX" 486 selector.Index = i 487 results = append(results, &Node{ 488 Value: object, 489 Selector: selector, 490 }) 491 } 492 if len(results) > 0 { 493 return results, nil 494 } 495 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 496 497 case reflect.Map: 498 results := make([]*Node, 0) 499 for _, key := range value.MapKeys() { 500 object := value.MapIndex(key) 501 selector.Type = "PROPERTY" 502 selector.Property = key.String() 503 results = append(results, &Node{ 504 Value: object, 505 Selector: selector, 506 }) 507 } 508 if len(results) > 0 { 509 return results, nil 510 } 511 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 512 513 case reflect.Struct: 514 valueType := value.Type() 515 results := make([]*Node, 0) 516 for i := 0; i < valueType.NumField(); i++ { 517 field := valueType.Field(i) 518 object := value.Field(i) 519 selector.Type = "PROPERTY" 520 selector.Property = field.Name 521 results = append(results, &Node{ 522 Value: object, 523 Selector: selector, 524 }) 525 } 526 if len(results) > 0 { 527 return results, nil 528 } 529 return nil, &ValueNotFound{Selector: selector.Current, PreviousValue: previousValue} 530 531 case reflect.Ptr: 532 return findNodesAnyIndexWork(selector, previousValue, derefValue(previousValue)) 533 } 534 535 return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value} 536 } 537 538 // findNodesAnyIndex returns a node for every value in the previous value list. 539 func findNodesAnyIndex(selector Selector, previousValue reflect.Value) ([]*Node, error) { 540 if !isValid(previousValue) { 541 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 542 } 543 return findNodesAnyIndexWork(selector, previousValue, unwrapValue(previousValue)) 544 } 545 546 func findNodesLengthWork(selector Selector, previousValue reflect.Value, value reflect.Value) ([]*Node, error) { 547 switch value.Kind() { 548 case reflect.Slice: 549 node := &Node{ 550 Value: reflect.ValueOf(value.Len()), 551 Selector: selector, 552 } 553 return []*Node{node}, nil 554 555 case reflect.Map: 556 node := &Node{ 557 Value: reflect.ValueOf(value.Len()), 558 Selector: selector, 559 } 560 return []*Node{node}, nil 561 562 case reflect.String: 563 node := &Node{ 564 Value: reflect.ValueOf(value.Len()), 565 Selector: selector, 566 } 567 return []*Node{node}, nil 568 569 case reflect.Struct: 570 node := &Node{ 571 Value: reflect.ValueOf(value.NumField()), 572 Selector: selector, 573 } 574 return []*Node{node}, nil 575 576 case reflect.Ptr: 577 return findNodesLengthWork(selector, previousValue, derefValue(value)) 578 } 579 580 return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value} 581 } 582 583 // findNodesLength returns the length 584 func findNodesLength(selector Selector, previousValue reflect.Value) ([]*Node, error) { 585 if !isValid(previousValue) { 586 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 587 } 588 return findNodesLengthWork(selector, previousValue, unwrapValue(previousValue)) 589 } 590 591 func findNodesTypeWork(selector Selector, value reflect.Value) ([]*Node, error) { 592 switch value.Kind() { 593 case reflect.Slice: 594 node := &Node{ 595 Value: reflect.ValueOf("array"), 596 Selector: selector, 597 } 598 return []*Node{node}, nil 599 600 case reflect.Map: 601 node := &Node{ 602 Value: reflect.ValueOf("map"), 603 Selector: selector, 604 } 605 return []*Node{node}, nil 606 607 case reflect.String: 608 node := &Node{ 609 Value: reflect.ValueOf("string"), 610 Selector: selector, 611 } 612 return []*Node{node}, nil 613 614 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 615 node := &Node{ 616 Value: reflect.ValueOf("int"), 617 Selector: selector, 618 } 619 return []*Node{node}, nil 620 621 case reflect.Float32, reflect.Float64: 622 node := &Node{ 623 Value: reflect.ValueOf("float"), 624 Selector: selector, 625 } 626 return []*Node{node}, nil 627 628 case reflect.Bool: 629 node := &Node{ 630 Value: reflect.ValueOf("bool"), 631 Selector: selector, 632 } 633 return []*Node{node}, nil 634 635 case reflect.Struct: 636 node := &Node{ 637 Value: reflect.ValueOf("struct"), 638 Selector: selector, 639 } 640 return []*Node{node}, nil 641 642 case reflect.Ptr: 643 return findNodesTypeWork(selector, derefValue(value)) 644 } 645 646 return nil, &UnsupportedTypeForSelector{Selector: selector, Value: value} 647 } 648 649 // findNodesType returns the type 650 func findNodesType(selector Selector, previousValue reflect.Value) ([]*Node, error) { 651 if !isValid(previousValue) { 652 return nil, &UnexpectedPreviousNilValue{Selector: selector.Raw} 653 } 654 return findNodesTypeWork(selector, unwrapValue(previousValue)) 655 } 656 657 func initialiseEmptyValue(selector Selector, previousValue reflect.Value) reflect.Value { 658 switch selector.Type { 659 case "PROPERTY": 660 return reflect.ValueOf(map[string]interface{}{}) 661 case "INDEX", "NEXT_AVAILABLE_INDEX", "INDEX_ANY", "DYNAMIC": 662 return reflect.ValueOf([]interface{}{}) 663 } 664 return previousValue 665 } 666 667 // findNodes returns all of the nodes from the previous value that match the given selector. 668 func findNodes(selector Selector, previousNode *Node, createIfNotExists bool) ([]*Node, error) { 669 if createIfNotExists && !isValid(previousNode.Value) { 670 previousNode.Value = initialiseEmptyValue(selector, previousNode.Value) 671 } 672 673 var res []*Node 674 var err error 675 676 switch selector.Type { 677 case "PROPERTY": 678 res, err = findNodesProperty(selector, previousNode.Value, createIfNotExists) 679 case "INDEX": 680 res, err = findNodesIndex(selector, previousNode.Value, createIfNotExists) 681 case "NEXT_AVAILABLE_INDEX": 682 res, err = findNextAvailableIndexNodes(selector, previousNode.Value, createIfNotExists) 683 case "INDEX_ANY": 684 res, err = findNodesAnyIndex(selector, previousNode.Value) 685 case "LENGTH": 686 res, err = findNodesLength(selector, previousNode.Value) 687 case "TYPE": 688 res, err = findNodesType(selector, previousNode.Value) 689 case "DYNAMIC": 690 res, err = findNodesDynamic(selector, previousNode.Value, createIfNotExists) 691 case "SEARCH": 692 res, err = findNodesSearch(selector, previousNode, createIfNotExists) 693 case "SEARCH_OPTIONAL": 694 res, err = findNodesSearch(selector, previousNode, createIfNotExists) 695 default: 696 err = &UnsupportedSelector{Selector: selector.Raw} 697 } 698 699 if err != nil { 700 return nil, err 701 } 702 703 return res, nil 704 }