setting_value.rb 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. module Puppet
  2. module Util
  3. # This class can work with a list of subsettings inside
  4. # an ini file setting string to add, remove, extract and set their values.
  5. class SettingValue
  6. # The constructor method
  7. # @param setting_value [String] The initial setting value
  8. # @param subsetting_separator [String] The character is used to separate
  9. # subsettings in the setting_value string.
  10. # @param default_quote_char [String] Quote the setting string with this character.
  11. def initialize(setting_value, subsetting_separator = ' ', default_quote_char = '', key_val_separator = '')
  12. @setting_value = setting_value
  13. @subsetting_separator = subsetting_separator
  14. @quote_char = default_quote_char
  15. @key_val_separator = key_val_separator
  16. @subsetting_items = []
  17. if @setting_value
  18. unquoted, quote_char = unquote_setting_value(setting_value)
  19. @quote_char = quote_char unless quote_char.empty?
  20. # an item can contain escaped separator
  21. @subsetting_items = unquoted.scan(Regexp.new("(?:(?:[^\\#{@subsetting_separator}]|\\.)+)"))
  22. @subsetting_items.map! { |item| item.strip }
  23. end
  24. end
  25. # If the setting value is quoted, the quotes are
  26. # removed and the unquoted string and the quoting
  27. # character are returned.
  28. # @param setting_value [String] The input value
  29. # @return [Array] The unquoted string and the quoting character
  30. def unquote_setting_value(setting_value)
  31. quote_char = ''
  32. if setting_value.start_with?('"') and setting_value.end_with?('"')
  33. quote_char = '"'
  34. elsif setting_value.start_with?("'") and setting_value.end_with?("'")
  35. quote_char = "'"
  36. end
  37. if quote_char != ''
  38. unquoted = setting_value[1, setting_value.length - 2]
  39. else
  40. unquoted = setting_value
  41. end
  42. [unquoted, quote_char]
  43. end
  44. # Get the resulting setting value by joining all the
  45. # subsettings, separator and quote characters.
  46. # @return [String]
  47. def get_value
  48. value = @subsetting_items.join @subsetting_separator
  49. @quote_char + value + @quote_char
  50. end
  51. # Get the value of the given subsetting item.
  52. # If the exact match is used the value will be true
  53. # if the item is found.
  54. # @param subsetting [String] The name of the subsetting to add.
  55. # @param use_exact_match [:true,:false] Should the full name match be used?
  56. # @return [nil,true,String]
  57. def get_subsetting_value(subsetting, use_exact_match=:false)
  58. index = find_subsetting(subsetting, use_exact_match)
  59. # the item is not found in the list
  60. return nil unless index
  61. # the exact match is set and the item is found, the value should be true
  62. return true if use_exact_match == :true
  63. item = @subsetting_items[index]
  64. item[(subsetting.length + @key_val_separator.length)..-1]
  65. end
  66. # Add a new subsetting item to the list of existing items
  67. # if such item is not already there.
  68. # @param subsetting [String] The name of the subsetting to add.
  69. # @param subsetting_value [String] The value of the subsetting.
  70. # It will be appended to the name.
  71. # @param use_exact_match [:true,:false] Should the full name match be used?
  72. # @param [Symbol] insert_type
  73. # @param [String,Integer] insert_value
  74. # @return [Array] The resulting subsettings list.
  75. def add_subsetting(subsetting, subsetting_value, use_exact_match=:false, insert_type=:end, insert_value=nil)
  76. index = find_subsetting(subsetting, use_exact_match)
  77. # update the existing values if the subsetting is found in the list
  78. return update_subsetting(subsetting, subsetting_value, use_exact_match) if index
  79. new_item = item_value(subsetting, subsetting_value)
  80. case insert_type
  81. when :start
  82. @subsetting_items.unshift(new_item)
  83. when :end
  84. @subsetting_items.push(new_item)
  85. when :before
  86. before_index = find_subsetting(insert_value, use_exact_match)
  87. if before_index
  88. @subsetting_items.insert(before_index, new_item)
  89. else
  90. @subsetting_items.push(new_item)
  91. end
  92. when :after
  93. after_index = find_subsetting(insert_value, use_exact_match)
  94. if after_index
  95. @subsetting_items.insert(after_index + 1, new_item)
  96. else
  97. @subsetting_items.push(new_item)
  98. end
  99. when :index
  100. before_index = insert_value.to_i
  101. before_index = @subsetting_items.length if before_index > @subsetting_items.length
  102. @subsetting_items.insert(before_index, new_item)
  103. else
  104. @subsetting_items.push(new_item)
  105. end
  106. @subsetting_items
  107. end
  108. # Update all matching items in the settings list to the new values.
  109. # @param subsetting [String] The name of the subsetting to add.
  110. # @param subsetting_value [String] The value of the subsetting.
  111. # @param use_exact_match [:true,:false] Should the full name match be used?
  112. # @return [Array] The resulting subsettings list.
  113. def update_subsetting(subsetting, subsetting_value, use_exact_match=:false)
  114. new_item = item_value(subsetting, subsetting_value)
  115. @subsetting_items.map! do |item|
  116. if match_subsetting?(item, subsetting, use_exact_match)
  117. new_item
  118. else
  119. item
  120. end
  121. end
  122. end
  123. # Find the first subsetting item matching the given name,
  124. # or, if the exact match is set, equal to the given name
  125. # and return its array index value. Returns nil if not found.
  126. # @param subsetting [String] The name of the subsetting to search.
  127. # @param use_exact_match [:true,:false] Look for the full string match?
  128. # @return [Integer, nil]
  129. def find_subsetting(subsetting, use_exact_match=:false)
  130. @subsetting_items.index do |item|
  131. match_subsetting?(item, subsetting, use_exact_match)
  132. end
  133. end
  134. # Check if the subsetting item matches the given name.
  135. # If the exact match is set the entire item is matched,
  136. # and only the item name and separator string if not.
  137. # @param item [String] The item value to check against the subsetting name.
  138. # @param subsetting [String] The subsetting name.
  139. # @param use_exact_match [:true,:false] Look for the full string match?
  140. # @return [true,false]
  141. def match_subsetting?(item, subsetting, use_exact_match=:false)
  142. if use_exact_match == :true
  143. item.eql?(subsetting)
  144. else
  145. item.start_with?(subsetting + @key_val_separator)
  146. end
  147. end
  148. # Remove all the subsetting items that match
  149. # the given subsetting name.
  150. # @param subsetting [String] The subsetting name to remove.
  151. # @param use_exact_match [:true,:false] Look for the full string match?
  152. # @return [Array] The resulting subsettings list.
  153. def remove_subsetting(subsetting, use_exact_match=:false)
  154. @subsetting_items.delete_if do |item|
  155. match_subsetting?(item, subsetting, use_exact_match)
  156. end
  157. end
  158. # The actual value of the subsetting item.
  159. # It's built from the subsetting name, its value and the separator
  160. # string if present.
  161. # @param subsetting [String] The subsetting name
  162. # @param subsetting_value [String] The value of the subsetting
  163. # @return [String]
  164. def item_value(subsetting, subsetting_value)
  165. (subsetting || '') + (@key_val_separator || '') + (subsetting_value || '')
  166. end
  167. end
  168. end
  169. end