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
53 def self.add_strategy(strategy_class)
54   unless MergeStrategy > strategy_class
55     #TRANSLATORS 'MergeStrategies.add_strategy' is a method, 'stratgey_class' is a variable and 'MergeStrategy' is a class name and should not be translated
56     raise ArgumentError, _("MergeStrategies.add_strategy 'strategy_class' must be a 'MergeStrategy' class. Got %{strategy_class}") %
57         { strategy_class: strategy_class }
58   end
59   strategies[strategy_class.key] = strategy_class
60   nil
61 end
key() click to toggle source
   # File lib/puppet/pops/merge_strategy.rb
73 def self.key
74   raise NotImplementedError, "Subclass must implement 'key'"
75 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
69 def self.merge(e1, e2, merge)
70   strategy(merge).merge(e1, e2)
71 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
79 def initialize(options)
80   assert_type('The merge options', self.class.options_t, options) unless options.empty?
81   @options = options
82 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
20 def self.strategy(merge)
21   return DefaultMergeStrategy::INSTANCE unless merge
22   return merge if merge.is_a?(MergeStrategy)
23 
24   if merge.is_a?(Hash)
25     merge_strategy = merge['strategy']
26     if merge_strategy.nil?
27       #TRANSLATORS 'merge' is a variable name and 'strategy' is a key and should not be translated
28       raise ArgumentError, _("The hash given as 'merge' must contain the name of a strategy in string form for the key 'strategy'")
29     end
30     merge_options  = merge.size == 1 ? EMPTY_HASH : merge
31   else
32     merge_strategy = merge
33     merge_options = EMPTY_HASH
34   end
35   merge_strategy = merge_strategy.to_sym if merge_strategy.is_a?(String)
36   strategy_class = strategies[merge_strategy]
37   raise ArgumentError, _("Unknown merge strategy: '%{strategy}'") % { strategy: merge_strategy } if strategy_class.nil?
38   merge_options == EMPTY_HASH ? strategy_class::INSTANCE : strategy_class.new(merge_options)
39 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
45 def self.strategy_keys
46   strategies.keys - [:default, :unconstrained_deep, :reverse_deep]
47 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
181 def options_t
182   @options_t ||=Types::TypeParser.singleton.parse("Struct[{strategy=>Optional[Pattern[/#{key}/]]}]")
183 end

Private Class Methods

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

Public Instance Methods

configuration() click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
166 def configuration
167   if @options.nil? || @options.empty?
168     self.class.key.to_s
169   else
170     @options.include?('strategy') ? @options : { 'strategy' => self.class.key.to_s }.merge(@options)
171   end
172 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
151 def convert_value(value)
152   value
153 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
121 def lookup(lookup_variants, lookup_invocation)
122   case lookup_variants.size
123   when 0
124     throw :no_such_key
125   when 1
126     merge_single(yield(lookup_variants[0]))
127   else
128     lookup_invocation.with(:merge, self) do
129       result = lookup_variants.reduce(NOT_FOUND) do |memo, lookup_variant|
130         not_found = true
131         value = catch(:no_such_key) do
132           v = yield(lookup_variant)
133           not_found = false
134           v
135         end
136         if not_found
137           memo
138         else
139           memo.equal?(NOT_FOUND) ? convert_value(value) : merge(memo, value)
140         end
141       end
142       throw :no_such_key if result == NOT_FOUND
143       lookup_invocation.report_result(result)
144     end
145   end
146 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
91 def merge(e1, e2)
92   checked_merge(
93     assert_type('The first element of the merge', value_t, e1),
94     assert_type('The second element of the merge', value_t, e2))
95 end
merge_lookup(lookup_variants) click to toggle source

TODO: API 5.0 Remove this method @deprecated

    # File lib/puppet/pops/merge_strategy.rb
 99 def merge_lookup(lookup_variants)
100   lookup(lookup_variants, Lookup::Invocation.current)
101 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
158 def merge_single(value)
159   value
160 end
options() click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
162 def options
163   @options
164 end

Protected Instance Methods

assert_type(param, type, value) click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
198 def assert_type(param, type, value)
199   Types::TypeAsserter.assert_instance_of(param, type, value)
200 end
checked_merge(e1, e2) click to toggle source
    # File lib/puppet/pops/merge_strategy.rb
194 def checked_merge(e1, e2)
195   raise NotImplementedError, "Subclass must implement 'checked_merge(e1,e2)'"
196 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
190 def value_t
191   raise NotImplementedError, "Subclass must implement 'value_t'"
192 end