class WSDL::SOAP::ClassDefCreator

Public Class Methods

new(definitions, name_creator, modulepath = nil) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 23
def initialize(definitions, name_creator, modulepath = nil)
  @definitions = definitions
  @name_creator = name_creator
  @modulepath = modulepath
  @elements = definitions.collect_elements
  @elements.uniq!
  @attributes = definitions.collect_attributes
  @attributes.uniq!
  @simpletypes = definitions.collect_simpletypes
  @simpletypes.uniq!
  @complextypes = definitions.collect_complextypes
  @complextypes.uniq!
  @modelgroups = definitions.collect_modelgroups
  @modelgroups.uniq!
  @faulttypes = nil
  if definitions.respond_to?(:collect_faulttypes)
    @faulttypes = definitions.collect_faulttypes
  end
  @defined_const = {}
end

Public Instance Methods

dump(type = nil) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 44
def dump(type = nil)
  result = "require 'xsd/qname'\n"
  # cannot use @modulepath because of multiple classes
  if @modulepath
    result << "\n"
    result << modulepath_split(@modulepath).collect { |ele| "module #{ele}" }.join("; ")
    result << "\n\n"
  end
  str = dump_group(type)
  unless str.empty?
    result << "\n" unless result.empty?
    result << str
  end
  str = dump_complextype(type)
  unless str.empty?
    result << "\n" unless result.empty?
    result << str
  end
  str = dump_simpletype(type)
  unless str.empty?
    result << "\n" unless result.empty?
    result << str
  end
  str = dump_element(type)
  unless str.empty?
    result << "\n" unless result.empty?
    result << str
  end
  str = dump_attribute(type)
  unless str.empty?
    result << "\n" unless result.empty?
    result << str
  end
  if @modulepath
    result << "\n\n"
    result << modulepath_split(@modulepath).collect { |ele| "end" }.join("; ")
    result << "\n"
  end
  result
end

Private Instance Methods

collect_dependency(type, dep) click to toggle source

removes collected key from dep

# File lib/wsdl/soap/classDefCreator.rb, line 412
def collect_dependency(type, dep)
  result = [type]
  return result unless dep.key?(type.name)
  dep[type.name].each do |deptype|
    result.concat(collect_dependency(deptype, dep))
  end
  dep.delete(type.name)
  result
end
create_arraydef(mpath, qname, typedef) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 383
def create_arraydef(mpath, qname, typedef)
  classname = mapped_class_basename(qname, mpath)
  c = ClassDef.new(classname, '::Array')
  c.comment = "#{qname}"
  parentmodule = mapped_class_name(qname, mpath)
  parse_elements(c, typedef.elements, qname.namespace, parentmodule, true)
  c
end
create_complextypedef(mpath, qname, type, qualified = false) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 238
def create_complextypedef(mpath, qname, type, qualified = false)
  case type.compoundtype
  when :TYPE_STRUCT, :TYPE_EMPTY
    create_structdef(mpath, qname, type, qualified)
  when :TYPE_ARRAY
    create_arraydef(mpath, qname, type)
  when :TYPE_SIMPLE
    create_simpleclassdef(mpath, qname, type)
  when :TYPE_MAP
    # mapped as a general Hash
    nil
  else
    raise RuntimeError.new(
      "unknown kind of complexContent: #{type.compoundtype}")
  end
end
create_elementdef(mpath, ele) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 128
def create_elementdef(mpath, ele)
  qualified = (ele.elementform == 'qualified')
  if ele.local_complextype
    create_complextypedef(mpath, ele.name, ele.local_complextype, qualified)
  elsif ele.local_simpletype
    create_simpletypedef(mpath, ele.name, ele.local_simpletype, qualified)
  elsif ele.empty?
    create_simpleclassdef(mpath, ele.name, nil)
  else
    # ignores type only element
    nil
  end
end
create_simpleclassdef(mpath, qname, type_or_element) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 223
def create_simpleclassdef(mpath, qname, type_or_element)
  classname = mapped_class_basename(qname, mpath)
  c = ClassDef.new(classname, '::String')
  c.comment = "#{qname}"
  init_lines = []
  if type_or_element and !type_or_element.attributes.empty?
    define_attribute(c, type_or_element.attributes)
    init_lines << "@__xmlattr = {}"
  end
  c.def_method('initialize', '*arg') do
    "super\n" + init_lines.join("\n")
  end
  c
