iqvoc 4.7.0 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/Gemfile +11 -11
  4. data/Gemfile.lock +178 -122
  5. data/README.md +39 -24
  6. data/{test/performance/browsing_test.rb → app/aides/inline_data_helper.rb} +23 -6
  7. data/app/aides/maker.rb +139 -0
  8. data/{lib → app/aides}/multi_logger.rb +0 -0
  9. data/app/aides/origin.rb +47 -0
  10. data/app/aides/rdfapi.rb +59 -0
  11. data/app/aides/skos_exporter.rb +151 -0
  12. data/app/aides/skos_importer.rb +348 -0
  13. data/app/assets/javascripts/iqvoc/entityselect.js.erb +7 -9
  14. data/app/controllers/application_controller.rb +1 -3
  15. data/app/controllers/collections/versions_controller.rb +1 -3
  16. data/app/controllers/concepts/versions_controller.rb +9 -3
  17. data/app/controllers/concerns/controller_extensions.rb +109 -0
  18. data/app/{concerns → controllers/concerns}/reverse_match_errors.rb +0 -0
  19. data/app/controllers/hierarchy_controller.rb +7 -3
  20. data/app/controllers/instance_configuration_controller.rb +1 -1
  21. data/app/controllers/pages_controller.rb +10 -0
  22. data/app/controllers/search_results_controller.rb +2 -2
  23. data/app/controllers/triplestore_sync_controller.rb +2 -4
  24. data/app/helpers/application_helper.rb +1 -1
  25. data/app/helpers/widget_helper.rb +3 -3
  26. data/app/jobs/export_job.rb +1 -3
  27. data/app/jobs/import_job.rb +1 -3
  28. data/app/models/ability.rb +59 -0
  29. data/app/models/abstract_user.rb +1 -1
  30. data/app/models/collection/base.rb +12 -3
  31. data/app/models/collection/member/skos/base.rb +1 -1
  32. data/app/models/concept/base.rb +15 -8
  33. data/app/models/concept/relation/base.rb +1 -1
  34. data/app/models/concept/relation/skos/base.rb +1 -1
  35. data/app/models/concept/skos/scheme.rb +1 -1
  36. data/app/models/concept/validations.rb +1 -1
  37. data/app/models/concerns/deep_cloning.rb +92 -0
  38. data/app/models/concerns/first_level_object_scopes.rb +9 -0
  39. data/app/{concerns → models/concerns}/first_level_object_validations.rb +9 -2
  40. data/app/models/concerns/rankable.rb +31 -0
  41. data/app/models/{search_extension.rb → concerns/search_extension.rb} +0 -0
  42. data/app/{concerns → models/concerns}/versioning.rb +0 -6
  43. data/app/models/configuration_setting.rb +1 -1
  44. data/app/models/labeling/skos/base.rb +2 -2
  45. data/app/models/match/skos/base.rb +2 -2
  46. data/app/models/note/skos/base.rb +7 -6
  47. data/app/models/note/skos/change_note.rb +1 -1
  48. data/{lib/iqvoc/rdf_sync.rb → app/services/rdf_sync_service.rb} +3 -3
  49. data/app/view_models/concept_view.rb +1 -1
  50. data/app/views/collections/_form.html.erb +2 -2
  51. data/app/views/concepts/scheme/edit.html.erb +1 -1
  52. data/app/views/pages/components.html.erb +45 -0
  53. data/app/views/pages/version.html.erb +6 -0
  54. data/app/views/partials/concept/_reverse_match_notice.html.erb +0 -1
  55. data/app/views/search_results/_sidebar.html.erb +3 -3
  56. data/config/application.rb +4 -1
  57. data/config/boot.rb +1 -2
  58. data/config/database.yml.postgresql +23 -0
  59. data/config/engine.rb +0 -2
  60. data/config/environments/heroku.rb +1 -1
  61. data/config/initializers/inflections.rb +9 -3
  62. data/config/initializers/iqvoc.rb +1 -7
  63. data/config/initializers/mime_types.rb +0 -1
  64. data/config/locales/de.yml +2 -1
  65. data/config/locales/en.yml +11 -10
  66. data/config/routes.rb +2 -0
  67. data/config/travis/database.yml.mysql +9 -0
  68. data/config/travis/database.yml.postgresql +7 -0
  69. data/config/travis/database.yml.sqlite +5 -0
  70. data/db/migrate/20141204151558_add_foreign_key_constraints.rb +23 -0
  71. data/iqvoc.gemspec +2 -2
  72. data/lib/generators/app/template.rb +15 -7
  73. data/lib/iqvoc.rb +2 -1
  74. data/lib/iqvoc/configuration/core.rb +18 -4
  75. data/lib/iqvoc/configuration/instance_configuration.rb +125 -0
  76. data/lib/iqvoc/configuration/navigation.rb +63 -0
  77. data/lib/iqvoc/environments/development.rb +4 -0
  78. data/lib/iqvoc/environments/production.rb +11 -12
  79. data/lib/iqvoc/environments/test.rb +4 -1
  80. data/lib/iqvoc/version.rb +2 -2
  81. data/lib/tasks/exporter.rake +1 -4
  82. data/lib/tasks/importer.rake +1 -5
  83. data/lib/tasks/sync.rake +1 -2
  84. data/test/controllers/concept_movement_test.rb +11 -11
  85. data/test/controllers/hierarchy_test.rb +83 -79
  86. data/test/controllers/reverse_match_test.rb +2 -2
  87. data/test/integration/alphabetical_test.rb +2 -3
  88. data/test/integration/browse_concepts_and_labels_test.rb +2 -2
  89. data/test/integration/collection_circularity_test.rb +6 -6
  90. data/test/integration/concept_scheme_browsing_test.rb +2 -2
  91. data/test/integration/edit_concepts_test.rb +1 -1
  92. data/test/integration/export_test.rb +5 -3
  93. data/test/integration/import_test.rb +4 -1
  94. data/test/integration/instance_configuration_browsing_test.rb +2 -2
  95. data/test/integration/navigation_test.rb +2 -2
  96. data/test/integration/note_annotations_test.rb +12 -11
  97. data/test/integration/reverse_match_job_test.rb +19 -10
  98. data/test/integration/search_test.rb +6 -6
  99. data/test/integration/tree_test.rb +3 -3
  100. data/test/integration/untranslated_test.rb +1 -1
  101. data/test/models/concept_test.rb +13 -14
  102. data/test/models/inline_data_test.rb +9 -9
  103. data/test/models/instance_configuration_test.rb +7 -3
  104. data/test/models/origin_test.rb +9 -59
  105. data/test/models/rdf_sync_test.rb +2 -4
  106. data/test/models/rdfapi_test.rb +0 -2
  107. data/test/models/skos_collection_import_test.rb +3 -4
  108. data/test/models/skos_export_test.rb +3 -5
  109. data/test/models/skos_import_test.rb +12 -10
  110. data/test/test_helper.rb +0 -1
  111. data/vendor/assets/stylesheets/{jquery-ui.css.scss → jquery-ui.scss} +0 -0
  112. data/vendor/assets/stylesheets/{jquery-ui.structure.css.scss → jquery-ui.structure.scss} +0 -0
  113. data/vendor/assets/stylesheets/{jquery-ui.theme.css.scss → jquery-ui.theme.scss} +0 -0
  114. metadata +34 -28
  115. data/lib/iqvoc/ability.rb +0 -60
  116. data/lib/iqvoc/controller_extensions.rb +0 -111
  117. data/lib/iqvoc/deep_cloning.rb +0 -90
  118. data/lib/iqvoc/inline_data_helper.rb +0 -45
  119. data/lib/iqvoc/instance_configuration.rb +0 -123
  120. data/lib/iqvoc/maker.rb +0 -141
  121. data/lib/iqvoc/navigation.rb +0 -61
  122. data/lib/iqvoc/origin.rb +0 -111
  123. data/lib/iqvoc/rankable.rb +0 -33
  124. data/lib/iqvoc/rdfapi.rb +0 -60
  125. data/lib/iqvoc/skos_exporter.rb +0 -153
  126. data/lib/iqvoc/skos_importer.rb +0 -337
