mn-requirements 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.adoc +2 -2
- data/lib/isodoc/i18n.rb +23 -0
- data/lib/isodoc-yaml/i18n-ar.yaml +26 -0
- data/lib/isodoc-yaml/i18n-de.yaml +27 -0
- data/lib/isodoc-yaml/i18n-en.yaml +27 -0
- data/lib/isodoc-yaml/i18n-es.yaml +27 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +27 -0
- data/lib/isodoc-yaml/i18n-ru.yaml +27 -0
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +27 -0
- data/lib/metanorma/default/default.rb +2 -0
- data/lib/metanorma/default/isodoc.rb +3 -3
- data/lib/metanorma/default/xrefs.rb +6 -6
- data/lib/metanorma/modspec/cleanup.rb +1 -2
- data/lib/metanorma/modspec/isodoc.rb +60 -59
- data/lib/metanorma/modspec/modspec.rb +1 -0
- data/lib/metanorma/modspec/reqt_label.rb +66 -26
- data/lib/metanorma/modspec/validate.rb +111 -0
- data/lib/metanorma/modspec/xrefs.rb +15 -15
- data/lib/metanorma/requirements/selector.rb +9 -4
- data/lib/metanorma/requirements/version.rb +3 -3
- data/mn-requirements.gemspec +1 -1
- metadata +13 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0e6c91b33ab3f3b3eb4ce26df120009dfe92441024891d766115421023630ea
|
4
|
+
data.tar.gz: 800e1d60081b242bd3aa921004839ac0cabbcde5102a6d8c29d1d652e22b5cfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad9db2b90feb438a6e146cc943585ccaf81b525147b9556860f11175976e65c247b44d2d084cfcae43b9d89fbba7d9b7bab8fef00f5d2051ea7ed1fd450b0c77
|
7
|
+
data.tar.gz: 4d875db98cb7ef2942ead616f49268314a12e592aecd5422b7f586fd98cf8fdf485d752e2fdf522dd9dc4640aab1f5e9e12e5c79dff6debbd9f17687396b3b32
|
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
|
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,
|
23
|
+
[requirement,model=ogc]
|
24
24
|
...
|
25
25
|
...
|
26
26
|
----
|
data/lib/isodoc/i18n.rb
ADDED
@@ -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
|
+
|
@@ -56,12 +56,12 @@ module Metanorma
|
|
56
56
|
|
57
57
|
def recommendation_attributes1(node, out)
|
58
58
|
oblig = node["obligation"] and
|
59
|
-
out << l10n("#{@labels['obligation']}: #{oblig}")
|
59
|
+
out << l10n("#{@labels['default']['obligation']}: #{oblig}")
|
60
60
|
node.xpath(ns("./subject")).each do |subj|
|
61
|
-
out << l10n("#{@labels['subject']}: #{subj.text}")
|
61
|
+
out << l10n("#{@labels['default']['subject']}: #{subj.text}")
|
62
62
|
end
|
63
63
|
node.xpath(ns("./inherit")).each do |i|
|
64
|
-
out << recommendation_attr_parse(i, @labels["inherits"])
|
64
|
+
out << recommendation_attr_parse(i, @labels["default"]["inherits"])
|
65
65
|
end
|
66
66
|
node.xpath(ns("./classification")).each do |c|
|
67
67
|
out << recommendation_attr_keyvalue(c, "tag", "value")
|
@@ -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
|
@@ -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,
|
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"] =
|
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(
|
33
|
-
|
34
|
-
|
35
|
-
|
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,
|
40
|
-
|
41
|
-
name = node.at(ns("./name")) and name.children.
|
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
|
-
|
49
|
-
title.children.
|
54
|
+
ret += l10n(": ") if name
|
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
|
-
|
64
|
-
|
65
|
-
p["class"] = "RecommendationLabel"
|
66
|
-
p << label.children.to_xml
|
70
|
+
out.add_child("<tr><td>#{@labels['modspec']['identifier']}</td>"\
|
71
|
+
"<td><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
|
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(
|
89
|
+
xref = recommendation_id(v.text) and head << [
|
84
90
|
rec_target(node), xref
|
85
91
|
]
|
86
92
|
end
|
87
|
-
|
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 << ["
|
97
|
-
recommendation_id(
|
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(
|
102
|
-
head << ["
|
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.
|
175
|
-
|
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 "
|
201
|
-
else "
|
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 "
|
208
|
-
when "conformanceclass" then "
|
209
|
-
when "verification", "abstracttest" then "
|
210
|
-
else "
|
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
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
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
|
@@ -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
|
-
|
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
|
16
|
-
@reqtlabels
|
17
|
-
|
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("./
|
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
|
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
|
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
|
@@ -50,28 +69,49 @@ module Metanorma
|
|
50
69
|
end
|
51
70
|
end
|
52
71
|
|
53
|
-
def
|
72
|
+
def reqt_links_test(docxml)
|
54
73
|
docxml.xpath(ns("//requirement | //recommendation | //permission"))
|
55
74
|
.each_with_object({}) do |r, m|
|
56
75
|
next unless %w(conformanceclass
|
57
76
|
verification).include?(r["type"])
|
58
77
|
|
59
78
|
subj = r.at(ns("./classification[tag = 'target']/value"))
|
60
|
-
id = r.at(ns("./identifier"))
|
61
|
-
|
79
|
+
id = r.at(ns("./identifier")) or next
|
80
|
+
lbl = @xrefs.anchor(@reqt_ids[id.text.strip], :xref, false)
|
81
|
+
next unless subj && lbl
|
82
|
+
|
83
|
+
m[subj.text] = { lbl: lbl, id: r["id"] }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def recommendation_link_test(ident)
|
88
|
+
test = @reqt_links_test[ident&.strip] or return nil
|
89
|
+
"<xref target='#{test[:id]}'>#{test[:lbl]}</xref>"
|
90
|
+
end
|
91
|
+
|
92
|
+
def reqt_links_class(docxml)
|
93
|
+
docxml.xpath(ns("//requirement | //recommendation | //permission"))
|
94
|
+
.each_with_object({}) do |r, m|
|
95
|
+
next unless %w(class conformanceclass).include?(r["type"])
|
96
|
+
|
97
|
+
id = r.at(ns("./identifier")) or next
|
98
|
+
r.xpath(ns("./requirement | ./recommendation | ./permission"))
|
99
|
+
.each do |r1|
|
100
|
+
id1 = r1.at(ns("./identifier")) or next
|
101
|
+
lbl = @xrefs.anchor(@reqt_ids[id.text.strip], :xref, false)
|
102
|
+
next unless lbl
|
62
103
|
|
63
|
-
|
104
|
+
m[id1.text] = { lbl: lbl, id: r["id"] }
|
105
|
+
end
|
64
106
|
end
|
65
107
|
end
|
66
108
|
|
67
|
-
def
|
68
|
-
@
|
69
|
-
test = @reqt_links[ident&.strip] or return nil
|
109
|
+
def recommendation_link_class(ident)
|
110
|
+
test = @reqt_links_class[ident&.strip] or return nil
|
70
111
|
"<xref target='#{test[:id]}'>#{test[:lbl]}</xref>"
|
71
112
|
end
|
72
113
|
|
73
|
-
def recommendation_id(
|
74
|
-
@reqt_ids ||= reqt_ids(docxml)
|
114
|
+
def recommendation_id(ident)
|
75
115
|
test = @reqt_ids[ident&.strip] or return ident&.strip
|
76
116
|
"<xref target='#{test}'>#{ident.strip}</xref>"
|
77
117
|
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
|
-
|
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 =
|
12
|
-
|
13
|
-
|
11
|
+
@i18n = i18n_klass(options[:lang] || "en",
|
12
|
+
options[:script] || "Latn",
|
13
|
+
options[:i18nhash])
|
14
|
+
@labels = @i18n.get.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
|
data/mn-requirements.gemspec
CHANGED
@@ -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.
|
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
|
4
|
+
version: 0.1.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-08-
|
11
|
+
date: 2022-08-30 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.
|
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.
|
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
|