class AdsCommon::Build::SavonRegistry

Contains the methods that extracts WSDL data.

Attributes

soap_exceptions[R]
soap_methods[R]
soap_namespaces[R]
soap_types[R]

Public Class Methods

new(wsdl, options = {}) click to toggle source

Initializes the instance.

Args:

  • wsdl: string containing wsdl to parse

  • options: variuos generation options

# File lib/ads_common/build/savon_registry.rb, line 41
def initialize(wsdl, options = {})
  @options = options
  @default_namespace = options[:namespace]
  do_process_wsdl(wsdl)
end

Private Instance Methods

attribute_to_boolean(attribute) click to toggle source

Simple converter for boolean values.

# File lib/ads_common/build/savon_registry.rb, line 255
def attribute_to_boolean(attribute)
  return (attribute.nil?) ? nil : attribute.value.eql?('true')
end
attribute_to_int(attribute) click to toggle source

Simple converter for int values.

# File lib/ads_common/build/savon_registry.rb, line 248
def attribute_to_int(attribute)
  return nil if attribute.nil?
  return attribute.value.eql?('unbounded') ?
      :unbounded : attribute.value.to_i
end
do_include_exception(exception) click to toggle source

Includes exception into ordered_exceptions if not already there and makes sure its base is already included.

# File lib/ads_common/build/savon_registry.rb, line 268
def do_include_exception(exception)
  return if find_exception(exception, @ordered_exceptions)
  if exception[:base].nil?
    @ordered_exceptions.push(exception)
  else
    base = find_exception(exception[:base], @soap_exceptions)
    do_include_exception(base)
    @ordered_exceptions.push(exception)
  end
end
do_process_wsdl(wsdl) click to toggle source

Generate code for given Savon client.

# File lib/ads_common/build/savon_registry.rb, line 50
def do_process_wsdl(wsdl)
  @soap_exceptions = []
  @soap_types = []
  @soap_methods = []
  @soap_namespaces = []

  doc = REXML::Document.new(wsdl.xml)
  process_types(doc)
  process_methods(doc)
  sort_exceptions()
end
extract_enumerations(type_element, type) click to toggle source

Extracts all possible enumerations for a type and adds them as an `enumerations` key on the type.

# File lib/ads_common/build/savon_registry.rb, line 160
def extract_enumerations(type_element, type)
  REXML::XPath.each(type_element,
      "restriction[@base='xsd:string']") do |enum_node|
    type.delete(:fields)
    type[:type] = enum_node.attribute('base').to_s.gsub(/^.+:/, '')
  end
  REXML::XPath.each(type_element,
      "restriction[@base='xsd:string']/enumeration") do |enum_node|
    type[:enumerations] ||= []
    type[:enumerations] << enum_node.attribute('value').to_s
  end
  return type
end
extract_exception(exception_element) click to toggle source

Extracts exception parameters from ComplexTypes element.

# File lib/ads_common/build/savon_registry.rb, line 112
def extract_exception(exception_element)
  return {:name => get_element_name(exception_element),
          :doc => get_element_doc(exception_element),
          :base => get_element_base(exception_element),
          :fields => get_element_fields(exception_element)}
end
extract_input_parameters(op_node, doc) click to toggle source

Extracts input parameters of given method as an array.

# File lib/ads_common/build/savon_registry.rb, line 175
def extract_input_parameters(op_node, doc)
  op_name = get_element_name(op_node)
  return find_sequence_fields(op_name, doc)
end
extract_method(method_element, doc) click to toggle source

Extracts method parameters from ComplexTypes element.

# File lib/ads_common/build/savon_registry.rb, line 120
def extract_method(method_element, doc)
  name = get_element_name(method_element)
  method = {
      :name => name.snakecase,
      :input => extract_input_parameters(method_element, doc),
      :output => extract_output_parameters(method_element, doc)
      # This could be used to include documentation from wsdl.
      #:doc => get_element_doc(operation, 'wsdl')
  }
  original_name = get_original_name_if_needed(name)
  method[:original_name] = original_name unless original_name.nil?
  return method
end
extract_output_parameters(op_node, doc) click to toggle source

Extracts output parameter name and fields.

# File lib/ads_common/build/savon_registry.rb, line 181
def extract_output_parameters(op_node, doc)
  output_element = REXML::XPath.first(op_node, 'descendant::wsdl:output')
  output_name = get_element_name(output_element)
  output_fields = find_sequence_fields(output_name, doc)
  return {:name => output_name.snakecase, :fields => output_fields}
end
extract_type(type_element, ns_index) click to toggle source

Extracts definition of all types. If a non standard undefined type is found it process it recursively.

# File lib/ads_common/build/savon_registry.rb, line 136
def extract_type(type_element, ns_index)
  type = {:name => get_element_name(type_element), :fields => []}
  if attribute_to_boolean(type_element.attribute('abstract'))
    type[:abstract] = true
  end
  base_type = get_element_base(type_element)
  type[:base] = base_type if base_type
  type[:ns] = ns_index if ns_index
  REXML::XPath.each(type_element,
      'sequence | complexContent/extension/sequence') do |seq_node|
    type[:fields] += get_element_fields(seq_node)
  end

  extract_enumerations(type_element, type)

  REXML::XPath.each(type_element, 'choice') do |seq_node|
    type[:choices] ||= []
    type[:choices] += get_element_fields(seq_node)
  end
  return type
