mn-requirements 0.0.1 → 0.1.1

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: e8561bbfa3412485e724742474078348fffb06c9687bcf2cb18d815027ab5df2
4
- data.tar.gz: e9d8755e0ba593ca3e308e579bb0abea161ccd0bac385d4e8ef58f946b083c6a
3
+ metadata.gz: afda052b107a46deb4475c78df7261e3cfb708b4525372da5c00d71040aaabcd
4
+ data.tar.gz: 68c1ef39846359da8902e194495d105ebc767bbfc8284ab81946b49483b8be63
5
5
  SHA512:
6
- metadata.gz: f8a0464554be764a948a3aa9a2531dbb0959e867d28c51d5ba9e25febd1e27260d810eae70a15001bedf95bddb386c6d59c0693a2eb8e73c16018ce4bb5c93ca
7
- data.tar.gz: 16afa9642145d263f50ee5e7cd62d9f27ac6ff852250785195ad32d06e6498ca865164b37637fe75ac7069656f5c6d50cf529bcf36ac14af918e06f8ed965c2e
6
+ metadata.gz: a467cdddb7c5bf675f7979d4b2d6a1581a21b0c76b30abbeec951cc0ab377088d7dea7efbb4e2195a6817e0d020a7311acad4eab2718bdddc209f931fb544796
7
+ data.tar.gz: c6bdc8ef9f159456a474a25476925d77497fe36809a69a63f9be9e712d4a9db86f25410d52e6850b1707c50f21a0a36f82beeea4e59007cff8a3aa49f028dc08
data/README.adoc CHANGED
@@ -16,11 +16,11 @@ toolset, allowing various models to be processed. The gem currently supports:
16
16
 
17
17
  == Usage
18
18
 
19
- Within Metanorma, a requirement is specified as being of a particular type; e.g.
19
+ Within Metanorma, a requirement is specified as being of a particular model; e.g.
20
20
 
21
21
  [source,asciidoc]
22
22
  ----
23
- [requirement,type=ogc]
23
+ [requirement,model=ogc]
24
24
  ...
25
25
  ...
26
26
  ----
