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
Public Class Methods
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 26 def self.create(base_type, init_parameters) 27 impl_class = Loaders.implementation_registry.module_for_type("#{base_type.name}TypeExtension") || self 28 impl_class.new(base_type, init_parameters) 29 end
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 38 def self.create_from_instance(base_type, instance) 39 type_parameters = base_type.type_parameters(true) 40 attrs = base_type.attributes(true) 41 params = type_parameters.keys.map do |pn| 42 attr = attrs[pn] 43 attr.nil? ? nil : instance.send(pn) 44 end 45 create(base_type, params) 46 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 53 def initialize(base_type, init_parameters) 54 pts = base_type.type_parameters(true) 55 raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using []') % { label: base_type.label } if pts.empty? 56 @base_type = base_type 57 58 named_args = init_parameters.size == 1 && init_parameters[0].is_a?(Hash) 59 if named_args 60 # Catch case when first parameter is an assignable Hash 61 named_args = pts.size >= 1 && !pts.values[0].type.instance?(init_parameters[0]) 62 end 63 64 by_name = {} 65 if named_args 66 hash = init_parameters[0] 67 hash.each_pair do |pn, pv| 68 tp = pts[pn] 69 if tp.nil? 70 raise Puppet::ParseError, _("'%{pn}' is not a known type parameter for %{label}-Type") % { pn: pn, label: base_type.label } 71 end 72 by_name[pn] = check_param(tp, pv) unless pv == :default 73 end 74 else 75 pts.values.each_with_index do |tp, idx| 76 if idx < init_parameters.size 77 pv = init_parameters[idx] 78 by_name[tp.name] = check_param(tp, pv) unless pv == :default 79 end 80 end 81 end 82 if by_name.empty? 83 raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using an empty parameter list') % { label: base_type.label } 84 end 85 @parameters = by_name 86 end
# File lib/puppet/pops/types/p_object_type_extension.rb 12 def self.register_ptype(loader, ir) 13 create_ptype(loader, ir, 'AnyType', 14 'base_type' => { 15 KEY_TYPE => PTypeType::DEFAULT 16 }, 17 'init_parameters' => { 18 KEY_TYPE => PArrayType::DEFAULT 19 } 20 ) 21 end
Public Instance Methods
# File lib/puppet/pops/types/p_object_type_extension.rb 48 def [](name) 49 @base_type[name] 50 end
# File lib/puppet/pops/types/p_object_type_extension.rb 88 def check_param(type_param, v) 89 TypeAsserter.assert_instance_of(nil, type_param.type, v) { type_param.label } 90 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 132 def check_self_recursion(originator) 133 @base_type.check_self_recursion(originator) 134 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 137 def create(*args) 138 @base_type.create(*args) 139 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 112 def eql?(o) 113 super(o) && @base_type.eql?(o.base_type) && @parameters.eql?(o.parameters) 114 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 117 def generalize 118 @base_type 119 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 122 def hash 123 @base_type.hash ^ @parameters.hash 124 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 157 def implementation_class(create = true) 158 @base_type.implementation_class(create) 159 end
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 96 def init_parameters 97 pts = @base_type.type_parameters(true) 98 if pts.size > 2 99 @parameters 100 else 101 result = pts.values.map do |tp| 102 pn = tp.name 103 @parameters.include?(pn) ? @parameters[pn] : :default 104 end 105 # Remove trailing defaults 106 result.pop while result.last == :default 107 result 108 end 109 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 142 def instance?(o, guard = nil) 143 @base_type.instance?(o, guard) && test_instance?(o, guard) 144 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 127 def loader 128 @base_type.loader 129 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 147 def new_function 148 @base_type.new_function 149 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 162 def parameter_info(impl_class) 163 @base_type.parameter_info(impl_class) 164 end
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 152 def simple_name 153 @base_type.simple_name 154 end
Protected Instance Methods
@api private
# File lib/puppet/pops/types/p_object_type_extension.rb 219 def _assignable?(o, guard = nil) 220 if o.is_a?(PObjectTypeExtension) 221 @base_type.assignable?(o.base_type, guard) && test_assignable?(o.parameters, guard) 222 else 223 @base_type.assignable?(o, guard) && test_assignable?(EMPTY_HASH, guard) 224 end 225 end
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 179 def test_assignable?(param_values, guard) 180 # Default implementation performs case expression style matching of all parameter values 181 # provided that the value exist (this should always be the case, since all defaults have 182 # been assigned at this point) 183 eval = Parser::EvaluatingParser.singleton.evaluator 184 @parameters.keys.all? do |pn| 185 if param_values.include?(pn) 186 a = param_values[pn] 187 b = @parameters[pn] 188 eval.match?(a, b) || a.is_a?(PAnyType) && b.is_a?(PAnyType) && b.assignable?(a) 189 else 190 false 191 end 192 end 193 end
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 206 def test_instance?(o, guard) 207 eval = Parser::EvaluatingParser.singleton.evaluator 208 @parameters.keys.all? do |pn| 209 begin 210 m = o.public_method(pn) 211 m.arity == 0 ? eval.match?(m.call, @parameters[pn]) : false 212 rescue NameError 213 false 214 end 215 end 216 end