end
find_exception(exception, list) click to toggle source

Finds object (exception) by name attribute in a list.

# File lib/ads_common/build/savon_registry.rb, line 280
def find_exception(exception, list)
  list.each do |e|
    return e if (e.eql?(exception) || e[:name].eql?(exception))
  end
  return nil
end
find_sequence_fields(name, doc) click to toggle source

Finds sequence fields for the element of given name.

# File lib/ads_common/build/savon_registry.rb, line 189
def find_sequence_fields(name, doc)
  result = []
  doc.each_element_with_attribute('name', name, 0,
      '//schema/element') do |element_node|
    REXML::XPath.each(element_node, 'complexType/sequence') do |seq_node|
      result += get_element_fields(seq_node)
    end
  end
  return result
end
get_complex_types(node) click to toggle source

Extracts ComplexTypes from node into an array.

# File lib/ads_common/build/savon_registry.rb, line 102
def get_complex_types(node)
  return REXML::XPath.each(node, 'complexType').to_a
end
get_element_base(element) click to toggle source

Gets element base defined as an attribute in sibling.

# File lib/ads_common/build/savon_registry.rb, line 206
def get_element_base(element)
  base_element = REXML::XPath.first(element, 'complexContent/extension')
  base = (base_element.nil?) ? nil :
      base_element.attribute('base').to_s.gsub(/^.+:/, '')
  return base
end
get_element_doc(root, namespace = nil) click to toggle source

Gets element documentation text.

# File lib/ads_common/build/savon_registry.rb, line 214
def get_element_doc(root, namespace = nil)
  key = 'documentation'
  key = "%s:%s" % [namespace, key] if namespace
  doc_element = REXML::XPath.first(root, "descendant::%s" % key)
  doc = (doc_element.nil?) ? '' :
      REXML::Text.unnormalize(doc_element.get_text.to_s)
  return doc
end
get_element_fields(element) click to toggle source

Gets subfields defined as elements under given root.

# File lib/ads_common/build/savon_registry.rb, line 224
def get_element_fields(element)
  fields = []
  REXML::XPath.each(element, 'descendant::element') do |item|
    name = get_element_name(item)
    original_name = get_original_name_if_needed(name)
    field = {
        :name => name.snakecase.to_sym,
        :original_name => original_name,
        :type => item.attribute('type').to_s.gsub(/^.+:/, ''),
        :min_occurs => attribute_to_int(item.attribute('minOccurs')),
        :max_occurs => attribute_to_int(item.attribute('maxOccurs'))}
    fields << field.reject {|k, v| v.nil?}
  end
  return fields
end
get_element_name(element) click to toggle source

Gets element name defined as its attribute.

# File lib/ads_common/build/savon_registry.rb, line 201
def get_element_name(element)
  return element.attribute('name').to_s
end
get_original_name_if_needed(name) click to toggle source

Returns original name if it can not be back-converted and required for XML serialization.

# File lib/ads_common/build/savon_registry.rb, line 242
def get_original_name_if_needed(name)
  return (name.nil? || (name.snakecase.lower_camelcase == name)) ?
      nil : name
end
get_simple_types(node) click to toggle source

Extracts SimpleTypes from node into an array.

# File lib/ads_common/build/savon_registry.rb, line 107
def get_simple_types(node)
  return REXML::XPath.each(node, 'simpleType').to_a
end
process_methods(doc) click to toggle source

Extracts SOAP actions as methods.

# File lib/ads_common/build/savon_registry.rb, line 94
def process_methods(doc)
  iface = REXML::XPath.first(doc, 'descendant::wsdl:portType')
  REXML::XPath.each(iface, 'descendant::wsdl:operation') do |operation|
    @soap_methods << extract_method(operation, doc)
  end
end
process_namespace(schema) click to toggle source

Returns index of namespace for given schema. Adds namespace to internal array if not yet present. Returns nil for service default namespace.

# File lib/ads_common/build/savon_registry.rb, line 80
def process_namespace(schema)
  namespace_url = schema.attribute('targetNamespace').value
  unless namespace_url == @default_namespace
    ns_index = @soap_namespaces.index(namespace_url)
    if ns_index.nil?
      ns_index = @soap_namespaces.length
      @soap_namespaces << namespace_url
    end
    return ns_index
  end
  return nil
end
process_types(doc) click to toggle source

Extracts different types from XML.

# File lib/ads_common/build/savon_registry.rb, line 63
def process_types(doc)
  REXML::XPath.each(doc, '//schema') do |schema|
    ns_index = process_namespace(schema)
    complex_types = get_complex_types(schema)
    simple_types =  get_simple_types(schema)
    (complex_types + simple_types).each do |ctype|
      ctype_name = get_element_name(ctype)
      @soap_types << extract_type(ctype, ns_index)
      if ctype_name.match('.+Exception$')
        @soap_exceptions << extract_exception(ctype)
      end
    end
  end
end
sort_exceptions() click to toggle source

Reorders exceptions so that base ones always come before derived.

# File lib/ads_common/build/savon_registry.rb, line 260
def sort_exceptions()
  @ordered_exceptions = []
  @soap_exceptions.each {|exception| do_include_exception(exception)}
  @soap_exceptions = @ordered_exceptions
end