class TPX_2_2::HeterogeneousList

A list (Array) whose elements are not all the same type or do not have the same id attribute. The HeterogenousList defines an array of [ChildClass, child_id_attribute_name] as the accepted :child_types.

Attributes

child_types[RW]

The types of objects and their id attribute names accepted by the HeterogeneousList. An Array of Arrays like [[ChildClass, child_id_attribute], [AnotherChildClass, another_child_id_attribute]].

child_id_of[RW]

Hash lookup accessor to list members. Hash of hashes like child_id_of[child_id_val] = child

Public Class Methods

children_of_class_and_id(child_class_id_array) click to toggle source

Defines the child class types that the list accepts. Another accessor for ‘child_types`.

@param [Array] child_class_id_array The list of [Class, id_atttribute_name] to accept as list members.

# File lib/tpx/2_2/heterogeneous_list.rb, line 17
def children_of_class_and_id(child_class_id_array)
  self.child_types = child_class_id_array
end
new(input_array) click to toggle source

Initialize a new HeterogeneousList from an Array.

@param [Array] input_array The Array of HeterogeneousList.child_types included classes (or Hash to be initialized as HeterogeneousList.child_type classes) to create the HeterogeneousList object from.

Calls superclass method
# File lib/tpx/2_2/heterogeneous_list.rb, line 29
def initialize(input_array)
  unless input_array.is_a? Array
    raise ValidationError, "Supplied parameter (#{input_array.inspect}) to #{self.class}#initialize should be of type Array!"
  end

  @child_id_of = {}
  validated_array = []

  input_array.each_with_index do |child, i|
    validate_expected_child_type(child, i)
    new_initialized_child = nil
    new_initialized_child_type = nil

    self.class.child_types.each do |child_type|
      if child.class == child_type[0] && child.has_key?(child_type[1])
        new_initialized_child = child
        new_initialized_child_type = child_type
        break
      elsif child.has_key?(child_type[1])
        new_initialized_child = child_type[0].new(child)
        new_initialized_child_type = child_type
        break
      end
    end

    if new_initialized_child
      validate_unique(new_initialized_child, new_initialized_child_type)
      child_id_of[new_initialized_child_type[0]] ||= {}
      child_id_of[new_initialized_child_type[0]][new_initialized_child[new_initialized_child_type[1]]] = new_initialized_child
      validated_array << new_initialized_child
    end
  end

  super validated_array
end

Public Instance Methods

<<(child) click to toggle source

Add a new child to the HeterogeneousList (push).

@param [Hash or HeterogeneousList.type] child The object to add to the HeterogeneousList.

Calls superclass method
# File lib/tpx/2_2/heterogeneous_list.rb, line 68
def <<(child)
  child_type = validate_expected_child_type(child)
  validate_unique(child, child_type)
  child_id_of[child_type[0]] ||= {}
  child_id_of[child_type[0]][child[child_type[1]]] = child
  super child
end
pos_msg(i) click to toggle source
# File lib/tpx/2_2/heterogeneous_list.rb, line 122
def pos_msg(i)
  pos_msg = i.nil? ? '' : " at position #{i}"
end
validate_expected_child_type(child, i=nil) click to toggle source

Validate that a child is of the proper type to add to the HeterogeneousList.

@param [Hash or one of HeterogeneousList.child_types] child The object to verify is one of HeterogeneousList.child_types. @param [Integer] i The position, if any, in the list of the object to verify is one of HeterogeneousList.child_types.

# File lib/tpx/2_2/heterogeneous_list.rb, line 80
def validate_expected_child_type(child, i=nil)
  if child.class == Hash || child.class == HashWithIndifferentAccess
    validate_expected_child_type_from_hash(child, i)
  else
    validate_expected_child_type_from_initialized_object(child, i)
  end
end
validate_expected_child_type_from_hash(child, i=nil) click to toggle source

Validate that a child is of the proper type to add to the HeterogeneousList.

@param [Hash] child The object to verify is one of HeterogeneousList.child_types. @param [Integer] i The position, if any, in the list of the object to verify is one of HeterogeneousList.child_types.

# File lib/tpx/2_2/heterogeneous_list.rb, line 92
def validate_expected_child_type_from_hash(child, i=nil)
  child_type_key_count = 0
  child_type_found = nil
  self.class.child_types.each do |child_type|
    if child.has_key?(child_type[1])
      child_type_key_count += 1
      child_type_found = child_type
    end
  end
  if child_type_key_count > 1
    raise ValidationError, "Supplied input object #{child.inspect}#{pos_msg} has multiple subject types in #{self.class}!"
  elsif child_type_key_count == 0
    raise ValidationError, "Supplied input object #{child.inspect}#{pos_msg(i)} not one of required types #{self.class.child_types} in #{self.class}!"
  end
  return child_type_found
end
validate_expected_child_type_from_initialized_object(child, i=nil) click to toggle source

Validate that a child is of the proper type to add to the HeterogeneousList.

@param [one of HeterogeneousList.child_types] child The object to verify is one of HeterogeneousList.child_types. @param [Integer] i The position, if any, in the list of the object to verify is one of HeterogeneousList.child_types.

# File lib/tpx/2_2/heterogeneous_list.rb, line 113
def validate_expected_child_type_from_initialized_object(child, i=nil)
  self.class.child_types.each do |child_type|
    if child.class == child_type[0] && child.has_key?(child_type[1])
      return child_type
    end
  end
  raise ValidationError, "Supplied input object #{child.inspect}#{pos_msg(i)} not one of required types #{self.class.child_types} in #{self.class}!"
end
validate_unique(child, child_type) click to toggle source

Validate that a child is not contained in the list prior to adding to the HeterogeneousList.

@param [Hash or HeterogeneousList.type] child The object to verify is not already contained in HeterogeneousList.

# File lib/tpx/2_2/heterogeneous_list.rb, line 129
def validate_unique(child, child_type)
  if child_id_of.has_key?(child_type[0]) and child_id_of[child_type[0]].has_key?(child[child_type[1]])
    raise TPX_2_2::DuplicateElementInsertError, "Duplicate input object id #{child[child_type[1]]} provided to #{self.class}!"
  end
end