@@ -0,0 +1,23 @@
1
+ require "yaml"
2
+ require "isodoc-i18n"
3
+
4
+ module IsoDoc
5
+ class MnRequirementsI18n < I18n
6
+ def load_yaml1(lang, script)
7
+ case lang
8
+ when "en", "fr", "ru", "de", "es", "ar"
9
+ load_yaml2(lang)
10
+ when "zh"
11
+ if script == "Hans" then load_yaml2("zh-Hans")
12
+ else load_yaml2("en")
13
+ end
14
+ else load_yaml2("en")
15
+ end
16
+ end
17
+
18
+ def load_yaml2(str)
19
+ YAML.load_file(File.join(File.dirname(__FILE__),
20
+ "../isodoc-yaml/i18n-#{str}.yaml"))
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ requirements:
2
+ default:
3
+ requirement: مطلب
4
+ recommendation: توصية
5
+ permission: إذن
6
+ obligation: التزام
7
+ subject: موضوع
8
+ inherits: يرث
9
+ modspec:
10
+ recommendationtest: اختبار التوصية
11
+ requirementtest: اختبار المتطلبات
12
+ permissiontest: اختبار الإذن
13
+ recommendationclass: فئة التوصيات
14
+ requirementclass: فئة المتطلبات
15
+ permissionclass: فئة الأذونات
16
+ abstracttest: اختبار تجريدي
17
+ conformanceclass: فئة المطابقة
18
+ conformancetest: اختبار المطابقة
19
+ targettype: نوع الهدف
20
+ target: استهداف
21
+ testpurpose: هدف الاختبار
22
+ testmethod: طريقة اختبار
23
+ dependency: الاعتماد
24
+ indirectdependency: التبعية غير المباشرة
25
+ identifier: المعرف
26
+ included_in: مدرج في
@@ -0,0 +1,27 @@
1
+ requirements:
2
+ default:
3
+ requirement: Anforderung
4
+ recommendation: Empfehlung
5
+ permission: Erlaubnis
6
+ obligation: Verbindlichkeit
7
+ subject: Thema
8
+ inherits: Erbt
9
+ modspec:
10
+ recommendationtest: Empfehlungstest
11
+ requirementtest: Anforderungstest
12
+ permissiontest: Berechtigungstest
13
+ recommendationclass: Empfehlungsklasse
14
+ requirementclass: Anforderungsklasse
15
+ permissionclass: Berechtigungsklasse
16
+ abstracttest: Abstrakter Test
17
+ conformanceclass: Konformitätsklasse
18
+ conformancetest: Konformitätstest
19
+ targettype: Zieltyp
20
+ target: Ziel
21
+ testpurpose: Testzweck
22
+ testmethod: Testmethode
23
+ dependency: Abhängigkeit
24
+ indirectdependency: Indirekte Abhängigkeit
25
+ identifier: Kennung
26
+ included_in: Enthalten in
27
+
@@ -0,0 +1,27 @@
1
+ requirements:
2
+ default:
3
+ requirement: Requirement
4
+ recommendation: Recommendation
5
+ permission: Permission
6
+ obligation: Obligation
7
+ subject: Subject
8
+ inherits: Inherits
9
+ modspec:
10
+ recommendationtest: Recommendation test
11
+ requirementtest: Requirement test
12
+ permissiontest: Permission test
13
+ recommendationclass: Recommendations class
14
+ requirementclass: Requirements class
15
+ permissionclass: Permissions class
16
+ abstracttest: Abstract test
17
+ conformanceclass: Conformance class
18
+ conformancetest: Conformance test
19
+ targettype: Target type
20
+ target: Target
21
+ testpurpose: Test purpose
22
+ testmethod: Test method
23
+ dependency: Dependency
24
+ indirectdependency: Indirect Dependency
25
+ identifier: Identifier
26
+ included_in: Included in
27
+
@@ -0,0 +1,27 @@
1
+ requirements:
2
+ default:
3
+ requirement: Requerimiento
4
+ recommendation: Recomendación
5
+ permission: Permiso
6
+ obligation: Obligación
7
+ subject: Tema
8
+ inherits: Hereda
9
+ modspec:
10
+ recommendationtest: Prueba de recomendación
11
+ requirementtest: Prueba de requerimiento
12
+ permissiontest: Prueba de permiso
13
+ recommendationclass: Clase de recomendaciones
14
+ requirementclass: Clase de requerimientos
15
+ permissionclass: Clase de permisos
16
+ abstracttest: Prueba abstracta
17
+ conformanceclass: Clase de conformidad
18
+ conformancetest: Prueba de conformidad
19
+ targettype: Tipo de objetivo
20
+ target: Objetivo
21
+ testpurpose: Propósito de prueba
22
+ testmethod: Método de prueba
23
+ dependency: Dependencia
24
+ indirectdependency: Dependencia indirecta
25
+ identifier: Identificador
26
+ included_in: Incluido en
27
+
@@ -0,0 +1,27 @@
1
+ requirements:
2
+ default:
3
+ requirement: Exigence
4
+ recommendation: Recommandation
5
+ permission: Autorisation
6
+ obligation: Obligation
7
+ subject: Sujet
8
+ inherits: Hérite
9
+ modspec:
10
+ recommendationtest: Test de recommendation
11
+ requirementtest: Test d’exigence
12
+ permissiontest: Test d’autorisation
13
+ recommendationclass: Classe de recommendations
14
+ requirementclass: Classe d’exigences
15
+ permissionclass: Classe d’autorisations
16
+ abstracttest: Test abstrait
17
+ conformanceclass: Classe de confirmité
18
+ conformancetest: Test de conformité
19
+ targettype: Type de cible
20
+ target: Cible
21
+ testpurpose: Objectif du test
22
+ testmethod: Méthode du test
23
+ dependency: Dépendance
24
+ indirectdependency: Dépendance indirecte
25
+ identifier: Identifiant
26
+ included_in: Inclus dans
27
+
@@ -0,0 +1,27 @@
1
+ requirements:
2
+ default:
3
+ requirement: Требование
4
+ recommendation: Рекомендация
5
+ permission: Разрешение
6
+ obligation: Обязательство
7
+ subject: Тема
8
+ inherits: Наследует
9
+ modspec:
10
+ recommendationtest: Проверка рекомендации
11
+ requirementtest: Проверка требований
12
+ permissiontest: Проверка разрешения
13
+ recommendationclass: Класс рекомендаций
14
+ requirementclass: Класс требований
15
+ permissionclass: Класс разрешений
16
+ abstracttest: Абстрактная проверка
17
+ conformanceclass: Класс соответствия
18
+ conformancetest: Проверка на соответствие
19
+ targettype: Тип цели
20
+ target: Цель
21
+ testpurpose: Цель теста
22
+ testmethod: Метод теста
23
+ dependency: Зависимость
24
+ indirectdependency: Косвенная зависимость
25
+ identifier: Идентификатор
26
+ included_in: Входит в
27
+
@@ -0,0 +1,27 @@
1
+ requirements:
2
+ default:
3
+ requirement: 要求
4
+ recommendation: 建议
5
+ permission: 容許
6
+ obligation: 义务
7
+ subject: 主体
8
+ inherits: 继承自
9
+ modspec:
10
+ recommendationtest: 推荐测试
11
+ requirementtest: 需求测试
12
+ permissiontest: 权限测试
13
+ recommendationclass: 推荐类
14
+ requirementclass: 需求类
15
+ permissionclass: 权限类
16
+ abstracttest: 抽象测试
17
+ conformanceclass: 一致性等级
18
+ conformancetest: 一致性测试
19
+ targettype: 目标类型
20
+ target: 目标
21
+ testpurpose: 测试目的
22
+ testmethod: 测试方法
23
+ dependency: 依赖
24
+ indirectdependency: 间接依赖
25
+ identifier: 标识符
26
+ included_in: 包含在
27
+
@@ -94,6 +94,8 @@ module Metanorma
94
94
  end
95
95
  end.join("\n")
96
96
  end
97
+
98
+ def validate(reqt, log); end
97
99
  end
98
100
  end
