class Puppet::Pops::MergeStrategy

Merges to objects into one based on an implemented strategy.

Constants

NOT_FOUND

Public Class Methods

add_strategy(strategy_class) click to toggle source

Adds a new merge strategy to the map of strategies known to this class

@param strategy_class [Class<MergeStrategy>] The class of the added strategy

   # File lib/puppet/pops/merge_strategy.rb
54 def self.add_strategy(strategy_class)
55   unless MergeStrategy > strategy_class
56     #TRANSLATORS 'MergeStrategies.add_strategy' is a method, 'stratgey_class' is a variable and 'MergeStrategy' is a class name and should not be translated
57     raise ArgumentError, _("MergeStrategies.add_strategy 'strategy_class' must be a 'MergeStrategy' class. Got %{strategy_class}") %
58         { strategy_class: strategy_class }
59   end
60   strategies[strategy_class.key] = strategy_class
61   nil
62 end
key() click to toggle source
   # File lib/puppet/pops/merge_strategy.rb
74 def self.key
75   raise NotImplementedError, "Subclass must implement 'key'"
76 end
merge(e1, e2, merge) click to toggle source

Finds a merge strategy that corresponds to the given merge argument and delegates the task of merging the elements of e1 and e2 to it.

@param e1 [Object] The first element @param e2 [Object] The second element @return [Object] The result of the merge

   # File lib/puppet/pops/merge_strategy.rb
70 def self.merge(e1, e2, merge)
71   strategy(merge).merge(e1, e2)
72 end
new(options) click to toggle source

Create a new instance of this strategy configured with the given options @param merge_options [Hash<String,Object>] Merge options

   # File lib/puppet/pops/merge_strategy.rb
80 def initialize(options)
81   assert_type('The merge options', self.class.options_t, options) unless options.empty?
82   @options = options
83 end
strategy(merge) click to toggle source

Finds the merge strategy for the given merge, creates an instance of it and returns that instance.

@param merge [MergeStrategy,String,Hash<String,Object>,nil] The merge strategy. Can be a string or symbol denoting the key

identifier or a hash with options where the key 'strategy' denotes the key

@return [MergeStrategy] The matching merge strategy

   # File lib/puppet/pops/merge_strategy.rb
21 def self.strategy(merge)
22   return DefaultMergeStrategy::INSTANCE unless merge
23   return merge if merge.is_a?(MergeStrategy)
24 
25   if merge.is_a?(Hash)
26     merge_strategy = merge['strategy']
27     if merge_strategy.nil?
28       #TRANSLATORS 'merge' is a variable name and 'strategy' is a key and should not be translated
29       raise ArgumentError, _("The hash given as 'merge' must contain the name of a strategy in string form for the key 'strategy'")
30     end
31     merge_options  = merge.size == 1 ? EMPTY_HASH : merge
32   else
33     merge_strategy = merge
34     merge_options = EMPTY_HASH
35   end
36   merge_strategy = merge_strategy.to_sym if merge_strategy.is_a?(String)
37   strategy_class = strategies[merge_strategy]
38   raise ArgumentError, _("Unknown merge strategy: '%{strategy}'") % { strategy: merge_strategy } if strategy_class.nil?
39   merge_options == EMPTY_HASH ? strategy_class::INSTANCE : strategy_class.new(merge_options)
40 end
strategy_keys() click to toggle source

Returns the list of merge strategy keys known to this class

@return [Array<Symbol>] List of strategy keys

   # File lib/puppet/pops/merge_strategy.rb
46 def self.strategy_keys
47   strategies.keys - [:default, :unconstrained_deep, :reverse_deep]
48 end

Protected Class Methods

options_t() click to toggle source

Returns the type used to validate the options hash

@return [Types::PStructType] the puppet type

    # File lib/puppet/pops/merge_strategy.rb
182 def options_t
183   @options_t ||=Types::TypeParser.singleton.parse("Struct[{strategy=>Optional[Pattern[/#{key}/]]}]")
184 end

