class Mobi::Mtld::Da::Device::Tree

Copyright
Author

Constants

API_ID
KEY_CHILDREN

tree key - has children

KEY_COMPILED_REGEX

tree key - list of compiled regexes

KEY_DATA

tree key - property data

KEY_DEVICE_ID

device-id property name

KEY_HEADERS

tree key - user-agent header names {“h”:{“sl”:}}

KEY_MAIN

tree key - tree main branch

KEY_MASKED

tree key - masked properties

KEY_META

tree key - {DATA-META-DATA}

KEY_META_REVISION

tree key - tree revision

KEY_META_TIMESTAMP

tree key - tree create time-stamp

KEY_META_VERSION

tree key - tree structure version

KEY_PROPERTY_NAMES

tree key - property names [property-name,]

KEY_REGEX

tree key - list of regexes [regex(String),]

KEY_UA_STOCK_HEADERS

tree key - stock user-agent header names {“h”:{“sl”:}}

KEY_VALUES

tree key - property values [property-value,]

MAP_INITIAL_CAPACITY

for MAP optimization, set to average number properties

MIN_JSON_VERSION

Attributes

data_revision[R]
properties[R]
stock_ua_headers[R]

A list of http-headers which may contain the original user-agent. if the tree does not contain KEY_UA_STOCK_HEADERS then this list will be used

tree[R]

Public Class Methods

new(json, config) click to toggle source

Load the JSON tree into a Hash.

# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 85
def initialize json, config
  @config = config

  begin
    @tree = JSON::Parser.new(json, :symbolize_names => true,
      :max_nesting => false).parse
  rescue
    raise Mobi::Mtld::Da::Exception::DataFileException, 'Invalid Json data.'
  end

  if @tree.nil? || !@tree.kind_of?(Hash)
    raise Mobi::Mtld::Da::Exception::DataFileException, "Unable to load Json data."
  end

  if !@tree.has_key?(KEY_META)
    raise Mobi::Mtld::Da::Exception::DataFileException, "Bad data loaded into the tree."
  end

  if @tree[KEY_META][KEY_META_VERSION].to_f < MIN_JSON_VERSION
    raise Mobi::Mtld::Da::Exception::DataFileException, "DeviceAtlas json file must be v" +
    " #{MIN_JSON_VERSION} or greater. Please download a more recent version."
  end

              # Prepare the user-agent rules branch before we start recognition.
              # To maintain backwards compatibility - only do this if we have the ua rules
  # branch
              if @tree[Mobi::Mtld::Da::Device::UaProps::KEY_UA_RULES] && @config.include_ua_props
    @ua_props = Mobi::Mtld::Da::Device::UaProps.new(self) # stick in the tree so we can use it later
  # remove the UAR branch to save some memory
  elsif @tree[Mobi::Mtld::Da::Device::UaProps::KEY_UA_RULES]
    @tree.delete(Mobi::Mtld::Da::Device::UaProps::KEY_UA_RULES)
  end
  
  # Prepare client side properties.
              if @tree[Mobi::Mtld::Da::Device::ClientProps::KEY_CP_RULES]
                      @client_props = Mobi::Mtld::Da::Device::ClientProps.new(self)
              end

  # cache values from the tree which are used by the API
  property_ids = @tree[KEY_PROPERTY_NAMES]
  max_property_ids = property_ids.size - 1
  for i in 0..max_property_ids
    if KEY_DEVICE_ID == property_ids[i]
      @device_id_prop_name_id = i.to_s.to_sym
      break
    end
  end

  # set ua headers
  @stock_ua_headers = [
    "x-device-user-agent",
    "x-original-user-agent",
    "x-operamini-phone-ua",
    "x-skyfire-phone",
    "x-bolt-phone-ua",
    "device-stock-ua",
    "x-ucbrowser-ua",
    "x-ucbrowser-device-ua",
    "x-ucbrowser-device",
    "x-puffin-ua"
  ]

  # update stock user-agent headers from tree
  headers = @tree[KEY_HEADERS]
  if !headers.nil?
    ua_stock_headers = headers[KEY_UA_STOCK_HEADERS]
    if !ua_stock_headers.nil?
      @stock_ua_headers = ua_stock_headers
    end
  end

  # set data revision
  @data_revision = @tree[KEY_META][KEY_META_REVISION]