99
101
  end
@@ -43,8 +43,9 @@ module Metanorma
43
43
 
44
44
  def recommendation_header(node, out)
45
45
  label, title, name = recommendation_labels(node)
46
- ret = name ? [name + l10n(":")] : []
46
+ ret = name ? [name] : []
47
47
  if label || title
48
+ ret << l10n(":") unless ret.empty?
48
49
  ret += ["<br/>", label]
49
50
  ret << l10n(". ") if label && title
50
51
  ret << title
@@ -55,12 +56,12 @@ module Metanorma
55
56
 
56
57
  def recommendation_attributes1(node, out)
57
58
  oblig = node["obligation"] and
58
- out << l10n("#{@labels['obligation']}: #{oblig}")
59
+ out << l10n("#{@labels['default']['obligation']}: #{oblig}")
59
60
  node.xpath(ns("./subject")).each do |subj|
60
- out << l10n("#{@labels['subject']}: #{subj.text}")
61
+ out << l10n("#{@labels['default']['subject']}: #{subj.text}")
61
62
  end
62
63
  node.xpath(ns("./inherit")).each do |i|
63
- out << recommendation_attr_parse(i, @labels["inherits"])
64
+ out << recommendation_attr_parse(i, @labels["default"]["inherits"])
64
65
  end
65
66
  node.xpath(ns("./classification")).each do |c|
66
67
  out << recommendation_attr_keyvalue(c, "tag", "value")
@@ -96,8 +97,10 @@ module Metanorma
96
97
  return out if node["exclude"] == "true"
97
98
 
98
99
  ret = node.dup
99
- ret["type"] = reqt_component_type(node)
100
- ret.name = "div"
100
+ if reqt_subpart?(node.name)
101
+ ret["type"] = reqt_component_type(node)
102
+ ret.name = "div"
103
+ end
101
104
  out << ret
102
105
  out
103
106
  end
@@ -7,22 +7,22 @@ module Metanorma
7
7
 
8
8
  def req_class_paths
