xsd-populator 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.
@@ -0,0 +1,13 @@
1
+ # loads and runs all tests for the rxsd project
2
+ #
3
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
4
+ # Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
5
+
6
+ require 'rspec'
7
+
8
+ CURRENT_DIR=File.dirname(__FILE__)
9
+ $: << File.expand_path(CURRENT_DIR + "/../lib")
10
+
11
+ require 'xsd_populator'
12
+ require 'byebug'
13
+ require 'nokogiri'
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'xsd_explanation_provider'
3
+
4
+ describe XsdExplanationProvider do
5
+ let(:logger){
6
+ logger = Logger.new(STDOUT)
7
+ logger.level = Logger::WARN
8
+ logger
9
+ }
10
+
11
+ let(:populator){
12
+ XsdPopulator.new(:xsd_file => File.expand_path(File.join(File.dirname(__FILE__), 'examples', 'ddex-ern-v36.xsd')), :logger => logger)
13
+ }
14
+
15
+ let(:provider){
16
+ XsdExplanationProvider.new(:data => {:xsd_reader => populator.xsd_reader}, :logger => logger)
17
+ }
18
+
19
+ it "requires an xsd reader" do
20
+ msg = expect{ XsdExplanationProvider.new(:logger => logger).take(:something) }.to raise_error(RuntimeError, 'XsdExplanationProvider needs an xsd reader')
21
+ end
22
+
23
+ it "gives itself for complex elements" do
24
+ expect(provider.take('NewReleaseMessage')).to eq provider
25
+ expect(provider.take(['NewReleaseMessage', 'MessageHeader'])).to eq provider
26
+ end
27
+
28
+ it "gives the element type for simple elements" do
29
+ expect(provider.take(['NewReleaseMessage', 'MessageHeader', 'MessageId'])).to eq 'xs:string'
30
+ end
31
+
32
+ it "gives the attribute type for attributes" do
33
+ expect(provider.take(['NewReleaseMessage', 'MessageHeader', '@LanguageAndScriptCode'])).to eq 'xs:string'
34
+ end
35
+
36
+ it "is the default fallback provider for XsdPopulators without a specified provider" do
37
+ expect(populator.provider.class).to eq XsdExplanationProvider
38
+ xml = populator.populate_element(['NewReleaseMessage', 'MessageHeader', 'MessageSender'])
39
+ # puts xml
40
+ doc = Nokogiri.XML(xml)
41
+ expect(doc.at('/MessageSender/PartyId').text).to eq 'xs:string'
42
+ expect(doc.at('/MessageSender').attributes['LanguageAndScriptCode'].value).to eq 'xs:string'
43
+ end
44
+ end # describe XsdExplanationProvider
@@ -0,0 +1,211 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe XsdPopulator do
4
+ let(:xsd_reader){
5
+ XsdReader::XML.new(:xsd_file => File.expand_path(File.join(File.dirname(__FILE__), 'examples', 'ddex-ern-v36.xsd')))
6
+ }
7
+
8
+ let(:logger){
9
+ logger = Logger.new(STDOUT)
10
+ logger.level = Logger::WARN
11
+ logger
12
+ }
13
+
14
+ let(:populator){
15
+ XsdPopulator.new(:reader => xsd_reader, :logger => logger)
16
+ }
17
+
18
+ describe "#configure" do
19
+ it "lets you change the configuration options at runtime" do
20
+ expect(populator.xsd_reader).to eq xsd_reader
21
+ expect(populator.logger).to eq logger
22
+ expect(populator.options[:relative_provider]).to eq nil
23
+ # save current configuration
24
+ old_options = populator.options.merge(:relative_provider => nil)
25
+ # reconfigure with invalid data
26
+ populator.configure({:reader => :dummy, :logger => :lagger, :relative_provider => :absolutely})
27
+ # some assertion
28
+ expect(populator.xsd_reader).to eq :dummy
29
+ expect(populator.logger).to eq :lagger
30
+ expect(populator.options[:relative_provider]).to eq :absolutely
31
+ # restore configuration
32
+ populator.configure old_options
33
+ # verify
34
+ expect(populator.xsd_reader).to eq xsd_reader
35
+ expect(populator.logger).to eq logger
36
+ expect(populator.options[:relative_provider]).to eq nil
37
+ end
38
+ end
39
+
40
+ describe "#uncache" do
41
+ it "lets you clear the populated_xml cache" do
42
+ # first create a dummy cache, because producing the full XML will take too much time
43
+ populator.instance_variable_set('@populated_xml', :dummy_value)
44
+ # verify the above instance variable is used to cache populaed_xml
45
+ expect(populator.populated_xml).to eq :dummy_value
46
+ # do it!
47
+ populator.uncache
48
+ # verify the cache instance var is clear
49
+ expect(populator.instance_variable_get('@populated_xml')).to eq nil
50
+ end
51
+ end
52
+
53
+ # # TAKES LONG
54
+ # it "should generate xml without data and include comments" do
55
+ # expect(doc.root_node.name).to eq 'NewReleaseMessage'
56
+ # end
57
+
58
+ # # TAKES LONG
59
+ # it "writes to file" do
60
+ # @populator.write_file(File.dirname(__FILE__) + '/examples/ddex-ern-v36.xml')
61
+ # end
62
+
63
+ # TAKES LONG
64
+ # it "it lets you specify a root-level element" do
65
+ # populator = XsdPopulator.new(:xsd_reader => @populator.xsd_reader, :element => 'CatalogListMessage')
66
+ # populator.write_file(File.dirname(__FILE__) + '/examples/ddex-ern-v36-CatalogListMessage2.xml')
67
+ # end
68
+ end
69
+
70
+ describe "XsdPopulator for partial layouts" do
71
+ let(:xsd_reader){
72
+ XsdReader::XML.new(:xsd_file => File.expand_path(File.join(File.dirname(__FILE__), 'examples', 'ddex-ern-v36.xsd')))
73
+ }
74
+
75
+ let(:logger){
76
+ logger = Logger.new(STDOUT)
77
+ logger.level = Logger::WARN
78
+ logger
79
+ }
80
+
81
+ let(:populator){
82
+ XsdPopulator.new({
83
+ :element => ['NewReleaseMessage', 'MessageHeader'],
84
+ :reader=> xsd_reader,
85
+ :logger => logger,
86
+ :strategy => :complete
87
+ })
88
+ }
89
+
90
+ it "lets you specify any specific element as root element at initialization" do
91
+ doc = Nokogiri.XML(populator.populated_xml)
92
+ expect(doc.root.name).to eq 'MessageHeader'
93
+ expect(doc.root.element_children.map(&:name)).to eq ["MessageThreadId", "MessageId", "MessageFileName", "MessageSender", "SentOnBehalfOf", "MessageRecipient", "MessageCreatedDateTime", "MessageAuditTrail", "Comment", "MessageControlType"]
94
+ expect(doc.root.at('MessageSender').at('PartyName').at('FullName').attributes['LanguageAndScriptCode'].value).to eq "xs:string"
95
+ expect(doc.root.at('MessageSender').at('PartyName').at('FullNameAsciiTranscribed').attributes).to eq({})
96
+ end
97
+
98
+ it "lets you specify any specific element to populate" do
99
+ xml = populator.populate_element([:NewReleaseMessage, :MessageHeader, :MessageSender])
100
+ doc = Nokogiri.XML(xml)
101
+ expect(doc.root.name).to eq 'MessageSender'
102
+ expect(doc.root.element_children.map(&:name)).to eq ['PartyId', 'PartyName', 'TradingName']
103
+ end
104
+
105
+ describe ':relative_provider options' do
106
+ class RelativeProviderTester
107
+ include DataProvider::Base
108
+
109
+ provides({
110
+ # for default/full stsack strategy
111
+ ['NewReleaseMessage', 'MessageHeader', 'MessageId'] => 'Full ID',
112
+ # for :relative_provider => true strategies with MessageHeader as root element
113
+ ['MessageHeader', 'MessageId'] => 'Relative Version1',
114
+ # for :relative_provider => true strategies with MessageId as root element
115
+ ['MessageId'] => 'Relative Version2'
116
+ })
117
+ end
118
+
119
+ it "by default uses the full stack for provider ids" do
120
+ populator.configure(:provider => RelativeProviderTester.new)
121
+ expect(Nokogiri.XML(populator.populated_xml).at('/MessageHeader/MessageId').text).to eq 'Full ID'
122
+ expect(Nokogiri.XML(populator.populate_element(['NewReleaseMessage', 'MessageHeader', 'MessageId'])).at('/MessageId').text).to eq 'Full ID'
123
+ end
124
+
125
+ it "uses 'relative' provider ids when the :relative_provider option is true" do
126
+ populator.configure(:provider => RelativeProviderTester.new, :relative_provider => true)
127
+ # MessageHeader is root element
128
+ expect(Nokogiri.XML(populator.populated_xml).at('/MessageHeader/MessageId').text).to eq 'Relative Version1'
129
+ # MessageId is root element
130
+ expect(Nokogiri.XML(populator.populate_element(['NewReleaseMessage', 'MessageHeader', 'MessageId'])).at('/MessageId').text).to eq 'Relative Version2'
131
+ end
132
+ end
133
+
134
+ describe XsdPopulator::ElementNotFoundException do
135
+ it 'is thrown when a specified root element cannot be found' do
136
+ expect{ populator.populate_element('InvalidNode') }.to raise_error(XsdPopulator::ElementNotFoundException)
137
+ pop = XsdPopulator.new(:xsd_reader => xsd_reader, :element => ['NewReleaseMessage', 'Foo'], :logger => logger)
138
+ expect{pop.populated_xml}.to raise_error(XsdPopulator::ElementNotFoundException)
139
+ end
140
+ end
141
+
142
+ describe :strategy do
143
+ class StrategyProvider
144
+ include DataProvider::Base
145
+
146
+ provides({
147
+ ['NewReleaseMessage', 'DealList', 'ReleaseDeal'] => 'Invalid value; ReleaseDeal is a complex node with child-nodes, it should get a DataProvider, not a string',
148
+ ['NewReleaseMessage', 'ReleaseList'] => 'Invalid again',
149
+ ['NewReleaseMessage', 'ResourceList'] => StrategyProvider.new,
150
+ ['NewReleaseMessage', 'WorkList', 'MusicalWork', 'MusicalWorkId'] => lambda{ [StrategyProvider.new] * 3 },
151
+ ['NewReleaseMessage', 'MessageHeader', 'SentOnBehalfOf', '@LanguageAndScriptCode'] => 'UK'
152
+ })
153
+ end
154
+
155
+ let(:populator){
156
+ XsdPopulator.new({
157
+ # :element => ['NewReleaseMessage', 'MessageHeader'], # We're going for 'FULL' render this time
158
+ :reader => xsd_reader,
159
+ :provider => StrategyProvider.new,
160
+ :logger => logger
161
+ })
162
+ }
163
+
164
+ it "defaults to the :smart strategy which doesn't add nodes for which no (valid) data is provided, unless there are providers available for any its offspring nodes" do
165
+ xml = populator.populated_xml
166
+ doc = Nokogiri.XML(xml)
167
+ # There's a provider available for ReleaseDeal, an offspring of DealList, and
168
+ # even though it will return invalid data, it will still cause the DealList node to be created
169
+ expect(doc.search("/NewReleaseMessage/DealList").length).to eq 1
170
+ expect(doc.search("/NewReleaseMessage/DealList/ReleaseDeal").length).to eq 0
171
+ # There is a provider for ReleaseList itself, but it returns invalid data; it will not be created
172
+ expect(doc.search("/NewReleaseMessage/ReleaseList").length).to eq 0
173
+ # There is a provider with valid data (a DataProvider object) for ResourceList, it will be created
174
+ expect(doc.search("/NewReleaseMessage/ResourceList").length).to eq 1
175
+ # There is no data provider for WorkList, but there is for one of it descendents so it's created
176
+ expect(doc.search("/NewReleaseMessage/WorkList").length).to eq 1
177
+ # for MusicalWorkId multiple data providers are provided,
178
+ # so multiple nodes will be created. All of them will be empty though...
179
+ expect(doc.search("/NewReleaseMessage/WorkList/MusicalWork/MusicalWorkId").map{|mw| mw.element_children.length}).to eq [0]*3
180
+ end
181
+
182
+ it "adds empty simple nodes when :strategy is :all_simple_elements" do
183
+ populator.configure(:strategy => :nil_to_empty)
184
+ doc = Nokogiri.XML(xml = populator.populated_xml)
185
+ expect(doc.search("/NewReleaseMessage/DealList").length).to eq 1 # jsut like
186
+ expect(doc.search("/NewReleaseMessage/DealList/ReleaseDeal").length).to eq 0
187
+ expect(doc.search("/NewReleaseMessage/ReleaseList").length).to eq 0
188
+ expect(doc.search("/NewReleaseMessage/ResourceList").length).to eq 1
189
+ expect(doc.search("/NewReleaseMessage/WorkList").length).to eq 1
190
+ expect(doc.search("/NewReleaseMessage/WorkList/MusicalWork/MusicalWorkId").map{|mw| mw.element_children.length}).to eq [4]*3
191
+ end
192
+
193
+ it "builds all the nodes it can find if the :strategy option is set to :complete" do
194
+ populator.configure(:strategy => :complete, :element => ['NewReleaseMessage', 'WorkList'])
195
+ doc = Nokogiri.XML(xml = populator.populated_xml)
196
+ expect(doc.search("/WorkList").length).to eq 1
197
+ expect(doc.search("/WorkList/MusicalWork/MusicalWorkId").map{|n| n.search("./ISWC").length}).to eq [1]*3
198
+ end
199
+
200
+ it "by default doesn't add provider-less attributes" do
201
+ xml = populator.populated_xml
202
+ doc = Nokogiri.XML(xml)
203
+ expect(doc.at("/NewReleaseMessage").attributes['MessageSchemaVersionId'].value).to eq '' # required attribute
204
+ expect(doc.at("/NewReleaseMessage").attributes['ReleaseProfileVersionId']).to eq nil
205
+ expect(doc.at("/NewReleaseMessage").attributes['LanguageAndScriptCode']).to eq nil
206
+ expect(doc.at("/NewReleaseMessage").attributes['LanguageAndScriptCode']).to eq nil
207
+ expect(doc.at("/NewReleaseMessage/MessageHeader").attributes['LanguageAndScriptCode']).to eq nil
208
+ expect(doc.at("/NewReleaseMessage/MessageHeader/SentOnBehalfOf").attributes['LanguageAndScriptCode'].value).to eq 'UK'
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,24 @@
1
+ GEM_NAME="xsd-populator"
2
+ PKG_VERSION='0.1.0'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = GEM_NAME
6
+ s.version = PKG_VERSION
7
+ s.files = `git ls-files`.split($/)
8
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
9
+
10
+ s.add_dependency 'builder', '~> 3.2'
11
+ s.add_dependency 'xsd-reader', '~> 0.1'
12
+ s.add_dependency 'data-provider', '~> 0.1'
13
+ s.add_development_dependency 'nokogiri', '~> 1.6'
14
+ s.add_development_dependency 'rspec', '~> 3.3'
15
+ s.add_development_dependency 'byebug', '~> 5.0'
16
+
17
+ s.author = "Mark van de Korput"
18
+ s.email = "dr.theman@gmail.com"
19
+ s.date = '2015-07-14'
20
+ s.summary = %q{A Ruby gem to build XML data from XSD schemas}
21
+ s.description = %q{A library of Ruby classes for generating XML data from XSD schemas (Data providers)}
22
+ s.homepage = %q{https://github.com/markkorput/xsd-populator}
23
+ s.license = "MIT"
24
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xsd-populator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mark van de Korput
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: builder
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: xsd-reader
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: data-provider
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.0'
97
+ description: A library of Ruby classes for generating XML data from XSD schemas (Data
98
+ providers)
99
+ email: dr.theman@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - Gemfile
106
+ - Gemfile.lock
107
+ - LICENSE
108
+ - README.md
109
+ - Rakefile
110
+ - lib/ddex_provider.rb
111
+ - lib/xsd_explanation_provider.rb
112
+ - lib/xsd_populator.rb
113
+ - spec/ddex_spec.rb
114
+ - spec/examples/MessageHeader.xml
115
+ - spec/examples/avs.xsd
116
+ - spec/examples/ddex-ern-v36-CatalogListMessage.xml
117
+ - spec/examples/ddex-ern-v36-MessageHeader.xml
118
+ - spec/examples/ddex-ern-v36-NewReleaseMessage.xml
119
+ - spec/examples/ddex-ern-v36.xsd
120
+ - spec/spec_helper.rb
121
+ - spec/xsd_explanation_provider_spec.rb
122
+ - spec/xsd_populator_spec.rb
123
+ - xsd-populator.gemspec
124
+ homepage: https://github.com/markkorput/xsd-populator
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.2.2
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: A Ruby gem to build XML data from XSD schemas
148
+ test_files: []