ddr-core 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +12 -0
  3. data/README.md +27 -0
  4. data/Rakefile +30 -0
  5. data/app/assets/config/ddr_core_manifest.js +0 -0
  6. data/app/controllers/users/omniauth_callbacks_controller.rb +11 -0
  7. data/app/controllers/users/sessions_controller.rb +15 -0
  8. data/app/models/concerns/ddr/captionable.rb +25 -0
  9. data/app/models/concerns/ddr/describable.rb +108 -0
  10. data/app/models/concerns/ddr/governable.rb +25 -0
  11. data/app/models/concerns/ddr/has_admin_metadata.rb +141 -0
  12. data/app/models/concerns/ddr/has_attachments.rb +10 -0
  13. data/app/models/concerns/ddr/has_children.rb +10 -0
  14. data/app/models/concerns/ddr/has_content.rb +132 -0
  15. data/app/models/concerns/ddr/has_extracted_text.rb +10 -0
  16. data/app/models/concerns/ddr/has_intermediate_file.rb +25 -0
  17. data/app/models/concerns/ddr/has_multires_image.rb +14 -0
  18. data/app/models/concerns/ddr/has_parent.rb +18 -0
  19. data/app/models/concerns/ddr/has_struct_metadata.rb +21 -0
  20. data/app/models/concerns/ddr/has_thumbnail.rb +33 -0
  21. data/app/models/concerns/ddr/solr_document_behavior.rb +429 -0
  22. data/app/models/concerns/ddr/streamable.rb +25 -0
  23. data/app/models/ddr/admin_set.rb +28 -0
  24. data/app/models/ddr/attachment.rb +14 -0
  25. data/app/models/ddr/collection.rb +28 -0
  26. data/app/models/ddr/component.rb +31 -0
  27. data/app/models/ddr/contact.rb +23 -0
  28. data/app/models/ddr/digest.rb +8 -0
  29. data/app/models/ddr/file.rb +40 -0
  30. data/app/models/ddr/item.rb +36 -0
  31. data/app/models/ddr/language.rb +31 -0
  32. data/app/models/ddr/media_type.rb +22 -0
  33. data/app/models/ddr/resource.rb +94 -0
  34. data/app/models/ddr/rights_statement.rb +25 -0
  35. data/app/models/ddr/target.rb +17 -0
  36. data/config/initializers/devise.rb +262 -0
  37. data/config/locales/ddr-core.en.yml +85 -0
  38. data/config/routes.rb +3 -0
  39. data/db/migrate/20141104181418_create_users.rb +34 -0
  40. data/db/migrate/20141107124012_add_columns_to_user.rb +46 -0
  41. data/lib/ddr-core.rb +1 -0
  42. data/lib/ddr/auth.rb +80 -0
  43. data/lib/ddr/auth/ability.rb +18 -0
  44. data/lib/ddr/auth/ability_definitions.rb +26 -0
  45. data/lib/ddr/auth/ability_definitions/admin_set_ability_definitions.rb +9 -0
  46. data/lib/ddr/auth/ability_definitions/alias_ability_definitions.rb +23 -0
  47. data/lib/ddr/auth/ability_definitions/attachment_ability_definitions.rb +13 -0
  48. data/lib/ddr/auth/ability_definitions/collection_ability_definitions.rb +28 -0
  49. data/lib/ddr/auth/ability_definitions/component_ability_definitions.rb +13 -0
  50. data/lib/ddr/auth/ability_definitions/item_ability_definitions.rb +13 -0
  51. data/lib/ddr/auth/ability_definitions/lock_ability_definitions.rb +13 -0
  52. data/lib/ddr/auth/ability_definitions/publication_ability_definitions.rb +16 -0
  53. data/lib/ddr/auth/ability_definitions/role_based_ability_definitions.rb +39 -0
  54. data/lib/ddr/auth/ability_definitions/superuser_ability_definitions.rb +9 -0
  55. data/lib/ddr/auth/ability_factory.rb +10 -0
  56. data/lib/ddr/auth/abstract_ability.rb +48 -0
  57. data/lib/ddr/auth/affiliation.rb +14 -0
  58. data/lib/ddr/auth/affiliation_groups.rb +20 -0
  59. data/lib/ddr/auth/anonymous_ability.rb +7 -0
  60. data/lib/ddr/auth/auth_context.rb +109 -0
  61. data/lib/ddr/auth/auth_context_factory.rb +13 -0
  62. data/lib/ddr/auth/detached_auth_context.rb +19 -0
  63. data/lib/ddr/auth/dynamic_groups.rb +13 -0
  64. data/lib/ddr/auth/effective_permissions.rb +12 -0
  65. data/lib/ddr/auth/effective_roles.rb +9 -0
  66. data/lib/ddr/auth/failure_app.rb +16 -0
  67. data/lib/ddr/auth/group.rb +40 -0
  68. data/lib/ddr/auth/grouper_gateway.rb +70 -0
  69. data/lib/ddr/auth/groups.rb +32 -0
  70. data/lib/ddr/auth/ldap_gateway.rb +74 -0
  71. data/lib/ddr/auth/permissions.rb +18 -0
  72. data/lib/ddr/auth/remote_groups.rb +14 -0
  73. data/lib/ddr/auth/role_based_access_controls_enforcement.rb +56 -0
  74. data/lib/ddr/auth/roles.rb +28 -0
  75. data/lib/ddr/auth/roles/role.rb +121 -0
  76. data/lib/ddr/auth/roles/role_type.rb +23 -0
  77. data/lib/ddr/auth/roles/role_types.rb +52 -0
  78. data/lib/ddr/auth/superuser_ability.rb +7 -0
  79. data/lib/ddr/auth/test_helpers.rb +22 -0
  80. data/lib/ddr/auth/user.rb +54 -0
  81. data/lib/ddr/auth/web_auth_context.rb +29 -0
  82. data/lib/ddr/core.rb +110 -0
  83. data/lib/ddr/core/engine.rb +8 -0
  84. data/lib/ddr/core/version.rb +5 -0
  85. data/lib/ddr/error.rb +16 -0
  86. data/lib/ddr/files.rb +13 -0
  87. data/lib/ddr/fits.rb +189 -0
  88. data/lib/ddr/index.rb +29 -0
  89. data/lib/ddr/index/abstract_query_result.rb +22 -0
  90. data/lib/ddr/index/connection.rb +38 -0
  91. data/lib/ddr/index/csv_query_result.rb +84 -0
  92. data/lib/ddr/index/document_builder.rb +9 -0
  93. data/lib/ddr/index/field.rb +35 -0
  94. data/lib/ddr/index/field_attribute.rb +22 -0
  95. data/lib/ddr/index/fields.rb +154 -0
  96. data/lib/ddr/index/filter.rb +139 -0
  97. data/lib/ddr/index/query.rb +82 -0
  98. data/lib/ddr/index/query_builder.rb +185 -0
  99. data/lib/ddr/index/query_clause.rb +112 -0
  100. data/lib/ddr/index/query_params.rb +40 -0
  101. data/lib/ddr/index/query_result.rb +102 -0
  102. data/lib/ddr/index/response.rb +30 -0
  103. data/lib/ddr/index/sort_order.rb +28 -0
  104. data/lib/ddr/index/unique_key_field.rb +12 -0
  105. data/lib/ddr/managers.rb +9 -0
  106. data/lib/ddr/managers/manager.rb +13 -0
  107. data/lib/ddr/managers/technical_metadata_manager.rb +141 -0
  108. data/lib/ddr/structure.rb +188 -0
  109. data/lib/ddr/structures/agent.rb +49 -0
  110. data/lib/ddr/structures/component_type_term.rb +29 -0
  111. data/lib/ddr/structures/div.rb +64 -0
  112. data/lib/ddr/structures/f_locat.rb +54 -0
  113. data/lib/ddr/structures/file.rb +52 -0
  114. data/lib/ddr/structures/file_grp.rb +35 -0
  115. data/lib/ddr/structures/file_sec.rb +22 -0
  116. data/lib/ddr/structures/fptr.rb +31 -0
  117. data/lib/ddr/structures/mets_hdr.rb +37 -0
  118. data/lib/ddr/structures/mptr.rb +49 -0
  119. data/lib/ddr/structures/struct_map.rb +40 -0
  120. data/lib/ddr/utils.rb +185 -0
  121. data/lib/ddr/vocab.rb +22 -0
  122. data/lib/ddr/vocab/asset.rb +51 -0
  123. data/lib/ddr/vocab/contact.rb +9 -0
  124. data/lib/ddr/vocab/display.rb +9 -0
  125. data/lib/ddr/vocab/duke_terms.rb +13 -0
  126. data/lib/ddr/vocab/rdf_vocabulary_parser.rb +43 -0
  127. data/lib/ddr/vocab/roles.rb +25 -0
  128. data/lib/ddr/vocab/sources/duketerms.rdf +870 -0
  129. data/lib/ddr/vocab/vocabulary.rb +37 -0
  130. data/lib/ddr/workflow.rb +8 -0
  131. data/lib/tasks/ddr/core_tasks.rake +4 -0
  132. metadata +428 -0