@@ -1,60 +0,0 @@
1
- module Iqvoc
2
- class Ability
3
- include CanCan::Ability
4
-
5
- @@if_published = lambda { |o| o.published? }
6
-
7
- def initialize(user = nil)
8
- can :read, Iqvoc::Concept.root_class.instance
9
- can :read, [::Concept::Base, ::Collection::Base, ::Label::Base], &@@if_published
10
-
11
- # static pages
12
- can :read, :help
13
-
14
- if user # Every logged in user ...
15
- can :use, :dashboard
16
- can :destroy, UserSession
17
-
18
- if user.owns_role?(:editor) || user.owns_role?(:publisher) || user.owns_role?(:administrator) # Editors and above ...
19
- can :read, [::Concept::Base, ::Collection::Base, ::Label::Base]
20
- can :create, [::Concept::Base, ::Collection::Base, ::Label::Base]
21
- can [:update, :destroy, :unlock], [::Concept::Base, ::Collection::Base, ::Label::Base], locked_by: user.id, published_at: nil
22
- can :lock, [::Concept::Base, ::Collection::Base, ::Label::Base], locked_by: nil, published_at: nil
23
- can [:check_consistency, :send_to_review], [::Concept::Base, ::Collection::Base, ::Label::Base], published_at: nil
24
- can :branch, [::Concept::Base, ::Collection::Base, ::Label::Base], &@@if_published
25
- end
26
-
27
- if user.owns_role?(:match_editor)
28
- can :read, ::Concept::Base
29
- can :create, ::Concept::Base
30
- can [:update, :lock], ::Concept::Base, locked_by: user.id, published_at: nil
31
- can :lock, ::Concept::Base, locked_by: nil, published_at: nil
32
- can :branch, ::Concept::Base, &@@if_published
33
- end
34
-
35
- if user.owns_role?(:publisher) || user.owns_role?(:administrator) # Publishers and above ...
36
- can :merge, [::Concept::Base, ::Collection::Base, ::Label::Base], published_at: nil
37
- end
38
-
39
- if user.owns_role?(:administrator)
40
- can [:update, :destroy, :unlock], [::Concept::Base, ::Label::Base], published_at: nil # Mustn't be locked by myself
41
-
42
- can :manage, User
43
- can :manage, Iqvoc.config
44
-
45
- can :full_export, ::Concept::Base
46
- can :import, ::Concept::Base
47
- can :export, ::Concept::Base
48
-
49
- can :update, Iqvoc::Concept.root_class.instance
50
-
51
- can :use, :administration
52
-
53
- can :reset, :thesaurus
54
- end
55
- else # no user
56
- can :create, UserSession
57
- end
58
- end
59
- end
60
- end
@@ -1,111 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module Iqvoc
4
- module ControllerExtensions
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- prepend_before_action :set_locale
9
- before_action :ensure_extension
10
-
11
- helper :all
12
- helper_method :current_user_session, :current_user, :concept_widget_data, :collection_widget_data, :label_widget_data
13
-
14
- rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
15
- rescue_from CanCan::AccessDenied, with: :handle_access_denied
16
- rescue_from ActionController::ParameterMissing, with: :handle_bad_request
17
- end
18
-
19
- protected
20
-
21
- def default_url_options(options = nil)
22
- { format: params[:format], lang: I18n.locale }.
23
- merge(options || {})
24
- end
25
-
26
- # Force an extension to every url. (LOD)
27
- def ensure_extension
28
- unless params[:format] || !request.get?
29
- flash.keep
30
- redirect_to url_for(params.merge(format: (request.format && request.format.symbol) || :html))
31
- end
32
- end
33
-
34
- def handle_access_denied(exception)
35
- @exception = exception
36
- @status = current_user ? 403 : 401
37
- @user_session = UserSession.new if @status == 401
38
- @return_url = request.fullpath
39
- respond_to do |format|
40
- format.html { render template: 'errors/access_denied', status: @status }
41
- format.any { head @status }
42
- end
43
- end
44
-
45
- def handle_not_found(exception)
46
- @exception = exception
47
- SearchResultsController.prepare_basic_variables(self)
48
-
49
- respond_to do |format|
50
- format.html { render template: 'errors/not_found', status: 404 }
51
- format.any { head 404 }
52
- end
53
- end
54
-
55
- def handle_bad_request(exception)
56
- @exception = exception
57
-
58
- respond_to do |format|
59
- format.any { head 400 }
60
- end
61
- end
62
-
63
- def set_locale
64
- if params[:lang].present? && Iqvoc::Concept.pref_labeling_languages.include?(params[:lang])
65
- I18n.locale = params[:lang]
66
- else
67
- I18n.locale = Iqvoc::Concept.pref_labeling_languages.first
68
- end
69
- end
70
-
71
- def concept_widget_data(concept, rank = nil)
72
- data = {
73
- id: concept.origin,
74
- name: (concept.pref_label && concept.pref_label.value.presence || ":#{concept.origin}") + (concept.additional_info ? " (#{concept.additional_info })" : '')
75
- }
76
- data[:rank] = rank if rank
77
- data
78
- end
79
-
80
- def collection_widget_data(collection)
81
- {
82
- id: collection.origin,
83
- name: collection.pref_label.to_s
84
- }
85
- end
86
-
87
- def label_widget_data(label)
88
- {
89
- id: label.origin,
90
- name: label.value
91
- }
92
- end
93
-
94
- # Configurable Ability class
95
- def current_ability
96
- @current_ability ||= Iqvoc.ability_class.new(current_user)
97
- end
98
-
99
- def current_user_session
100
- @current_user_session ||= UserSession.find
101
- end
102
-
103
- def current_user
104
- @current_user ||= current_user_session && current_user_session.user
105
- end
106
-
107
- def with_layout?
108
- !params[:layout]
109
- end
110
- end
111
- end
@@ -1,90 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- # Copyright 2011-2013 innoQ Deutschland GmbH
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- module Iqvoc
18
- module DeepCloning
19
- def self.included(base) #:nodoc:
20
- base.alias_method_chain :dup, :deep_cloning
21
- end
22
-
23
- # clones an ActiveRecord model.
24
- # if passed the :include option, it will deep clone the given associations
25
- # if passed the :except option, it won't clone the given attributes
26
- #
27
- # === Usage:
28
- #
29
- # ==== Cloning a model without an attribute
30
- # pirate.clone except: :name
31
- #
32
- # ==== Cloning a model without multiple attributes
33
- # pirate.clone except: [:name, :nick_name]
34
- # ==== Cloning one single association
35
- # pirate.clone include: :mateys
36
- #
37
- # ==== Cloning multiple associations
38
- # pirate.clone include: [:mateys, :treasures]
39
- #
40
- # ==== Cloning really deep
41
- # pirate.clone include: {treasures: :gold_pieces}
42
- #
43
- # ==== Cloning really deep with multiple associations
44
- # pirate.clone include: [:mateys, {treasures: :gold_pieces}]
45
- #
46
- # ==== Cloning multiple associations - but only the join table entries without cloning the associated objects themselves
47
- # pirate.clone include_association: [:matey_ids, :treasure_ids]
48
- #
49
- def dup_with_deep_cloning(options = {})
50
- kopy = dup_without_deep_cloning
51
-
52
- if options[:except]
53
- Array(options[:except]).each do |attribute|
54
- kopy.write_attribute(attribute, attributes_from_column_definition[attribute.to_s])
55
- end
56
- end
57
-
58
- if options[:include_association]
59
- Array(options[:include_association]).each do |association_attribute|
60
- kopy.send("#{association_attribute}=", self.send("#{association_attribute}"))
61
- end
62
- end
63
-
64
- if options[:include]
65
- Array(options[:include]).each do |association, deep_associations|
66
- if (association.kind_of? Hash)
67
- deep_associations = association[association.keys.first]
68
- association = association.keys.first
69
- end
70
- opts = deep_associations.blank? ? {} : { include: deep_associations }
71
- association_reflection = self.class.reflect_on_association(association)
72
- cloned_object = case association_reflection.macro
73
- when :belongs_to, :has_one
74
- self.send(association) && self.send(association).dup(opts)
75
- when :has_many, :has_and_belongs_to_many
76
- fk = association_reflection.options[:foreign_key]# || self.class.to_s.underscore
77
- self.send(association).collect do |obj|
78
- cloned_obj = obj.dup(opts)
79
- cloned_obj.send("#{fk}=", kopy.id) unless fk.blank?
80
- cloned_obj
81
- end
82
- end
83
- kopy.send("#{association}=", cloned_object)
84
- end
85
- end
86
-
87
- return kopy
88
- end
89
- end
90
- end
@@ -1,45 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- # Copyright 2011-2013 innoQ Deutschland GmbH
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'csv'
18
-
19
- module Iqvoc
20
- module InlineDataHelper
21
- # delimiters for strings representing a list of values - XXX: lacks encapsulation
22
- JOINER = ', '
23
- SPLITTER = /[,\n] */
24
-
25
- CSV_OPTIONS = {
26
- col_sep: ', ',
27
- quote_char: '"'
28
- }
29
-
30
- def self.parse_inline_values(inline_values)
31
- options = CSV_OPTIONS.clone
32
- options[:col_sep] = options[:col_sep].strip
33
- begin
34
- values = inline_values.parse_csv(options)
35
- rescue CSV::MalformedCSVError => exc
36
- values = inline_values.parse_csv(CSV_OPTIONS)
37
- end
38
- values ? values.map(&:strip) : []
39
- end
40
-
41
- def self.generate_inline_values(values)
42
- values.to_csv(CSV_OPTIONS).strip
43
- end
44
- end
45
- end
@@ -1,123 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- # Copyright 2011-2013 innoQ Deutschland GmbH
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'singleton'
18
-
19
- module Iqvoc
20
- # provides the interface to configuration settings
21
- class InstanceConfiguration
22
- include Singleton
23
-
24
- attr_reader :defaults # XXX: dangerous (mutable object)
25
-
26
- class UnregisteredSetting < ArgumentError
27
- def to_s
28
- 'A setting needs to be registered with register_setting before it can be used.'
29
- end
30
- end
31
-
32
- def initialize
33
- @defaults = {} # default settings
34
- @records = {} # customized (non-default) settings
35
- @settings = {} # current settings, using defaults as fallback
36
- # NB: cannot cache immediately because defaults need to be registered first
37
- end
38
-
39
- # convenience wrapper for `register_setting` batch operations
40
- # accepts a hash of key / default value pairs
41
- def register_settings(settings)
42
- settings.each do |key, default_value|
43
- register_setting(key, default_value)
44
- end
45
- end
46
-
47
- # create or update a default setting
48
- def register_setting(key, default_value)
49
- self.class.validate_value(default_value)
50
-
51
- @defaults[key] = default_value
52
-
53
- # update cache
54
- @settings[key] = @records[key] || default_value
55
- end
56
-
57
- # remove a default setting
58
- # returns nil if setting does not exist
59
- # NB: does *not* delete configuration settings from the database
60
- def deregister_setting(key)
61
- res = @defaults.delete(key)
62
-
63
- # update cache
64
- @settings.delete(key)
65
-
66
- return res
67
- end
68
-
69
- # retrieve individual setting, using default value as fallback
70
- def [](key)
71
- initialize_cache unless @initialized
72
- return @settings[key]
73
- end
74
-
75
- # store individual customized setting
76
- def []=(key, value)
77
- raise UnregisteredSetting unless @defaults.include?(key)
78
- self.class.validate_value(value)
79
-
80
- json = JSON.dump([value])[1..-2] # temporary array wrapper ensures valid JSON text
81
- if setting = ConfigurationSetting.find_by_key(key)
82
- setting.update_attributes(value: json)
83
- else
84
- ConfigurationSetting.create(key: key, value: json)
85
- end
86
-
87
- # update cache
88
- @records[key] = value
89
- @settings[key] = value
90
-
91
- return value
92
- end
93
-
94
- # populate settings caches
95
- # (subsequent updates will happen automatically via the respective setters)
96
- def initialize_cache
97
- return false unless ConfigurationSetting.table_exists? # pre-migration
98
-
99
- # cache customized settings
100
- ConfigurationSetting.all.each do |setting|
101
- @records[setting.key] = JSON.load("[#{setting.value}]")[0] # temporary array wrapper ensures valid JSON text
102
- end
103
-
104
- # cache current settings
105
- @defaults.each do |key, default_value|
106
- value = @records[key]
107
- @settings[key] = value.nil? ? default_value : value
108
- end
109
-
110
- @initialized = true
111
- end
112
-
113
- # checks whether value type is supported
114
- def self.validate_value(value) # TODO: compare type to default's? (cf. controller)
115
- if value == nil
116
- raise TypeError, 'nil values not supported'
117
- end
118
- unless [TrueClass, FalseClass, String, Fixnum, Float, Array].include?(value.class)
119
- raise TypeError, 'complex values not supported'
120
- end
121
- end
122
- end
123
- end
@@ -1,141 +0,0 @@
1
- module Iqvoc
2
- module Maker
3
- # labels:
4
- # -
5
- # value: <string>
6
- # <attribute>: <value>
7
- # inflectionals: [<string>, ...]
8
- # components: [<label>, ...]
9
- #
10
- # concepts:
11
- # -
12
- # <attribute>: <value>
13
- # pref_labels: [<label>, ...]
14
- # alt_labels: [<label>, ...]
15
- # broader: <concept>
16
- # narrower: <concept>
17
- # related: [<concept>, ...]
18
- #
19
- # NB:
20
- # * <label> and <concept> can either be strings referencing a previously
21
- # declared entity or objects representing a new entity
22
- # XXX: The latter is not currently supported yet!
23
- # * order of concepts matters when referencing relations
24
- # * order of labels matters when referencing components
25
- def self.from_yaml(yml)
26
- data = YAML.load(yml)
27
-
28
- labels = {}
29
- data['labels'].each { |label| # XXX: use omap to simplify format (making `value` the key instead of an attribute)?
30
- term = label.delete('value')
31
-
32
- components = label.delete('components').map { |term|
33
- labels[term]
34
- } if label['components']
35
-
36
- options = {
37
- inflectionals: label.delete('inflectionals'),
38
- components: components,
39
- label_attributes: label
40
- }
41
-
42
- labels[term] = self.label(term, options)
43
- } if data['labels']
44
-
45
- concepts = {}
46
- data['concepts'].each { |concept| # XXX: use omap to simplify format (using a single pref_label as key)?
47
- relations = {}
48
- ['broader', 'narrower'].each { |type| # TODO: missing related, support for poly-hierarchies
49
- relations[type] = concepts[concept.delete(type)] if concept[type]
50
- }
51
-
52
- lbls = {} # TODO: rename
53
- ['pref', 'alt'].each { |type| # TODO: missing hidden
54
- key = "#{type}_labels"
55
- lbls[type] = concept.delete(key).map { |term|
56
- labels[term]
57
- } if concept[key]
58
- }
59
-
60
- options = {
61
- pref_labels: lbls['pref'],
62
- alt_labels: lbls['alt'],
63
- concept_attributes: concept
64
- }
65
-
66
- identifier = options[:pref_labels].first.value
67
- concepts[identifier] = self.concept(options)
68
- concepts[identifier].send(Iqvoc::Concept.broader_relation_class.name.to_relation_name).
69
- create_with_reverse_relation(relations['broader']) if relations['broader']
70
- concepts[identifier].send(Iqvoc::Concept.broader_relation_class.narrower_class.name.to_relation_name).
71
- create_with_reverse_relation(relations['narrower']) if relations['narrower']
72
- } if data['concepts']
73
-
74
- return { concepts: concepts, labels: labels }
75
- end
76
-
77
- # optional arguments:
78
- # concept_attributes for custom concept attributes
79
- # pref_labels is an array of strings or label instances to be used as prefLabels
80
- # alt_labels is an array of strings or label instances to be used as altLabels
81
- def self.concept(options={})
82
- attributes = options[:concept_attributes] || {}
83
- pref_labels = options[:pref_labels] || []
84
- alt_labels = options[:alt_labels] || []
85
-
86
- defaults = { # NB: must use strings, not symbols as keys due to YAML
87
- 'published_at' => 3.days.ago
88
- }
89
- attributes = defaults.merge(attributes)
90
-
91
- concept = Iqvoc::Concept.base_class.create!(attributes)
92
-
93
- pref_labels.each { |term|
94
- label = term.is_a?(String) ? self.label(term) : term
95
- Iqvoc::Concept.pref_labeling_class.
96
- create!(owner: concept, target: label)
97
- }
98
- alt_labels.each { |term|
99
- label = term.is_a?(String) ? self.label(term) : term
100
- Iqvoc::Concept.further_labeling_classes.first.first.
101
- create!(owner: concept, target: label)
102
- }
103
-
104
- return concept
105
- end
106
-
107
- # optional arguments:
108
- # label_attributes for custom label attributes
109
- # inflectionals is an array of strings to be used as inflectionals
110
- # components is an array of labels to be used as compound form contents
111
- def self.label(value, options={}) # FIXME: move into SKOS-XL extension
112
- attributes = options[:label_attributes] || {}
113
- inflectionals = options[:inflectionals] || []
114
- components = options[:components] || []
115
-
116
- defaults = { # NB: must use strings, not symbols as keys due to YAML
117
- value: value, # intentionally not a string; symbol takes precedence
118
- 'origin' => Iqvoc::Origin.new(value).to_s,
119
- 'language' => Iqvoc::Concept.pref_labeling_languages.first,
120
- 'published_at' => 2.days.ago
121
- }
122
- attributes = defaults.merge(attributes)
123
-
124
- klass = Iqvoc::XLLabel rescue Iqvoc::Label # FIXME: breaks encapsulation (hard-coded iqvoc_skosxl dependency)
125
- label = klass.base_class.create!(attributes)
126
-
127
- inflectionals.each { |inf|
128
- label.inflectionals.create!(value: inf)
129
- }
130
-
131
- if components.length > 0
132
- compound_form_contents = components.each_with_index.map { |label, i|
133
- CompoundForm::Content::Base.new(label: label, order: i)
134
- }
135
- label.compound_forms.create!(compound_form_contents: compound_form_contents)
136
- end
137
-
138
- return label
139
- end
140
- end
141
- end