Class: Puppet::Pops::Binder::Injector::Private::InjectorImpl Private
- Defined in:
- lib/puppet/pops/binder/injector.rb
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.
Defined Under Namespace
Classes: NotFound
Instance Attribute Summary collapse
- #binder ⇒ Object readonly private
-
#entries ⇒ Object
readonly
private
Hash of key => InjectorEntry.
- #key_factory ⇒ Object readonly private
- #type_calculator ⇒ Object readonly private
Instance Method Summary collapse
-
#assistable_injected_class(key) ⇒ Object
private
Produces an injectable class given a key, or nil if key does not represent an injectable class.
-
#data_key(name) ⇒ Object
private
Produces a key for a PDataType/name combination.
- #format_binding(b) ⇒ Object private
-
#get_contributions(scope, contributions_key) ⇒ Object
private
Returns contributions to a multibind in precedence order; highest first.
-
#get_entry(key) ⇒ Object
private
Should be used to get entries as it converts missing entries to NotFound entries or AssistedInject entries.
-
#initialize(configured_binder, parent_injector = nil) ⇒ InjectorImpl
constructor
private
A new instance of InjectorImpl.
- #lookup(scope, *args, &block) ⇒ Object private
- #lookup_key(scope, key) ⇒ Object private
- #lookup_producer(scope, *args, &block) ⇒ Object private
- #lookup_producer_key(scope, key) ⇒ Object private
- #lookup_producer_type(scope, type, name = '') ⇒ Object private
- #lookup_type(scope, type, name = '') ⇒ Object private
- #make_producer(clazz, descriptor, scope, entry, options) ⇒ Object private
- #merge_producer_options(binding, options) ⇒ Object private
- #named_arguments_to_hash(named_args) ⇒ Object private
-
#named_key(type, name) ⇒ Object
private
Produces a key for a type/name combination.
-
#produce(scope, entry) ⇒ Object
private
Returns the produced instance.
-
#producer(scope, entry, use) ⇒ Producers::Producer
private
Returns the producer for the entry.
- #singleton?(descriptor) ⇒ Boolean private
- #singleton_wrapped(descriptor, scope, entry, producer) ⇒ Object private
- #transform(producer_descriptor, scope, entry) ⇒ Object private
- #transform_ArrayMultibindProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_ConstantProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_EvaluatingProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_FirstFoundProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_HashLookupProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_HashMultibindProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_InstanceProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_LookupProducerDescriptor(descriptor, scope, entry) ⇒ Object private
-
#transform_NilClass(descriptor, scope, entry) ⇒ Object
private
Handles a missing producer (which is valid for a Multibinding where one is selected automatically).
- #transform_NonCachingProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #transform_ProducerProducerDescriptor(descriptor, scope, entry) ⇒ Object private
- #type_error_detail(expected, actual) ⇒ Object private
Constructor Details
#initialize(configured_binder, parent_injector = nil) ⇒ InjectorImpl
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 InjectorImpl.
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/puppet/pops/binder/injector.rb', line 423 def initialize(configured_binder, parent_injector = nil) @binder = configured_binder @parent = parent_injector # TODO: Different error message raise ArgumentError, "Given Binder is not configured" unless configured_binder #&& configured_binder.configured?() @entries = configured_binder.injector_entries() # It is essential that the injector uses the same key factory as the binder since keys must be # represented the same (but still opaque) way. # @key_factory = configured_binder.key_factory() @type_calculator = Types::TypeCalculator.singleton @@transform_visitor ||= Visitor.new(nil,"transform", 2, 2) @recursion_lock = [ ] 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.
421 422 423 |
# File 'lib/puppet/pops/binder/injector.rb', line 421 def binder @binder end |
#entries ⇒ 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.
Hash of key => InjectorEntry
415 416 417 |
# File 'lib/puppet/pops/binder/injector.rb', line 415 def entries @entries 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.
417 418 419 |
# File 'lib/puppet/pops/binder/injector.rb', line 417 def key_factory @key_factory end |
#type_calculator ⇒ 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.
419 420 421 |
# File 'lib/puppet/pops/binder/injector.rb', line 419 def type_calculator @type_calculator end |
Instance Method Details
#assistable_injected_class(key) ⇒ 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 an injectable class given a key, or nil if key does not represent an injectable class
564 565 566 567 568 |
# File 'lib/puppet/pops/binder/injector.rb', line 564 def assistable_injected_class(key) kt = key_factory.get_type(key) return nil unless kt.is_a?(Types::PRuntimeType) && kt.runtime == :ruby && !key_factory.is_named?(key) type_calculator.injectable_class(kt) end |
#data_key(name) ⇒ 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 a key for a PDataType/name combination
481 482 483 |
# File 'lib/puppet/pops/binder/injector.rb', line 481 def data_key(name) key_factory.data_key(name) end |
#format_binding(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.
664 665 666 |
# File 'lib/puppet/pops/binder/injector.rb', line 664 def format_binding(b) Binder.format_binding(b) end |
#get_contributions(scope, contributions_key) ⇒ 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.
Returns contributions to a multibind in precedence order; highest first. Returns an Array on the form [ [key, entry], [key, entry]] where the key is intended to be used to lookup the value (or a producer) for that entry.
554 555 556 557 558 559 |
# File 'lib/puppet/pops/binder/injector.rb', line 554 def get_contributions(scope, contributions_key) result = {} return [] unless contributions = lookup_key(scope, contributions_key) contributions.each { |k| result[k] = get_entry(k) } result.sort {|a, b| a[0] <=> b[0] } end |
#get_entry(key) ⇒ 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.
Should be used to get entries as it converts missing entries to NotFound entries or AssistedInject entries
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
# File 'lib/puppet/pops/binder/injector.rb', line 533 def get_entry(key) case entry = entries[ key ] when NilClass # not found, is this an assisted inject? if clazz = assistable_injected_class(key) entry = Producers::AssistedInjectProducer.new(self, clazz) entries[ key ] = entry else entries[ key ] = NotFound.new() entry = nil end when NotFound entry = nil end entry end |
#lookup(scope, *args, &block) ⇒ 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.
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
# File 'lib/puppet/pops/binder/injector.rb', line 441 def lookup(scope, *args, &block) raise ArgumentError, "lookup should be called with two or three arguments, got: #{args.size()+1}" unless args.size.between?(1,2) val = case args[ 0 ] when Types::PAnyType lookup_type(scope, *args) when String raise ArgumentError, "lookup of name should only pass the name" unless args.size == 1 lookup_key(scope, key_factory.data_key(args[ 0 ])) else raise ArgumentError, 'lookup using a key should only pass a single key' unless args.size == 1 lookup_key(scope, args[ 0 ]) end # call block with result if given if block case block.arity when 1 block.call(val) when 2 block.call(scope, val) else raise ArgumentError, "The block should have arity 1 or 2" end else val end end |
#lookup_key(scope, key) ⇒ 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.
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 |
# File 'lib/puppet/pops/binder/injector.rb', line 502 def lookup_key(scope, key) if @recursion_lock.include?(key) raise ArgumentError, "Lookup loop detected for key: #{key}" end begin @recursion_lock.push(key) case entry = get_entry(key) when NilClass @parent ? @parent.lookup_key(scope, key) : nil when InjectorEntry val = produce(scope, entry) return nil if val.nil? unless type_calculator.instance?(entry.binding.type, val) raise "Type error: incompatible type returned by producer, #{type_error_detail(entry.binding.type, val)}" end val when Producers::AssistedInjectProducer entry.produce(scope) else # internal, direct entries entry end ensure @recursion_lock.pop() end end |
#lookup_producer(scope, *args, &block) ⇒ 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.
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 |
# File 'lib/puppet/pops/binder/injector.rb', line 570 def lookup_producer(scope, *args, &block) raise ArgumentError, "lookup_producer should be called with two or three arguments, got: #{args.size()+1}" unless args.size <= 2 p = case args[ 0 ] when Types::PAnyType lookup_producer_type(scope, *args) when String raise ArgumentError, "lookup_producer of name should only pass the name" unless args.size == 1 lookup_producer_key(scope, key_factory.data_key(args[ 0 ])) else raise ArgumentError, "lookup_producer using a key should only pass a single key" unless args.size == 1 lookup_producer_key(scope, args[ 0 ]) end # call block with result if given if block case block.arity when 1 block.call(p) when 2 block.call(scope, p) else raise ArgumentError, "The block should have arity 1 or 2" end else p end end |
#lookup_producer_key(scope, key) ⇒ 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.
602 603 604 605 606 607 608 609 610 611 612 |
# File 'lib/puppet/pops/binder/injector.rb', line 602 def lookup_producer_key(scope, key) if @recursion_lock.include?(key) raise ArgumentError, "Lookup loop detected for key: #{key}" end begin @recursion_lock.push(key) producer(scope, get_entry(key), :multiple_use) ensure @recursion_lock.pop() end end |
#lookup_producer_type(scope, type, name = '') ⇒ 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.
615 616 617 |
# File 'lib/puppet/pops/binder/injector.rb', line 615 def lookup_producer_type(scope, type, name='') lookup_producer_key(scope, named_key(type, name)) end |
#lookup_type(scope, type, name = '') ⇒ 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.
486 487 488 489 490 491 492 493 |
# File 'lib/puppet/pops/binder/injector.rb', line 486 def lookup_type(scope, type, name='') val = lookup_key(scope, named_key(type, name)) return nil if val.nil? unless type_calculator.instance?(type, val) raise ArgumentError, "Type error: incompatible type, #{type_error_detail(type, val)}" end val end |
#make_producer(clazz, descriptor, scope, entry, options) ⇒ 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.
714 715 716 |
# File 'lib/puppet/pops/binder/injector.rb', line 714 def make_producer(clazz, descriptor, scope, entry, ) singleton_wrapped(descriptor, scope, entry, clazz.new(self, entry.binding, scope, )) end |
#merge_producer_options(binding, options) ⇒ 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.
659 660 661 |
# File 'lib/puppet/pops/binder/injector.rb', line 659 def (binding, ) named_arguments_to_hash(binding.producer_args).merge() end |
#named_arguments_to_hash(named_args) ⇒ 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.
651 652 653 654 655 656 |
# File 'lib/puppet/pops/binder/injector.rb', line 651 def named_arguments_to_hash(named_args) nb = named_args.nil? ? [] : named_args result = {} nb.each {|arg| result[ :"#{arg.name}" ] = arg.value } result end |
#named_key(type, name) ⇒ 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 a key for a type/name combination.
475 476 477 |
# File 'lib/puppet/pops/binder/injector.rb', line 475 def named_key(type, name) key_factory.named_key(type, name) end |
#produce(scope, entry) ⇒ 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.
Returns the produced instance
645 646 647 648 |
# File 'lib/puppet/pops/binder/injector.rb', line 645 def produce(scope, entry) return nil unless entry # not found producer(scope, entry, :single_use).produce(scope) end |
#producer(scope, entry, use) ⇒ Producers::Producer
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 producer for the entry
624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/puppet/pops/binder/injector.rb', line 624 def producer(scope, entry, use) return nil unless entry # not found return entry.producer(scope) if entry.is_a?(Producers::AssistedInjectProducer) unless entry.cached_producer entry.cached_producer = transform(entry.binding.producer, scope, entry) end unless entry.cached_producer raise ArgumentError, "Injector entry without a producer #{format_binding(entry.binding)}" end entry.cached_producer.producer(scope) end |
#singleton?(descriptor) ⇒ 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.
758 759 760 |
# File 'lib/puppet/pops/binder/injector.rb', line 758 def singleton?(descriptor) ! descriptor.eContainer().is_a?(Bindings::NonCachingProducerDescriptor) end |
#singleton_wrapped(descriptor, scope, entry, producer) ⇒ 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.
719 720 721 722 723 |
# File 'lib/puppet/pops/binder/injector.rb', line 719 def singleton_wrapped(descriptor, scope, entry, producer) return producer unless singleton?(descriptor) Producers::SingletonProducer.new(self, entry.binding, scope, (entry.binding, {:value => producer.produce(scope)})) end |
#transform(producer_descriptor, scope, entry) ⇒ 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.
637 638 639 |
# File 'lib/puppet/pops/binder/injector.rb', line 637 def transform(producer_descriptor, scope, entry) @@transform_visitor.visit_this_2(self, producer_descriptor, scope, entry) end |
#transform_ArrayMultibindProducerDescriptor(descriptor, scope, entry) ⇒ 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.
686 687 688 |
# File 'lib/puppet/pops/binder/injector.rb', line 686 def transform_ArrayMultibindProducerDescriptor(descriptor, scope, entry) make_producer(Producers::ArrayMultibindProducer, descriptor, scope, entry, named_arguments_to_hash(entry.binding.producer_args)) end |
#transform_ConstantProducerDescriptor(descriptor, scope, entry) ⇒ 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.
696 697 698 699 |
# File 'lib/puppet/pops/binder/injector.rb', line 696 def transform_ConstantProducerDescriptor(descriptor, scope, entry) producer_class = singleton?(descriptor) ? Producers::SingletonProducer : Producers::DeepCloningProducer producer_class.new(self, entry.binding, scope, (entry.binding, {:value => descriptor.value})) end |
#transform_EvaluatingProducerDescriptor(descriptor, scope, entry) ⇒ 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.
708 709 710 711 |
# File 'lib/puppet/pops/binder/injector.rb', line 708 def transform_EvaluatingProducerDescriptor(descriptor, scope, entry) make_producer(Producers::EvaluatingProducer, descriptor, scope, entry, (entry.binding, {:expression => descriptor.expression})) end |
#transform_FirstFoundProducerDescriptor(descriptor, scope, entry) ⇒ 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.
752 753 754 755 |
# File 'lib/puppet/pops/binder/injector.rb', line 752 def transform_FirstFoundProducerDescriptor(descriptor, scope, entry) make_producer(Producers::FirstFoundProducer, descriptor, scope, entry, (entry.binding, {:producers => descriptor.producers.collect {|p| transform(p, scope, entry) }})) end |
#transform_HashLookupProducerDescriptor(descriptor, scope, entry) ⇒ 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.
740 741 742 743 |
# File 'lib/puppet/pops/binder/injector.rb', line 740 def transform_HashLookupProducerDescriptor(descriptor, scope, entry) make_producer(Producers::LookupKeyProducer, descriptor, scope, entry, (entry.binding, {:type => descriptor.type, :name => descriptor.name, :key => descriptor.key})) end |
#transform_HashMultibindProducerDescriptor(descriptor, scope, entry) ⇒ 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.
691 692 693 |
# File 'lib/puppet/pops/binder/injector.rb', line 691 def transform_HashMultibindProducerDescriptor(descriptor, scope, entry) make_producer(Producers::HashMultibindProducer, descriptor, scope, entry, named_arguments_to_hash(entry.binding.producer_args)) end |
#transform_InstanceProducerDescriptor(descriptor, scope, entry) ⇒ 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.
702 703 704 705 |
# File 'lib/puppet/pops/binder/injector.rb', line 702 def transform_InstanceProducerDescriptor(descriptor, scope, entry) make_producer(Producers::InstantiatingProducer, descriptor, scope, entry, (entry.binding, {:class_name => descriptor.class_name, :init_args => descriptor.arguments})) end |
#transform_LookupProducerDescriptor(descriptor, scope, entry) ⇒ 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.
734 735 736 737 |
# File 'lib/puppet/pops/binder/injector.rb', line 734 def transform_LookupProducerDescriptor(descriptor, scope, entry) make_producer(Producers::LookupProducer, descriptor, scope, entry, (entry.binding, {:type => descriptor.type, :name => descriptor.name})) end |
#transform_NilClass(descriptor, scope, entry) ⇒ 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.
Handles a missing producer (which is valid for a Multibinding where one is selected automatically)
671 672 673 674 675 676 677 678 679 680 681 682 683 |
# File 'lib/puppet/pops/binder/injector.rb', line 671 def transform_NilClass(descriptor, scope, entry) unless entry.binding.is_a?(Bindings::Multibinding) raise ArgumentError, "Binding without producer detected, #{format_binding(entry.binding)}" end case entry.binding.type when Types::PArrayType transform(Bindings::ArrayMultibindProducerDescriptor.new(), scope, entry) when Types::PHashType transform(Bindings::HashMultibindProducerDescriptor.new(), scope, entry) else raise ArgumentError, "Unsupported multibind type, must be an array or hash type, #{format_binding(entry.binding)}" end end |
#transform_NonCachingProducerDescriptor(descriptor, scope, entry) ⇒ 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.
746 747 748 749 |
# File 'lib/puppet/pops/binder/injector.rb', line 746 def transform_NonCachingProducerDescriptor(descriptor, scope, entry) # simply delegates to the wrapped producer transform(descriptor.producer, scope, entry) end |
#transform_ProducerProducerDescriptor(descriptor, scope, entry) ⇒ 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.
726 727 728 729 730 731 |
# File 'lib/puppet/pops/binder/injector.rb', line 726 def transform_ProducerProducerDescriptor(descriptor, scope, entry) p = transform(descriptor.producer, scope, entry) clazz = singleton?(descriptor) ? Producers::SingletonProducerProducer : Producers::ProducerProducer clazz.new(self, entry.binding, scope, (entry.binding, (entry.binding, { :producer_producer => p }))) end |
#type_error_detail(expected, actual) ⇒ 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.
496 497 498 499 |
# File 'lib/puppet/pops/binder/injector.rb', line 496 def type_error_detail(expected, actual) actual_t = type_calculator.infer(actual) "expected: #{expected}, got: #{actual_t}" end |