ncs_mdes 0.2.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.
- data/.gitignore +10 -0
- data/.rvmrc +1 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +9 -0
- data/README.md +59 -0
- data/Rakefile +7 -0
- data/bin/mdes-console +21 -0
- data/documents/1.2/Data_Transmission_Schema_V1.2.xsd +13980 -0
- data/documents/2.0/NCS_Transmission_Schema_2.0.01.02.xml +26918 -0
- data/lib/ncs_navigator/mdes/source_documents.rb +103 -0
- data/lib/ncs_navigator/mdes/specification.rb +86 -0
- data/lib/ncs_navigator/mdes/transmission_table.rb +53 -0
- data/lib/ncs_navigator/mdes/variable.rb +119 -0
- data/lib/ncs_navigator/mdes/variable_type.rb +196 -0
- data/lib/ncs_navigator/mdes/version.rb +5 -0
- data/lib/ncs_navigator/mdes.rb +27 -0
- data/ncs_mdes.gemspec +27 -0
- data/spec/ncs_navigator/mdes/source_documents_spec.rb +95 -0
- data/spec/ncs_navigator/mdes/specification_spec.rb +102 -0
- data/spec/ncs_navigator/mdes/transmission_table_spec.rb +89 -0
- data/spec/ncs_navigator/mdes/variable_spec.rb +216 -0
- data/spec/ncs_navigator/mdes/variable_type_spec.rb +202 -0
- data/spec/ncs_navigator/mdes/version_spec.rb +13 -0
- data/spec/ncs_navigator/mdes_spec.rb +9 -0
- data/spec/spec_helper.rb +45 -0
- metadata +165 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.expand_path("../../../spec_helper.rb", __FILE__)
|
2
|
+
|
3
|
+
module NcsNavigator::Mdes
|
4
|
+
describe SourceDocuments do
|
5
|
+
before do
|
6
|
+
@spec_base, ENV[SourceDocuments::BASE_ENV_VAR] = ENV[SourceDocuments::BASE_ENV_VAR], nil
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
ENV[SourceDocuments::BASE_ENV_VAR] = @spec_base
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#base' do
|
14
|
+
let(:base) { SourceDocuments.new.base }
|
15
|
+
|
16
|
+
it 'defaults to the documents directory in the gem' do
|
17
|
+
base.should == File.expand_path('../../../../documents', __FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can be overridden using the NCS_MDES_DOCS_DIR environment variable' do
|
21
|
+
ENV['NCS_MDES_DOCS_DIR'] = '/etc/foo'
|
22
|
+
base.should == '/etc/foo'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#schema' do
|
27
|
+
let(:docs) { SourceDocuments.new }
|
28
|
+
|
29
|
+
before do
|
30
|
+
docs.base = '/baz'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'absolutizes a relative path against the base' do
|
34
|
+
docs.schema = '1.3/bar.xsd'
|
35
|
+
docs.schema.should == '/baz/1.3/bar.xsd'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'leaves an absolute path alone' do
|
39
|
+
docs.schema = '/somewhere/particular.xsd'
|
40
|
+
docs.schema.should == '/somewhere/particular.xsd'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.get' do
|
45
|
+
describe '1.2' do
|
46
|
+
subject { SourceDocuments.get('1.2') }
|
47
|
+
|
48
|
+
it 'has the correct path for the schema' do
|
49
|
+
subject.schema.should =~ %r{1.2/Data_Transmission_Schema_V1.2.xsd$}
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'is of the specified version' do
|
53
|
+
subject.version.should == '1.2'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '2.0' do
|
58
|
+
subject { SourceDocuments.get('2.0') }
|
59
|
+
|
60
|
+
it 'has the correct path for the schema' do
|
61
|
+
subject.schema.should =~ %r{2.0/NCS_Transmission_Schema_2.0.01.02.xml$}
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'is of the specified version' do
|
65
|
+
subject.version.should == '2.0'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'fails for an unsupported version' do
|
70
|
+
lambda { SourceDocuments.get('1.0') }.
|
71
|
+
should raise_error('MDES 1.0 is not supported by this version of ncs_mdes')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '.xmlns' do
|
76
|
+
subject { SourceDocuments.xmlns }
|
77
|
+
|
78
|
+
it 'includes the XSD namespace' do
|
79
|
+
subject['xs'].should == 'http://www.w3.org/2001/XMLSchema'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'includes the NCS namespace' do
|
83
|
+
subject['ncs'].should == 'http://www.nationalchildrensstudy.gov'
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'includes the NCS doc namespace' do
|
87
|
+
subject['ncsdoc'].should == 'http://www.nationalchildrensstudy.gov/doc'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'is available from an instance also' do
|
91
|
+
SourceDocuments.new.xmlns.keys.sort.should == %w(ncs ncsdoc xs)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
module NcsNavigator::Mdes
|
4
|
+
describe Specification do
|
5
|
+
describe '#version' do
|
6
|
+
it 'delegates to the source documents' do
|
7
|
+
Specification.new('1.2').version.should == '1.2'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#initialize' do
|
12
|
+
it 'accepts a string version' do
|
13
|
+
Specification.new('2.0').version.should == '2.0'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'accepts a SourceDocuments instance' do
|
17
|
+
Specification.new(SourceDocuments.new.tap { |s| s.version = '3.1' }).version.
|
18
|
+
should == '3.1'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#xsd' do
|
23
|
+
it 'is parsed' do
|
24
|
+
Specification.new('1.2', :log => logger).xsd.root.name.should == 'schema'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#transmission_tables' do
|
29
|
+
it 'is composed of TransmissionTable instances' do
|
30
|
+
Specification.new('2.0', :log => logger).transmission_tables.first.
|
31
|
+
should be_a TransmissionTable
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'in version 1.2' do
|
35
|
+
let!(:tables) { Specification.new('1.2', :log => logger).transmission_tables }
|
36
|
+
|
37
|
+
it 'has 124 tables' do
|
38
|
+
tables.size.should == 124
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'emits no warnings' do
|
42
|
+
logger[:warn].should == []
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'resolves all NCS type references' do
|
46
|
+
tables.collect { |table|
|
47
|
+
table.variables.collect { |v| v.type }.select { |t| t.reference? }
|
48
|
+
}.flatten.collect { |t| t.name }.select { |n| n =~ /^ncs:/ }.should == []
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'in version 2.0' do
|
53
|
+
let!(:tables) { Specification.new('2.0', :log => logger).transmission_tables }
|
54
|
+
|
55
|
+
it 'has 264 tables' do
|
56
|
+
tables.size.should == 264
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'emits no warnings' do
|
60
|
+
logger[:warn].should == []
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'resolves all NCS type references' do
|
64
|
+
tables.collect { |table|
|
65
|
+
table.variables.collect { |v| v.type }.select { |t| t.reference? }
|
66
|
+
}.flatten.collect { |t| t.name }.select { |n| n =~ /^ncs:/ }.should == []
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#types' do
|
72
|
+
it 'is composed of VariableType instances' do
|
73
|
+
Specification.new('2.0', :log => logger).types.first.
|
74
|
+
should be_a VariableType
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'in version 1.2' do
|
78
|
+
let!(:types) { Specification.new('1.2', :log => logger).types }
|
79
|
+
|
80
|
+
it 'has 281 types' do
|
81
|
+
types.size.should == 281
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'emits no warnings' do
|
85
|
+
logger[:warn].size.should == 0
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'in version 2.0' do
|
90
|
+
let!(:types) { Specification.new('2.0', :log => logger).types }
|
91
|
+
|
92
|
+
it 'has 423 types' do
|
93
|
+
types.size.should == 423
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'emits no warnings' do
|
97
|
+
logger[:warn].size.should == 0
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module NcsNavigator::Mdes
|
6
|
+
describe TransmissionTable do
|
7
|
+
describe '.from_element' do
|
8
|
+
let(:element) {
|
9
|
+
Nokogiri::XML(<<-XSD).root.xpath('//xs:element[@name="study_center"]').first
|
10
|
+
<xs:schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ncs="http://www.nationalchildrensstudy.gov" xmlns:ncsdoc="http://www.nationalchildrensstudy.gov/doc" xmlns:xlink="http://www.w3.org/TR/WD-xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.nationalchildrensstudy.gov" elementFormDefault="unqualified" attributeFormDefault="unqualified">
|
11
|
+
<xs:element name="transmission_tables">
|
12
|
+
<xs:complexType>
|
13
|
+
<xs:sequence>
|
14
|
+
<xs:element name="study_center" minOccurs="0" maxOccurs="unbounded">
|
15
|
+
<xs:complexType>
|
16
|
+
<xs:sequence>
|
17
|
+
<xs:element name="sc_id" ncsdoc:pii="" ncsdoc:status="1" ncsdoc:key_asso="" nillable="false" type="ncs:study_center_cl1"/>
|
18
|
+
<xs:element name="sc_name" ncsdoc:pii="" ncsdoc:status="1" ncsdoc:key_asso="" nillable="true">
|
19
|
+
<xs:simpleType>
|
20
|
+
<xs:restriction base="xs:string">
|
21
|
+
<xs:maxLength value="100"/>
|
22
|
+
</xs:restriction>
|
23
|
+
</xs:simpleType>
|
24
|
+
</xs:element>
|
25
|
+
<xs:element name="comments" ncsdoc:pii="P" ncsdoc:status="1" ncsdoc:key_asso="" nillable="true">
|
26
|
+
<xs:simpleType>
|
27
|
+
<xs:restriction base="xs:string">
|
28
|
+
<xs:maxLength value="8000"/>
|
29
|
+
</xs:restriction>
|
30
|
+
</xs:simpleType>
|
31
|
+
</xs:element>
|
32
|
+
<xs:element name="transaction_type" ncsdoc:pii="" ncsdoc:status="1" ncsdoc:key_asso="" nillable="true">
|
33
|
+
<xs:simpleType>
|
34
|
+
<xs:restriction base="xs:string">
|
35
|
+
<xs:maxLength value="36"/>
|
36
|
+
</xs:restriction>
|
37
|
+
</xs:simpleType>
|
38
|
+
</xs:element>
|
39
|
+
</xs:sequence>
|
40
|
+
</xs:complexType>
|
41
|
+
</xs:element>
|
42
|
+
</xs:sequence>
|
43
|
+
</xs:complexType>
|
44
|
+
</xs:element>
|
45
|
+
</xs:schema>
|
46
|
+
XSD
|
47
|
+
}
|
48
|
+
|
49
|
+
subject { TransmissionTable.from_element(element) }
|
50
|
+
|
51
|
+
it 'has the right name' do
|
52
|
+
subject.name.should == 'study_center'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'has the right variables' do
|
56
|
+
subject.variables.collect(&:name).
|
57
|
+
should == %w(sc_id sc_name comments transaction_type)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#initialize' do
|
62
|
+
it 'accepts a name' do
|
63
|
+
TransmissionTable.new('study_center').name.should == 'study_center'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#[]' do
|
68
|
+
subject {
|
69
|
+
TransmissionTable.new('example').tap do |t|
|
70
|
+
t.variables = %w(foo bar baz).collect do |n|
|
71
|
+
Variable.new(n)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
}
|
75
|
+
|
76
|
+
it 'gets a variable' do
|
77
|
+
subject['bar'].should be_a(Variable)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'gets a variable by name' do
|
81
|
+
subject['baz'].name.should == 'baz'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'is nil for an unknown variable' do
|
85
|
+
subject['quux'].should be_nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module NcsNavigator::Mdes
|
6
|
+
describe Variable do
|
7
|
+
describe '.from_element' do
|
8
|
+
def variable(s)
|
9
|
+
Variable.from_element(schema_element(s), :log => logger)
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:comments) {
|
13
|
+
variable(<<-XSD)
|
14
|
+
<xs:element name="comments" ncsdoc:pii="P" ncsdoc:status="1" ncsdoc:key_asso="" nillable="true">
|
15
|
+
<xs:simpleType>
|
16
|
+
<xs:restriction base="xs:string">
|
17
|
+
<xs:maxLength value="8000"/>
|
18
|
+
</xs:restriction>
|
19
|
+
</xs:simpleType>
|
20
|
+
</xs:element>
|
21
|
+
XSD
|
22
|
+
}
|
23
|
+
|
24
|
+
let(:sc_id) {
|
25
|
+
variable('<xs:element name="sc_id" ncsdoc:pii="" ncsdoc:status="1" ncsdoc:key_asso="" nillable="false" type="ncs:study_center_cl1"/>')
|
26
|
+
}
|
27
|
+
|
28
|
+
it 'has the correct name' do
|
29
|
+
comments.name.should == 'comments'
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#type' do
|
33
|
+
context 'when embedded' do
|
34
|
+
it 'is a VariableType' do
|
35
|
+
comments.type.should be_a VariableType
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'is parsed from the contents' do
|
39
|
+
comments.type.max_length.should == 8000
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'is not a reference' do
|
43
|
+
comments.type.should_not be_reference
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when a named type' do
|
48
|
+
context 'with the XML schema prefix' do
|
49
|
+
let!(:subject) { variable('<xs:element type="xs:decimal"/>') }
|
50
|
+
|
51
|
+
it 'is a VariableType' do
|
52
|
+
subject.type.should be_a VariableType
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'has a matching base type' do
|
56
|
+
subject.type.base_type.should == :decimal
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'is not a reference' do
|
60
|
+
subject.type.should_not be_reference
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with another prefix' do
|
65
|
+
it 'is a VariableType' do
|
66
|
+
sc_id.type.should be_a VariableType
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'has the name' do
|
70
|
+
sc_id.type.name.should == 'ncs:study_center_cl1'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'is a reference' do
|
74
|
+
sc_id.type.should be_reference
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when none present' do
|
80
|
+
let!(:subject) { variable('<xs:element name="bar"/>') }
|
81
|
+
|
82
|
+
it 'is nil' do
|
83
|
+
subject.type.should be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'warns' do
|
87
|
+
logger[:warn].first.should == 'Could not determine a type for variable "bar" on line 2'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#required?' do
|
93
|
+
it 'is true when not nillable' do
|
94
|
+
variable('<xs:element nillable="false"/>').should be_required
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'is false when nillable' do
|
98
|
+
comments.should_not be_required
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#pii' do
|
103
|
+
it 'is false when blank' do
|
104
|
+
variable('<xs:element ncsdoc:pii=""/>').pii.should == false
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'is true when "Y"' do
|
108
|
+
variable('<xs:element ncsdoc:pii="Y"/>').pii.should == true
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'is :possible when "P"' do
|
112
|
+
variable('<xs:element ncsdoc:pii="P"/>').pii.should == :possible
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'is the literal value when some other value' do
|
116
|
+
variable('<xs:element ncsdoc:pii="7"/>').pii.should == '7'
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'is :unknown when not set' do
|
120
|
+
variable('<xs:element/>').pii.should == :unknown
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#status' do
|
125
|
+
it 'is :active for 1' do
|
126
|
+
variable('<xs:element ncsdoc:status="1"/>').status.should == :active
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'is :new for 2' do
|
130
|
+
variable('<xs:element ncsdoc:status="2"/>').status.should == :new
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'is :modified for 3' do
|
134
|
+
variable('<xs:element ncsdoc:status="3"/>').status.should == :modified
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'is :retired for 4' do
|
138
|
+
variable('<xs:element ncsdoc:status="4"/>').status.should == :retired
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'is the literal value for some other value' do
|
142
|
+
variable('<xs:element ncsdoc:status="P4"/>').status.should == 'P4'
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'is nil when not set' do
|
146
|
+
variable('<xs:element/>').status.should be_nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#resolve_type!' do
|
152
|
+
let(:reference_type) { VariableType.reference('ncs:color_cl3') }
|
153
|
+
let(:actual_type) { VariableType.new('color_cl3') }
|
154
|
+
|
155
|
+
let(:types) { [ actual_type ] }
|
156
|
+
let(:variable) {
|
157
|
+
Variable.new('hair_color').tap { |v| v.type = reference_type }
|
158
|
+
}
|
159
|
+
|
160
|
+
context 'when the type is available' do
|
161
|
+
it 'resolves' do
|
162
|
+
variable.resolve_type!(types)
|
163
|
+
variable.type.should be actual_type
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'when the type is not resolvable' do
|
168
|
+
before { variable.resolve_type!([], :log => logger) }
|
169
|
+
|
170
|
+
it 'leaves the reference alone' do
|
171
|
+
variable.type.should be reference_type
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'warns' do
|
175
|
+
logger[:warn].first.should == 'Undefined type ncs:color_cl3 for hair_color.'
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'when the reference is of an unknown namespace' do
|
180
|
+
let(:unknown_kind_of_ref) { VariableType.reference('foo:bar') }
|
181
|
+
|
182
|
+
before {
|
183
|
+
variable.type = unknown_kind_of_ref
|
184
|
+
variable.resolve_type!(types, :log => logger)
|
185
|
+
}
|
186
|
+
|
187
|
+
it 'leaves it in place' do
|
188
|
+
variable.type.should be unknown_kind_of_ref
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'warns' do
|
192
|
+
logger[:warn].first.
|
193
|
+
should == 'Unknown reference namespace in type "foo:bar" for hair_color'
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'when the type is an XML Schema type' do
|
198
|
+
it 'ignores it' do
|
199
|
+
variable.type = VariableType.xml_schema_type('decimal')
|
200
|
+
variable.resolve_type!(types, :log => logger)
|
201
|
+
logger[:warn].should == []
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'when the type is not a reference' do
|
206
|
+
let(:not_a_ref) { VariableType.new('ncs:color_cl3') }
|
207
|
+
|
208
|
+
it 'does nothing' do
|
209
|
+
variable.type = not_a_ref
|
210
|
+
variable.resolve_type!(types)
|
211
|
+
variable.type.should be not_a_ref
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module NcsNavigator::Mdes
|
6
|
+
describe VariableType do
|
7
|
+
describe '.from_xsd_simple_type' do
|
8
|
+
def vtype(body_s, name=nil)
|
9
|
+
VariableType.from_xsd_simple_type(schema_element(<<-XML), :log => logger)
|
10
|
+
<xs:simpleType #{name ? "name='#{name}'" : nil}>
|
11
|
+
#{body_s}
|
12
|
+
</xs:simpleType>
|
13
|
+
XML
|
14
|
+
end
|
15
|
+
|
16
|
+
def vtype_from_string(restriction_body, name=nil)
|
17
|
+
vtype(<<-XML, name)
|
18
|
+
<xs:restriction base="xs:string">
|
19
|
+
#{restriction_body}
|
20
|
+
</xs:restriction>
|
21
|
+
XML
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'with an unsupported restriction base' do
|
25
|
+
let!(:subject) { vtype('<xs:restriction base="xs:int"/>') }
|
26
|
+
|
27
|
+
it 'is nil' do
|
28
|
+
subject.should be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'logs a warning' do
|
32
|
+
logger[:warn].first.
|
33
|
+
should == 'Unsupported restriction base in simpleType on line 2'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'with an unsupported restriction subelement' do
|
38
|
+
let!(:subject) { vtype_from_string('<xs:color value="red"/>') }
|
39
|
+
|
40
|
+
it 'logs a warning' do
|
41
|
+
logger[:warn].first.should == 'Unsupported restriction element "color" on line 4'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#name' do
|
46
|
+
it 'is set if there is one' do
|
47
|
+
vtype_from_string(nil, 'foo').name.should == 'foo'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'is nil if there is not one' do
|
51
|
+
vtype_from_string(nil, nil).name.should be_nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#max_length' do
|
56
|
+
it 'is set if present' do
|
57
|
+
vtype_from_string('<xs:maxLength value="255"/>').max_length.should == 255
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#min_length' do
|
62
|
+
it 'is set if present' do
|
63
|
+
vtype_from_string('<xs:minLength value="1"/>').min_length.should == 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#pattern' do
|
68
|
+
it 'is compiled to a regexp if present' do
|
69
|
+
vtype_from_string('<xs:pattern value="([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])?"/>').
|
70
|
+
pattern.should == /([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])?/
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'when malformed' do
|
74
|
+
let!(:subject) { vtype_from_string('<xs:pattern value="(["/>') }
|
75
|
+
|
76
|
+
it 'is nil if present but malformed' do
|
77
|
+
subject.pattern.should be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'logs a warning' do
|
81
|
+
logger[:warn].first.should == 'Uncompilable pattern "([" in simpleType on line 4'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#base_type' do
|
87
|
+
it 'is :string' do
|
88
|
+
vtype_from_string('<xs:maxLength value="255"/>').base_type.should == :string
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'is not a reference' do
|
93
|
+
vtype_from_string('<xs:maxLength value="255"/>').should_not be_reference
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#code_list' do
|
97
|
+
context 'when there are no enumerated values' do
|
98
|
+
it 'is nil' do
|
99
|
+
vtype_from_string('<xs:maxLength value="255"/>').code_list.should be_nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'when there are enumerated values' do
|
104
|
+
subject {
|
105
|
+
vtype_from_string(<<-XSD)
|
106
|
+
<xs:enumeration value="1" ncsdoc:label="Retired" ncsdoc:desc="Eq" ncsdoc:global_value="192-1" ncsdoc:master_cl="equipment_action"/>
|
107
|
+
<xs:enumeration value="2" ncsdoc:label="Sent to manufacturer" ncsdoc:desc="Eq" ncsdoc:global_value="192-2" ncsdoc:master_cl="equipment_action"/>
|
108
|
+
<xs:enumeration value="3" ncsdoc:label="Conducting Maintenance on Site" ncsdoc:desc="Eq" ncsdoc:global_value="192-3" ncsdoc:master_cl="equipment_action"/>
|
109
|
+
<xs:enumeration value="-7" ncsdoc:label="Not applicable" ncsdoc:desc="Eq" ncsdoc:global_value="99-7" ncsdoc:master_cl="missing_data"/>
|
110
|
+
<xs:enumeration value="-4" ncsdoc:label="Missing in Error" ncsdoc:desc="Eq" ncsdoc:global_value="99-4" ncsdoc:master_cl="missing_data"/>
|
111
|
+
XSD
|
112
|
+
}
|
113
|
+
|
114
|
+
it 'has an entry for each value' do
|
115
|
+
subject.code_list.collect(&:to_s).should == %w(1 2 3 -7 -4)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'has the description' do
|
119
|
+
subject.code_list.description.should == "Eq"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '.reference' do
|
126
|
+
subject { VariableType.reference('ncs:bar') }
|
127
|
+
|
128
|
+
it 'has the right name' do
|
129
|
+
subject.name.should == 'ncs:bar'
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'is a reference' do
|
133
|
+
subject.should be_reference
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '.xml_schema_type' do
|
138
|
+
subject { VariableType.xml_schema_type('int') }
|
139
|
+
|
140
|
+
it 'has no name' do
|
141
|
+
subject.name.should be_nil
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'has the correct base type' do
|
145
|
+
subject.base_type.should == :int
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'is not a reference' do
|
149
|
+
subject.should_not be_reference
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe VariableType::CodeListEntry do
|
155
|
+
describe '.from_xsd_enumeration' do
|
156
|
+
def code_list_entry(xml_s)
|
157
|
+
VariableType::CodeListEntry.from_xsd_enumeration(schema_element(xml_s), :log => logger)
|
158
|
+
end
|
159
|
+
|
160
|
+
let(:missing) {
|
161
|
+
code_list_entry(<<-XSD)
|
162
|
+
<xs:enumeration value="-4" ncsdoc:label="Missing in Error" ncsdoc:desc="" ncsdoc:global_value="99-4" ncsdoc:master_cl="missing_data"/>
|
163
|
+
XSD
|
164
|
+
}
|
165
|
+
|
166
|
+
describe '#value' do
|
167
|
+
it 'is set' do
|
168
|
+
missing.value.should == "-4"
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'warns when missing' do
|
172
|
+
code_list_entry('<xs:enumeration ncsdoc:label="Foo"/>')
|
173
|
+
logger[:warn].first.should == 'Missing value for code list entry on line 2'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#label" do
|
178
|
+
it 'is set' do
|
179
|
+
missing.label.should == "Missing in Error"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '#global_value' do
|
184
|
+
it 'is set' do
|
185
|
+
missing.global_value.should == '99-4'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe '#master_cl' do
|
190
|
+
it 'is set' do
|
191
|
+
missing.master_cl.should == 'missing_data'
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '#to_s' do
|
197
|
+
it 'is the value' do
|
198
|
+
VariableType::CodeListEntry.new('14').to_s.should == '14'
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|