Class: Metanorma::Ogc::Converter

Inherits:
Standoc::Converter
  • Object
show all
Defined in:
lib/metanorma/ogc/log.rb,
lib/metanorma/ogc/front.rb,
lib/metanorma/ogc/sections.rb,
lib/metanorma/ogc/converter.rb

Constant Summary collapse

OGC_LOG_MESSAGES =
{
  # rubocop:disable Naming/VariableNumber
  "OGC_1": { category: "Document Attributes",
             error: "%s is not a recognised status",
             severity: 2 },
  "OGC_2": { category: "Document Attributes",
             error: "%s is not an allowed status for %s",
             severity: 2 },
  "OGC_3": { category: "Document Attributes",
             error: "Version not permitted for %s",
             severity: 2 },
  "OGC_4": { category: "Document Attributes",
             error: "Version required for %s",
             severity: 2 },
  "OGC_5": { category: "Style",
             error: "Executive Summary required for Engineering Reports!",
             severity: 2 },
  "OGC_6": { category: "Style",
             error: "Executive Summary only allowed for Engineering Reports!",
             severity: 2 },
  "OGC_7": { category: "Style",
             error: "(section sequencing) %s",
             severity: 2 },
  "OGC_8": { category: "Style",
             error: "Document must contain at least one clause",
             severity: 2 },
  "OGC_9": { category: "Style",
             error: "Normative References are mandatory",
             severity: 2 },
  "OGC_10": { category: "Style",
              error: "Abstract is missing!",
              severity: 2 },
  "OGC_11": { category: "Style",
              error: "Keywords are missing!",
              severity: 2 },
  "OGC_12": { category: "Style",
              error: "Preface is missing!",
              severity: 2 },
  "OGC_13": { category: "Style",
              error: "Submitting Organizations is missing!",
              severity: 2 },
  "OGC_14": { category: "Style",
              error: "Submitters is missing!",
              severity: 2 },
  "OGC_15": { category: "Bibliography",
              error: "Engineering report should not contain normative references",
              severity: 2 },
  "OGC_16": { category: "Document Attributes",
              error: "'%s' is not a legal document type: reverting to 'standard'",
              severity: 2 },
  "OGC_17": { category: "Document Attributes",
              error: "'%s' is not a permitted subtype of Standard: reverting to 'implementation'",
              severity: 2 },
  "OGC_18": { category: "Document Attributes",
              error: "'%s' is not a permitted subtype of best-practice: reverting to 'general'",
              severity: 2 },
}.freeze
OGC_COLORS =
{
  text: "rgb(88, 89, 91)",
  "secondary-shade-1": "rgb(237, 193, 35)",
  "secondary-shade-2": "rgb(246, 223, 140)",
  "background-definition-term": "rgb(215, 243, 255)",
  "background-definition-description": "rgb(242, 251, 255)",
  "text-title": "rgb(33, 55, 92)",
  "background-page": "rgb(33, 55, 92)",
  "background-text-label-legacy": "rgb(33, 60, 107)",
  "background-term-preferred-label": "rgb(249, 235, 187)",
  "background-term-deprecated-label": "rgb(237, 237, 238)",
  "background-term-admitted-label": "rgb(223, 236, 249)",
  "background-table-header": "rgb(33, 55, 92)",
  "background-table-row-even": "rgb(252, 246, 222)",
  "background-table-row-odd": "rgb(254, 252, 245)",
  "admonition-note": "rgb(79, 129, 189)",
  "admonition-tip": "rgb(79, 129, 189)",
  "admonition-editor": "rgb(79, 129, 189)",
  "admonition-important": "rgb(79, 129, 189)",
  "admonition-warning": "rgb(79, 129, 189)",
  "admonition-caution": "rgb(79, 129, 189)",
  "admonition-todo": "rgb(79, 129, 189)",
  "admonition-safety-precaution": "rgb(79, 129, 189)",
}.freeze

Instance Method Summary collapse

Instance Method Details

#adoc2xml(text, flavour) ⇒ Object

preempt subdoctype warning



164
165
166
167
168
169
170
171
172
173
# File 'lib/metanorma/ogc/converter.rb', line 164

def adoc2xml(text, flavour)
  Nokogiri::XML(text).root and return text
  c = isolated_asciidoctor_convert(
    "= X\nA\n:semantic-metadata-headless: true\n" \
    ":novalid:\n:docsubtype: implementation\n" \
    ":doctype: standard\n\n#{text}\n",
    backend: flavour, header_footer: true,
  )
  Nokogiri::XML(c).at("//xmlns:sections")
