iqvoc 4.0.8 → 4.0.9

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.
Files changed (209) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/Gemfile +5 -1
  3. data/Gemfile.lock +35 -18
  4. data/README.md +3 -2
  5. data/app/assets/stylesheets/iqvoc/components.css.scss +0 -6
  6. data/app/controllers/collections_controller.rb +30 -17
  7. data/app/controllers/concepts/alphabetical_controller.rb +15 -9
  8. data/app/{models/collection/member/concept.rb → controllers/concepts/expired_controller.rb} +13 -15
  9. data/app/controllers/concepts/hierarchical_controller.rb +3 -0
  10. data/app/controllers/concepts_controller.rb +2 -3
  11. data/app/controllers/instance_configuration_controller.rb +5 -6
  12. data/app/controllers/search_results_controller.rb +1 -2
  13. data/app/helpers/application_helper.rb +1 -5
  14. data/app/helpers/concepts_helper.rb +1 -1
  15. data/app/helpers/rdf_helper.rb +1 -1
  16. data/app/helpers/widget_helper.rb +3 -3
  17. data/app/models/collection/base.rb +64 -46
  18. data/app/models/collection/member/base.rb +12 -0
  19. data/app/models/collection/member/skos/base.rb +13 -12
  20. data/app/models/collection/skos/base.rb +1 -1
  21. data/app/models/collection/{member/collection.rb → skos/unordered.rb} +1 -16
  22. data/app/models/collection/unordered.rb +7 -0
  23. data/app/models/concept/base.rb +26 -107
  24. data/app/models/concept/relation/base.rb +4 -0
  25. data/app/models/concept/relation/skos/base.rb +17 -7
  26. data/app/models/concept/skos/base.rb +10 -1
  27. data/app/models/concept/skos/scheme.rb +1 -1
  28. data/app/models/concept/validations.rb +117 -0
  29. data/app/models/label/base.rb +4 -3
  30. data/app/models/labeling/skos/base.rb +24 -13
  31. data/app/models/match/skos/base.rb +24 -5
  32. data/app/models/note/skos/base.rb +17 -14
  33. data/app/views/collections/_form.html.erb +2 -2
  34. data/app/views/collections/_header.html.erb +2 -2
  35. data/app/views/collections/_sidebar.html.erb +3 -3
  36. data/app/views/collections/index.html.erb +1 -1
  37. data/app/views/collections/show.html.erb +1 -1
  38. data/app/views/collections/show.iqrdf +1 -1
  39. data/app/views/concepts/alphabetical/index.html.erb +1 -1
  40. data/app/views/concepts/expired/index.html.erb +16 -0
  41. data/app/views/concepts/notifications/_referenced_concepts.html.erb +1 -1
  42. data/app/views/concepts/sidebars/_plural.html.erb +4 -0
  43. data/app/views/dashboard/index.html.erb +1 -1
  44. data/app/views/layouts/_controls.html.erb +25 -24
  45. data/app/views/layouts/_navigation.html.erb +1 -1
  46. data/app/views/layouts/application.html.erb +0 -6
  47. data/app/views/partials/concept/_edit_link_base.html.erb +2 -1
  48. data/app/views/partials/labeling/skos/_base.html.erb +1 -2
  49. data/app/views/partials/note/_edit_base.html.erb +1 -1
  50. data/app/views/partials/note/skos/_edit_change_note.html.erb +1 -1
  51. data/app/views/rdf/scheme.iqrdf +1 -1
  52. data/app/views/search_results/_header.html.erb +2 -2
  53. data/app/views/search_results/_sidebar.html.erb +2 -2
  54. data/app/views/search_results/index.html.erb +1 -1
  55. data/app/views/triplestore_sync/index.html.erb +2 -2
  56. data/config/locales/de.yml +9 -2
  57. data/config/locales/en.yml +11 -4
  58. data/config/locales/pt.yml +8 -3
  59. data/config/routes.rb +15 -6
  60. data/db/migrate/20130227145825_fix_collection_type.rb +10 -0
  61. data/db/schema.rb +1 -1
  62. data/lib/generators/app/template.rb +20 -0
  63. data/lib/iqvoc/configuration/collection.rb +5 -5
  64. data/lib/iqvoc/configuration/concept.rb +7 -7
  65. data/lib/iqvoc/configuration/core.rb +11 -10
  66. data/lib/iqvoc/controller_extensions.rb +2 -5
  67. data/lib/iqvoc/inline_data_helper.rb +25 -3
  68. data/lib/iqvoc/instance_configuration.rb +1 -1
  69. data/lib/iqvoc/rdfapi.rb +56 -0
  70. data/lib/iqvoc/skos_importer.rb +88 -40
  71. data/lib/iqvoc/version.rb +1 -1
  72. data/lib/multi_logger.rb +38 -0
  73. data/lib/tasks/importer.rake +6 -1
  74. data/test/integration/browse_concepts_and_labels_test.rb +16 -0
  75. data/test/integration/instance_configuration_test.rb +5 -5
  76. data/test/integration/search_test.rb +18 -17
  77. data/test/unit/concept_test.rb +53 -4
  78. data/test/unit/inline_data_test.rb +61 -0
  79. data/test/unit/origin_test.rb +1 -1
  80. data/test/unit/rdfapi_test.rb +83 -0
  81. data/test/unit/skos_import_test.rb +1 -1
  82. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  83. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_flat_55_fbec88_40x100.png +0 -0
  84. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  85. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  86. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  87. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  88. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  89. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  90. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_217bc0_256x240.png +0 -0
  91. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_2e83ff_256x240.png +0 -0
  92. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_469bdd_256x240.png +0 -0
  93. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_6da8d5_256x240.png +0 -0
  94. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_cd0a0a_256x240.png +0 -0
  95. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_d8e7f3_256x240.png +0 -0
  96. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_f9bd01_256x240.png +0 -0
  97. data/vendor/assets/stylesheets/{jquery-ui-1.8.23.custom.css → jquery-ui-1.8.23.custom.css.scss} +17 -17
  98. metadata +29 -131
  99. data/app/controllers/collections/hierarchical_controller.rb +0 -44
  100. data/public/assets/ajax-loader-dada1fbb71d7fb80d8dde7a031ae6cd0.gif +0 -0
  101. data/public/assets/ajax-loader.gif +0 -0
  102. data/public/assets/arrow_down-07c5dea12928d65fcc31c08279366170.gif +0 -0
  103. data/public/assets/arrow_down.gif +0 -0
  104. data/public/assets/arrow_up-51ede92c113b9a870e7a306907360ba8.gif +0 -0
  105. data/public/assets/arrow_up.gif +0 -0
  106. data/public/assets/bootstrap/bootstrap-2012a68e8267282c0a2c177d7005ae6d.css +0 -9
  107. data/public/assets/bootstrap/bootstrap-2012a68e8267282c0a2c177d7005ae6d.css.gz +0 -0
  108. data/public/assets/bootstrap/bootstrap-35fd77cdf54a8cb63a39d8d0cea7a746.js +0 -19
  109. data/public/assets/bootstrap/bootstrap-35fd77cdf54a8cb63a39d8d0cea7a746.js.gz +0 -0
  110. data/public/assets/bootstrap/bootstrap-responsive-609b376f4bb032588c054b563d4bca1f.css +0 -9
  111. data/public/assets/bootstrap/bootstrap-responsive-609b376f4bb032588c054b563d4bca1f.css.gz +0 -0
  112. data/public/assets/bootstrap/bootstrap-responsive.css +0 -9
  113. data/public/assets/bootstrap/bootstrap-responsive.css.gz +0 -0
  114. data/public/assets/bootstrap/bootstrap.css +0 -9
  115. data/public/assets/bootstrap/bootstrap.css.gz +0 -0
  116. data/public/assets/bootstrap/bootstrap.js +0 -19
  117. data/public/assets/bootstrap/bootstrap.js.gz +0 -0
  118. data/public/assets/bootstrap/glyphicons-halflings-0e7ff93d8f48fe1f5f762e4312e78da7.png +0 -0
  119. data/public/assets/bootstrap/glyphicons-halflings-white-ef3d5b8d6a297804352b4a46fdb5466d.png +0 -0
  120. data/public/assets/bootstrap/glyphicons-halflings-white.png +0 -0
  121. data/public/assets/bootstrap/glyphicons-halflings.png +0 -0
  122. data/public/assets/file-58ce0b58f19dfe871b25270e98cff66c.gif +0 -0
  123. data/public/assets/file.gif +0 -0
  124. data/public/assets/folder-5c5b1fd2f1ece710f9159f05cc2aaaa8.gif +0 -0
  125. data/public/assets/folder-closed-8b61fc55011d534f0216c1150994f229.gif +0 -0
  126. data/public/assets/folder-closed.gif +0 -0
  127. data/public/assets/folder.gif +0 -0
  128. data/public/assets/html5-05e1be9157c8366db72fb7a1bcc8daff.js +0 -3
  129. data/public/assets/html5-05e1be9157c8366db72fb7a1bcc8daff.js.gz +0 -0
  130. data/public/assets/html5.js +0 -3
  131. data/public/assets/html5.js.gz +0 -0
  132. data/public/assets/iqvoc/ie_fixes-6a106c21d979ccdd1f6bf1cb129a0e69.css +0 -1
  133. data/public/assets/iqvoc/ie_fixes-6a106c21d979ccdd1f6bf1cb129a0e69.css.gz +0 -0
  134. data/public/assets/iqvoc/ie_fixes.css +0 -1
  135. data/public/assets/iqvoc/ie_fixes.css.gz +0 -0
  136. data/public/assets/iqvoc_logo-316859a511c646918fe75e92fa0bf6ac.png +0 -0
  137. data/public/assets/iqvoc_logo.png +0 -0
  138. data/public/assets/jquery-ui/ui-bg_flat_0_aaaaaa_40x100-a1eb3e0764573ed4b261ca742ed96ac3.png +0 -0
  139. data/public/assets/jquery-ui/ui-bg_flat_55_fbec88_40x100-439ee8e6c8ce855f43ed4d7b90684720.png +0 -0
  140. data/public/assets/jquery-ui/ui-bg_glass_75_d0e5f5_1x400-9357836db77954d0d8c5feb259635223.png +0 -0
  141. data/public/assets/jquery-ui/ui-bg_glass_85_dfeffc_1x400-7beb11d1590fb2fb1ef5c754100a078a.png +0 -0
  142. data/public/assets/jquery-ui/ui-bg_glass_95_fef1ec_1x400-c723e9a2b50006c6054836a10b76bb84.png +0 -0
  143. data/public/assets/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100-cb26f48ac4912c23ce301c69c474d306.png +0 -0
  144. data/public/assets/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100-519299e2aa31bffdd4fed34b4fac603d.png +0 -0
  145. data/public/assets/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100-27e08524d3d56bb59e354435b663c3ac.png +0 -0
  146. data/public/assets/jquery-ui/ui-icons_217bc0_256x240-ed26778199d8722ae064038a1e841bc8.png +0 -0
  147. data/public/assets/jquery-ui/ui-icons_2e83ff_256x240-94086d0ce953eb0887ab1b8140903af9.png +0 -0
  148. data/public/assets/jquery-ui/ui-icons_469bdd_256x240-1c055f2d65517ef8faf1d1999c8ac2fa.png +0 -0
  149. data/public/assets/jquery-ui/ui-icons_6da8d5_256x240-8f5b417c5604f1b7b5965c98754c33b9.png +0 -0
  150. data/public/assets/jquery-ui/ui-icons_cd0a0a_256x240-8b44e266bdc1f57f1393579591f89222.png +0 -0
  151. data/public/assets/jquery-ui/ui-icons_d8e7f3_256x240-1b415e411069df902e6f417cc014172c.png +0 -0
  152. data/public/assets/jquery-ui/ui-icons_f9bd01_256x240-4553d0576c0498ca4c776aa77aa80833.png +0 -0
  153. data/public/assets/json2-b08b7b9af3e715f42c088ac728f62a2b.js +0 -157
  154. data/public/assets/json2-b08b7b9af3e715f42c088ac728f62a2b.js.gz +0 -0
  155. data/public/assets/json2.js +0 -157
  156. data/public/assets/json2.js.gz +0 -0
  157. data/public/assets/manifest-3ce8edde69d5d291841ef7c49daaa9cb.js +0 -21
  158. data/public/assets/manifest-3ce8edde69d5d291841ef7c49daaa9cb.js.gz +0 -0
  159. data/public/assets/manifest-c0eca563fd9f16907d302af9a2dcae6b.css +0 -51
  160. data/public/assets/manifest-c0eca563fd9f16907d302af9a2dcae6b.css.gz +0 -0
  161. data/public/assets/manifest.css +0 -51
  162. data/public/assets/manifest.css.gz +0 -0
  163. data/public/assets/manifest.js +0 -21
  164. data/public/assets/manifest.js.gz +0 -0
  165. data/public/assets/manifest.yml +0 -47
  166. data/public/assets/minus-1d0fae0720bab52bd98598218e8345c0.gif +0 -0
  167. data/public/assets/minus.gif +0 -0
  168. data/public/assets/plus-1a29e46532f839ed9c977ef4613d079f.gif +0 -0
  169. data/public/assets/plus.gif +0 -0
  170. data/public/assets/spinner_16x16-17dcf941457ae4e702f4600e714b21c1.gif +0 -0
  171. data/public/assets/spinner_16x16.gif +0 -0
  172. data/public/assets/spinner_24x24-78c707c1921b93962ea5edd7f4a74134.gif +0 -0
  173. data/public/assets/spinner_24x24.gif +0 -0
  174. data/public/assets/treeview-black-c46d96020e5d79c652af0fb0c6656384.gif +0 -0
  175. data/public/assets/treeview-black-line-0903c58efd34c3203d132e6f873049f6.gif +0 -0
  176. data/public/assets/treeview-black-line.gif +0 -0
  177. data/public/assets/treeview-black.gif +0 -0
  178. data/public/assets/treeview-default-ee6298d311205d21dc57c01c0696df70.gif +0 -0
  179. data/public/assets/treeview-default-line-2c4106cfd4d322c6e6565f80702c27cb.gif +0 -0
  180. data/public/assets/treeview-default-line.gif +0 -0
  181. data/public/assets/treeview-default.gif +0 -0
  182. data/public/assets/treeview-famfamfam-20dfef13cd5fd1e08fb61ee68eb9d3fa.gif +0 -0
  183. data/public/assets/treeview-famfamfam-line-a02cce2b80977e066df83137aae71fa8.gif +0 -0
  184. data/public/assets/treeview-famfamfam-line.gif +0 -0
  185. data/public/assets/treeview-famfamfam.gif +0 -0
  186. data/public/assets/treeview-gray-01bfdcd116e081e23daf13024fd3e4e0.gif +0 -0
  187. data/public/assets/treeview-gray-line-029b3a7b92ed10ea6c4b6289cb9fa0e3.gif +0 -0
  188. data/public/assets/treeview-gray-line.gif +0 -0
  189. data/public/assets/treeview-gray.gif +0 -0
  190. data/public/assets/treeview-red-2a5abbce598d05c864d845998381eef6.gif +0 -0
  191. data/public/assets/treeview-red-line-f51e6c30aa3b0ff856900ba85d769f1c.gif +0 -0
  192. data/public/assets/treeview-red-line.gif +0 -0
  193. data/public/assets/treeview-red.gif +0 -0
  194. data/vendor/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  195. data/vendor/assets/images/jquery-ui/ui-bg_flat_55_fbec88_40x100.png +0 -0
  196. data/vendor/assets/images/jquery-ui/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  197. data/vendor/assets/images/jquery-ui/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  198. data/vendor/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  199. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  200. data/vendor/assets/images/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  201. data/vendor/assets/images/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  202. data/vendor/assets/images/jquery-ui/ui-icons_217bc0_256x240.png +0 -0
  203. data/vendor/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png +0 -0
  204. data/vendor/assets/images/jquery-ui/ui-icons_469bdd_256x240.png +0 -0
  205. data/vendor/assets/images/jquery-ui/ui-icons_6da8d5_256x240.png +0 -0
  206. data/vendor/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png +0 -0
  207. data/vendor/assets/images/jquery-ui/ui-icons_d8e7f3_256x240.png +0 -0
  208. data/vendor/assets/images/jquery-ui/ui-icons_f9bd01_256x240.png +0 -0
  209. data/vendor/assets/javascripts/json2.js +0 -487
