sekken 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.travis.yml +11 -0
- data/.yardopts +6 -0
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +27 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +21 -0
- data/donate.png +0 -0
- data/lib/sekken.rb +75 -0
- data/lib/sekken/envelope.rb +92 -0
- data/lib/sekken/errors.rb +9 -0
- data/lib/sekken/example_message.rb +41 -0
- data/lib/sekken/httpclient.rb +35 -0
- data/lib/sekken/importer.rb +77 -0
- data/lib/sekken/message.rb +135 -0
- data/lib/sekken/operation.rb +100 -0
- data/lib/sekken/resolver.rb +20 -0
- data/lib/sekken/response.rb +50 -0
- data/lib/sekken/version.rb +5 -0
- data/lib/sekken/wsdl.rb +86 -0
- data/lib/sekken/wsdl/binding.rb +64 -0
- data/lib/sekken/wsdl/binding_operation.rb +85 -0
- data/lib/sekken/wsdl/document.rb +83 -0
- data/lib/sekken/wsdl/document_collection.rb +61 -0
- data/lib/sekken/wsdl/input_output.rb +84 -0
- data/lib/sekken/wsdl/message.rb +38 -0
- data/lib/sekken/wsdl/operation.rb +47 -0
- data/lib/sekken/wsdl/port.rb +29 -0
- data/lib/sekken/wsdl/port_type.rb +38 -0
- data/lib/sekken/wsdl/port_type_operation.rb +42 -0
- data/lib/sekken/wsdl/service.rb +55 -0
- data/lib/sekken/xml/attribute.rb +13 -0
- data/lib/sekken/xml/element.rb +82 -0
- data/lib/sekken/xml/element_builder.rb +220 -0
- data/lib/sekken/xs/schema.rb +57 -0
- data/lib/sekken/xs/schema_collection.rb +49 -0
- data/lib/sekken/xs/types.rb +272 -0
- data/sekken.gemspec +42 -0
- data/spec/fixtures/response/another_soap_fault.xml +14 -0
- data/spec/fixtures/response/authentication.xml +14 -0
- data/spec/fixtures/response/header.xml +13 -0
- data/spec/fixtures/response/list.xml +18 -0
- data/spec/fixtures/response/multi_ref.xml +39 -0
- data/spec/fixtures/response/soap_fault.xml +8 -0
- data/spec/fixtures/response/soap_fault12.xml +18 -0
- data/spec/fixtures/response/taxcloud.xml +1 -0
- data/spec/fixtures/wsdl/amazon.wsdl +1920 -0
- data/spec/fixtures/wsdl/arrays_with_attributes.wsdl +117 -0
- data/spec/fixtures/wsdl/authentication.wsdl +63 -0
- data/spec/fixtures/wsdl/awse.wsdl +1510 -0
- data/spec/fixtures/wsdl/betfair.wsdl +2981 -0
- data/spec/fixtures/wsdl/blz_service.wsdl +88 -0
- data/spec/fixtures/wsdl/bookt/bookt.wsdl +11 -0
- data/spec/fixtures/wsdl/bookt/bookt0.xsd +433 -0
- data/spec/fixtures/wsdl/bookt/bookt1.xsd +42 -0
- data/spec/fixtures/wsdl/bookt/bookt10.xsd +38 -0
- data/spec/fixtures/wsdl/bookt/bookt11.xsd +17 -0
- data/spec/fixtures/wsdl/bookt/bookt12.xsd +18 -0
- data/spec/fixtures/wsdl/bookt/bookt13.xsd +22 -0
- data/spec/fixtures/wsdl/bookt/bookt14.xsd +27 -0
- data/spec/fixtures/wsdl/bookt/bookt15.xsd +28 -0
- data/spec/fixtures/wsdl/bookt/bookt2.wsdl +243 -0
- data/spec/fixtures/wsdl/bookt/bookt2.xsd +81 -0
- data/spec/fixtures/wsdl/bookt/bookt3.wsdl +286 -0
- data/spec/fixtures/wsdl/bookt/bookt3.xsd +61 -0
- data/spec/fixtures/wsdl/bookt/bookt4.xsd +35 -0
- data/spec/fixtures/wsdl/bookt/bookt5.xsd +22 -0
- data/spec/fixtures/wsdl/bookt/bookt6.xsd +26 -0
- data/spec/fixtures/wsdl/bookt/bookt7.xsd +18 -0
- data/spec/fixtures/wsdl/bookt/bookt8.xsd +22 -0
- data/spec/fixtures/wsdl/bookt/bookt9.xsd +29 -0
- data/spec/fixtures/wsdl/bronto.wsdl +3285 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange.wsdl +104 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange0.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange1.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange2.wsdl +119 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange2.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange3.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange4.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange5.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange6.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange7.xsd +1 -0
- data/spec/fixtures/wsdl/bydexchange/bydexchange8.xsd +1 -0
- data/spec/fixtures/wsdl/crowd.wsdl +2437 -0
- data/spec/fixtures/wsdl/data_exchange.wsdl +98 -0
- data/spec/fixtures/wsdl/document_literal_wrapped.wsdl +153 -0
- data/spec/fixtures/wsdl/economic.wsdl +65660 -0
- data/spec/fixtures/wsdl/edialog.wsdl +13148 -0
- data/spec/fixtures/wsdl/email_verification.wsdl +394 -0
- data/spec/fixtures/wsdl/equifax.wsdl +794 -0
- data/spec/fixtures/wsdl/geotrust.wsdl +156 -0
- data/spec/fixtures/wsdl/interhome.wsdl +2137 -0
- data/spec/fixtures/wsdl/iws.wsdl +695 -0
- data/spec/fixtures/wsdl/jetairways.wsdl +156 -0
- data/spec/fixtures/wsdl/jira.wsdl +3890 -0
- data/spec/fixtures/wsdl/juniper.wsdl +215 -0
- data/spec/fixtures/wsdl/namespaced_actions.wsdl +307 -0
- data/spec/fixtures/wsdl/oracle.wsdl +3629 -0
- data/spec/fixtures/wsdl/ratp.wsdl +955 -0
- data/spec/fixtures/wsdl/rio2/rio2.wsdl +74 -0
- data/spec/fixtures/wsdl/rio2/rio2_0.wsdl +55 -0
- data/spec/fixtures/wsdl/rio2/rio2_0.xsd +58 -0
- data/spec/fixtures/wsdl/rio2/rio2_1.xsd +41 -0
- data/spec/fixtures/wsdl/rio2/rio2_2.xsd +222 -0
- data/spec/fixtures/wsdl/rio2/rio2_3.xsd +10 -0
- data/spec/fixtures/wsdl/rpc_literal.wsdl +105 -0
- data/spec/fixtures/wsdl/spyne.wsdl +70 -0
- data/spec/fixtures/wsdl/stockquote.wsdl +124 -0
- data/spec/fixtures/wsdl/taxcloud.wsdl +934 -0
- data/spec/fixtures/wsdl/team_software/team_software.wsdl +542 -0
- data/spec/fixtures/wsdl/team_software/team_software0.xsd +448 -0
- data/spec/fixtures/wsdl/team_software/team_software1.xsd +41 -0
- data/spec/fixtures/wsdl/team_software/team_software2.xsd +258 -0
- data/spec/fixtures/wsdl/team_software/team_software3.xsd +14 -0
- data/spec/fixtures/wsdl/telefonkatalogen.wsdl +45 -0
- data/spec/fixtures/wsdl/temperature.wsdl +136 -0
- data/spec/fixtures/wsdl/wasmuth/wasmuth.wsdl +157 -0
- data/spec/fixtures/wsdl/wasmuth/wasmuth1.xsd +210 -0
- data/spec/fixtures/wsdl/wasmuth/wasmuth2.xsd +549 -0
- data/spec/fixtures/wsdl/xignite.wsdl +3470 -0
- data/spec/fixtures/wsdl/yahoo.wsdl +2425 -0
- data/spec/fixtures/wsdl/zanox_export_service.xml +520 -0
- data/spec/integration/amazon_spec.rb +51 -0
- data/spec/integration/authentication_spec.rb +38 -0
- data/spec/integration/awse_spec.rb +95 -0
- data/spec/integration/betfair_spec.rb +179 -0
- data/spec/integration/blz_service_spec.rb +46 -0
- data/spec/integration/bookt_spec.rb +59 -0
- data/spec/integration/bronto_spec.rb +178 -0
- data/spec/integration/bydexchange_spec.rb +40 -0
- data/spec/integration/crowd_spec.rb +44 -0
- data/spec/integration/data_exchange_spec.rb +27 -0
- data/spec/integration/document_literal_spec.rb +104 -0
- data/spec/integration/economic_spec.rb +64 -0
- data/spec/integration/email_verification_spec.rb +82 -0
- data/spec/integration/equifax_spec.rb +216 -0
- data/spec/integration/geotrust_spec.rb +17 -0
- data/spec/integration/interhome_spec.rb +156 -0
- data/spec/integration/iws_spec.rb +27 -0
- data/spec/integration/jetairways_spec.rb +142 -0
- data/spec/integration/jira_spec.rb +27 -0
- data/spec/integration/juniper_spec.rb +20 -0
- data/spec/integration/namespaced_actions_spec.rb +37 -0
- data/spec/integration/oracle_spec.rb +61 -0
- data/spec/integration/ratp_spec.rb +178 -0
- data/spec/integration/rio2_spec.rb +56 -0
- data/spec/integration/rpc_literal_spec.rb +101 -0
- data/spec/integration/spyne_spec.rb +60 -0
- data/spec/integration/stockquote_spec.rb +46 -0
- data/spec/integration/taxcloud_spec.rb +45 -0
- data/spec/integration/team_software_spec.rb +51 -0
- data/spec/integration/telefonkatalogen_spec.rb +42 -0
- data/spec/integration/temperature_spec.rb +71 -0
- data/spec/integration/wasmuth_spec.rb +47 -0
- data/spec/integration/xignite_spec.rb +112 -0
- data/spec/integration/yahoo_spec.rb +116 -0
- data/spec/sekken/httpclient_spec.rb +41 -0
- data/spec/sekken/operation/build_spec.rb +308 -0
- data/spec/sekken/operation/document_literal_spec.rb +53 -0
- data/spec/sekken/operation/example_body_spec.rb +95 -0
- data/spec/sekken/operation/rpc_literal_spec.rb +50 -0
- data/spec/sekken/operation_spec.rb +169 -0
- data/spec/sekken/resolver_spec.rb +38 -0
- data/spec/sekken/response_spec.rb +17 -0
- data/spec/sekken/wsdl/document_spec.rb +191 -0
- data/spec/sekken/wsdl_spec.rb +46 -0
- data/spec/sekken/xs/complex_type_spec.rb +197 -0
- data/spec/sekken/xs/element_spec.rb +82 -0
- data/spec/sekken/xs/simple_type_spec.rb +39 -0
- data/spec/sekken_spec.rb +128 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/fixture.rb +19 -0
- data/spec/support/http_mock.rb +43 -0
- metadata +344 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class Sekken
|
|
2
|
+
class WSDL
|
|
3
|
+
class Port
|
|
4
|
+
|
|
5
|
+
def initialize(port_node, soap_node)
|
|
6
|
+
@name = port_node['name']
|
|
7
|
+
@binding = port_node['binding']
|
|
8
|
+
|
|
9
|
+
@type = soap_node.namespace.href
|
|
10
|
+
@location = soap_node['location']
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :name, :binding, :type, :location
|
|
14
|
+
|
|
15
|
+
def fetch_binding(documents)
|
|
16
|
+
binding_local = @binding.split(':').last
|
|
17
|
+
|
|
18
|
+
documents.bindings.fetch(binding_local) {
|
|
19
|
+
raise "Unable to find binding #{binding_local.inspect} for port #{@name.inspect}"
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_hash
|
|
24
|
+
{ name => { type: type, location: location } }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'sekken/wsdl/port_type_operation'
|
|
2
|
+
|
|
3
|
+
class Sekken
|
|
4
|
+
class WSDL
|
|
5
|
+
class PortType
|
|
6
|
+
|
|
7
|
+
def initialize(port_type_node)
|
|
8
|
+
@port_type_node = port_type_node
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
@port_type_node['name']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def operations
|
|
16
|
+
@operations ||= operations!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def operations!
|
|
22
|
+
operations = {}
|
|
23
|
+
|
|
24
|
+
@port_type_node.element_children.each do |operation_node|
|
|
25
|
+
next unless operation_node.name == 'operation'
|
|
26
|
+
|
|
27
|
+
operation_name = operation_node['name']
|
|
28
|
+
operation = PortTypeOperation.new(operation_node)
|
|
29
|
+
|
|
30
|
+
operations[operation_name] = operation
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
operations
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class Sekken
|
|
2
|
+
class WSDL
|
|
3
|
+
class PortTypeOperation
|
|
4
|
+
|
|
5
|
+
def initialize(operation_node)
|
|
6
|
+
@operation_node = operation_node
|
|
7
|
+
|
|
8
|
+
@name = operation_node['name']
|
|
9
|
+
@input_node = find_node('input')
|
|
10
|
+
@output_node = find_node('output')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :name
|
|
14
|
+
|
|
15
|
+
def input
|
|
16
|
+
return @input if defined? @input
|
|
17
|
+
@input = parse_node(@input_node)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def output
|
|
21
|
+
return @output if defined? @output
|
|
22
|
+
@output = parse_node(@output_node)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def find_node(node_name)
|
|
28
|
+
@operation_node.element_children.find { |node| node.name == node_name }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parse_node(node)
|
|
32
|
+
input = {}
|
|
33
|
+
|
|
34
|
+
input[:name] = node['name']
|
|
35
|
+
input[:message] = node['message']
|
|
36
|
+
|
|
37
|
+
input
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'sekken/wsdl/port'
|
|
2
|
+
|
|
3
|
+
class Sekken
|
|
4
|
+
class WSDL
|
|
5
|
+
class Service
|
|
6
|
+
|
|
7
|
+
def initialize(service_node)
|
|
8
|
+
@service_node = service_node
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
@service_node['name']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def ports
|
|
16
|
+
@ports ||= ports!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_hash
|
|
20
|
+
port_hash = ports.values.inject({}) { |memo, port| memo.merge port.to_hash }
|
|
21
|
+
{ name => { ports: port_hash } }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def ports!
|
|
27
|
+
ports = {}
|
|
28
|
+
|
|
29
|
+
@service_node.element_children.each do |port_node|
|
|
30
|
+
next unless port_node.name == 'port'
|
|
31
|
+
|
|
32
|
+
soap_node = port_node.element_children.find { |node|
|
|
33
|
+
namespace = node.namespace.href
|
|
34
|
+
|
|
35
|
+
soap_1_1 = namespace == Sekken::NS_SOAP_1_1
|
|
36
|
+
soap_1_2 = namespace == Sekken::NS_SOAP_1_2
|
|
37
|
+
address = node.name == 'address'
|
|
38
|
+
|
|
39
|
+
(soap_1_1 || soap_1_2) && address
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
next unless soap_node
|
|
43
|
+
|
|
44
|
+
port_name = port_node['name']
|
|
45
|
+
port = Port.new(port_node, soap_node)
|
|
46
|
+
|
|
47
|
+
ports[port_name] = port
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
ports
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
class Sekken
|
|
2
|
+
class XML
|
|
3
|
+
class Element
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@children = []
|
|
7
|
+
@attributes = {}
|
|
8
|
+
@recursive = false
|
|
9
|
+
@singular = true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_accessor :parent, :name, :namespace, :form
|
|
13
|
+
|
|
14
|
+
# Public: Whether this element is a simple type.
|
|
15
|
+
def simple_type?
|
|
16
|
+
!!base_type
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Public: Whether this element is a complex type.
|
|
20
|
+
def complex_type?
|
|
21
|
+
!simple_type?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Public: The base name for a simple type element.
|
|
25
|
+
attr_accessor :base_type
|
|
26
|
+
|
|
27
|
+
# Public: Accessor for whether this is a single element.
|
|
28
|
+
attr_accessor :singular
|
|
29
|
+
alias_method :singular?, :singular
|
|
30
|
+
|
|
31
|
+
# Public: Whether or not this element's type is defined recursively,
|
|
32
|
+
# meaning one of this element's parents is of the same type as this element.
|
|
33
|
+
def recursive?
|
|
34
|
+
!!recursive_type
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Public: The name of the recursive type definition if any.
|
|
38
|
+
attr_accessor :recursive_type
|
|
39
|
+
|
|
40
|
+
# Private: The complex type id for this element to track recursive type definitions.
|
|
41
|
+
attr_accessor :complex_type_id
|
|
42
|
+
|
|
43
|
+
# Public: The child elements.
|
|
44
|
+
attr_accessor :children
|
|
45
|
+
|
|
46
|
+
# Public: The attributes.
|
|
47
|
+
attr_accessor :attributes
|
|
48
|
+
|
|
49
|
+
# Public: Returns this element and its children as an Array of Hashes for inspection.
|
|
50
|
+
def to_a(memo = [], stack = [])
|
|
51
|
+
new_stack = stack + [name]
|
|
52
|
+
data = { namespace: namespace, form: form, singular: singular? }
|
|
53
|
+
|
|
54
|
+
unless attributes.empty?
|
|
55
|
+
data[:attributes] = attributes.each_with_object({}) do |attribute, memo|
|
|
56
|
+
memo[attribute.name] = { optional: attribute.optional? }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if recursive?
|
|
61
|
+
data[:recursive_type] = recursive_type
|
|
62
|
+
memo << [new_stack, data]
|
|
63
|
+
|
|
64
|
+
elsif simple_type?
|
|
65
|
+
data[:type] = base_type
|
|
66
|
+
memo << [new_stack, data]
|
|
67
|
+
|
|
68
|
+
elsif complex_type?
|
|
69
|
+
memo << [new_stack, data]
|
|
70
|
+
|
|
71
|
+
children.each do |child|
|
|
72
|
+
child.to_a(memo, new_stack)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
memo
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
require 'sekken/xml/element'
|
|
2
|
+
require 'sekken/xml/attribute'
|
|
3
|
+
|
|
4
|
+
class Sekken
|
|
5
|
+
class XML
|
|
6
|
+
class ElementBuilder
|
|
7
|
+
|
|
8
|
+
def initialize(schemas)
|
|
9
|
+
@logger = Logging.logger[self]
|
|
10
|
+
@schemas = schemas
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def build(parts)
|
|
14
|
+
parts.map { |part|
|
|
15
|
+
case
|
|
16
|
+
when part[:type] then build_type_element(part)
|
|
17
|
+
when part[:element] then build_element(part)
|
|
18
|
+
end
|
|
19
|
+
}.compact
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
# Private: Expects a part with a @type attribute, resolves the type
|
|
25
|
+
# and returns an Element with that type.
|
|
26
|
+
def build_type_element(part)
|
|
27
|
+
type = find_type part[:type], part[:namespaces]
|
|
28
|
+
|
|
29
|
+
element = Element.new
|
|
30
|
+
element.name = part[:name]
|
|
31
|
+
element.form = 'unqualified'
|
|
32
|
+
|
|
33
|
+
handle_type(element, type)
|
|
34
|
+
element
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Private: Expects a part with an @element attribute, resolves the element
|
|
38
|
+
# and its type and returns an Element with that type.
|
|
39
|
+
def build_element(part)
|
|
40
|
+
local, namespace = expand_qname(part[:element], part[:namespaces])
|
|
41
|
+
schema = @schemas.find_by_namespace(namespace)
|
|
42
|
+
raise "Unable to find schema for #{namespace.inspect}" unless schema
|
|
43
|
+
|
|
44
|
+
xs_element = schema.elements.fetch(local)
|
|
45
|
+
type = find_type_for_element(xs_element)
|
|
46
|
+
|
|
47
|
+
element = Element.new
|
|
48
|
+
element.name = xs_element.name
|
|
49
|
+
element.form = 'qualified'
|
|
50
|
+
element.namespace = namespace
|
|
51
|
+
|
|
52
|
+
handle_type(element, type)
|
|
53
|
+
element
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def handle_type(element, type)
|
|
57
|
+
case type
|
|
58
|
+
|
|
59
|
+
when XS::ComplexType
|
|
60
|
+
element.complex_type_id = type.id
|
|
61
|
+
element.children = child_elements(element, type)
|
|
62
|
+
element.attributes = element_attributes(type)
|
|
63
|
+
|
|
64
|
+
when XS::SimpleType
|
|
65
|
+
element.base_type = type.base
|
|
66
|
+
|
|
67
|
+
when String
|
|
68
|
+
element.base_type = type
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def handle_simple_type(attribute, type)
|
|
74
|
+
case type
|
|
75
|
+
when XS::SimpleType then attribute.base_type = type.base
|
|
76
|
+
when String then attribute.base_type = type
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def element_attributes(type)
|
|
81
|
+
type.attributes.map { |attribute|
|
|
82
|
+
attr = Attribute.new
|
|
83
|
+
|
|
84
|
+
if attribute.ref
|
|
85
|
+
local, namespace = expand_qname(attribute.ref, attribute.namespaces)
|
|
86
|
+
schema = find_schema(namespace)
|
|
87
|
+
|
|
88
|
+
if schema
|
|
89
|
+
attribute = schema.attributes[local]
|
|
90
|
+
else
|
|
91
|
+
@logger.debug("Unable to find schema for attribute@ref #{attribute.ref.inspect}")
|
|
92
|
+
next
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
type = find_type_for_attribute(attribute)
|
|
97
|
+
handle_simple_type(attr, type)
|
|
98
|
+
|
|
99
|
+
attr.name = attribute.name
|
|
100
|
+
attr.use = attribute.use
|
|
101
|
+
|
|
102
|
+
attr
|
|
103
|
+
}.compact
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def child_elements(parent, type)
|
|
107
|
+
type.elements.map { |child_element|
|
|
108
|
+
el = Element.new
|
|
109
|
+
el.parent = parent
|
|
110
|
+
|
|
111
|
+
max_occurs = child_element['maxOccurs'].to_s
|
|
112
|
+
el.singular = max_occurs.empty? || max_occurs == '1'
|
|
113
|
+
|
|
114
|
+
if child_element.ref
|
|
115
|
+
child_element = find_element(child_element.ref, child_element.namespaces)
|
|
116
|
+
el.form = 'qualified'
|
|
117
|
+
else
|
|
118
|
+
el.form = child_element.form
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
el.name = child_element.name
|
|
122
|
+
el.namespace = child_element.namespace
|
|
123
|
+
|
|
124
|
+
# prevent recursion
|
|
125
|
+
if recursive_child_definition? parent, child_element
|
|
126
|
+
el.recursive_type = child_element.type
|
|
127
|
+
else
|
|
128
|
+
type = find_type_for_element(child_element)
|
|
129
|
+
handle_type(el, type)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
el
|
|
133
|
+
}
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Private: Accepts an Element and figures out if its type is already defined in this
|
|
137
|
+
# elements (self) ancestors. Used to prevent recursive child element definitions.
|
|
138
|
+
def recursive_child_definition?(parent, element)
|
|
139
|
+
return false unless element.type
|
|
140
|
+
|
|
141
|
+
local, namespace = expand_qname(element.type, element.namespaces)
|
|
142
|
+
id = [namespace, local].join(':')
|
|
143
|
+
|
|
144
|
+
current_parent = parent
|
|
145
|
+
|
|
146
|
+
while current_parent
|
|
147
|
+
return true if current_parent.complex_type_id == id
|
|
148
|
+
current_parent = current_parent.parent
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
false
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def find_type_for_element(element)
|
|
155
|
+
if element.type
|
|
156
|
+
find_type(element.type, element.namespaces)
|
|
157
|
+
else
|
|
158
|
+
element.inline_type
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
alias_method :find_type_for_attribute, :find_type_for_element
|
|
163
|
+
|
|
164
|
+
def find_type(qname, namespaces)
|
|
165
|
+
local, namespace = expand_qname(qname, namespaces)
|
|
166
|
+
|
|
167
|
+
# assume built-in or unknown type for unqualified type qnames for now.
|
|
168
|
+
# we could fallback to the element's default namespace. needs tests.
|
|
169
|
+
return qname unless namespace
|
|
170
|
+
|
|
171
|
+
schema = find_schema(namespace)
|
|
172
|
+
|
|
173
|
+
# custom type
|
|
174
|
+
if schema
|
|
175
|
+
|
|
176
|
+
# complex type
|
|
177
|
+
if complex_type = schema.complex_types[local]
|
|
178
|
+
complex_type
|
|
179
|
+
|
|
180
|
+
# simple type
|
|
181
|
+
elsif simple_type = schema.simple_types[local]
|
|
182
|
+
simple_type
|
|
183
|
+
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# built-in or unknown type
|
|
187
|
+
else
|
|
188
|
+
qname
|
|
189
|
+
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def find_element(qname, namespaces)
|
|
194
|
+
local, namespace = expand_qname(qname, namespaces)
|
|
195
|
+
@schemas.element(namespace, local)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def find_attribute(qname, namespaces)
|
|
199
|
+
local, namespace = expand_qname(qname, namespaces)
|
|
200
|
+
@schemas.attribute(namespace, local)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def find_schema(namespace)
|
|
204
|
+
@schemas.find_by_namespace(namespace)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def split_qname(qname)
|
|
208
|
+
qname.split(':').reverse
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def expand_qname(qname, namespaces)
|
|
212
|
+
local, nsid = split_qname(qname)
|
|
213
|
+
namespace = namespaces["xmlns:#{nsid}"]
|
|
214
|
+
|
|
215
|
+
[local, namespace]
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|