Class: Puppet::Pops::MergeStrategy

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/pops/merge_strategy.rb

Overview

Merges to objects into one based on an implemented strategy.

Constant Summary collapse

NOT_FOUND =
Object.new.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ MergeStrategy

Create a new instance of this strategy configured with the given options


79
80
81
82
# File 'lib/puppet/pops/merge_strategy.rb', line 79

def initialize(options)
  assert_type('The merge options', self.class.options_t, options) unless options.empty?
  @options = options
end

Class Method Details

.add_strategy(strategy_class) ⇒ Object

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


53
54
55
56
57
58
59
60
61
# File 'lib/puppet/pops/merge_strategy.rb', line 53

def self.add_strategy(strategy_class)
  unless MergeStrategy > strategy_class
    #TRANSLATORS 'MergeStrategies.add_strategy' is a method, 'stratgey_class' is a variable and 'MergeStrategy' is a class name and should not be translated
    raise ArgumentError, _("MergeStrategies.add_strategy 'strategy_class' must be a 'MergeStrategy' class. Got %{strategy_class}") %
        { strategy_class: strategy_class }
  end
  strategies[strategy_class.key] = strategy_class
  nil
end

.keyObject

Raises:

  • (NotImplementedError)

73
74
75
# File 'lib/puppet/pops/merge_strategy.rb', line 73

def self.key
  raise NotImplementedError, "Subclass must implement 'key'"
end

.merge(e1, e2, merge) ⇒ Object

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.


69
70
71
# File 'lib/puppet/pops/merge_strategy.rb', line 69

def self.merge(e1, e2, merge)
  strategy(merge).merge(e1, e2)
end

.options_tTypes::PStructType

Returns the type used to validate the options hash


181
182
183
# File 'lib/puppet/pops/merge_strategy.rb', line 181

def options_t
  @options_t ||=Types::TypeParser.singleton.parse("Struct[{strategy=>Optional[Pattern[/#{key}/]]}]")
end

.strategy(merge) ⇒ MergeStrategy

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

Raises:

  • (ArgumentError)

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/puppet/pops/merge_strategy.rb', line 20

def self.strategy(merge)
  return DefaultMergeStrategy::INSTANCE unless merge
  return merge if merge.is_a?(MergeStrategy)

  if merge.is_a?(Hash)
    merge_strategy = merge['strategy']
    if merge_strategy.nil?
      #TRANSLATORS 'merge' is a variable name and 'strategy' is a key and should not be translated
      raise ArgumentError, _("The hash given as 'merge' must contain the name of a strategy in string form for the key 'strategy'")
    end
    merge_options  = merge.size == 1 ? EMPTY_HASH : merge
  else
    merge_strategy = merge
    merge_options = EMPTY_HASH
  end
  merge_strategy = merge_strategy.to_sym if merge_strategy.is_a?(String)
  strategy_class = strategies[merge_strategy]
  raise ArgumentError, _("Unknown merge strategy: '%{strategy}'") % { strategy: merge_strategy } if strategy_class.nil?
  merge_options == EMPTY_HASH ? strategy_class::INSTANCE : strategy_class.new(merge_options)
end

.strategy_keysArray<Symbol>

Returns the list of merge strategy keys known to this class


45
46
47
# File 'lib/puppet/pops/merge_strategy.rb', line 45

def self.strategy_keys
  strategies.keys - [:default, :unconstrained_deep, :reverse_deep]
end

Instance Method Details

#configurationObject


166
167
168
169
170
171
172
# File 'lib/puppet/pops/merge_strategy.rb', line 166

def configuration
  if @options.nil? || @options.empty?
    self.class.key.to_s
  else
    @options.include?('strategy') ? @options : { 'strategy' => self.class.key.to_s }.merge(@options)
  end
end

#convert_value(value) ⇒ Object

Converts a single value to the type expected when merging two elements


151
152
153
# File 'lib/puppet/pops/merge_strategy.rb', line 151

def convert_value(value)
  value
end

#lookup(lookup_variants, lookup_invocation) {|variant, variant| ... } ⇒ Object

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

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

Yields:

  • }
  • }

Yield Parameters:

  • variant (Object)

    each variant given in the lookup_variants array.

  • variant (Object)

    each variant given in the lookup_variants array.

Yield Returns:

  • (Object)

    the value to merge with other values

  • (Object)

    the value to merge with other values


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/puppet/pops/merge_strategy.rb', line 121

def lookup(lookup_variants, lookup_invocation)
  case lookup_variants.size
  when 0
    throw :no_such_key
  when 1
    merge_single(yield(lookup_variants[0]))
  else
    lookup_invocation.with(:merge, self) do
      result = lookup_variants.reduce(NOT_FOUND) do |memo, lookup_variant|
        not_found = true
        value = catch(:no_such_key) do
          v = yield(lookup_variant)
          not_found = false
          v
        end
        if not_found
          memo
        else
          memo.equal?(NOT_FOUND) ? convert_value(value) : merge(memo, value)
        end
      end
      throw :no_such_key if result == NOT_FOUND
      lookup_invocation.report_result(result)
    end
  end
end

#merge(e1, e2) ⇒ Object

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


91
92
93
94
95
# File 'lib/puppet/pops/merge_strategy.rb', line 91

def merge(e1, e2)
  checked_merge(
    assert_type('The first element of the merge', value_t, e1),
    assert_type('The second element of the merge', value_t, e2))
end

#merge_lookup(lookup_variants) ⇒ Object

Deprecated.

TODO: API 5.0 Remove this method


99
100
101
# File 'lib/puppet/pops/merge_strategy.rb', line 99

def merge_lookup(lookup_variants)
  lookup(lookup_variants, Lookup::Invocation.current)
end

#merge_single(value) ⇒ Object

Applies the merge strategy on a single element. Only applicable for `unique`


158
159
160
# File 'lib/puppet/pops/merge_strategy.rb', line 158

def merge_single(value)
  value
end

#optionsObject


162
163
164
# File 'lib/puppet/pops/merge_strategy.rb', line 162

def options
  @options
end