@@ -25,4 +25,16 @@ class Collection::Member::Base < ActiveRecord::Base
25
25
  belongs_to :collection, :class_name => 'Collection::Base'
26
26
  belongs_to :target, :class_name => 'Concept::Base'
27
27
 
28
+ def self.view_section(obj)
29
+ "main"
30
+ end
31
+
32
+ def self.view_section_sort_key(obj)
33
+ 100
34
+ end
35
+
36
+ def self.partial_name(obj)
37
+ "partials/collection/member"
38
+ end
39
+
28
40
  end
@@ -16,22 +16,23 @@
16
16
 
17
17
  class Collection::Member::SKOS::Base < Collection::Member::Base
18
18
 
19
- self.rdf_namespace = "skos"
20
- self.rdf_predicate = "member"
19
+ self.rdf_namespace = 'skos'
20
+ self.rdf_predicate = 'member'
21
21
 
22
- def self.build_from_rdf(subject, predicate, object)
23
- raise "Labeling::SKOS::Base#build_from_rdf: Subject (#{subject}) must be a Collection." unless subject.is_a?(Collection::Base)
24
- raise "Labeling::SKOS::Base#build_from_rdf: Object (#{object}) must be a Collection or Concept." unless object.is_a?(Collection::Base) or object.is_a?(Concept::Base)
22
+ def self.build_from_rdf(rdf_subject, rdf_predicate, rdf_object)
23
+ raise "#{self.name}#build_from_rdf: Subject (#{rdf_subject}) must be a Collection." unless rdf_subject.is_a?(Collection::Base)
24
+ raise "#{self.name}#build_from_rdf: Object (#{rdf_object}) must be a Collection or Concept." unless rdf_object.is_a?(Collection::Base) or rdf_object.is_a?(Concept::Base)
25
25
 
