class DTK::Client::DtkResponse

Attributes

command_name[RW]
evaluated_data[RW]
order_defintion[RW]

Public Class Methods

new(data, data_type, forced_metadata, print_error_table) click to toggle source

when adding class to table view you need to define mapping and order to be displayed in table this can be fixed with facets, but that is todo for now TODO: use facets with ordered hashes

# File lib/view_processor/table_print.rb, line 64
def initialize(data, data_type, forced_metadata, print_error_table)
  # if there is no custom metadata, then we use metadata predefined in meta-response.json file

  if forced_metadata.nil?
    # get all table definitions from json file
    @table_defintions = get_metadata()
    # e.g. data type ASSEMBLY
    @command_name     = data_type
    # e.g. ASSEMBLY => TableDefintions::ASSEMBLY
    table_defintion   = get_table_defintion(@command_name)
    # e.g. ASSEMBLY => TableDefintions::ASSEMBLY_ORDER
    @order_definition = get_table_defintion(@command_name, true)
  else
    # if there is custom metadata, check if it is in valid format
    validate_forced_metadata(forced_metadata)

    table_defintion   = forced_metadata['mapping']
    @order_definition = forced_metadata['order']
  end

  # if one defintion is missing we stop the execution
  if table_defintion.nil? || @order_definition.nil?
    raise DTK::Client::DtkError,"Missing table definition(s) for data type #{data_type}."
  end

  # transforms data to DtkOpenStruct
  structured_data = []

  # very important since rest of the code expect array to be used
  data = [data] unless data.kind_of?(Array)

  data.each do |data_element|
    # special flag to filter out data not needed here
    next if data_element['dtk_client_hidden']

    structured_data << to_ostruct(data_element)
  end

  # we use array of OpenStruct to hold our evaluated values
  @evaluated_data = []
  @error_data     = []
  @action_data    = []
  structured_data.each do |structured_element|
    evaluated_element = DtkOpenStruct.new
    error_element     = DtkOpenStruct.new

    # based on mapping we set key = eval(value)
    table_defintion.each do |k,v|
      begin
        # due to problems with space we have special way of handling error columns
        # in such a way that those error will be specially printed later on

        if print_error_table && k.include?('error')
          error_message = value_of(structured_element, v)
          server_error = nil

          # here we see if there was an error if not we will skip this
          # if so we add it to @error_data

          if error_message.empty?
            # no error message just add it as regular element
            evaluated_element.send("#{k}=",value_of(structured_element, v))
          else
            error_index = ""
            error_type = value_of(structured_element,'errors.dtk_type') || ""

            val = value_of(structured_element,'dtk_type')||''
            # extract e.g. 3.1.1.1 from '3.1.1.1 action' etc.
            error_index = "[ #{val.scan( /\d+[,.]?\d?[,.]?\d?[,.]?\d?[,.]?\d?/ ).first} ]"

            # original table takes that index
            evaluated_element.send("#{k}=", error_index)
            # we set new error element
            error_element.id = error_index

            if error_type == "user_error"
              error_element.message = "[USER ERROR] " + error_message
            elsif error_type == "test_error"
              error_element.message = "[TEST ERROR] " + error_message
            else
              error_element.message = "[SERVER ERROR] " + error_message
            end

            # add it with other
            @error_data << error_element
          end
        else
          evaluated_element.send("#{k}=", value_of(structured_element, v))
          # eval "evaluated_element.#{k}=structured_element.#{v}"
        end
      rescue NoMethodError => e
        unless e.message.include? "nil:NilClass"
          # when chaining comands there are situations where more complex strcture
          # e.g. external_ref.region will not be there. So we are handling that case
          # make sure when in development to disable this TODO: better solution needed
          raise DTK::Client::DtkError,"Error with missing metadata occurred. There is a mistake in table metadata or unexpected data presented to table view."
        end
      end
    end

    @order_definition.delete('errors')

    @evaluated_data << evaluated_element
  end
end

Public Instance Methods

filter_remove_underscore(field) click to toggle source
# File lib/view_processor/table_print.rb, line 217
def filter_remove_underscore(field)

