Class: OpenAPISourceTools::Ordering::KeyPath
- Inherits:
-
Object
- Object
- OpenAPISourceTools::Ordering::KeyPath
- Includes:
- Comparable
- Defined in:
- lib/openapi/sourcetools/order.rb
Overview
Allowed keys starting from root, with pattern, any or multiple any key. Initialized with the path to the order array.
Instance Attribute Summary collapse
-
#first_multiple ⇒ Object
readonly
Returns the value of attribute first_multiple.
-
#items ⇒ Object
readonly
Returns the value of attribute items.
-
#multiple ⇒ Object
readonly
Returns the value of attribute multiple.
Instance Method Summary collapse
- #<=>(other) ⇒ Object
-
#initialize(parent_keys, regexp_prefix) ⇒ KeyPath
constructor
the parent_keys is processed to an array of regular expressions and :multi.
-
#match?(key_path) ⇒ Boolean
Performs base checks whether match is possible and if so, obtains indexes od matching patterns and starts search using those.
-
#matching_item_indexes(key, skip_non_multis) ⇒ Object
Finds indexes of regular expressions that match key, skipping given number.
-
#search(index_arrays, array_index, position_index) ⇒ Object
Given possible matches, uses position_index to check for matches relevant to the current situation and checks recursively if a solution ending to the desired point can be found.
Constructor Details
#initialize(parent_keys, regexp_prefix) ⇒ KeyPath
the parent_keys is processed to an array of regular expressions and :multi. A '' is eventually replaced with regular expression that accepts anything. A '**' is replaced by :multi that matches at least one key during match. A string starting with regexp_prefix is changed to a regular expression. Other string is turned to anchored regular expression that matches only the string. The order of '' and '**' can be modified to minimize occurrences of :multi.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/openapi/sourcetools/order.rb', line 41 def initialize(parent_keys, regexp_prefix) @multiple = false @items = [] parent_keys.each do |key| if key == '*' if @items.last == :multi # :multi, :one is same as :one, :multi as at least 2 arbitrary items. @items.pop @items.push(:one, :multi) else @items.push(:one) end elsif key == '**' @multiple = true if @items.last == :multi # :multi, :multi is same as :one, :multi as at least 2 arbitrary items. @items.pop @items.push(:one, :multi) else @items.push(:multi) end elsif key.start_with?(regexp_prefix) @items.push(Regexp.new(key[regexp_prefix.size..])) else @items.push(Regexp.new("^#{Regexp.escape(key)}$")) end end @items.each_with_index do |item, idx| @items[idx] = ANY if item == :one end @first_multiple = @items.index(:multi) || @items.size end |
Instance Attribute Details
#first_multiple ⇒ Object (readonly)
Returns the value of attribute first_multiple.
33 34 35 |
# File 'lib/openapi/sourcetools/order.rb', line 33 def first_multiple @first_multiple end |
#items ⇒ Object (readonly)
Returns the value of attribute items.
33 34 35 |
# File 'lib/openapi/sourcetools/order.rb', line 33 def items @items end |
#multiple ⇒ Object (readonly)
Returns the value of attribute multiple.
33 34 35 |
# File 'lib/openapi/sourcetools/order.rb', line 33 def multiple @multiple end |
Instance Method Details
#<=>(other) ⇒ Object
127 128 129 130 131 132 133 |
# File 'lib/openapi/sourcetools/order.rb', line 127 def <=>(other) # The purpose is to place longest "exact" items to the end. # Hence items.size, and the more multiple, the earlier. d = @items.size <=> other.items.size return d unless d.zero? -@items.count(:multi) <=> -other.items.count(:multi) end |
#match?(key_path) ⇒ Boolean
Performs base checks whether match is possible and if so, obtains indexes od matching patterns and starts search using those.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/openapi/sourcetools/order.rb', line 106 def match?(key_path) return true if @items.empty? && key_path.empty? slack = key_path.size - @items.size return false if slack.negative? # Path too short. return false if slack.positive? && !@multiple # Path too long. # Last key must match last item. return false unless @items.last == :multi || @items.last.match?(key_path.last) # First key must match first item. return false unless @items.first == :multi || @items.first.match?(key_path.first) return true if key_path.size <= 2 # Tested both already. # Form arrays of possible match indexes for search. Omit first and last. index_arrays = [] (1...(key_path.size - 1)).each do |idx| key = key_path[idx] idxs = matching_item_indexes(key, idx) return false if idxs.empty? index_arrays.push(idxs) end search(index_arrays, 0, @items.first == :multi ? 0 : 1) end |
#matching_item_indexes(key, skip_non_multis) ⇒ Object
Finds indexes of regular expressions that match key, skipping given number.
75 76 77 78 79 80 81 82 |
# File 'lib/openapi/sourcetools/order.rb', line 75 def matching_item_indexes(key, skip_non_multis) indexes = [] ([skip_non_multis, @first_multiple].min...@items.size).each do |idx| item = @items[idx] indexes.push(idx) if item == :multi || item.match?(key) end indexes end |
#search(index_arrays, array_index, position_index) ⇒ Object
Given possible matches, uses position_index to check for matches relevant to the current situation and checks recursively if a solution ending to the desired point can be found.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/openapi/sourcetools/order.rb', line 87 def search(index_arrays, array_index, position_index) if array_index == index_arrays.size # Last key is known to match last item, so if that were tested, it would pass. return position_index == @items.size - 1 end if @items[position_index] == :multi # Multi absorbs current key and releases to next position. return true if search(index_arrays, array_index + 1, position_index + 1) # Multi absorbs current key and stays for more. search(index_arrays, array_index + 1, position_index) else # Only current item to match with. return false if index_arrays[array_index].index(position_index).nil? search(index_arrays, array_index + 1, position_index + 1) end end |