26
- if subject.send(:members).select{|rel| rel.collection_id == subject.id || rel.target == object}.empty?
27
- subject.send(:members) << self.new(:target => object)
28
- if object.is_a?(Collection::Base)
29
- subject.send(:subcollections) << object
30
- end
26
+ member_instance = rdf_subject.members.select{|rel| rel.target == rdf_object}.first
27
+ if member_instance.nil?
28
+ predicate_class = Iqvoc::RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
29
+ member_instance = predicate_class.new(:target => rdf_object)
30
+ rdf_subject.members << member_instance
31
31
  end
32
32
 
33
- if object.send(:collections).select{|coll| coll.id == subject.id}.empty?
34
- object.send(:collections) << subject
33
+ if rdf_object.collections.select{|coll| coll.id == rdf_subject.id}.empty?
34
+ rdf_object.collections << rdf_subject
35
35
  end
36
+ member_instance
36
37
  end
37
38
  end
@@ -19,7 +19,7 @@ class Collection::SKOS::Base < Collection::Base
19
19
  self.rdf_namespace = "skos"
20
20
  self.rdf_class = "Collection"
21
21
 
22
- def build_rdf_subject(document, controller, &block)
22
+ def build_rdf_subject(&block)
23
23
  ns = IqRdf::Namespace.find_namespace_class(self.rdf_namespace)