end
create_simpletypedef(mpath, qname, simpletype, qualified = false) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 142
def create_simpletypedef(mpath, qname, simpletype, qualified = false)
  if simpletype.restriction
    create_simpletypedef_restriction(mpath, qname, simpletype, qualified)
  elsif simpletype.list
    create_simpletypedef_list(mpath, qname, simpletype, qualified)
  elsif simpletype.union
    create_simpletypedef_union(mpath, qname, simpletype, qualified)
  else
    raise RuntimeError.new("unknown kind of simpletype: #{simpletype}")
  end
end
create_simpletypedef_list(mpath, qname, typedef, qualified) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 167
def create_simpletypedef_list(mpath, qname, typedef, qualified)
  list = typedef.list
  classname = mapped_class_basename(qname, mpath)
  c = ClassDef.new(classname, '::Array')
  c.comment = "#{qname}"
  if simpletype = list.local_simpletype
    if simpletype.restriction.nil?
      raise RuntimeError.new(
        "unknown kind of simpletype: #{simpletype}")
    end
    define_stringenum_restriction(c, simpletype.restriction.enumeration)
    c.comment << "\n  contains list of #{classname}::*"
  elsif list.itemtype
    c.comment << "\n  contains list of #{mapped_class_basename(list.itemtype, mpath)}::*"
  else
    raise RuntimeError.new("unknown kind of list: #{list}")
  end
  c
end
create_simpletypedef_restriction(mpath, qname, typedef, qualified) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 154
def create_simpletypedef_restriction(mpath, qname, typedef, qualified)
  restriction = typedef.restriction
  unless restriction.enumeration?
    # not supported.  minlength?
    return nil
  end
  classname = mapped_class_basename(qname, mpath)
  c = ClassDef.new(classname, '::String')
  c.comment = "#{qname}"
  define_classenum_restriction(c, classname, restriction.enumeration)
  c
end
create_simpletypedef_union(mpath, qname, typedef, qualified) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 187
def create_simpletypedef_union(mpath, qname, typedef, qualified)
  union = typedef.union
  classname = mapped_class_basename(qname, mpath)
  c = ClassDef.new(classname, '::String')
  c.comment = "#{qname}"
  if union.member_types
    # fixme
    c.comment << "\n any of #{union.member_types}"
  end
  c
end
create_structdef(mpath, qname, typedef, qualified = false) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 255
def create_structdef(mpath, qname, typedef, qualified = false)
  classname = mapped_class_basename(qname, mpath)
  baseclassname = nil
  if typedef.complexcontent
    if base = typedef.complexcontent.base
      # :TYPE_ARRAY must not be derived (#424)
      basedef = @complextypes[base]
      if basedef and basedef.compoundtype != :TYPE_ARRAY
        # baseclass should be a toplevel complexType
        baseclassname = mapped_class_basename(base, @modulepath)
      end
    end
  end
  if @faulttypes and @faulttypes.index(qname)
    c = ClassDef.new(classname, '::StandardError')
  else
    c = ClassDef.new(classname, baseclassname)
  end
  c.comment = "#{qname}"
  c.comment << "\nabstract" if typedef.abstract
  parentmodule = mapped_class_name(qname, mpath)
  init_lines, init_params =
    parse_elements(c, typedef.elements, qname.namespace, parentmodule)
  unless typedef.attributes.empty?
    define_attribute(c, typedef.attributes)
    init_lines << "@__xmlattr = {}"
  end
  c.def_method('initialize', *init_params) do
    init_lines.join("\n")
  end
  c
