suma 0.1.14 → 0.1.15
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 +25 -27
- data/README.adoc +57 -13
- data/lib/suma/cli/extract_terms.rb +307 -150
- data/lib/suma/cli/reformat.rb +1 -1
- data/lib/suma/cli/validate_links.rb +2 -2
- data/lib/suma/collection_manifest.rb +3 -2
- data/lib/suma/processor.rb +0 -1
- data/lib/suma/schema_attachment.rb +3 -3
- data/lib/suma/schema_collection.rb +2 -2
- data/lib/suma/version.rb +1 -1
- data/lib/suma.rb +1 -0
- data/suma.gemspec +1 -0
- metadata +16 -5
- data/lib/suma/schema_config/config.rb +0 -147
- data/lib/suma/schema_config/schema.rb +0 -19
- data/lib/suma/schema_config.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52836adb9e003f9d760a6c015207379be88b8821855d64388a5f30d09474de7e
|
4
|
+
data.tar.gz: d7427de3e6dc21291671122bd07bc23c739e4f59f031e3b02988f89254767d00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0de4abdc501a6dba9b716e7ad9a15f66985bec98b2978c9f1b25ed0f069d02d8a172f8b78c442e8f90e32098ad1622a3ba16a890c2ed57d896c4c2b427c5c3e
|
7
|
+
data.tar.gz: ed0f32387285db507797e7b34962a20e4dc6174e7389ffa2488afb8724668c11d1e0089e9e2b62a958875e0e2bb9d7f4976d5d0ef887cd83604acb4939d25b7a
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2025-
|
3
|
+
# on 2025-07-05 22:42:28 UTC using RuboCop version 1.77.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -13,43 +13,32 @@ Gemspec/DuplicatedAssignment:
|
|
13
13
|
Exclude:
|
14
14
|
- 'suma.gemspec'
|
15
15
|
|
16
|
-
# Offense count:
|
17
|
-
# This cop supports safe autocorrection (--autocorrect).
|
18
|
-
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
19
|
-
# SupportedHashRocketStyles: key, separator, table
|
20
|
-
# SupportedColonStyles: key, separator, table
|
21
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
22
|
-
Layout/HashAlignment:
|
23
|
-
Exclude:
|
24
|
-
- 'lib/suma/cli/validate.rb'
|
25
|
-
|
26
|
-
# Offense count: 55
|
16
|
+
# Offense count: 57
|
27
17
|
# This cop supports safe autocorrection (--autocorrect).
|
28
|
-
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
18
|
+
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
29
19
|
# URISchemes: http, https
|
30
20
|
Layout/LineLength:
|
31
21
|
Exclude:
|
32
22
|
- 'lib/suma/cli.rb'
|
33
23
|
- 'lib/suma/cli/build.rb'
|
24
|
+
- 'lib/suma/cli/extract_terms.rb'
|
34
25
|
- 'lib/suma/cli/validate.rb'
|
35
26
|
- 'lib/suma/cli/validate_ascii.rb'
|
36
27
|
- 'lib/suma/cli/validate_links.rb'
|
37
|
-
- 'lib/suma/collection_manifest.rb'
|
38
28
|
- 'lib/suma/processor.rb'
|
39
29
|
- 'lib/suma/schema_attachment.rb'
|
40
30
|
- 'lib/suma/schema_collection.rb'
|
41
31
|
- 'lib/suma/schema_document.rb'
|
42
32
|
- 'lib/suma/thor_ext.rb'
|
33
|
+
- 'spec/suma/cli/extract_terms_spec.rb'
|
43
34
|
- 'spec/suma/cli/validate_ascii_spec.rb'
|
44
35
|
- 'suma.gemspec'
|
45
36
|
|
46
|
-
# Offense count:
|
47
|
-
#
|
48
|
-
|
49
|
-
Layout/TrailingWhitespace:
|
37
|
+
# Offense count: 1
|
38
|
+
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
39
|
+
Lint/DuplicateBranch:
|
50
40
|
Exclude:
|
51
|
-
- 'lib/suma/cli.rb'
|
52
|
-
- 'lib/suma/cli/validate.rb'
|
41
|
+
- 'lib/suma/cli/extract_terms.rb'
|
53
42
|
|
54
43
|
# Offense count: 2
|
55
44
|
Lint/DuplicateMethods:
|
@@ -57,10 +46,11 @@ Lint/DuplicateMethods:
|
|
57
46
|
- 'lib/suma/cli/validate_ascii.rb'
|
58
47
|
- 'lib/suma/express_schema.rb'
|
59
48
|
|
60
|
-
# Offense count:
|
49
|
+
# Offense count: 20
|
61
50
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
62
51
|
Metrics/AbcSize:
|
63
52
|
Exclude:
|
53
|
+
- 'lib/suma/cli/extract_terms.rb'
|
64
54
|
- 'lib/suma/cli/validate_ascii.rb'
|
65
55
|
- 'lib/suma/cli/validate_links.rb'
|
66
56
|
- 'lib/suma/schema_attachment.rb'
|
@@ -73,15 +63,16 @@ Metrics/AbcSize:
|
|
73
63
|
Metrics/BlockLength:
|
74
64
|
Max: 64
|
75
65
|
|
76
|
-
# Offense count:
|
66
|
+
# Offense count: 8
|
77
67
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
78
68
|
Metrics/CyclomaticComplexity:
|
79
69
|
Exclude:
|
70
|
+
- 'lib/suma/cli/extract_terms.rb'
|
80
71
|
- 'lib/suma/cli/validate_ascii.rb'
|
81
72
|
- 'lib/suma/cli/validate_links.rb'
|
82
73
|
- 'lib/suma/thor_ext.rb'
|
83
74
|
|
84
|
-
# Offense count:
|
75
|
+
# Offense count: 30
|
85
76
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
86
77
|
Metrics/MethodLength:
|
87
78
|
Max: 107
|
@@ -91,10 +82,11 @@ Metrics/MethodLength:
|
|
91
82
|
Metrics/ParameterLists:
|
92
83
|
Max: 6
|
93
84
|
|
94
|
-
# Offense count:
|
85
|
+
# Offense count: 5
|
95
86
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
96
87
|
Metrics/PerceivedComplexity:
|
97
88
|
Exclude:
|
89
|
+
- 'lib/suma/cli/extract_terms.rb'
|
98
90
|
- 'lib/suma/cli/validate_ascii.rb'
|
99
91
|
- 'lib/suma/cli/validate_links.rb'
|
100
92
|
|
@@ -113,12 +105,12 @@ Performance/CollectionLiteralInLoop:
|
|
113
105
|
Exclude:
|
114
106
|
- 'spec/suma/cli_spec.rb'
|
115
107
|
|
116
|
-
# Offense count:
|
108
|
+
# Offense count: 9
|
117
109
|
# Configuration parameters: CountAsOne.
|
118
110
|
RSpec/ExampleLength:
|
119
|
-
Max:
|
111
|
+
Max: 44
|
120
112
|
|
121
|
-
# Offense count:
|
113
|
+
# Offense count: 6
|
122
114
|
RSpec/MultipleExpectations:
|
123
115
|
Max: 12
|
124
116
|
|
@@ -136,3 +128,9 @@ Style/EmptyElse:
|
|
136
128
|
# SupportedStyles: annotated, template, unannotated
|
137
129
|
Style/FormatStringToken:
|
138
130
|
EnforcedStyle: unannotated
|
131
|
+
|
132
|
+
# Offense count: 1
|
133
|
+
# Configuration parameters: Max.
|
134
|
+
Style/SafeNavigationChainLength:
|
135
|
+
Exclude:
|
136
|
+
- 'lib/suma/cli/extract_terms.rb'
|
data/README.adoc
CHANGED
@@ -331,8 +331,10 @@ out which schemas the document includes.
|
|
331
331
|
|
332
332
|
=== Extract terms command
|
333
333
|
|
334
|
-
The `suma extract_terms` command extracts terms from
|
335
|
-
generates Glossarist v2 dataset in the output directory.
|
334
|
+
The `suma extract_terms` command extracts terms from EXPRESS schemas and
|
335
|
+
generates a Glossarist v2 dataset in the output directory. This command processes
|
336
|
+
various types of STEP schemas and creates standardized terminology datasets
|
337
|
+
suitable for glossary and dictionary applications.
|
336
338
|
|
337
339
|
[source,sh]
|
338
340
|
----
|
@@ -341,38 +343,80 @@ $ suma extract_terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH [options]
|
|
341
343
|
|
342
344
|
Parameters:
|
343
345
|
|
344
|
-
`SCHEMA_MANIFEST_FILE`:: Path to
|
346
|
+
`SCHEMA_MANIFEST_FILE`:: Path to the schema manifest file that lists all schemas
|
347
|
+
to process (e.g., "schemas-smrl-all.yml")
|
345
348
|
|
346
|
-
`GLOSSARIST_OUTPUT_PATH`:: Path to the output directory
|
347
|
-
dataset
|
349
|
+
`GLOSSARIST_OUTPUT_PATH`:: Path to the output directory where the Glossarist v2
|
350
|
+
dataset will be generated
|
348
351
|
|
349
352
|
Options:
|
350
353
|
|
351
|
-
|
354
|
+
`--language_code`, `-l`:: Language code for the Glossarist dataset (default: "eng")
|
352
355
|
|
356
|
+
==== Supported schema types
|
357
|
+
|
358
|
+
The command supports extraction from the following EXPRESS schema types:
|
359
|
+
|
360
|
+
* **ARM (Application Reference Model)** - Application module schemas ending with `_arm`
|
361
|
+
* **MIM (Module Implementation Model)** - Application module schemas ending with `_mim`
|
362
|
+
* **Resource schemas** - General resource schemas
|
363
|
+
* **BOM (Business Object Model)** - Business object model schemas ending with `_bom`
|
364
|
+
|
365
|
+
==== Extracted terms
|
366
|
+
|
367
|
+
The command extracts the following types of terms from EXPRESS schemas:
|
368
|
+
|
369
|
+
* **Entities** - EXPRESS entity definitions with their attributes and relationships
|
370
|
+
* **Types** - EXPRESS type definitions including enumerations and select types
|
371
|
+
* **Functions** - EXPRESS function definitions
|
372
|
+
* **Procedures** - EXPRESS procedure definitions
|
373
|
+
* **Constants** - EXPRESS constant definitions
|
374
|
+
|
375
|
+
Each extracted term includes:
|
376
|
+
|
377
|
+
* Unique identifier based on schema and term name
|
378
|
+
* Term definition and description
|
379
|
+
* Source schema information
|
380
|
+
* Appropriate domain classification (application module, resource, or business object model)
|
381
|
+
|
382
|
+
==== Output format
|
383
|
+
|
384
|
+
The command generates a Glossarist v2 compliant dataset with:
|
385
|
+
|
386
|
+
* `concept/` directory containing concept definition files
|
387
|
+
* `localized_concept/` directory containing localized concept files
|
388
|
+
* YAML format following Glossarist v2 schema specifications
|
389
|
+
* Proper cross-references and citations to source schemas
|
390
|
+
|
391
|
+
.To extract terms from a schema manifest file
|
353
392
|
[example]
|
354
393
|
====
|
355
|
-
.To extract terms from SCHEMA_MANIFEST_FILE
|
356
394
|
[source,sh]
|
357
395
|
----
|
358
|
-
$ bundle exec suma extract_terms
|
359
|
-
# => generates glossarist_output/concept
|
396
|
+
$ bundle exec suma extract_terms schemas-smrl-all.yml glossarist_output
|
397
|
+
# => generates glossarist_output/concept/*.yaml and glossarist_output/localized_concept/*.yaml
|
360
398
|
----
|
399
|
+
====
|
361
400
|
|
362
|
-
.To extract terms from
|
401
|
+
.To extract terms from a specific schema subset
|
402
|
+
[example]
|
403
|
+
====
|
363
404
|
[source,sh]
|
364
405
|
----
|
365
|
-
$ bundle exec suma extract_terms
|
366
|
-
# =>
|
406
|
+
$ bundle exec suma extract_terms schemas-activity-modules.yml terms_output
|
407
|
+
# => processes only schemas listed in the manifest file
|
367
408
|
----
|
368
409
|
====
|
369
410
|
|
411
|
+
The generated dataset is meant to be used for ISO 10303-2.
|
412
|
+
|
370
413
|
|
371
414
|
== Usage: Ruby
|
372
415
|
|
373
416
|
=== General
|
374
417
|
|
375
|
-
Suma can be used programmatically in your Ruby applications. The following
|
418
|
+
Suma can be used programmatically in your Ruby applications. The following
|
419
|
+
examples demonstrate common usage patterns.
|
376
420
|
|
377
421
|
=== Building collections
|
378
422
|
|
@@ -4,7 +4,6 @@ require "thor"
|
|
4
4
|
require_relative "../thor_ext"
|
5
5
|
require "fileutils"
|
6
6
|
require "expressir"
|
7
|
-
require "yaml"
|
8
7
|
require "securerandom"
|
9
8
|
require "glossarist"
|
10
9
|
|
@@ -19,23 +18,13 @@ module Suma
|
|
19
18
|
option :language_code, type: :string, default: "eng", aliases: "-l",
|
20
19
|
desc: "Language code for the Glossarist"
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
def extract_terms(schema_manifest_file, output_path) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
21
|
+
def extract_terms(schema_manifest_file, output_path)
|
25
22
|
language_code = options[:language_code]
|
26
23
|
schema_manifest_file = File.expand_path(schema_manifest_file)
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
"`#{schema_manifest_file}` not found."
|
32
|
-
end
|
33
|
-
|
34
|
-
if !YAML_FILE_EXTENSIONS.include?(File.extname(schema_manifest_file))
|
35
|
-
raise ArgumentError, "Specified SCHEMA_MANIFEST_FILE " \
|
36
|
-
"`#{schema_manifest_file}` " \
|
37
|
-
"is not a YAML file."
|
38
|
-
end
|
25
|
+
unless File.exist?(schema_manifest_file)
|
26
|
+
raise Errno::ENOENT, "Specified SCHEMA_MANIFEST_FILE " \
|
27
|
+
"`#{schema_manifest_file}` not found."
|
39
28
|
end
|
40
29
|
|
41
30
|
run(schema_manifest_file, output_path, language_code)
|
@@ -44,152 +33,184 @@ module Suma
|
|
44
33
|
private
|
45
34
|
|
46
35
|
def run(schema_manifest_file, output_path, language_code = "eng")
|
47
|
-
|
48
|
-
|
49
|
-
exp_files.map do |exp_file|
|
36
|
+
get_exp_files(schema_manifest_file).map do |exp_file|
|
50
37
|
extract(exp_file, output_path, language_code)
|
51
38
|
end
|
52
39
|
end
|
53
40
|
|
54
41
|
def get_exp_files(schema_manifest_file)
|
55
|
-
|
56
|
-
|
57
|
-
permitted_classes: [Date, Time, Symbol],
|
58
|
-
permitted_symbols: [],
|
59
|
-
aliases: true,
|
60
|
-
)
|
61
|
-
|
62
|
-
paths = data["schemas"].values.filter_map { |v| v["path"] }
|
42
|
+
config = Expressir::SchemaManifest.from_file(schema_manifest_file)
|
43
|
+
paths = config.schemas.map(&:path)
|
63
44
|
|
64
45
|
if paths.empty?
|
65
46
|
raise Errno::ENOENT, "No EXPRESS files found in " \
|
66
47
|
"`#{schema_manifest_file}`."
|
67
48
|
end
|
68
49
|
|
69
|
-
|
70
|
-
paths.map do |path|
|
71
|
-
File.expand_path(path, File.dirname(schema_manifest_file))
|
72
|
-
end
|
50
|
+
paths
|
73
51
|
end
|
74
52
|
|
75
|
-
def extract(exp_file, output_path, language_code)
|
76
|
-
|
53
|
+
def extract(exp_file, output_path, language_code)
|
54
|
+
exp_path_rel = Pathname.new(exp_file).relative_path_from(Pathname.getwd)
|
55
|
+
puts "Building terms: #{exp_path_rel}"
|
56
|
+
|
77
57
|
repo = Expressir::Express::Parser.from_file(exp_file)
|
78
58
|
schema = get_default_schema(repo)
|
79
59
|
|
60
|
+
unless schema.file
|
61
|
+
raise Error.new("Schema must have an associated file")
|
62
|
+
end
|
63
|
+
|
80
64
|
collection = build_managed_concept_collection(
|
81
65
|
schema, language_code
|
82
66
|
)
|
83
67
|
|
84
|
-
output_data(collection, output_path
|
68
|
+
output_data(collection, output_path)
|
85
69
|
end
|
86
70
|
|
87
|
-
def output_data(collection, output_path
|
71
|
+
def output_data(collection, output_path)
|
88
72
|
unless File.exist?(output_path)
|
89
73
|
FileUtils.mkdir_p(File.expand_path(output_path))
|
90
74
|
end
|
91
75
|
|
92
|
-
puts "Saving collection to files in: #{
|
76
|
+
puts "Saving collection to files in: #{output_path}"
|
93
77
|
collection.save_to_files(File.expand_path(output_path))
|
94
78
|
|
95
|
-
puts "Processing EXPRESS file: #{exp_file}...Done."
|
96
79
|
collection
|
97
80
|
end
|
98
81
|
|
99
|
-
def build_managed_concept_collection(schema, language_code)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
schema
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
82
|
+
def build_managed_concept_collection(schema, language_code)
|
83
|
+
Glossarist::ManagedConceptCollection.new.tap do |collection|
|
84
|
+
# Extract schema-level citation data once to reuse across all entities
|
85
|
+
source_ref = get_source_ref(schema)
|
86
|
+
|
87
|
+
# Create one concept per entity
|
88
|
+
schema.entities.each do |entity|
|
89
|
+
localized_concept = build_localized_concept(
|
90
|
+
schema: schema,
|
91
|
+
entity: entity,
|
92
|
+
language_code: language_code,
|
93
|
+
source_ref: source_ref,
|
94
|
+
)
|
95
|
+
|
96
|
+
managed_data = Glossarist::ManagedConceptData.new.tap do |data|
|
97
|
+
data.id = get_entity_identifier(schema, entity)
|
98
|
+
|
99
|
+
# TODO: Why do we need both localizations and localized_concepts??
|
100
|
+
data.localizations[language_code] = localized_concept
|
101
|
+
# uuid is automatically set from the serialization of the object
|
102
|
+
data.localized_concepts = {
|
103
|
+
language_code => get_localized_concept_identifier(
|
104
|
+
schema, entity, language_code
|
105
|
+
),
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
managed_concept = Glossarist::ManagedConcept.new.tap do |concept|
|
110
|
+
# uuid is automatically set from the serialization of the object
|
111
|
+
concept.id = get_entity_identifier(schema, entity)
|
112
|
+
concept.uuid = concept.id
|
113
|
+
concept.data = managed_data
|
114
|
+
end
|
115
|
+
|
116
|
+
collection.store(managed_concept)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
110
120
|
|
111
|
-
|
112
|
-
|
113
|
-
}
|
121
|
+
def build_localized_concept(schema:, entity:, language_code:, source_ref:)
|
122
|
+
schema_domain = get_domain(schema)
|
114
123
|
|
115
|
-
|
116
|
-
|
117
|
-
|
124
|
+
localized_concept_data = Glossarist::ConceptData.new.tap do |data|
|
125
|
+
data.terms = get_entity_terms(entity)
|
126
|
+
data.definition = get_entity_definitions(entity, schema)
|
127
|
+
data.language_code = language_code
|
128
|
+
data.domain = schema_domain
|
129
|
+
data.sources = [source_ref] if source_ref
|
118
130
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
131
|
+
# Only assign optional fields if they have content
|
132
|
+
notes = get_entity_notes(entity, schema_domain)
|
133
|
+
data.notes = notes if notes && !notes.empty?
|
123
134
|
|
124
|
-
|
125
|
-
|
135
|
+
examples = get_entity_examples(entity, schema_domain)
|
136
|
+
data.examples = examples if examples && !examples.empty?
|
137
|
+
end
|
126
138
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
localized_concept_data.notes = get_notes(schema, schema_domain) || []
|
131
|
-
localized_concept_data.examples = get_examples(schema,
|
132
|
-
schema_domain) || []
|
133
|
-
localized_concept_data.language_code = language_code
|
134
|
-
localized_concept_data.domain = schema_domain
|
135
|
-
localized_concept_data.sources = get_source_ref(schema) || []
|
136
|
-
|
137
|
-
localized_concept = Glossarist::LocalizedConcept.new
|
138
|
-
localized_concept.data = localized_concept_data
|
139
|
-
|
140
|
-
localized_concept.uuid = localized_concept_id
|
141
|
-
localized_concept
|
139
|
+
Glossarist::LocalizedConcept.new.tap do |concept|
|
140
|
+
concept.data = localized_concept_data
|
141
|
+
end
|
142
142
|
end
|
143
143
|
|
144
|
+
# We only deal with 1 schema
|
144
145
|
def get_default_schema(repo)
|
145
146
|
repo.schemas.first
|
146
147
|
end
|
147
148
|
|
148
|
-
def
|
149
|
-
|
150
|
-
s.id == "__identifier"
|
151
|
-
end
|
152
|
-
remark_item.remarks.first || SecureRandom.uuid
|
149
|
+
def find_remark_value(schema, remark_id)
|
150
|
+
schema.remark_items.find { |s| s.id == remark_id }&.remarks&.first
|
153
151
|
end
|
154
152
|
|
155
|
-
def
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
153
|
+
def get_entity_identifier(schema, entity)
|
154
|
+
"#{schema.id}.#{entity.id}"
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_localized_concept_identifier(schema, entity, lang)
|
158
|
+
"#{schema.id}.#{entity.id}-#{lang}"
|
160
159
|
end
|
161
160
|
|
162
161
|
def get_source_ref(schema)
|
163
|
-
|
164
|
-
|
162
|
+
origin = Glossarist::Citation.new.tap do |citation|
|
163
|
+
citation.ref = "ISO 10303"
|
164
|
+
custom_locality = build_custom_locality(schema)
|
165
|
+
|
166
|
+
unless custom_locality.empty?
|
167
|
+
citation.custom_locality = custom_locality
|
168
|
+
end
|
165
169
|
end
|
166
|
-
ref = remark_item&.remarks&.first
|
167
170
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
171
|
+
Glossarist::ConceptSource.new(type: "authoritative", origin: origin)
|
172
|
+
end
|
173
|
+
|
174
|
+
# SCHEMA action_schema
|
175
|
+
# '{iso standard 10303 part(41) version(9) object(1) action-schema(1)}';
|
176
|
+
def build_custom_locality(schema)
|
177
|
+
[].tap do |localities|
|
178
|
+
# Add schema name
|
179
|
+
localities << Glossarist::CustomLocality.new(
|
180
|
+
name: "schema",
|
181
|
+
value: schema.id,
|
172
182
|
)
|
183
|
+
|
184
|
+
# Add version if available
|
185
|
+
version_item = schema.version.items.detect { |i| i.name == "version" }
|
186
|
+
if version_item
|
187
|
+
localities << Glossarist::CustomLocality.new(
|
188
|
+
name: "version",
|
189
|
+
value: version_item.value,
|
190
|
+
)
|
191
|
+
end
|
173
192
|
end
|
174
193
|
end
|
175
194
|
|
195
|
+
# TODO: What if this was a "bom"?
|
176
196
|
def get_domain(schema)
|
177
|
-
prefix =
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
remark_item = schema.remark_items.find do |s|
|
183
|
-
s.id == "__schema_file"
|
184
|
-
end
|
197
|
+
prefix = if mim?(schema.id) || arm?(schema.id)
|
198
|
+
"application module"
|
199
|
+
else
|
200
|
+
"resource"
|
201
|
+
end
|
185
202
|
|
186
|
-
|
203
|
+
"#{prefix}: #{schema.id}"
|
187
204
|
end
|
188
205
|
|
189
206
|
def arm?(schema_id)
|
190
207
|
schema_id.end_with?("_arm")
|
191
208
|
end
|
192
209
|
|
210
|
+
def mim?(schema_id)
|
211
|
+
schema_id.end_with?("_mim")
|
212
|
+
end
|
213
|
+
|
193
214
|
def get_terms(schema)
|
194
215
|
schema_title = get_title(schema)
|
195
216
|
if schema_title
|
@@ -203,69 +224,210 @@ module Suma
|
|
203
224
|
end
|
204
225
|
end
|
205
226
|
|
206
|
-
def
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
227
|
+
def get_entity_terms(entity)
|
228
|
+
# For now, use the entity ID as the term
|
229
|
+
# This could be enhanced to look for entity-specific title remark items
|
230
|
+
[
|
231
|
+
Glossarist::Designation::Base.new(
|
232
|
+
designation: entity.id,
|
233
|
+
type: "expression",
|
234
|
+
normative_status: "preferred",
|
235
|
+
),
|
236
|
+
]
|
212
237
|
end
|
213
238
|
|
214
|
-
def
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
represent_str = "that represents the #{get_title(schema)} {{entity}}"
|
219
|
-
if subtype
|
220
|
-
represent_str = "that is a type of #{subtype} #{represent_str}"
|
221
|
-
end
|
239
|
+
def get_entity_definitions(entity, schema)
|
240
|
+
schema_type = extract_file_type(schema.file)
|
241
|
+
schema_domain = get_domain(schema)
|
222
242
|
|
223
|
-
definition =
|
224
|
-
|
225
|
-
"{{application object}} #{represent_str}"
|
226
|
-
else
|
227
|
-
"{{entity data type}} #{represent_str}"
|
228
|
-
end
|
243
|
+
definition = generate_entity_definition(entity, schema_domain,
|
244
|
+
schema_type)
|
229
245
|
[Glossarist::DetailedDefinition.new(content: definition)]
|
230
246
|
end
|
231
247
|
|
232
|
-
def
|
233
|
-
|
234
|
-
end
|
248
|
+
def get_entity_notes(entity, schema_domain)
|
249
|
+
notes = []
|
235
250
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
end&.flatten&.compact
|
251
|
+
# Add trimmed definition from entity description as first note
|
252
|
+
if entity.remarks && !entity.remarks.empty?
|
253
|
+
trimmed_def = trim_definition(entity.remarks)
|
254
|
+
if trimmed_def && !trimmed_def.empty?
|
255
|
+
notes << Glossarist::DetailedDefinition.new(
|
256
|
+
content: convert_express_xref(trimmed_def, schema_domain),
|
257
|
+
)
|
258
|
+
end
|
259
|
+
end
|
246
260
|
|
247
|
-
|
248
|
-
|
261
|
+
# Add other notes
|
262
|
+
other_notes = [
|
263
|
+
entity.remark_items&.select do |ri|
|
264
|
+
ri.id == "__note"
|
265
|
+
end&.map(&:remarks),
|
266
|
+
].flatten.compact
|
267
|
+
|
268
|
+
other_notes.each do |note|
|
269
|
+
notes << Glossarist::DetailedDefinition.new(
|
249
270
|
content: convert_express_xref(note, schema_domain),
|
250
271
|
)
|
251
272
|
end
|
273
|
+
|
274
|
+
notes
|
252
275
|
end
|
253
276
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
ri.id == "__example"
|
259
|
-
end&.map(&:remarks)
|
260
|
-
end&.flatten&.compact
|
277
|
+
def get_entity_examples(entity, schema_domain)
|
278
|
+
examples = entity.remark_items&.select do |ri|
|
279
|
+
ri.id == "__example"
|
280
|
+
end&.map(&:remarks)&.flatten&.compact || []
|
261
281
|
|
262
|
-
examples
|
282
|
+
examples.map do |example|
|
263
283
|
Glossarist::DetailedDefinition.new(
|
264
284
|
content: convert_express_xref(example, schema_domain),
|
265
285
|
)
|
266
286
|
end
|
267
287
|
end
|
268
288
|
|
289
|
+
def extract_file_type(filename)
|
290
|
+
match = filename.match(/(arm|mim|bom)_annotated\.exp$/)
|
291
|
+
return "resource" unless match
|
292
|
+
|
293
|
+
{
|
294
|
+
"arm" => "module_arm",
|
295
|
+
"mim" => "module_mim",
|
296
|
+
"bom" => "business_object_model",
|
297
|
+
}[match.captures[0]] || "resource"
|
298
|
+
end
|
299
|
+
|
300
|
+
def get_schema_type(schema)
|
301
|
+
return "mim" if mim?(schema.id)
|
302
|
+
return "arm" if arm?(schema.id)
|
303
|
+
return "bom" if bom?(schema.id)
|
304
|
+
|
305
|
+
"resource"
|
306
|
+
end
|
307
|
+
|
308
|
+
def bom?(schema_id)
|
309
|
+
schema_id.end_with?("_bom")
|
310
|
+
end
|
311
|
+
|
312
|
+
# rubocop:disable Metrics/MethodLength
|
313
|
+
def combine_paragraphs(full_paragraph, next_paragraph)
|
314
|
+
# If full_paragraph already contains a period, extract that.
|
315
|
+
if m = full_paragraph.match(/\A(?<inner_first>[^\n]*?\.)\s/)
|
316
|
+
# puts "CONDITION 1"
|
317
|
+
if m[:inner_first]
|
318
|
+
return m[:inner_first]
|
319
|
+
else
|
320
|
+
return full_paragraph
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
# If full_paragraph ends with a period, this is the last.
|
325
|
+
if /\.\s*\Z/.match?(full_paragraph)
|
326
|
+
# puts "CONDITION 2"
|
327
|
+
return full_paragraph
|
328
|
+
end
|
329
|
+
|
330
|
+
# If next_paragraph is a list
|
331
|
+
if next_paragraph.start_with?("*")
|
332
|
+
# puts "CONDITION 3"
|
333
|
+
return "#{full_paragraph}\n\n#{next_paragraph}"
|
334
|
+
end
|
335
|
+
|
336
|
+
# If next_paragraph is a continuation of a list
|
337
|
+
if next_paragraph.start_with?("which", "that")
|
338
|
+
# puts "CONDITION 4"
|
339
|
+
return "#{full_paragraph}\n\n#{next_paragraph}"
|
340
|
+
end
|
341
|
+
|
342
|
+
# puts "CONDITION 5"
|
343
|
+
full_paragraph
|
344
|
+
end
|
345
|
+
|
346
|
+
def trim_definition(definition)
|
347
|
+
return nil if definition.nil? || definition.empty?
|
348
|
+
|
349
|
+
# Handle case where definition is an array
|
350
|
+
definition_str = if definition.is_a?(Array)
|
351
|
+
definition.join("\n\n")
|
352
|
+
else
|
353
|
+
definition.to_s
|
354
|
+
end
|
355
|
+
|
356
|
+
return nil if definition_str.empty?
|
357
|
+
|
358
|
+
# Unless the first paragraph ends with "between" and is followed by a
|
359
|
+
# list, don't split
|
360
|
+
paragraphs = definition_str.split("\n\n")
|
361
|
+
|
362
|
+
# puts paragraphs.inspect
|
363
|
+
|
364
|
+
first_paragraph = paragraphs.first
|
365
|
+
|
366
|
+
combined = if paragraphs.length > 1
|
367
|
+
paragraphs[1..].inject(first_paragraph) do |acc, p|
|
368
|
+
combine_paragraphs(acc, p)
|
369
|
+
end
|
370
|
+
else
|
371
|
+
combine_paragraphs(first_paragraph, "")
|
372
|
+
end
|
373
|
+
|
374
|
+
# puts "combined--------- #{combined}"
|
375
|
+
|
376
|
+
# Remove comments until end of line
|
377
|
+
combined = "#{combined}\n"
|
378
|
+
combined.gsub!(/\n\/\/.*?\n/, "\n")
|
379
|
+
combined.strip!
|
380
|
+
|
381
|
+
express_reference_to_mention(combined)
|
382
|
+
end
|
383
|
+
# rubocop:enable Metrics/MethodLength
|
384
|
+
|
385
|
+
# Replace `<<express:{schema}.{entity},{render}>>` with {{entity,render}}
|
386
|
+
def express_reference_to_mention(description)
|
387
|
+
# TODO: Use Expressir to check whether the "entity" is really an
|
388
|
+
# EXPRESS ENTITY. If not, skip the mention.
|
389
|
+
description.gsub(/<<express:([^,]+),([^>]+)>>/) do |_match|
|
390
|
+
"{{#{Regexp.last_match[1].split('.').last},#{Regexp.last_match[2]}}}"
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def entity_name_to_text(entity_id)
|
395
|
+
entity_id.downcase.gsub("_", " ")
|
396
|
+
end
|
397
|
+
|
398
|
+
# rubocop:disable Layout/LineLength
|
399
|
+
def generate_entity_definition(entity, _domain, schema_type)
|
400
|
+
return "" if entity.nil?
|
401
|
+
|
402
|
+
# See: metanorma/iso-10303-2#90
|
403
|
+
entity_type = case schema_type
|
404
|
+
when "module_arm"
|
405
|
+
"{{application object}}"
|
406
|
+
when "module_mim"
|
407
|
+
"{{entity data type}}"
|
408
|
+
when "resource", "business_object_model"
|
409
|
+
"{{entity data type}}"
|
410
|
+
else
|
411
|
+
raise Error.new("[suma] encountered unsupported schema_type")
|
412
|
+
end
|
413
|
+
|
414
|
+
if entity.subtype_of.empty?
|
415
|
+
"#{entity_type} " \
|
416
|
+
"that represents the " \
|
417
|
+
"#{entity_name_to_text(entity.id)} {{entity}}"
|
418
|
+
else
|
419
|
+
entity_subtypes = entity.subtype_of.map do |e|
|
420
|
+
"{{#{e.id}}}"
|
421
|
+
end
|
422
|
+
|
423
|
+
"#{entity_type} that is a type of " \
|
424
|
+
"#{entity_subtypes.join(' and ')} " \
|
425
|
+
"that represents the " \
|
426
|
+
"#{entity_name_to_text(entity.id)} {{entity}}"
|
427
|
+
end
|
428
|
+
end
|
429
|
+
# rubocop:enable Layout/LineLength
|
430
|
+
|
269
431
|
def convert_express_xref(content, schema_domain)
|
270
432
|
content.gsub(/<<express:(.*),(.*)>>/) do
|
271
433
|
"{{<#{schema_domain}>" \
|
@@ -273,13 +435,8 @@ module Suma
|
|
273
435
|
end
|
274
436
|
end
|
275
437
|
|
276
|
-
def
|
277
|
-
|
278
|
-
"#{sanitize_string(identifier)}.yaml"
|
279
|
-
end
|
280
|
-
|
281
|
-
def sanitize_string(str)
|
282
|
-
str.gsub(" ", "_").gsub("/", "_").gsub(":", "_")
|
438
|
+
def id_from_designation(designation)
|
439
|
+
designation.gsub(" ", "_").gsub("/", "_").gsub(":", "_")
|
283
440
|
end
|
284
441
|
end
|
285
442
|
end
|
data/lib/suma/cli/reformat.rb
CHANGED
@@ -57,7 +57,7 @@ module Suma
|
|
57
57
|
# containing '(*text*)' inside
|
58
58
|
comments = file_content.scan(/\(\*"(.*?)\n\*\)/m).map(&:first)
|
59
59
|
|
60
|
-
if comments.
|
60
|
+
if comments.any?
|
61
61
|
content_without_comments = file_content.gsub(/\(\*".*?\n\*\)/m, "")
|
62
62
|
|
63
63
|
# remove extra newlines
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "thor"
|
4
4
|
require_relative "../utils"
|
5
|
+
require "expressir"
|
5
6
|
|
6
7
|
module Suma
|
7
8
|
module Cli
|
@@ -43,7 +44,6 @@ module Suma
|
|
43
44
|
# Lazy-load dependencies only when this command is actually used
|
44
45
|
require "expressir"
|
45
46
|
require "ruby-progressbar"
|
46
|
-
require_relative "../schema_config"
|
47
47
|
require "pathname"
|
48
48
|
end
|
49
49
|
|
@@ -74,7 +74,7 @@ module Suma
|
|
74
74
|
|
75
75
|
# Load and initialize the schemas configuration
|
76
76
|
def load_schemas_config(schemas_file_path)
|
77
|
-
schemas_config =
|
77
|
+
schemas_config = Expressir::SchemaManifest.from_yaml(File.read(schemas_file_path))
|
78
78
|
# Ensure the config is initialized with the correct path to resolve relative paths
|
79
79
|
schemas_config.set_initial_path(schemas_file_path.to_s)
|
80
80
|
schemas_config
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "metanorma/cli"
|
4
4
|
require "metanorma/cli/collection"
|
5
5
|
require "metanorma/collection/collection"
|
6
|
+
require "expressir"
|
6
7
|
|
7
8
|
module Suma
|
8
9
|
class CollectionManifest < Metanorma::Collection::Config::Manifest
|
@@ -36,7 +37,7 @@ module Suma
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def export_schema_config(path)
|
39
|
-
export_config = @schema_config ||
|
40
|
+
export_config = @schema_config || Expressir::SchemaManifest.new
|
40
41
|
return export_config unless entry
|
41
42
|
|
42
43
|
entry.each do |x|
|
@@ -127,7 +128,7 @@ module Suma
|
|
127
128
|
if File.basename(file) == "collection.yml"
|
128
129
|
schemas_yaml_path = File.join(File.dirname(file), "schemas.yaml")
|
129
130
|
if schemas_yaml_path && File.exist?(schemas_yaml_path)
|
130
|
-
@schema_config =
|
131
|
+
@schema_config = Expressir::SchemaManifest.from_file(schemas_yaml_path)
|
131
132
|
end
|
132
133
|
end
|
133
134
|
end
|
data/lib/suma/processor.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "fileutils"
|
4
|
+
require "expressir"
|
4
5
|
# require "metanorma/cli"
|
5
|
-
require_relative "schema_config"
|
6
6
|
|
7
7
|
module Suma
|
8
8
|
class SchemaAttachment
|
@@ -68,8 +68,8 @@ module Suma
|
|
68
68
|
|
69
69
|
def to_config(path: nil)
|
70
70
|
# return @config unless @config
|
71
|
-
@config =
|
72
|
-
@config.schemas <<
|
71
|
+
@config = Expressir::SchemaManifest.new
|
72
|
+
@config.schemas << Expressir::SchemaManifestEntry.new(
|
73
73
|
id: @schema.id,
|
74
74
|
path: @schema.path,
|
75
75
|
)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require_relative "express_schema"
|
4
4
|
require_relative "schema_attachment"
|
5
5
|
require_relative "schema_document"
|
6
|
-
|
6
|
+
require "expressir"
|
7
7
|
require_relative "utils"
|
8
8
|
|
9
9
|
module Suma
|
@@ -19,7 +19,7 @@ module Suma
|
|
19
19
|
@output_path_docs = Pathname.new(output_path_docs || Dir.pwd).expand_path
|
20
20
|
@output_path_schemas = Pathname.new(output_path_schemas || Dir.pwd).expand_path
|
21
21
|
@config = config
|
22
|
-
@config ||= config_yaml &&
|
22
|
+
@config ||= config_yaml && Expressir::SchemaManifest.from_file(config_yaml)
|
23
23
|
@manifest = manifest
|
24
24
|
end
|
25
25
|
|
data/lib/suma/version.rb
CHANGED
data/lib/suma.rb
CHANGED
data/suma.gemspec
CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
|
34
34
|
spec.require_paths = ["lib"]
|
35
35
|
|
36
36
|
spec.add_dependency "expressir", "~> 2.1"
|
37
|
+
spec.add_dependency "glossarist", "~> 2.3.7"
|
37
38
|
spec.add_dependency "lutaml-model", "~> 0.7"
|
38
39
|
spec.add_dependency "metanorma-cli"
|
39
40
|
spec.add_dependency "plurimath"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: suma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: expressir
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: glossarist
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.3.7
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.3.7
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: lutaml-model
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,9 +160,6 @@ files:
|
|
146
160
|
- lib/suma/processor.rb
|
147
161
|
- lib/suma/schema_attachment.rb
|
148
162
|
- lib/suma/schema_collection.rb
|
149
|
-
- lib/suma/schema_config.rb
|
150
|
-
- lib/suma/schema_config/config.rb
|
151
|
-
- lib/suma/schema_config/schema.rb
|
152
163
|
- lib/suma/schema_document.rb
|
153
164
|
- lib/suma/site_config.rb
|
154
165
|
- lib/suma/thor_ext.rb
|
@@ -1,147 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "lutaml/model"
|
4
|
-
require_relative "schema"
|
5
|
-
require_relative "../utils"
|
6
|
-
|
7
|
-
module Suma
|
8
|
-
module SchemaConfig
|
9
|
-
class Config < Lutaml::Model::Serializable
|
10
|
-
attribute :schemas, Schema, collection: true, initialize_empty: true
|
11
|
-
attribute :path, Lutaml::Model::Type::String
|
12
|
-
attr_accessor :output_path
|
13
|
-
|
14
|
-
def initialize(**args)
|
15
|
-
@path = path_relative_to_absolute(path) if path
|
16
|
-
super
|
17
|
-
end
|
18
|
-
|
19
|
-
def base_path
|
20
|
-
File.dirname(@path)
|
21
|
-
end
|
22
|
-
|
23
|
-
yaml do
|
24
|
-
map "schemas", with: { from: :schemas_from_yaml, to: :schemas_to_yaml }
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.from_file(path)
|
28
|
-
from_yaml(File.read(path)).tap do |x|
|
29
|
-
x.set_initial_path(path)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_file(to_path = path)
|
34
|
-
File.write(to_path, to_yaml)
|
35
|
-
end
|
36
|
-
|
37
|
-
def set_initial_path(new_path)
|
38
|
-
@path = path_relative_to_absolute(new_path)
|
39
|
-
schemas.each do |schema|
|
40
|
-
schema.path = path_relative_to_absolute(schema.path)
|
41
|
-
schema.container_path = File.expand_path(@path)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def schemas_from_yaml(model, value)
|
46
|
-
model.schemas = value.map do |k, v|
|
47
|
-
Schema.new(id: k, path: path_relative_to_absolute(v["path"]))
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def schemas_to_yaml(model, doc)
|
52
|
-
doc["schemas"] = model.schemas.sort_by(&:id).to_h do |schema|
|
53
|
-
# We are outputting the schemas collection file to the directory where
|
54
|
-
# the collection config is at (assumed to be Dir.pwd), not to the
|
55
|
-
# directory we sourced the manifest from, e.g.
|
56
|
-
# documents/iso-10303-41/schemas.yaml.
|
57
|
-
|
58
|
-
# So the schema.container_path = @config.path is not
|
59
|
-
# in fact needed, as the files are already absolute. This notion of
|
60
|
-
# using @path to create relative paths was misconceived
|
61
|
-
[
|
62
|
-
schema.id,
|
63
|
-
{
|
64
|
-
"path" => path_absolute_to_relative(
|
65
|
-
schema.path,
|
66
|
-
model.output_path || Dir.pwd,
|
67
|
-
),
|
68
|
-
},
|
69
|
-
]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def path_relative_to_absolute(relative_path)
|
74
|
-
eval_path = Pathname.new(relative_path)
|
75
|
-
return relative_path if eval_path.absolute?
|
76
|
-
|
77
|
-
# Or based on current working directory?
|
78
|
-
return relative_path unless @path
|
79
|
-
|
80
|
-
# ... but if this calculates path, we end up expanding it anyway
|
81
|
-
|
82
|
-
Pathname.new(File.dirname(@path)).join(eval_path).expand_path.to_s
|
83
|
-
end
|
84
|
-
|
85
|
-
def path_absolute_to_relative(absolute_path, container_path)
|
86
|
-
container_path ||= @path
|
87
|
-
return absolute_path unless container_path
|
88
|
-
|
89
|
-
p = Pathname.new(container_path)
|
90
|
-
container = p.directory? ? p.to_s : p.dirname
|
91
|
-
Pathname.new(absolute_path).relative_path_from(container).to_s
|
92
|
-
end
|
93
|
-
|
94
|
-
def update_path(new_path)
|
95
|
-
if @path.nil?
|
96
|
-
@path = new_path
|
97
|
-
return @path
|
98
|
-
end
|
99
|
-
|
100
|
-
old_base_path = File.dirname(@path)
|
101
|
-
new_base_path = File.dirname(new_path)
|
102
|
-
update_schema_path(old_base_path, new_base_path)
|
103
|
-
|
104
|
-
@path = new_path
|
105
|
-
end
|
106
|
-
|
107
|
-
def concat(another_config)
|
108
|
-
unless another_config.is_a?(self.class)
|
109
|
-
raise StandardError, "Can only concat a SchemaConfig::Config object."
|
110
|
-
end
|
111
|
-
|
112
|
-
# We need to update the relative paths when paths exist
|
113
|
-
if path && another_config.path && path != another_config.path
|
114
|
-
new_config = another_config.dup
|
115
|
-
new_config.update_path(path)
|
116
|
-
end
|
117
|
-
|
118
|
-
schemas.concat(another_config.schemas)
|
119
|
-
end
|
120
|
-
|
121
|
-
def save_to_path(filename)
|
122
|
-
new_config = dup.tap do |c|
|
123
|
-
c.path = filename
|
124
|
-
c.update_path(File.dirname(filename))
|
125
|
-
c.output_path = filename
|
126
|
-
end
|
127
|
-
|
128
|
-
File.open(filename, "w") do |f|
|
129
|
-
Utils.log "Writing #{filename}..."
|
130
|
-
f.write(new_config.to_yaml)
|
131
|
-
Utils.log "Done."
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def update_schema_path(old_base_path, new_base_path)
|
136
|
-
schemas.each do |schema|
|
137
|
-
schema_path = Pathname.new(schema.path)
|
138
|
-
next if schema_path.absolute?
|
139
|
-
|
140
|
-
schema_path = (Pathname.new(old_base_path) + schema_path).cleanpath
|
141
|
-
# This is the new relative schema_path
|
142
|
-
schema.path = schema_path.relative_path_from(new_base_path)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "lutaml/model"
|
4
|
-
|
5
|
-
module Suma
|
6
|
-
module SchemaConfig
|
7
|
-
class Schema < Lutaml::Model::Serializable
|
8
|
-
attribute :id, Lutaml::Model::Type::String
|
9
|
-
attribute :path, Lutaml::Model::Type::String
|
10
|
-
# attribute :schemas_only, Lutaml::Model::Type::Boolean
|
11
|
-
|
12
|
-
# container_path is a copy of Suma::SchemaConfig::Config.path,
|
13
|
-
# used to resolve the path of each schema within
|
14
|
-
# Suma::SchemaConfig::Config.schemas,
|
15
|
-
# when Suma::SchemaConfig::Config.schemas is recursively flattened
|
16
|
-
attr_accessor :container_path
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/lib/suma/schema_config.rb
DELETED