24
24
  raise "Namespace '#{base_namespace}' is not defined in IqRdf document." unless ns
25
25
  subject = IqRdf.build_uri(self.origin, ns.build_uri(self.rdf_class), &block)
@@ -14,20 +14,5 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Collection::Member::Collection < Collection::Member::Base
18
-
19
- belongs_to :subcollection, :class_name => 'Collection::Base', :foreign_key => 'target_id'
20
-
21
- def self.view_section(obj)
22
- "main"
23
- end
24
-
25
- def self.view_section_sort_key(obj)
26
- 100
27
- end
28
-
29
- def self.partial_name(obj)
30
- "partials/collection/member"
31
- end
32
-
17
+ class Collection::SKOS::Unordered < Collection::SKOS::Base
33
18
  end
@@ -14,5 +14,12 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+
17
18
  class Collection::Unordered < Collection::SKOS::Base
19
+
20
+ def initialize(*args)
21
+ ActiveSupport::Deprecation.warn("Collection::Unordered is deprecated. Use Collection::SKOS::Unordered instead.")
22
+ super
23
+ end
24
+
18
25
  end
@@ -27,19 +27,7 @@ class Concept::Base < ActiveRecord::Base
27
27
  self.rdf_namespace = nil
28
28
  self.rdf_class = nil
29
29
 
30
- # ********** Validations
31
-
32
- validates :origin, :presence => true, :on => :update
33
-
34
- validate :ensure_distinct_versions, :on => :create
35
-
36
- validate :ensure_a_pref_label_in_the_primary_thesaurus_language,
37
- :on => :update
38
-
39
- validate :ensure_no_pref_labels_share_the_same_language
40
- validate :ensure_exclusive_top_term
41
- validate :ensure_rooted_top_terms
42
- validate :ensure_valid_rank_for_ranked_relations
30
+ include Concept::Validations
43
31
 
44
32
  Iqvoc::Concept.include_modules.each do |mod|
45
33
  include mod
@@ -63,9 +51,10 @@ class Concept::Base < ActiveRecord::Base
63
51
  labeling_class = reflection && reflection.class_name && reflection.class_name.constantize
64
52
  if labeling_class && labeling_class < Labeling::Base
65
53
  self.send(relation_name).all.map(&:destroy)
66
- lang_values = {nil => lang_values.first} if lang_values.is_a?(Array) # For language = nil: <input name=bla[labeling_class][]> => Results in an Array!
67
- lang_values.each do |lang, values|
68
- values.split(Iqvoc::InlineDataHelper::Splitter).each do |value|
54
+ lang_values = { nil => lang_values.first } if lang_values.is_a?(Array) # For language = nil: <input name=bla[labeling_class][]> => Results in an Array! -- XXX: obsolete/dupe (cf `labelings_by_text=`)?
55
+ lang_values.each do |lang, inline_values|
56
+ lang = nil if lang.to_s == 'none'
57
+ Iqvoc::InlineDataHelper.parse_inline_values(inline_values).each do |value|
69
58
  value.squish!
70
59
  self.send(relation_name).build(:target => labeling_class.label_class.new(:value => value, :language => lang)) unless value.blank?
71
60
  end
@@ -85,7 +74,7 @@ class Concept::Base < ActiveRecord::Base
85
74
  # rankable: {'relation_name' => ['origin1:100', 'origin2:90']}
86
75
  (@concept_relations_by_id ||= {}).each do |relation_name, new_origins|
87
76
  # Split comma-separated origins and clean up parameter strings
88
- new_origins = new_origins.split(Iqvoc::InlineDataHelper::Splitter).map(&:squish)
77
+ new_origins = new_origins.split(Iqvoc::InlineDataHelper::SPLITTER).map(&:squish)
89
78
 
90
79
  # Extract embedded ranks (if any) from origin strings (e.g. "origin1:100")
91
80
  # => { 'origin1' => nil, 'origin2' => 90 }
@@ -139,7 +128,7 @@ class Concept::Base < ActiveRecord::Base
139
128
  has_many :matches, :foreign_key => 'concept_id', :class_name => "Match::Base", :dependent => :destroy
140
129
  include_to_deep_cloning(:matches)
141
130
 
142
- has_many :collection_members, :foreign_key => 'target_id', :class_name => "Collection::Member::Concept", :dependent => :destroy
131
+ has_many :collection_members, :foreign_key => 'target_id', :class_name => "Collection::Member::Base", :dependent => :destroy
143
132
  has_many :collections, :through => :collection_members, :class_name => Iqvoc::Collection.base_class_name
144
133
  include_to_deep_cloning(:collection_members)
145
134
 
@@ -300,18 +289,22 @@ class Concept::Base < ActiveRecord::Base
300
289
  def labelings_by_text=(hash)
301
290
  @labelings_by_text = hash
302
291
 