end
define_attribute(c, attributes) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 354
  def define_attribute(c, attributes)
    const = {}
    unless attributes.empty?
      c.def_method("__xmlattr") do <<-__EOD__
          @__xmlattr ||= {}
        __EOD__
      end
    end
    attributes.each do |attribute|
      name = name_attribute(attribute)
      methodname = safemethodname('xmlattr_' + name.name)
      constname = 'Attr' + safeconstname(name.name)
      const[constname] ||= 0
      if (const[constname] += 1) > 1
        constname += "_#{const[constname]}"
      end
      c.def_const(constname, dqname(name))
      c.def_method(methodname) do <<-__EOD__
          __xmlattr[#{constname}]
        __EOD__
      end
      c.def_method(methodname + '=', 'value') do <<-__EOD__
          __xmlattr[#{constname}] = value
        __EOD__
      end
      c.comment << "\n  #{methodname} - #{attribute_basetype(attribute) || '(any)'}"
    end
  end
define_classenum_restriction(c, classname, enumeration) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 211
def define_classenum_restriction(c, classname, enumeration)
  const = {}
  enumeration.each do |value|
    constname = safeconstname(value)
    const[constname] ||= 0
    if (const[constname] += 1) > 1
      constname += "_#{const[constname]}"
    end
    c.def_const(constname, "new(#{ndq(value)})")
  end
end
define_stringenum_restriction(c, enumeration) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 199
def define_stringenum_restriction(c, enumeration)
  const = {}
  enumeration.each do |value|
    constname = safeconstname(value)
    const[constname] ||= 0
    if (const[constname] += 1) > 1
      constname += "_#{const[constname]}"
    end
    c.def_const(constname, ndq(value))
  end
end
dump_attribute(target = nil) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 96
def dump_attribute(target = nil)
  @attributes.collect { |attribute|
    next if target and target != attribute.name
    if attribute.local_simpletype
      c = create_simpletypedef(@modulepath, attribute.name, attribute.local_simpletype)
    end
    c ? c.dump : nil
  }.compact.join("\n")
end
dump_complextype(target = nil) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 114
def dump_complextype(target = nil)
  definitions = sort_dependency(@complextypes).collect { |type|
    next if target and target != type.name
    c = create_complextypedef(@modulepath, type.name, type)
    c ? c.dump : nil
  }.compact.join("\n")
end
dump_element(target = nil) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 87
def dump_element(target = nil)
  @elements.collect { |ele|
    next if @complextypes[ele.name]
    next if target and target != ele.name
    c = create_elementdef(@modulepath, ele)
    c ? c.dump : nil
  }.compact.join("\n")
end
dump_group(target = nil) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 122
def dump_group(target = nil)
  definitions = @modelgroups.collect { |group|
    # TODO: not dumped for now but may be useful in the future
  }.compact.join("\n")
end
dump_simpletype(target = nil) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 106
def dump_simpletype(target = nil)
  @simpletypes.collect { |type|
    next if target and target != type.name
    c = create_simpletypedef(@modulepath, type.name, type)
    c ? c.dump : nil
  }.compact.join("\n")
end
modulepath_split(modulepath) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 422
def modulepath_split(modulepath)
  if modulepath.is_a?(::Array)
    modulepath
  else
    modulepath.to_s.split('::')
  end
end
parse_elements(c, elements, base_namespace, mpath, as_array = false) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 288
def parse_elements(c, elements, base_namespace, mpath, as_array = false)
  init_lines = []
  init_params = []
  any = false
  elements.each do |element|
    case element
    when XMLSchema::Any
      # only 1 <any/> is allowed for now.
      raise RuntimeError.new("duplicated 'any'") if any
      any = true
      attrname = '__xmlele_any'
      c.def_attr(attrname, false, attrname)
      c.def_method('set_any', 'elements') do
        '@__xmlele_any = elements'
      end
      init_lines << "@__xmlele_any = nil"
    when XMLSchema::Element
      next if element.ref == SchemaName
      name = name_element(element).name
      typebase = @modulepath
      if element.anonymous_type?
        inner = create_elementdef(mpath, element)
        unless as_array
          inner.comment = "inner class for member: #{name}\n" + inner.comment
        end
        c.innermodule << inner
        typebase = mpath
      end
      unless as_array
        attrname = safemethodname(name)
        varname = safevarname(name)
        c.def_attr(attrname, true, varname)
        init_lines << "@#{varname} = #{varname}"
        if element.map_as_array?
          init_params << "#{varname} = []"
        else
          init_params << "#{varname} = nil"
        end
        c.comment << "\n  #{attrname} - #{create_type_name(typebase, element) || '(any)'}"
      end
    when WSDL::XMLSchema::Sequence
      child_init_lines, child_init_params =
        parse_elements(c, element.elements, base_namespace, mpath, as_array)
      init_lines.concat(child_init_lines)
      init_params.concat(child_init_params)
    when WSDL::XMLSchema::Choice
      child_init_lines, child_init_params =
        parse_elements(c, element.elements, base_namespace, mpath, as_array)
      init_lines.concat(child_init_lines)
      init_params.concat(child_init_params)
    when WSDL::XMLSchema::Group
      if element.content.nil?
        warn("no group definition found: #{element}")
        next
      end
      child_init_lines, child_init_params =
        parse_elements(c, element.content.elements, base_namespace, mpath, as_array)
      init_lines.concat(child_init_lines)
      init_params.concat(child_init_params)
    else
      raise RuntimeError.new("unknown type: #{element}")
    end
  end
  [init_lines, init_params]
end
sort_dependency(types) click to toggle source
# File lib/wsdl/soap/classDefCreator.rb, line 392
def sort_dependency(types)
  dep = {}
  root = []
  types.each do |type|
    if type.complexcontent and (base = type.complexcontent.base)
      dep[base] ||= []
      dep[base] << type
    else
      root << type
    end
  end
  sorted = []
  root.each do |type|
    sorted.concat(collect_dependency(type, dep))
  end
  sorted.concat(dep.values.flatten)
  sorted
end