end

Public Instance Methods

data_creation_timestamp() click to toggle source

Get data file creation timestamp

# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 173
def data_creation_timestamp
  return @tree[KEY_META][KEY_META_TIMESTAMP]
end
data_version() click to toggle source

Get data file version

# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 168
def data_version
  return @tree[KEY_META][KEY_META_VERSION]
end
property_name_by_id(property_id) click to toggle source
# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 265
def property_name_by_id property_id
  return @tree[KEY_PROPERTY_NAMES][property_id]
end
property_names() click to toggle source

Get the list of all available property names from the tree (not contains client side props)

# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 163
def property_names
  return @tree[KEY_PROPERTY_NAMES]
end
property_value_by_id(value_id) click to toggle source
# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 269
def property_value_by_id value_id
  return @tree[KEY_VALUES][value_id]
end
put_properties(user_agent, stock_user_agents, client_side_properties = nil) click to toggle source

Get properties from tree walk/ua/client-side and put them in the tree.properties

user_agent

user-agent string (from the original User-Agent header) to be

used for detecting ua-props

stock_user_agents

list of candidate user-agent strings to be used for

tree walk

client_side_properties

optional client side properties

# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 184
def put_properties user_agent, stock_user_agents, client_side_properties = nil
  # reset properties
  @properties = Mobi::Mtld::Da::Properties.new
  put_tree_walk_properties user_agent, stock_user_agents
  if !client_side_properties.nil? && !client_side_properties.empty?
    if @client_props.nil?
      # stop if the JSON file does not contain the required CPR section
      raise Mobi::Mtld::Da::Exception::ClientPropertiesException, "JSON data does not support client " +
      "properties."
    end
    @client_props.put_properties client_side_properties
  end
end
put_tree_walk_properties(user_agent, stock_user_agents = nil) click to toggle source

Get properties from tree walk/ua and put them in the tree.properties

if !stock_user_agents.nil?

- iterate over stockUserAgents
  for each item: tree-walk and stop iteration if result has deviceId
- use userAgent for detecting the ua-props

if stock_user_agents.nil?

- use userAgent for tree walk
- use userAgent for detecting the ua-props
user_agent

user-agent string (from the original User-Agent header)

stock_user_agents

list of candidate user-agent strings to be used for

tree walk

# File ../../device_api/trunk/ruby/src/lib/tree.rb, line 212
def put_tree_walk_properties user_agent, stock_user_agents = nil
  
  include_ua_props = @config.include_ua_props

  # props_to_vals = {property-id-from-tree-p: value-id-from-tree-v,}
  props_to_vals = {}
  regexes = @tree[KEY_REGEX][API_ID.to_s.to_sym]
  tree_main = @tree[KEY_MAIN]
  matched = ""
  user_agent.strip!

  if stock_user_agents.nil?

    seek_properties tree_main, user_agent, props_to_vals, matched, regexes

  else

    stock_user_agents.each do |stock_user_agent|
      seek_properties(tree_main, stock_user_agent, props_to_vals, matched,
        regexes)
      if !props_to_vals[@device_id_prop_name_id].nil?
        break
      end
    end

  end

  # put the detected properties which are as
  #   {property-id-from-tree-p: value-id-from-tree-v,}
  # into the (Properties) properties object
  props_to_vals.each do |property_id, value_id|
    name = property_name_by_id property_id.to_s.to_i
    @properties[name[1..name.length].to_sym] =
      Mobi::Mtld::Da::Property.new(property_value_by_id(value_id), name[0,1])
  end

  # matched and un-matched
  if @config.include_match_info
    # add in matched and unmatched UA parts
    @properties[:"_matched"] = Mobi::Mtld::Da::Property.new(matched, Mobi::Mtld::Da::DataType::STRING)
    @properties[:"_unmatched"] =
      Mobi::Mtld::Da::Property.new(
        user_agent[matched.length..user_agent.length],
        Mobi::Mtld::Da::DataType::STRING)
  end

  # get ua-props from the original user-agent header
  if include_ua_props && !@ua_props.nil?
    @ua_props.put_properties user_agent, props_to_vals
  end

end