class AdsCommon::ResultsExtractor

Public Class Methods

new(registry) click to toggle source

Instance initializer.

Args:

- registry: a registry that defines service
# File lib/ads_common/results_extractor.rb, line 28
def initialize(registry)
  @registry = registry
end

Public Instance Methods

extract_exception_data(soap_fault, exception_name) click to toggle source

Extracts misc data from SOAP fault.

# File lib/ads_common/results_extractor.rb, line 53
def extract_exception_data(soap_fault, exception_name)
  exception_type = get_full_type_signature(exception_name)
  process_attributes(soap_fault, false)
  soap_fault = normalize_fields(soap_fault, exception_type[:fields])
  return soap_fault
end
extract_header_data(response) click to toggle source

Extracts misc data from response header.

# File lib/ads_common/results_extractor.rb, line 44
def extract_header_data(response)
  header_type = get_full_type_signature(:SoapResponseHeader)
  headers = response.header[:response_header].dup
  process_attributes(headers, false)
  headers = normalize_fields(headers, header_type[:fields])
  return headers
end
extract_result(response, action_name) click to toggle source

Extracts the finest results possible for the given result. Returns the response itself in worst case (contents unknown).

# File lib/ads_common/results_extractor.rb, line 34
def extract_result(response, action_name)
  method = @registry.get_method_signature(action_name)
  action = method[:output][:name].to_sym
  result = response.to_hash
  result = result[action] if result.include?(action)
  result = normalize_output(result, method)
  return result[:rval] || result
end

Private Instance Methods

arrayize(object) click to toggle source

Makes sure object is an array.

# File lib/ads_common/results_extractor.rb, line 254
def arrayize(object)
  return [] if object.nil?
  return object.is_a?(Array) ? object : [object]
end
check_array_collapse(data, field_def) click to toggle source

Checks if the field signature allows an array and forces array structure even for a signle item.

# File lib/ads_common/results_extractor.rb, line 242
def check_array_collapse(data, field_def)
  result = data
  if !field_def[:min_occurs].nil? &&
      (field_def[:max_occurs] == :unbounded ||
          (!field_def[:max_occurs].nil? && field_def[:max_occurs] > 1)) &&
              !(field_def[:type] =~ /MapEntry$/)
    result = arrayize(result)
  end
  return result
end
check_key_value_hash(item) click to toggle source

Checks if the argument is hash and has exactly ':key' and ':value' keys.

# File lib/ads_common/results_extractor.rb, line 174
def check_key_value_hash(item)
  return (item.kind_of?(Hash) && item.include?(:key) &&
      item.include?(:value) && (item.keys.size == 2))
end
check_key_value_struct(data) click to toggle source

Checks if all elements of the array or hash passed are hashes and have ':key' and ':value' keys only.

# File lib/ads_common/results_extractor.rb, line 160
def check_key_value_struct(data)
  if data.kind_of?(Hash)
    return check_key_value_hash(data)
  end
  if data.kind_of?(Array) && !data.empty?
    data.each do |item|
      return false if !check_key_value_hash(item)
    end
    return true
  end
  return false
end
convert_key_value_to_hash(data) click to toggle source

Converts an array containing hashes or a hash with ':key' and ':value' keys only into a key -> value hash.

# File lib/ads_common/results_extractor.rb, line 181
def convert_key_value_to_hash(data)
  return case data
    when Hash then {data[:key] => data[:value]}
    when Array then
      data.inject({}) do |result, item|
        result[item[:key]] = item[:value]
        result
      end
  end
end
determine_choice(field_data, field_choices) click to toggle source

Finds the choice option matching data provided.

# File lib/ads_common/results_extractor.rb, line 213
def determine_choice(field_data, field_choices)
  result = nil
  key_name = field_data.keys.first
  unless key_name.nil?
    choice = find_named_entry(field_choices, key_name)
    result = choice[:type] unless choice.nil?
  end
  return result
end
determine_choice_type_override(field_data, field_def) click to toggle source

Determines a choice type override for for the field. Returns nil if no override found.

# File lib/ads_common/results_extractor.rb, line 204
def determine_choice_type_override(field_data, field_def)
  result = nil
  if field_data.kind_of?(Hash) and field_def.include?(:choices)
    result = determine_choice(field_data, field_def[:choices])
  end
  return result
end
determine_xsi_type_override(field_data, field_def) click to toggle source

Determines an xsi:type override for for the field. Returns nil if no override found.

# File lib/ads_common/results_extractor.rb, line 194
def determine_xsi_type_override(field_data, field_def)
  result = nil
  if field_data.kind_of?(Hash) and field_data.include?(:xsi_type)
    result = field_data[:xsi_type]
  end
  return result
end
find_named_entry(data_array, name) click to toggle source

Finds an item in an Array based on its ':name' field.

# File lib/ads_common/results_extractor.rb, line 224
def find_named_entry(data_array, name)
  index = data_array.index {|item| name.eql?(item[:name])}
  return index.nil? ? nil : data_array[index]