end

#boilerplate_file(_xmldoc) ⇒ Object



24
25
26
# File 'lib/metanorma/ogc/converter.rb', line 24

def boilerplate_file(_xmldoc)
  File.join(@libdir, "boilerplate.adoc")
end

#clause_parse(attrs, xml, node) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/metanorma/ogc/sections.rb', line 48

def clause_parse(attrs, xml, node)
  %w(overview future_outlook value_proposition
     contributors aims objectives topics outlook security)
    .include?(node.attr("type")) and
    attrs = attrs.merge(type: node.attr("type"))
  case node.attr("heading")&.downcase || node.title.downcase
  when "submitters"
    return submitters_parse(attrs.merge(type: "submitters"), xml, node)
  when "contributors"
    return submitters_parse(attrs.merge(type: "contributors"), xml, node)
  when "conformance" then attrs = attrs.merge(type: "conformance")
  when "security considerations"
    attrs = attrs.merge(type: "security")
  end
  super
end

#default_publisherObject



75
76
77
# File 'lib/metanorma/ogc/front.rb', line 75

def default_publisher
  "OGC"
end

#default_requirement_modelObject



20
21
22
# File 'lib/metanorma/ogc/converter.rb', line 20

def default_requirement_model
  "ogc"
end

#doc_converter(node) ⇒ Object



159
160
161
# File 'lib/metanorma/ogc/converter.rb', line 159

def doc_converter(node)
  IsoDoc::Ogc::WordConvert.new(doc_extract_attributes(node))
end

#doctype(node) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/metanorma/ogc/converter.rb', line 28

def doctype(node)
  d = super
  d1 = ::IsoDoc::Ogc::DOCTYPE_ABBR.invert[d] and d = d1
  unless %w{abstract-specification-topic best-practice other policy
            change-request-supporting-document community-practice
            community-standard discussion-paper engineering-report
            reference-model release-notes standard user-guide white-paper
            technical-paper test-suite draft-standard}.include? d
    @warned_doctype or
      @log.add("OGC_16", nil, params: [d])
    @warned_doctype = true
    d = @default_doctype
  end
  d
end

#document_scheme(node) ⇒ Object



44
45
46
47
48
49
50
51
# File 'lib/metanorma/ogc/converter.rb', line 44

def document_scheme(node)
  if r = node.attr("document-scheme")
    %w(2026 2022 2018).include?(r) ? r : "2026"
  elsif r = node.attr("published-date") || node.attr("copyright-year")
    published_date_scheme(r)
  else "2026"
  end
end

#externalid(node) ⇒ Object



94
95
96
97
98
99
100
101
102
# File 'lib/metanorma/ogc/front.rb', line 94

def externalid(node)
  i = node.attr("external-id") and return i
  d = doctype(node)
  a = node.attr("abbrev")
  d && a or return
  url = "http://www.opengis.net/doc/#{IsoDoc::Ogc::DOCTYPE_ABBR[d]}/#{a}"
  v = node.attr("edition") || node.attr("version") and url += "/#{v}"
  url
end

#externalurl(node) ⇒ Object



124
125
126
127
128
129
130
# File 'lib/metanorma/ogc/front.rb', line 124

def externalurl(node)
  if doctype(node) == "engineering-report"
    "http://www.opengis.net/doc/PER/t14-#{node.attr('referenceurlid')}"
  else
    node.attr("referenceurlid")
  end
end

#html_converter(node) ⇒ Object



149
150
151
# File 'lib/metanorma/ogc/converter.rb', line 149

def html_converter(node)
  IsoDoc::Ogc::HtmlConvert.new(html_extract_attributes(node))
end

#init_toc(node) ⇒ Object



13
14
15
16
17
18
# File 'lib/metanorma/ogc/converter.rb', line 13

def init_toc(node)
  super
  @tocfigures = true
  @toctables = true
  @tocrecommendations = true
end

#log_messagesObject

rubocop:enable Naming/VariableNumber



63
64
65
# File 'lib/metanorma/ogc/log.rb', line 63

def log_messages
  super.merge(OGC_LOG_MESSAGES)
end

#metadata_attrs(node) ⇒ Object



120
121
122
123
124
125
126
127
128
# File 'lib/metanorma/ogc/converter.rb', line 120