Private Class Methods

strategies() click to toggle source
   # File lib/puppet/pops/merge_strategy.rb
10 def self.strategies
11   @@strategies ||= {}
12 end

Public Instance Methods

configuration() click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
167 def configuration
168   if @options.nil? || @options.empty?
169     self.class.key.to_s
170   else
171     @options.include?('strategy') ? @options : { 'strategy' => self.class.key.to_s }.merge(@options)
172   end
173 end
convert_value(value) click to toggle source

Converts a single value to the type expected when merging two elements @param value [Object] the value to convert @return [Object] the converted value

    # File lib/puppet/pops/merge_strategy.rb
152 def convert_value(value)
153   value
154 end
lookup(lookup_variants, lookup_invocation) { |lookup_variants| ... } click to toggle source

Merges the result of yielding the given lookup_variants to a given block.

@param lookup_variants [Array] The variants to pass as second argument to the given block @return [Object] the merged value. @yield [} ] @yieldparam variant [Object] each variant given in the lookup_variants array. @yieldreturn [Object] the value to merge with other values @throws :no_such_key if the lookup was unsuccessful

Merges the result of yielding the given lookup_variants to a given block.

@param lookup_variants [Array] The variants to pass as second argument to the given block @return [Object] the merged value. @yield [} ] @yieldparam variant [Object] each variant given in the lookup_variants array. @yieldreturn [Object] the value to merge with other values @throws :no_such_key if the lookup was unsuccessful

    # File lib/puppet/pops/merge_strategy.rb
122 def lookup(lookup_variants, lookup_invocation)
123   case lookup_variants.size
124   when 0
125     throw :no_such_key
126   when 1
127     merge_single(yield(lookup_variants[0]))
128   else
129     lookup_invocation.with(:merge, self) do
130       result = lookup_variants.reduce(NOT_FOUND) do |memo, lookup_variant|
131         not_found = true
132         value = catch(:no_such_key) do
133           v = yield(lookup_variant)
134           not_found = false
135           v
136         end
137         if not_found
138           memo
139         else
140           memo.equal?(NOT_FOUND) ? convert_value(value) : merge(memo, value)
141         end
142       end
143       throw :no_such_key if result == NOT_FOUND
144       lookup_invocation.report_result(result)
145     end
146   end
147 end
merge(e1, e2) click to toggle source

Merges the elements of e1 and e2 according to the rules of this strategy and options given when this instance was created

@param e1 [Object] The first element @param e2 [Object] The second element @return [Object] The result of the merge

   # File lib/puppet/pops/merge_strategy.rb
92 def merge(e1, e2)
93   checked_merge(
94     assert_type('The first element of the merge', value_t, e1),
95     assert_type('The second element of the merge', value_t, e2))
96 end
merge_lookup(lookup_variants) click to toggle source

TODO: API 5.0 Remove this method @deprecated

    # File lib/puppet/pops/merge_strategy.rb
100 def merge_lookup(lookup_variants)
101   lookup(lookup_variants, Lookup::Invocation.current)
102 end
merge_single(value) click to toggle source

Applies the merge strategy on a single element. Only applicable for `unique` @param value [Object] the value to merge with nothing @return [Object] the merged value

    # File lib/puppet/pops/merge_strategy.rb
159 def merge_single(value)
160   value
161 end
options() click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
163 def options
164   @options
165 end

Protected Instance Methods

assert_type(param, type, value) click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
199 def assert_type(param, type, value)
200   Types::TypeAsserter.assert_instance_of(param, type, value)
201 end
checked_merge(e1, e2) click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
195 def checked_merge(e1, e2)
196   raise NotImplementedError, "Subclass must implement 'checked_merge(e1,e2)'"
197 end
value_t() click to toggle source

Returns the type used to validate the options hash

@return [Types::PAnyType] the puppet type

    # File lib/puppet/pops/merge_strategy.rb
191 def value_t
192   raise NotImplementedError, "Subclass must implement 'value_t'"
193 end