glossarist 2.8.18 → 2.9.0
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/.rubocop_todo.yml +175 -8
- data/Rakefile +4 -0
- data/config.yml +2 -3
- data/data/concept-model/README.md +35 -0
- data/data/concept-model/SOURCE.json +5 -0
- data/data/concept-model/glossarist.context.jsonld +209 -0
- data/data/concept-model/glossarist.ttl +960 -0
- data/data/concept-model/shapes/glossarist.shacl.ttl +575 -0
- data/glossarist.gemspec +2 -0
- data/lib/glossarist/asset_reference.rb +2 -0
- data/lib/glossarist/bibliographic_reference.rb +13 -0
- data/lib/glossarist/cli/export_command.rb +130 -7
- data/lib/glossarist/cli.rb +11 -2
- data/lib/glossarist/concept_document.rb +13 -0
- data/lib/glossarist/concept_reference.rb +6 -0
- data/lib/glossarist/concept_store.rb +2 -3
- data/lib/glossarist/dataset_register.rb +2 -2
- data/lib/glossarist/figure_reference.rb +0 -4
- data/lib/glossarist/formula_reference.rb +0 -4
- data/lib/glossarist/non_verbal_reference.rb +10 -0
- data/lib/glossarist/rdf/gloss_detailed_definition.rb +6 -1
- data/lib/glossarist/rdf/gloss_localized_concept.rb +65 -0
- data/lib/glossarist/rdf/lutaml_ext.rb +33 -0
- data/lib/glossarist/rdf.rb +2 -0
- data/lib/glossarist/reference.rb +33 -0
- data/lib/glossarist/table_reference.rb +0 -4
- data/lib/glossarist/tasks/shacl.rake +30 -0
- data/lib/glossarist/tasks/sync.rake +14 -0
- data/lib/glossarist/tasks/sync_model.rb +92 -0
- data/lib/glossarist/transforms/concept_to_gloss_transform.rb +3 -2
- data/lib/glossarist/utilities/uuid.rb +5 -1
- data/lib/glossarist/validation/rules/related_concept_cycle_rule.rb +15 -1
- data/lib/glossarist/validation/shacl_validator.rb +97 -0
- data/lib/glossarist/validation.rb +1 -0
- data/lib/glossarist/version.rb +1 -1
- data/lib/glossarist.rb +1 -0
- metadata +41 -2
|
@@ -65,7 +65,11 @@ module Glossarist
|
|
|
65
65
|
else
|
|
66
66
|
match_data = namespace.match(/\A(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})\z/)
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
# `match_data` is a MatchData on success, nil on failure. Do not
|
|
69
|
+
# use ActiveSupport's `#present?` here — ActiveSupport is not a
|
|
70
|
+
# declared dependency of this gem, and `#present?` raises
|
|
71
|
+
# NoMethodError in bundles where it isn't loaded.
|
|
72
|
+
unless match_data
|
|
69
73
|
raise ArgumentError,
|
|
70
74
|
"Only UUIDs are valid namespace identifiers"
|
|
71
75
|
end
|
|
@@ -54,11 +54,25 @@ module Glossarist
|
|
|
54
54
|
graph
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
# Returns a graph node identifier for the target of a relationship.
|
|
58
|
+
#
|
|
59
|
+
# For intra-edition references (ref.source is nil), the target is
|
|
60
|
+
# just ref.id — a clause identifier unique within the dataset.
|
|
61
|
+
#
|
|
62
|
+
# Returns nil for cross-edition references (ref.source is a URN,
|
|
63
|
+
# e.g. a +supersedes+ edge pointing at the previous edition's
|
|
64
|
+
# concept with the same clause id). Such edges cannot form
|
|
65
|
+
# cycles within the current dataset and are excluded from the
|
|
66
|
+
# graph. Without this exclusion, a cross-edition edge from
|
|
67
|
+
# concept 3.1.1.1 to its predecessor in another edition (which
|
|
68
|
+
# also has identifier 3.1.1.1) would look like a self-loop and
|
|
69
|
+
# trip the cycle detector with a false positive.
|
|
57
70
|
def resolve_target_id(rel)
|
|
58
71
|
ref = rel.ref
|
|
59
72
|
return nil unless ref
|
|
73
|
+
return nil if ref.source
|
|
60
74
|
|
|
61
|
-
ref.id
|
|
75
|
+
ref.id
|
|
62
76
|
end
|
|
63
77
|
|
|
64
78
|
def detect_cycles(graph)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rdf/turtle"
|
|
4
|
+
require "shacl"
|
|
5
|
+
require "pathname"
|
|
6
|
+
|
|
7
|
+
module Glossarist
|
|
8
|
+
module Validation
|
|
9
|
+
# Validates Turtle output against SHACL shapes.
|
|
10
|
+
#
|
|
11
|
+
# Shapes resolution order:
|
|
12
|
+
# 1. Explicit :shapes_path option
|
|
13
|
+
# 2. Vendored shapes at data/concept-model/shapes/glossarist.shacl.ttl
|
|
14
|
+
# (shipped with the gem, relative to the gem root)
|
|
15
|
+
class ShaclValidator
|
|
16
|
+
VENDORED_SHAPES_PATH =
|
|
17
|
+
File.expand_path(
|
|
18
|
+
"../../../data/concept-model/shapes/glossarist.shacl.ttl",
|
|
19
|
+
__dir__
|
|
20
|
+
).freeze
|
|
21
|
+
|
|
22
|
+
attr_reader :shapes_path
|
|
23
|
+
|
|
24
|
+
def initialize(shapes_path: nil)
|
|
25
|
+
@shapes_path = shapes_path || self.class.default_shapes_path
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def validate_files(paths)
|
|
29
|
+
validate_graphs(Array(paths).map { |p| load_graph(p) })
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def validate_graphs(graphs)
|
|
33
|
+
shapes = SHACL::Shapes.from_graph(load_graph(@shapes_path))
|
|
34
|
+
failures = []
|
|
35
|
+
|
|
36
|
+
graphs.each do |graph|
|
|
37
|
+
report = shapes.execute(graph)
|
|
38
|
+
next if report.conform?
|
|
39
|
+
|
|
40
|
+
failures << Report.new(results: report.results)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
AggregateReport.new(failures: failures)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class << self
|
|
47
|
+
def default_shapes_path
|
|
48
|
+
return VENDORED_SHAPES_PATH if File.exist?(VENDORED_SHAPES_PATH)
|
|
49
|
+
|
|
50
|
+
raise ArgumentError,
|
|
51
|
+
"No SHACL shapes path provided and the vendored shapes " \
|
|
52
|
+
"file (#{VENDORED_SHAPES_PATH}) is missing. Pass " \
|
|
53
|
+
"shapes_path: '/path/to/glossarist.shacl.ttl'."
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def load_graph(path)
|
|
60
|
+
return path if path.is_a?(RDF::Graph)
|
|
61
|
+
|
|
62
|
+
graph = RDF::Graph.new
|
|
63
|
+
RDF::Turtle::Reader.new(File.read(path)) do |reader|
|
|
64
|
+
reader.each_statement { |stmt| graph << stmt }
|
|
65
|
+
end
|
|
66
|
+
graph
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
Report = Struct.new(:results, keyword_init: true) do
|
|
71
|
+
def conformant?
|
|
72
|
+
results.empty?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def to_s
|
|
76
|
+
" #{results.length} violation(s)"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
AggregateReport = Struct.new(:failures, keyword_init: true) do
|
|
81
|
+
def conformant?
|
|
82
|
+
failures.empty?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def to_s
|
|
86
|
+
lines = ["SHACL validation failed: #{failures.length} file(s) with violations"]
|
|
87
|
+
failures.each do |failure|
|
|
88
|
+
lines << failure.to_s
|
|
89
|
+
failure.results.each do |result|
|
|
90
|
+
lines << " #{result.path}: #{result.message}"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
lines.join("\n")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -8,5 +8,6 @@ module Glossarist
|
|
|
8
8
|
autoload :Rules, "glossarist/validation/rules"
|
|
9
9
|
autoload :BibliographyIndex, "glossarist/validation/bibliography_index"
|
|
10
10
|
autoload :AssetIndex, "glossarist/validation/asset_index"
|
|
11
|
+
autoload :ShaclValidator, "glossarist/validation/shacl_validator"
|
|
11
12
|
end
|
|
12
13
|
end
|
data/lib/glossarist/version.rb
CHANGED
data/lib/glossarist.rb
CHANGED
|
@@ -23,6 +23,7 @@ module Glossarist
|
|
|
23
23
|
autoload :ConceptData, "glossarist/concept_data"
|
|
24
24
|
autoload :ConceptRef, "glossarist/concept_ref"
|
|
25
25
|
autoload :ConceptReference, "glossarist/concept_reference"
|
|
26
|
+
autoload :Reference, "glossarist/reference"
|
|
26
27
|
autoload :ReferenceExtractor, "glossarist/reference_extractor"
|
|
27
28
|
autoload :ReferenceResolver, "glossarist/reference_resolver"
|
|
28
29
|
autoload :ResolutionAdapter, "glossarist/resolution_adapter"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: glossarist
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '2.3'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rdf-turtle
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.3'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.3'
|
|
55
69
|
- !ruby/object:Gem::Dependency
|
|
56
70
|
name: relaton
|
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -92,6 +106,20 @@ dependencies:
|
|
|
92
106
|
- - "<"
|
|
93
107
|
- !ruby/object:Gem::Version
|
|
94
108
|
version: '3'
|
|
109
|
+
- !ruby/object:Gem::Dependency
|
|
110
|
+
name: shacl
|
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - "~>"
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '0.4'
|
|
116
|
+
type: :runtime
|
|
117
|
+
prerelease: false
|
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
119
|
+
requirements:
|
|
120
|
+
- - "~>"
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: '0.4'
|
|
95
123
|
- !ruby/object:Gem::Dependency
|
|
96
124
|
name: sts
|
|
97
125
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -170,6 +198,11 @@ files:
|
|
|
170
198
|
- README.adoc
|
|
171
199
|
- Rakefile
|
|
172
200
|
- config.yml
|
|
201
|
+
- data/concept-model/README.md
|
|
202
|
+
- data/concept-model/SOURCE.json
|
|
203
|
+
- data/concept-model/glossarist.context.jsonld
|
|
204
|
+
- data/concept-model/glossarist.ttl
|
|
205
|
+
- data/concept-model/shapes/glossarist.shacl.ttl
|
|
173
206
|
- exe/glossarist
|
|
174
207
|
- glossarist.gemspec
|
|
175
208
|
- lib/glossarist.rb
|
|
@@ -276,6 +309,7 @@ files:
|
|
|
276
309
|
- lib/glossarist/rdf/gloss_pronunciation.rb
|
|
277
310
|
- lib/glossarist/rdf/gloss_reference.rb
|
|
278
311
|
- lib/glossarist/rdf/localized_literal.rb
|
|
312
|
+
- lib/glossarist/rdf/lutaml_ext.rb
|
|
279
313
|
- lib/glossarist/rdf/namespaces.rb
|
|
280
314
|
- lib/glossarist/rdf/namespaces/dcterms_namespace.rb
|
|
281
315
|
- lib/glossarist/rdf/namespaces/glossarist_namespace.rb
|
|
@@ -288,6 +322,7 @@ files:
|
|
|
288
322
|
- lib/glossarist/rdf/relationship_predicates.rb
|
|
289
323
|
- lib/glossarist/rdf/v3.rb
|
|
290
324
|
- lib/glossarist/rdf/v3/configuration.rb
|
|
325
|
+
- lib/glossarist/reference.rb
|
|
291
326
|
- lib/glossarist/reference_extractor.rb
|
|
292
327
|
- lib/glossarist/reference_resolver.rb
|
|
293
328
|
- lib/glossarist/register_data.rb
|
|
@@ -313,6 +348,9 @@ files:
|
|
|
313
348
|
- lib/glossarist/sts/term_mapper.rb
|
|
314
349
|
- lib/glossarist/table.rb
|
|
315
350
|
- lib/glossarist/table_reference.rb
|
|
351
|
+
- lib/glossarist/tasks/shacl.rake
|
|
352
|
+
- lib/glossarist/tasks/sync.rake
|
|
353
|
+
- lib/glossarist/tasks/sync_model.rb
|
|
316
354
|
- lib/glossarist/transforms.rb
|
|
317
355
|
- lib/glossarist/transforms/concept_to_gloss_transform.rb
|
|
318
356
|
- lib/glossarist/transforms/concept_to_tbx_transform.rb
|
|
@@ -402,6 +440,7 @@ files:
|
|
|
402
440
|
- lib/glossarist/validation/rules/source_urn_format_rule.rb
|
|
403
441
|
- lib/glossarist/validation/rules/terms_presence_rule.rb
|
|
404
442
|
- lib/glossarist/validation/rules/uuid_format_rule.rb
|
|
443
|
+
- lib/glossarist/validation/shacl_validator.rb
|
|
405
444
|
- lib/glossarist/validation/validation_issue.rb
|
|
406
445
|
- lib/glossarist/validation_result.rb
|
|
407
446
|
- lib/glossarist/version.rb
|