303
- # For language = nil: <input name=bla[labeling_class][]> => Results in an Array!
304
- @labelings_by_text.each do |relation_name, array_or_hash|
305
- @labelings_by_text[relation_name] = {nil => array_or_hash.first} if array_or_hash.is_a?(Array)
292
+ @labelings_by_text.each do |relation_name, labels_by_lang|
293
+ # if `language` is `nil`, the respective HTML form field returns an array
294
+ # instead of a hash (`<input name=bla[labeling_class][]>`)
295
+ if labels_by_lang.is_a?(Array)
296
+ @labelings_by_text[relation_name] = { nil => labels_by_lang.first }
297
+ end
306
298
  end
307
299
 
308
300
  @labelings_by_text
309
301
  end
310
302
 
311
303
  def labelings_by_text(relation_name, language)
312
- (@labelings_by_text && @labelings_by_text[relation_name] && @labelings_by_text[relation_name][language]) ||
313
- self.send(relation_name).by_label_language(language).
314
- map { |l| l.target.value }.join(Iqvoc::InlineDataHelper::Joiner)
304
+ (@labelings_by_text && @labelings_by_text[relation_name] &&
305
+ @labelings_by_text[relation_name][language]) ||
306
+ Iqvoc::InlineDataHelper.generate_inline_values(self.send(relation_name).
307
+ by_label_language(language).map { |l| l.target.value })
315
308
  end
316
309
 
317
310
  def concept_relations_by_id=(hash)
@@ -321,7 +314,7 @@ class Concept::Base < ActiveRecord::Base
321
314
  def concept_relations_by_id(relation_name)
322
315
  (@concept_relations_by_id && @concept_relations_by_id[relation_name]) ||
323
316
  self.send(relation_name).map { |l| l.target.origin }.
324
- join(Iqvoc::InlineDataHelper::Joiner)
317
+ join(Iqvoc::InlineDataHelper::JOINER)
325
318
  end
326
319
 
327
320
  def concept_relations_by_id_and_rank(relation_name)
@@ -335,12 +328,12 @@ class Concept::Base < ActiveRecord::Base
335
328
  # If no prefLabel for the requested language exists, a new label will be returned
336
329
  # (if you modify it, don't forget to save it afterwards!)
337
330
  def pref_label
338
- lang = I18n.locale.to_s
331
+ lang = I18n.locale.to_s == "none" ? nil : I18n.locale.to_s
339
332
  @cached_pref_labels ||= pref_labels.each_with_object({}) do |label, hash|
340
333
  if hash[label.language]
341
334
  Rails.logger.warn("Two pref_labels (#{hash[label.language]}, #{label}) for one language (#{label.language}). Taking the second one.")
342
335
  end
343
- hash[label.language.to_s] = label
336
+ hash[label.language] = label
344
337
  end
345
338
  if @cached_pref_labels[lang].nil?
346
339
  # Fallback to the main language
@@ -354,12 +347,16 @@ class Concept::Base < ActiveRecord::Base
354
347
  def labels_for_labeling_class_and_language(labeling_class, lang = :en, only_published = true)
355
348
  # Convert lang to string in case it's not nil.
356
349
  # nil values play their own role for labels without a language.
357
- lang = lang.to_s unless lang.nil?
350
+ if lang == "none"
351
+ lang = nil
352
+ elsif lang
353
+ lang = lang.to_s
354
+ end
358
355
  labeling_class = labeling_class.name if labeling_class < ActiveRecord::Base # Use the class name string
359
356
  @labels ||= labelings.each_with_object({}) do |labeling, hash|
360
357
  ((hash[labeling.class.name.to_s] ||= {})[labeling.target.language] ||= []) << labeling.target if labeling.target
361
358
  end
362
- return ((@labels && @labels[labeling_class] && @labels[labeling_class][lang]) || []).select{|l| l.published? || !only_published}
359
+ ((@labels && @labels[labeling_class] && @labels[labeling_class][lang]) || []).select{|l| l.published? || !only_published}
363
360
  end
364
361
 
365
362
  def related_concepts_for_relation_class(relation_class, only_published = true)
@@ -416,82 +413,4 @@ class Concept::Base < ActiveRecord::Base
416
413
  }
417
414
  end
418
415
 
419
- # ********** Validation methods
420
-
421
- # validates that
422
- # a) no more than one concept with the same origin already exists
423
- # b) if a concept with the same origin exists, its publication state differs
424
- # from the to-be-saved one's
425
- def ensure_distinct_versions
426
- query = Concept::Base.by_origin(origin)
427
- existing_total = query.count
428
- if existing_total >= 2
429
- errors.add :base, I18n.t("txt.models.concept.version_error")
430
- elsif existing_total == 1
431
- unless (query.published.count == 0 and published?) or
432
- (query.published.count == 1 and not published?)
433
- errors.add :base, I18n.t("txt.models.concept.version_error")
434
- end
435
- end
436
- end
437
-
438
- # top term and broader relations are mutually exclusive
439
- def ensure_exclusive_top_term
440
- if @full_validation
441
- if top_term && broader_relations.any?
442
- errors.add :base, I18n.t("txt.models.concept.top_term_exclusive_error")
443
- end
444
- end
445
- end
446
-
447
- # top terms must never be used as descendants (narrower relation targets)
448
- # NB: for top terms themselves, this is covered by `ensure_exclusive_top_term`
449
- def ensure_rooted_top_terms
450
- if @full_validation
451
- if narrower_relations.includes(:target). # XXX: inefficient?
452
- select { |rel| rel.target && rel.target.top_term? }.any?
453
- errors.add :base, I18n.t("txt.models.concept.top_term_rooted_error")
454
- end
455
- end
456
- end
457
-
458
- def ensure_a_pref_label_in_the_primary_thesaurus_language
459
- if @full_validation
460
- labels = pref_labels.select{|l| l.published?}
461
- if labels.count == 0
462
- errors.add :base, I18n.t("txt.models.concept.no_pref_label_error")
463
- elsif not labels.map(&:language).map(&:to_s).include?(Iqvoc::Concept.pref_labeling_languages.first.to_s)
464
- errors.add :base, I18n.t("txt.models.concept.main_pref_label_language_missing_error")
465
- end
466
- end
467
- end
468
-
469
- def ensure_no_pref_labels_share_the_same_language
470
- # We have many sources a prefLabel can be defined in
471
- pls = pref_labelings.map(&:target) +
472
- send(Iqvoc::Concept.pref_labeling_class_name.to_relation_name).map(&:target) +
473
- labelings.select{|l| l.is_a?(Iqvoc::Concept.pref_labeling_class)}.map(&:target)
474
- languages = {}
475
- pls.compact.each do |pref_label|
476
- lang = pref_label.language.to_s
477
- origin = (pref_label.origin || pref_label.id || pref_label.value).to_s
478
- if (languages.keys.include?(lang) && languages[lang] != origin)
479
- errors.add :pref_labelings, I18n.t("txt.models.concept.pref_labels_with_same_languages_error")
480
- end
481
- languages[lang] = origin
482
- end
483
- end
484
-
485
- def ensure_valid_rank_for_ranked_relations
486
- if @full_validation
487
- relations.each do |relation|
488
- if relation.class.rankable? && !(0..100).include?(relation.rank)
489
- errors.add :base, I18n.t("txt.models.concept.invalid_rank_for_ranked_relations",
490
- :relation => relation.class.model_name.human.downcase,
491
- :relation_target_label => relation.target.pref_label.to_s)
492
- end
493
- end
494
- end
495
- end
496
-
497
416
  end