def (node)
  c = update_colors(node)
  ret = super
  c.keys.sort.each do |k|
    ret += "<presentation-metadata><color-#{k}>" \
           "#{c[k]}</color-#{k}></presentation-metadata>"
  end
  ret
end

#metadata_committee_prep(node) ⇒ Object



87
88
89
90
91
92
# File 'lib/metanorma/ogc/front.rb', line 87

def (node)
  node.attr("committee") or node.set_attribute("committee", "technical")
  a = node.attr("workinggroup") and
    node.set_attribute("workgroup", a)
  true
end

#metadata_committee_types(_node) ⇒ Object



83
84
85
# File 'lib/metanorma/ogc/front.rb', line 83

def (_node)
  %w(committee subcommittee workgroup)
end


137
138
139
140
141
# File 'lib/metanorma/ogc/front.rb', line 137

def (node, xml)
  node.attr("copyrightyear") and
    node.set_attr("copyright-year", node.attr("copyrightyear"))
  super
end

#metadata_date(node, xml) ⇒ Object



143
144
145
146
147
148
# File 'lib/metanorma/ogc/front.rb', line 143

def (node, xml)
  super
  ogc_date(node, xml, "submissiondate", "received")
  ogc_date(node, xml, "publicationdate", "published")
  ogc_date(node, xml, "approvaldate", "issued")
end

#metadata_id_nonprimary(node, xml) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/metanorma/ogc/front.rb', line 104

def (node, xml)
  add_noko_elem(xml, "docidentifier", externalid(node),
                type: "ogc-external")
  node.attr("referenceurlid") and
    add_noko_elem(xml, "docidentifier", externalurl(node),
                  type: "ogc-external")
end

#metadata_id_primary(node, xml) ⇒ Object



116
117
118
119
120
121
122
# File 'lib/metanorma/ogc/front.rb', line 116

def (node, xml)
  id = node.attr("docidentifier") || node.attr("docnumber") ||
    node.attr("docreference")
  add_noko_elem(xml, "docidentifier", id,
                type: (node),
                primary: "true")
end

#metadata_id_primary_type(_node) ⇒ Object



112
113
114
# File 'lib/metanorma/ogc/front.rb', line 112

def (_node)
  "ogc-internal"
end

#metadata_source(node, xml) ⇒ Object



132
133
134
135
# File 'lib/metanorma/ogc/front.rb', line 132

def (node, xml)
  super
  add_noko_elem(xml, "uri", node.attr("previous-uri"), type: "previous")
end

#metadata_subdoctype(node, xml) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/metanorma/ogc/front.rb', line 164

def (node, xml)
  s = node.attr("docsubtype")
  s1 = ::IsoDoc::Ogc::DOCSUBTYPE_ABBR.invert[s] and s = s1
  case doctype(node)
  when "standard"
    unless %w{conceptual-model conceptual-model-and-encoding
              conceptual-model-and-implementation encoding extension
              implementation profile profile-with-extension}.include? s
      @log.add("OGC_17", nil, params: [s])
      s = "implementation"
    end
  when "best-practice"
    unless %w{general encoding extension profile
              profile-with-extension}.include? s
      @log.add("OGC_18", nil, params: [s])
      s = "general"
    end
  end
  s && !s.empty? and xml.subdoctype s
end

#metadata_version(node, xml) ⇒ Object



158
159
160
161
162
# File 'lib/metanorma/ogc/front.rb', line 158

def (node, xml)
  node.attr("version") and
    node.set_attr("edition", node.attr("version"), false)
  super
end

#ogc_date(node, xml, ogcname, metanormaname) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/metanorma/ogc/front.rb', line 150

def ogc_date(node, xml, ogcname, metanormaname)
  if node.attr(ogcname)
    xml.date type: metanormaname do |d|
      add_noko_elem(d, "on", node.attr(ogcname))
    end
  end
end

#ogc_editor(node, xml) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/metanorma/ogc/front.rb', line 43

def ogc_editor(node, xml)
  node.attr("editor") or return
  xml.contributor do |c|
    c.role type: "editor"
    c.person do |p|
      p.name do |n|
        add_noko_elem(n, "completename", node.attr("editor"))
      end
    end
  end
end

#org_abbrevObject



79
80
81
# File 'lib/metanorma/ogc/front.rb', line 79

def org_abbrev
  { "Open Geospatial Consortium" => "OGC" }
end

#org_author(node, xml) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/metanorma/ogc/front.rb', line 8

def org_author(node, xml)
  node.attr("submitting-organizations") or return
  csv_split(@c.decode(node.attr("submitting-organizations")),
            ";")&.each do |org|
    xml.contributor do |c|
      c.role type: "author"
      c.organization do |a|
        add_noko_elem(a, "name", org)
      end
    end
  end
end

#outputs(node, ret) ⇒ Object



75
76
77
78
79
80
81
82
83
84
# File 'lib/metanorma/ogc/converter.rb', line 75

def outputs(node, ret)
  File.open("#{@filename}.xml", "w:UTF-8") { |f| f.write(ret) }
  presentation_xml_converter(node).convert("#{@filename}.xml")
  html_converter(node).convert("#{@filename}.presentation.xml", nil,
                               false, "#{@filename}.html")
  doc_converter(node).convert("#{@filename}.presentation.xml", nil,
                              false, "#{@filename}.doc")
  pdf_converter(node)&.convert("#{@filename}.presentation.xml", nil,
                               false, "#{@filename}.pdf")
end

#override_style(node) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/metanorma/ogc/sections.rb', line 20

def override_style(node)
  s = node.attr("style")
  if %w(overview future_outlook value_proposition
        contributors).include?(s)
    node.set_attr("style", "preface")
    node.set_attr("type", s)
  end
  if %w(aims objectives topics outlook security).include?(s)
    node.set_attr("type", s)
  end
end

#parse_flexible_date(date_str) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/metanorma/ogc/converter.rb', line 63

def parse_flexible_date(date_str)
  case date_str
  when /^\d{4}$/
    Date.new(date_str.to_i, 1, 1)
  when /^\d{4}-\d{2}$/
    year, month = date_str.split("-").map(&:to_i)
    Date.new(year, month, 1)
  else
    Date.parse(date_str)
  end
end

#pdf_converter(node) ⇒ Object



153
154
155
156
157
# File 'lib/metanorma/ogc/converter.rb', line 153

def pdf_converter(node)
  return nil if node.attr("no-pdf")

  IsoDoc::Ogc::PdfConvert.new(pdf_extract_attributes(node))
end

#personal_author(node, xml) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/metanorma/ogc/front.rb', line 21

def personal_author(node, xml)
  ogc_editor(node, xml)
  if node.attr("fullname") || node.attr("surname")
    personal_author1(node, xml, "")
  end
  i = 2
  while node.attr("fullname_#{i}") || node.attr("surname_#{i}")
    personal_author1(node, xml, "_#{i}")
    i += 1
  end
end

#personal_author1(node, xml, suffix) ⇒ Object



55
56
57
58
59
60
61
62
63
64
# File 'lib/metanorma/ogc/front.rb', line 55

def personal_author1(node, xml, suffix)
  xml.contributor do |c|
    personal_role(node, c, suffix)
    c.person do |p|
      p.name do |n|
        personal_author_name(node, n, suffix)
      end
    end
  end
end

#personal_author_name(node, xml, suffix) ⇒ Object



66
67
68
69
70
71
72
73
# File 'lib/metanorma/ogc/front.rb', line 66

def personal_author_name(node, xml, suffix)
  if node.attr("fullname#{suffix}")
    add_noko_elem(xml, "completename", node.attr("fullname#{suffix}"))
  else
    add_noko_elem(xml, "forename", node.attr("givenname#{suffix}"))
    add_noko_elem(xml, "surname", node.attr("surname#{suffix}"))
  end
end

#personal_role(node, contrib, suffix) ⇒ Object



33
34
35
36
37
38
39
40
41
# File 'lib/metanorma/ogc/front.rb', line 33

def personal_role(node, contrib, suffix)
  type = node.attr("role#{suffix}")&.downcase || "editor"
  if type == "contributor"
    contrib.role type: "author" do |r|
      add_noko_elem(r, "description", type)
    end
  else contrib.role type: type
  end
end

#presentation_xml_converter(node) ⇒ Object



143
144
145
146
147
# File 'lib/metanorma/ogc/converter.rb', line 143

def presentation_xml_converter(node)
  IsoDoc::Ogc::PresentationXMLConvert
    .new(html_extract_attributes(node)
    .merge(output_formats: ::Metanorma::Ogc::Processor.new.output_formats))
end

#published_date_scheme(date_str) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/metanorma/ogc/converter.rb', line 53

def published_date_scheme(date_str)
  published_date = parse_flexible_date(date_str) or return nil
  if published_date >= Date.new(2026, 1, 1) then "2026"
  elsif published_date >= Date.new(2021, 11, 8) then "2022"
  else "2018"
  end
