class Puppet::Pops::Types::PObjectTypeExtension

Base class for Parameterized Object implementations. The wrapper impersonates the base object and extends it with methods to filter assignable types and instances based on parameter values.

@api public

Attributes

base_type[R]
parameters[R]

Public Class Methods

create(base_type, init_parameters) click to toggle source

@api private

   # File lib/puppet/pops/types/p_object_type_extension.rb
27 def self.create(base_type, init_parameters)
28   impl_class = Loaders.implementation_registry.module_for_type("#{base_type.name}TypeExtension") || self
29   impl_class.new(base_type, init_parameters)
30 end
create_from_instance(base_type, instance) click to toggle source

Creates an array of type parameters from the attributes of the given instance that matches the type parameters by name. Type parameters for which there is no matching attribute will have `nil` in their corresponding position on the array. The array is then passed as the `init_parameters` argument in a call to `create`

@return [PObjectTypeExtension] the created extension @api private

   # File lib/puppet/pops/types/p_object_type_extension.rb
39 def self.create_from_instance(base_type, instance)
40   type_parameters = base_type.type_parameters(true)
41   attrs = base_type.attributes(true)
42   params = type_parameters.keys.map do |pn|
43     attr = attrs[pn]
44     attr.nil? ? nil : instance.send(pn)
45   end
46   create(base_type, params)
47 end
new(base_type, init_parameters) click to toggle source

@api private

   # File lib/puppet/pops/types/p_object_type_extension.rb
54 def initialize(base_type, init_parameters)
55   pts = base_type.type_parameters(true)
56   raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using []') % { label: base_type.label } if pts.empty?
57   @base_type = base_type
58 
59   named_args = init_parameters.size == 1 && init_parameters[0].is_a?(Hash)
60   if named_args
61     # Catch case when first parameter is an assignable Hash
62     named_args = pts.size >= 1 && !pts.values[0].type.instance?(init_parameters[0])
63   end
64 
65   by_name = {}
66   if named_args
67     hash = init_parameters[0]
68     hash.each_pair do |pn, pv|
69       tp = pts[pn]
70       if tp.nil?
71         raise Puppet::ParseError, _("'%{pn}' is not a known type parameter for %{label}-Type") % { pn: pn, label: base_type.label }
72       end
73       by_name[pn] = check_param(tp, pv) unless pv == :default
74     end
75   else
76     pts.values.each_with_index do |tp, idx|
77       if idx < init_parameters.size
78         pv = init_parameters[idx]
79         by_name[tp.name] = check_param(tp, pv) unless pv == :default
80       end
81     end
82   end
83   if by_name.empty?
84     raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using an empty parameter list') % { label: base_type.label }
85   end
86   @parameters = by_name
87 end
register_ptype(loader, ir) click to toggle source
   # File lib/puppet/pops/types/p_object_type_extension.rb
13 def self.register_ptype(loader, ir)
14   create_ptype(loader, ir, 'AnyType',
15     'base_type' => {
16       KEY_TYPE => PTypeType::DEFAULT
17     },
18     'init_parameters' => {
19       KEY_TYPE => PArrayType::DEFAULT
20     }
21   )
22 end

Public Instance Methods

[](name) click to toggle source
   # File lib/puppet/pops/types/p_object_type_extension.rb
49 def [](name)
50   @base_type[name]
51 end
check_param(type_param, v) click to toggle source
   # File lib/puppet/pops/types/p_object_type_extension.rb
89 def check_param(type_param, v)
90   TypeAsserter.assert_instance_of(nil, type_param.type, v) { type_param.label }
91 end
check_self_recursion(originator) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
133 def check_self_recursion(originator)
134   @base_type.check_self_recursion(originator)
135 end
create(*args) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
138 def create(*args)
139   @base_type.create(*args)
140 end
eql?(o) click to toggle source

@api private

Calls superclass method
    # File lib/puppet/pops/types/p_object_type_extension.rb
113 def eql?(o)
114   super(o) && @base_type.eql?(o.base_type) && @parameters.eql?(o.parameters)
115 end
generalize() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
118 def generalize
119   @base_type
120 end
hash() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
123 def hash
124   @base_type.hash ^ @parameters.hash
125 end
implementation_class(create = true) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
158 def implementation_class(create = true)
159   @base_type.implementation_class(create)
160 end
init_parameters() click to toggle source

Return the parameter values as positional arguments with unset values as :default. The array is stripped from trailing :default values @return [Array] the parameter values @api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
 97 def init_parameters
 98   pts = @base_type.type_parameters(true)
 99   if pts.size > 2
100     @parameters
101   else
102     result = pts.values.map do |tp|
103       pn = tp.name
104       @parameters.include?(pn) ? @parameters[pn] : :default
105     end
106     # Remove trailing defaults
107     result.pop while result.last == :default
108     result
109   end
110 end
instance?(o, guard = nil) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
143 def instance?(o, guard = nil)
144   @base_type.instance?(o, guard) && test_instance?(o, guard)
145 end
loader() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
128 def loader
129   @base_type.loader
130 end
new_function() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
148 def new_function
149   @base_type.new_function
150 end
parameter_info(impl_class) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
163 def parameter_info(impl_class)
164   @base_type.parameter_info(impl_class)
165 end
simple_name() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
153 def simple_name
154   @base_type.simple_name
155 end

Protected Instance Methods

_assignable?(o, guard = nil) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
220 def _assignable?(o, guard = nil)
221   if o.is_a?(PObjectTypeExtension)
222     @base_type.assignable?(o.base_type, guard) && test_assignable?(o.parameters, guard)
223   else
224     @base_type.assignable?(o, guard) && test_assignable?(EMPTY_HASH, guard)
225   end
226 end
test_assignable?(param_values, guard) click to toggle source

Checks that the given `param_values` hash contains all keys present in the `parameters` of this instance and that each keyed value is a match for the given parameter. The match is done using case expression semantics.

This method is only called when a given type is found to be assignable to the base type of this extension.

@param param_values the parameter values of the assignable type @param guard guard against endless recursion @return [Boolean] true or false to indicate assignability @api public

    # File lib/puppet/pops/types/p_object_type_extension.rb
180 def test_assignable?(param_values, guard)
181   # Default implementation performs case expression style matching of all parameter values
182   # provided that the value exist (this should always be the case, since all defaults have
183   # been assigned at this point)
184   eval = Parser::EvaluatingParser.singleton.evaluator
185   @parameters.keys.all? do |pn|
186     if param_values.include?(pn)
187       a = param_values[pn]
188       b = @parameters[pn]
189       eval.match?(a, b) || a.is_a?(PAnyType) && b.is_a?(PAnyType) && b.assignable?(a)
190     else
191       false
192     end
193   end
194 end
test_instance?(o, guard) click to toggle source

Checks that the given instance `o` has one attribute for each key present in the `parameters` of this instance and that each attribute value is a match for the given parameter. The match is done using case expression semantics.

This method is only called when the given value is found to be an instance of the base type of this extension.

@param o [Object] the instance to test @param guard guard against endless recursion @return [Boolean] true or false to indicate if the value is an instance or not @api public

    # File lib/puppet/pops/types/p_object_type_extension.rb
207 def test_instance?(o, guard)
208   eval = Parser::EvaluatingParser.singleton.evaluator
209   @parameters.keys.all? do |pn|
210     begin
211       m = o.public_method(pn)
212       m.arity == 0 ? eval.match?(m.call, @parameters[pn]) : false
213     rescue NameError
214       false
215     end
216   end
217 end