class Puppet::Pops::Binder::BindingsChecker

A validator/checker of a bindings model @api public

Constants

Bindings
Issues
Types

Attributes

acceptor[R]
type_calculator[R]

Public Instance Methods

binding_parent(p) click to toggle source

@api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 186
def binding_parent(p)
  begin
    x = p.eContainer
    if x.nil?
      acceptor.accept(Issues::MODEL_OBJECT_IS_UNBOUND, p)
      return nil
    end
    p = x
  end while !p.is_a?(Bindings::AbstractBinding)
  p
end
check(b) click to toggle source

Performs binding validity check @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 33
def check(b)
  @@check_visitor.visit_this_0(self, b)
end
check_ArrayMultibindProducerDescriptor(p) click to toggle source

Checks that the type declared in the binder is a PArrayType @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 144
def check_ArrayMultibindProducerDescriptor(p)
  b = binding_parent(p)
  acceptor.accept(Issues::MULTIBIND_INCOMPATIBLE_TYPE, p, {:binding => b, :actual_type => b.type}) unless b.type.is_a?(Types::PArrayType)
end
check_Binding(b) click to toggle source

Checks that a binding has a producer and a type @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 39
def check_Binding(b)
  # Must have a type
  acceptor.accept(Issues::MISSING_TYPE, b) unless b.type.is_a?(Types::PAnyType)

  # Must have a producer
  acceptor.accept(Issues::MISSING_PRODUCER, b) unless b.producer.is_a?(Bindings::ProducerDescriptor)
end
check_Bindings(b) click to toggle source

Checks that the bindings object contains at least one binding. Then checks each binding in turn @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 63
def check_Bindings(b)
  acceptor.accept(Issues::MISSING_BINDINGS, b) unless has_entries?(b.bindings)
end
check_ConstantProducerDescriptor(p) click to toggle source

Checks that a constant value has been declared in the producer and that the type of the value is compatible with the type declared in the binding @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 95
def check_ConstantProducerDescriptor(p)
  # the product must be of compatible type
  # TODO: Likely to change when value becomes a typed Puppet Object
  b = binding_parent(p)
  if p.value.nil?
    acceptor.accept(Issues::MISSING_VALUE, p, {:binding => b})
  else
    infered = type_calculator.infer(p.value)
    unless type_calculator.assignable?(b.type, infered)
      acceptor.accept(Issues::INCOMPATIBLE_TYPE, p, {:binding => b, :expected_type => b.type, :actual_type => infered})
    end
  end
end
check_EvaluatingProducerDescriptor(p) click to toggle source

Checks that an expression has been declared in the producer @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 111
def check_EvaluatingProducerDescriptor(p)
  unless p.expression.is_a?(Puppet::Pops::Model::Expression)
    acceptor.accept(Issues::MISSING_EXPRESSION, p, {:binding => binding_parent(p)})
  end
end
check_Expression(t) click to toggle source

@api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 165
def check_Expression(t)
  @expression_validator.validate(t)
end
check_HashLookupProducerDescriptor(p) click to toggle source

Checks that a key has been declared, then calls producer_LookupProducerDescriptor to perform checks associated with the super class @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 137
def check_HashLookupProducerDescriptor(p)
  acceptor.accept(Issues::MISSING_KEY, p, {:binding => binding_parent(p)}) unless has_chars?(p.key)
  check_LookupProducerDescriptor(p)
end
check_HashMultibindProducerDescriptor(p) click to toggle source

Checks that the type declared in the binder is a PHashType @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 151
def check_HashMultibindProducerDescriptor(p)
  b = binding_parent(p)
  acceptor.accept(Issues::MULTIBIND_INCOMPATIBLE_TYPE, p, {:binding => b, :actual_type => b.type}) unless b.type.is_a?(Types::PHashType)
end
check_InstanceProducerDescriptor(p) click to toggle source

Checks that a class name has been declared in the producer @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 119
def check_InstanceProducerDescriptor(p)
  acceptor.accept(Issues::MISSING_CLASS_NAME, p, {:binding => binding_parent(p)}) unless has_chars?(p.class_name)
end
check_LayeredBindings(b) click to toggle source