end
get_full_type_signature(type_name) click to toggle source

Returns type signature with all inherited fields.

# File lib/ads_common/results_extractor.rb, line 275
def get_full_type_signature(type_name)
  result = (type_name.nil?) ? nil : @registry.get_type_signature(type_name)
  result[:fields] = implode_parent(result) if result and result[:base]
  return result
end
implode_parent(data_type) click to toggle source

Returns all inherited fields of superclasses for given type.

# File lib/ads_common/results_extractor.rb, line 260
def implode_parent(data_type)
  result = []
  if data_type[:base]
    parent_type = @registry.get_type_signature(data_type[:base])
    result += implode_parent(parent_type) unless parent_type.nil?
  end
  data_type[:fields].each do |field|
    # If the parent type includes a field with the same name, overwrite it.
    result.reject! {|parent_field| parent_field[:name].eql?(field[:name])}
    result << field
  end
  return result
end
normalize_array_field(data, field_def) click to toggle source

Normalizes every item of an Array.

# File lib/ads_common/results_extractor.rb, line 101
def normalize_array_field(data, field_def)
  result = data
  # Convert a specific structure to a handy hash if detected.
  if check_key_value_struct(result)
    result = convert_key_value_to_hash(result).inject({}) do |s, (k,v)|
      s[k] = normalize_output_field(v, field_def)
      s
    end
  else
    result = data.map {|item| normalize_output_field(item, field_def)}
  end
  return result
end
normalize_fields(data, fields) click to toggle source

Normalizes all fields for the given data based on the fields list provided.

# File lib/ads_common/results_extractor.rb, line 70
def normalize_fields(data, fields)
  fields.each do |field|
    field_name = field[:name]
    if data.include?(field_name)
      field_data = data[field_name]
      field_data = normalize_output_field(field_data, field)
      field_data = check_array_collapse(field_data, field)
      data[field_name] = field_data unless field_data.nil?
    end
  end
  return data
end
normalize_hash_field(field, field_def) click to toggle source

Normalizes every item of a Hash.

# File lib/ads_common/results_extractor.rb, line 116
def normalize_hash_field(field, field_def)
  process_attributes(field, true)
  field_type = field_def[:type]
  field_def = get_full_type_signature(field_type)

  # First checking for xsi:type provided.
  xsi_type_override = determine_xsi_type_override(field, field_def)
  unless xsi_type_override.nil?
    field_def = get_full_type_signature(xsi_type_override)
    return (field_def.nil?) ? field :
        normalize_fields(field, field_def[:fields])
  end

  result = field

  # Now checking for choice options from wsdl.
  choice_type_override = determine_choice_type_override(field, field_def)
  unless choice_type_override.nil?
    # For overrides we need to process sub-field and than return it
    # in the original structure.
    field_key = field.keys.first
    field_data = field[field_key]
    field_def = get_full_type_signature(choice_type_override)
    if !field_def.nil? and field_data.kind_of?(Hash)
      field_data = normalize_fields(field_data, field_def[:fields])
    end
    result = {field_key => field_data}
  else
    # Otherwise using the best we have.
    unless field_def.nil?
      result = normalize_fields(field, field_def[:fields])
    end
  end

  # Convert a single key-value hash to a proper hash if detected.
  if check_key_value_struct(result)
    result = convert_key_value_to_hash(result)
  end

  return result
end
normalize_item(item, field_def) click to toggle source

Converts one leaf item to a built-in type.

# File lib/ads_common/results_extractor.rb, line 230
def normalize_item(item, field_def)
  return case field_def[:type]
    when 'long', 'int' then Integer(item)
    when 'double', 'float' then Float(item)
    when 'boolean' then item.kind_of?(String) ?
        item.casecmp('true') == 0 : item
    else item
  end
end
normalize_output(output_data, method_definition) click to toggle source

Normalizes output starting with root output node.

# File lib/ads_common/results_extractor.rb, line 63
def normalize_output(output_data, method_definition)
  fields = method_definition[:output][:fields]
  return normalize_fields(output_data, fields)
end
normalize_output_field(field_data, field_def) click to toggle source

Normalizes one field of a given data recursively.

Args:

- field_data: XML data to normalize
- field_def: field type definition for the data
# File lib/ads_common/results_extractor.rb, line 89
def normalize_output_field(field_data, field_def)
  return case field_data
    when Array
      normalize_array_field(field_data, field_def)
    when Hash
      normalize_hash_field(field_data, field_def)
    else
      normalize_item(field_data, field_def)
  end
end
process_attributes(data, keep_xsi_type = false) click to toggle source

Handles attributes received from Savon.

# File lib/ads_common/results_extractor.rb, line 282
def process_attributes(data, keep_xsi_type = false)
  if keep_xsi_type
    xsi_type = data.delete(:"@xsi:type")
    data[:xsi_type] = xsi_type if xsi_type
  end
  data.reject! {|key, value| key.to_s.start_with?('@')}
end