mn-requirements 0.2.2 → 0.2.3

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: ed29bf407c16d8890bb04abf9028498f568a8d42cb2d232aab1f2312ccd045c3
4
+ data.tar.gz: 7cb6924aa3b79542533047703be36e769b4e69b299c052868232ed81764b45c0
5
5
  SHA512:
6
- metadata.gz: '098e5bd08fdb6628f7b493e5cbdde2ff793168008837f5b0184034ed79e202a31295d29ba8e5707aa56c2abfdee7bf31c8a7677ed7deb3f7fc2732e9f731cb6e'
7
- data.tar.gz: ddcd729ae096912a304b1763092c135d5967f1a21d35f5f907dc16b408c75e8c64c3ba1864fd5941d08b36e77e6051e339353b6f19e92244e700f775c4dd5c21
6
+ metadata.gz: bb1c844f85032d0fac0c678259ca2983debbbe55f7cbf308d155aac2f7f8169142ec2f838a57c0329dd6f9aa1d007e4040c7e3cf0bdf33205b41b6cdc737e40b
7
+ data.tar.gz: 49b72dcb20a45e87f82fa0b64bdc7db99374f2cf2c1c0bb031543cef803306e17e240b015c9a6a120a9714d5f8064dc4d18d72adad71d27e4864f91d24f88778
@@ -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,9 +1,12 @@
1
+ require "tsort"
2
+
1
3
  module Metanorma
2
4
  class Requirements
3
5
  class Modspec < Default
4
6
  def validate(reqt, log)
5
7
  @log ||= log
6
8
  @ids ||= reqt_links(reqt.document)
9
+ reqt_cycles_validate
7
10
  reqt_link_validate(reqt)
8
11
  end
9
12
 
@@ -140,6 +143,54 @@ module Metanorma
140
143
  indirect_dependency: classif_tag(reqt, "indirect-dependency"),
141
144
  implements: classif_tag(reqt, "implements") }
142
145
  end
146
+
147
+ def reqt_cycles_validate
148
+ @cycles_validated and return
149
+ @cycles_validated = true
150
+ %i(child dependency indirect_dependency implements).each do |x|
151
+ reqt_cycles_validate1(x)
152
+ end
153
+ end
154
+
155
+ def reqt_cycles_validate1(link)
156
+ arr = TSHash.new(@ids[:id].values)
157
+ arr.link = link
158
+ TSort.each_strongly_connected_component(
159
+ lambda { |&b| arr.tsort_each_node(&b) },
160
+ lambda { |n, &b| arr.tsort_each_child(n, &b) },
161
+ ) do |c|
162
+ c.size == 1 and next
163
+ log_cycle(link, c)
164
+ end
165
+ end
166
+
167
+ def log_cycle(link, path)
168
+ @log.add("Requirements", nil, <<~MSG
169
+ Cycle in Modspec linkages through #{link}: #{(path << path.first).join(' => ')}
170
+ MSG
171
+ )
172
+ end
173
+
174
+ class TSHash
175
+ include TSort
176
+ attr_accessor :link
177
+
178
+ def initialize(arr)
179
+ @hash = arr.each_with_object({}) do |v, m|
180
+ m[v[:label]] = v
181
+ end
182
+ end
183
+
184
+ def tsort_each_node(&block)
185
+ @hash.keys.each(&block)
186
+ end
187
+
188
+ def tsort_each_child(node, &block)
189
+ (@hash[node] || {})[@link]&.each(&block)
190
+ end
191
+ end
192
+
193
+ def reqt_cycles_validate_dependency; end
143
194
  end
144
195
  end
145
196
  end
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  class Requirements
3
- VERSION = "0.2.2".freeze
3
+ VERSION = "0.2.3".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.2.3
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-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: isodoc-i18n