class A4Tools::TalkConsumer

Attributes

definition[R]

Public Class Methods

new(defn=nil) click to toggle source
# File lib/talk_consumer.rb, line 7
def initialize(defn=nil)
  self.definition = translate_definition(defn)
  @constants = {}

  setup_constants
end

Public Instance Methods

[](key) click to toggle source
# File lib/talk_consumer.rb, line 228
def [](key)
  return @constants[key.to_sym][:constant][:value]
end
class_fields_match?(cls, obj) click to toggle source
# File lib/talk_consumer.rb, line 172
def class_fields_match?(cls, obj)
  return false unless obj.is_a? Hash
  obj.keys.each { |key| return false if field_named(cls, key).nil? }
  cls[:field].each { |field| return false unless obj.has_key?(field[:name].to_sym) }
  true
end
class_named(name) click to toggle source
# File lib/talk_consumer.rb, line 85
def class_named(name)
  @definition[:class].each { |cls| return cls if name_matches?(cls[:name], name) }
  nil
end
constant_named(name, collection=nil) click to toggle source
# File lib/talk_consumer.rb, line 121
def constant_named(name, collection=nil)
  if collection.nil? then
    constant = @constants[name.to_sym]
    return constant[:constant], constant[:container] unless constant.nil?
    return nil, nil
  end

  collection = glossary_named(collection) || enumeration_named(collection) if collection.is_a? String
  return nil if collection.nil?

  set = collection[:term] || collection[:constant]
  return (set.select { |item| (item[:name] == name or item[:value] == name or item[:value] == name.to_f) }).first, collection
end
definition=(defn) click to toggle source
# File lib/talk_consumer.rb, line 14
def definition=(defn)
  @definition = symbolify translate_definition(defn)

  @definition[:class] ||= []
  @definition[:class].each { |cls| cls[:field] ||= [] }

  @definition[:enumeration] ||= []
  @definition[:enumeration].each { |enum| enum[:constant] ||= [] }

  @definition[:glossary] ||= []
  @definition[:glossary].each { |glossary| glossary[:term] ||= [] }
end
enumeration_named(name) click to toggle source
# File lib/talk_consumer.rb, line 116
def enumeration_named(name)
  @definition[:enumeration].select { |enum| return enum if name_matches?(enum[:name], name) }
  nil
end
expand_name(name) click to toggle source
# File lib/talk_consumer.rb, line 218
def expand_name(name)
  return nil if name.nil?
  [ :class_named, :glossary_named, :enumeration_named ].each do |method|
    thing = send(method, name)
    return thing[:name] unless thing.nil?
  end

  nil
end
field_named(cls, name) click to toggle source
# File lib/talk_consumer.rb, line 80
def field_named(cls, name)
  cls[:field].each { |field| return field if field[:name] == name.to_s }
  nil
end
get_field_from_object(object, field_name) click to toggle source
# File lib/talk_consumer.rb, line 188
def get_field_from_object(object, field_name)
  m = field_name.to_s.match(/^([a-zA-Z0-9_]+)\[([0-9]+)\]$/)
  if m.nil? then
    return field_name, (object[field_name.to_sym] rescue nil)
  else
    name = m[1]
    value = object[name.to_sym][m[2].to_i] rescue nil
    return name, value
  end
end
glossary_named(name) click to toggle source
# File lib/talk_consumer.rb, line 111
def glossary_named(name)
  @definition[:glossary].select { |glossary| return glossary if name_matches?(glossary[:name], name) }
  nil
end
guess_class(obj) click to toggle source
# File lib/talk_consumer.rb, line 179
def guess_class(obj)
  return obj[:__class] if obj.has_key? :__class
  return "com.acres4.common.info.NamedObjectWrapper" if obj.has_key? :className
  return "com.acres4.common.info.JSONRPCResponse" if obj.has_key? :result and obj.has_key? :jsonrpc
  return "com.acres4.common.info.JSONRPCRequest" if obj.has_key? :request and obj.has_key? :jsonrpc
  @definition[:class].each { |cls| return cls[:name] if class_fields_match?(cls, obj) }
  nil
end
locate_data(object, path, classhint=nil) click to toggle source
# File lib/talk_consumer.rb, line 199
def locate_data(object, path, classhint=nil)
  path = path.split(".") if path.is_a? String
  path = [] if path.nil?

  type = classhint || guess_class(object)
  return object, type if type.nil? or path.empty?

  cls = class_named(type)
  return nil if cls.nil?

  field_name, value = get_field_from_object(object, path.first)
  return nil if field_name.nil? or value.nil?

  field = field_named(cls, field_name)
  return nil if field.nil?

  locate_data(value, path[1..-1], field[:type].first)
