class ActiveSupport::XMLConverter

:nodoc:

def become_array?(value)

def become_array?(value)
  value["type"] == "array"
end

def become_content?(value)

def become_content?(value)
  value["type"] == "file" || (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
end

def become_empty_string?(value)

def become_empty_string?(value)
  # { "string" => true }
  # No tests fail when the second term is removed.
  value["type"] == "string" && value["nil"] != "true"
end

def become_hash?(value)

def become_hash?(value)
  !nothing?(value) && !garbage?(value)
end

def deep_to_h(value)

def deep_to_h(value)
  case value
  when Hash
    process_hash(value)
  when Array
    process_array(value)
  when String
    value
  else
    raise "can't typecast #{value.class.name} - #{value.inspect}"
  end
end

def garbage?(value)

def garbage?(value)
  # If the type is the only element which makes it then
  # this still makes the value nil, except if type is
  # an XML node(where type['value'] is a Hash)
  value["type"] && !value["type"].is_a?(::Hash) && value.size == 1
end

def initialize(xml, disallowed_types = nil)

def initialize(xml, disallowed_types = nil)
  @xml = normalize_keys(XmlMini.parse(xml))
  @disallowed_types = disallowed_types || DISALLOWED_TYPES
end

def normalize_keys(params)

def normalize_keys(params)
  case params
  when Hash
    Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
  when Array
    params.map { |v| normalize_keys(v) }
  else
    params
  end
end

def nothing?(value)

def nothing?(value)
  # blank or nil parsed values are represented by nil
  value.blank? || value["nil"] == "true"
end

def process_array(value)

def process_array(value)
  value.map! { |i| deep_to_h(i) }
  value.length > 1 ? value : value.first
end

def process_content(value)

def process_content(value)
  content = value["__content__"]
  if parser = ActiveSupport::XmlMini::PARSING[value["type"]]
    parser.arity == 1 ? parser.call(content) : parser.call(content, value)
  else
    content
  end
end

def process_hash(value)

def process_hash(value)
  if value.include?("type") && !value["type"].is_a?(Hash) && @disallowed_types.include?(value["type"])
    raise DisallowedType, value["type"]
  end
  if become_array?(value)
    _, entries = Array.wrap(value.detect { |k, v| not v.is_a?(String) })
    if entries.nil? || value["__content__"].try(:empty?)
      []
    else
      case entries
      when Array
        entries.collect { |v| deep_to_h(v) }
      when Hash
        [deep_to_h(entries)]
      else
        raise "can't typecast #{entries.inspect}"
      end
    end
  elsif become_content?(value)
    process_content(value)
  elsif become_empty_string?(value)
    ""
  elsif become_hash?(value)
    xml_value = value.transform_values { |v| deep_to_h(v) }
    # Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
    # how multipart uploaded files from HTML appear
    xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
  end
end

def to_h

def to_h
  deep_to_h(@xml)
end