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



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

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



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

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)


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

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.



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

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

.options_tTypes::PStructType

Returns the type used to validate the options hash



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

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)


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

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



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

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

Instance Method Details

#configurationObject



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

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



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

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



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
147
# File 'lib/puppet/pops/merge_strategy.rb', line 122

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



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

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



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

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



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

def merge_single(value)
  value
end

#optionsObject



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

def options
  @options
end