class AMA::Entity::Mapper::Type

Type wrapper

Attributes

attributes[RW]

@!attribute attributes

@return [Hash{Symbol, AMA::Entity::Mapper::Type::Attribute}]
parameters[RW]

@!attribute parameters

@return [Hash{Symbol, AMA::Entity::Mapper::Type::Parameter}]
type[RW]

@!attribute type

@return [Class]
virtual[RW]

@!attribute virtual

@return [TrueClass, FalseClass]

Public Class Methods

new(klass, virtual: false) click to toggle source

@param [Class, Module] klass

# File lib/ama-entity-mapper/type.rb, line 62
def initialize(klass, virtual: false)
  @type = validate_type!(klass)
  @parameters = {}
  @attributes = {}
  @virtual = virtual
end

Public Instance Methods

==(other) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 179
def ==(other)
  eql?(other)
end
attribute!(name, *types, **options) click to toggle source

Shortcut for attribute creation.

@param [String, Symbol] name @param [Array<AMA::Entity::Mapper::Type>] types @param [Hash] options

# File lib/ama-entity-mapper/type.rb, line 101
def attribute!(name, *types, **options)
  name = name.to_sym
  types = types.map do |type|
    next type if type.is_a?(Parameter)
    next parameter!(type) if type.is_a?(Symbol)
    next self.class.new(type) unless type.is_a?(Type)
    type
  end
  attributes[name] = Attribute.new(self, name, *types, **options)
end
eql?(other) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 174
def eql?(other)
  return false unless other.is_a?(self.class)
  @type == other.type && @attributes == other.attributes
end
hash() click to toggle source
# File lib/ama-entity-mapper/type.rb, line 170
def hash
  @type.hash ^ @attributes.hash
end
instance!(object, context) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 79
def instance!(object, context)
  return if instance?(object)
  message = "Provided object #{object} is not an instance of #{self}"
  validation_error(message, context: context)
end
instance?(object) click to toggle source

Tells if provided object is an instance of this type.

This doesn't mean all of it's attributes do match requested types.

@param [Object] object @return [TrueClass, FalseClass]

# File lib/ama-entity-mapper/type.rb, line 75
def instance?(object)
  object.is_a?(@type)
end
parameter!(id) click to toggle source

Creates new type parameter

@param [Symbol] id @return [Parameter]

# File lib/ama-entity-mapper/type.rb, line 116
def parameter!(id)
  id = id.to_sym
  return @parameters[id] if @parameters.key?(id)
  @parameters[id] = Parameter.new(self, id)
end
resolve(parameters) click to toggle source

@param [Hash<AMA::Entity::Mapper::Type, AMA::Entity::Mapper::Type>] parameters @return [AMA::Entity::Mapper::Type]

# File lib/ama-entity-mapper/type.rb, line 146
def resolve(parameters)
  parameters.reduce(self) do |carrier, tuple|
    carrier.resolve_parameter(*tuple)
  end
end
resolve_parameter(parameter, substitution) click to toggle source

Resolves single parameter type. Substitution may be either another parameter or array of types.

@param [Parameter] parameter @param [Parameter, Array<Type>] substitution

# File lib/ama-entity-mapper/type.rb, line 127
def resolve_parameter(parameter, substitution)
  parameter = validate_parameter!(parameter)
  substitution = validate_substitution!(substitution)
  clone.tap do |clone|
    intermediate = attributes.map do |key, value|
      [key, value.resolve_parameter(parameter, substitution)]
    end
    clone.attributes = Hash[intermediate]
    intermediate = clone.parameters.map do |key, value|
      [key, value == parameter ? substitution : value]
    end
    clone.parameters = Hash[intermediate]
  end
end
resolved!(context = Context.new) click to toggle source

Validates that type is fully resolved, otherwise raises an error @param [AMA::Entity::Mapper::Context] context

# File lib/ama-entity-mapper/type.rb, line 92
def resolved!(context = Context.new)
  attributes.values.each { |attribute| attribute.resolved!(context) }
end
resolved?() click to toggle source

@return [TrueClass, FalseClass]

# File lib/ama-entity-mapper/type.rb, line 86
def resolved?
  attributes.values.all?(&:resolved?)
end
to_def() click to toggle source
# File lib/ama-entity-mapper/type.rb, line 191
def to_def
  return @type.to_s if parameters.empty?
  params = parameters.map do |key, value|
    value = [value] unless value.is_a?(Enumerable)
    value = value.map(&:to_def)
    value = value.size > 1 ? "[#{value.join(', ')}]" : value.first
    "#{key}:#{value}"
  end
  "#{@type}<#{params.join(', ')}>"
end
to_s() click to toggle source
# File lib/ama-entity-mapper/type.rb, line 183
def to_s
  message = "Type #{@type}"
  unless @parameters.empty?
    message += " (parameters: #{@parameters.keys})"
  end
  message
end
valid!(object, context) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 162
def valid!(object, context)
  violations = self.violations(object, context)
  return if violations.empty?
  message = "#{object} has failed type #{to_def} validation: " \
    "#{violations.join(', ')}"
  validation_error(message, context: context)
end
valid?(object, context) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 158
def valid?(object, context)
  violations(object, context).empty?
end
violations(object, context) click to toggle source

rubocop:enable Metrics/LineLength

# File lib/ama-entity-mapper/type.rb, line 154
def violations(object, context)
  validator.validate(object, self, context)
end

Private Instance Methods

validate_parameter!(parameter) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 211
def validate_parameter!(parameter)
  return parameter if parameter.is_a?(Parameter)
  message = "Non-parameter type #{parameter} " \
      'supplied for resolution'
  compliance_error(message)
end
validate_substitution!(substitution) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 218
def validate_substitution!(substitution)
  return substitution if substitution.is_a?(Parameter)
  substitution = [substitution] if substitution.is_a?(self.class)
  if substitution.is_a?(Enumerable)
    return validate_substitutions!(substitution)
  end
  message = 'Provided substitution is neither another Parameter ' \
      'or Array of Types: ' \
      "#{substitution} (#{substitution.class})"
  compliance_error(message)
end
validate_substitutions!(substitutions) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 230
def validate_substitutions!(substitutions)
  if substitutions.empty?
    compliance_error('Empty list of substitutions passed')
  end
  invalid = substitutions.reject do |substitution|
    substitution.is_a?(Type)
  end
  return substitutions if invalid.empty?
  compliance_error("Invalid substitutions supplied: #{invalid}")
end
validate_type!(type) click to toggle source
# File lib/ama-entity-mapper/type.rb, line 204
def validate_type!(type)
  return type if type.is_a?(Class) || type.is_a?(Module)
  message = 'Expected Type to be instantiated with ' \
      "Class/Module instance, got #{type}"
  compliance_error(message)
end