lolsoap 0.8.3 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a60c39b2f4f03c4308d6f8c9dbcfa2b33c67eba3
4
- data.tar.gz: e46ab60e8fcd3048c379c08544329bffe051f58d
2
+ SHA256:
3
+ metadata.gz: 7adc22f6b91f820d8f182293ede6bbfbde631dacd43e2cc3a0519f20d446ddc2
4
+ data.tar.gz: 2af9641360a9091eff4224690aa48fdef48c3b0a5a36da43e8bc5e18e91615f2
5
5
  SHA512:
6
- metadata.gz: 099b596571f4f0d34bf41768e2819bcea1f5411457c6deb28d28090c6b480b571515bb87e8333cb411e47041fd2eaa7feacf73c12ba6ab43f446feda05b77965
7
- data.tar.gz: 4ecf0b3962d57e6bf8e768e706414716df634633fc7f3ebbc3da1c0ea6df96eb86764ac1dba16c7acd891b2fac71e50d2a001b64d4920732c1882feac75d0b9e
6
+ metadata.gz: 66f69ccca6a132a97d91d2402ec25f57e47d93963fe13dfb9c82a7b5423b0add88d914a6ef1849bc5186b75358e79d5f407514485cc7adf62c8f3ca0f9812abc
7
+ data.tar.gz: 1b181fb487fab405e6fe29c9cedc2a3d39be008963531689a99dee50648efeebd1c1958bd7d80af4cd09326a72363e2bb0c3cfb1c459c63c338d7e9daa8826dc
data/.gitignore CHANGED
@@ -19,6 +19,8 @@ pkg
19
19
 
20
20
  Gemfile.lock
21
21
 
22
+ Dockerfile
23
+
22
24
  # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
23
25
  #
24
26
  # * Create a file at ~/.gitignore