@@ -71,6 +71,10 @@ class Concept::Relation::Base < ActiveRecord::Base
71
71
  self
72
72
  end
73
73
 
74
+ def self.bidirectional?
75
+ !!self.reverse_relation_class
76
+ end
77
+
74
78
  def self.view_section(obj)
75
79
  "relations"
76
80
  end
@@ -18,15 +18,25 @@ class Concept::Relation::SKOS::Base < Concept::Relation::Base
18
18
 
19
19
  self.rdf_namespace = 'skos'
20
20
 
21
- def self.build_from_rdf(subject, predicate, object)
22
- raise "Labeling::SKOS::Base#build_from_rdf: Subject (#{subject}) must be a Concept." unless subject.is_a?(Concept::Base)
23
- raise "Labeling::SKOS::Base#build_from_rdf: Object (#{object}) must be a Concept." unless object.is_a?(Concept::Base)
21
+ def self.build_from_rdf(rdf_subject, rdf_predicate, rdf_object)
22
+ raise "#{self.name}#build_from_rdf: Subject (#{rdf_subject}) must be a Concept." unless rdf_subject.is_a? Concept::Base
23
+ raise "#{self.name}#build_from_rdf: Object (#{rdf_object}) must be a Concept." unless rdf_object.is_a? Concept::Base
24
24
 
25
- if subject.send(self.name.to_relation_name).select{|rel| rel.target_id == object.id || rel.target == object}.empty?
26
- subject.send(self.name.to_relation_name) << self.new(:target => object)
25
+ relation_class = Iqvoc::RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
26
+
27
+ relation_instance = rdf_subject.send(self.name.to_relation_name).select{|rel| rel.target == rdf_object}
28
+ unless relation_instance
29
+ relation_instance = relation_class.new(:target => rdf_object)
30
+ rdf_subject.send(self.name.to_relation_name) << relation_instance
27
31
  end
28
- if self.reverse_relation_class && object.send(self.reverse_relation_class.name.to_relation_name).select{|rel| rel.target_id == subject.id || rel.target == subject}.empty?
29
- object.send(self.reverse_relation_class.name.to_relation_name) << self.reverse_relation_class.new(:target => subject)
32
+
33
+ if relation_class.bidirectional?
34
+ reverse_class = relation_class.reverse_relation_class
35
+ reverse_collection = rdf_object.send(reverse_class.name.to_relation_name)
36
+ if reverse_collection.select{|rel| rel.target == rdf_subject}.empty?
37
+ reverse_instance = reverse_class.new(:target => rdf_subject)
38
+ reverse_collection << reverse_instance
39
+ end
30
40
  end
31
41
  end
32
42
 
@@ -19,7 +19,7 @@ class Concept::SKOS::Base < Concept::Base
19
19
  self.rdf_namespace = "skos"
20
20
  self.rdf_class = "Concept"
21
21
 
22
- def build_rdf_subject(document, controller, &block)
22
+ def build_rdf_subject(&block)
23
23
  ns = IqRdf::Namespace.find_namespace_class(self.rdf_namespace)
24
24
  raise "Namespace '#{self.rdf_namespace}' is not defined in IqRdf document." unless ns
25
25
  subject = IqRdf.build_uri(self.origin, ns.build_uri(self.rdf_class), &block)
@@ -32,4 +32,13 @@ class Concept::SKOS::Base < Concept::Base
32
32
  return subject
33
33
  end
34
34
 
35
+ # ********** Scopes
36
+ def self.expired(time = Time.now)
37
+ where(arel_table[:expired_at].lt(time))
38
+ end
39
+
40
+ def self.not_expired(time = Time.now)
41
+ col = arel_table[:expired_at]
42
+ where((col.eq(nil)).or(col.gteq(time)))
43
+ end
35
44
  end
@@ -37,7 +37,7 @@ class Concept::SKOS::Scheme
37
37
  :scheme
38
38
  end
39
39
 
40
- def build_rdf_subject(document, controller, &block)
40
+ def build_rdf_subject(&block)
41
41
  ns = IqRdf::Namespace.find_namespace_class(self.class.rdf_namespace.to_sym)
42
42
  raise "Namespace '#{rdf_namespace}' is not defined in IqRdf document." unless ns
43
43
  IqRdf.build_uri(origin, ns.build_uri(self.class.rdf_class), &block)
