lolsoap 0.8.3 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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: