glossarist-new 1.0.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 +7 -0
- data/.editorconfig +15 -0
- data/.github/workflows/test.yml +34 -0
- data/.gitignore +18 -0
- data/.hound.yml +3 -0
- data/.rspec +3 -0
- data/.rubocop.yml +35 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +23 -0
- data/README.adoc +11 -0
- data/Rakefile +8 -0
- data/config.yml +83 -0
- data/glossarist.gemspec +36 -0
- data/lib/glossarist/citation.rb +85 -0
- data/lib/glossarist/collection.rb +86 -0
- data/lib/glossarist/concept.rb +143 -0
- data/lib/glossarist/concept_date.rb +20 -0
- data/lib/glossarist/concept_manager.rb +44 -0
- data/lib/glossarist/concept_source.rb +62 -0
- data/lib/glossarist/designation/abbreviation.rb +23 -0
- data/lib/glossarist/designation/base.rb +37 -0
- data/lib/glossarist/designation/expression.rb +50 -0
- data/lib/glossarist/designation/grammar_info.rb +58 -0
- data/lib/glossarist/designation/graphical_symbol.rb +17 -0
- data/lib/glossarist/designation/letter_symbol.rb +19 -0
- data/lib/glossarist/designation/symbol.rb +21 -0
- data/lib/glossarist/designation.rb +27 -0
- data/lib/glossarist/detailed_definition.rb +31 -0
- data/lib/glossarist/glossary_definition.rb +29 -0
- data/lib/glossarist/localized_concept.rb +61 -0
- data/lib/glossarist/managed_concept.rb +107 -0
- data/lib/glossarist/managed_concept_collection.rb +79 -0
- data/lib/glossarist/model.rb +29 -0
- data/lib/glossarist/non_verb_rep.rb +18 -0
- data/lib/glossarist/related_concept.rb +31 -0
- data/lib/glossarist/utilities/boolean_attributes.rb +35 -0
- data/lib/glossarist/utilities/common_functions.rb +29 -0
- data/lib/glossarist/utilities/enum/class_methods.rb +99 -0
- data/lib/glossarist/utilities/enum/enum_collection.rb +45 -0
- data/lib/glossarist/utilities/enum/instance_methods.rb +55 -0
- data/lib/glossarist/utilities/enum.rb +21 -0
- data/lib/glossarist/utilities.rb +5 -0
- data/lib/glossarist/version.rb +8 -0
- data/lib/glossarist.rb +31 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fca876eda8d9aaf1f9c931e93b47865f618f37991b317cf9a9b1aecaee4f60cf
|
4
|
+
data.tar.gz: 9af3d0caefb3ecf7c1cc8958b4440641d279126bcc4a2888feb91ee4bb2ccf42
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 35fd58588549adf1b1978b6688b21257f8a9f094246daa69365f6e031a0c9e6de9ddbd57835692f80b4fbbe0a4f8cd40af8f60e2dd237cb397d8fb515824bd21
|
7
|
+
data.tar.gz: 9f0843c03da02ffde2f6defad7f6d42732842ecb32cbbd560283d6e2ac5700073e7573ecf5d74e0764b781fedcb9fe48caae1d9a3de80c5e7d0a89976a603c8e
|
data/.editorconfig
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# EditorConfig is awesome: http://EditorConfig.org
|
2
|
+
|
3
|
+
# top-most EditorConfig file
|
4
|
+
root = true
|
5
|
+
|
6
|
+
# Unix-style newlines with a newline ending every file
|
7
|
+
[*]
|
8
|
+
charset = utf-8
|
9
|
+
end_of_line = lf
|
10
|
+
|
11
|
+
[{*.adoc,*.html,*.js,*.json,*.rake,*.rb,*.rf,*.yaml,*.yml,Rakefile,rakefile}]
|
12
|
+
indent_style = space
|
13
|
+
indent_size = 2
|
14
|
+
insert_final_newline = true
|
15
|
+
trim_trailing_whitespace = true
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
- push
|
5
|
+
- pull_request
|
6
|
+
- workflow_dispatch
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
name: Ruby ${{ matrix.ruby }}
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
|
13
|
+
strategy:
|
14
|
+
fail-fast: false
|
15
|
+
matrix:
|
16
|
+
ruby:
|
17
|
+
- "3.0"
|
18
|
+
- "2.7"
|
19
|
+
- "2.6"
|
20
|
+
- "2.5"
|
21
|
+
- "2.4"
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- name: Fetch source code
|
25
|
+
uses: actions/checkout@v2
|
26
|
+
|
27
|
+
- name: Set up Ruby
|
28
|
+
uses: ruby/setup-ruby@v1
|
29
|
+
with:
|
30
|
+
ruby-version: ${{ matrix.ruby }}
|
31
|
+
bundler-cache: true
|
32
|
+
|
33
|
+
- name: Run tests
|
34
|
+
run: bundle exec rspec
|
data/.gitignore
ADDED
data/.hound.yml
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
inherit_from:
|
2
|
+
- https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
|
3
|
+
|
4
|
+
# local repo-specific modifications
|
5
|
+
|
6
|
+
AllCops:
|
7
|
+
TargetRubyVersion: 2.4
|
8
|
+
|
9
|
+
# This one breaks plenty of RSpec idioms.
|
10
|
+
Lint/AmbiguousBlockAssociation:
|
11
|
+
Exclude:
|
12
|
+
- "spec/**/*"
|
13
|
+
|
14
|
+
# Defining a constant or class inside RSpec.describe block
|
15
|
+
# sometimes makes sense.
|
16
|
+
Lint/ConstantDefinitionInBlock:
|
17
|
+
Exclude:
|
18
|
+
- "spec/**/*"
|
19
|
+
|
20
|
+
# This requirement is silly to me.
|
21
|
+
Style/AccessModifierDeclarations:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
# Makes little sense for Glossarist models, as these attr_accessors should all
|
25
|
+
# be documented eventually.
|
26
|
+
Style/AccessorGrouping:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
# This requirement is silly to me.
|
30
|
+
Style/ClassCheck:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
# This requirement is silly to me.
|
34
|
+
Style/SingleArgumentDig:
|
35
|
+
Enabled: false
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2021, Ribose
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
18
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
20
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
21
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
22
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
23
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.adoc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
= Glossarist
|
2
|
+
|
3
|
+
== Credits
|
4
|
+
|
5
|
+
This gem is developed, maintained and funded by
|
6
|
+
https://www.ribose.com[Ribose Inc.]
|
7
|
+
|
8
|
+
== License
|
9
|
+
|
10
|
+
The gem is available as open source under the terms of the
|
11
|
+
https://opensource.org/licenses/BSD-2-Clause[2-Clause BSD License].
|
data/Rakefile
ADDED
data/config.yml
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# This file can be used to configure enum attributes in the model.
|
2
|
+
# For example to add different allowed values for Abbreviation::Type
|
3
|
+
# you can change the values under abbreviation => type
|
4
|
+
#
|
5
|
+
# NOTE: All the keys in this file are needed for the script to run
|
6
|
+
# and should not be removed. You can change the values but atleast
|
7
|
+
# one option should be present in each list.
|
8
|
+
|
9
|
+
concept_source:
|
10
|
+
status:
|
11
|
+
- identical
|
12
|
+
- similar
|
13
|
+
- modified
|
14
|
+
- restyle
|
15
|
+
- context_added
|
16
|
+
- generalisation
|
17
|
+
- specialisation
|
18
|
+
- unspecified
|
19
|
+
- related
|
20
|
+
- not_equal
|
21
|
+
type:
|
22
|
+
- authoritative
|
23
|
+
- lineage
|
24
|
+
|
25
|
+
designation:
|
26
|
+
base:
|
27
|
+
normative_status:
|
28
|
+
- preferred
|
29
|
+
- deprecated
|
30
|
+
- admitted
|
31
|
+
- <símbolo> # in iev-data => '<symbol>'
|
32
|
+
- 티에스 # in iev-data => translates to 'TS' I think it is a synonym and not status.
|
33
|
+
- prąd startowy # in iev-data => 'starting current' I think it is a synonym and not status.
|
34
|
+
|
35
|
+
related_concept:
|
36
|
+
type:
|
37
|
+
- deprecates
|
38
|
+
- supersedes
|
39
|
+
- superseded_by
|
40
|
+
- narrower
|
41
|
+
- broader
|
42
|
+
- equivalent
|
43
|
+
- compare
|
44
|
+
- contrast
|
45
|
+
- see
|
46
|
+
|
47
|
+
abbreviation:
|
48
|
+
type:
|
49
|
+
- truncation
|
50
|
+
- acronym
|
51
|
+
- initialism
|
52
|
+
|
53
|
+
grammar_info:
|
54
|
+
boolean_attribute:
|
55
|
+
- preposition
|
56
|
+
- participle
|
57
|
+
- adj
|
58
|
+
- verb
|
59
|
+
- adverb
|
60
|
+
- noun
|
61
|
+
gender:
|
62
|
+
- m
|
63
|
+
- f
|
64
|
+
- n
|
65
|
+
- c
|
66
|
+
number:
|
67
|
+
- singular
|
68
|
+
- dual
|
69
|
+
- plural
|
70
|
+
|
71
|
+
concept:
|
72
|
+
status:
|
73
|
+
- draft
|
74
|
+
- not_valid
|
75
|
+
- valid
|
76
|
+
- superseded
|
77
|
+
- retired
|
78
|
+
|
79
|
+
concept_date:
|
80
|
+
type:
|
81
|
+
- accepted
|
82
|
+
- amended
|
83
|
+
- retired
|
data/glossarist.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/glossarist/version"
|
4
|
+
|
5
|
+
all_files_in_git = Dir.chdir(File.expand_path(__dir__)) do
|
6
|
+
`git ls-files -z`.split("\x0")
|
7
|
+
end
|
8
|
+
|
9
|
+
Gem::Specification.new do |spec|
|
10
|
+
spec.name = "glossarist-new"
|
11
|
+
spec.version = Glossarist::VERSION
|
12
|
+
spec.authors = ["Ribose"]
|
13
|
+
spec.email = ["open.source@ribose.com"]
|
14
|
+
|
15
|
+
spec.summary =
|
16
|
+
"Concept models for terminology glossaries conforming ISO 10241-1."
|
17
|
+
spec.homepage = "https://github.com/glossarist/glossarist-ruby"
|
18
|
+
spec.license = "BSD-2-Clause"
|
19
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
|
20
|
+
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
23
|
+
spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
|
24
|
+
|
25
|
+
# Specify which files should be added to the gem when it is released.
|
26
|
+
spec.files = all_files_in_git
|
27
|
+
.reject { |f| f.match(%r{\A(?:test|spec|features|bin|\.)/}) }
|
28
|
+
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_development_dependency "pry", "~> 0.14.0"
|
34
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
35
|
+
spec.add_development_dependency "rspec", "~> 3.10"
|
36
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) Copyright 2021 Ribose Inc.
|
4
|
+
#
|
5
|
+
|
6
|
+
module Glossarist
|
7
|
+
class Citation < Model
|
8
|
+
# Unstructured (plain text) reference.
|
9
|
+
# @return [String]
|
10
|
+
attr_accessor :text
|
11
|
+
|
12
|
+
# Source in structured reference.
|
13
|
+
# @return [String]
|
14
|
+
attr_accessor :source
|
15
|
+
|
16
|
+
# Document ID in structured reference.
|
17
|
+
# @return [String]
|
18
|
+
attr_accessor :id
|
19
|
+
|
20
|
+
# Document version in structured reference.
|
21
|
+
# @return [String]
|
22
|
+
attr_accessor :version
|
23
|
+
|
24
|
+
# @return [String]
|
25
|
+
# Referred clause of the document.
|
26
|
+
attr_accessor :clause
|
27
|
+
|
28
|
+
# Link to document.
|
29
|
+
# @return [String]
|
30
|
+
attr_accessor :link
|
31
|
+
|
32
|
+
# Original ref text before parsing.
|
33
|
+
# @return [String]
|
34
|
+
# @note This attribute is likely to be removed or reworked in future.
|
35
|
+
# It is arguably not relevant to Glossarist itself.
|
36
|
+
attr_accessor :original
|
37
|
+
|
38
|
+
# Whether it is a plain text ref.
|
39
|
+
# @return [Boolean]
|
40
|
+
def plain?
|
41
|
+
(source && id && version).nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
# Whether it is a structured ref.
|
45
|
+
# @return [Boolean]
|
46
|
+
def structured?
|
47
|
+
!plain?
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_h
|
51
|
+
{
|
52
|
+
"ref" => ref_to_h,
|
53
|
+
"clause" => clause,
|
54
|
+
"link" => link,
|
55
|
+
"original" => original,
|
56
|
+
}.compact
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.from_h(hash)
|
60
|
+
hash = hash.dup
|
61
|
+
|
62
|
+
ref_val = hash.delete("ref")
|
63
|
+
hash.merge!(Hash === ref_val ? ref_val : {"text" => ref_val})
|
64
|
+
hash.compact!
|
65
|
+
|
66
|
+
super(hash)
|
67
|
+
end
|
68
|
+
|
69
|
+
def ref=(ref)
|
70
|
+
@source = ref["source"]
|
71
|
+
@id = ref["id"]
|
72
|
+
@version = ref["version"]
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def ref_to_h
|
78
|
+
if structured?
|
79
|
+
{ "source" => source, "id" => id, "version" => version }.compact
|
80
|
+
else
|
81
|
+
text
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) Copyright 2021 Ribose Inc.
|
4
|
+
#
|
5
|
+
|
6
|
+
module Glossarist
|
7
|
+
# @todo Add support for lazy concept loading.
|
8
|
+
# @todo Consider extracting persistence backend to a separate class.
|
9
|
+
class Collection
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
# Path to concepts directory.
|
13
|
+
# @return [String]
|
14
|
+
attr_accessor :path
|
15
|
+
|
16
|
+
# @param path [String]
|
17
|
+
# concepts directory path, either absolute or relative to CWD
|
18
|
+
def initialize(path: nil)
|
19
|
+
@path = path
|
20
|
+
@index = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def each(&block)
|
24
|
+
@index.each_value(&block)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns concept with given ID, if it is present in collection, or +nil+
|
28
|
+
# otherwise.
|
29
|
+
#
|
30
|
+
# @param id [String]
|
31
|
+
# Concept ID
|
32
|
+
# @return [Concept, nil]
|
33
|
+
def fetch(id)
|
34
|
+
@index[id]
|
35
|
+
end
|
36
|
+
|
37
|
+
alias :[] :fetch
|
38
|
+
|
39
|
+
# If concept with given ID is present in this collection, returns that
|
40
|
+
# concept. Otherwise, instantiates a new concept, adds it to
|
41
|
+
# the collection, and returns it.
|
42
|
+
#
|
43
|
+
# @param id [String]
|
44
|
+
# Concept ID
|
45
|
+
# @return [Concept]
|
46
|
+
def fetch_or_initialize(id)
|
47
|
+
fetch(id) or store(Concept.new(id: id))
|
48
|
+
end
|
49
|
+
|
50
|
+
# Adds concept to the collection. If collection contains a concept with
|
51
|
+
# the same ID already, that concept is replaced.
|
52
|
+
#
|
53
|
+
# @param concept [Concept]
|
54
|
+
# concept about to be added
|
55
|
+
def store(concept)
|
56
|
+
@index[concept.id] = concept
|
57
|
+
end
|
58
|
+
|
59
|
+
alias :<< :store
|
60
|
+
|
61
|
+
# Reads all concepts from files.
|
62
|
+
def load_concepts
|
63
|
+
Dir.glob(concepts_glob) do |filename|
|
64
|
+
store(load_concept_from_file(filename))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private def load_concept_from_file(filename)
|
69
|
+
Concept.from_h(Psych.safe_load(File.read(filename)))
|
70
|
+
end
|
71
|
+
|
72
|
+
# Writes all concepts to files.
|
73
|
+
def save_concepts
|
74
|
+
@index.each_value &method(:save_concept_to_file)
|
75
|
+
end
|
76
|
+
|
77
|
+
private def save_concept_to_file(concept)
|
78
|
+
filename = File.join(path, "concept-#{concept.id}.yaml")
|
79
|
+
File.write(filename, Psych.dump(concept.to_h))
|
80
|
+
end
|
81
|
+
|
82
|
+
private def concepts_glob
|
83
|
+
File.join(path, "concept-*.{yaml,yml}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) Copyright 2021 Ribose Inc.
|
4
|
+
#
|
5
|
+
|
6
|
+
module Glossarist
|
7
|
+
class Concept < Model
|
8
|
+
# Concept ID.
|
9
|
+
# @return [String]
|
10
|
+
attr_accessor :id
|
11
|
+
alias :termid= :id=
|
12
|
+
|
13
|
+
# Concept designations.
|
14
|
+
# @todo Alias +terms+ exists only for legacy reasons and will be removed.
|
15
|
+
# @return [Array<Designations::Base>]
|
16
|
+
attr_reader :designations
|
17
|
+
alias :terms :designations
|
18
|
+
|
19
|
+
# <<BasicDocument>>LocalizedString
|
20
|
+
# @return [String]
|
21
|
+
attr_accessor :domain
|
22
|
+
|
23
|
+
# <<BasicDocument>>LocalizedString
|
24
|
+
# @return [String]
|
25
|
+
attr_accessor :subject
|
26
|
+
|
27
|
+
# Concept definition.
|
28
|
+
# @return [Array<DetailedDefinition>]
|
29
|
+
attr_reader :definition
|
30
|
+
|
31
|
+
# Non verbal representation of the concept.
|
32
|
+
# @return [NonVerbRep]
|
33
|
+
attr_accessor :non_verb_rep
|
34
|
+
|
35
|
+
# Concept notes
|
36
|
+
# @return [Array<DetailedDefinition>]
|
37
|
+
attr_reader :notes
|
38
|
+
|
39
|
+
# Concept examples
|
40
|
+
# @return [Array<DetailedDefinition>]
|
41
|
+
attr_reader :examples
|
42
|
+
|
43
|
+
def initialize(*)
|
44
|
+
@localizations = {}
|
45
|
+
@sources = []
|
46
|
+
@related = []
|
47
|
+
@notes = []
|
48
|
+
@designations = []
|
49
|
+
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
# List of authorative sources.
|
54
|
+
# @todo Alias +authoritative_source+ exists for legacy reasons and may be
|
55
|
+
# removed.
|
56
|
+
# @return [Array<ConceptSource>]
|
57
|
+
attr_reader :sources
|
58
|
+
alias :authoritative_source :sources
|
59
|
+
|
60
|
+
# return [Array<ConceptDate>]
|
61
|
+
attr_reader :dates
|
62
|
+
|
63
|
+
def examples=(examples)
|
64
|
+
@examples = examples&.map { |e| DetailedDefinition.new(e) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def notes=(notes)
|
68
|
+
@notes = notes&.map { |n| DetailedDefinition.new(n) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def definition=(definition)
|
72
|
+
@definition = definition&.map { |d| DetailedDefinition.new(d) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def designations=(designations)
|
76
|
+
@designations = designations&.map do |designation|
|
77
|
+
Designation::Base.from_h(designation)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
alias :terms= :designations=
|
82
|
+
|
83
|
+
def dates=(dates)
|
84
|
+
@dates = dates&.map { |d| ConceptDate.new(d) }
|
85
|
+
end
|
86
|
+
|
87
|
+
def sources=(sources)
|
88
|
+
@sources = sources&.map do |source|
|
89
|
+
ConceptSource.new(source)
|
90
|
+
end || []
|
91
|
+
end
|
92
|
+
|
93
|
+
def authoritative_source=(sources)
|
94
|
+
self.sources = sources&.map do |source|
|
95
|
+
source.merge({ "type" => "authoritative" })
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_h
|
100
|
+
{
|
101
|
+
"id" => id,
|
102
|
+
"related" => related&.map(&:to_h),
|
103
|
+
"terms" => (terms&.map(&:to_h) || []),
|
104
|
+
"definition" => definition&.map(&:to_h),
|
105
|
+
"notes" => notes&.map(&:to_h),
|
106
|
+
"examples" => examples&.map(&:to_h),
|
107
|
+
}
|
108
|
+
.compact
|
109
|
+
end
|
110
|
+
|
111
|
+
# @deprecated For legacy reasons only.
|
112
|
+
# Implicit conversion (i.e. {#to_hash} alias) will be removed soon.
|
113
|
+
alias :to_hash :to_h
|
114
|
+
|
115
|
+
# rubocop:disable Metrics/AbcSize, Style/RescueModifier
|
116
|
+
def self.from_h(hash)
|
117
|
+
new.tap do |concept|
|
118
|
+
concept.id = hash.dig("termid")
|
119
|
+
concept.sources = hash.dig("sources")
|
120
|
+
concept.related = hash.dig("related")
|
121
|
+
concept.definition = hash.dig("definition")
|
122
|
+
|
123
|
+
hash.values
|
124
|
+
.grep(Hash)
|
125
|
+
.map { |subhash| LocalizedConcept.from_h(subhash) rescue nil }
|
126
|
+
.compact
|
127
|
+
|
128
|
+
concept.related = hash.dig("related") || []
|
129
|
+
end
|
130
|
+
end
|
131
|
+
# rubocop:enable Metrics/AbcSize, Style/RescueModifier
|
132
|
+
|
133
|
+
# All Related Concepts
|
134
|
+
# @return [Array<RelatedConcept>]
|
135
|
+
def related
|
136
|
+
@related.empty? ? nil : @related
|
137
|
+
end
|
138
|
+
|
139
|
+
def related=(related)
|
140
|
+
@related = related&.map { |r| RelatedConcept.new(r) } || []
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Glossarist
|
4
|
+
class ConceptDate < Model
|
5
|
+
include Glossarist::Utilities::Enum
|
6
|
+
|
7
|
+
# Iso8601 date
|
8
|
+
# @return [String]
|
9
|
+
attr_accessor :date
|
10
|
+
|
11
|
+
register_enum :type, Glossarist::GlossaryDefinition::CONCEPT_DATE_TYPES
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
{
|
15
|
+
"type" => type,
|
16
|
+
"date" => date,
|
17
|
+
}.compact
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Glossarist
|
4
|
+
class ConceptManager
|
5
|
+
# Path to concepts directory.
|
6
|
+
# @return [String]
|
7
|
+
attr_accessor :path
|
8
|
+
|
9
|
+
# @param path [String]
|
10
|
+
# concepts directory path, either absolute or relative to CWD
|
11
|
+
def initialize(path: nil)
|
12
|
+
@path = path
|
13
|
+
end
|
14
|
+
|
15
|
+
# Reads all concepts from files.
|
16
|
+
def load_from_files(collection: nil)
|
17
|
+
collection ||= ManagedConceptCollection.new
|
18
|
+
|
19
|
+
Dir.glob(concepts_glob) do |filename|
|
20
|
+
collection.store(load_concept_from_file(filename))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Writes all concepts to files.
|
25
|
+
def save_to_files(managed_concepts)
|
26
|
+
managed_concepts.each_value &method(:save_concept_to_file)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def load_concept_from_file(filename)
|
32
|
+
ManagedConcept.new(Psych.safe_load(File.read(filename)))
|
33
|
+
end
|
34
|
+
|
35
|
+
def save_concept_to_file(concept)
|
36
|
+
filename = File.join(path, "concept-#{concept.id}.yaml")
|
37
|
+
File.write(filename, Psych.dump(concept.to_h))
|
38
|
+
end
|
39
|
+
|
40
|
+
def concepts_glob
|
41
|
+
File.join(path, "concept-*.{yaml,yml}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|