9
9
  [
10
- { klass: "permission", label: "permission",
10
+ { klass: "permission", label: @labels["default"]["permission"],
11
11
  xpath: "permission" },
12
- { klass: "requirement", label: "requirement",
12
+ { klass: "requirement", label: @labels["default"]["requirement"],
13
13
  xpath: "requirement" },
14
- { klass: "recommendation", label: "recommendation",
14
+ { klass: "recommendation", label: @labels["default"]["recommendation"],
15
15
  xpath: "recommendation" },
16
16
  ]
17
17
  end
18
18
 
19
19
  def req_nested_class_paths
20
20
  [
21
- { klass: "permission", label: "permission",
21
+ { klass: "permission", label: @labels["default"]["permission"],
22
22
  xpath: "permission" },
23
- { klass: "requirement", label: "requirement",
23
+ { klass: "requirement", label: @labels["default"]["requirement"],
24
24
  xpath: "requirement" },
25
- { klass: "recommendation", label: "recommendation",
25
+ { klass: "recommendation", label: @labels["default"]["recommendation"],
26
26
  xpath: "recommendation" },
27
27
  ]
28
28
  end
@@ -37,8 +37,7 @@ module Metanorma
37
37
  d.remove
38
38
  end
39
39
  if REQS.include?(term.text) && !val.text.empty?
40
- val["label"] = val.text.strip
41
- val.children.remove
40
+ val.children = "<identifier>#{val.text.strip}</identifier>"
42
41
  end
43
42
  val
44
43
  end
@@ -5,16 +5,17 @@ module Metanorma
5
5
  class Requirements
6
6
  class Modspec < Default
7
7
  def requirement_render1(node)
8
+ init_lookups(node.document)
8
9
  requirement_table_cleanup(super)
9
10
  end
10
11
 
11
- def recommendation_base(node, klass)
12
+ def recommendation_base(node, _klass)
12
13
  out = node.document.create_element("table")
13
14
  out.default_namespace = node.namespace.href
14
15
  %w(id keep-with-next keep-lines-together unnumbered).each do |x|
15
16
  out[x] = node[x] if node[x]
16
17
  end
17
- out["class"] = klass
18
+ out["class"] = "modspec"
18
19
  out["type"] = recommend_class(node)
19
20
  recommendation_component_labels(node)
20
21
  out
@@ -29,24 +30,30 @@ module Metanorma
29
30
  end
30
31
  end
31
32
 
32
- def recommendation_header(recommend, out)
33
- h = out.add_child("<thead><tr><th scope='colgroup' colspan='2'>"\
34
- "</th></tr></thead>").first
35
- recommendation_name(recommend, h.at(ns(".//th")))
33
+ def recommendation_header(reqt, out)
34
+ n = recommendation_name(reqt, nil)
35
+ x = if reqt.ancestors("requirement, recommendation, permission").empty?
36
+ "<thead><tr><th scope='colgroup' colspan='2'>"\
37
+ "<p class='#{recommend_name_class(reqt)}'>#{n}</p>"\
38
+ "</th></tr></thead>"
39
+ else
40
+ "<thead><tr><td>#{recommendation_class_label(reqt)}</td>"\
41
+ "<td>#{n}</td></tr></thead>"
42
+ end
43
+ out << x
36
44
  out
37
45
  end
38
46
 
39
- def recommendation_name(node, out)
40
- b = out.add_child("<p class='#{recommend_name_class(node)}'></p>").first
41
- name = node.at(ns("./name")) and name.children.each do |n|
42
- b << n
43
- end
47
+ def recommendation_name(node, _out)
48
+ ret = ""
49
+ name = node.at(ns("./name")) and ret += name.children.to_xml
44
50
  title = node.at(ns("./title"))
45
- return unless title &&
51
+ return ret unless title &&
46
52
  node.ancestors("requirement, recommendation, permission").empty?
47
53
 
48
- b << l10n(": ") if name
49
- title.children.each { |n| b << n }
54
+ ret += l10n(": ") unless !name || name.text.empty?
55
+ ret += title.children.to_xml
56
+ ret
50
57
  end
51
58
 
52
59
  def recommendation_attributes(node, out)
@@ -60,10 +67,8 @@ module Metanorma
60
67
 
61
68
  def recommend_title(node, out)
62
69
  label = node.at(ns("./identifier")) or return
63
- b = out.add_child("<tr><td colspan='2'><p></p></td></tr>")
64
- p = b.at(ns(".//p"))
65
- p["class"] = "RecommendationLabel"
66
- p << label.children.to_xml
70
+ out.add_child("<tr><td scope='colgroup' colspan='2'>"\
71
+ "<tt>#{label.children.to_xml}</tt></td>")
67
72
  end
68
73
 
69
74
  def recommendation_attributes1(node)
@@ -76,30 +81,42 @@ module Metanorma
76
81
  end
77
82
 
78
83
  def recommendation_attributes1_head(node, head)
79
- oblig = node["obligation"] and head << ["Obligation", oblig]
84
+ oblig = node["obligation"] and
85
+ head << [@labels["default"]["obligation"], oblig]
80
86
  subj = node.at(ns("./subject"))&.children and
81
87
  head << [rec_subj(node), subj]
82
88
  node.xpath(ns("./classification[tag = 'target']/value")).each do |v|
83
- xref = recommendation_id(node.document, v.text) and head << [
89
+ xref = recommendation_id(v.text) and head << [
84
90
  rec_target(node), xref
85
91
  ]
86
92
  end
87
- %w(general class).include?(node["type"]) and
88
- xref = recommendation_link(node.document,
89
- node.at(ns("./identifier"))&.text) and
90
- head << ["Conformance test", xref]
93
+ head += recommendation_backlinks(node)
91
94
  recommendation_attributes1_dependencies(node, head)
92
95
  end
93
96
 
97
+ def recommendation_backlinks(node)
98
+ ret = []
99
+ id = node.at(ns("./identifier")) or return ret
100
+ %w(general class).include?(node["type"]) and
101
+ xref = recommendation_link_test(id.text) and
102
+ ret << [@labels["modspec"]["conformancetest"], xref]
103
+ ret
104
+ (node["type"].nil? || node["type"].empty? ||
105
+ node["type"] == "verification") and
106
+ xref = recommendation_link_class(id.text) and
107
+ ret << [@labels["modspec"]["included_in"], xref]
108
+ ret
109
+ end
110
+
94
111
  def recommendation_attributes1_dependencies(node, head)
95
112
  node.xpath(ns("./inherit")).each do |i|
96
- head << ["Dependency",
97
- recommendation_id(node.document, i.children.to_xml)]
113
+ head << [@labels["modspec"]["dependency"],
114
+ recommendation_id(i.children.to_xml)]
98
115
  end
99
116
  node.xpath(ns("./classification[tag = 'indirect-dependency']/value"))
100
117
  .each do |v|
101
- xref = recommendation_id(node.document, v.children.to_xml) and
102
- head << ["Indirect Dependency", xref]
118
+ xref = recommendation_id(v.children.to_xml) and
119
+ head << [@labels["modspec"]["indirectdependency"], xref]
103
120
  end
104
121
  head
105
122
  end
@@ -171,43 +188,25 @@ module Metanorma
171
188
  return table unless table["type"] == "recommendclass"
172
189
 
173
190
  table.xpath(ns("./tbody/tr/td/table")).each do |t|
174
- t.xpath(ns("./thead | ./tbody |./tfoot")).each do |x|
175
- x.replace(x.children)
176
- end
177
- (x = t.at(ns("./tr/th[@colspan = '2']"))) &&
178
- (y = t.at(ns("./tr/td[@colspan = '2']"))) and
179
- requirement_table_cleanup1(x, y)
180
- t.parent.parent.replace(t.children)
191
+ x = t.at(ns("./thead/tr")) or next
192
+ t.parent.parent.replace(x)
181
193
  end
182
194
  table
183
195
  end
184
196
 
185
- # table nested in table: merge label and caption into a single row
186
- def requirement_table_cleanup1(outer, inner)
187
- outer.delete("colspan")
188
- outer.delete("scope")
189
- inner.delete("colspan")
190
- inner.delete("scope")
191
- outer.name = "td"
192
- p = outer.at(ns("./p[@class = 'RecommendationTitle']")) and
193
- p.delete("class")
194
- outer.parent << inner.dup
195
- inner.parent.remove
196
- end
197
-
198
197
  def rec_subj(node)
199
198
  case node["type"]
200
- when "class" then "Target type"
201
- else "Subject"
199
+ when "class" then @labels["modspec"]["targettype"]
200
+ else @labels["default"]["subject"]
202
201
  end
203
202
  end
204
203
 
205
204
  def rec_target(node)
206
205
  case node["type"]
207
- when "class" then "Target type"
208
- when "conformanceclass" then "Requirements class"
209
- when "verification", "abstracttest" then "Requirement"
210
- else "Target"
206
+ when "class" then @labels["modspec"]["targettype"]
207
+ when "conformanceclass" then @labels["modspec"]["requirementclass"]
208
+ when "verification", "abstracttest" then @labels["default"]["requirement"]
209
+ else @labels["modspec"]["target"]
211
210
  end
212
211
  end
213
212
 
@@ -227,11 +226,13 @@ module Metanorma
227
226
  end
228
227
 
229
228
  def recommend_component_label(node)
230
- case node["class"]
231
- when "test-purpose" then "Test purpose"
232
- when "test-method" then "Test method"
233
- else Metanorma::Utils.strict_capitalize_first(node["class"])
234
- end
229
+ c = case node["class"]
230
+ when "test-purpose" then "Test purpose"
231
+ when "test-method" then "Test method"
232
+ else node["class"]
233
+ end
234
+ @labels["default"][c] || @labels["modspec"][c] ||
235
+ Metanorma::Utils.strict_capitalize_first(c)
235
236
  end
236
237
  end
237
238
  end
@@ -1,4 +1,5 @@
1
1
  require_relative "cleanup"
2
+ require_relative "validate"
2
3
  require_relative "isodoc"
3
4
 
4
5
  module Metanorma
@@ -2,42 +2,61 @@ module Metanorma
2
2
  class Requirements
3
3
  class Modspec < Default
4
4
  def recommendation_label(elem, type, xrefs)
5
+ @xrefs ||= xrefs.dup
6
+ init_lookups(elem.document)
7
+
5
8
  label = elem.at(ns("./identifier"))&.text
6
9
  if inject_crossreference_reqt?(elem, label)
7
- number = xrefs.anchor(reqtlabels(elem.document, label), :xref, false)
8
- number.nil? ? type : number
10
+ recommendation_label_xref(elem, label, xrefs)
9
11
  else
10
12
  type = recommendation_class_label(elem)
11
13
  super
12
14
  end
13
15
  end
14
16
 
15
- def reqtlabels(doc, label)
16
- @reqtlabels ||= doc
17
- .xpath(ns("//requirement | //recommendation | //permission"))
17
+ def recommendation_label_xref(elem, label, xrefs)
18
+ id = @reqtlabels[label]
19
+ number = xrefs.anchor(id, :xref, false)
20
+ number.nil? and return type
21
+ elem.ancestors("requirement, recommendation, permission").empty? and
22
+ return number
23
+ "<xref target='#{id}'>#{number}</xref>"
24
+ end
25
+
26
+ def init_lookups(doc)
27
+ return if @init_lookups
28
+
29
+ @init_lookups = true
30
+ @reqtlabels = reqtlabels(doc)
31
+ @reqt_ids = reqt_ids(doc)
32
+ @reqt_links_class = reqt_links_class(doc)
33
+ @reqt_links_test = reqt_links_test(doc)
34
+ end
35
+
36
+ def reqtlabels(doc)
37
+ doc.xpath(ns("//requirement | //recommendation | //permission"))
18
38
  .each_with_object({}) do |r, m|
19
- l = r.at(ns("./label"))&.text and m[l] = r["id"]
39
+ l = r.at(ns("./identifier"))&.text and m[l] = r["id"]
20
40
  end
21
- @reqtlabels[label]
22
41
  end
23
42
 
24
- # embedded reqts xref to top level reqts via label lookup
43
+ # embedded reqts xref to reqts via label lookup
25
44
  def inject_crossreference_reqt?(node, label)
26
- !node.ancestors("requirement, recommendation, permission").empty? &&
27
- reqtlabels(node.document, label)
45
+ !node.ancestors("requirement, recommendation, permission").empty? and
46
+ @reqtlabels[label]
28
47
  end
29
48
 
30
49
  def recommendation_class_label(node)
31
50
  case node["type"]
32
- when "verification" then @labels["#{node.name}test"]
33
- when "class" then @labels["#{node.name}class"]
34
- when "abstracttest" then @labels["abstracttest"]
35
- when "conformanceclass" then @labels["conformanceclass"]
51
+ when "verification" then @labels["modspec"]["#{node.name}test"]
52
+ when "class" then @labels["modspec"]["#{node.name}class"]
53
+ when "abstracttest" then @labels["modspec"]["abstracttest"]
54
+ when "conformanceclass" then @labels["modspec"]["conformanceclass"]
36
55
  else
37
56
  case node.name
38
- when "recommendation" then @labels["recommendation"]
39
- when "requirement" then @labels["requirement"]
40
- when "permission" then @labels["permission"]
57
+ when "recommendation" then @labels["default"]["recommendation"]
58
+ when "requirement" then @labels["default"]["requirement"]
59
+ when "permission" then @labels["default"]["permission"]
41
60
  end
42
61
  end
43
62
  end
@@ -46,34 +65,56 @@ module Metanorma
46
65
  docxml.xpath(ns("//requirement | //recommendation | //permission"))
47
66
  .each_with_object({}) do |r, m|
48
67
  id = r.at(ns("./identifier")) or next
49
- m[id.text] = r["id"]
68
+ m[id.text] =
69
+ { id: r["id"], lbl: @xrefs.anchor(r["id"], :xref, false) }
50
70
  end
51
71
  end
52
72
 
53
- def reqt_links(docxml)
73
+ def reqt_links_test(docxml)
54
74
  docxml.xpath(ns("//requirement | //recommendation | //permission"))
55
75
  .each_with_object({}) do |r, m|
56
76
  next unless %w(conformanceclass
57
77
  verification).include?(r["type"])
58
78
 
59
79
  subj = r.at(ns("./classification[tag = 'target']/value"))
60
- id = r.at(ns("./identifier"))
61
- next unless subj && id
80
+ id = r.at(ns("./identifier")) or next
81
+ lbl = @xrefs.anchor(@reqt_ids[id.text.strip][:id], :xref, false)
82
+ next unless subj && lbl
62
83
 
63
- m[subj.text] = { lbl: id.text, id: r["id"] }
84
+ m[subj.text] = { lbl: lbl, id: r["id"] }
64
85
  end
65
86
  end
66
87
 
67
- def recommendation_link(docxml, ident)
68
- @reqt_links ||= reqt_links(docxml)
69
- test = @reqt_links[ident&.strip] or return nil
88
+ def recommendation_link_test(ident)
89
+ test = @reqt_links_test[ident&.strip] or return nil
70
90
  "<xref target='#{test[:id]}'>#{test[:lbl]}</xref>"
71
91
  end
72
92
 
73
- def recommendation_id(docxml, ident)
74
- @reqt_ids ||= reqt_ids(docxml)
93
+ def reqt_links_class(docxml)
94
+ docxml.xpath(ns("//requirement | //recommendation | //permission"))
95
+ .each_with_object({}) do |r, m|
96
+ next unless %w(class conformanceclass).include?(r["type"])
97
+
98
+ id = r.at(ns("./identifier")) or next
99
+ r.xpath(ns("./requirement | ./recommendation | ./permission"))
100
+ .each do |r1|
101
+ id1 = r1.at(ns("./identifier")) or next
102
+ lbl = @xrefs.anchor(@reqt_ids[id.text.strip][:id], :xref, false)
103
+ next unless lbl
104
+
105
+ m[id1.text] = { lbl: lbl, id: r["id"] }
106
+ end
107
+ end
108
+ end
109
+
110
+ def recommendation_link_class(ident)
111
+ test = @reqt_links_class[ident&.strip] or return nil
112
+ "<xref target='#{test[:id]}'>#{test[:lbl]}</xref>"
113
+ end
114
+
115
+ def recommendation_id(ident)
75
116
  test = @reqt_ids[ident&.strip] or return ident&.strip
76
- "<xref target='#{test}'>#{ident.strip}</xref>"
117
+ "<xref target='#{test[:id]}'>#{test[:lbl]}</xref>"
77
118
  end
78
119
  end
79
120
  end
@@ -0,0 +1,111 @@
1
+ module Metanorma
2
+ class Requirements
3
+ class Modspec < Default
4
+ def validate(reqt, log)
5
+ @log ||= log
6
+ @ids ||= reqt_links(reqt.document)
7
+ reqt_link_validate(reqt)
8
+ end
9
+
10
+ def nested_reqt?(reqt)
11
+ reqt.at("./ancestor::requirement | ./ancestor::recommendation | "\
12
+ "./ancestor::permission")
13
+ end
14
+
15
+ def reqt_link_validate(reqt)
16
+ return if nested_reqt?(reqt)
17
+
18
+ reqt_to_conformance(reqt, "general", "verification")
19
+ reqt_to_conformance(reqt, "class", "conformanceclass")
20
+ conformance_to_reqt(reqt, "general", "verification")
21
+ conformance_to_reqt(reqt, "class", "conformanceclass")
22
+ class_to_children(reqt, "class", "general")
23
+ class_to_children(reqt, "conformanceclass", "verification")
24
+ children_to_class(reqt, "verification", "conformanceclass")
25
+ end
26
+
27
+ def type2validate(reqt)
28
+ type = reqt["type"]
29
+ type = "general" if type.nil? || type.empty?
30
+ type
31
+ end
32
+
33
+ CLASS2LABEL = {
34
+ general: "Requirement",
35
+ verification: "Conformance test",
36
+ class: "Requirement class",
37
+ conformanceclass: "Conformance class",
38
+ }.freeze
39
+
40
+ def log_reqt(reqt, leftclass, rightclass)
41
+ @log.add("Requirements", reqt[:elem],
42
+ "#{CLASS2LABEL[leftclass.to_sym]} #{reqt[:label] || reqt[:id]} "\
43
+ "has no corresponding #{CLASS2LABEL[rightclass.to_sym]}")
44
+ end
45
+
46
+ def reqt_to_conformance(reqt, reqtclass, confclass)
47
+ return unless type2validate(reqt) == reqtclass
48
+
49
+ r = @ids[:id][reqt["id"]]
50
+ (r[:label] && @ids[:class][confclass]&.any? do |x|
51
+ x[:subject] == r[:label]
52
+ end) and return
53
+ log_reqt(r, reqtclass, confclass)
54
+ end
55
+
56
+ def conformance_to_reqt(reqt, reqtclass, confclass)
57
+ return unless type2validate(reqt) == confclass
58
+
59
+ r = @ids[:id][reqt["id"]]
60
+ (r[:subject] && @ids[:class][reqtclass]&.any? do |x|
61
+ r[:subject] == x[:label]
62
+ end) and return
63
+ log_reqt(r, confclass, reqtclass)
64
+ end
65
+
66
+ def class_to_children(reqt, type, childclass)
67
+ return unless type2validate(reqt) == type
68
+
69
+ r = @ids[:id][reqt["id"]]
70
+ !r[:child].empty? and return
71
+ log_reqt(r, type, childclass)
72
+ end
73
+
74
+ def children_to_class(reqt, childclass, parentclass)
75
+ return unless type2validate(reqt) == childclass
76
+
77
+ r = @ids[:id][reqt["id"]]
78
+ (r[:label] && @ids[:class][parentclass]&.any? do |x|
79
+ x[:child].include?(r[:label])
80
+ end) and return
81
+ log_reqt(r, childclass, parentclass)
82
+ end
83
+
84
+ def reqt_links(docxml)
85
+ docxml.xpath("//requirement | //recommendation | //permission")
86
+ .each_with_object({ id: {}, class: {} }) do |r, m|
87
+ next if nested_reqt?(r)
88
+
89
+ reqt_links1(r, m)
90
+ end
91
+ end
92
+
93
+ def reqt_links1(reqt, hash)
94
+ type = type2validate(reqt)
95
+ hash[:id][reqt["id"]] = reqt_links_struct(reqt)
96
+ hash[:class][type] ||= []
97
+ hash[:class][type] << hash[:id][reqt["id"]]
98
+ hash
99
+ end
100
+
101
+ def reqt_links_struct(reqt)
102
+ { id: reqt["id"], elem: reqt, label: reqt.at("./identifier")&.text,
103
+ subject: reqt.at("./classification[tag = 'target']/value")&.text,
104
+ child: reqt.xpath("./requirement | ./recommendation | ./permission")
105
+ .map do |r|
106
+ r.at("./identifier")&.text
107
+ end }
108
+ end
109
+ end
110
+ end
111
+ end
@@ -3,38 +3,38 @@ module Metanorma
3
3
  class Modspec < Default
4
4
  def req_class_paths
5
5
  [
6
- { klass: "permissionclass", label: "permissionclass",
6
+ { klass: "permissionclass", label: @labels["modspec"]["permissionclass"],
7
7
  xpath: "permission[@type = 'class']" },
8
- { klass: "requirementclass", label: "requirementclass",
8
+ { klass: "requirementclass", label: @labels["modspec"]["requirementclass"],
9
9
  xpath: "requirement[@type = 'class']" },
10
- { klass: "recommendationclass", label: "recommendationclass",
10
+ { klass: "recommendationclass", label: @labels["modspec"]["recommendationclass"],
11
11
  xpath: "recommendation[@type = 'class']" },
12
- { klass: "permissiontest", label: "permissiontest",
12
+ { klass: "permissiontest", label: @labels["modspec"]["permissiontest"],
13
13
  xpath: "permission[@type = 'verification']" },
14
- { klass: "recommendationtest", label: "recommendationtest",
14
+ { klass: "recommendationtest", label: @labels["modspec"]["recommendationtest"],
15
15
  xpath: "recommendation[@type = 'verification']" },
16
- { klass: "requirementtest", label: "requirementtest",
16
+ { klass: "requirementtest", label: @labels["modspec"]["requirementtest"],
17
17
  xpath: "requirement[@type = 'verification']" },
18
- { klass: "abstracttest", label: "abstracttest",
18
+ { klass: "abstracttest", label: @labels["modspec"]["abstracttest"],
19
19
  xpath: "permission[@type = 'abstracttest']" },
20
- { klass: "abstracttest", label: "abstracttest",
20
+ { klass: "abstracttest", label: @labels["modspec"]["abstracttest"],
21
21
  xpath: "requirement[@type = 'abstracttest']" },
22
- { klass: "abstracttest", label: "abstracttest",
22
+ { klass: "abstracttest", label: @labels["modspec"]["abstracttest"],
23
23
  xpath: "recommendation[@type = 'abstracttest']" },
24
- { klass: "conformanceclass", label: "conformanceclass",
24
+ { klass: "conformanceclass", label: @labels["modspec"]["conformanceclass"],
25
25
  xpath: "permission[@type = 'conformanceclass']" },
26
- { klass: "conformanceclass", label: "conformanceclass",
26
+ { klass: "conformanceclass", label: @labels["modspec"]["conformanceclass"],
27
27
  xpath: "requirement[@type = 'conformanceclass']" },
28
- { klass: "conformanceclass", label: "conformanceclass",
28
+ { klass: "conformanceclass", label: @labels["modspec"]["conformanceclass"],
29
29
  xpath: "recommendation[@type = 'conformanceclass']" },
30
- { klass: "permission", label: "permission",
30
+ { klass: "permission", label: @labels["default"]["permission"],
31
31
  xpath: "permission[not(@type = 'verification' or @type = 'class' "\
32
32
  "or @type = 'abstracttest' or @type = 'conformanceclass')]" },
33
- { klass: "recommendation", label: "recommendation",
33
+ { klass: "recommendation", label: @labels["default"]["recommendation"],
34
34
  xpath: "recommendation[not(@type = 'verification' or "\
35
35
  "@type = 'class' or @type = 'abstracttest' or "\
36
36
  "@type = 'conformanceclass')]" },
37
- { klass: "requirement", label: "requirement",
37
+ { klass: "requirement", label: @labels["default"]["requirement"],
38
38
  xpath: "requirement[not(@type = 'verification' or @type = 'class' "\
39
39
  "or @type = 'abstracttest' or @type = 'conformanceclass')]" },
40
40
  ]
@@ -1,6 +1,6 @@
1
1
  require_relative "../default/default"
2
2
  require_relative "../modspec/modspec"
3
- require "isodoc-i18n"
3
+ require_relative "../../isodoc/i18n"
4
4
 
5
5
  module Metanorma
6
6
  class Requirements
@@ -8,9 +8,10 @@ module Metanorma
8
8
 
9
9
  def initialize(options)
10
10
  @default = options[:default]
11
- @i18n = ::IsoDoc::I18n.new(options[:lang] || "en",
12
- options[:script] || "Latn")
13
- @labels = options[:labels]
11
+ @i18n = i18n_klass(options[:lang] || "en",
12
+ options[:script] || "Latn",
13
+ options[:i18nhash])
14
+ @labels = @i18n.get.deep_merge(options[:labels] || {})["requirements"]
14
15
  @models = {}
15
16
  model_names.each { |k| @models[k] = create(k) }
16
17
  end
@@ -19,6 +20,10 @@ module Metanorma
19
20
  %i[default ogc]
20
21
  end
21
22
 
23
+ def i18n_klass(lang = "en", script = "Latn", i18nhash = nil)
24
+ ::IsoDoc::MnRequirementsI18n.new(lang, script, i18nhash: i18nhash)
25
+ end
26
+
22
27
  # all roles that can be assigned to an example to make it a reqt,
23
28
  # across all models (because the model may not be an attribute but
24
29
  # embedded in the definition list). Mapped to obligation
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  class Requirements
3
- VERSION = "0.0.1".freeze
4
- end
5
- end
3
+ VERSION = "0.1.1".freeze
4
+ end
5
+ end
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
26
26
 
27
27
  spec.add_dependency "isodoc-i18n", "~> 1.0.0"
28
- spec.add_dependency "metanorma-utils", "~> 1.3.0"
28
+ spec.add_dependency "metanorma-utils", "~> 1.3.2"
29
29
 
30
30
  spec.add_development_dependency "debug"
31
31
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
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.0.1
4
+ version: 0.1.1
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-08-22 00:00:00.000000000 Z
11
+ date: 2022-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: isodoc-i18n
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.3.0
33
+ version: 1.3.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.3.0
40
+ version: 1.3.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: debug
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -227,6 +227,14 @@ files:
227
227
  - bin/console
228
228
  - bin/rspec
229
229
  - bin/setup
230
+ - lib/isodoc-yaml/i18n-ar.yaml
231
+ - lib/isodoc-yaml/i18n-de.yaml
232
+ - lib/isodoc-yaml/i18n-en.yaml
233
+ - lib/isodoc-yaml/i18n-es.yaml
234
+ - lib/isodoc-yaml/i18n-fr.yaml
235
+ - lib/isodoc-yaml/i18n-ru.yaml
236
+ - lib/isodoc-yaml/i18n-zh-Hans.yaml
237
+ - lib/isodoc/i18n.rb
230
238
  - lib/metanorma/default/cleanup.rb
231
239
  - lib/metanorma/default/default.rb
232
240
  - lib/metanorma/default/isodoc.rb
@@ -236,6 +244,7 @@ files:
236
244
  - lib/metanorma/modspec/isodoc.rb
237
245
  - lib/metanorma/modspec/modspec.rb
238
246
  - lib/metanorma/modspec/reqt_label.rb
247
+ - lib/metanorma/modspec/validate.rb
239
248
  - lib/metanorma/modspec/xrefs.rb
240
249
  - lib/metanorma/requirements/selector.rb
241
250
  - lib/metanorma/requirements/version.rb