Checks that the binding has layers and that each layer has a name and at least one binding @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 82
def check_LayeredBindings(b)
  acceptor.accept(Issues::MISSING_LAYERS, b) unless has_entries?(b.layers)
end
check_LookupProducerDescriptor(p) click to toggle source

Checks that a type and a name has been declared. The type must be assignable to the type declared in the binding. The name can be an empty string to denote ‘no name’ @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 126
def check_LookupProducerDescriptor(p)
  b = binding_parent(p)
  unless type_calculator.assignable(b.type, p.type)
    acceptor.accept(Issues::INCOMPATIBLE_TYPE, p, {:binding => b, :expected_type => b.type, :actual_type => p.type })
  end
  acceptor.accept(Issues::MISSING_NAME, p, {:binding => b}) if p.name.nil? # empty string is OK
end
check_Multibinding(b) click to toggle source

Checks that the producer is a Multibind producer and that the type is a PCollectionType @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 49
def check_Multibinding(b)
  # id is optional (empty id blocks contributions)

  # A multibinding must have PCollectionType
  acceptor.accept(Issues::MULTIBIND_TYPE_ERROR, b, {:actual_type => b.type})  unless b.type.is_a?(Types::PCollectionType)

  # if the producer is nil, a suitable producer will be picked automatically
  unless b.producer.nil? || b.producer.is_a?(Bindings::MultibindProducerDescriptor)
    acceptor.accept(Issues::MULTIBIND_NOT_COLLECTION_PRODUCER, b, {:actual_producer => b.producer})
  end
end
check_NamedBindings(b) click to toggle source

Checks that a name has been associated with the bindings @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 69
def check_NamedBindings(b)
  acceptor.accept(Issues::MISSING_BINDINGS_NAME, b) unless has_chars?(b.name)
  check_Bindings(b)
end
check_NamedLayer(l) click to toggle source

Check layer has a name @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 76
def check_NamedLayer(l)
  acceptor.accept(Issues::MISSING_LAYER_NAME, binding_parent(l)) unless has_chars?(l.name)
end
check_NonCachingProducerDescriptor(p) click to toggle source

Checks that the non caching producer has a producer to delegate to @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 88
def check_NonCachingProducerDescriptor(p)
  acceptor.accept(Issues::PRODUCER_MISSING_PRODUCER, p) unless p.producer.is_a?(Bindings::ProducerDescriptor)
end
check_PAnyType(t) click to toggle source

@api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 170
def check_PAnyType(t)
  # Do nothing
end
check_ProducerProducerDescriptor(p) click to toggle source

Checks that the producer that this producer delegates to is declared @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 158
def check_ProducerProducerDescriptor(p)
  unless p.producer.is_a?(Bindings::ProducerDescriptor)
    acceptor.accept(Issues::PRODUCER_MISSING_PRODUCER, p, {:binding => binding_parent(p)})
  end
end
has_chars?(s) click to toggle source

Returns true if the argument is a non empty string @api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 176
def has_chars?(s)
  s.is_a?(String) && !s.empty?
end
has_entries?(s) click to toggle source

@api private

# File lib/puppet/pops/binder/bindings_checker.rb, line 181
def has_entries?(s)
  !(s.nil? || s.empty?)
end
validate(b) click to toggle source

Validates the entire model by visiting each model element and calling `check`. The result is collected (or acted on immediately) by the configured diagnostic provider/acceptor given when creating this Checker.

@api public

# File lib/puppet/pops/binder/bindings_checker.rb, line 26
def validate(b)
  check(b)
  b.eAllContents.each {|c| check(c) }
end

Public Class Methods

new(diagnostics_producer) click to toggle source

@api public

# File lib/puppet/pops/binder/bindings_checker.rb, line 13
def initialize(diagnostics_producer)
  @@check_visitor     ||= Puppet::Pops::Visitor.new(nil, "check", 0, 0)
  @type_calculator      = Puppet::Pops::Types::TypeCalculator.new()
  @expression_validator = Puppet::Pops::Validation::ValidatorFactory_4_0.new().checker(diagnostics_producer)
  @acceptor             = diagnostics_producer
end