mn-requirements 0.2.2 → 0.3.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
2
  SHA256:
3
- metadata.gz: 30c82855931f4c0fb8b033a7fcb15583826ef041cee6ff1c4630570abd42a074
4
- data.tar.gz: c3765be67270e9fdad7d61b30654ce5a7ed5a7327d3b77598170354cd930c91a
3
+ metadata.gz: 4f81b57e8350c7018f06bb68420de8d7b409b7f9ff4b81eb0d98d06f484e246e
4
+ data.tar.gz: 771ba5edb39491ad133dfc2d8cacaba2e11a0eba8b95389a2d834ddd84d0227a
5
5
  SHA512:
6
- metadata.gz: '098e5bd08fdb6628f7b493e5cbdde2ff793168008837f5b0184034ed79e202a31295d29ba8e5707aa56c2abfdee7bf31c8a7677ed7deb3f7fc2732e9f731cb6e'
7
- data.tar.gz: ddcd729ae096912a304b1763092c135d5967f1a21d35f5f907dc16b408c75e8c64c3ba1864fd5941d08b36e77e6051e339353b6f19e92244e700f775c4dd5c21
6
+ metadata.gz: 38d500ecb762b731b2ef373c55c67b0cfef8e4a93bfcf4619d629c6fe69fae635c4362502bf3235a94f3b5cfbab7248fcd5e7110c42640916bd4e3b3b33e21dc
7
+ data.tar.gz: 8d5c5b770acd55b9b0006345f3c743e863239257c353626e4f56f0cb50dc218f9512338080e30bec75160e89b61bf85b747296ead049480812625799cc3fc74e
@@ -95,7 +95,9 @@ module Metanorma
95
95
  end.join("\n")
96
96
  end
97
97
 
98
- def validate(reqt, log); end
98
+ def validate(_reqt, _log)
99
+ []
100
+ end
99
101
  end
100
102
  end
101
103
  end
@@ -197,9 +197,9 @@ module Metanorma
197
197
  end
198
198
 
199
199
  def requirement_description_parse(node, out)
200
- lbl = "statement"
201
- recommend_class(node.parent) == "recommendclass" and
202
- lbl = "description"
200
+ lbl = "description"
201
+ recommend_class(node.parent) == "recommend" and
202
+ lbl = "statement"
203
203
  out << "<tr><th>#{@labels['modspec'][lbl]}</th>" \
204
204
  "<td>#{node.children.to_xml}</td></tr>"
205
205
  out
@@ -1,3 +1,10 @@
1
+ class Nokogiri::XML::Document
2
+ def reqt_iter(&block)
3
+ xpath("//xmlns:requirement | //xmlns:recommendation | //xmlns:permission")
4
+ .each_with_object({}, &block)
5
+ end
6
+ end
7
+
1
8
  module Metanorma
2
9
  class Requirements
3
10
  class Modspec < Default
@@ -36,10 +43,9 @@ module Metanorma
36
43
  end
37
44
 
38
45
  def reqtlabels(doc)
39
- doc.xpath(ns("//requirement | //recommendation | //permission"))
40
- .each_with_object({}) do |r, m|
41
- l = r.at(ns("./identifier"))&.text and m[l] = r["id"]
42
- end
46
+ doc.reqt_iter do |r, m|
47
+ l = r.at(ns("./identifier"))&.text and m[l] = r["id"]
48
+ end
43
49
  end
44
50
 
45
51
  # embedded reqts xref to reqts via label lookup
@@ -64,30 +70,23 @@ module Metanorma
64
70
  end
65
71
 
66
72
  def reqt_ids(docxml)
67
- docxml.xpath(ns("//requirement | //recommendation | //permission"))
68
- .each_with_object({}) do |r, m|
69
- id = r.at(ns("./identifier")) or next
70
- m[id.text] =
71
- { id: r["id"], lbl: @xrefs.anchor(r["id"], :xref, false) }
72
- end
73
+ docxml.reqt_iter do |r, m|
74
+ id = r.at(ns("./identifier")) or next
75
+ m[id.text] =
76
+ { id: r["id"], lbl: @xrefs.anchor(r["id"], :xref, false) }
77
+ end
73
78
  end
74
79
 
75
80
  def reqt_links_test(docxml)
76
- docxml.xpath(ns("//requirement | //recommendation | //permission"))
77
- .each_with_object({}) do |r, m|
78
- reqt_links_test1(r, m)
79
- end
81
+ docxml.reqt_iter { |r, m| reqt_links_test1(r, m) }
80
82
  end
81
83
 
82
84
  def reqt_links_test1(reqt, acc)
83
- return unless %w(conformanceclass
84
- verification).include?(reqt["type"])
85
-
85
+ %w(conformanceclass verification).include?(reqt["type"]) or return
86
86
  subj = reqt_extract_target(reqt)
87
87
  id = reqt.at(ns("./identifier")) or return
88
88
  lbl = @xrefs.anchor(@reqt_ids[id.text.strip][:id], :xref, false)
89
- return unless subj && lbl
90
-
89
+ (subj && lbl) or return
91
90
  acc[subj.text] = { lbl: lbl, id: reqt["id"] }
92
91
  end
93
92
 
@@ -110,23 +109,20 @@ module Metanorma
110
109
 
111
110
  # we have not implemented multiple levels of nesting of classes
112
111
  def reqt_links_class(docxml)
