Class: Udat::Collection
Overview
Class of Udat::Node’s 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::Node’s too. Udat::Collection’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::Node’s using Object#to_udat.
Defined Under Namespace
Classes: UnorderedWrapper
Instance Attribute Summary
Attributes inherited from Node
Instance Method Summary collapse
-
#<<(value) ⇒ Object
Behaves differently depending on the type of the argument.
-
#==(other) ⇒ Object
Returns true, if class, tag and content are matching another object.
-
#[](key) ⇒ Object
Behaves differently depending on the type of the argument.
-
#[]=(key, value) ⇒ Object
Same as Udat::Collection#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.
-
#collection? ⇒ Boolean
Returns true.
-
#concat(other) ⇒ Object
Appends the values (and corresponding keys) of another Udat::Collection and returns self.
-
#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.
-
#encode_content ⇒ Object
Returns the encoded form of the content as a string.
-
#fetch(key, tag = AnyTag) ⇒ Object
Same as Udat::Collection#[], but raises an Udat::UdatIndexError, if no value was found.
-
#fetch_collection(key, tag = AnyTag) ⇒ Object
Same as Udat::Collection#fetch, but raises an error, if the value is not an Udat::Collection.
-
#fetch_scalar(key, tag = AnyTag) ⇒ Object
Same as Udat::Collection#fetch, but raises an error, if the value is not an Udat::Scalar.
-
#first ⇒ Object
Returns the first value of the collection, or nil if empty.
-
#include?(value) ⇒ Boolean
Returns true, if the value is contained in the collection.
-
#initialize(tag, content) ⇒ Collection
constructor
Creates a new Udat::Collection with a given tag (which may be nil) and a given content, represented by a nested Array structure.
-
#inspect ⇒ Object
Same as Udat::Node#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 Udat::Collection#ordered?.
-
#ordered! ⇒ Object
Same as Udat::Collection#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 true, if the order of the contents of this collection is significant for comparisons.
-
#pop ⇒ Object
Deletes the last entry and returns its value.
-
#rehash ⇒ Object
Deletes the internal index hashes.
-
#replace(other) ⇒ Object
Replaces the values (and corresponding keys) with the values/keys of another Udat::Collection and returns self.
-
#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.
-
#shift ⇒ Object
Deletes the first entry and returns its value.
-
#to_ary ⇒ Object
Same as Udat::Collection#values.
-
#to_hash ⇒ Object
Returns a hash, where each key is mapped to the respective value.
-
#unordered! ⇒ Object
Same as Udat::Collection#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.
-
#value_without_key ⇒ Object
Returns the last value without 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.
-
#values_without_key ⇒ Object
Returns an Array of values having no key.
Methods inherited from Node
#encode, #encode_document, #eql?, #hash, parse, parse_document, read_from_stream, #require_collection, #require_scalar, #require_tag, #rpc, #scalar?, #to_s, #to_udat, #write_to_stream
Constructor Details
#initialize(tag, content) ⇒ Collection
Creates a new Udat::Collection with a given tag (which may be nil) and a given content, represented by a nested Array structure. It is not recommended to use this method. Use Object#to_udat instead.
541 542 543 544 545 546 547 |
# File 'lib/udat.rb', line 541 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.
713 714 715 716 717 718 719 720 721 722 723 |
# File 'lib/udat.rb', line 713 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
Returns true, if class, tag and content are matching another object. The order of the content is only significant for comparison, if both objects have the Udat::Collection#ordered attribute set to true.
1027 1028 1029 1030 1031 1032 1033 1034 1035 |
# File 'lib/udat.rb', line 1027 def ==(other) return false unless self.class == other.class if self.unordered? or other.unordered? return UnorderedWrapper.new(self) == UnorderedWrapper.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 Udat::Collection#value_by_index. If the argument is nil, the method behaves like Udat::Collection#value_without_key. Otherwise the method behaves same as Udat::Collection#value_by_key.
829 830 831 832 833 834 835 836 837 |
# File 'lib/udat.rb', line 829 def [](key) if key.nil? return value_without_key elsif key.kind_of? Integer return value_by_index(key) else return value_by_key(key) end end |
#[]=(key, value) ⇒ Object
Same as Udat::Collection#set_value_for_key.
725 726 727 |
# File 'lib/udat.rb', line 725 def []=(key, value) set_value_for_key(key, value) end |
#append_pair(key, value) ⇒ Object
Appends a new key with a new value. Returns self.
672 673 674 675 676 677 678 679 680 681 |
# File 'lib/udat.rb', line 672 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) end return self end |
#append_value(value) ⇒ Object
Appends a new value. Returns self.
683 684 685 686 687 688 689 690 691 |
# File 'lib/udat.rb', line 683 def append_value(value) value = value.to_udat synchronize do index = @entries.length @entries << [nil, value] add_to_index_hashes(index, nil, value) end return self end |
#clear ⇒ Object
Empties the collection. Returns self.
626 627 628 629 630 631 632 633 |
# File 'lib/udat.rb', line 626 def clear synchronize do @entries.clear rehash require_index_hashes end return self end |
#collection? ⇒ Boolean
Returns true.
550 551 552 |
# File 'lib/udat.rb', line 550 def collection? true end |
#concat(other) ⇒ Object
Appends the values (and corresponding keys) of another Udat::Collection and returns self.
937 938 939 940 941 942 943 944 945 946 947 948 |
# File 'lib/udat.rb', line 937 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.
636 637 638 639 640 641 642 643 |
# File 'lib/udat.rb', line 636 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[1] : nil end end |
#delete_key(key) ⇒ Object
Deletes all entries with a given key. Returns self.
653 654 655 656 657 658 659 660 |
# File 'lib/udat.rb', line 653 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. Returns self.
662 663 664 665 666 667 668 669 |
# File 'lib/udat.rb', line 662 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.
887 888 889 890 891 892 |
# File 'lib/udat.rb', line 887 def each_index synchronize do (0...length).each { |i| yield i } end return self end |
#empty? ⇒ Boolean
Returns true, if the collection is empty.
883 884 885 |
# File 'lib/udat.rb', line 883 def empty? length == 0 end |
#encode_content ⇒ Object
Returns the encoded form of the content as a string. This method is used by Udat::Node#encode_without_brackets.
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 |
# File 'lib/udat.rb', line 999 def encode_content synchronize do return ( @entries.empty? ? "~" : @entries.collect do |key, value| if key "<#{key.encode_without_brackets}>" << "[#{value.encode_without_brackets}]" else "[#{value.encode_without_brackets}]" end end.join ) end end |
#fetch(key, tag = AnyTag) ⇒ Object
Same as Udat::Collection#[], but raises an Udat::UdatIndexError, 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.
842 843 844 845 846 847 848 849 |
# File 'lib/udat.rb', line 842 def fetch(key, tag = AnyTag) value = self[key] unless value raise UdatIndexError, "UDAT node not found." end value.require_tag(tag) unless tag == AnyTag return value end |
#fetch_collection(key, tag = AnyTag) ⇒ Object
Same as Udat::Collection#fetch, but raises an error, if the value is not an Udat::Collection.
860 861 862 863 864 865 |
# File 'lib/udat.rb', line 860 def fetch_collection(key, tag = AnyTag) value = fetch(key) value.require_collection value.require_tag(tag) unless tag == AnyTag return value end |
#fetch_scalar(key, tag = AnyTag) ⇒ Object
Same as Udat::Collection#fetch, but raises an error, if the value is not an Udat::Scalar.
852 853 854 855 856 857 |
# File 'lib/udat.rb', line 852 def fetch_scalar(key, tag = AnyTag) value = fetch(key) value.require_scalar value.require_tag(tag) unless tag == AnyTag return value end |
#first ⇒ Object
Returns the first value of the collection, or nil if empty.
867 868 869 |
# File 'lib/udat.rb', line 867 def first value_by_index(0) end |
#include?(value) ⇒ Boolean
Returns true, if the value is contained in the collection.
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 |
# File 'lib/udat.rb', line 808 def include?(value) value = value.to_udat synchronize do require_index_hashes if value.kind_of? Collection and value.unordered? return (@all_unordered_value_indicies[ UnorderedWrapper.new(value) ] || []).empty? ? false : true else return ((@value_indicies[value] || []) + ( @unordered_value_indicies[UnorderedWrapper.new(value)] || [] )).empty? ? false : true end end end |
#inspect ⇒ Object
Same as Udat::Node#inspect, but in case of unordered collections it prepends “udat-unordered” instead of just “udat”.
1016 1017 1018 1019 1020 1021 1022 |
# File 'lib/udat.rb', line 1016 def inspect if ordered? return super else "udat-unordered#{self.encode_document}" 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.
740 741 742 743 744 745 746 |
# File 'lib/udat.rb', line 740 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.
804 805 806 |
# File 'lib/udat.rb', line 804 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.
897 898 899 900 901 |
# File 'lib/udat.rb', line 897 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.
903 904 905 906 907 908 909 910 |
# File 'lib/udat.rb', line 903 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. The Array may contain nil’s for values having no key.
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 |
# File 'lib/udat.rb', line 777 def keys_by_value(value) value = value.to_udat synchronize do require_index_hashes if value.kind_of? Collection and value.unordered? indicies = @all_unordered_value_indicies[ UnorderedWrapper.new(value) ] || [] else indicies = (@value_indicies[value] || []) + ( @unordered_value_indicies[UnorderedWrapper.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.
871 872 873 |
# File 'lib/udat.rb', line 871 def last value_by_index(-1) end |
#length ⇒ Object Also known as: size
Returns the number of values in the collection.
876 877 878 879 880 |
# File 'lib/udat.rb', line 876 def length synchronize do @entries.length end end |
#ordered ⇒ Object
Same as Udat::Collection#ordered?.
960 961 962 963 964 |
# File 'lib/udat.rb', line 960 def ordered synchronize do return @ordered end end |
#ordered! ⇒ Object
Same as Udat::Collection#ordered = true, but returns self.
992 993 994 995 |
# File 'lib/udat.rb', line 992 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.
977 978 979 980 981 982 983 984 985 |
# File 'lib/udat.rb', line 977 def ordered=(ordered) synchronize do if ordered == false @ordered = false else @ordered = true end end end |
#ordered? ⇒ Boolean
Returns true, if the order of the contents of this collection is significant for comparisons.
967 968 969 |
# File 'lib/udat.rb', line 967 def ordered? self.ordered end |
#pop ⇒ Object
Deletes the last entry and returns its value.
649 650 651 |
# File 'lib/udat.rb', line 649 def pop delete_at(-1) 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). Returns self.
560 561 562 563 564 565 566 567 568 569 570 |
# File 'lib/udat.rb', line 560 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 Udat::Collection and returns self.
951 952 953 954 955 956 957 |
# File 'lib/udat.rb', line 951 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. Returns self.
701 702 703 704 705 |
# File 'lib/udat.rb', line 701 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. Returns self.
694 695 696 697 698 |
# File 'lib/udat.rb', line 694 def set_value_for_key(key, value) delete_key(key) append_pair(key, value) return self end |
#shift ⇒ Object
Deletes the first entry and returns its value.
645 646 647 |
# File 'lib/udat.rb', line 645 def shift delete_at(0) end |
#to_ary ⇒ Object
Same as Udat::Collection#values.
930 931 932 |
# File 'lib/udat.rb', line 930 def to_ary values end |
#to_hash ⇒ Object
Returns a hash, where each key is mapped to the respective value.
919 920 921 922 923 924 925 926 927 928 |
# File 'lib/udat.rb', line 919 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 Udat::Collection#ordered = false, but returns self.
987 988 989 990 |
# File 'lib/udat.rb', line 987 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.
972 973 974 |
# File 'lib/udat.rb', line 972 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.
731 732 733 734 735 736 737 |
# File 'lib/udat.rb', line 731 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.
800 801 802 |
# File 'lib/udat.rb', line 800 def value_by_key(key) values_by_key(key).last end |
#value_without_key ⇒ Object
Returns the last value without key.
796 797 798 |
# File 'lib/udat.rb', line 796 def value_without_key values_without_key.last end |
#values ⇒ Object Also known as: to_a
Returns an Array containing all values of the collection.
912 913 914 915 916 |
# File 'lib/udat.rb', line 912 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.
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
# File 'lib/udat.rb', line 757 def values_by_key(key) key = key.to_udat synchronize do require_index_hashes if key.kind_of? Collection and key.unordered? indicies = @all_unordered_key_indicies[ UnorderedWrapper.new(key) ] || [] else indicies = (@key_indicies[key] || []) + ( @unordered_key_indicies[UnorderedWrapper.new(key)] || [] ) indicies.uniq! indicies.sort! end return indicies.collect { |index| @entries[index][1] } end end |
#values_without_key ⇒ Object
Returns an Array of values having no key.
748 749 750 751 752 753 754 755 |
# File 'lib/udat.rb', line 748 def values_without_key synchronize do require_index_hashes return ( (@key_indicies[nil] || []).collect { |index| @entries[index][1] } ) end end |