kigster/dupervisor

View on GitHub
lib/dupervisor/parser.rb

Summary

Maintainability
A
55 mins
Test Coverage
require_relative 'formats'
module DuperVisor
  #
  # This class is responsible for coordination of parsing attempts of a
  # given contet with diffirent format parsers.
  #
  class Parser
    class ParseError < StandardError; end
    class FormatNotFound < ParseError; end

    include DuperVisor::Formats::Accessors

    attr_accessor :content, :parse_errors

    def initialize(body)
      self.content = Content.new(body: body)
    end

    def parse(input_format = nil)
      self.parse_errors    = {}
      content.parse_result = nil
      formats_to_check = input_format ? [ formats[input_format] ] : format_classes
      formats_to_check.each do |format_class|
        format = format_class.format
        parse_result = try_format(format, format_class)
        if parse_result
          content.parse_result = parse_result
          content.format       = format
          break
        end
      end
      unless content.parse_result || parse_errors.empty?
        if input_format
          raise ParseError.new("Can not parse from format #{input_format}. Format exception:" +
                                 parse_errors.values.map(&:inspect).join("\n"))
        else
          raise FormatNotFound.new('No suitable format detected. Query #parse_errors for specifics.')
        end
      end
      content
    end

    def try_format(format, format_class)
      format_class.from.call(content.body)
    rescue *(format_class.errors) => e
      self.parse_errors[format] = e
      nil
    end
  end
end