113
- docxml.xpath(ns("//requirement | //recommendation | //permission"))
114
- .each_with_object({}) do |r, m|
115
- next unless %w(class conformanceclass).include?(r["type"])
116
-
117
- id = r.at(ns("./identifier")) or next
118
- r.xpath(ns("./requirement | ./recommendation | ./permission"))
119
- .each do |r1|
120
- m = reqt_links_class1(id, r, r1, m)
121
- end
112
+ docxml.reqt_iter do |r, m|
113
+ %w(class conformanceclass).include?(r["type"]) or next
114
+ id = r.at(ns("./identifier")) or next
115
+ r.xpath(ns("./requirement | ./recommendation | ./permission"))
116
+ .each do |r1|
117
+ m = reqt_links_class1(id, r, r1, m)
122
118
  end
119
+ end
123
120
  end
124
121
 
125
122
  def reqt_links_class1(id, parent_reqt, reqt, acc)
126
123
  id1 = reqt.at(ns("./identifier")) or return acc
127
124
  lbl = @xrefs.anchor(@reqt_ids[id.text.strip][:id], :xref, false)
128
- return acc unless lbl
129
-
125
+ lbl or return acc
130
126
  acc[id1.text] = { lbl: lbl, id: parent_reqt["id"] }
131
127
  acc
132
128
  end
@@ -139,10 +135,7 @@ module Metanorma
139
135
  end
140
136
 
141
137
  def reqt_id_base_init(docxml)
142
- docxml.xpath(ns("//requirement | //recommendation | //permission"))
143
- .each_with_object({}) do |r, m|
144
- m[r["id"]] = reqt_extract_id_base(r)&.text
145
- end
138
+ docxml.reqt_iter { |r, m| m[r["id"]] = reqt_extract_id_base(r)&.text }
146
139
  end
147
140
 
148
141
  def reqt_id_base_inherit(ret, class2reqt)
@@ -1,10 +1,15 @@
1
+ require "tsort"
2
+
1
3
  module Metanorma
2
4
  class Requirements
3
5
  class Modspec < Default
4
6
  def validate(reqt, log)
7
+ @fatalerrors = []
5
8
  @log ||= log
6
9
  @ids ||= reqt_links(reqt.document)
10
+ reqt_cycles_validate
7
11
  reqt_link_validate(reqt)
12
+ @fatalerrors
8
13
  end
9
14
 
10
15
  def nested_reqt?(reqt)
@@ -109,17 +114,26 @@ module Metanorma
109
114
  .each_with_object({ id: {}, class: {}, label: {} }) do |r, m|
110
115
  next if nested_reqt?(r)
111
116
 
112
- reqt_links1(r, m)
117
+ reqt_links1(r, m, type2validate(r), reqt_links_struct(r))
113
118
  end
114
119
  end
115
120
 
116
- def reqt_links1(reqt, hash)
117
- type = type2validate(reqt)
118
- a = reqt_links_struct(reqt)
119
- hash[:id][reqt["id"]] = a
121
+ def reqt_links1(reqt, hash, type, struct)
122
+ hash[:id][reqt["id"]] = struct
120
123
  hash[:class][type] ||= []
121
- hash[:class][type] << a
122
- hash[:label][a[:label]] = reqt["id"]
124
+ hash[:class][type] << struct
125
+ reqt_links1_label(reqt, hash, struct)
126
+ end
127
+
128
+ def reqt_links1_label(reqt, hash, struct)
129
+ return hash unless struct[:label]
130
+
131
+ if hash[:label][struct[:label]]
132
+ msg = "Modspec identifier #{struct[:label]} is used more than once"
133
+ @log.add("Requirements", reqt, msg)
134
+ @fatalerrors << msg
135
+ end
136
+ hash[:label][struct[:label]] = reqt["id"]
123
137
  hash
124
138
  end
125
139
 
@@ -140,6 +154,54 @@ module Metanorma
140
154
  indirect_dependency: classif_tag(reqt, "indirect-dependency"),
141
155
  implements: classif_tag(reqt, "implements") }
142
156
  end
157
+
158
+ def reqt_cycles_validate
159
+ @cycles_validated and return
160
+ @cycles_validated = true
161
+ %i(child dependency indirect_dependency implements).each do |x|
162
+ reqt_cycles_validate1(x)
163
+ end
164
+ end
165
+
166
+ def reqt_cycles_validate1(link)
167
+ arr = TSHash.new(@ids[:id].values)
168
+ arr.link = link
169
+ TSort.each_strongly_connected_component(
170
+ lambda { |&b| arr.tsort_each_node(&b) },
171
+ lambda { |n, &b| arr.tsort_each_child(n, &b) },
172
+ ) do |c|
173
+ c.size == 1 and next
174
+ log_cycle(link, c)
175
+ end
176
+ end
177
+
178
+ def log_cycle(link, path)
179
+ @log.add("Requirements", nil, <<~MSG
180
+ Cycle in Modspec linkages through #{link}: #{(path << path.first).join(' => ')}
181
+ MSG
182
+ )
183
+ end
184
+
185
+ class TSHash
186
+ include TSort
187
+ attr_accessor :link
188
+
189
+ def initialize(arr)
190
+ @hash = arr.each_with_object({}) do |v, m|
191
+ m[v[:label]] = v
192
+ end
193
+ end
194
+
195
+ def tsort_each_node(&block)
196
+ @hash.keys.each(&block)
197
+ end
198
+
199
+ def tsort_each_child(node, &block)
200
+ (@hash[node] || {})[@link]&.each(&block)
201
+ end
202
+ end
203
+
204
+ def reqt_cycles_validate_dependency; end
143
205
  end
144
206
  end
145
207
  end
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  class Requirements
3
- VERSION = "0.2.2".freeze
3
+ VERSION = "0.3.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mn-requirements
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-09 00:00:00.000000000 Z
11
+ date: 2022-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: isodoc-i18n