Class: UdatCollection
Overview
Class of UDAT objects holding an ordered or unordered collection of values (where each value can optionally have a key associated with it). Keys and values of collections are always UDAT objects too. UdatCollection’s can be interpreted as maps, arrays, sets or any other non-scalar data structure.
Note: Keys and values are always implicitly casted by all instance methods of this class to Udat objects using Object#to_udat.
Defined Under Namespace
Classes: UdatUnorderedWrapper
Constant Summary
Constants inherited from Udat
Udat::ExampleDocument, Udat::KeepTag
Instance Attribute Summary
Attributes inherited from Udat
Instance Method Summary collapse
-
#<<(value) ⇒ Object
Behaves differently depending on the type of the argument.
- #==(other) ⇒ Object
-
#[](key) ⇒ Object
Behaves differently depending on the type of the argument.
-
#[]=(key, value) ⇒ Object
Same as UdatCollection#set_value_for_key.
-
#append_pair(key, value) ⇒ Object
Appends a new key with a new value.
-
#append_value(value) ⇒ Object
Appends a new value.
-
#clear ⇒ Object
Empties the collection.
-
#concat(other) ⇒ Object
Appends the values (and corresponding keys) of another UdatCollection.
-
#delete_at(index) ⇒ Object
Deletes the entry at the given numeric index.
-
#delete_key(key) ⇒ Object
Deletes all entries with a given key.
-
#delete_value(value) ⇒ Object
Deletes all entries with a given value.
-
#each_index ⇒ Object
Calls a given block for each numeric index.
-
#empty? ⇒ Boolean
Returns true, if the collection is empty.
-
#encoded_content ⇒ Object
Returns the encoded form of the content as a string.
-
#fetch(*args) ⇒ Object
Same as UdatCollection#[], but raises an error, if no value was found.
-
#fetch_collection(*args) ⇒ Object
Same as UdatCollection#fetch, but raises an error, if the value is not an UdatCollection.
-
#fetch_scalar(*args) ⇒ Object
Same as UdatCollection#fetch, but raises an error, if the value is not an UdatScalar.
-
#first ⇒ Object
Returns the first value of the collection, or nil if empty.
-
#initialize(tag, content) ⇒ UdatCollection
constructor
Creates a new Udat object with a given tag (which may be nil) and a given content, represented by a nested Array structure.
-
#inspect ⇒ Object
Same as Udat#inspect, but in case of unordered collections it prepends “udat-unordered” instead of just “udat”.
-
#key_by_index(index) ⇒ Object
Returns the key at a numeric index, or nil, if the index is out of bounds or at the given index there is only a value without key.
-
#key_by_value(value) ⇒ Object
Returns the last key having a given value.
-
#key_value_pairs ⇒ Object
Returns an Array containing the key/value pairs each as an Array of size 2.
-
#keys ⇒ Object
Returns an Array containing all keys of the collection.
-
#keys_by_value(value) ⇒ Object
Returns an Array of keys having a given value.
-
#last ⇒ Object
Returns the last value of the collection, or nil if empty.
-
#length ⇒ Object
(also: #size)
Returns the number of values in the collection.
-
#ordered ⇒ Object
Same as UdatCollection#ordered?.
-
#ordered! ⇒ Object
Same as UdatCollection#ordered = true, but returns self.
-
#ordered=(ordered) ⇒ Object
If set to false, the order of the contents of this collection will be ignored for comparisons.
-
#ordered? ⇒ Boolean
Returns false, if the order of the contents of this collection is to be ignored for comparisons.
-
#rehash ⇒ Object
Deletes the internal index hashes.
-
#replace(other) ⇒ Object
Replaces the values (and corresponding keys) with the values/keys of another UdatCollection.
-
#set_key_for_value(key, value) ⇒ Object
Deletes all values or key/value pairs where the given value matches, and appends a new key/value pair.
-
#set_value_for_key(key, value) ⇒ Object
Deletes all key/value pairs where the given key matches, and appends a new key/value pair.
-
#to_ary ⇒ Object
Same as UdatCollection#values.
-
#to_hash ⇒ Object
Returns a hash, where each key is mapped to the respective value.
-
#unordered! ⇒ Object
Same as UdatCollection#ordered = false, but returns self.
-
#unordered? ⇒ Boolean
Returns true, if the order of the contents of this collection is to be ignored for comparisons.
-
#value_by_index(index) ⇒ Object
Returns the value at a numeric index, or nil, if the index is out of bounds.
-
#value_by_key(key) ⇒ Object
Returns the last value having a given key.
-
#values ⇒ Object
(also: #to_a)
Returns an Array containing all values of the collection.
-
#values_by_key(key) ⇒ Object
Returns an Array of values having a given key.
Methods inherited from Udat
#collection?, #encode, #eql?, escape_string, #hash, parse, read_from_stream, #scalar?, #to_s, #to_udat, #write_to_stream
Constructor Details
#initialize(tag, content) ⇒ UdatCollection
Creates a new Udat object with a given tag (which may be nil) and a given content, represented by a nested Array structure. See the source code for details. It is not recommended to use this method. Use Object#to_udat instead.
457 458 459 460 461 462 463 |
# File 'lib/udat.rb', line 457 def initialize(tag, content) super tag @ordered = true @entries = [] require_index_hashes content.to_ary.each { |entry| self << entry } end |
Instance Method Details
#<<(value) ⇒ Object
Behaves differently depending on the type of the argument. If the argument is an Array with 2 elements, a new key/value pair is added, with the key being the first element of the array, and the value being the second argument of the array. Arrays with any other number of elements cause an error. If the argument is not an array, then it is added as a value without a key.
610 611 612 613 614 615 616 617 618 619 620 |
# File 'lib/udat.rb', line 610 def <<(value) if value.kind_of? Array unless value.length == 2 raise ArgumentError, "#{value.length} array elements found where 2 were expected." end return append_pair(value[0], value[1]) else return append_value(value) end end |
#==(other) ⇒ Object
900 901 902 903 904 905 906 907 908 |
# File 'lib/udat.rb', line 900 def ==(other) return false unless self.class == other.class if self.unordered? or other.unordered? return UdatUnorderedWrapper.new(self) == UdatUnorderedWrapper.new(other) else return super end end |
#[](key) ⇒ Object
Behaves differently depending on the type of the argument. If the argument is an Integer the method behaves same as UdatCollection#value_by_index. Otherwise the method behaves same as UdatCollection#value_by_key.
695 696 697 698 699 700 701 |
# File 'lib/udat.rb', line 695 def [](key) if key.kind_of? Integer return value_by_index(key) else return value_by_key(key) end end |
#[]=(key, value) ⇒ Object
Same as UdatCollection#set_value_for_key.
622 623 624 |
# File 'lib/udat.rb', line 622 def []=(key, value) set_value_for_key(key, value) end |
#append_pair(key, value) ⇒ Object
Appends a new key with a new value.
571 572 573 574 575 576 577 578 579 580 |
# File 'lib/udat.rb', line 571 def append_pair(key, value) key = key.to_udat value = value.to_udat synchronize do index = @entries.length @entries << [key, value] add_to_index_hashes(index, key, value) unless index_hashes_void? end return self end |
#append_value(value) ⇒ Object
Appends a new value.
582 583 584 585 586 587 588 |
# File 'lib/udat.rb', line 582 def append_value(value) value = value.to_udat synchronize do @entries << [nil, value] end return self end |
#clear ⇒ Object
Empties the collection.
533 534 535 536 537 538 539 540 |
# File 'lib/udat.rb', line 533 def clear synchronize do @entries.clear rehash require_index_hashes end return self end |
#concat(other) ⇒ Object
Appends the values (and corresponding keys) of another UdatCollection.
812 813 814 815 816 817 818 819 820 821 822 823 |
# File 'lib/udat.rb', line 812 def concat(other) synchronize do other.key_value_pairs.each do |key, value| if key.nil? append_value(value) else append_pair(key, value) end end end return self end |
#delete_at(index) ⇒ Object
Deletes the entry at the given numeric index. Returns the value, or nil if the index is out of bounds.
543 544 545 546 547 548 549 550 |
# File 'lib/udat.rb', line 543 def delete_at(index) index = index.to_int synchronize do key_value_pair = @entries.delete_at(index) rehash return key_value_pair ? key_value_pair[0] : nil end end |
#delete_key(key) ⇒ Object
Deletes all entries with a given key.
552 553 554 555 556 557 558 559 |
# File 'lib/udat.rb', line 552 def delete_key(key) key = key.to_udat synchronize do @entries.delete_if { |e_key, e_value| e_key == key } rehash end return self end |
#delete_value(value) ⇒ Object
Deletes all entries with a given value.
561 562 563 564 565 566 567 568 |
# File 'lib/udat.rb', line 561 def delete_value(value) value = value.to_udat synchronize do @entries.delete_if { |e_key, e_value| e_value == value } rehash end return self end |
#each_index ⇒ Object
Calls a given block for each numeric index.
764 765 766 767 768 769 |
# File 'lib/udat.rb', line 764 def each_index synchronize do (0...length).each { |i| yield i } end return self end |
#empty? ⇒ Boolean
Returns true, if the collection is empty.
760 761 762 |
# File 'lib/udat.rb', line 760 def empty? length == 0 end |
#encoded_content ⇒ Object
Returns the encoded form of the content as a string. This method is used by Udat#encode, which returns the complete encoding of the data (including the tag).
837 838 839 840 841 842 843 844 845 846 847 848 849 850 |
# File 'lib/udat.rb', line 837 def encoded_content synchronize do return ( @entries.empty? ? "~" : @entries.collect do |key, value| if key "<#{key.encode}>[#{value.encode}]" else "[#{value.encode}]" end end.join ) end end |
#fetch(*args) ⇒ Object
Same as UdatCollection#[], but raises an error, if no value was found. If an additional second argument is passed, an error will also be raised if the tag (i.e. type) of the value is not equal to the second argument.
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 |
# File 'lib/udat.rb', line 706 def fetch(*args) if args.length == 1 value = self[args[0]] unless value raise IndexError, "Value for the given key or index not found." end return value elsif args.length == 2 value = fetch(args[0]) unless value.tag == args[1] raise UdatTagMismatch, "UDAT tag mismatch." end return value else raise ArgumentError, "Wrong number of arguments supplied." end end |
#fetch_collection(*args) ⇒ Object
Same as UdatCollection#fetch, but raises an error, if the value is not an UdatCollection.
725 726 727 728 729 730 731 732 |
# File 'lib/udat.rb', line 725 def fetch_collection(*args) value = fetch(*args) if value.scalar? raise UdatTypeMismatch, "Scalar value found, where a collection was expected." end return value end |
#fetch_scalar(*args) ⇒ Object
Same as UdatCollection#fetch, but raises an error, if the value is not an UdatScalar.
735 736 737 738 739 740 741 742 |
# File 'lib/udat.rb', line 735 def fetch_scalar(*args) value = fetch(*args) if value.collection? raise UdatTypeMismatch, "Collection found, where a scalar value was expected." end return value end |
#first ⇒ Object
Returns the first value of the collection, or nil if empty.
744 745 746 |
# File 'lib/udat.rb', line 744 def first self[0] end |
#inspect ⇒ Object
Same as Udat#inspect, but in case of unordered collections it prepends “udat-unordered” instead of just “udat”.
892 893 894 895 896 897 898 |
# File 'lib/udat.rb', line 892 def inspect if ordered? return super else "udat-unordered{#{self.encode}}" end end |
#key_by_index(index) ⇒ Object
Returns the key at a numeric index, or nil, if the index is out of bounds or at the given index there is only a value without key.
628 629 630 631 632 633 634 |
# File 'lib/udat.rb', line 628 def key_by_index(index) index = index.to_int synchronize do entry = @entries[index] return entry ? entry[0] : nil end end |
#key_by_value(value) ⇒ Object
Returns the last key having a given value.
687 688 689 |
# File 'lib/udat.rb', line 687 def key_by_value(value) keys_by_value(value).last end |
#key_value_pairs ⇒ Object
Returns an Array containing the key/value pairs each as an Array of size 2. If there is no key, the first element of the sub Array is nil.
773 774 775 776 777 |
# File 'lib/udat.rb', line 773 def key_value_pairs synchronize do return @entries.collect { |entry| entry.dup } end end |
#keys ⇒ Object
Returns an Array containing all keys of the collection.
779 780 781 782 783 784 785 786 |
# File 'lib/udat.rb', line 779 def keys keys = nil synchronize do keys = @entries.collect { |key, value| key } end keys.compact! return keys end |
#keys_by_value(value) ⇒ Object
Returns an Array of keys having a given value.
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 |
# File 'lib/udat.rb', line 664 def keys_by_value(value) value = value.to_udat synchronize do require_index_hashes if value.kind_of? UdatCollection and value.unordered? indicies = @all_unordered_value_indicies[ UdatUnorderedWrapper.new(value) ] || [] else indicies = (value_indicies[key] || []) + ( @unordered_value_indicies[UdatUnorderedWrapper.new(value)] || [] ) indicies.uniq! indicies.sort! end return indicies.collect { |index| @entries[index][0] } end end |
#last ⇒ Object
Returns the last value of the collection, or nil if empty.
748 749 750 |
# File 'lib/udat.rb', line 748 def last self[-1] end |
#length ⇒ Object Also known as: size
Returns the number of values in the collection.
753 754 755 756 757 |
# File 'lib/udat.rb', line 753 def length synchronize do @entries.length end end |
#ordered ⇒ Object
Same as UdatCollection#ordered?.
853 854 855 856 857 |
# File 'lib/udat.rb', line 853 def ordered synchronize do return @ordered end end |
#ordered! ⇒ Object
Same as UdatCollection#ordered = true, but returns self.
885 886 887 888 |
# File 'lib/udat.rb', line 885 def ordered! self.ordered = true return self end |
#ordered=(ordered) ⇒ Object
If set to false, the order of the contents of this collection will be ignored for comparisons.
870 871 872 873 874 875 876 877 878 |
# File 'lib/udat.rb', line 870 def ordered=(ordered) synchronize do if ordered == false @ordered = false else @ordered = true end end end |
#ordered? ⇒ Boolean
Returns false, if the order of the contents of this collection is to be ignored for comparisons.
860 861 862 |
# File 'lib/udat.rb', line 860 def ordered? self.ordered end |
#rehash ⇒ Object
Deletes the internal index hashes. They are automatically reconstructed once a lookup is done. This method should be called by the user, if contained Udat objects have changed, AFTER being added to this collection (similar to Hash#rehash).
470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/udat.rb', line 470 def rehash synchronize do @key_indicies = nil @value_indicies = nil @unordered_key_indicies = nil @unordered_value_indicies = nil @all_unordered_key_indicies = nil @all_unordered_value_indicies = nil end return self end |
#replace(other) ⇒ Object
Replaces the values (and corresponding keys) with the values/keys of another UdatCollection.
826 827 828 829 830 831 832 |
# File 'lib/udat.rb', line 826 def replace(other) synchronize do clear concat(other) end return self end |
#set_key_for_value(key, value) ⇒ Object
Deletes all values or key/value pairs where the given value matches, and appends a new key/value pair.
598 599 600 601 602 |
# File 'lib/udat.rb', line 598 def set_key_for_value(key, value) delete_value(value) append_pair(key, value) return self end |
#set_value_for_key(key, value) ⇒ Object
Deletes all key/value pairs where the given key matches, and appends a new key/value pair.
591 592 593 594 595 |
# File 'lib/udat.rb', line 591 def set_value_for_key(key, value) delete_key(key) append_pair(key, value) return self end |
#to_ary ⇒ Object
Same as UdatCollection#values.
806 807 808 |
# File 'lib/udat.rb', line 806 def to_ary values end |
#to_hash ⇒ Object
Returns a hash, where each key is mapped to the respective value.
795 796 797 798 799 800 801 802 803 804 |
# File 'lib/udat.rb', line 795 def to_hash hash = {} synchronize do @entries.each do |key, value| next if key.nil? hash[key] = value unless hash.has_key? key end end return hash end |
#unordered! ⇒ Object
Same as UdatCollection#ordered = false, but returns self.
880 881 882 883 |
# File 'lib/udat.rb', line 880 def unordered! self.ordered = false return self end |
#unordered? ⇒ Boolean
Returns true, if the order of the contents of this collection is to be ignored for comparisons.
865 866 867 |
# File 'lib/udat.rb', line 865 def unordered? not self.ordered end |
#value_by_index(index) ⇒ Object
Returns the value at a numeric index, or nil, if the index is out of bounds.
637 638 639 640 641 642 643 |
# File 'lib/udat.rb', line 637 def value_by_index(index) index = index.to_int synchronize do entry = @entries[index] return entry ? entry[1] : nil end end |
#value_by_key(key) ⇒ Object
Returns the last value having a given key.
683 684 685 |
# File 'lib/udat.rb', line 683 def value_by_key(key) values_by_key(key).last end |
#values ⇒ Object Also known as: to_a
Returns an Array containing all values of the collection.
788 789 790 791 792 |
# File 'lib/udat.rb', line 788 def values synchronize do return @entries.collect { |key, value| value } end end |
#values_by_key(key) ⇒ Object
Returns an Array of values having a given key.
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'lib/udat.rb', line 645 def values_by_key(key) key = key.to_udat synchronize do require_index_hashes if key.kind_of? UdatCollection and key.unordered? indicies = @all_unordered_key_indicies[ UdatUnorderedWrapper.new(key) ] || [] else indicies = (@key_indicies[key] || []) + ( @unordered_key_indicies[UdatUnorderedWrapper.new(key)] || [] ) indicies.uniq! indicies.sort! end return indicies.collect { |index| @entries[index][1] } end end |