@@ -0,0 +1,117 @@
1
+ module Concept
2
+ module Validations
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ validates :origin, :presence => true, :on => :update
7
+
8
+ validate :distinct_versions, :on => :create
9
+ validate :pref_label_in_primary_thesaurus_language, :on => :update
10
+ validate :unique_pref_label_language
11
+ validate :exclusive_top_term
12
+ validate :rooted_top_terms
13
+ validate :valid_rank_for_ranked_relations
14
+ validate :unique_pref_label
15
+ end
16
+
17
+ def distinct_versions
18
+ query = Concept::Base.by_origin(origin)
19
+ existing_total = query.count
20
+ if existing_total >= 2
21
+ errors.add :base, I18n.t("txt.models.concept.version_error")
22
+ elsif existing_total == 1
23
+ unless (query.published.count == 0 and published?) or
24
+ (query.published.count == 1 and not published?)
25
+ errors.add :base, I18n.t("txt.models.concept.version_error")
26
+ end
27
+ end
28
+ end
29
+
30
+ # top term and broader relations are mutually exclusive
31
+ def exclusive_top_term
32
+ if @full_validation
33
+ if top_term && broader_relations.any?
34
+ errors.add :base, I18n.t("txt.models.concept.top_term_exclusive_error")
35
+ end
36
+ end
37
+ end
38
+
39
+ # top terms must never be used as descendants (narrower relation targets)
40
+ # NB: for top terms themselves, this is covered by `ensure_exclusive_top_term`
41
+ def rooted_top_terms
42
+ if @full_validation
43
+ if narrower_relations.includes(:target). # XXX: inefficient?
44
+ select { |rel| rel.target && rel.target.top_term? }.any?
45
+ errors.add :base, I18n.t("txt.models.concept.top_term_rooted_error")
46
+ end
47
+ end
48
+ end
49
+
50
+ def pref_label_in_primary_thesaurus_language
51
+ if @full_validation
52
+ labels = pref_labels.select{|l| l.published?}
53
+ if labels.count == 0
54
+ errors.add :base, I18n.t("txt.models.concept.no_pref_label_error")
55
+ elsif not labels.map(&:language).map(&:to_s).include?(Iqvoc::Concept.pref_labeling_languages.first.to_s)
56
+ errors.add :base, I18n.t("txt.models.concept.main_pref_label_language_missing_error")
57
+ end
58
+ end
59
+ end
60
+
61
+ def unique_pref_label_language
62
+ # We have many sources a prefLabel can be defined in
63
+ pls = pref_labelings.map(&:target) +
64
+ send(Iqvoc::Concept.pref_labeling_class_name.to_relation_name).map(&:target) +
65
+ labelings.select{|l| l.is_a?(Iqvoc::Concept.pref_labeling_class)}.map(&:target)
66
+ languages = {}
67
+ pls.compact.each do |pref_label|
68
+ lang = pref_label.language.to_s
69
+ origin = (pref_label.origin || pref_label.id || pref_label.value).to_s
70
+ if (languages.keys.include?(lang) && languages[lang] != origin)
71
+ errors.add :pref_labelings, I18n.t("txt.models.concept.pref_labels_with_same_languages_error")
72
+ end
73
+ languages[lang] = origin
74
+ end
75
+ end
76
+
77
+ def unique_pref_label
78
+ if @full_validation
79
+ # checks if there are any existing pref labels with the same
80
+ # language and value
81
+ conflicting_pref_labels = pref_labels.select do |l|
82
+ Labeling::SKOS::PrefLabel.
83
+ joins(:owner, :target).
84
+ where(:labels => { :value => l.value, :language => l.language }).
85
+ where("labelings.owner_id != ?", id).
86
+ where("concepts.origin != ?", origin).
87
+ any?
88
+ end
89
+
90
+ if conflicting_pref_labels.any?
91
+ if conflicting_pref_labels.one?
92
+ errors.add :base,
93
+ I18n.t("txt.models.concept.pref_label_not_unique",
94
+ :label => conflicting_pref_labels.last.value)
95
+ else
96
+ errors.add :base,
97
+ I18n.t("txt.models.concept.pref_labels_not_unique",
98
+ :label => conflicting_pref_labels.map(&:value).join(", "))
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def valid_rank_for_ranked_relations
105
+ if @full_validation
106
+ relations.each do |relation|
107
+ if relation.class.rankable? && !(0..100).include?(relation.rank)
108
+ errors.add :base, I18n.t("txt.models.concept.invalid_rank_for_ranked_relations",
109
+ :relation => relation.class.model_name.human.downcase,
110
+ :relation_target_label => relation.target.pref_label.to_s)
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ end
117
+ end
@@ -33,7 +33,8 @@ class Label::Base < ActiveRecord::Base
33
33
  # ********* Scopes
34
34
 
35
35
  def self.by_language(lang_code)
36
- if (lang_code.is_a?(Array) && lang_code.include?(nil))
36
+ lang_code = nil if lang_code.to_s == "none"
37
+ if (lang_code.is_a?(Array) && lang_code.include?("none"))
37
38
  where(arel_table[:language].eq(nil).or(arel_table[:language].in(lang_code.compact)))
38
39
  elsif lang_code.blank?
39
40
  where(arel_table[:language].eq(nil))
@@ -93,8 +94,8 @@ class Label::Base < ActiveRecord::Base
93
94
  end
94
95
 
95
96
  def to_s
96
- if language.to_s != I18n.locale.to_s.strip
97
- value.to_s + " [#{I18n.t("txt.common.translation_missing_for")} '#{I18n.locale.to_s.strip}']"
97
+ if (language.presence || "none") != I18n.locale.to_s
98
+ value.to_s + " [#{I18n.t("txt.common.translation_missing_for")} '#{I18n.locale}']"
98
99
  else
99
100
  value.to_s
100
101
  end
@@ -28,6 +28,14 @@ class Labeling::SKOS::Base < Labeling::Base
28
28
  includes(:target).merge(self.label_class.where(:value => label, :language => language))
29
29
  end
30
30
 
31
+ def self.concept_expired
32
+ includes(:owner).merge(Iqvoc::Concept.base_class.expired)
33
+ end
34
+
35
+ def self.concept_not_expired
36
+ includes(:owner).merge(Iqvoc::Concept.base_class.not_expired)
37
+ end
38
+
31
39
  # ********** Methods
32
40
 
33
41
  def self.label_class
@@ -35,11 +43,11 @@ class Labeling::SKOS::Base < Labeling::Base
35
43
  end
36
44
 
37
45
  def self.partial_name(obj)
