Class: Puppet::Pops::Binder::Binder::LayerProcessor Private
- Defined in:
- lib/puppet/pops/binder/binder.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Processes the information in a layer, aggregating it to the injector_entries hash in its parent binder. A LayerProcessor holds the intermediate state required while processing one layer.
Instance Attribute Summary collapse
- #binder ⇒ Object readonly private
- #binder_precedence ⇒ Object readonly private
- #bindings ⇒ Object readonly private
- #contributions ⇒ Object readonly private
- #key_factory ⇒ Object readonly private
Instance Method Summary collapse
-
#add(b) ⇒ Object
private
Add the binding to the list of potentially effective bindings from this layer.
-
#add_contribution(b) ⇒ Object
private
Add a multibind contribution.
-
#bind(binding) ⇒ Object
private
Bind given abstract binding.
- #bind_Binding(o) ⇒ Object private
- #bind_Bindings(o) ⇒ Object private
-
#bind_LayeredBindings(o) ⇒ Object
private
Process layered bindings from highest to lowest layer.
- #bind_NamedBindings(o) ⇒ Object private
-
#bind_NamedLayer(o) ⇒ Object
private
Processes one named (“top level”) layer consisting of a list of NamedBindings.
-
#highest(b1, b2) ⇒ Puppet::Pops::Binder::InjectorEntry
private
The entry with the highest precedence.
-
#initialize(binder, key_factory) ⇒ LayerProcessor
constructor
private
A new instance of LayerProcessor.
- #is_contribution?(binding) ⇒ Boolean private
-
#key(binding) ⇒ Object
private
Produces the key for the given Binding.
-
#raise_conflicting_binding(b1, b2) ⇒ Object
private
Raises a conflicting bindings error given two InjectorEntry’s with same precedence in the same layer (if they are in different layers, something is seriously wrong).
Constructor Details
#initialize(binder, key_factory) ⇒ LayerProcessor
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of LayerProcessor.
178 179 180 181 182 183 184 185 |
# File 'lib/puppet/pops/binder/binder.rb', line 178 def initialize(binder, key_factory) @binder = binder @binder_precedence = binder.binder_precedence @key_factory = key_factory @bindings = [] @contributions = [] @@bind_visitor ||= Puppet::Pops::Visitor.new(nil,"bind",0,0) end |
Instance Attribute Details
#binder ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
173 174 175 |
# File 'lib/puppet/pops/binder/binder.rb', line 173 def binder @binder end |
#binder_precedence ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
176 177 178 |
# File 'lib/puppet/pops/binder/binder.rb', line 176 def binder_precedence @binder_precedence end |
#bindings ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
172 173 174 |
# File 'lib/puppet/pops/binder/binder.rb', line 172 def bindings @bindings end |
#contributions ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
175 176 177 |
# File 'lib/puppet/pops/binder/binder.rb', line 175 def contributions @contributions end |
#key_factory ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
174 175 176 |
# File 'lib/puppet/pops/binder/binder.rb', line 174 def key_factory @key_factory end |
Instance Method Details
#add(b) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Add the binding to the list of potentially effective bindings from this layer
190 191 192 |
# File 'lib/puppet/pops/binder/binder.rb', line 190 def add(b) bindings << Puppet::Pops::Binder::InjectorEntry.new(b, binder_precedence) end |
#add_contribution(b) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Add a multibind contribution
197 198 199 |
# File 'lib/puppet/pops/binder/binder.rb', line 197 def add_contribution(b) contributions << Puppet::Pops::Binder::InjectorEntry.new(b, binder_precedence) end |
#bind(binding) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Bind given abstract binding
204 205 206 |
# File 'lib/puppet/pops/binder/binder.rb', line 204 def bind(binding) @@bind_visitor.visit_this_0(self, binding) end |
#bind_Binding(o) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
290 291 292 293 294 295 296 |
# File 'lib/puppet/pops/binder/binder.rb', line 290 def bind_Binding(o) if is_contribution?(o) add_contribution(o) else add(o) end end |
#bind_Bindings(o) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
299 300 301 |
# File 'lib/puppet/pops/binder/binder.rb', line 299 def bind_Bindings(o) o.bindings.each {|b| bind(b) } end |
#bind_LayeredBindings(o) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process layered bindings from highest to lowest layer
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/puppet/pops/binder/binder.rb', line 312 def bind_LayeredBindings(o) o.layers.each do |layer| processor = LayerProcessor.new(binder, key_factory) # All except abstract (==error) are transferred to injector_entries processor.bind(layer).each do |k, v| entry = binder.injector_entries[k] unless key_factory.is_contributions_key?(k) if v.is_abstract?() layer_name, bindings_name = Puppet::Pops::Binder::Binder.get_named_binding_layer_and_name(v.binding) type_name = Puppet::Pops::Types::TypeCalculator.singleton.string(v.binding.type) raise ArgumentError, "The abstract binding '#{type_name}/#{v.binding.name}' in '#{bindings_name}' in layer '#{layer_name}' was not overridden" end raise ArgumentError, "Internal Error - redefinition of key: #{k}, (should never happen)" if entry binder.injector_entries[k] = v else # add contributions to existing contributions, else set them binder.injector_entries[k] = entry ? entry + v : v end end end end |
#bind_NamedBindings(o) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
304 305 306 307 |
# File 'lib/puppet/pops/binder/binder.rb', line 304 def bind_NamedBindings(o) # Name is ignored here, it should be introspected when needed (in case of errors) o.bindings.each {|b| bind(b) } end |
#bind_NamedLayer(o) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Processes one named (“top level”) layer consisting of a list of NamedBindings
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
# File 'lib/puppet/pops/binder/binder.rb', line 338 def bind_NamedLayer(o) o.bindings.each {|b| bind(b) } this_layer = {} # process regular bindings bindings.each do |b| bkey = key(b.binding) # ignore if a higher layer defined it (unless the lower is final), but ensure override gets resolved # (override is not resolved across binders) if x = binder.injector_entries[bkey] if b.is_final? raise_conflicting_binding(x, b) end x.mark_override_resolved() next end # If a lower (parent) binder exposes a final binding it may not be overridden # if (x = binder.lookup_in_parent(bkey)) && x.is_final? raise_conflicting_binding(x, b) end # if already found in this layer, one wins (and resolves override), or it is an error existing = this_layer[bkey] winner = existing ? highest(existing, b) : b this_layer[bkey] = winner if existing winner.mark_override_resolved() end end # Process contributions # - organize map multibind_id to bindings with this id # - for each id, create an array with the unique anonymous keys to the contributed bindings # - bind the index to a special multibind contributions key (these are aggregated) # c_hash = Hash.new {|hash, key| hash[ key ] = [] } contributions.each {|b| c_hash[ b.binding.multibind_id ] << b } # - for each id c_hash.each do |k, v| index = v.collect do |b| bkey = key(b.binding) this_layer[bkey] = b bkey end.flatten contributions_key = key_factory.multibind_contributions(k) unless this_layer[contributions_key] this_layer[contributions_key] = [] end this_layer[contributions_key] += index end this_layer end |
#highest(b1, b2) ⇒ Puppet::Pops::Binder::InjectorEntry
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the entry with the highest precedence.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/puppet/pops/binder/binder.rb', line 210 def highest(b1, b2) if b1.is_abstract? != b2.is_abstract? # if one is abstract and the other is not, the non abstract wins b1.is_abstract? ? b2 : b1 else case b1.precedence <=> b2.precedence when 1 b1 when -1 b2 when 0 raise_conflicting_binding(b1, b2) end end end |
#is_contribution?(binding) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
285 286 287 |
# File 'lib/puppet/pops/binder/binder.rb', line 285 def is_contribution?(binding) ! binding.multibind_id.nil? end |
#key(binding) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Produces the key for the given Binding.
275 276 277 278 279 280 281 282 |
# File 'lib/puppet/pops/binder/binder.rb', line 275 def key(binding) k = if is_contribution?(binding) # contributions get a unique (sequential) key binder.next_anonymous_key() else key_factory.binding_key(binding) end end |
#raise_conflicting_binding(b1, b2) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Raises a conflicting bindings error given two InjectorEntry’s with same precedence in the same layer (if they are in different layers, something is seriously wrong)
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/puppet/pops/binder/binder.rb', line 228 def raise_conflicting_binding(b1, b2) b1_layer_name, b1_bindings_name = binder.class.get_named_binding_layer_and_name(b1.binding) b2_layer_name, b2_bindings_name = binder.class.get_named_binding_layer_and_name(b2.binding) finality_msg = (b1.is_final? || b2.is_final?) ? ". Override of final binding not allowed" : '' # TODO: Use of layer_name is not very good, it is not guaranteed to be unique unless b1_layer_name == b2_layer_name raise ArgumentError, [ 'Conflicting binding for', "'#{b1.binding.name}'", 'being resolved across layers', "'#{b1_layer_name}' and", "'#{b2_layer_name}'" ].join(' ')+finality_msg end # Conflicting bindings made from the same source if b1_bindings_name == b2_bindings_name raise ArgumentError, [ 'Conflicting binding for name:', "'#{b1.binding.name}'", 'in layer:', "'#{b1_layer_name}', ", 'both from:', "'#{b1_bindings_name}'" ].join(' ')+finality_msg end # Conflicting bindings from different sources raise ArgumentError, [ 'Conflicting binding for name:', "'#{b1.binding.name}'", 'in layer:', "'#{b1_layer_name}',", 'from:', "'#{b1_bindings_name}', and", "'#{b2_bindings_name}'" ].join(' ')+finality_msg end |