end
get_metadata() click to toggle source
# File lib/view_processor/table_print.rb, line 170
def get_metadata
  content = DiskCacher.new.fetch("table_metadata", ::DTK::Configuration.get(:meta_table_ttl))
  raise DTK::Client::DtkError, "Table metadata is empty, please contact DTK team." if content.empty?
  return JSON.parse(content)
end
get_table_defintion(name,is_order=false) click to toggle source
# File lib/view_processor/table_print.rb, line 199
def get_table_defintion(name,is_order=false)
  begin
    @table_defintions[name.downcase][(is_order ? 'order' : 'mapping')]
  rescue NameError => e
    return nil
  end
end
print() click to toggle source
safe_name(identifier) click to toggle source
# File lib/view_processor/table_print.rb, line 195
def safe_name(identifier)
  (identifier == 'id' || identifier  == 'type') ? "dtk_#{identifier}" : identifier
end
to_ostruct(data) click to toggle source
# File lib/view_processor/table_print.rb, line 176
def to_ostruct(data)
  result = data.inject({}) do |res, (k, v)|
    k = safe_name(k)
    case v
    when Hash
      res.store(k, to_ostruct(v))
      res
    when Array
      res.store(k, v.each { |el| Hash === el ? to_ostruct(el) : el })
      res
    else
      res.store(k,v)
      res
    end
  end

  DtkOpenStruct.new(result)
end
validate_forced_metadata(forced_metadata) click to toggle source

Check if custom metadata is sent in valid format

# File lib/view_processor/table_print.rb, line 208
def validate_forced_metadata(forced_metadata)
  # if custom metadata does not contain order(Array) or mapping(Hash),then it's not valid metadata
  unless (forced_metadata['order'].nil? || forced_metadata['mapping'].nil?)
    return if (forced_metadata['order'].class.eql?(Array) && forced_metadata['mapping'].class.eql?(Hash))
  end

  raise DTK::Client::DtkError,"Provided table definition is not valid. Please review your order and mapping for provided definition: \n #{forced_metadata.inspect}"
end

Private Instance Methods

evaluate_command(value, command) click to toggle source
# File lib/view_processor/table_print.rb, line 267
def evaluate_command(value, command)
  case
    when command.include?('map{')
      matched_data = command.match(/\['(.+)'\]/)

      my_lambda = lambda{|_x| _x.map{|r|r["#{matched_data[1]}"]||[]}}
      value = my_lambda.call(value)

      raise DTK::Client::DtkError,"There is a mistake in table metadata: #{command.inspect}" if value.nil?
    when command.include?('(')
      # matches command and params e.g. split('.') => [1] split, [2] '.'
      matched_data = command.match(/(.+)\((.+)\)/)
      command, params = matched_data[1], matched_data[2]
      value = value.send(command,params)
    when command.include?('[')
      # matches command such as first['foo']
      matched_data    = command.match(/(.+)\[(.+)\]/)
      command, params =  matched_data[1],matched_data[2]

      value = evaluate_command(value,command)
      value = value.send('[]',params)
    when command.start_with?("list_")
      matched_data = command.match(/list_(.+)/)

      my_lambda = lambda{|_x| _x.map{|r|r["#{matched_data[1]}"]||[]}}
      value = my_lambda.call(value)

      raise DTK::Client::DtkError,"There is a mistake in table metadata: #{command.inspect}" if value.nil?
    when command.start_with?("count_")
      matched_data = command.match(/count_(.+)/)

      my_lambda = lambda{|_x| _x.map{|r|r["#{matched_data[1]}"]||[]}.flatten.size}
      value = my_lambda.call(value)

      raise DTK::Client::DtkError,"There is a mistake in table metadata: #{command.inspect}" if value.nil?
    else
      value = value.send(command)
  end
  return value
end
value_of(open_struct_object, mapped_command) click to toggle source

based on string sequence in mapped_command we are executing list of commands to follow so for value of “foo.bar.split('.').last” we will get 4 commands that will sequentaly be executed using values from previus results

# File lib/view_processor/table_print.rb, line 255
def value_of(open_struct_object, mapped_command)
  # split string by '.' delimiter keeping in mind to split when words only
  commands = mapped_command.split(/\.(?=\w)/)

  value = open_struct_object
  commands.each do |command|
    value = evaluate_command(value, command)
  end
  return value
end