38
- "partials/labeling/skos/base"
46
+ 'partials/labeling/skos/base'
39
47
  end
40
48
 
41
49
  def self.edit_partial_name(obj)
42
- "partials/labeling/skos/edit_base"
50
+ 'partials/labeling/skos/edit_base'
43
51
  end
44
52
 
45
53
  def self.single_query(params = {})
@@ -54,10 +62,10 @@ class Labeling::SKOS::Base < Labeling::Base
54
62
  end
55
63
 
56
64
  if params[:collection_origin].present?
57
- collection = Collection::Unordered.where(:origin => params[:collection_origin]).last
65
+ collection = Collection::Base.where(:origin => params[:collection_origin]).last
58
66
  if collection
59
67
  scope = scope.includes(:owner => :collection_members)
60
- scope = scope.where("#{Collection::Member::Base.table_name}.collection_id" => collection)
68
+ scope = scope.where("#{Collection::Member::Base.table_name}.collection_id" => collection.id)
61
69
  else
62
70
  raise "Collection with Origin #{params[:collection_origin]} not found!"
63
71
  end
@@ -65,10 +73,10 @@ class Labeling::SKOS::Base < Labeling::Base
65
73
  scope = scope.includes(:owner)
66
74
 
67
75
  scope = case params[:for]
68
- when "concept"
69
- scope.where("concepts.type" => Iqvoc::Concept.base_class_name).merge(Concept::Base.published)
70
- when "collection"
71
- scope.where("concepts.type" => Iqvoc::Collection.base_class_name)
76
+ when 'concept'
77
+ scope.where('concepts.type' => Iqvoc::Concept.base_class_name).merge(Concept::Base.published)
78
+ when 'collection'
79
+ scope.where('concepts.type' => Iqvoc::Collection.base_class_name)
72
80
  else
73
81
  # no additional conditions
74
82
  scope
@@ -81,18 +89,21 @@ class Labeling::SKOS::Base < Labeling::Base
81
89
  'partials/labeling/skos/search_result'
82
90
  end
83
91
 
84
- def self.build_from_rdf(subject, predicate, object)
85
- raise "Labeling::SKOS::Base#build_from_rdf: Subject (#{subject}) must be a Concept." unless subject.is_a?(Concept::Base)
86
- raise "Labeling::SKOS::Base#build_from_rdf: Object (#{object}) must be a string literal" unless object =~ /^"(.+)"(@(.+))?$/
92
+ def self.build_from_rdf(rdf_subject, rdf_predicate, rdf_object)
93
+ raise "#{self.name}#build_from_rdf: Subject (#{rdf_subject}) must be a Concept." unless rdf_subject.is_a?(Concept::Base)
94
+ raise "#{self.name}#build_from_rdf: Object (#{rdf_object}) must be a string literal" unless rdf_object =~ /^"(.+)"(@(.+))?$/
87
95
 
88
96
  lang = $3
89
97
  value = JSON.parse(%Q{["#{$1}"]})[0].gsub("\\n", "\n") # Trick to decode \uHHHHH chars
90
98
 
91
- subject.send(self.name.to_relation_name) << self.new(:target => self.label_class.new(:value => value, :language => lang))
99
+ predicate_class = Iqvoc::RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
100
+ predicate_class.new(:target => self.label_class.new(:value => value, :language => lang)).tap do |labeling|
101
+ rdf_subject.send(predicate_class.name.to_relation_name) << labeling
102
+ end
92
103
  end
93
104
 
94
105
  def build_rdf(document, subject)
95
- subject.send(self.rdf_namespace.camelcase).send(self.rdf_predicate, target.to_s, :lang => target.language)
106
+ subject.send(self.rdf_namespace.camelcase).send(self.rdf_predicate, target.value.to_s, :lang => target.language)
96
107
  end
97
108
 
98
109
  def build_search_result_rdf(document, result)
@@ -1,13 +1,32 @@
1
+ # encoding: UTF-8
2
+
3
+ # Copyright 2011 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
+
1
17
  class Match::SKOS::Base < Match::Base
2
18
 
3
19
  self.rdf_namespace = 'skos'
4
20
 
5
- def self.build_from_rdf(subject, predicate, object)
6
- raise "Note::SKOS::Base#build_from_rdf: Subject (#{subject}) must be able to recieve this kind of notes (#{self.name} => #{self.name.to_relation_name})." unless subject.class.reflections.include?(self.name.to_relation_name)
7
- raise "Note::SKOS::Base#build_from_rdf: Object (#{object}) must be a URI" unless object =~ /^<(.+)>$/
21
+ def self.build_from_rdf(rdf_subject, rdf_predicate, rdf_object)
22
+ raise "#{self.class}#build_from_rdf: Subject (#{rdf_subject}) must be able to recieve this kind of match (#{self.name} => #{self.name.to_relation_name})." unless rdf_subject.class.reflections.include?(self.name.to_relation_name)
23
+ raise "#{self.class}#build_from_rdf: Object (#{rdf_object}) must be a URI" unless rdf_object =~ /^<(.+)>$/ # XXX: this assumes nt-format, right?
8
24
  uri = $1
9
25
 
10
- subject.send(self.name.to_relation_name) << self.new(:value => uri)
26
+ match_class = Iqvoc::RDFAPI::PREDICATE_DICTIONARY[rdf_predicate] || self
27
+ match_class.new(:value => uri).tap do |match|
28
+ rdf_subject.send(self.name.to_relation_name) << match
29
+ end
11
30
  end
12
31
 
13
32
  def build_rdf(document, subject)
@@ -16,7 +35,7 @@ class Match::SKOS::Base < Match::Base
16
35
  if (IqRdf::Namespace.find_namespace_class(self.rdf_namespace.camelcase))
17
36
  subject.send(self.rdf_namespace.camelcase).send(self.rdf_predicate, URI.parse(value))
18
37
  else
19
- raise "Match::SKOS::MappingRelation#build_rdf: couldn't find Namespace '#{self.rdf_namespace.camelcase}'."
38
+ raise "#{self.class}#build_rdf: couldn't find Namespace '#{self.rdf_namespace.camelcase}'."
20
39
  end
21
40
  end
22
41