glossarist 2.13.7 → 2.13.8
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/lib/glossarist/rdf/gloss_generic_member.rb +9 -2
- data/lib/glossarist/rdf/gloss_nary_member.rb +21 -12
- data/lib/glossarist/rdf/gloss_partitive_member.rb +5 -0
- data/lib/glossarist/transforms/concept_to_gloss_transform.rb +16 -4
- data/lib/glossarist/v3/abstract_hyperedge.rb +2 -2
- data/lib/glossarist/v3/generic_member.rb +43 -8
- data/lib/glossarist/v3/hyperedge_member.rb +16 -11
- data/lib/glossarist/v3/hyperedge_registry.rb +3 -1
- data/lib/glossarist/v3/hyperedge_writer.rb +5 -3
- data/lib/glossarist/v3/partitive_member.rb +24 -6
- data/lib/glossarist/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 439b6f94f23e6018ec771d6032a05f83aac496fb4a03c8d33cebc793886cc8fa
|
|
4
|
+
data.tar.gz: 8462a0e92e3e0ff0a9b3447fe94ae1ce9d8f3b59ce10955daeb746a4c0b514d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e6be9e8613779b1e7a791cc40df512e0592e9d3aa8d27d2339f80f04dc832e001024d412a71f20571e366b7be952581834e12e09dede444a8bf604a3b556e865
|
|
7
|
+
data.tar.gz: 37170de8e503b351d2e609fd91e294e10bd48f4ae53d20c81b3224737a6413cb53e593bab170e2ea9683f5583cc7969447492bd136ba1dcb2c559d707a9fe3eb
|
|
@@ -8,7 +8,14 @@ module Glossarist
|
|
|
8
8
|
# deterministic_id from GlossNaryMember. The `rdf do` block
|
|
9
9
|
# re-declares the predicates because lutaml-model's `rdf` DSL
|
|
10
10
|
# replaces the parent mapping (not extends).
|
|
11
|
+
#
|
|
12
|
+
# Carries `gloss:characteristic` — the delimiting characteristic
|
|
13
|
+
# text per ISO 704:2022 §5.5.4.2.1 (e.g., "detecting movement by
|
|
14
|
+
# means of light sensors"). Each species in a coordinate set has
|
|
15
|
+
# its own characteristic under the parent hyperedge's criterion.
|
|
11
16
|
class GlossGenericMember < GlossNaryMember
|
|
17
|
+
attribute :characteristic, :hash
|
|
18
|
+
|
|
12
19
|
rdf do
|
|
13
20
|
namespace Namespaces::GlossaristNamespace
|
|
14
21
|
|
|
@@ -26,8 +33,8 @@ module Glossarist
|
|
|
26
33
|
to: :presence
|
|
27
34
|
predicate :count, namespace: Namespaces::GlossaristNamespace,
|
|
28
35
|
to: :count
|
|
29
|
-
predicate :
|
|
30
|
-
|
|
36
|
+
predicate :characteristic, namespace: Namespaces::GlossaristNamespace,
|
|
37
|
+
to: :characteristic
|
|
31
38
|
end
|
|
32
39
|
end
|
|
33
40
|
end
|
|
@@ -4,27 +4,27 @@ require "lutaml/model"
|
|
|
4
4
|
|
|
5
5
|
module Glossarist
|
|
6
6
|
module Rdf
|
|
7
|
-
# Shared base for typed n-ary
|
|
7
|
+
# Shared base for typed n-ary hyperedge member RDF views
|
|
8
8
|
# (GlossPartitiveMember, GlossGenericMember, future leaves).
|
|
9
9
|
#
|
|
10
10
|
# Carries the shared attributes and the deterministic_id algorithm.
|
|
11
|
-
# Concrete leaves declare their own `rdf do` block
|
|
12
|
-
#
|
|
13
|
-
#
|
|
11
|
+
# Concrete leaves declare their own `rdf do` block AND their own
|
|
12
|
+
# type-specific attributes — `is_delimiting` on GlossPartitiveMember
|
|
13
|
+
# (binary role, ISO 704 §5.5.4.2.2); `characteristic` on
|
|
14
|
+
# GlossGenericMember (delimiting text, ISO 704 §5.5.4.2.1).
|
|
14
15
|
#
|
|
15
16
|
# Subject identity is content-derived so the same member in the
|
|
16
|
-
# same
|
|
17
|
+
# same hyperedge produces the same URI across runs (and across
|
|
17
18
|
# processes). Two members with identical ref + dimensions share a
|
|
18
19
|
# subject — that is intentional: it exposes model-level
|
|
19
|
-
# inconsistency if the same
|
|
20
|
-
#
|
|
20
|
+
# inconsistency if the same concept is given different dimensions
|
|
21
|
+
# inside the same dataset.
|
|
21
22
|
class GlossNaryMember < Lutaml::Model::Serializable
|
|
22
23
|
attribute :ref_id, :string
|
|
23
24
|
attribute :ref_source, :string
|
|
24
25
|
attribute :ref_text, :string
|
|
25
26
|
attribute :presence, :string
|
|
26
27
|
attribute :count, :string
|
|
27
|
-
attribute :is_delimiting, :boolean
|
|
28
28
|
|
|
29
29
|
# Human-readable SOURCE:ID when both are present; SHA-256 / 16
|
|
30
30
|
# hex chars fallback otherwise. Same content → same slug across
|
|
@@ -33,10 +33,19 @@ module Glossarist
|
|
|
33
33
|
readable = [member.ref_source, member.ref_id].compact.reject(&:empty?)
|
|
34
34
|
return readable.join(":") unless readable.empty?
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
36
|
+
parts = [member.ref_source, member.ref_id, member.ref_text,
|
|
37
|
+
member.presence, member.count]
|
|
38
|
+
# Type-specific discriminator: include the delimiting flag for
|
|
39
|
+
# partitive members (binary role) or the characteristic text
|
|
40
|
+
# for generic members (so members of different criteria don't
|
|
41
|
+
# collide on the same hash input).
|
|
42
|
+
case member
|
|
43
|
+
when GlossPartitiveMember
|
|
44
|
+
parts << member.is_delimiting
|
|
45
|
+
when GlossGenericMember
|
|
46
|
+
parts << member.characteristic
|
|
47
|
+
end
|
|
48
|
+
DeterministicSlug.from_parts(*parts)
|
|
40
49
|
end
|
|
41
50
|
end
|
|
42
51
|
end
|
|
@@ -8,7 +8,12 @@ module Glossarist
|
|
|
8
8
|
# deterministic_id from GlossNaryMember. The `rdf do` block
|
|
9
9
|
# re-declares the predicates because lutaml-model's `rdf` DSL
|
|
10
10
|
# replaces the parent mapping (not extends).
|
|
11
|
+
#
|
|
12
|
+
# Carries `gloss:isDelimiting` — the binary role flag per
|
|
13
|
+
# ISO 704:2022 §5.5.4.2.2 (a part is or is not a delimiting part).
|
|
11
14
|
class GlossPartitiveMember < GlossNaryMember
|
|
15
|
+
attribute :is_delimiting, :boolean
|
|
16
|
+
|
|
12
17
|
rdf do
|
|
13
18
|
namespace Namespaces::GlossaristNamespace
|
|
14
19
|
|
|
@@ -136,12 +136,12 @@ module Glossarist
|
|
|
136
136
|
partitive_relations: build_gloss_hyperedges(
|
|
137
137
|
relation_list, V3::PartitiveHyperedge,
|
|
138
138
|
:build_gloss_partitive_member, :partitive_member_ids,
|
|
139
|
-
:partitive_members, Rdf::GlossPartitiveRelation, identifier
|
|
139
|
+
:partitive_members, Rdf::GlossPartitiveRelation, identifier
|
|
140
140
|
),
|
|
141
141
|
generic_relations: build_gloss_hyperedges(
|
|
142
142
|
relation_list, V3::GenericHyperedge,
|
|
143
143
|
:build_gloss_generic_member, :generic_member_ids,
|
|
144
|
-
:generic_members, Rdf::GlossGenericRelation, identifier
|
|
144
|
+
:generic_members, Rdf::GlossGenericRelation, identifier
|
|
145
145
|
),
|
|
146
146
|
**rel_targets,
|
|
147
147
|
)
|
|
@@ -156,7 +156,7 @@ module Glossarist
|
|
|
156
156
|
member_ids_attr, members_attr,
|
|
157
157
|
gloss_relation_class, identifier)
|
|
158
158
|
Array(relations)
|
|
159
|
-
.
|
|
159
|
+
.grep(hyperedge_class)
|
|
160
160
|
.map { |rel| build_one_gloss_hyperedge(rel, member_builder, member_ids_attr, members_attr, gloss_relation_class, identifier) }
|
|
161
161
|
end
|
|
162
162
|
|
|
@@ -192,6 +192,8 @@ module Glossarist
|
|
|
192
192
|
|
|
193
193
|
# Shared member builder. Per-class metadata (the rdf view class
|
|
194
194
|
# is dispatched by the caller) keeps the duplication to one place.
|
|
195
|
+
# Per-type fields are dispatched by class — PartitiveMember
|
|
196
|
+
# carries `is_delimiting`; GenericMember carries `characteristic`.
|
|
195
197
|
def build_gloss_nary_member(gloss_member_class, member)
|
|
196
198
|
ref = member.ref
|
|
197
199
|
ref_attrs = if ref.is_a?(Glossarist::ConceptRef)
|
|
@@ -200,11 +202,21 @@ module Glossarist
|
|
|
200
202
|
{}
|
|
201
203
|
end
|
|
202
204
|
|
|
205
|
+
type_attrs =
|
|
206
|
+
case member
|
|
207
|
+
when V3::PartitiveMember
|
|
208
|
+
{ is_delimiting: member.is_delimiting }
|
|
209
|
+
when V3::GenericMember
|
|
210
|
+
{ characteristic: member.characteristic }
|
|
211
|
+
else
|
|
212
|
+
{}
|
|
213
|
+
end
|
|
214
|
+
|
|
203
215
|
gloss_member_class.new(
|
|
204
216
|
**ref_attrs,
|
|
205
217
|
presence: member.presence,
|
|
206
218
|
count: member.count,
|
|
207
|
-
|
|
219
|
+
**type_attrs,
|
|
208
220
|
)
|
|
209
221
|
end
|
|
210
222
|
|
|
@@ -114,8 +114,8 @@ module Glossarist
|
|
|
114
114
|
parts = [comprehensive.source, comprehensive.id].compact.reject(&:empty?)
|
|
115
115
|
return nil if parts.empty?
|
|
116
116
|
|
|
117
|
-
parts.join("-").downcase.gsub(/[^a-z0-9
|
|
118
|
-
|
|
117
|
+
parts.join("-").downcase.gsub(/[^a-z0-9-]/, "-")
|
|
118
|
+
.gsub(/-{2,}/, "-").gsub(/\A-|-\z/, "")
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
# Kebab-case slug derived from the English criterion. Falls back
|
|
@@ -2,16 +2,51 @@
|
|
|
2
2
|
|
|
3
3
|
module Glossarist
|
|
4
4
|
module V3
|
|
5
|
-
# GenericMember — one member of a GenericHyperedge.
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# GenericMember — one member (species) of a GenericHyperedge. The
|
|
6
|
+
# `comprehensive` of its parent GenericHyperedge denotes the genus
|
|
7
|
+
# concept; this member denotes one species.
|
|
8
8
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# Per ISO 704:2022 §5.5.4.2.1, the intension of a species includes
|
|
10
|
+
# the intension of the genus plus at least one additional
|
|
11
|
+
# DELIMITING CHARACTERISTIC. Each species in a coordinate set
|
|
12
|
+
# (siblings sharing the same criterion of subdivision) carries its
|
|
13
|
+
# own delimiting characteristic value.
|
|
14
|
+
#
|
|
15
|
+
# Example (ISO 704 §5.5.4.2.1 Example 3):
|
|
16
|
+
# Hyperedge comprehensive: computer mouse
|
|
17
|
+
# Hyperedge criterion (of subdivision): means of movement detection
|
|
18
|
+
# Members:
|
|
19
|
+
# - mechanical mouse
|
|
20
|
+
# characteristic: "detecting movement by means of rollers"
|
|
21
|
+
# - optomechanical mouse
|
|
22
|
+
# characteristic: "detecting movement by means of rollers and light sensors"
|
|
23
|
+
# - optical mouse
|
|
24
|
+
# characteristic: "detecting movement by means of light sensors"
|
|
25
|
+
#
|
|
26
|
+
# Multidimensionality (ISO 704 §5.6.3): the same genus can have
|
|
27
|
+
# multiple GenericHyperedges, each with a different criterion
|
|
28
|
+
# (e.g., means of movement detection vs computer connection). The
|
|
29
|
+
# `characteristic` on each member is meaningful only within its
|
|
30
|
+
# parent hyperedge's criterion context.
|
|
31
|
+
#
|
|
32
|
+
# Distinct from PartitiveMember: partitive members are binary
|
|
33
|
+
# delimiting (a part is or isn't delimiting); generic members are
|
|
34
|
+
# textually delimiting (each species has its own characteristic
|
|
35
|
+
# phrase that distinguishes it from coordinate concepts).
|
|
11
36
|
class GenericMember < HyperedgeMember
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
37
|
+
# The delimiting characteristic of this species under the parent
|
|
38
|
+
# hyperedge's criterion of subdivision. Localized — different
|
|
39
|
+
# languages may express the same characteristic differently.
|
|
40
|
+
# Required for semantic completeness per ISO 704 §5.5.4.2.1, but
|
|
41
|
+
# the model permits nil to allow incremental population.
|
|
42
|
+
attribute :characteristic, :hash
|
|
43
|
+
|
|
44
|
+
key_value do
|
|
45
|
+
map :ref, to: :ref
|
|
46
|
+
map :presence, to: :presence
|
|
47
|
+
map :count, to: :count
|
|
48
|
+
map :characteristic, to: :characteristic
|
|
49
|
+
end
|
|
15
50
|
end
|
|
16
51
|
end
|
|
17
52
|
end
|
|
@@ -3,14 +3,25 @@
|
|
|
3
3
|
module Glossarist
|
|
4
4
|
module V3
|
|
5
5
|
# HyperedgeMember — abstract base shape for members of any
|
|
6
|
-
# n-ary concept-system
|
|
6
|
+
# n-ary concept-system hyperedge (PartitiveMember, GenericMember,
|
|
7
7
|
# future AssociativeMember, SequentialMember).
|
|
8
8
|
#
|
|
9
|
-
# Carries the shared ISO 704:2022 MECE dimensions
|
|
10
|
-
#
|
|
9
|
+
# Carries the shared ISO 704:2022 MECE dimensions on every member:
|
|
10
|
+
# presence — required (default) | optional
|
|
11
|
+
# count — exactly_one (default) | at_least_one | multiple
|
|
11
12
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
13
|
+
# Type-specific extensions live on the leaves:
|
|
14
|
+
# PartitiveMember — `is_delimiting` (Boolean): per ISO 704
|
|
15
|
+
# §5.5.4.2.2, a part is or is not a delimiting part. Binary role.
|
|
16
|
+
# GenericMember — `characteristic` (LocalizedString): per ISO 704
|
|
17
|
+
# §5.5.4.2.1, each species carries a delimiting characteristic
|
|
18
|
+
# text (e.g., "detecting movement by means of light sensors")
|
|
19
|
+
# that distinguishes it from coordinate concepts under the
|
|
20
|
+
# hyperedge's criterion of subdivision.
|
|
21
|
+
#
|
|
22
|
+
# The combination (optional, at_least_one) is invalid and collapses
|
|
23
|
+
# to (optional, multiple). Multiplicity is the SSOT for the
|
|
24
|
+
# validation; this class delegates to it.
|
|
14
25
|
class HyperedgeMember < Lutaml::Model::Serializable
|
|
15
26
|
DEFAULT_PRESENCE = "required"
|
|
16
27
|
DEFAULT_COUNT = "exactly_one"
|
|
@@ -22,13 +33,11 @@ module Glossarist
|
|
|
22
33
|
attribute :count, :string,
|
|
23
34
|
values: Glossarist::GlossaryDefinition::MEMBER_COUNT_VALUES,
|
|
24
35
|
default: -> { DEFAULT_COUNT }
|
|
25
|
-
attribute :is_delimiting, :boolean, default: -> { false }
|
|
26
36
|
|
|
27
37
|
key_value do
|
|
28
38
|
map :ref, to: :ref
|
|
29
39
|
map :presence, to: :presence
|
|
30
40
|
map :count, to: :count
|
|
31
|
-
map :is_delimiting, to: :is_delimiting
|
|
32
41
|
end
|
|
33
42
|
|
|
34
43
|
def initialize(*)
|
|
@@ -55,10 +64,6 @@ module Glossarist
|
|
|
55
64
|
presence == "optional"
|
|
56
65
|
end
|
|
57
66
|
|
|
58
|
-
def delimiting?
|
|
59
|
-
is_delimiting == true
|
|
60
|
-
end
|
|
61
|
-
|
|
62
67
|
private
|
|
63
68
|
|
|
64
69
|
def validate_ref!
|
|
@@ -15,10 +15,12 @@ module Glossarist
|
|
|
15
15
|
# validator, RDF emitter, RelationLoader) — they all iterate or
|
|
16
16
|
# resolve through this registry.
|
|
17
17
|
module HyperedgeRegistry
|
|
18
|
-
#
|
|
18
|
+
# rubocop:disable Style/MutableConstant — these MUST stay
|
|
19
|
+
# mutable; register() adds entries at load time.
|
|
19
20
|
BY_WIRE_KEY = {}
|
|
20
21
|
BY_TYPE_TAG = {}
|
|
21
22
|
BY_RDF_TYPE = {}
|
|
23
|
+
# rubocop:enable Style/MutableConstant
|
|
22
24
|
|
|
23
25
|
Mutex = ::Mutex.new
|
|
24
26
|
|
|
@@ -45,8 +45,10 @@ module Glossarist
|
|
|
45
45
|
hyperedge.is_a?(AbstractHyperedge)
|
|
46
46
|
|
|
47
47
|
path = hyperedge.file_path(@relations_dir)
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
unless path
|
|
49
|
+
raise WriteError,
|
|
50
|
+
"cannot derive file path — comprehensive must be non-empty"
|
|
51
|
+
end
|
|
50
52
|
|
|
51
53
|
FileUtils.mkdir_p(File.dirname(path))
|
|
52
54
|
File.write(path, serialize(hyperedge))
|
|
@@ -72,7 +74,7 @@ module Glossarist
|
|
|
72
74
|
ordered["type"] = hash.delete("type")
|
|
73
75
|
ordered["status"] = hash.delete("status") if hash.key?("status")
|
|
74
76
|
ordered["comprehensive"] = hash.delete("comprehensive")
|
|
75
|
-
ordered["members"]
|
|
77
|
+
ordered["members"] = hash.delete("members")
|
|
76
78
|
ordered["completeness"] = hash.delete("completeness") if hash.key?("completeness")
|
|
77
79
|
ordered["criterion"] = hash.delete("criterion") if hash.key?("criterion")
|
|
78
80
|
ordered["sources"] = hash.delete("sources") if hash.key?("sources")
|
|
@@ -2,15 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
module Glossarist
|
|
4
4
|
module V3
|
|
5
|
-
# PartitiveMember — one member of a PartitiveHyperedge.
|
|
6
|
-
# the ISO 704:2022 MECE shape from HyperedgeMember; the
|
|
5
|
+
# PartitiveMember — one member of a PartitiveHyperedge. The
|
|
7
6
|
# `comprehensive` of its parent PartitiveHyperedge denotes the
|
|
8
|
-
# whole concept.
|
|
7
|
+
# whole concept; this member denotes one of its parts.
|
|
9
8
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
9
|
+
# Per ISO 704:2022 §5.5.4.2.2, a part is either delimiting or not:
|
|
10
|
+
# a delimiting part behaves like a delimiting characteristic — it
|
|
11
|
+
# distinguishes the comprehensive (whole) from coordinate concepts.
|
|
12
|
+
# Example: for "optomechanical mouse", the delimiting parts are
|
|
13
|
+
# mouse ball, x/y-axis rollers, infrared emitter/sensor — they
|
|
14
|
+
# distinguish it from "mechanical mouse" and "optical mouse".
|
|
15
|
+
# Mouse button is NOT delimiting (all computer mice have buttons).
|
|
16
|
+
#
|
|
17
|
+
# The binary role is sufficient — no per-member delimiting text is
|
|
18
|
+
# needed because the part itself IS the delimiting marker.
|
|
12
19
|
class PartitiveMember < HyperedgeMember
|
|
13
|
-
|
|
20
|
+
attribute :is_delimiting, :boolean, default: -> { false }
|
|
21
|
+
|
|
22
|
+
key_value do
|
|
23
|
+
map :ref, to: :ref
|
|
24
|
+
map :presence, to: :presence
|
|
25
|
+
map :count, to: :count
|
|
26
|
+
map :is_delimiting, to: :is_delimiting
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def delimiting?
|
|
30
|
+
is_delimiting == true
|
|
31
|
+
end
|
|
14
32
|
end
|
|
15
33
|
end
|
|
16
34
|
end
|
data/lib/glossarist/version.rb
CHANGED
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.13.
|
|
4
|
+
version: 2.13.8
|
|
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-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|