<commit_before>%w(qname xpath namespace).each do |lib|
  require File.expand_path("../#{lib}", __FILE__)
end

module WSDL
  class Parser

    def initialize(document)
      @document = document
    end

    attr_reader :document

    def parse
      @bindings = parse_bindings
      @services = parse_services

      { "services" => @services }
    end

  private

    def parse_bindings
      xpath.wsdl(:definitions, :binding).inject({}) do |bindings, binding|
        details = { "operations" => {} }

        transport_binding = xpath(binding).query(:name, "binding")
        if namespace(transport_binding).soap?
          details["style"] = transport_binding["style"]
          details["transport"] = transport_binding["transport"]
        end

        xpath(binding).wsdl(:operation).each do |operation|
          operation_details = {}

          transport_operation = xpath(operation).query(:name, "operation")
          if transport_operation && namespace(transport_operation).soap?
            # TODO: investigate why nokogiri on jruby returns nil instead of an empty string
            operation_details["soap_action"] = transport_operation["soapAction"] || ""
            operation_details["style"] = transport_operation["style"]

            soap_body_details = Proc.new do |nodes|
              nodes.map do |node|
                body = xpath(node).query(:name, "body")
                { "use" => body["use"] }
              end
            end

            operation_details["input"]  = soap_body_details.call(xpath(operation).wsdl(:input)).first
            operation_details["output"] = soap_body_details.call(xpath(operation).wsdl(:output)).first
            operation_details["fault"]  = soap_body_details.call(xpath(operation).wsdl(:fault))
          end

          details["operations"][operation["name"]] = operation_details
        end

        bindings[binding["name"]] = details
        bindings
      end
    end

    def parse_services
      xpath.wsdl(:definitions, :service).inject({}) do |services, service|
        services[service["name"]] = { "ports" => find_ports(service) }
        services
      end
    end

    def find_ports(service)
      xpath(service).wsdl(:port).inject({}) do |ports, port|
        address_node = port.children.find(&:element?)
        binding_name = qname(port["binding"]).local

        ports[port["name"]] = {
          "type"     => namespace(address_node).type,
          "location" => address_node["location"],
          "binding"  => @bindings[binding_name]
        }
        ports
      end
    end

    def qname(node)
      QName.new(node)
    end

    def namespace(qname)
      Namespace.new(qname)
    end

    def xpath(node = nil)
      XPath.new node || document
    end

  end
end
<commit_msg>cleans up parse_bindings<commit_after>%w(qname xpath namespace).each do |lib|
  require File.expand_path("../#{lib}", __FILE__)
end

module WSDL
  class Parser

    def initialize(document)
      @document = document
    end

    attr_reader :document

    def parse
      @bindings = parse_bindings
      @services = parse_services

      { "services" => @services }
    end

  private

    def parse_bindings
      xpath.wsdl(:definitions, :binding).inject({}) do |bindings, binding|
        details = {}

        transport_binding = xpath(binding).query(:name, "binding")
        if namespace(transport_binding).soap?
          details["style"] = transport_binding["style"]
          details["transport"] = transport_binding["transport"]
        end

        details["operations"] = find_operations(binding)

        bindings[binding["name"]] = details
        bindings
      end
    end

    def parse_services
      xpath.wsdl(:definitions, :service).inject({}) do |services, service|
        services[service["name"]] = { "ports" => find_ports(service) }
        services
      end
    end

    def find_operations(binding)
      xpath(binding).wsdl(:operation).inject({}) do |operations, operation|
        details = {}

        transport_operation = xpath(operation).query(:name, "operation")
        if transport_operation && namespace(transport_operation).soap?
          # NOTE: Nokogiri Java returns nil instead of an empty String for empty attributes.
          #       https://github.com/tenderlove/nokogiri/issues/589
          details["soap_action"] = transport_operation["soapAction"] || ""
          details["style"] = transport_operation["style"]

          details["input"]  = find_operation_body(xpath(operation).wsdl(:input)).first
          details["output"] = find_operation_body(xpath(operation).wsdl(:output)).first
          details["fault"]  = find_operation_body(xpath(operation).wsdl(:fault))
        end

        operations[operation["name"]] = details
        operations
      end
    end

    def find_operation_body(nodes)
      nodes.map do |node|
        body = xpath(node).query(:name, "body")
        { "use" => body["use"] }
      end
    end

    def find_ports(service)
      xpath(service).wsdl(:port).inject({}) do |ports, port|
        address_node = port.children.find(&:element?)
        binding_name = qname(port["binding"]).local

        ports[port["name"]] = {
          "type"     => namespace(address_node).type,
          "location" => address_node["location"],
          "binding"  => @bindings[binding_name]
        }
        ports
      end
    end

    def qname(node)
      QName.new(node)
    end

    def namespace(qname)
      Namespace.new(qname)
    end

    def xpath(node = nil)
      XPath.new node || document
    end

  end
end

{'fraction_non_alphanumeric': 0.12482040229885058, 'fraction_numerical': 0.0005387931034482759, 'mean_word_length': 2.553924696873006, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4779648', 'n_tokens_mistral': 1623, 'n_tokens_neox': 1557, 'n_words': 317}