dim-toolkit 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,187 +1,157 @@
1
- require_relative 'globals'
2
- require_relative 'exit_helper'
3
-
4
- module Dim
5
- class Consistency
6
- def initialize(loader)
7
- @loader = loader
8
- end
9
-
10
- def cyclic_check(ref, previous_ref, checked_ids = {}, list = [])
11
- return if checked_ids[ref.id]
12
-
13
- # Circular dependency can occur only on same category level
14
- return if previous_ref && (ref.category_level != previous_ref.category_level)
15
-
16
- if list.include?(ref.id)
17
- Dim::ExitHelper.exit(
18
- code: 1,
19
- filename: ref.filename,
20
- msg: "\"#{ref.id}\" is cyclically referenced: #{list.join(' -> ')} -> #{ref.id}"
21
- )
22
- end
23
-
24
- list << ref.id
25
-
26
- ref.existingRefs.each do |ref_id|
27
- cyclic_check(@loader.requirements[ref_id], ref, checked_ids, list)
28
- end
29
-
30
- list.pop
31
-
32
- # Any value other than nil and false will work, as this is being used to check
33
- # boolean condition on line#11
34
- checked_ids[ref.id] = 1 if list.empty?
35
- end
36
- private :cyclic_check
37
-
38
- def insert_default_values(req)
39
- req.all_attributes.each do |key, config|
40
- next if req.data.key?(key)
41
-
42
- req.data[key] = config[:default]
43
- end
44
- end
45
-
46
- def insert_property_file_definitions(ref)
47
- @loader.property_table.fetch(ref.document, {}).each do |attr, value|
48
- ref.data[attr] = value if ref.data[attr].nil?
49
-
50
- if attr == 'test_setups' && (ref.data['verification_methods'].nil? || ref.data['verification_methods'] == '')
51
- ref.data['verification_methods'] = value
52
- end
53
- end
54
- end
55
-
56
- def merge_test_setups_and_verification_methods(ref)
57
- return if ref.data.key?('verification_methods') && !ref.data['verification_methods'].nil?
58
-
59
- ref.data['verification_methods'] = ref.data['test_setups'].clone
60
- end
61
-
62
- def calculate_test_setups(ref)
63
- return unless ref.data['test_setups'].nil?
64
-
65
- tags = ref.data['tags'].cleanArray
66
-
67
- ref.data['test_setups'] = if ref.data['type'] != 'requirement' || tags.include?('process')
68
- 'none'
69
- elsif ref.category == 'input' || ref.category == 'unspecified'
70
- 'none'
71
- elsif ref.category == 'module'
72
- 'off_target'
73
- elsif tags.include?('tool')
74
- 'off_target'
75
- else
76
- 'on_target'
77
- end
78
- end
79
-
80
- def calculate_verification_methods(ref)
81
- return unless ref.data['verification_methods'].nil?
82
-
83
- tags = ref.data['tags'].cleanArray
84
-
85
- ref.data['verification_methods'] = if ref.data['type'] != 'requirement' || tags.include?('process')
86
- 'none'
87
- elsif ref.category == 'input' || ref.category == 'unspecified'
88
- 'none'
89
- elsif ref.category == 'module'
90
- 'off_target'
91
- elsif tags.include?('tool')
92
- 'off_target'
93
- else
94
- 'on_target'
95
- end
96
- end
97
-
98
- def calculate_review_status(ref)
99
- return unless ref.data['review_status'].nil?
100
-
101
- ref.data['review_status'] = if ref.category == 'input' || ref.category == 'unspecified'
102
- 'not_reviewed'
103
- else
104
- 'accepted'
105
- end
106
- end
107
-
108
- def clean_comma_separated(ref)
109
- %w[tags developer tester refs test_setups verification_methods].each do |var|
110
- ref.data[var] = ref.data[var].cleanString
111
- end
112
- end
113
-
114
- def calculate_developer_tester(ref)
115
- %w[developer tester].each do |t|
116
- next unless ref.data[t].nil?
117
-
118
- ref.data[t] = if ref.data['type'] != 'requirement'
119
- ''
120
- elsif ref.data['tags'].cleanArray.include?('process') && t == 'tester'
121
- ''
122
- elsif ref.category == 'input' || ref.category == 'unspecified'
123
- ''
124
- else
125
- ref.origin
126
- end
127
- end
128
- end
129
-
130
- def calculate_status(ref)
131
- return unless ref.data['status'].nil?
132
-
133
- ref.data['status'] = %w[requirement information].include?(ref.data['type']) ? 'draft' : 'valid'
134
- end
135
-
136
- def check(allow_missing:)
137
- requirements_by_module = {}
138
- @loader.module_data.keys.each { |um| requirements_by_module[um] = [] }
139
- @loader.requirements.each { |_id, r| requirements_by_module[r.document] << r }
140
-
141
- @loader.requirements.each do |_id, r|
142
- insert_property_file_definitions(r)
143
- insert_default_values(r)
144
- merge_test_setups_and_verification_methods(r)
145
- calculate_test_setups(r)
146
- calculate_verification_methods(r)
147
- calculate_review_status(r)
148
- calculate_developer_tester(r)
149
- calculate_status(r)
150
- end
151
-
152
- @loader.requirements.each do |_id, r|
153
- clean_comma_separated(r)
154
- end
155
-
156
- @loader.requirements.each do |id, r|
157
- r.data['refs'].cleanArray.each do |ref|
158
- if !@loader.requirements.has_key?(ref)
159
- unless allow_missing
160
- Dim::ExitHelper.exit(
161
- code: 1,
162
- filename: r.filename,
163
- msg: "\"#{id}\" refers to non-existing \"#{ref}\""
164
- )
165
- end
166
- else
167
- # Generate upstream and downstream refs based on category level
168
- if @loader.requirements[id].category_level <= @loader.requirements[ref].category_level
169
- @loader.requirements[id].downstreamRefs |= [ref]
170
- @loader.requirements[ref].upstreamRefs |= [id]
171
- else
172
- @loader.requirements[id].upstreamRefs |= [ref]
173
- @loader.requirements[ref].downstreamRefs |= [id]
174
- end
175
- @loader.requirements[ref].backwardRefs << id
176
- r.existingRefs << ref
177
- end
178
- end
179
- end
180
-
181
- @checked_ids = {}
182
- @loader.requirements.each do |_id, r|
183
- cyclic_check(r, nil, @checked_ids)
184
- end
185
- end
186
- end
187
- end
1
+ require_relative 'globals'
2
+ require_relative 'exit_helper'
3
+
4
+ module Dim
5
+ class Consistency
6
+ def initialize(loader)
7
+ @loader = loader
8
+ end
9
+
10
+ def cyclic_check(ref, previous_ref, checked_ids = {}, list = [])
11
+ return if checked_ids[ref.id]
12
+
13
+ # Circular dependency can occur only on same category level
14
+ return if previous_ref && (ref.category_level != previous_ref.category_level)
15
+
16
+ if list.include?(ref.id)
17
+ Dim::ExitHelper.exit(
18
+ code: 1,
19
+ filename: ref.filename,
20
+ msg: "\"#{ref.id}\" is cyclically referenced: #{list.join(' -> ')} -> #{ref.id}"
21
+ )
22
+ end
23
+
24
+ list << ref.id
25
+
26
+ ref.existingRefs.each do |ref_id|
27
+ cyclic_check(@loader.requirements[ref_id], ref, checked_ids, list)
28
+ end
29
+
30
+ list.pop
31
+
32
+ # Any value other than nil and false will work, as this is being used to check
33
+ # boolean condition on line#11
34
+ checked_ids[ref.id] = 1 if list.empty?
35
+ end
36
+ private :cyclic_check
37
+
38
+ def insert_default_values(req)
39
+ req.all_attributes.each do |key, config|
40
+ next if req.data.key?(key)
41
+
42
+ req.data[key] = config[:default]
43
+ end
44
+ end
45
+
46
+ def insert_property_file_definitions(ref)
47
+ @loader.property_table.fetch(ref.document, {}).each do |attr, value|
48
+ ref.data[attr] = value if ref.data[attr].nil?
49
+ end
50
+ end
51
+
52
+ def calculate_verification_methods(ref)
53
+ return unless ref.data['verification_methods'].nil?
54
+
55
+ tags = ref.data['tags'].cleanArray
56
+
57
+ ref.data['verification_methods'] = if ref.data['type'] != 'requirement' || tags.include?('process')
58
+ 'none'
59
+ elsif ref.category == 'input' || ref.category == 'unspecified'
60
+ 'none'
61
+ elsif ref.category == 'module'
62
+ 'off_target'
63
+ elsif tags.include?('tool')
64
+ 'off_target'
65
+ else
66
+ 'on_target'
67
+ end
68
+ end
69
+
70
+ def calculate_review_status(ref)
71
+ return unless ref.data['review_status'].nil?
72
+
73
+ ref.data['review_status'] = if ref.category == 'input' || ref.category == 'unspecified'
74
+ 'not_reviewed'
75
+ else
76
+ 'accepted'
77
+ end
78
+ end
79
+
80
+ def clean_comma_separated(ref)
81
+ %w[tags developer tester refs verification_methods].each do |var|
82
+ ref.data[var] = ref.data[var].cleanString
83
+ end
84
+ end
85
+
86
+ def calculate_developer_tester(ref)
87
+ %w[developer tester].each do |t|
88
+ next unless ref.data[t].nil?
89
+
90
+ ref.data[t] = if ref.data['type'] != 'requirement'
91
+ ''
92
+ elsif ref.data['tags'].cleanArray.include?('process') && t == 'tester'
93
+ ''
94
+ elsif ref.category == 'input' || ref.category == 'unspecified'
95
+ ''
96
+ else
97
+ ref.origin
98
+ end
99
+ end
100
+ end
101
+
102
+ def calculate_status(ref)
103
+ return unless ref.data['status'].nil?
104
+
105
+ ref.data['status'] = %w[requirement information].include?(ref.data['type']) ? 'draft' : 'valid'
106
+ end
107
+
108
+ def check(allow_missing:)
109
+ requirements_by_module = {}
110
+ @loader.module_data.keys.each { |um| requirements_by_module[um] = [] }
111
+ @loader.requirements.each { |_id, r| requirements_by_module[r.document] << r }
112
+
113
+ @loader.requirements.each do |_id, r|
114
+ insert_property_file_definitions(r)
115
+ insert_default_values(r)
116
+ calculate_verification_methods(r)
117
+ calculate_review_status(r)
118
+ calculate_developer_tester(r)
119
+ calculate_status(r)
120
+ end
121
+
122
+ @loader.requirements.each do |_id, r|
123
+ clean_comma_separated(r)
124
+ end
125
+
126
+ @loader.requirements.each do |id, r|
127
+ r.data['refs'].cleanArray.each do |ref|
128
+ if !@loader.requirements.has_key?(ref)
129
+ unless allow_missing
130
+ Dim::ExitHelper.exit(
131
+ code: 1,
132
+ filename: r.filename,
133
+ msg: "\"#{id}\" refers to non-existing \"#{ref}\""
134
+ )
135
+ end
136
+ else
137
+ # Generate upstream and downstream refs based on category level
138
+ if @loader.requirements[id].category_level <= @loader.requirements[ref].category_level
139
+ @loader.requirements[id].downstreamRefs |= [ref]
140
+ @loader.requirements[ref].upstreamRefs |= [id]
141
+ else
142
+ @loader.requirements[id].upstreamRefs |= [ref]
143
+ @loader.requirements[ref].downstreamRefs |= [id]
144
+ end
145
+ @loader.requirements[ref].backwardRefs << id
146
+ r.existingRefs << ref
147
+ end
148
+ end
149
+ end
150
+
151
+ @checked_ids = {}
152
+ @loader.requirements.each do |_id, r|
153
+ cyclic_check(r, nil, @checked_ids)
154
+ end
155
+ end
156
+ end
157
+ end
data/lib/dim/dimmain.rb CHANGED
@@ -1,28 +1,28 @@
1
- $stdout.sync = true
2
-
3
- require 'yaml'
4
-
5
- require_relative 'globals'
6
- require_relative 'exit_helper'
7
- require_relative 'ext/string'
8
- require_relative 'loader'
9
- require_relative 'ver'
10
- require_relative 'requirement'
11
- require_relative 'commands/stats'
12
- require_relative 'commands/check'
13
- require_relative 'commands/export'
14
- require_relative 'commands/format'
15
- require_relative 'options'
16
-
17
- module Dim
18
- def self.main(args = ARGV)
19
- Dim::Options.parse(args)
20
- loader = Dim::Loader.new
21
- loader.load(file: OPTIONS[:input],
22
- attributes_file: OPTIONS[:attributes],
23
- allow_missing: OPTIONS[:allow_missing],
24
- no_check_enclosed: OPTIONS[:no_check_enclosed] || false,
25
- silent: OPTIONS[:silent] || false)
26
- SUBCOMMANDS[OPTIONS[:subcommand]].new(loader).execute(silent: OPTIONS[:silent] || false)
27
- end
28
- end
1
+ $stdout.sync = true
2
+
3
+ require 'yaml'
4
+
5
+ require_relative 'globals'
6
+ require_relative 'exit_helper'
7
+ require_relative 'ext/string'
8
+ require_relative 'loader'
9
+ require_relative 'ver'
10
+ require_relative 'requirement'
11
+ require_relative 'commands/stats'
12
+ require_relative 'commands/check'
13
+ require_relative 'commands/export'
14
+ require_relative 'commands/format'
15
+ require_relative 'options'
16
+
17
+ module Dim
18
+ def self.main(args = ARGV)
19
+ Dim::Options.parse(args)
20
+ loader = Dim::Loader.new
21
+ loader.load(file: OPTIONS[:input],
22
+ attributes_file: OPTIONS[:attributes],
23
+ allow_missing: OPTIONS[:allow_missing],
24
+ no_check_enclosed: OPTIONS[:no_check_enclosed] || false,
25
+ silent: OPTIONS[:silent] || false)
26
+ SUBCOMMANDS[OPTIONS[:subcommand]].new(loader).execute(silent: OPTIONS[:silent] || false)
27
+ end
28
+ end
data/lib/dim/encoding.rb CHANGED
@@ -1,4 +1,4 @@
1
- # This overwrites the configuration of local machines,
2
- # Dim shall read, process and write only UTF_8.
3
- Encoding.default_external = Encoding::UTF_8
4
- Encoding.default_internal = Encoding::UTF_8
1
+ # This overwrites the configuration of local machines,
2
+ # Dim shall read, process and write only UTF_8.
3
+ Encoding.default_external = Encoding::UTF_8
4
+ Encoding.default_internal = Encoding::UTF_8
@@ -1,23 +1,23 @@
1
- module Dim
2
- class ExitHelper
3
- @exit_code = 0
4
-
5
- class << self
6
- def exit_code
7
- @exit_code
8
- end
9
-
10
- def reset_exit_code
11
- @exit_code = 0
12
- end
13
-
14
- def exit(msg:, code: 0, filename: nil)
15
- @exit_code = code
16
- inf = filename ? "in #{filename}: " : ''
17
- pre = code.positive? ? 'Error: ' : ''
18
- warn("#{pre}#{inf}#{msg}")
19
- Kernel.exit(code)
20
- end
21
- end
22
- end
23
- end
1
+ module Dim
2
+ class ExitHelper
3
+ @exit_code = 0
4
+
5
+ class << self
6
+ def exit_code
7
+ @exit_code
8
+ end
9
+
10
+ def reset_exit_code
11
+ @exit_code = 0
12
+ end
13
+
14
+ def exit(msg:, code: 0, filename: nil)
15
+ @exit_code = code
16
+ inf = filename ? "in #{filename}: " : ''
17
+ pre = code.positive? ? 'Error: ' : ''
18
+ warn("#{pre}#{inf}#{msg}")
19
+ Kernel.exit(code)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,25 +1,24 @@
1
- require_relative '../globals'
2
- require_relative '../requirement'
3
-
4
- module Dim
5
- class Csv < ExporterInterface
6
- EXPORTER['csv'] = self
7
-
8
- def header(content)
9
- @keys = @loader.all_attributes.keys
10
- @keys.delete('test_setups')
11
- content.puts 'Sep=,'
12
- content.puts "id,document_name,originator,#{@keys.join(',')}"
13
- end
14
-
15
- def requirement(content, req)
16
- vals = [req.id, req.document, req.origin]
17
- @keys.each { |k| vals << req.data[k] }
18
- # These values will never be nil.
19
- # ID cannot be nil in Dim file, so as origin (default is "") and
20
- # document cannot be missing in Dim files.
21
- # Which leaves with data and YAML file cannot define nil value.
22
- content.puts(vals.map { |a| "\"#{a.gsub('"', '""')}\"" }.join(','))
23
- end
24
- end
25
- end
1
+ require_relative '../globals'
2
+ require_relative '../requirement'
3
+
4
+ module Dim
5
+ class Csv < ExporterInterface
6
+ EXPORTER['csv'] = self
7
+
8
+ def header(content)
9
+ @keys = @loader.all_attributes.keys
10
+ content.puts 'Sep=,'
11
+ content.puts "id,document_name,originator,#{@keys.join(',')}"
12
+ end
13
+
14
+ def requirement(content, req)
15
+ vals = [req.id, req.document, req.origin]
16
+ @keys.each { |k| vals << req.data[k] }
17
+ # These values will never be nil.
18
+ # ID cannot be nil in Dim file, so as origin (default is "") and
19
+ # document cannot be missing in Dim files.
20
+ # Which leaves with data and YAML file cannot define nil value.
21
+ content.puts(vals.map { |a| "\"#{a.gsub('"', '""')}\"" }.join(','))
22
+ end
23
+ end
24
+ end
@@ -1,37 +1,37 @@
1
- module Dim
2
- # This is how the interface is used by the Dim::Export:
3
- #
4
- # initialize()
5
- #
6
- # for every module:
7
- # header()
8
- # document()
9
- # metadata()
10
- # for every requirement in module:
11
- # requirement()
12
- # footer()
13
- #
14
- # if hasIndex:
15
- # for every originator/category combination:
16
- # index()
17
- class ExporterInterface
18
- attr_reader :hasIndex
19
-
20
- def initialize(loader)
21
- @hasIndex = false
22
- @loader = loader
23
- end
24
-
25
- def header(f); end
26
-
27
- def document(f, name); end
28
-
29
- def metadata(f, metadata); end
30
-
31
- def requirement(f, r); end
32
-
33
- def footer(f); end
34
-
35
- def index(f, category, origin, modules); end
36
- end
37
- end
1
+ module Dim
2
+ # This is how the interface is used by the Dim::Export:
3
+ #
4
+ # initialize()
5
+ #
6
+ # for every document:
7
+ # header()
8
+ # document()
9
+ # metadata()
10
+ # for every requirement in document:
11
+ # requirement()
12
+ # footer()
13
+ #
14
+ # if hasIndex:
15
+ # for every originator/category combination:
16
+ # index()
17
+ class ExporterInterface
18
+ attr_reader :hasIndex
19
+
20
+ def initialize(loader)
21
+ @hasIndex = false
22
+ @loader = loader
23
+ end
24
+
25
+ def header(f); end
26
+
27
+ def document(f, name); end
28
+
29
+ def metadata(f, metadata); end
30
+
31
+ def requirement(f, r); end
32
+
33
+ def footer(f); end
34
+
35
+ def index(f, category, origin, modules); end
36
+ end
37
+ end
@@ -1,32 +1,30 @@
1
- require 'json'
2
-
3
- require_relative '../globals'
4
- require_relative '../requirement'
5
-
6
- module Dim
7
- class Json < ExporterInterface
8
- EXPORTER['json'] = self
9
-
10
- def header(_f)
11
- @content = []
12
- end
13
-
14
- def requirement(_f, r)
15
- vals = { 'id' => r.id, 'document_name' => r.document, 'originator' => r.origin }
16
-
17
- @loader.all_attributes.keys.each do |k|
18
- next if k == 'test_setups'
19
-
20
- v = r.data[k]
21
- v = v.cleanUniqArray.join(',') if k == 'refs'
22
- vals[k] = v.strip
23
- end
24
-
25
- @content << vals
26
- end
27
-
28
- def footer(f)
29
- f.puts(JSON.pretty_generate(@content))
30
- end
31
- end
32
- end
1
+ require 'json'
2
+
3
+ require_relative '../globals'
4
+ require_relative '../requirement'
5
+
6
+ module Dim
7
+ class Json < ExporterInterface
8
+ EXPORTER['json'] = self
9
+
10
+ def header(_f)
11
+ @content = []
12
+ end
13
+
14
+ def requirement(_f, r)
15
+ vals = { 'id' => r.id, 'document_name' => r.document, 'originator' => r.origin }
16
+
17
+ @loader.all_attributes.keys.each do |k|
18
+ v = r.data[k]
19
+ v = v.cleanUniqArray.join(',') if k == 'refs'
20
+ vals[k] = v.strip
21
+ end
22
+
23
+ @content << vals
24
+ end
25
+
26
+ def footer(f)
27
+ f.puts(JSON.pretty_generate(@content))
28
+ end
29
+ end
30
+ end