data/README.md CHANGED
@@ -120,6 +120,18 @@ Development sponsored by [Loco2](http://loco2.com/).
120
120
 
121
121
  ## Changelog ##
122
122
 
123
+ ### 0.11 ###
124
+
125
+ * Use `frozen_string_literal` to improve speed/memory usage
126
+
127
+ ### 0.10 ###
128
+
129
+ * Added support for using WSDL with abstract types in operation definitions
130
+
131
+ ### 0.9 ###
132
+
133
+ * Support unqualified form for elements in a schema
134
+
123
135
  ### 0.8 ###
124
136
 
125
137
  * Use namespaces when looking up definitions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'lolsoap/wsdl'
2
4
 
3
5
  module LolSoap
@@ -68,7 +70,21 @@ module LolSoap
68
70
  sub_node = @node.document.create_element(name.to_s, *args)
69
71
  sub_node.namespace = @node.namespace_scopes.find { |n| n.prefix == prefix }
70
72
 
71
- @node << sub_node
73
+ # Nokogiri doesn't currently allow to add a child element without a
74
+ # namespace to a parent with a namespace: the child inherits the parent's
75
+ # namespace. It's a known issue:
76
+ # https://github.com/sparklemotion/nokogiri/issues/1469 Until it's fixed,
77
+ # we'll use this workaround: store the parent's namespace, set it to nil
78
+ # temporarily, add the child and re-add the original namespace to the
79
+ # parent.
80
+ if sub_node.namespace.nil?
81
+ parent_namespace = @node.namespace
82
+ @node.namespace = nil
83
+ @node << sub_node
84
+ @node.namespace = parent_namespace
85
+ else
86
+ @node << sub_node
87
+ end
72
88
 
73
89
  builder = __class__.new(sub_node, sub_type)
74
90
  yield builder if block_given?
@@ -1,3 +1,3 @@
1
1
  module LolSoap
2
- VERSION = "0.8.3"
2
+ VERSION = "0.11.0"
3
3
  end
data/lib/lolsoap/wsdl.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'lolsoap/wsdl_parser'
2
4
 
3
5
  module LolSoap
@@ -13,8 +15,8 @@ module LolSoap
13
15
  require 'lolsoap/wsdl/operation_io_part'
14
16
 
15
17
  # Create a new instance by parsing a raw string of XML
16
- def self.parse(raw)
17
- new(WSDLParser.parse(raw))
18
+ def self.parse(raw, options={})
19
+ new(WSDLParser.parse(raw), options)
18
20
  end
19
21
 
20
22
  # The SOAP endpoint URL
@@ -29,13 +31,15 @@ module LolSoap
29
31
  # The version of SOAP detected.
30
32
  attr_reader :soap_version
31
33
 
32
- def initialize(parser)
33
- @prefixes = generate_prefixes(parser)
34
- @namespaces = prefixes.invert
35
- @types = load_types(parser)
36
- @operations = load_operations(parser)
37
- @endpoint = parser.endpoint
34
+ def initialize(parser, options={})
35
+ @prefixes = generate_prefixes(parser)
36
+ @namespaces = prefixes.invert
37
+ @abstract_types = load_types(parser.abstract_types)
38
+ @types = load_types(parser.types)
39
+ @operations = load_operations(parser)
40
+ @endpoint = parser.endpoint
38
41
  @soap_version = parser.soap_version
42
+ @allow_abstract_types = options[:allow_abstract_types]
39
43
  end
40
44
 
41
45
  # Hash of types declared by the service
@@ -43,9 +47,23 @@ module LolSoap
43
47
  Hash[@types.values.map { |t| [t.name, t] }]
44
48
  end
45
49
 
50
+ # Hash of abstract types declared by the service
51
+ def abstract_types
52
+ Hash[@abstract_types.values.map { |t| [t.name, t] }]
53
+ end
54
+
46
55
  # Get a single type, or a NullType if the type doesn't exist
47
56
  def type(namespace, name)
48
- @types.fetch([namespace, name]) { NullType.new }
57
+ if @allow_abstract_types
58
+ @types.fetch([namespace, name]) { abstract_type(namespace, name) }
59
+ else
60
+ @types.fetch([namespace, name]) { NullType.new }
61
+ end
62
+ end
63
+
64
+ # Get a single abstract type, or a NullType if the type doesn't exist
65
+ def abstract_type(namespace, name)
66
+ @abstract_types.fetch([namespace, name]) { NullType.new }
49
67
  end
50
68
 
51
69
  # Hash of operations that are supported by the SOAP service
@@ -73,9 +91,9 @@ module LolSoap
73
91
  private
74
92
 
75
93
  # @private
76
- def load_types(parser)
94
+ def load_types(types)
77
95
  Hash[
78
- parser.types.map do |id, type|
96
+ types.map do |id, type|
79
97
  [id, build_type(type)]
80
98
  end
81
99
  ]
@@ -135,7 +153,7 @@ module LolSoap
135
153
  Element.new(
136
154
  self,
137
155
  params[:name],
138
- prefix(params[:namespace]),
156
+ params[:namespace] && prefix(params[:namespace]),
139
157
  type_reference(params[:type]),
140
158
  params[:singular]
141
159
  )
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
  require 'cgi'
3
5
 
@@ -6,25 +8,55 @@ module LolSoap
6
8
  class WSDLParser
7
9
  class ParseError < StandardError; end
8
10
 
11
+ class Schema < Struct.new(:target_namespace, :element_form_default)
12
+ UNQUALIFIED = 'unqualified'
13
+
14
+ def self.from_node(node)
15
+ new(
16
+ node.attr('targetNamespace').to_s,
17
+ node.attr('elementFormDefault')
18
+ )
19
+ end
20
+
21
+ def default_form
22
+ element_form_default || UNQUALIFIED
23
+ end
24
+ end
25
+
9
26
  class Node
10
- attr_reader :parser, :node, :target_namespace, :name, :namespace
27
+ attr_reader :parser, :node, :schema, :name, :namespace
11
28
 
12
- def initialize(parser, node, target_namespace)
13
- @parser = parser
14
- @node = node
15
- @target_namespace = target_namespace
16
- @namespace, @name = parser.namespace_and_name(node, node.attr('name').to_s, target_namespace)
29
+ def initialize(parser, schema, node)
30
+ @parser = parser
31
+ @node = node
32
+ @schema = schema
17
33
  end
18
34
 
19
35
  def id
20
36
  [namespace, name]
21
37
  end
38
+
39
+ def target_namespace
40
+ schema.target_namespace
41
+ end
22
42
  end
23
43
 
24
44
  class Element < Node
45
+ QUALIFIED = 'qualified'
46
+
47
+ attr_reader :form
48
+
49
+ def initialize(*params)
50
+ super(*params)
51
+
52
+ @form = node.attr('form') || schema.default_form
53
+
54
+ @namespace, @name = parser.namespace_and_name(node, node.attr('name').to_s, default_namespace)
55
+ end
56
+
25
57
  def type
26
58
  if complex_type = node.at_xpath('xs:complexType', parser.ns)
27
- type = Type.new(parser, complex_type, target_namespace)
59
+ type = Type.new(parser, schema, complex_type)
28
60
  {
29
61
  :elements => type.elements,
30
62
  :namespace => type.namespace,
@@ -39,6 +71,14 @@ module LolSoap
39
71
  max_occurs.empty? || max_occurs == '1'
40
72
  end
41
73
 
74
+ def qualified?
75
+ form == QUALIFIED
76
+ end
77
+
78
+ def default_namespace
79
+ target_namespace
80
+ end
81
+
42
82
  private
43
83
 
44
84
  def max_occurs
@@ -72,6 +112,12 @@ module LolSoap
72
112
  end
73
113
 
74
114
  class Type < Node
115
+ def initialize(*params)
116
+ super(*params)
117
+
118
+ @namespace, @name = parser.namespace_and_name(node, node.attr('name').to_s, target_namespace)
119
+ end
120
+
75
121
  def elements
76
122
  parent_elements.merge(own_elements)
77
123
  end
@@ -108,7 +154,8 @@ module LolSoap
108
154
 
109
155
  def element_nodes
110
156
  node.xpath('*/xs:element | */*/xs:element | xs:complexContent/xs:extension/*/xs:element | xs:complexContent/xs:extension/*/*/xs:element', parser.ns).map { |el|
111
- element = Element.new(parser, el, target_namespace)
157
+ element = TypeElement.new(parser, schema, el)
158
+
112
159
  if reference = el.attribute('ref')
113
160
  ReferencedElement.new(element, parser.element(*parser.namespace_and_name(el, reference.to_s)))
114
161
  else
@@ -140,6 +187,12 @@ module LolSoap
140
187
  end
141
188
  end
142
189
 
190
+ class TypeElement < Element
191
+ def default_namespace
192
+ target_namespace if qualified?
193
+ end
194
+ end
195
+
143
196
  class AttributeGroup < Node
144
197
  def attributes
145
198
  own_attributes + referenced_attributes
@@ -254,14 +307,20 @@ module LolSoap
254
307
  def types
255
308
  @types ||= begin
256
309
  types = {}
257
- each_node('xs:complexType[not(@abstract="true")]') do |node, target_ns|
258
- type = Type.new(self, node, target_ns)
259
- types[type.id] = {
260
- :name => type.name,
261
- :namespace => type.namespace,
262
- :elements => type.elements,
263
- :attributes => type.attributes
264
- }
310
+ each_node('xs:complexType[not(@abstract="true")]') do |node, schema|
311
+ type = Type.new(self, schema, node)
312
+ types[type.id] = type_record(type)
313
+ end
314
+ types
315
+ end
316
+ end
317
+
318
+ def abstract_types
319
+ @abstract_types ||= begin
320
+ types = {}
321
+ each_node('xs:complexType[@abstract="true"]') do |node, schema|
322
+ type = Type.new(self, schema, node)
323
+ types[type.id] = type_record(type)
265
324
  end
266
325
  types
267
326
  end
@@ -274,8 +333,8 @@ module LolSoap
274
333
  def elements
275
334
  @elements ||= begin
276
335
  elements = {}
277
- each_node('xs:element') do |node, target_ns|
278
- element = Element.new(self, node, target_ns)
336
+ each_node('xs:element') do |node, schema|
337
+ element = Element.new(self, schema, node)
279
338
  elements[element.id] = {
280
339
  :name => element.name,
281
340
  :namespace => element.namespace,
@@ -378,11 +437,10 @@ module LolSoap
378
437
  end
379
438
 
380
439
  def each_node(xpath)
381
- schemas.each do |schema|
382
- target_namespace = schema.attr('targetNamespace').to_s
383
-
384
- schema.xpath(xpath, ns).each do |node|
385
- yield node, target_namespace
440
+ schemas.each do |schema_node|
441
+ schema = Schema.from_node(schema_node)
442
+ schema_node.xpath(xpath, ns).each do |node|
443
+ yield node, schema
386
444
  end
387
445
  end
388
446
  end
@@ -392,9 +450,19 @@ module LolSoap
392
450
  target = schemas if target.size == 0
393
451
 
394
452
  if node = target.at_xpath("xs:#{selector}[@name='#{name.split(':').last}']", ns)
395
- target_namespace = node.at_xpath('parent::xs:schema/@targetNamespace', ns).to_s
396
- node_class.new(self, node, target_namespace)
453
+ schema = Schema.from_node(node.at_xpath('parent::xs:schema', ns))
454
+ node_class.new(self, schema, node)
397
455
  end
398
456
  end
457
+
458
+ private
459
+ def type_record(type)
460
+ {
461
+ :name => type.name,
462
+ :namespace => type.namespace,
463
+ :elements => type.elements,
464
+ :attributes => type.attributes
465
+ }
466
+ end
399
467
  end
400
468
  end
data/lolsoap.gemspec CHANGED
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_dependency 'nokogiri', '~> 1.5'
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.7"
23
- spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "bundler", "~> 2.0"
23
+ spec.add_development_dependency "rake", "~> 12.3"
24
24
  spec.add_development_dependency "minitest", "~> 2.10.0"
25
25
  spec.add_development_dependency "yard"
26
26
  end
@@ -12,7 +12,8 @@
12
12
  <types>
13
13
  <schema targetNamespace="http://example.com/stockquote.xsd"
14
14
  xmlns:xsd3="http://example.com/stockquote.xsd"
15
- xmlns="http://www.w3.org/2001/XMLSchema">
15
+ xmlns="http://www.w3.org/2001/XMLSchema"
16
+ elementFormDefault="qualified">
16
17
  <attributeGroup name="BaseRequestAttributes">
17
18
  <attribute name="signature" type="xs:string"/>
18
19
  </attributeGroup>
@@ -28,7 +28,7 @@ module LolSoap
28
28
  el.wont_equal nil
29
29
  el.text.to_s.must_equal 'LOCO2'
30
30
 
31
- el = doc.at_xpath('//ns0:tradePriceRequest/ns0:specialTickerSymbol/ns1:name', doc.namespaces)
31
+ el = doc.at_xpath('//ns0:tradePriceRequest/ns0:specialTickerSymbol/name', doc.namespaces)
32
32
  el.wont_equal nil
33
33
  el.text.to_s.must_equal 'LOCOLOCOLOCO'
34
34
 
@@ -28,6 +28,11 @@ module LolSoap
28
28
  o.input.body.content.name.must_equal 'historicalPriceRequest'
29
29
  end
30
30
 
31
+ subject.abstract_types.length.must_equal 1
32
+ subject.abstract_types.fetch('BaseRequest').tap do |t|
33
+ t.prefix.must_equal 'ns0'
34
+ end
35
+
31
36
  subject.types.length.must_equal 4
32
37
  subject.types.fetch('TradePriceRequest').tap do |t|
33
38
  t.prefix.must_equal 'ns0'
@@ -35,6 +35,7 @@ module LolSoap
35
35
 
36
36
  doc.expect(:create_element, sub_node, args)
37
37
  sub_node.expect(:namespace=, nil, [namespace])
38
+ sub_node.expect(:namespace, namespace)
38
39
  node.children.expect(:<<, nil, [sub_node])
39
40
 
40
41
  yield sub_node
@@ -59,8 +59,16 @@ module LolSoap
59
59
  :attributes => ['id'],
60
60
  :namespace => namespace
61
61
  }
62
- },
63
- :elements => {
62
+ },
63
+ :abstract_types => {
64
+ [namespace, 'BaseBrush'] => {
65
+ :name => 'BaseBrush',
66
+ :elements => {},
67
+ :attributes => ['id'],
68
+ :namespace => namespace
69
+ },
70
+ },
71
+ :elements => {
64
72
  [namespace, 'brush'] => {
65
73
  :name => 'brush',
66
74
  :namespace => namespace,
@@ -172,6 +180,16 @@ module LolSoap
172
180
  end
173
181
  end
174
182
 
183
+ describe '#abstract_types' do
184
+ it 'returns a hash of abstract types' do
185
+ subject.abstract_types.length.must_equal 1
186
+
187
+ subject.abstract_types['BaseBrush'].tap do |t|
188
+ t.attributes.must_equal ['id']
189
+ end
190
+ end
191
+ end
192
+
175
193
  describe '#type' do
176
194
  it 'returns a single type' do
177
195
  subject.type(namespace, 'Brush').must_equal subject.types.fetch('Brush')
@@ -180,6 +198,28 @@ module LolSoap
180
198
  it 'returns a null object if a type is missing' do
181
199
  subject.type(namespace, 'FooBar').must_equal WSDL::NullType.new
182
200
  end
201
+
202
+ it 'returns a null object for abstract types' do
203
+ subject.type(namespace, 'BaseBrush').must_equal WSDL::NullType.new
204
+ end
205
+
206
+ describe 'when abstract types are allowed' do
207
+ subject { WSDL.new(parser, :allow_abstract_types => true) }
208
+
209
+ it 'returns an abstract type' do
210
+ subject.type(namespace, 'BaseBrush').must_equal subject.abstract_types.fetch('BaseBrush')
211
+ end
212
+ end
213
+ end
214
+
215
+ describe '#abstract_type' do
216
+ it 'returns a single type' do
217
+ subject.abstract_type(namespace, 'BaseBrush').must_equal subject.abstract_types.fetch('BaseBrush')
218
+ end
219
+
220
+ it 'returns a null object if a type is missing' do
221
+ subject.abstract_type(namespace, 'FooBar').must_equal WSDL::NullType.new
222
+ end
183
223
  end
184
224
  end
185
225
  end
@@ -96,7 +96,7 @@ module LolSoap
96
96
  :elements => {
97
97
  'name' => {
98
98
  :name => 'name',
99
- :namespace => namespace2,
99
+ :namespace => nil,
100
100
  :type => [xs, "string"],
101
101
  :singular => true
102
102
  }
@@ -107,6 +107,26 @@ module LolSoap
107
107
  end
108
108
  end
109
109
 
110
+ describe "#abstract_types" do
111
+ it 'returns the abstract types, with attributes and namespace' do
112
+ subject.abstract_types.must_equal({
113
+ [namespace, "BaseRequest"] => {
114
+ :name => "BaseRequest",
115
+ :namespace => "http://example.com/stockquote.xsd",
116
+ :elements => {
117
+ "accountId" => {
118
+ :name => "accountId",
119
+ :namespace => "http://example.com/stockquote.xsd",
120
+ :type => [xs, "string"],
121
+ :singular=>true
122
+ }
123
+ },
124
+ :attributes=>["signature"]
125
+ },
126
+ })
127
+ end
128
+ end
129
+
110
130
  describe '#elements' do
111
131
  it 'returns the elements with inline types' do
112
132
  subject.elements.must_equal({
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lolsoap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Leighton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-13 00:00:00.000000000 Z
11
+ date: 2022-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -30,28 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.7'
33
+ version: '2.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.7'
40
+ version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '12.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '12.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -156,8 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
156
  - !ruby/object:Gem::Version
157
157
  version: '0'
158
158
  requirements: []
159
- rubyforge_project:
160
- rubygems_version: 2.5.1
159
+ rubygems_version: 3.1.6
161
160
  signing_key:
162
161
  specification_version: 4
163
162
  summary: A library for dealing with SOAP requests and responses.
@@ -183,4 +182,3 @@ test_files:
183
182
  - test/unit/test_wsdl_parser.rb
184
183
  - test/unit/wsdl/test_element.rb
185
184
  - test/unit/wsdl/test_type.rb
186
- has_rdoc: