isq 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/isq +6 -0
- data/lib/isq/cli.rb +49 -0
- data/lib/isq/dataset.rb +68 -0
- data/lib/isq/designation.rb +7 -0
- data/lib/isq/export.rb +153 -0
- data/lib/isq/lang_string.rb +16 -0
- data/lib/isq/math_concept.rb +42 -5
- data/lib/isq/part_document.rb +63 -0
- data/lib/isq/quantity.rb +77 -7
- data/lib/isq/symbol_term.rb +6 -0
- data/lib/isq/term_instance.rb +32 -0
- data/lib/isq/unit.rb +7 -2
- data/lib/isq/version.rb +1 -1
- data/lib/isq/yaml_adapters.rb +96 -0
- data/lib/isq.rb +8 -0
- data/lib/tasks/export.rake +8 -299
- metadata +28 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0dc68df904baa524f066fa29fa52882f1ac1f1b9be557aa1ef3118affeda590
|
|
4
|
+
data.tar.gz: efdf842000e1a325713c1558a0b6e37dede13c5da796bcb26d28425282f4a57a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 18ba08c24d8d9205810c2e113fae80340f138f3e4683a9a6e63354c68719fb451ccb2f0bd194bf4f221c3bc8865778fa5c17c2b6b8c5e6b530311101a15bb717
|
|
7
|
+
data.tar.gz: 38cc4b9c2cb152d1f1bad3911d8c3d9a757e340d74863233949d5270f0dc90db7860bf31c715d456fbf3da836aa1608b967233467e05b9db72edfea924bf6905
|
data/exe/isq
ADDED
data/lib/isq/cli.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "isq"
|
|
4
|
+
require "thor"
|
|
5
|
+
|
|
6
|
+
module Isq
|
|
7
|
+
class Cli < Thor
|
|
8
|
+
def self.exit_on_failure?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
desc "export", "Generate TTL and JSON-LD exports from YAML source data"
|
|
13
|
+
method_option :dataset_dir,
|
|
14
|
+
aliases: "-d",
|
|
15
|
+
type: :string,
|
|
16
|
+
desc: "YAML dataset directory"
|
|
17
|
+
method_option :export_dir,
|
|
18
|
+
aliases: "-o",
|
|
19
|
+
type: :string,
|
|
20
|
+
desc: "Output directory"
|
|
21
|
+
method_option :format,
|
|
22
|
+
aliases: "-f",
|
|
23
|
+
type: :string,
|
|
24
|
+
enum: %w[ttl jsonld both],
|
|
25
|
+
default: "both",
|
|
26
|
+
desc: "Output format: ttl, jsonld, or both"
|
|
27
|
+
def export
|
|
28
|
+
dataset_dir = options[:dataset_dir] || ENV.fetch("ISQ_DATASET_DIR", default_dataset_dir)
|
|
29
|
+
export_dir = options[:export_dir] || ENV.fetch("ISQ_EXPORT_DIR", default_export_dir)
|
|
30
|
+
|
|
31
|
+
dataset = Isq::Dataset.load(dataset_dir)
|
|
32
|
+
Isq::Export.new(dataset: dataset, export_dir: export_dir,
|
|
33
|
+
format: options[:format].to_sym).run
|
|
34
|
+
|
|
35
|
+
say "Generated exports in #{export_dir}:"
|
|
36
|
+
say " #{dataset.total_count} entries across #{dataset.part_keys.length} parts"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def default_dataset_dir
|
|
42
|
+
File.expand_path("../../../iso-iec-80000/sources/dataset", __dir__)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def default_export_dir
|
|
46
|
+
File.expand_path("../../../browser/public/exports", __dir__)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/isq/dataset.rb
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Isq
|
|
4
|
+
class Dataset
|
|
5
|
+
attr_reader :entries, :math_entries, :part_keys
|
|
6
|
+
|
|
7
|
+
def initialize(entries: [], math_entries: [])
|
|
8
|
+
@entries = Array(entries)
|
|
9
|
+
@math_entries = Array(math_entries)
|
|
10
|
+
index!
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.load(dataset_dir)
|
|
14
|
+
entries = load_yaml_file(dataset_dir, "quantities.yaml") { |yaml| Isq::Quantity.from_yaml(yaml) }
|
|
15
|
+
math_entries = load_yaml_file(dataset_dir, "math.yaml") { |yaml| Isq::MathConcept.from_yaml(yaml) }
|
|
16
|
+
|
|
17
|
+
new(entries: entries, math_entries: math_entries)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def entries_for_part(part_key)
|
|
21
|
+
by_part[part_key] || []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def unique_units_for_part(part_key)
|
|
25
|
+
part_entries = entries_for_part(part_key)
|
|
26
|
+
seen = Set.new
|
|
27
|
+
part_entries.each_with_object([]) do |entry, acc|
|
|
28
|
+
next unless entry.is_a?(Isq::Quantity)
|
|
29
|
+
next unless entry.has_unit
|
|
30
|
+
|
|
31
|
+
Array(entry.has_unit).each do |unit_ref|
|
|
32
|
+
next if seen.include?(unit_ref)
|
|
33
|
+
|
|
34
|
+
seen << unit_ref
|
|
35
|
+
acc << unit_ref
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def total_count
|
|
41
|
+
@entries.length + @math_entries.length
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def counts_by_part
|
|
45
|
+
by_part.transform_values(&:length)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def by_part
|
|
51
|
+
@by_part
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def index!
|
|
55
|
+
all_entries = @entries + @math_entries
|
|
56
|
+
@by_part = all_entries.group_by(&:part)
|
|
57
|
+
@part_keys = @by_part.keys.sort
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.load_yaml_file(dir, filename)
|
|
61
|
+
path = File.join(dir, filename)
|
|
62
|
+
return [] unless File.exist?(path)
|
|
63
|
+
|
|
64
|
+
yaml = File.read(path)
|
|
65
|
+
yield yaml
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
data/lib/isq/export.rb
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
module Isq
|
|
7
|
+
class Export
|
|
8
|
+
def initialize(dataset:, export_dir:, format: :both)
|
|
9
|
+
@dataset = dataset
|
|
10
|
+
@export_dir = export_dir
|
|
11
|
+
@format = format
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run
|
|
15
|
+
prepare_output_dir
|
|
16
|
+
write_per_part
|
|
17
|
+
write_bulk
|
|
18
|
+
write_manifest
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def prepare_output_dir
|
|
24
|
+
FileUtils.rm_rf(@export_dir)
|
|
25
|
+
FileUtils.mkdir_p(@export_dir)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def write_per_part
|
|
29
|
+
@dataset.part_keys.each do |part_key|
|
|
30
|
+
part_dir = File.join(@export_dir, "part-#{part_key}")
|
|
31
|
+
FileUtils.mkdir_p(part_dir)
|
|
32
|
+
|
|
33
|
+
part_doc = Isq::PartDocument.for_part(part_key)
|
|
34
|
+
entries = @dataset.entries_for_part(part_key)
|
|
35
|
+
units = build_unit_instances(@dataset.unique_units_for_part(part_key), entries)
|
|
36
|
+
|
|
37
|
+
if write_turtle?
|
|
38
|
+
part_ttl = compose_part_turtle(part_doc, units, entries)
|
|
39
|
+
File.write(File.join(part_dir, "index.ttl"), part_ttl)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
if write_jsonld?
|
|
43
|
+
part_jsonld = compose_part_jsonld(part_doc, units, entries)
|
|
44
|
+
File.write(File.join(part_dir, "index.jsonld"), part_jsonld)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
write_per_entry_files(part_dir, entries)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def write_per_entry_files(part_dir, entries)
|
|
52
|
+
entries.each do |entry|
|
|
53
|
+
if write_turtle?
|
|
54
|
+
File.write(File.join(part_dir, "#{entry.id}.ttl"), entry.to_turtle)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if write_jsonld?
|
|
58
|
+
File.write(File.join(part_dir, "#{entry.id}.jsonld"), entry.to_jsonld)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def write_bulk
|
|
64
|
+
if write_turtle?
|
|
65
|
+
all_turtle = @dataset.part_keys.map do |part_key|
|
|
66
|
+
part_doc = Isq::PartDocument.for_part(part_key)
|
|
67
|
+
entries = @dataset.entries_for_part(part_key)
|
|
68
|
+
units = build_unit_instances(@dataset.unique_units_for_part(part_key), entries)
|
|
69
|
+
compose_part_turtle(part_doc, units, entries)
|
|
70
|
+
end.join("\n")
|
|
71
|
+
File.write(File.join(@export_dir, "iso80000-all.ttl"), all_turtle)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if write_jsonld?
|
|
75
|
+
all_jsonld = @dataset.part_keys.map do |part_key|
|
|
76
|
+
part_doc = Isq::PartDocument.for_part(part_key)
|
|
77
|
+
entries = @dataset.entries_for_part(part_key)
|
|
78
|
+
units = build_unit_instances(@dataset.unique_units_for_part(part_key), entries)
|
|
79
|
+
compose_part_jsonld(part_doc, units, entries)
|
|
80
|
+
end.join("\n")
|
|
81
|
+
File.write(File.join(@export_dir, "iso80000-all.jsonld"), all_jsonld)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def write_manifest
|
|
86
|
+
manifest = {
|
|
87
|
+
generated: Time.now.utc.iso8601,
|
|
88
|
+
total_entries: @dataset.total_count,
|
|
89
|
+
parts: @dataset.counts_by_part,
|
|
90
|
+
namespaces: namespace_registry,
|
|
91
|
+
}
|
|
92
|
+
File.write(File.join(@export_dir, "manifest.json"), JSON.pretty_generate(manifest))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_unit_instances(unit_refs, entries)
|
|
96
|
+
unit_map = collect_unit_data(entries)
|
|
97
|
+
unit_refs.filter_map do |ref|
|
|
98
|
+
data = unit_map[ref]
|
|
99
|
+
next unless data
|
|
100
|
+
|
|
101
|
+
Isq::Unit.new(
|
|
102
|
+
id: ref.sub("isoiec80000:", ""),
|
|
103
|
+
pref_label: data[:name],
|
|
104
|
+
notation: data[:symbols],
|
|
105
|
+
bindingness_type: "smart:normative",
|
|
106
|
+
)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def collect_unit_data(entries)
|
|
111
|
+
entries.each_with_object({}) do |entry, map|
|
|
112
|
+
next unless entry.is_a?(Isq::Quantity)
|
|
113
|
+
next unless entry.unit_data
|
|
114
|
+
|
|
115
|
+
map.merge!(entry.unit_data) { |_key, old, _new| old }
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def compose_part_turtle(part_doc, units, entries)
|
|
120
|
+
lines = []
|
|
121
|
+
lines << part_doc.to_turtle
|
|
122
|
+
units.each { |u| lines << u.to_turtle }
|
|
123
|
+
entries.each { |e| lines << e.to_turtle }
|
|
124
|
+
lines.join("\n")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def compose_part_jsonld(part_doc, units, entries)
|
|
128
|
+
lines = []
|
|
129
|
+
lines << part_doc.to_jsonld
|
|
130
|
+
units.each { |u| lines << u.to_jsonld }
|
|
131
|
+
entries.each { |e| lines << e.to_jsonld }
|
|
132
|
+
lines.join("\n")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def namespace_registry
|
|
136
|
+
{
|
|
137
|
+
smart: "https://w3id.org/standards/smart/ontologies/core/",
|
|
138
|
+
isoiec80000: "https://w3id.org/standards/isoiec80000/ontologies/core/",
|
|
139
|
+
dcterms: "http://purl.org/dc/terms/",
|
|
140
|
+
skos: "http://www.w3.org/2004/02/skos/core#",
|
|
141
|
+
skosxl: "http://www.w3.org/2008/05/skos-xl#",
|
|
142
|
+
}
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def write_turtle?
|
|
146
|
+
@format == :both || @format == :ttl
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def write_jsonld?
|
|
150
|
+
@format == :both || @format == :jsonld
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/rdf/language_tagged"
|
|
4
|
+
|
|
5
|
+
module Isq
|
|
6
|
+
class LangString < String
|
|
7
|
+
include Lutaml::Rdf::LanguageTagged
|
|
8
|
+
|
|
9
|
+
attr_reader :language
|
|
10
|
+
|
|
11
|
+
def initialize(text, language: "en")
|
|
12
|
+
super(text.to_s)
|
|
13
|
+
@language = language
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/isq/math_concept.rb
CHANGED
|
@@ -2,21 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
module Isq
|
|
4
4
|
class MathConcept < SduSmart::TermEntry
|
|
5
|
+
include Isq::YamlAdapters
|
|
6
|
+
|
|
5
7
|
attribute :identifier, :string
|
|
6
8
|
attribute :pref_label, :string
|
|
7
|
-
attribute :notation, :string, collection: true
|
|
9
|
+
attribute :notation, :string, collection: true, initialize_empty: true
|
|
8
10
|
attribute :definition, :string
|
|
9
11
|
attribute :note, :string
|
|
12
|
+
attribute :part, :string
|
|
13
|
+
attribute :edition, :string
|
|
14
|
+
attribute :designations, Isq::Designation, collection: true, initialize_empty: true
|
|
15
|
+
attribute :symbols, Isq::SymbolTerm, collection: true, initialize_empty: true
|
|
16
|
+
|
|
17
|
+
def definition=(value)
|
|
18
|
+
value_set_for(:definition)
|
|
19
|
+
@definition = value
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def note=(value)
|
|
23
|
+
value_set_for(:note)
|
|
24
|
+
@note = value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
yaml do
|
|
28
|
+
map "id", to: :id
|
|
29
|
+
map "num", to: :identifier
|
|
30
|
+
map "part", to: :part
|
|
31
|
+
map "edition", to: :edition
|
|
32
|
+
map "def", with: { from: :definition_from_yaml, to: :definition_to_yaml }
|
|
33
|
+
map "remarks", with: { from: :note_from_yaml, to: :note_to_yaml }
|
|
34
|
+
map "designations", with: { from: :designations_from_yaml, to: :designations_to_yaml }
|
|
35
|
+
map "symbols", with: { from: :symbols_from_yaml, to: :symbols_to_yaml }
|
|
36
|
+
end
|
|
10
37
|
|
|
11
38
|
rdf do
|
|
12
39
|
namespace SduSmart::Rdf::Namespaces::IsoIec80000Namespace,
|
|
13
40
|
SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
14
41
|
Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
15
|
-
Lutaml::Rdf::Namespaces::SkosNamespace
|
|
42
|
+
Lutaml::Rdf::Namespaces::SkosNamespace,
|
|
43
|
+
SduSmart::Rdf::Namespaces::SkosXlNamespace
|
|
16
44
|
|
|
17
45
|
subject { |m| "https://w3id.org/standards/isoiec80000/ontologies/core/#{m.id}" }
|
|
18
46
|
|
|
19
|
-
type "isoiec80000:MathConcept"
|
|
47
|
+
type ["isoiec80000:MathConcept", "smart:TermEntry"]
|
|
20
48
|
|
|
21
49
|
predicate :identifier,
|
|
22
50
|
namespace: Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
@@ -32,11 +60,13 @@ module Isq
|
|
|
32
60
|
|
|
33
61
|
predicate :definition,
|
|
34
62
|
namespace: Lutaml::Rdf::Namespaces::SkosNamespace,
|
|
35
|
-
to: :definition
|
|
63
|
+
to: :definition,
|
|
64
|
+
lang_tagged: true
|
|
36
65
|
|
|
37
66
|
predicate :note,
|
|
38
67
|
namespace: Lutaml::Rdf::Namespaces::SkosNamespace,
|
|
39
|
-
to: :note
|
|
68
|
+
to: :note,
|
|
69
|
+
lang_tagged: true
|
|
40
70
|
|
|
41
71
|
predicate :hasBindingnessType,
|
|
42
72
|
namespace: SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
@@ -45,6 +75,13 @@ module Isq
|
|
|
45
75
|
predicate :isPartOf,
|
|
46
76
|
namespace: Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
47
77
|
to: :is_part_of
|
|
78
|
+
|
|
79
|
+
members :designations,
|
|
80
|
+
predicate_name: :prefLabel,
|
|
81
|
+
namespace: SduSmart::Rdf::Namespaces::SkosXlNamespace
|
|
82
|
+
members :symbols,
|
|
83
|
+
predicate_name: :altLabel,
|
|
84
|
+
namespace: SduSmart::Rdf::Namespaces::SkosXlNamespace
|
|
48
85
|
end
|
|
49
86
|
end
|
|
50
87
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Isq
|
|
4
|
+
class PartDocument < SduSmart::PublicationDocument
|
|
5
|
+
PART_TITLES = {
|
|
6
|
+
"2" => "Mathematics",
|
|
7
|
+
"3" => "Space and Time",
|
|
8
|
+
"4" => "Mechanics",
|
|
9
|
+
"5" => "Thermodynamics",
|
|
10
|
+
"6" => "Electromagnetism",
|
|
11
|
+
"7" => "Light and Radiation",
|
|
12
|
+
"8" => "Acoustics",
|
|
13
|
+
"9" => "Physical Chemistry and Molecular Physics",
|
|
14
|
+
"10" => "Atomic and Nuclear Physics",
|
|
15
|
+
"11" => "Characteristic Numbers",
|
|
16
|
+
"12" => "Condensed Matter Physics",
|
|
17
|
+
"13" => "Information Science",
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
attribute :part_number, :string
|
|
21
|
+
attribute :title, :string
|
|
22
|
+
attribute :bindingness_type, :string
|
|
23
|
+
|
|
24
|
+
rdf do
|
|
25
|
+
namespace SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
26
|
+
Lutaml::Rdf::Namespaces::DctermsNamespace
|
|
27
|
+
|
|
28
|
+
subject { |m| "https://w3id.org/standards/isoiec80000/ontologies/core/part-#{m.part_number}" }
|
|
29
|
+
|
|
30
|
+
type "smart:PublicationDocument"
|
|
31
|
+
|
|
32
|
+
predicate :title,
|
|
33
|
+
namespace: Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
34
|
+
to: :title
|
|
35
|
+
|
|
36
|
+
predicate :identifier,
|
|
37
|
+
namespace: Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
38
|
+
to: :part_number
|
|
39
|
+
|
|
40
|
+
predicate :hasPublicationType,
|
|
41
|
+
namespace: SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
42
|
+
to: :publication_type
|
|
43
|
+
|
|
44
|
+
predicate :hasBindingnessType,
|
|
45
|
+
namespace: SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
46
|
+
to: :bindingness_type
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.for_part(part_number)
|
|
50
|
+
new(
|
|
51
|
+
id: "part-#{part_number}",
|
|
52
|
+
part_number: "ISO 80000-#{part_number}",
|
|
53
|
+
title: PART_TITLES.fetch(part_number, "Part #{part_number}"),
|
|
54
|
+
publication_type: "smart:internationalStandard",
|
|
55
|
+
bindingness_type: "smart:normative",
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.all_parts
|
|
60
|
+
PART_TITLES.keys.map { |p| for_part(p) }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/isq/quantity.rb
CHANGED
|
@@ -2,22 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
module Isq
|
|
4
4
|
class Quantity < SduSmart::TermEntry
|
|
5
|
+
include Isq::YamlAdapters
|
|
6
|
+
|
|
5
7
|
attribute :identifier, :string
|
|
6
8
|
attribute :pref_label, :string
|
|
7
|
-
attribute :notation, :string, collection: true
|
|
9
|
+
attribute :notation, :string, collection: true, initialize_empty: true
|
|
8
10
|
attribute :definition, :string
|
|
9
11
|
attribute :note, :string
|
|
10
|
-
attribute :has_unit, :string, collection: true
|
|
12
|
+
attribute :has_unit, :string, collection: true, initialize_empty: true
|
|
13
|
+
attribute :part, :string
|
|
14
|
+
attribute :edition, :string
|
|
15
|
+
attribute :designations, Isq::Designation, collection: true, initialize_empty: true
|
|
16
|
+
attribute :symbols, Isq::SymbolTerm, collection: true, initialize_empty: true
|
|
17
|
+
|
|
18
|
+
attr_accessor :unit_data
|
|
19
|
+
|
|
20
|
+
def definition=(value)
|
|
21
|
+
value_set_for(:definition)
|
|
22
|
+
@definition = value
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def note=(value)
|
|
26
|
+
value_set_for(:note)
|
|
27
|
+
@note = value
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
yaml do
|
|
31
|
+
map "id", to: :id
|
|
32
|
+
map "num", to: :identifier
|
|
33
|
+
map "part", to: :part
|
|
34
|
+
map "edition", to: :edition
|
|
35
|
+
map "def", with: { from: :definition_from_yaml, to: :definition_to_yaml }
|
|
36
|
+
map "remarks", with: { from: :note_from_yaml, to: :note_to_yaml }
|
|
37
|
+
map "designations", with: { from: :designations_from_yaml, to: :designations_to_yaml }
|
|
38
|
+
map "symbols", with: { from: :symbols_from_yaml, to: :symbols_to_yaml }
|
|
39
|
+
map "units", with: { from: :units_from_yaml, to: :units_to_yaml }
|
|
40
|
+
end
|
|
11
41
|
|
|
12
42
|
rdf do
|
|
13
43
|
namespace SduSmart::Rdf::Namespaces::IsoIec80000Namespace,
|
|
14
44
|
SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
15
45
|
Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
16
|
-
Lutaml::Rdf::Namespaces::SkosNamespace
|
|
46
|
+
Lutaml::Rdf::Namespaces::SkosNamespace,
|
|
47
|
+
SduSmart::Rdf::Namespaces::SkosXlNamespace
|
|
17
48
|
|
|
18
49
|
subject { |m| "https://w3id.org/standards/isoiec80000/ontologies/core/#{m.id}" }
|
|
19
50
|
|
|
20
|
-
type "isoiec80000:Quantity"
|
|
51
|
+
type ["isoiec80000:Quantity", "smart:TermEntry"]
|
|
21
52
|
|
|
22
53
|
predicate :identifier,
|
|
23
54
|
namespace: Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
@@ -33,15 +64,18 @@ module Isq
|
|
|
33
64
|
|
|
34
65
|
predicate :definition,
|
|
35
66
|
namespace: Lutaml::Rdf::Namespaces::SkosNamespace,
|
|
36
|
-
to: :definition
|
|
67
|
+
to: :definition,
|
|
68
|
+
lang_tagged: true
|
|
37
69
|
|
|
38
70
|
predicate :note,
|
|
39
71
|
namespace: Lutaml::Rdf::Namespaces::SkosNamespace,
|
|
40
|
-
to: :note
|
|
72
|
+
to: :note,
|
|
73
|
+
lang_tagged: true
|
|
41
74
|
|
|
42
75
|
predicate :hasUnit,
|
|
43
76
|
namespace: SduSmart::Rdf::Namespaces::IsoIec80000Namespace,
|
|
44
|
-
to: :has_unit
|
|
77
|
+
to: :has_unit,
|
|
78
|
+
uri_reference: true
|
|
45
79
|
|
|
46
80
|
predicate :hasBindingnessType,
|
|
47
81
|
namespace: SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
@@ -50,6 +84,42 @@ module Isq
|
|
|
50
84
|
predicate :isPartOf,
|
|
51
85
|
namespace: Lutaml::Rdf::Namespaces::DctermsNamespace,
|
|
52
86
|
to: :is_part_of
|
|
87
|
+
|
|
88
|
+
members :designations,
|
|
89
|
+
predicate_name: :prefLabel,
|
|
90
|
+
namespace: SduSmart::Rdf::Namespaces::SkosXlNamespace
|
|
91
|
+
members :symbols,
|
|
92
|
+
predicate_name: :altLabel,
|
|
93
|
+
namespace: SduSmart::Rdf::Namespaces::SkosXlNamespace
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def units_from_yaml(model, value)
|
|
97
|
+
unless value.is_a?(Array)
|
|
98
|
+
model.has_unit = []
|
|
99
|
+
model.unit_data = {}
|
|
100
|
+
return []
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
data = {}
|
|
104
|
+
refs = value.map do |u|
|
|
105
|
+
sym = Array(u["symbol"]).first
|
|
106
|
+
ref = if sym
|
|
107
|
+
"isoiec80000:unit-#{sym}"
|
|
108
|
+
else
|
|
109
|
+
name = u["en"]&.downcase&.gsub(/\s+/, "-")
|
|
110
|
+
"isoiec80000:unit-#{name}" if name
|
|
111
|
+
end
|
|
112
|
+
data[ref] = { name: u["en"], symbols: Array(u["symbol"]) } if ref
|
|
113
|
+
ref
|
|
114
|
+
end.compact
|
|
115
|
+
|
|
116
|
+
model.has_unit = refs
|
|
117
|
+
model.unit_data = data
|
|
118
|
+
refs
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def units_to_yaml(model, doc)
|
|
122
|
+
# Unit YAML round-trip requires Dataset lookup
|
|
53
123
|
end
|
|
54
124
|
end
|
|
55
125
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Isq
|
|
4
|
+
class TermInstance < SduSmart::Term
|
|
5
|
+
attribute :text, :string
|
|
6
|
+
attribute :lang, :string, default: "en"
|
|
7
|
+
|
|
8
|
+
def text=(value)
|
|
9
|
+
value_set_for(:text)
|
|
10
|
+
@text = value
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
rdf do
|
|
14
|
+
namespace SduSmart::Rdf::Namespaces::SkosXlNamespace,
|
|
15
|
+
SduSmart::Rdf::Namespaces::SmartNamespace
|
|
16
|
+
|
|
17
|
+
subject { |m| "https://w3id.org/standards/isoiec80000/ontologies/core/#{m.id}" }
|
|
18
|
+
|
|
19
|
+
type ["skosxl:Label", "smart:Term"]
|
|
20
|
+
|
|
21
|
+
predicate :literalForm,
|
|
22
|
+
namespace: SduSmart::Rdf::Namespaces::SkosXlNamespace,
|
|
23
|
+
to: :text,
|
|
24
|
+
lang_tagged: true
|
|
25
|
+
|
|
26
|
+
predicate :hasTermFormType,
|
|
27
|
+
namespace: SduSmart::Rdf::Namespaces::SmartNamespace,
|
|
28
|
+
to: :term_form_type,
|
|
29
|
+
uri_reference: true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/isq/unit.rb
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
module Isq
|
|
4
4
|
class Unit < SduSmart::TermEntry
|
|
5
5
|
attribute :pref_label, :string
|
|
6
|
-
attribute :notation, :string, collection: true
|
|
6
|
+
attribute :notation, :string, collection: true, initialize_empty: true
|
|
7
|
+
|
|
8
|
+
yaml do
|
|
9
|
+
map "en", to: :pref_label
|
|
10
|
+
map "symbol", to: :notation
|
|
11
|
+
end
|
|
7
12
|
|
|
8
13
|
rdf do
|
|
9
14
|
namespace SduSmart::Rdf::Namespaces::IsoIec80000Namespace,
|
|
@@ -13,7 +18,7 @@ module Isq
|
|
|
13
18
|
|
|
14
19
|
subject { |m| "https://w3id.org/standards/isoiec80000/ontologies/core/#{m.id}" }
|
|
15
20
|
|
|
16
|
-
type "isoiec80000:Unit"
|
|
21
|
+
type ["isoiec80000:Unit", "smart:TermEntry"]
|
|
17
22
|
|
|
18
23
|
predicate :prefLabel,
|
|
19
24
|
namespace: Lutaml::Rdf::Namespaces::SkosNamespace,
|
data/lib/isq/version.rb
CHANGED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Isq
|
|
4
|
+
module YamlAdapters
|
|
5
|
+
def definition_from_yaml(model, value)
|
|
6
|
+
return unless value.is_a?(Hash)
|
|
7
|
+
|
|
8
|
+
lang = value.keys.first.to_s
|
|
9
|
+
text = value.values.first
|
|
10
|
+
model.definition = Isq::LangString.new(text.to_s, language: lang)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def definition_to_yaml(model, doc)
|
|
14
|
+
return unless model.definition
|
|
15
|
+
|
|
16
|
+
lang = model.definition.language || "en"
|
|
17
|
+
doc["def"] = { lang => model.definition.to_s }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def note_from_yaml(model, value)
|
|
21
|
+
return unless value.is_a?(Hash)
|
|
22
|
+
|
|
23
|
+
lang = value.keys.first.to_s
|
|
24
|
+
text = value.values.first
|
|
25
|
+
model.note = Isq::LangString.new(text.to_s, language: lang)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def note_to_yaml(model, doc)
|
|
29
|
+
return unless model.note
|
|
30
|
+
|
|
31
|
+
lang = model.note.language || "en"
|
|
32
|
+
doc["remarks"] = { lang => model.note.to_s }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def designations_from_yaml(model, value)
|
|
36
|
+
unless value.is_a?(Array)
|
|
37
|
+
model.designations = []
|
|
38
|
+
return []
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
designations = value.each_with_index.map do |entry, i|
|
|
42
|
+
lang_data = entry["designation"]
|
|
43
|
+
next unless lang_data.is_a?(Hash)
|
|
44
|
+
|
|
45
|
+
lang = lang_data.keys.first.to_s
|
|
46
|
+
text_data = lang_data[lang] || lang_data[lang.to_sym]
|
|
47
|
+
next unless text_data.is_a?(Hash)
|
|
48
|
+
|
|
49
|
+
d = Isq::Designation.new(
|
|
50
|
+
id: "term-#{model.id}-#{i}",
|
|
51
|
+
lang: lang,
|
|
52
|
+
term_form_type: "smart:fullForm",
|
|
53
|
+
index_as: Array(text_data["index_as"]),
|
|
54
|
+
)
|
|
55
|
+
d.text = Isq::LangString.new(text_data["text"].to_s, language: lang)
|
|
56
|
+
d
|
|
57
|
+
end.compact
|
|
58
|
+
|
|
59
|
+
model.designations = designations
|
|
60
|
+
model.pref_label = designations.first&.text
|
|
61
|
+
designations
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def designations_to_yaml(model, doc)
|
|
65
|
+
doc["designations"] = model.designations.map do |d|
|
|
66
|
+
{ "designation" => { d.lang => { "text" => d.text.to_s, "index_as" => Array(d.index_as) } } }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def symbols_from_yaml(model, value)
|
|
71
|
+
unless value.is_a?(Array)
|
|
72
|
+
model.symbols = []
|
|
73
|
+
model.notation = []
|
|
74
|
+
return []
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
symbols = value.each_with_index.map do |sym, i|
|
|
78
|
+
s = Isq::SymbolTerm.new(
|
|
79
|
+
id: "sym-#{model.id}-#{i}",
|
|
80
|
+
lang: "en",
|
|
81
|
+
term_form_type: "smart:symbol",
|
|
82
|
+
)
|
|
83
|
+
s.text = Isq::LangString.new(sym.to_s, language: "en")
|
|
84
|
+
s
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
model.symbols = symbols
|
|
88
|
+
model.notation = symbols.map { |s| s.text.to_s }
|
|
89
|
+
symbols
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def symbols_to_yaml(model, doc)
|
|
93
|
+
doc["symbols"] = model.symbols.map { |s| s.text.to_s }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
data/lib/isq.rb
CHANGED
|
@@ -3,8 +3,16 @@
|
|
|
3
3
|
require "sdu_smart"
|
|
4
4
|
|
|
5
5
|
module Isq
|
|
6
|
+
autoload :LangString, "#{__dir__}/isq/lang_string"
|
|
7
|
+
autoload :YamlAdapters, "#{__dir__}/isq/yaml_adapters"
|
|
8
|
+
autoload :TermInstance, "#{__dir__}/isq/term_instance"
|
|
9
|
+
autoload :Designation, "#{__dir__}/isq/designation"
|
|
10
|
+
autoload :SymbolTerm, "#{__dir__}/isq/symbol_term"
|
|
6
11
|
autoload :Quantity, "#{__dir__}/isq/quantity"
|
|
7
12
|
autoload :Unit, "#{__dir__}/isq/unit"
|
|
8
13
|
autoload :MathConcept, "#{__dir__}/isq/math_concept"
|
|
14
|
+
autoload :PartDocument, "#{__dir__}/isq/part_document"
|
|
15
|
+
autoload :Dataset, "#{__dir__}/isq/dataset"
|
|
16
|
+
autoload :Export, "#{__dir__}/isq/export"
|
|
9
17
|
autoload :VERSION, "#{__dir__}/isq/version"
|
|
10
18
|
end
|
data/lib/tasks/export.rake
CHANGED
|
@@ -1,309 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "yaml"
|
|
4
|
-
require "json"
|
|
5
|
-
require "fileutils"
|
|
6
|
-
|
|
7
3
|
namespace :export do
|
|
8
|
-
ROOT = File.join(__dir__, "..", "..", "..")
|
|
9
|
-
EXPORT_DIR = ENV.fetch("ISQ_EXPORT_DIR", File.join(ROOT, "browser", "public", "exports"))
|
|
10
|
-
DATASET_DIR = ENV.fetch("ISQ_DATASET_DIR", File.join(ROOT, "iso-iec-80000", "sources", "dataset"))
|
|
11
|
-
|
|
12
|
-
PART_TITLES = {
|
|
13
|
-
"3" => "Space and Time", "4" => "Mechanics", "5" => "Thermodynamics",
|
|
14
|
-
"6" => "Electromagnetism", "7" => "Light and Radiation", "8" => "Acoustics",
|
|
15
|
-
"9" => "Physical Chemistry", "10" => "Atomic and Nuclear", "11" => "Characteristic Numbers",
|
|
16
|
-
"12" => "Condensed Matter", "13" => "Information Science", "2" => "Mathematics",
|
|
17
|
-
}.freeze
|
|
18
|
-
|
|
19
|
-
SMART = "https://w3id.org/standards/smart/ontologies/core/"
|
|
20
|
-
ISO = "https://w3id.org/standards/isoiec80000/ontologies/core/"
|
|
21
|
-
DCTERMS = "http://purl.org/dc/terms/"
|
|
22
|
-
SKOS = "http://www.w3.org/2004/02/skos/core#"
|
|
23
|
-
SKOSXL = "http://www.w3.org/2008/05/skos-xl#"
|
|
24
|
-
|
|
25
|
-
JSONLD_CONTEXT = {
|
|
26
|
-
"@context" => {
|
|
27
|
-
"smart" => SMART,
|
|
28
|
-
"isoiec80000" => ISO,
|
|
29
|
-
"dcterms" => DCTERMS,
|
|
30
|
-
"skos" => SKOS,
|
|
31
|
-
"skosxl" => SKOSXL,
|
|
32
|
-
"rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
|
33
|
-
"rdfs" => "http://www.w3.org/2000/01/rdf-schema#",
|
|
34
|
-
"owl" => "http://www.w3.org/2002/07/owl#",
|
|
35
|
-
"xsd" => "http://www.w3.org/2001/XMLSchema#",
|
|
36
|
-
},
|
|
37
|
-
}.freeze
|
|
38
|
-
|
|
39
|
-
def load_entries
|
|
40
|
-
quantities = YAML.load_file(File.join(DATASET_DIR, "quantities.yaml"))
|
|
41
|
-
math = YAML.load_file(File.join(DATASET_DIR, "math.yaml"))
|
|
42
|
-
quantities + math
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def math?(entry)
|
|
46
|
-
entry["part"].to_s.start_with?("2")
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def entry_rdf_type(entry)
|
|
50
|
-
math?(entry) ? "isoiec80000:MathConcept" : "isoiec80000:Quantity"
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def unit_uri(unit)
|
|
54
|
-
sym = unit["symbol"]&.first
|
|
55
|
-
sym ? "isoiec80000:unit-#{sym}" : "isoiec80000:unit-#{unit['en']&.downcase&.gsub(/\s+/, '-')}"
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def escape_literal(s)
|
|
59
|
-
s.gsub("\\", "\\\\\\\\").gsub('"', '\\"')
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def generate_turtle(entry)
|
|
63
|
-
id = entry["id"]
|
|
64
|
-
rdf_type = entry_rdf_type(entry)
|
|
65
|
-
lines = []
|
|
66
|
-
|
|
67
|
-
# Term instances for designations
|
|
68
|
-
entry["designations"]&.each_with_index do |des, i|
|
|
69
|
-
tid = "term-#{id}-#{i}"
|
|
70
|
-
text = des.dig("designation", "en", "text")
|
|
71
|
-
next unless text
|
|
72
|
-
|
|
73
|
-
lines << "isoiec80000:#{tid} a smart:Term, skosxl:Label ;"
|
|
74
|
-
lines << " skosxl:literalForm \"#{escape_literal(text)}\"@en ;"
|
|
75
|
-
lines << " smart:hasTermFormType smart:fullForm ."
|
|
76
|
-
lines << ""
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Term instances for symbols
|
|
80
|
-
entry["symbols"]&.each_with_index do |sym, i|
|
|
81
|
-
tid = "sym-#{id}-#{i}"
|
|
82
|
-
lines << "isoiec80000:#{tid} a smart:Term, skosxl:Label ;"
|
|
83
|
-
lines << " skosxl:literalForm \"#{escape_literal(sym)}\"@en ;"
|
|
84
|
-
lines << " smart:hasTermFormType smart:symbol ."
|
|
85
|
-
lines << ""
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# Main entry
|
|
89
|
-
lines << "isoiec80000:#{id} a #{rdf_type}, smart:TermEntry ;"
|
|
90
|
-
lines << " dcterms:identifier \"#{entry['num']}\" ;"
|
|
91
|
-
|
|
92
|
-
# skosxl:prefLabel for first designation
|
|
93
|
-
if entry["designations"]&.any?
|
|
94
|
-
lines << " skosxl:prefLabel isoiec80000:term-#{id}-0 ;"
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# skosxl:altLabel for remaining designations
|
|
98
|
-
entry["designations"]&.each_with_index do |_des, i|
|
|
99
|
-
next if i == 0
|
|
100
|
-
lines << " skosxl:altLabel isoiec80000:term-#{id}-#{i} ;"
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# skosxl:altLabel for symbol terms
|
|
104
|
-
entry["symbols"]&.each_with_index do |_sym, i|
|
|
105
|
-
lines << " skosxl:altLabel isoiec80000:sym-#{id}-#{i} ;"
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
if entry["def"]&.dig("en")
|
|
109
|
-
lines << " skos:definition \"\"\"#{escape_literal(entry['def']['en'])}\"\"\"@en ;"
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
if entry["remarks"]&.dig("en")
|
|
113
|
-
lines << " skos:note \"\"\"#{escape_literal(entry['remarks']['en'])}\"\"\"@en ;"
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
if entry["units"]&.any?
|
|
117
|
-
for unit in entry["units"]
|
|
118
|
-
lines << " isoiec80000:hasUnit #{unit_uri(unit)} ;"
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
lines << " smart:hasBindingnessType smart:normative ;"
|
|
123
|
-
lines << " dcterms:isPartOf isoiec80000:part-#{entry['part']} ."
|
|
124
|
-
|
|
125
|
-
lines.join("\n")
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def generate_unit_turtle(unit)
|
|
129
|
-
uri = unit_uri(unit)
|
|
130
|
-
name = unit["en"]
|
|
131
|
-
lines = ["#{uri} a isoiec80000:Unit, smart:TermEntry ;"]
|
|
132
|
-
lines << " skos:prefLabel \"#{name}\"@en ;"
|
|
133
|
-
if unit["symbol"]&.any?
|
|
134
|
-
for sym in unit["symbol"]
|
|
135
|
-
lines << " skos:notation \"#{sym}\" ;"
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
lines << " smart:hasBindingnessType smart:normative ."
|
|
139
|
-
lines.join("\n")
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def entry_jsonld(entry)
|
|
143
|
-
id = entry["id"]
|
|
144
|
-
part = entry["part"]
|
|
145
|
-
|
|
146
|
-
# Term instances for designations
|
|
147
|
-
terms = entry["designations"]&.each_with_index&.map do |des, i|
|
|
148
|
-
text = des.dig("designation", "en", "text")
|
|
149
|
-
next unless text
|
|
150
|
-
|
|
151
|
-
{
|
|
152
|
-
"@id" => "#{ISO}term-#{id}-#{i}",
|
|
153
|
-
"@type" => ["smart:Term", "skosxl:Label"],
|
|
154
|
-
"skosxl:literalForm" => { "@value" => text, "@language" => "en" },
|
|
155
|
-
"smart:hasTermFormType" => { "@id" => "smart:fullForm" },
|
|
156
|
-
}
|
|
157
|
-
end&.compact || []
|
|
158
|
-
|
|
159
|
-
# Term instances for symbols
|
|
160
|
-
symbol_terms = entry["symbols"]&.each_with_index&.map do |sym, i|
|
|
161
|
-
{
|
|
162
|
-
"@id" => "#{ISO}sym-#{id}-#{i}",
|
|
163
|
-
"@type" => ["smart:Term", "skosxl:Label"],
|
|
164
|
-
"skosxl:literalForm" => { "@value" => sym, "@language" => "en" },
|
|
165
|
-
"smart:hasTermFormType" => { "@id" => "smart:symbol" },
|
|
166
|
-
}
|
|
167
|
-
end || []
|
|
168
|
-
|
|
169
|
-
all_terms = terms + symbol_terms
|
|
170
|
-
|
|
171
|
-
entry_obj = {
|
|
172
|
-
"@id" => "#{ISO}#{id}",
|
|
173
|
-
"@type" => [entry_rdf_type(entry), "smart:TermEntry"],
|
|
174
|
-
"dcterms:identifier" => entry["num"],
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if terms.any?
|
|
178
|
-
entry_obj["skosxl:prefLabel"] = { "@id" => "#{ISO}term-#{id}-0" }
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
alt_labels = []
|
|
182
|
-
entry["designations"]&.each_with_index do |_des, i|
|
|
183
|
-
next if i == 0
|
|
184
|
-
alt_labels << { "@id" => "#{ISO}term-#{id}-#{i}" }
|
|
185
|
-
end
|
|
186
|
-
entry["symbols"]&.each_with_index do |_sym, i|
|
|
187
|
-
alt_labels << { "@id" => "#{ISO}sym-#{id}-#{i}" }
|
|
188
|
-
end
|
|
189
|
-
entry_obj["skosxl:altLabel"] = alt_labels if alt_labels.any?
|
|
190
|
-
|
|
191
|
-
if entry["def"]&.dig("en")
|
|
192
|
-
entry_obj["skos:definition"] = { "@value" => entry["def"]["en"], "@language" => "en" }
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
if entry["remarks"]&.dig("en")
|
|
196
|
-
entry_obj["skos:note"] = { "@value" => entry["remarks"]["en"], "@language" => "en" }
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
if entry["units"]&.any?
|
|
200
|
-
entry_obj["isoiec80000:hasUnit"] = entry["units"].map { |u| { "@id" => unit_uri(u) } }
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
entry_obj["smart:hasBindingnessType"] = { "@id" => "smart:normative" }
|
|
204
|
-
entry_obj["dcterms:isPartOf"] = { "@id" => "#{ISO}part-#{part}" }
|
|
205
|
-
|
|
206
|
-
{ "@graph" => all_terms + [entry_obj] }
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
def generate_part_turtle(part_key, part_entries)
|
|
210
|
-
lines = [
|
|
211
|
-
"@prefix isoiec80000: <#{ISO}> .",
|
|
212
|
-
"@prefix smart: <#{SMART}> .",
|
|
213
|
-
"@prefix dcterms: <#{DCTERMS}> .",
|
|
214
|
-
"@prefix skos: <#{SKOS}> .",
|
|
215
|
-
"@prefix skosxl: <#{SKOSXL}> .",
|
|
216
|
-
"",
|
|
217
|
-
]
|
|
218
|
-
|
|
219
|
-
# PublicationDocument instance
|
|
220
|
-
lines << "isoiec80000:part-#{part_key} a smart:PublicationDocument ;"
|
|
221
|
-
lines << " dcterms:title \"#{PART_TITLES[part_key] || "Part #{part_key}"}\"@en ;"
|
|
222
|
-
lines << " dcterms:identifier \"ISO 80000-#{part_key}\" ;"
|
|
223
|
-
lines << " smart:hasPublicationType smart:internationalStandard ;"
|
|
224
|
-
lines << " smart:hasBindingnessType smart:normative ."
|
|
225
|
-
lines << ""
|
|
226
|
-
|
|
227
|
-
# Collect unique units
|
|
228
|
-
units = part_entries.each_with_object([]) do |entry, acc|
|
|
229
|
-
entry["units"]&.each do |u|
|
|
230
|
-
key = unit_uri(u)
|
|
231
|
-
acc << u unless acc.any? { |existing| unit_uri(existing) == key }
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
units.each do |u|
|
|
236
|
-
lines << generate_unit_turtle(u)
|
|
237
|
-
lines << ""
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
part_entries.each do |entry|
|
|
241
|
-
lines << generate_turtle(entry)
|
|
242
|
-
lines << ""
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
lines.join("\n")
|
|
246
|
-
end
|
|
247
|
-
|
|
248
4
|
desc "Generate TTL and JSON-LD exports for all entries"
|
|
249
5
|
task :all do
|
|
250
|
-
require "
|
|
251
|
-
|
|
252
|
-
FileUtils.rm_rf(EXPORT_DIR)
|
|
253
|
-
FileUtils.mkdir_p(EXPORT_DIR)
|
|
254
|
-
|
|
255
|
-
entries = load_entries
|
|
256
|
-
by_part = entries.group_by { |e| e["part"].to_s }
|
|
257
|
-
|
|
258
|
-
all_turtle = []
|
|
259
|
-
all_jsonld = []
|
|
260
|
-
|
|
261
|
-
by_part.each do |part_key, part_entries|
|
|
262
|
-
part_dir = File.join(EXPORT_DIR, "part-#{part_key}")
|
|
263
|
-
FileUtils.mkdir_p(part_dir)
|
|
264
|
-
|
|
265
|
-
# Per-part Turtle
|
|
266
|
-
part_ttl = generate_part_turtle(part_key, part_entries)
|
|
267
|
-
File.write(File.join(part_dir, "index.ttl"), part_ttl)
|
|
268
|
-
|
|
269
|
-
# Per-part JSON-LD
|
|
270
|
-
part_graphs = part_entries.map { |e| entry_jsonld(e) }
|
|
271
|
-
part_jsonld = { **JSONLD_CONTEXT, "@graph" => part_graphs.flat_map { |g| g["@graph"] } }
|
|
272
|
-
File.write(File.join(part_dir, "index.jsonld"), JSON.pretty_generate(part_jsonld))
|
|
273
|
-
|
|
274
|
-
all_turtle << part_ttl
|
|
275
|
-
all_jsonld.concat(part_graphs.flat_map { |g| g["@graph"] })
|
|
276
|
-
|
|
277
|
-
# Per-entry files
|
|
278
|
-
part_entries.each do |entry|
|
|
279
|
-
base = entry["id"]
|
|
280
|
-
entry_json = entry_jsonld(entry)
|
|
281
|
-
File.write(File.join(part_dir, "#{base}.ttl"), generate_turtle(entry))
|
|
282
|
-
File.write(File.join(part_dir, "#{base}.jsonld"), JSON.pretty_generate({ **JSONLD_CONTEXT, **entry_json }))
|
|
283
|
-
end
|
|
284
|
-
end
|
|
6
|
+
require "isq"
|
|
285
7
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
File.write(File.join(EXPORT_DIR, "iso80000-all.jsonld"), JSON.pretty_generate(bulk_jsonld))
|
|
8
|
+
root = File.join(__dir__, "..", "..", "..")
|
|
9
|
+
dataset_dir = ENV.fetch("ISQ_DATASET_DIR", File.join(root, "iso-iec-80000", "sources", "dataset"))
|
|
10
|
+
export_dir = ENV.fetch("ISQ_EXPORT_DIR", File.join(root, "browser", "public", "exports"))
|
|
290
11
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
generated: Time.now.utc.iso8601,
|
|
294
|
-
total_entries: entries.length,
|
|
295
|
-
parts: by_part.transform_values(&:length),
|
|
296
|
-
namespaces: {
|
|
297
|
-
smart: SMART,
|
|
298
|
-
isoiec80000: ISO,
|
|
299
|
-
dcterms: DCTERMS,
|
|
300
|
-
skos: SKOS,
|
|
301
|
-
skosxl: SKOSXL,
|
|
302
|
-
},
|
|
303
|
-
}
|
|
304
|
-
File.write(File.join(EXPORT_DIR, "manifest.json"), JSON.pretty_generate(manifest))
|
|
12
|
+
dataset = Isq::Dataset.load(dataset_dir)
|
|
13
|
+
Isq::Export.new(dataset: dataset, export_dir: export_dir).run
|
|
305
14
|
|
|
306
|
-
puts "Generated exports in #{
|
|
307
|
-
puts " #{
|
|
15
|
+
puts "Generated exports in #{export_dir}:"
|
|
16
|
+
puts " #{dataset.total_count} entries across #{dataset.part_keys.length} parts"
|
|
308
17
|
end
|
|
309
18
|
end
|
metadata
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: isq
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
|
-
bindir:
|
|
8
|
+
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
@@ -37,20 +37,45 @@ dependencies:
|
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: 0.8.0
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: thor
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.3'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '1.3'
|
|
40
54
|
description: 'Ruby gem extending the SmartSDU Core Ontology with ISO/IEC 80000-specific
|
|
41
55
|
domain classes: Quantity, Unit, and MathConcept. Includes a Rake task for generating
|
|
42
56
|
per-part Turtle and JSON-LD exports from YAML source data.'
|
|
43
57
|
email:
|
|
44
58
|
- open.source@ribose.com
|
|
45
|
-
executables:
|
|
59
|
+
executables:
|
|
60
|
+
- isq
|
|
46
61
|
extensions: []
|
|
47
62
|
extra_rdoc_files: []
|
|
48
63
|
files:
|
|
64
|
+
- exe/isq
|
|
49
65
|
- lib/isq.rb
|
|
66
|
+
- lib/isq/cli.rb
|
|
67
|
+
- lib/isq/dataset.rb
|
|
68
|
+
- lib/isq/designation.rb
|
|
69
|
+
- lib/isq/export.rb
|
|
70
|
+
- lib/isq/lang_string.rb
|
|
50
71
|
- lib/isq/math_concept.rb
|
|
72
|
+
- lib/isq/part_document.rb
|
|
51
73
|
- lib/isq/quantity.rb
|
|
74
|
+
- lib/isq/symbol_term.rb
|
|
75
|
+
- lib/isq/term_instance.rb
|
|
52
76
|
- lib/isq/unit.rb
|
|
53
77
|
- lib/isq/version.rb
|
|
78
|
+
- lib/isq/yaml_adapters.rb
|
|
54
79
|
- lib/tasks/export.rake
|
|
55
80
|
homepage: https://github.com/metanorma/isq
|
|
56
81
|
licenses:
|