module Metanorma
class Requirements
class Modspec < Default
REQT_TYPE_NORM = {
requirement: "general",
recommendation: "general",
permission: "general",
requirements_class: "class",
requirement_class: "class",
recommendation_class: "class",
permission_class: "class",
conformance_test: "verification",
conformance_class: "conformanceclass",
abstract_test: "abstracttest",
}.freeze
def requirement_type_cleanup(reqt)
ret = REQT_TYPE_NORM[reqt["type"]&.to_sym] or return
reqt["type"] = ret
end
def requirement_metadata_component_tags
%w(test-purpose test-method test-method-type conditions part description
statement reference step guidance) +
requirement_metadata_requirement_tags
end
def requirement_metadata_requirement_tags
%w(conformance-test conformance-class abstract-test requirement-class
recommendation-class permission-class requirement permission
recommendation)
end
def requirement_metadata1(reqt, dlist, ins)
ins1 = super
dlist.xpath("./dt").each do |e|
tag = e.text&.gsub(/ /, "-")&.downcase
tag = "description" if tag == "statement"
next unless requirement_metadata_component_tags.include?(tag)
ins1.next = requirement_metadata1_component(e, tag)
ins1 = ins1.next
end
end
def requirement_metadata1_component(term, tag)
val = term.at("./following::dd")
val.name = tag
val.xpath("./dl").each do |d|
requirement_metadata1(val, d, d)
d.remove
end
requirement_metadata_requirement_tags.include?(term.text) or
return val
requirement_metadata1_component_val2id(val)
end
def requirement_metadata1_component_val2id(val)
if val.at(".//link") && val.text.strip.empty?
val.children = "#{val.at('.//link')['target']}"
elsif !val.text.strip.empty?
val.children = "#{val.text.strip}"
end
val
end
# separate from default model requirement_metadata_cleanup,
# which extracts model:: ogc into reqt["model"]
def requirement_metadata_cleanup(reqt)
super
requirement_metadata_to_component(reqt)
requirement_metadata_to_requirement(reqt)
requirement_subparts_to_blocks(reqt)
requirement_target_identifiers(reqt)
requirement_anchor_identifier(reqt)
end
def requirement_anchor_identifier(reqt)
Metanorma::Utils::guid_anchor?(reqt["id"]) or return
id = reqt.at("./identifier") or return
anchor = id.text.strip
anchor.empty? and return
reqt["id"] = Metanorma::Utils::to_ncname(anchor)
end
def requirement_target_identifiers(reqt)
reqt.xpath("./classification[tag][value/link]").each do |c|
%w(target indirect-dependency implements identifier-base)
.include?(c.at("./tag").text.downcase) or next
v = c.at("./value[link]")
v.children = v.at("./link/@target").text
end
end
def requirement_metadata_to_component(reqt)
xpath = requirement_metadata_component_tags - %w(statement description) -
requirement_metadata_requirement_tags
reqt.xpath(xpath.map { |x| ".//#{x}" }.join(" | ")).each do |c|
c["class"] = c.name
c.name = "component"
end
end
def requirement_metadata_to_requirement(reqt)
xpath = requirement_metadata_requirement_tags
reqt.xpath(xpath.map { |x| "./#{x}" }.join(" | ")).each do |c|
c["id"] = Metanorma::Utils::anchor_or_uuid
c["model"] = reqt["model"] # all requirements must have a model
requirement_metadata_to_requirement1(c)
end
end
def requirement_metadata_to_requirement1(reqt)
reqt["type"] = reqt.name.sub(/-/, "_")
reqt.name =
case reqt.name
when "recommendation-class", "recommendation" then "recommendation"
when "permission-class", "permission" then "permission"
else "requirement"
end
requirement_type_cleanup(reqt)
end
def requirement_subparts_to_blocks(reqt)
reqt.xpath(".//component | .//description").each do |c|
next if %w(p ol ul dl table component description)
.include?(c&.elements&.first&.name)
c.children = "
#{c.children.to_xml}
"
end
end
def add_misc_container(xmldoc)
unless ins = xmldoc.at("//metanorma-extension")
a = xmldoc.at("//termdocsource") || xmldoc.at("//bibdata")
a.next = ""
ins = xmldoc.at("//metanorma-extension")
end
ins
end
def add_misccontainer_anchor_aliases(xmldoc)
m = add_misc_container(xmldoc)
x = ".//table[@id = '_misccontainer_anchor_aliases']/tbody"
unless ins = m.at(x)
m << ""
ins = m.at(x)
end
ins
end
def requirement_anchor_aliases(reqt)
x = reqt.xpath("./identifier")
x.empty? and return
table = add_misccontainer_anchor_aliases(reqt.document)
ids = x.each_with_object([]) do |i, m|
m << "#{i.text} | "
end
table << "#{reqt['id']} | #{ids.join}
"
end
def requirement_identifier_cleanup(reqt)
super
requirement_anchor_aliases(reqt)
end
end
end
end