diff options
Diffstat (limited to 'lib/wsdl')
-rw-r--r-- | lib/wsdl/data.rb | 1 | ||||
-rw-r--r-- | lib/wsdl/definitions.rb | 21 | ||||
-rw-r--r-- | lib/wsdl/operation.rb | 2 | ||||
-rw-r--r-- | lib/wsdl/parser.rb | 3 | ||||
-rw-r--r-- | lib/wsdl/soap/cgiStubCreator.rb | 73 | ||||
-rw-r--r-- | lib/wsdl/soap/classDefCreator.rb | 112 | ||||
-rw-r--r-- | lib/wsdl/soap/classDefCreatorSupport.rb | 106 | ||||
-rw-r--r-- | lib/wsdl/soap/clientSkeltonCreator.rb | 78 | ||||
-rw-r--r-- | lib/wsdl/soap/definitions.rb | 28 | ||||
-rw-r--r-- | lib/wsdl/soap/driverCreator.rb | 84 | ||||
-rw-r--r-- | lib/wsdl/soap/mappingRegistryCreator.rb | 90 | ||||
-rw-r--r-- | lib/wsdl/soap/methodDefCreator.rb | 148 | ||||
-rw-r--r-- | lib/wsdl/soap/servantSkeltonCreator.rb | 65 | ||||
-rw-r--r-- | lib/wsdl/soap/standaloneServerStubCreator.rb | 79 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/complexContent.rb | 4 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/complexType.rb | 22 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/data.rb | 7 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/enumeration.rb | 36 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/parser.rb | 3 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/schema.rb | 13 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/simpleRestriction.rb | 48 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/simpleType.rb | 81 |
22 files changed, 1090 insertions, 14 deletions
diff --git a/lib/wsdl/data.rb b/lib/wsdl/data.rb index 8a14dd14d7..45eaad8526 100644 --- a/lib/wsdl/data.rb +++ b/lib/wsdl/data.rb @@ -6,6 +6,7 @@ # either the dual license version in 2003, or any later version. +require 'xsd/qname' require 'wsdl/documentation' require 'wsdl/definitions' require 'wsdl/types' diff --git a/lib/wsdl/definitions.rb b/lib/wsdl/definitions.rb index 561a335744..c530220fde 100644 --- a/lib/wsdl/definitions.rb +++ b/lib/wsdl/definitions.rb @@ -43,8 +43,7 @@ class Definitions < Info end def inspect - name = @name || '(unnamed)' - "#<#{self.class}:#{name}>" + sprintf("#<%s:0x%x %s>", self.class.name, __id__, @name || '(unnamed)') end def targetnamespace=(targetnamespace) @@ -58,7 +57,7 @@ class Definitions < Info result = XSD::NamedElements.new if @types @types.schemas.each do |schema| - result.concat(schema.elements) + result.concat(schema.collect_elements) end end @imports.each do |import| @@ -71,7 +70,7 @@ class Definitions < Info result = @anontypes.dup if @types @types.schemas.each do |schema| - result.concat(schema.complextypes) + result.concat(schema.collect_complextypes) end end @imports.each do |import| @@ -80,6 +79,20 @@ class Definitions < Info result end + def collect_simpletypes + result = XSD::NamedElements.new + if @types + @types.schemas.each do |schema| + result.concat(schema.collect_simpletypes) + end + end + @imports.each do |import| + result.concat(import.content.collect_simpletypes) + end + result + end + + # ToDo: simpletype must be accepted... def add_type(complextype) @anontypes << complextype end diff --git a/lib/wsdl/operation.rb b/lib/wsdl/operation.rb index 228dc85b05..be28446d34 100644 --- a/lib/wsdl/operation.rb +++ b/lib/wsdl/operation.rb @@ -119,7 +119,7 @@ private return parts.dup end if parts.length != result.length - raise RuntimeError.new("Incomplete parameter order list.") + raise RuntimeError.new("Incomplete prarmeterOrder list.") end result end diff --git a/lib/wsdl/parser.rb b/lib/wsdl/parser.rb index 7e7a4d8bce..6387911f79 100644 --- a/lib/wsdl/parser.rb +++ b/lib/wsdl/parser.rb @@ -119,7 +119,8 @@ private STDERR.puts("Unknown element #{ element }.") o = Documentation.new # which accepts any element. end - o.parent = parent + # node could be a pseudo element. pseudo element has its own parent. + o.parent = parent if o.parent.nil? end attrs.each do |key, value| attr = unless /:/ =~ key diff --git a/lib/wsdl/soap/cgiStubCreator.rb b/lib/wsdl/soap/cgiStubCreator.rb new file mode 100644 index 0000000000..e5b64336e7 --- /dev/null +++ b/lib/wsdl/soap/cgiStubCreator.rb @@ -0,0 +1,73 @@ +# WSDL4R - Creating CGI stub code from WSDL. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'wsdl/soap/mappingRegistryCreator' +require 'wsdl/soap/methodDefCreator' +require 'wsdl/soap/classDefCreatorSupport' + + +module WSDL +module SOAP + + +class CGIStubCreator + include ClassDefCreatorSupport + + attr_reader :definitions + + def initialize(definitions) + @definitions = definitions + end + + def dump(service_name) + STDERR.puts "!!! IMPORTANT !!!" + STDERR.puts "- CGI stub can only 1 port. Creating stub for the first port... Rests are ignored." + STDERR.puts "!!! IMPORTANT !!!" + port = @definitions.service(service_name).ports[0] + dump_porttype(port.porttype.name) + end + +private + + def dump_porttype(name) + class_name = create_class_name(name) + methoddef, types = MethodDefCreator.new(@definitions).dump(name) + mr_creator = MappingRegistryCreator.new(@definitions) + c1 = ::XSD::CodeGen::ClassDef.new(class_name) + c1.def_require("soap/rpc/cgistub") + c1.def_require("soap/mapping/registry") + c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new") + c1.def_code(mr_creator.dump(types)) + c1.def_code <<-EOD +Methods = [ +#{ methoddef.gsub(/^/, " ") } +] + EOD + c2 = ::XSD::CodeGen::ClassDef.new(class_name + "App", + "::SOAP::RPC::CGIStub") + c2.def_method("initialize", "*arg") do + <<-EOD + super(*arg) + servant = #{class_name}.new + #{class_name}::Methods.each do |name_as, name, params, soapaction, ns| + add_method_with_namespace_as(ns, servant, name, name_as, params, soapaction) + end + self.mapping_registry = #{class_name}::MappingRegistry + self.level = Logger::Severity::ERROR + EOD + end + c1.dump + "\n" + c2.dump + format(<<-EOD) + #{class_name}App.new('app', nil).start + EOD + end +end + + +end +end diff --git a/lib/wsdl/soap/classDefCreator.rb b/lib/wsdl/soap/classDefCreator.rb new file mode 100644 index 0000000000..6c7d381932 --- /dev/null +++ b/lib/wsdl/soap/classDefCreator.rb @@ -0,0 +1,112 @@ +# WSDL4R - Creating class definition from WSDL +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/data' +require 'wsdl/soap/classDefCreatorSupport' +require 'xsd/codegen' + + +module WSDL +module SOAP + + +class ClassDefCreator + include ClassDefCreatorSupport + + def initialize(definitions) + @simpletypes = definitions.collect_simpletypes + @complextypes = definitions.collect_complextypes + @faulttypes = definitions.collect_faulttypes + end + + def dump(class_name = nil) + result = "" + if class_name + result = dump_classdef(class_name) + else + @complextypes.each do |type| + case type.compoundtype + when :TYPE_STRUCT + result << dump_classdef(type) + when :TYPE_ARRAY + result << dump_arraydef(type) + else + raise RuntimeError.new("Unknown complexContent definition...") + end + result << "\n" + end + + result << @simpletypes.collect { |type| + dump_simpletypedef(type) + }.join("\n") + end + result + end + +private + + def dump_simpletypedef(simpletype) + qname = simpletype.name + if simpletype.restriction.enumeration.empty? + STDERR.puts("#{qname}: simpleType which is not enum type not supported.") + return "" + end + c = XSD::CodeGen::ModuleDef.new(create_class_name(qname)) + c.comment = "#{ qname.namespace }" + simpletype.restriction.enumeration.each do |value| + c.def_const(safeconstname(value), value.dump) + end + c.dump + end + + def dump_classdef(complextype) + qname = complextype.name + if @faulttypes.index(qname) + c = XSD::CodeGen::ClassDef.new(create_class_name(qname), + "::StandardError") + else + c = XSD::CodeGen::ClassDef.new(create_class_name(qname)) + end + c.comment = "#{ qname.namespace }" + c.def_classvar("schema_type", qname.name.dump) + c.def_classvar("schema_ns", qname.namespace.dump) + init_lines = "" + params = [] + complextype.each_element do |element| + name = element.name.name + varname = safevarname(name) + c.def_attr(name, true, varname) + init_lines << "@#{ varname } = #{ varname }\n" + params << "#{ varname } = nil" + end + complextype.attributes.each do |attribute| + name = "attr_" + attribute.name + varname = safevarname(name) + c.def_attr(name, true, varname) + init_lines << "@#{ varname } = #{ varname }\n" + params << "#{ varname } = nil" + end + c.def_method("initialize", *params) do + init_lines + end + c.dump + end + + def dump_arraydef(complextype) + qname = complextype.name + c = XSD::CodeGen::ClassDef.new(create_class_name(qname), "::Array") + c.comment = "#{ qname.namespace }" + c.def_classvar("schema_type", qname.name.dump) + c.def_classvar("schema_ns", qname.namespace.dump) + c.dump + end +end + + +end +end diff --git a/lib/wsdl/soap/classDefCreatorSupport.rb b/lib/wsdl/soap/classDefCreatorSupport.rb new file mode 100644 index 0000000000..dbcc55f7b9 --- /dev/null +++ b/lib/wsdl/soap/classDefCreatorSupport.rb @@ -0,0 +1,106 @@ +# WSDL4R - Creating class code support from WSDL. +# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'soap/mapping' +require 'soap/mapping/typeMap' +require 'xsd/codegen/gensupport' + + +module WSDL +module SOAP + + +module ClassDefCreatorSupport + include XSD::CodeGen::GenSupport + + def create_class_name(qname) + if klass = basetype_mapped_class(qname) + ::SOAP::Mapping::DefaultRegistry.find_mapped_obj_class(klass.name) + else + safeconstname(qname.name) + end + end + + def basetype_mapped_class(name) + ::SOAP::TypeMap[name] + end + + def dump_method_signature(operation) + name = operation.name.name + input = operation.input + output = operation.output + fault = operation.fault + signature = "#{ name }#{ dump_inputparam(input) }" + str = <<__EOD__ +# SYNOPSIS +# #{name}#{dump_inputparam(input)} +# +# ARGS +#{dump_inout_type(input).chomp} +# +# RETURNS +#{dump_inout_type(output).chomp} +# +__EOD__ + unless fault.empty? + faultstr = (fault.collect { |f| dump_inout_type(f).chomp }).join(', ') + str <<<<__EOD__ +# RAISES +# #{faultstr} +# +__EOD__ + end + str + end + +private + + def dump_inout_type(param) + if param + message = param.find_message + params = "" + message.parts.each do |part| + next unless part.type + name = safevarname(part.name) + typename = safeconstname(part.type.name) + params << add_at("# #{name}", "#{typename} - #{part.type}\n", 20) + end + unless params.empty? + return params + end + end + "# N/A\n" + end + + def dump_inputparam(input) + message = input.find_message + params = "" + message.parts.each do |part| + params << ", " unless params.empty? + params << safevarname(part.name) + end + if params.empty? + "" + else + "(#{ params })" + end + end + + def add_at(base, str, pos) + if base.size >= pos + base + ' ' + str + else + base + ' ' * (pos - base.size) + str + end + end +end + + +end +end diff --git a/lib/wsdl/soap/clientSkeltonCreator.rb b/lib/wsdl/soap/clientSkeltonCreator.rb new file mode 100644 index 0000000000..9c538dd612 --- /dev/null +++ b/lib/wsdl/soap/clientSkeltonCreator.rb @@ -0,0 +1,78 @@ +# WSDL4R - Creating client skelton code from WSDL. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'wsdl/soap/classDefCreatorSupport' + + +module WSDL +module SOAP + + +class ClientSkeltonCreator + include ClassDefCreatorSupport + + attr_reader :definitions + + def initialize(definitions) + @definitions = definitions + end + + def dump(service_name) + result = "" + @definitions.service(service_name).ports.each do |port| + result << dump_porttype(port.porttype.name) + result << "\n" + end + result + end + +private + + def dump_porttype(name) + drv_name = create_class_name(name) + + result = "" + result << <<__EOD__ +endpoint_url = ARGV.shift +obj = #{ drv_name }.new(endpoint_url) + +# Uncomment the below line to see SOAP wiredumps. +# obj.wiredump_dev = STDERR + +__EOD__ + @definitions.porttype(name).operations.each do |operation| + result << dump_method_signature(operation) + result << dump_input_init(operation.input) << "\n" + result << dump_operation(operation) << "\n\n" + end + result + end + + def dump_operation(operation) + name = operation.name + input = operation.input + "puts obj.#{ safemethodname(name.name) }#{ dump_inputparam(input) }" + end + + def dump_input_init(input) + result = input.find_message.parts.collect { |part| + "#{ uncapitalize(part.name) }" + }.join(" = ") + if result.empty? + "" + else + result << " = nil" + end + result + end +end + + +end +end diff --git a/lib/wsdl/soap/definitions.rb b/lib/wsdl/soap/definitions.rb index 7a62242204..2f6e7e19f0 100644 --- a/lib/wsdl/soap/definitions.rb +++ b/lib/wsdl/soap/definitions.rb @@ -75,8 +75,36 @@ class Definitions < Info types + self.class.soap_rpc_complextypes end + def collect_faulttypes + result = [] + collect_fault_messages.each do |message| + parts = message(message).parts + if parts.size != 1 + raise RuntimeError.new("Expecting fault message to have only 1 part.") + end + if result.index(parts[0].type).nil? + result << parts[0].type + end + end + result + end + private + def collect_fault_messages + result = [] + porttypes.each do |porttype| + porttype.operations.each do |operation| + operation.fault.each do |fault| + if result.index(fault.message).nil? + result << fault.message + end + end + end + end + result + end + def rpc_operation_complextypes(binding) types = XSD::NamedElements.new binding.operations.each do |op_bind| diff --git a/lib/wsdl/soap/driverCreator.rb b/lib/wsdl/soap/driverCreator.rb new file mode 100644 index 0000000000..50be8ed1dc --- /dev/null +++ b/lib/wsdl/soap/driverCreator.rb @@ -0,0 +1,84 @@ +# WSDL4R - Creating driver code from WSDL. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'wsdl/soap/mappingRegistryCreator' +require 'wsdl/soap/methodDefCreator' +require 'wsdl/soap/classDefCreatorSupport' +require 'xsd/codegen' + + +module WSDL +module SOAP + + +class DriverCreator + include ClassDefCreatorSupport + + attr_reader :definitions + + def initialize(definitions) + @definitions = definitions + end + + def dump(porttype = nil) + if porttype.nil? + result = "" + @definitions.porttypes.each do |type| + result << dump_porttype(type.name) + result << "\n" + end + else + result = dump_porttype(porttype) + end + result + end + +private + + def dump_porttype(name) + class_name = create_class_name(name) + methoddef, types = MethodDefCreator.new(@definitions).dump(name) + mr_creator = MappingRegistryCreator.new(@definitions) + binding = @definitions.bindings.find { |item| item.type == name } + addresses = @definitions.porttype(name).locations + + c = ::XSD::CodeGen::ClassDef.new(class_name, "::SOAP::RPC::Driver") + c.def_require("soap/rpc/driver") + c.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new") + c.def_const("DefaultEndpointUrl", addresses[0].dump) + c.def_code(mr_creator.dump(types)) + c.def_code <<-EOD +Methods = [ +#{ methoddef.gsub(/^/, " ") } +] + EOD + c.def_method("initialize", "endpoint_url = nil") do + <<-EOD + endpoint_url ||= DefaultEndpointUrl + super(endpoint_url, nil) + self.mapping_registry = MappingRegistry + init_methods + EOD + end + c.def_privatemethod("init_methods") do + <<-EOD + Methods.each do |name_as, name, params, soapaction, namespace| + qname = ::XSD::QName.new(namespace, name_as) + @proxy.add_method(qname, soapaction, name, params) + add_rpc_method_interface(name, params) + end + EOD + end + c.dump + end +end + + +end +end diff --git a/lib/wsdl/soap/mappingRegistryCreator.rb b/lib/wsdl/soap/mappingRegistryCreator.rb new file mode 100644 index 0000000000..d3b28f47e0 --- /dev/null +++ b/lib/wsdl/soap/mappingRegistryCreator.rb @@ -0,0 +1,90 @@ +# WSDL4R - Creating MappingRegistry code from WSDL. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'wsdl/soap/classDefCreatorSupport' + + +module WSDL +module SOAP + + +class MappingRegistryCreator + include ClassDefCreatorSupport + + attr_reader :definitions + + def initialize(definitions) + @definitions = definitions + @complextypes = @definitions.collect_complextypes + @types = nil + end + + def dump(types) + @types = types + map_cache = [] + map = "" + @types.each do |type| + if map_cache.index(type).nil? + map_cache << type + if type.namespace != XSD::Namespace + if typemap = dump_typemap(type) + map << typemap + end + end + end + end + return map + end + +private + + def dump_typemap(type) + if definedtype = @complextypes[type] + case definedtype.compoundtype + when :TYPE_STRUCT + dump_struct_typemap(definedtype) + when :TYPE_ARRAY + dump_array_typemap(definedtype) + else + raise NotImplementedError.new("Must not reach here.") + end + end + end + + def dump_struct_typemap(definedtype) + ele = definedtype.name + return <<__EOD__ +MappingRegistry.set( + #{ create_class_name(ele) }, + ::SOAP::SOAPStruct, + ::SOAP::Mapping::Registry::TypedStructFactory, + { :type => ::XSD::QName.new("#{ ele.namespace }", "#{ ele.name }") } +) +__EOD__ + end + + def dump_array_typemap(definedtype) + ele = definedtype.name + arytype = definedtype.find_arytype || XSD::AnyTypeName + type = XSD::QName.new(arytype.namespace, arytype.name.sub(/\[(?:,)*\]$/, '')) + @types << type + return <<__EOD__ +MappingRegistry.set( + #{ create_class_name(ele) }, + ::SOAP::SOAPArray, + ::SOAP::Mapping::Registry::TypedArrayFactory, + { :type => ::XSD::QName.new("#{ type.namespace }", "#{ type.name }") } +) +__EOD__ + end +end + + +end +end diff --git a/lib/wsdl/soap/methodDefCreator.rb b/lib/wsdl/soap/methodDefCreator.rb new file mode 100644 index 0000000000..eded972cdc --- /dev/null +++ b/lib/wsdl/soap/methodDefCreator.rb @@ -0,0 +1,148 @@ +# WSDL4R - Creating driver code from WSDL. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'wsdl/soap/classDefCreatorSupport' + + +module WSDL +module SOAP + + +class MethodDefCreator + include ClassDefCreatorSupport + + attr_reader :definitions + + def initialize(definitions) + @definitions = definitions + @simpletypes = @definitions.collect_simpletypes + @complextypes = @definitions.collect_complextypes + @elements = @definitions.collect_elements + @types = nil + end + + def dump(porttype) + @types = [] + result = "" + operations = @definitions.porttype(porttype).operations + binding = @definitions.porttype_binding(porttype) + operations.each do |operation| + op_bind = binding.operations[operation.name] + result << ",\n" unless result.empty? + result << dump_method(operation, op_bind).chomp + end + return result, @types + end + +private + + def dump_method(operation, binding) + name = safemethodname(operation.name.name) + name_as = operation.name.name + params = collect_parameter(operation) + soapaction = binding.soapoperation.soapaction + namespace = binding.input.soapbody.namespace + paramstr = param2str(params) + if paramstr.empty? + paramstr = '[]' + else + paramstr = "[\n" << paramstr.gsub(/^/, ' ') << "\n ]" + end + return <<__EOD__ +[#{ dq(name_as) }, #{ dq(name) }, + #{ paramstr }, + #{ soapaction ? dq(soapaction) : "nil" }, #{ dq(namespace) } +] +__EOD__ + end + + def collect_parameter(operation) + result = operation.inputparts.collect { |part| + collect_type(part.type) + param_set('in', definedtype(part), part.name) + } + outparts = operation.outputparts + if outparts.size > 0 + retval = outparts[0] + collect_type(retval.type) + result << param_set('retval', definedtype(retval), retval.name) + cdr(outparts).each { |part| + collect_type(part.type) + result << param_set('out', definedtype(part), part.name) + } + end + result + end + + def definedtype(part) + if mapped = basetype_mapped_class(part.type) + ['::' + mapped.name] + elsif definedelement = @elements[part.element] + raise RuntimeError.new("Part: #{part.name} should be typed for RPC service for now.") + elsif definedtype = @simpletypes[part.type] + ['::' + basetype_mapped_class(definedtype.base).name] + elsif definedtype = @complextypes[part.type] + case definedtype.compoundtype + when :TYPE_STRUCT + ['::SOAP::SOAPStruct', part.type.namespace, part.type.name] + when :TYPE_ARRAY + arytype = definedtype.find_arytype || XSD::AnyTypeName + ns = arytype.namespace + name = arytype.name.sub(/\[(?:,)*\]$/, '') + ['::SOAP::SOAPArray', ns, name] + else + raise NotImplementedError.new("Must not reach here.") + end + else + raise RuntimeError.new("Part: #{part.name} cannot be resolved.") + end + end + + def param_set(io_type, type, name) + [io_type, type, name] + end + + def collect_type(type) + # ignore inline type definition. + return if type.nil? + @types << type + return unless @complextypes[type] + @complextypes[type].each_element do |element| + collect_type(element.type) + end + end + + def param2str(params) + params.collect { |param| + "[#{ dq(param[0]) }, #{ dq(param[2]) }, #{ type2str(param[1]) }]" + }.join(",\n") + end + + def type2str(type) + if type.size == 1 + "[#{ type[0] }]" + else + "[#{ type[0] }, #{ dq(type[1]) }, #{ dq(type[2]) }]" + end + end + + def dq(ele) + "\"" << ele << "\"" + end + + def cdr(ary) + result = ary.dup + result.shift + result + end +end + + +end +end diff --git a/lib/wsdl/soap/servantSkeltonCreator.rb b/lib/wsdl/soap/servantSkeltonCreator.rb new file mode 100644 index 0000000000..bf293949b8 --- /dev/null +++ b/lib/wsdl/soap/servantSkeltonCreator.rb @@ -0,0 +1,65 @@ +# WSDL4R - Creating servant skelton code from WSDL. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'wsdl/soap/classDefCreatorSupport' +require 'xsd/codegen' + + +module WSDL +module SOAP + + +class ServantSkeltonCreator + include ClassDefCreatorSupport + include ::XSD::CodeGen::GenSupport + + attr_reader :definitions + + def initialize(definitions) + @definitions = definitions + end + + def dump(porttype = nil) + if porttype.nil? + result = "" + @definitions.porttypes.each do |type| + result << dump_porttype(type.name) + result << "\n" + end + else + result = dump_porttype(porttype) + end + result + end + +private + + def dump_porttype(name) + class_name = create_class_name(name) + c = ::XSD::CodeGen::ClassDef.new(class_name) + operations = @definitions.porttype(name).operations + operations.each do |operation| + name = operation.name.name + input = operation.input + m = ::XSD::CodeGen::MethodDef.new(name, + input.find_message.parts.collect { |part| safevarname(part.name) }) do + <<-EOD + raise NotImplementedError.new + EOD + end + m.comment = dump_method_signature(operation) + c.add_method(m) + end + c.dump + end +end + + +end +end diff --git a/lib/wsdl/soap/standaloneServerStubCreator.rb b/lib/wsdl/soap/standaloneServerStubCreator.rb new file mode 100644 index 0000000000..34bcfdbba9 --- /dev/null +++ b/lib/wsdl/soap/standaloneServerStubCreator.rb @@ -0,0 +1,79 @@ +# WSDL4R - Creating standalone server stub code from WSDL. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'wsdl/soap/mappingRegistryCreator' +require 'wsdl/soap/methodDefCreator' +require 'wsdl/soap/classDefCreatorSupport' + + +module WSDL +module SOAP + + +class StandaloneServerStubCreator + include ClassDefCreatorSupport + + attr_reader :definitions + + def initialize(definitions) + @definitions = definitions + end + + def dump(service_name) + STDERR.puts "!!! IMPORTANT !!!" + STDERR.puts "- Standalone stub can have only 1 port for now. So creating stub for the first port and rests are ignored." + STDERR.puts "- Standalone server stub ignores port location defined in WSDL. Location is http://localhost:10080/ by default. Generated client from WSDL must be configured to point this endpoint by hand." + STDERR.puts "!!! IMPORTANT !!!" + port = @definitions.service(service_name).ports[0] + dump_porttype(port.porttype.name) + end + +private + + def dump_porttype(name) + class_name = create_class_name(name) + methoddef, types = MethodDefCreator.new(@definitions).dump(name) + mr_creator = MappingRegistryCreator.new(@definitions) + + c1 = ::XSD::CodeGen::ClassDef.new(class_name) + c1.def_require("soap/rpc/standaloneServer") + c1.def_require("soap/mapping/registry") + c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new") + c1.def_code(mr_creator.dump(types)) + c1.def_code <<-EOD +Methods = [ +#{ methoddef.gsub(/^/, " ") } +] + EOD + c2 = ::XSD::CodeGen::ClassDef.new(class_name + "App", + "::SOAP::RPC::StandaloneServer") + c2.def_method("initialize", "*arg") do + <<-EOD + super(*arg) + servant = #{class_name}.new + #{class_name}::Methods.each do |name_as, name, params, soapaction, ns| + qname = XSD::QName.new(ns, name_as) + @soaplet.app_scope_router.add_method(servant, qname, soapaction, name, params) + end + self.mapping_registry = #{class_name}::MappingRegistry + EOD + end + c1.dump + "\n" + c2.dump + format(<<-EOD) + + if $0 == __FILE__ + # Change listen port. + #{class_name}App.new('app', nil, '0.0.0.0', 10080).start + end + EOD + end +end + + +end +end diff --git a/lib/wsdl/xmlSchema/complexContent.rb b/lib/wsdl/xmlSchema/complexContent.rb index 22f6851864..66ad9e251d 100644 --- a/lib/wsdl/xmlSchema/complexContent.rb +++ b/lib/wsdl/xmlSchema/complexContent.rb @@ -28,6 +28,10 @@ class ComplexContent < Info @attributes = XSD::NamedElements.new end + def targetnamespace + parent.targetnamespace + end + def parse_element(element) case element when RestrictionName, ExtensionName diff --git a/lib/wsdl/xmlSchema/complexType.rb b/lib/wsdl/xmlSchema/complexType.rb index e889482d09..056a806dc5 100644 --- a/lib/wsdl/xmlSchema/complexType.rb +++ b/lib/wsdl/xmlSchema/complexType.rb @@ -8,6 +8,7 @@ require 'wsdl/info' require 'wsdl/xmlSchema/content' +require 'wsdl/xmlSchema/element' require 'xsd/namedelements' @@ -36,11 +37,16 @@ class ComplexType < Info def targetnamespace parent.targetnamespace end - + + AnyAsElement = Element.new(XSD::QName.new(nil, 'any'), XSD::AnyTypeName) def each_element if @content @content.elements.each do |element| - yield(element.name, element) + if element.is_a?(Any) + yield(AnyAsElement) + else + yield(element) + end end end end @@ -48,7 +54,11 @@ class ComplexType < Info def find_element(name) if @content @content.elements.each do |element| - return element if name == element.name + if element.is_a?(Any) + return AnyAsElement if name == AnyAsElement.name + else + return element if name == element.name + end end end nil @@ -57,7 +67,11 @@ class ComplexType < Info def find_element_by_name(name) if @content @content.elements.each do |element| - return element if name == element.name.name + if element.is_a?(Any) + return AnyAsElement if name == AnyAsElement.name.name + else + return element if name == element.name.name + end end end nil diff --git a/lib/wsdl/xmlSchema/data.rb b/lib/wsdl/xmlSchema/data.rb index 2fa8ad6a91..1283ac2a1d 100644 --- a/lib/wsdl/xmlSchema/data.rb +++ b/lib/wsdl/xmlSchema/data.rb @@ -6,8 +6,11 @@ # either the dual license version in 2003, or any later version. +require 'xsd/datatypes' require 'wsdl/xmlSchema/schema' require 'wsdl/xmlSchema/import' +require 'wsdl/xmlSchema/simpleType' +require 'wsdl/xmlSchema/simpleRestriction' require 'wsdl/xmlSchema/complexType' require 'wsdl/xmlSchema/complexContent' require 'wsdl/xmlSchema/any' @@ -17,7 +20,7 @@ require 'wsdl/xmlSchema/choice' require 'wsdl/xmlSchema/sequence' require 'wsdl/xmlSchema/attribute' require 'wsdl/xmlSchema/unique' - +require 'wsdl/xmlSchema/enumeration' module WSDL module XMLSchema @@ -30,6 +33,7 @@ ChoiceName = XSD::QName.new(XSD::Namespace, 'choice') ComplexContentName = XSD::QName.new(XSD::Namespace, 'complexContent') ComplexTypeName = XSD::QName.new(XSD::Namespace, 'complexType') ElementName = XSD::QName.new(XSD::Namespace, 'element') +EnumerationName = XSD::QName.new(XSD::Namespace, 'enumeration') ExtensionName = XSD::QName.new(XSD::Namespace, 'extension') ImportName = XSD::QName.new(XSD::Namespace, 'import') RestrictionName = XSD::QName.new(XSD::Namespace, 'restriction') @@ -57,6 +61,7 @@ SchemaLocationAttrName = XSD::QName.new(nil, 'schemaLocation') TargetNamespaceAttrName = XSD::QName.new(nil, 'targetNamespace') TypeAttrName = XSD::QName.new(nil, 'type') UseAttrName = XSD::QName.new(nil, 'use') +ValueAttrName = XSD::QName.new(nil, 'value') end diff --git a/lib/wsdl/xmlSchema/enumeration.rb b/lib/wsdl/xmlSchema/enumeration.rb new file mode 100644 index 0000000000..cd61572d07 --- /dev/null +++ b/lib/wsdl/xmlSchema/enumeration.rb @@ -0,0 +1,36 @@ +# WSDL4R - XMLSchema enumeration definition for WSDL. +# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' + + +module WSDL +module XMLSchema + + +class Enumeration < Info + def initialize + super + end + + def parse_element(element) + nil + end + + def parse_attr(attr, value) + case attr + when ValueAttrName + parent.enumeration << value + value + end + end +end + + +end +end diff --git a/lib/wsdl/xmlSchema/parser.rb b/lib/wsdl/xmlSchema/parser.rb index 688af27c8c..5401c5f729 100644 --- a/lib/wsdl/xmlSchema/parser.rb +++ b/lib/wsdl/xmlSchema/parser.rb @@ -116,7 +116,8 @@ private unless o raise UnknownElementError.new("Unknown element #{ element }.") end - o.parent = parent + # node could be a pseudo element. pseudo element has its own parent. + o.parent = parent if o.parent.nil? end attrs.each do |key, value| attr = unless /:/ =~ key diff --git a/lib/wsdl/xmlSchema/schema.rb b/lib/wsdl/xmlSchema/schema.rb index b2a195d41f..b530a92556 100644 --- a/lib/wsdl/xmlSchema/schema.rb +++ b/lib/wsdl/xmlSchema/schema.rb @@ -17,6 +17,7 @@ module XMLSchema class Schema < Info attr_reader :targetnamespace # required attr_reader :complextypes + attr_reader :simpletypes attr_reader :elements attr_reader :attributes attr_reader :imports @@ -27,6 +28,7 @@ class Schema < Info super @targetnamespace = nil @complextypes = XSD::NamedElements.new + @simpletypes = XSD::NamedElements.new @elements = XSD::NamedElements.new @attributes = XSD::NamedElements.new @imports = [] @@ -44,8 +46,9 @@ class Schema < Info @complextypes << o o when SimpleTypeName - STDERR.puts("Restriction of basetype with simpleType definition is ignored for now.") - nil + o = SimpleType.new + @simpletypes << o + o when ElementName o = Element.new @elements << o @@ -83,6 +86,12 @@ class Schema < Info result end + def collect_simpletypes + result = XSD::NamedElements.new + result.concat(@simpletypes) + result + end + def self.parse_element(element) if element == SchemaName Schema.new diff --git a/lib/wsdl/xmlSchema/simpleRestriction.rb b/lib/wsdl/xmlSchema/simpleRestriction.rb new file mode 100644 index 0000000000..6986e74423 --- /dev/null +++ b/lib/wsdl/xmlSchema/simpleRestriction.rb @@ -0,0 +1,48 @@ +# WSDL4R - XMLSchema simpleType definition for WSDL. +# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'xsd/namedelements' + + +module WSDL +module XMLSchema + + +class SimpleRestriction < Info + attr_reader :base + attr_reader :enumeration + + def initialize + super + @base = nil + @enumeration = [] # NamedElements? + end + + def valid?(value) + @enumeration.include?(value) + end + + def parse_element(element) + case element + when EnumerationName + Enumeration.new # just a parsing handler + end + end + + def parse_attr(attr, value) + case attr + when BaseAttrName + @base = value + end + end +end + + +end +end diff --git a/lib/wsdl/xmlSchema/simpleType.rb b/lib/wsdl/xmlSchema/simpleType.rb new file mode 100644 index 0000000000..830086f99e --- /dev/null +++ b/lib/wsdl/xmlSchema/simpleType.rb @@ -0,0 +1,81 @@ +# WSDL4R - XMLSchema simpleType definition for WSDL. +# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'xsd/namedelements' + + +module WSDL +module XMLSchema + + +class SimpleType < Info + attr_accessor :name + attr_reader :derivetype + attr_reader :restriction + + def check_lexical_format(value) + if @restriction + check_restriction(value) + elsif @extension + raise NotImplementedError + # ToDo + else + raise ArgumentError.new("incomplete simpleType") + end + end + + def base + if @restriction + @restriction.base + elsif @extension + @extension.base + else + raise ArgumentError.new("incomplete simpleType") + end + end + + def initialize(name = nil) + super() + @name = name + @derivetype = nil + @restriction = nil + end + + def targetnamespace + parent.targetnamespace + end + + def parse_element(element) + case element + when RestrictionName + @restriction = SimpleRestriction.new + @derivetype = element.name + @restriction + end + end + + def parse_attr(attr, value) + case attr + when NameAttrName + @name = XSD::QName.new(targetnamespace, value) + end + end + +private + + def check_restriction(value) + unless @restriction.valid?(value) + raise ::XSD::ValueSpaceError.new("#{@name}: cannot accept '#{value}'.") + end + end +end + + +end +end |