rescue Date::Error, ArgumentError
  nil
end

#section(node) ⇒ Object



15
16
17
18
# File 'lib/metanorma/ogc/sections.rb', line 15

def section(node)
  override_style(node)
  super
end

#sectiontype(node, level = true) ⇒ Object



7
8
9
10
11
12
13
# File 'lib/metanorma/ogc/sections.rb', line 7

def sectiontype(node, level = true)
  ret = sectiontype_streamline(sectiontype1(node))
  return ret if ret == "terms and definitions" &&
    node.attr("style") == "appendix" && node.level == 1

  super
end

#sectiontype1(node) ⇒ Object

legacy encoding



43
44
45
46
# File 'lib/metanorma/ogc/sections.rb', line 43

def sectiontype1(node)
  role_style(node, "executive_summary") and return "executivesummary"
  super
end

#sectiontype_streamline(ret) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/metanorma/ogc/sections.rb', line 32

def sectiontype_streamline(ret)
  case ret
  when "preface" then "foreword"
  when "foreword", "introduction" then "donotrecognise-foreword"
  when "references" then "normative references"
  when "glossary" then "terms and definitions"
  else super
  end
end

#set_obligation(attrs, node) ⇒ Object



98
99
100
101
102
103
104
105
106
107
# File 'lib/metanorma/ogc/sections.rb', line 98

def set_obligation(attrs, node)
  if node.attr("style") == "appendix" && node.level == 1
    attrs[:obligation] = if node.attributes.has_key?("obligation")
                           node.attr("obligation")
                         else "informative"
                         end
  else
    super
  end
end

#style(_node, _text) ⇒ Object



86
87
88
# File 'lib/metanorma/ogc/converter.rb', line 86

def style(_node, _text)
  nil
end

#submitters_parse(attrs, xml, node) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/metanorma/ogc/sections.rb', line 65

def submitters_parse(attrs, xml, node)
  title = @i18n.submitters
  doctype(node) == "engineering-report" ||
    attrs[:type] == "contributors" and
    title = @i18n.contributors_clause
  xml.clause **attr_code(attrs) do |xml_section|
    section_title(xml_section, title)
    xml_section << node.content
  end
end

#table_cell(node, xml_tr, tblsec) ⇒ Object



90
91
92
93
# File 'lib/metanorma/ogc/converter.rb', line 90

def table_cell(node, xml_tr, tblsec)
  node.set_attr("valign", "middle")
  super
end

#term_def_parse(attrs, xml, node, _toplevel) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/metanorma/ogc/sections.rb', line 76

def term_def_parse(attrs, xml, node, _toplevel)
  if node.attr("style") == "appendix" && node.level == 1
    terms_annex_parse(attrs, xml, node)
  else
    super
  end
end

#terms_annex_parse(attrs, xml, node) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/metanorma/ogc/sections.rb', line 84

def terms_annex_parse(attrs, xml, node)
  attrs1 = attrs.merge(id: "_#{UUIDTools::UUID.random_create}")
  xml.annex **attr_code(attrs1) do |xml_section|
    section_title(xml_section, node.title)
    attrs.delete(:anchor)
    xml_section.terms **attr_code(attrs) do |terms|
      (s = node.attr("source")) && s.split(",").each do |s1|
        terms.termdocsource(nil, **attr_code(bibitemid: s1))
      end
      terms << node.content
    end
  end
end

#title(node, xml) ⇒ Object



185
186
187
188
189
# File 'lib/metanorma/ogc/front.rb', line 185

def title(node, xml)
  super
  content = node.attr("abbrev") and
    add_title_xml(xml, content, @lang, "abbrev")
end

#toc(value) ⇒ Object

ignore, we generate ToC outside of asciidoctor



5
# File 'lib/metanorma/ogc/sections.rb', line 5

def toc(value); end

#update_colors(node) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/metanorma/ogc/converter.rb', line 130

def update_colors(node)
  c = OGC_COLORS.dup
  if %w(2026 2022).include?(document_scheme(node))
    c[:"secondary-shade-1"] = "rgb(0, 177, 255)"
    c[:"secondary-shade-2"] = "rgb(0, 177, 255)"
  end
  if node.attr("doctype") == "white-paper"
    c[:"text-title"] = "rgb(68, 84, 106)"
    c[:"background-page"] = "rgb(68, 84, 106)"
  end
  c
end