class Unimatrix::Parser

Public Class Methods

new( content = {} ) { |self| ... } click to toggle source
# File lib/unimatrix/parser.rb, line 5
def initialize( content = {} )
  @content = content
  yield self if block_given?
end

Public Instance Methods

associations() click to toggle source
# File lib/unimatrix/parser.rb, line 32
def associations
  @content.include?( '$associations' ) ?
    @content[ '$associations' ] :
    nil
end
find_resource_class_by_type_name( attribute_type_name, option_type_name ) click to toggle source
# File lib/unimatrix/parser.rb, line 124
def find_resource_class_by_type_name( attribute_type_name, option_type_name )
  resource_class = Resource.find_by_type_name( attribute_type_name )
  unless resource_class.present?
    resource_class = Resource.find_by_type_name( option_type_name )
  end
  resource_class
end
key() click to toggle source
# File lib/unimatrix/parser.rb, line 22
def key
  'id'
end
keys() click to toggle source
# File lib/unimatrix/parser.rb, line 26
def keys
  @content.include?( '$this' ) ?
    @content[ '$this' ][ 'ids' ] :
    nil
end
name() click to toggle source
# File lib/unimatrix/parser.rb, line 10
def name
  @content.include?( '$this' ) ?
    @content[ '$this' ][ 'name' ] :
    nil
end
parse_resource( name, attributes ) click to toggle source
# File lib/unimatrix/parser.rb, line 49
def parse_resource( name, attributes )

  @resources_mutex ||= Hash.new { | hash, key | hash[ key ] = [] }
  resource_key = attributes[ key ]

  # Lock the resource index for this name/key combination
  # This prevents objects that are associated with
  # themselves from causing a stack overflow
  return nil if @resources_mutex[ name ].include?( resource_key )
  @resources_mutex[ name ].push( resource_key )

  resource = nil

  if attributes.present?

    resource_type_name = attributes[ :type_name ] || self.type_name
    resource_class =
      Resource.find_by_type_name( resource_type_name ) ||
      Resource.find_by_type_name( self.type_name )

    if resource_class.present?
      relations = name == self.name ?
        self.parse_associations( attributes ) : []
      resource = resource_class.build( attributes, relations )
    end

  end

  @resources_mutex[ name ].delete( object_key )

  resource

end
resource_associations_by( name, key ) click to toggle source
# File lib/unimatrix/parser.rb, line 132
def resource_associations_by( name, key )
  result = Hash.new { | hash, key | hash[ key ] = [] }
  associations = self.associations
  if associations && associations.include?( name )
    association = associations[ name ].detect do | association |
      association[ 'id' ] == key
    end
    if association.present?
      association.each do | key, value |
        unless key == 'id'
          type_name = value[ 'type_name' ]
          result[ key ] = ( value[ 'ids' ] || [] ).map do | associated_id |
            self.resource_by(
              key,
              associated_id,
              { 'type_name' => type_name }
            )
          end
          result[ key ].compact!
        end
      end
    end
  end
  result
end
resource_attribute_index() click to toggle source
# File lib/unimatrix/parser.rb, line 158
def resource_attribute_index
  @resource_attribute_index ||= begin
    index = Hash.new { | hash, key | hash[ key ] = {} }
    @content.each do | key, resources_attributes |
      unless key[0] == '$'
        resources_attributes.each do | resource_attributes |
          index[ key ][ resource_attributes[ 'id' ] ] = resource_attributes
        end
      end
    end
    index
  end
end
resource_by( name, key, options = {} ) click to toggle source
# File lib/unimatrix/parser.rb, line 83
def resource_by( name, key, options = {} )

  @resources_index ||= Hash.new { | hash, key | hash[ key ] = {} }
  @resource_index_mutex ||= Hash.new { | hash, key | hash[ key ] = [] }

  @resources_index[ name ][ key ] ||= begin

    # lock the resource index for this name/key combination
    # note: this prevents Unimatrix objects that are associated with
    #       themselves from causing a stack overflow
    return nil if @resource_index_mutex[ name ].include?( key )
    @resource_index_mutex[ name ].push( key )

    result = nil
    resource_attributes = resource_attribute_index[ name ][ key ]
    
      if resource_attributes.present?
        
        parse_nested_attributes( resource_attributes )
        
        resource_class = find_resource_class_by_type_name(
          resource_attributes[ 'type_name' ],
          options[ 'type_name' ]
        )
        if resource_class.present?
          result = resource_class.build(
            resource_attributes,
            self.resource_associations_by( name, key )
          )
        end
      end

    # unlock the resource index for this name/key combination
    @resource_index_mutex[ name ].delete( key )

    result

  end

end
resources() click to toggle source
# File lib/unimatrix/parser.rb, line 38
def resources
  result = nil

  unless self.name.blank?
    result = self.keys.map do | key |
      self.resource_by( name, key, { 'type_name' => self.type_name } )
    end
  end
  result
end
type_name() click to toggle source
# File lib/unimatrix/parser.rb, line 16
def type_name
  @content.include?( '$this' ) ?
    @content[ '$this' ][ 'type_name' ] :
    nil
end

Private Instance Methods

parse_nested_attributes( attributes ) click to toggle source
# File lib/unimatrix/parser.rb, line 172
         def parse_nested_attributes( attributes )

  nested_attributes = {}

  attributes.delete_if do | key, value |

    if key.include?( '.' )

      key, nested_key = key.split( '.' )

      if nested_attributes[ key ].present?
        nested_attributes[ key ][ nested_key.to_sym ] = value
      else
        nested_attributes[ key ] = { nested_key.to_sym => value }
      end

      true

    else
      false
    end

  end

  if nested_attributes.present?

    nested_attributes.each do | key, value |

      attributes[ key ] = Struct.new( *value.keys ).new

      value.each do | nested_key, nested_value |
        attributes[ key ][ nested_key ] = nested_value
      end

    end

  end

end