@@ -0,0 +1,10 @@
1
+ module Ddr
2
+ module HasExtractedText
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :extracted_text, Ddr::File.optional
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ module Ddr
2
+ module HasIntermediateFile
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :intermediate_file, Ddr::File.optional
7
+ end
8
+
9
+ def intermediate_type
10
+ intermediate_file&.media_type
11
+ end
12
+
13
+ # This method is used in dul-hydra 'ComponentsController'
14
+ def intermediate_extension
15
+ if filename = intermediate_file&.original_filename
16
+ ::File.extname(filename)
17
+ end
18
+ end
19
+
20
+ def intermediate_path
21
+ intermediate_file&.file&.disk_path
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ module Ddr
2
+ module HasMultiresImage
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :multires_image, Ddr::File.optional
7
+ end
8
+
9
+ def multires_image_file_path
10
+ multires_image&.file&.disk_path
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Ddr
2
+ module HasParent
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :parent_id, Valkyrie::Types::ID.optional
7
+ end
8
+
9
+ def parent
10
+ Ddr.query_service.find_by(id: parent_id) if parent_id
11
+ end
12
+
13
+ def publishable?
14
+ parent&.published? || false
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module Ddr
2
+ module HasStructMetadata
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :struct_metadata, Ddr::File.optional
7
+ end
8
+
9
+ def structure
10
+ if has_struct_metadata?
11
+ file = Ddr.storage_adapter.find_by(id: struct_metadata.file_identifier)
12
+ Ddr::Structure.new(Nokogiri::XML(file))
13
+ end
14
+ end
15
+
16
+ #def multires_image_file_paths
17
+ # ::SolrDocument.find(pid).multires_image_file_paths
18
+ #end
19
+
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ module Ddr
2
+ module HasThumbnail
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :thumbnail, Ddr::File.optional
7
+ end
8
+
9
+ def thumbnail_path
10
+ thumbnail&.file&.disk_path
11
+ end
12
+
13
+ # ******DDRevo******
14
+ # This method is used only in the '#copy_thumbnail_from' method defined below.
15
+ # ******DDRevo******
16
+ # def thumbnail_changed?
17
+ # thumbnail.content_changed?
18
+ # end
19
+ #
20
+ # ******DDRevo******
21
+ # This method is used in a dul-hydra rake task ('thumbnail:copy') and will be accounted for in the dul-hydra
22
+ # refactor.
23
+ # ******DDRevo******
24
+ # def copy_thumbnail_from(other)
25
+ # if other && other.has_thumbnail?
26
+ # self.thumbnail.content = other.thumbnail.content
27
+ # self.thumbnail.mimeType = other.thumbnail.mimeType if thumbnail_changed?
28
+ # end
29
+ # thumbnail_changed?
30
+ # end
31
+
32
+ end
33
+ end
@@ -0,0 +1,429 @@
1
+ require 'json'
2
+ require 'solrizer'
3
+
4
+ module Ddr
5
+ module SolrDocumentBehavior
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ alias_method :pid, :id
10
+ end
11
+
12
+ class NotFound < Error; end
13
+
14
+ module ClassMethods
15
+ def find(id)
16
+ query = Ddr::Index::Query.new { id id }
17
+ if doc = query.docs.first
18
+ return doc
19
+ end
20
+ raise NotFound, "SolrDocument not found for \"#{id}\"."
21
+ end
22
+
23
+ def find_by_permanent_id(ark)
24
+ query = Ddr::Index::Query.new do
25
+ q *:*
26
+ where permanent_id: ark
27
+ end
28
+ if doc = query.docs.first
29
+ return doc
30
+ end
31
+ raise NotFound, "SolrDocument not found for permanent id \"#{ark}\"."
32
+ end
33
+ end
34
+
35
+ def inspect
36
+ "#<#{self.class.name} id=#{id.inspect}>"
37
+ end
38
+
39
+ def method_missing(name, *args, &block)
40
+ if args.empty? && !block
41
+ begin
42
+ field = Ddr::Index::Fields.get(name)
43
+ rescue NameError
44
+ # pass
45
+ else
46
+ # Preserves the default behavior of the deprecated method
47
+ # Blacklight::Solr::Document#get, which this procedure
48
+ # effectively replaces.
49
+ val = self[field]
50
+ return val.is_a?(Array) ? val.join(", ") : val
51
+ end
52
+ end
53
+ super
54
+ end
55
+
56
+ def resource
57
+ @resource = Valkyrie::MetadataAdapter.find(:index_solr).query_service.find_by(id: id)
58
+ end
59
+
60
+ ### DDRevo: Not sure if / where this is used
61
+ def to_partial_path
62
+ 'document'
63
+ end
64
+
65
+ ### DDRevo: This is probably no longer needed
66
+ def safe_id
67
+ id.sub(/:/, "-")
68
+ end
69
+
70
+ ### DDRevo: No longer relevant
71
+ # def object_profile
72
+ # @object_profile ||= get_json(Ddr::Index::Fields::OBJECT_PROFILE)
73
+ # end
74
+
75
+ ### DDRevo: No longer relevant
76
+ # def object_state
77
+ # object_profile["objState"]
78
+ # end
79
+
80
+ def object_create_date
81
+ parse_date(self[Ddr::Index::Fields::RESOURCE_CREATE_DATE])
82
+ end
83
+
84
+ def object_modified_date
85
+ parse_date(self[Ddr::Index::Fields::RESOURCE_MODIFIED_DATE])
86
+ end
87
+
88
+ def last_fixity_check_on
89
+ get_date(Ddr::Index::Fields::LAST_FIXITY_CHECK_ON)
90
+ end
91
+
92
+ def last_virus_check_on
93
+ get_date(Ddr::Index::Fields::LAST_VIRUS_CHECK_ON)
94
+ end
95
+
96
+ ### DDRevo: No longer relevant
97
+ # def datastreams
98
+ # object_profile["datastreams"]
99
+ # end
100
+
101
+ ### DDRevo: No longer relevant
102
+ # def has_datastream?(dsID)
103
+ # datastreams[dsID].present?
104
+ # end
105
+
106
+ def has_admin_policy?
107
+ admin_policy_id.present?
108
+ end
109
+
110
+ def admin_policy
111
+ if has_admin_policy?
112
+ self.class.find(admin_policy_id)
113
+ end
114
+ end
115
+
116
+ def has_children?
117
+ resource.children.present?
118
+ end
119
+
120
+ ### DDRevo: No longer relevant
121
+ # def label
122
+ # object_profile["objLabel"]
123
+ # end
124
+
125
+ def title_display
126
+ title
127
+ end
128
+
129
+ def identifier
130
+ # We want the multivalued version here
131
+ self[Solrizer.solr_name(:identifier, :stored_searchable, type: :text)]
132
+ end
133
+
134
+ def source
135
+ self[Solrizer.solr_name(:source, :stored_searchable, type: :text)]
136
+ end
137
+
138
+ def has_thumbnail?
139
+ resource.has_thumbnail?
140
+ end
141
+
142
+ def has_content?
143
+ resource.has_content?
144
+ end
145
+
146
+ def has_intermediate_file?
147
+ resource.has_intermediate_file?
148
+ end
149
+
150
+ def has_extracted_text?
151
+ resource.has_extracted_text?
152
+ end
153
+
154
+ ### DDRevo: Not relevant as coded. Not sure if comparable functionality is needed
155
+ # def content_ds
156
+ # datastreams[Ddr::Datastreams::CONTENT]
157
+ # end
158
+
159
+ def content_mime_type
160
+ resource.content_type
161
+ end
162
+ # For duck-typing with Ddr::HasContent
163
+ alias_method :content_type, :content_mime_type
164
+
165
+ def content_human_size
166
+ resource.content_human_size
167
+ end
168
+
169
+ ### DDRevo: Not relevant as coded. Not sure if comparable functionality is needed
170
+ # def content_checksum
171
+ # content_ds["dsChecksum"] rescue nil
172
+ # end
173
+
174
+ def targets
175
+ @targets ||= query_service.find_inverse_references_by(resource: resource, property: 'for_collection_id')
176
+ end
177
+
178
+ def targets_count
179
+ @targets_count = targets.count
180
+ end
181
+
182
+ def has_target?
183
+ targets_count > 0
184
+ end
185
+
186
+ ### DDRevo Still relevant?
187
+ # def association(name)
188
+ # get_pid(ActiveFedora::SolrService.solr_name(name, :symbol))
189
+ # end
190
+
191
+ def controller_name
192
+ resource_model.tableize
193
+ end
194
+
195
+ def rights_statement
196
+ @rights_statement ||= RightsStatement.call(self)
197
+ end
198
+
199
+ def roles
200
+ # @roles ||= Ddr::Auth::Roles::Role.from_json(access_role)
201
+ @roles ||= resource.roles
202
+ end
203
+
204
+ def resource_roles
205
+ resource.resource_roles
206
+ end
207
+
208
+ def inherited_roles
209
+ resource.inherited_roles
210
+ end
211
+
212
+ def structure
213
+ JSON.parse(fetch(Ddr::Index::Fields::STRUCTURE))
214
+ rescue
215
+ nil
216
+ end
217
+
218
+ def effective_permissions(agents)
219
+ Ddr::Auth::EffectivePermissions.call(self, agents)
220
+ end
221
+
222
+ def research_help
223
+ research_help_contact = self[Ddr::Index::Fields::RESEARCH_HELP_CONTACT] || inherited_research_help_contact
224
+ Ddr::Contact.call(research_help_contact) if research_help_contact
225
+ end
226
+
227
+ def parent_id
228
+ is_part_of || is_member_of_collection
229
+ end
230
+
231
+ def has_parent?
232
+ parent_id.present?
233
+ end
234
+
235
+ def parent
236
+ if has_parent?
237
+ self.class.find(parent_id)
238
+ end
239
+ end
240
+
241
+ def multires_image_file_paths
242
+ if structure
243
+ structure_docs.map { |doc| doc.multires_image_file_path }.compact
244
+ else
245
+ []
246
+ end
247
+ end
248
+
249
+ # DRY HasAdminMetadata
250
+ def finding_aid
251
+ if ead_id
252
+ FindingAid.new(ead_id)
253
+ end
254
+ end
255
+
256
+ def intermediate_type
257
+ if has_intermediate_file?
258
+ resource.intermediate_type
259
+ end
260
+ end
261
+
262
+ def intermediate_path
263
+ if has_intermediate_file?
264
+ resource.intermediate_path
265
+ end
266
+ end
267
+
268
+ def intermediate_extension
269
+ if has_intermediate_file?
270
+ extensions = Ddr.preferred_file_extensions
271
+ if extensions.include? intermediate_type
272
+ extensions[intermediate_type]
273
+ else
274
+ intermediate_extension_default
275
+ end
276
+ end
277
+ end
278
+
279
+ def captionable?
280
+ resource.captionable?
281
+ end
282
+
283
+ def caption_type
284
+ if captionable?
285
+ resource.caption_type
286
+ end
287
+ end
288
+
289
+ def caption_extension
290
+ if captionable?
291
+ extensions = Ddr.preferred_file_extensions
292
+ if extensions.include? caption_type
293
+ extensions[caption_type]
294
+ else
295
+ caption_extension_default
296
+ end
297
+ end
298
+ end
299
+
300
+ def caption_path
301
+ if captionable?
302
+ resource.caption_path
303
+ end
304
+ end
305
+
306
+ def streamable?
307
+ resource.streamable?
308
+ end
309
+
310
+ def streamable_media_extension
311
+ if streamable?
312
+ extensions = Ddr.preferred_file_extensions
313
+ if extensions.include? streamable_media_type
314
+ extensions[streamable_media_type]
315
+ else
316
+ streamable_media_extension_default
317
+ end
318
+ end
319
+ end
320
+
321
+ def streamable_media_type
322
+ if streamable?
323
+ resource.streamable_media_type
324
+ end
325
+ end
326
+
327
+ def streamable_media_path
328
+ if streamable?
329
+ resource.streamable_media_path
330
+ end
331
+ end
332
+
333
+ def thumbnail_path
334
+ if has_thumbnail?
335
+ resource.thumbnail_path
336
+ end
337
+ end
338
+
339
+ # FIXME - Probably need a more general solution mapping object reader methods to index field names.
340
+ def rights
341
+ self["rights_tesim"]
342
+ end
343
+
344
+ def children
345
+ resource.children
346
+ end
347
+
348
+ private
349
+
350
+ def query_service
351
+ @query_service ||= Valkyrie::MetadataAdapter.find(:index_solr).query_service
352
+ end
353
+
354
+ # def targets_query
355
+ # "#{Ddr::Index::Fields::IS_EXTERNAL_TARGET_FOR}:#{internal_uri_for_query}"
356
+ # end
357
+ #
358
+ # def internal_uri_for_query
359
+ # ActiveFedora::SolrService.escape_uri_for_query(internal_uri)
360
+ # end
361
+ #
362
+ def get_date(field)
363
+ parse_date(self[field])
364
+ end
365
+
366
+ def get_json(field)
367
+ JSON.parse Array(self[field]).first
368
+ end
369
+
370
+ def parse_date(date)
371
+ Time.parse(date).localtime if date
372
+ end
373
+
374
+ # def get_pid(field)
375
+ # ActiveFedora::Base.pid_from_uri(self[field]) rescue nil
376
+ # end
377
+ #
378
+ def inherited_research_help_contact
379
+ if doc = admin_policy
380
+ doc.research_help_contact
381
+ end
382
+ end
383
+
384
+ def structure_docs
385
+ structure_repo_ids.map { |repo_id| self.class.find(repo_id) }.compact
386
+ end
387
+
388
+ # For simplicity, initial implementation returns repo ID's only from top-level
389
+ # (i.e., not nested) contents. This is done since we have not clarified what
390
+ # an _ordered_ list of repo ID's should look like if structure contains nested
391
+ # contents.
392
+ def structure_repo_ids
393
+ default_struct_map['contents'].map { |content| content['contents'].map { |content| content['repo_id'] } }.flatten
394
+ end
395
+
396
+ def default_struct_map
397
+ structure['default'] || structure.values.first
398
+ end
399
+
400
+ def intermediate_extension_default
401
+ # datastreams[Ddr::Datastreams::INTERMEDIATE_FILE].default_file_extension
402
+ resource.intermediate_file.default_file_extension
403
+ end
404
+
405
+ def caption_extension_default
406
+ # datastreams[Ddr::Datastreams::CAPTION].default_file_extension
407
+ resource.caption.default_file_extension
408
+ end
409
+
410
+ def streamable_media_extension_default
411
+ # datastreams[Ddr::Datastreams::STREAMABLE_MEDIA].default_file_extension
412
+ resource.streamable_media.default_file_extension
413
+ end
414
+
415
+ ### DDRevo: Using resource.children rather than this query
416
+ # def children_query
417
+ # case self[Ddr::Index::Fields::RESOURCE_MODEL]
418
+ # when 'Ddr::Collection'
419
+ # Ddr::Index::Query.build(self) do |parent|
420
+ # is_member_of_collection parent.id
421
+ # end
422
+ # when 'Ddr::Item'
423
+ # Ddr::Index::Query.build(self) do |parent|
424
+ # is_part_of parent.id
425
+ # end
426
+ # end
427
+ # end
428
+ end
429
+ end