end
method_named(name, protocol=nil) click to toggle source
# File lib/talk_consumer.rb, line 95
def method_named(name, protocol=nil)
  protocol = protocol_named(protocol) if(protocol.is_a? String)
  if protocol.nil? then
    @definition[:protocol].each do |proto|
      next if proto[:method].nil?
      proto[:method].each do |m|
        next if !m.is_a? Hash || m[:name].nil?
        return m, proto if m[:name] == name
      end
    end

    return nil
  end
  return (protocol[:method].select { |method| method[:name] == name }).first, protocol
end
methods_in_protocol(protocol) click to toggle source
# File lib/talk_consumer.rb, line 158
def methods_in_protocol(protocol)
  protocol = protocol_named(name) if(protocol.is_a? String)
  protocol[:method]
end
name_matches?(cls_name, name) click to toggle source
# File lib/talk_consumer.rb, line 57
def name_matches?(cls_name, name)
  cls_name[-name.length .. -1] == name
end
name_similar?(item_name, name) click to toggle source
# File lib/talk_consumer.rb, line 61
def name_similar?(item_name, name)
  item_name = item_name[:name] if item_name.is_a? Hash
  return false if item_name.nil?

  item_comps = item_name.split(".")
  comps = name.split(".")
  return true if name == item_name
  return true if item_name.end_with? name
  if item_comps.last.start_with? comps.last then
    return false if comps.length > item_comps.length
    comps[0..-2].reverse.each_index do |idx|
      return false unless item_comps[-1 - idx] == comps[idx]
    end
    return true
  end

  return false
end
primitive?(type) click to toggle source
# File lib/talk_consumer.rb, line 47
def primitive?(type)
  type = type[:type] if type.is_a? Hash
  type = type.first if type.is_a? Array
  primitives = [
    "uint8", "uint16", "uint32", "uint64",
    "int8", "int16", "int32", "int64",
    "string", "real", "bool", "object", "talkobject" ]
  primitives.include? type
end
protocol_named(name) click to toggle source
# File lib/talk_consumer.rb, line 90
def protocol_named(name)
  @definition[:protocol].each { |proto| return proto if proto[:name] == name }
  nil
end
setup_constants() click to toggle source
# File lib/talk_consumer.rb, line 163
def setup_constants
  @definition[:enumeration].each do |enum|
    enum[:constant].each { |constant| @constants[constant[:name].to_sym] = { constant:constant, container:enum } }
  end
  @definition[:glossary].each do |glossary|
    glossary[:term].each { |term| @constants[term[:name].to_sym] = { constant:term, container:glossary } }
  end
end
things_named_like(name, allowed=nil, exclude=[:field]) click to toggle source
# File lib/talk_consumer.rb, line 152
def things_named_like(name, allowed=nil, exclude=[:field])
  allowed ||= @definition.keys
  allowed = [allowed] unless allowed.is_a? Array
  allowed.inject([]) { |total, key| total + things_named_recursive(name, @definition[key], exclude) }
end
things_named_recursive(name, collection, exclude) click to toggle source
# File lib/talk_consumer.rb, line 135
def things_named_recursive(name, collection, exclude)
  total = []
  if collection.is_a? Array then
    collection.each do |item|
      next if item.nil?
      total += things_named_recursive(name, item, exclude)
    end
  elsif collection.is_a? Hash then
    total.push(collection) if name_similar?(collection, name)
    collection.each do |key, item|
      total += things_named_recursive(name, item, exclude) unless (item.nil? or exclude.include? key)
    end
  end

  total
end
translate_definition(defn) click to toggle source
# File lib/talk_consumer.rb, line 27
def translate_definition(defn)
  # Accept the definition if it's already a hash or nil
  return defn if defn.is_a? Hash or defn.nil?

  # Try to parse the definition as a JSON string, then try to treat it as a path to a file
  [ lambda { JSON.parse(defn) }, lambda { JSON.parse(IO.read(defn)) } ].each do |func|
    begin
      return func.call
    rescue JSON::ParserError
    end
  end

  nil
end
truncated_name(name) click to toggle source
# File lib/talk_consumer.rb, line 42
def truncated_name(name)
  name = name[:name] if name.is_a? Hash
  name.to_s.split(".").last
end