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,29 @@
1
+ module Ddr::Structures
2
+ class ComponentTypeTerm
3
+
4
+ CONFIG_FILE = ::File.join(Rails.root, 'config', 'structure_component_type.yml')
5
+
6
+ @@lookup = {}
7
+
8
+ def self.term(media_type)
9
+ hit = lookup_table.detect { |k,v| media_type =~ k }
10
+ hit.last if hit
11
+ end
12
+
13
+ def self.lookup_table
14
+ load_lookup if @@lookup.empty?
15
+ @@lookup
16
+ end
17
+
18
+ def self.load_lookup
19
+ config = YAML::load(::File.read(CONFIG_FILE))
20
+ config.each do |type_term, media_types|
21
+ media_types.each do |media_type|
22
+ lookup_key = Regexp.new("\\A#{media_type.gsub('*', '.*')}\\Z")
23
+ @@lookup[lookup_key] = type_term
24
+ end
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,64 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'div' node
4
+ #
5
+ class Div < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def label
12
+ self['LABEL']
13
+ end
14
+
15
+ def order
16
+ self['ORDER']
17
+ end
18
+
19
+ def orderlabel
20
+ self['ORDERLABEL']
21
+ end
22
+
23
+ def type
24
+ self['TYPE']
25
+ end
26
+
27
+ def divs
28
+ xpath('xmlns:div').map { |node| Div.new(node) }
29
+ end
30
+
31
+ def fptrs
32
+ xpath('xmlns:fptr').map { |node| Fptr.new(node) }
33
+ end
34
+
35
+ def mptrs
36
+ xpath('xmlns:mptr').map { |node| Mptr.new(node) }
37
+ end
38
+
39
+ def <=>(other)
40
+ order.to_i <=> other.order.to_i
41
+ end
42
+
43
+ def dereferenced_hash
44
+ contents = []
45
+ contents.concat(divs.map { |div| div.dereferenced_hash }) unless divs.empty?
46
+ contents.concat(fptrs.map { |fptr| fptr.dereferenced_hash }) unless fptrs.empty?
47
+ contents.concat(mptrs.map { |mptr| mptr.dereferenced_hash }) unless mptrs.empty?
48
+ dh = { id: id, label: label, order: order, orderlabel: orderlabel, type: type }.compact
49
+ dh[:contents] = contents unless contents.empty?
50
+ dh
51
+ end
52
+
53
+ def self.build(args)
54
+ node = Nokogiri::XML::Node.new('div', args[:document])
55
+ node['ID'] = args[:id] if args[:id]
56
+ node['LABEL'] = args[:label] if args[:label]
57
+ node['ORDER'] = args[:order] if args[:order]
58
+ node['ORDERLABEL'] = args[:orderlabel] if args[:orderlabel]
59
+ node['TYPE'] = args[:type] if args[:type]
60
+ node
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,54 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'FLocat' node
4
+ #
5
+ class FLocat < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def loctype
12
+ self['LOCTYPE']
13
+ end
14
+
15
+ def otherloctype
16
+ self['OTHERLOCTYPE']
17
+ end
18
+
19
+ def use
20
+ self['USE']
21
+ end
22
+
23
+ def href
24
+ self['xlink:href']
25
+ end
26
+
27
+ def ark?
28
+ loctype == 'ARK'
29
+ end
30
+
31
+ def ark
32
+ href if ark?
33
+ end
34
+
35
+ def effective_use
36
+ use ? use : File.new(parent).effective_use
37
+ end
38
+
39
+ def repo_id
40
+ SolrDocument.find_by_permanent_id(ark).id if ark?
41
+ end
42
+
43
+ def self.build(args)
44
+ node = Nokogiri::XML::Node.new('FLocat', args[:document])
45
+ node['ID'] = args[:id] if args[:id]
46
+ node['LOCTYPE'] = args[:loctype] if args[:loctype]
47
+ node['OTHERLOCTYPE'] = args[:otherloctype] if args[:otherloctype]
48
+ node['USE'] = args[:use] if args[:use]
49
+ node['xlink:href'] = args[:href] if args[:href]
50
+ node
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,52 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'file' node
4
+ #
5
+ class File < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def use
12
+ self['USE']
13
+ end
14
+
15
+ def files
16
+ xpath('xmlns:file').map { |node| File.new(node) }
17
+ end
18
+
19
+ def flocats
20
+ xpath('xmlns:FLocat').map { |node| FLocat.new(node) }
21
+ end
22
+
23
+ def effective_use
24
+ if use
25
+ use
26
+ else
27
+ case parent.name
28
+ when "file"
29
+ File.new(parent).effective_use
30
+ when "fileGrp"
31
+ FileGrp.new(parent).effective_use
32
+ end
33
+ end
34
+ end
35
+
36
+ def repo_ids
37
+ flocats.map(&:repo_id)
38
+ end
39
+
40
+ def self.build(args)
41
+ node = Nokogiri::XML::Node.new('file', args[:document])
42
+ node['ID'] = args[:id] if args[:id]
43
+ node['USE'] = args[:use] if args[:use]
44
+ node
45
+ end
46
+
47
+ def self.find(structure, fileid)
48
+ structure.files[fileid]
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,35 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'fileGrp' node
4
+ #
5
+ class FileGrp < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def use
12
+ self['USE']
13
+ end
14
+
15
+ def filegrps
16
+ xpath('xmlns:filegrp').map { |node| FileGrp.new(node) }
17
+ end
18
+
19
+ def files
20
+ xpath('xmlns:file').map { |node| File.new(node) }
21
+ end
22
+
23
+ def effective_use
24
+ use
25
+ end
26
+
27
+ def self.build(args)
28
+ node = Nokogiri::XML::Node.new('fileGrp', args[:document])
29
+ node['ID'] = args[:id] if args[:id]
30
+ node['USE'] = args[:use] if args[:use]
31
+ node
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'fileSec' node
4
+ #
5
+ class FileSec < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def filegrps
12
+ xpath('xmlns:fileGrp').map { |node| FileGrp.new(node) }
13
+ end
14
+
15
+ def self.build(args)
16
+ node = Nokogiri::XML::Node.new('fileSec', args[:document])
17
+ node['ID'] = args[:id] if args[:id]
18
+ node
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'fptr' node
4
+ #
5
+ class Fptr < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def fileid
12
+ self['FILEID']
13
+ end
14
+
15
+ def dereferenced_hash
16
+ structure = Ddr::Structure.new(document)
17
+ file = File.find(structure, fileid)
18
+ repo_id = file.repo_ids.first
19
+ use = file.flocats.first.effective_use
20
+ { id: id, repo_id: repo_id, use: use }.compact
21
+ end
22
+
23
+ def self.build(args)
24
+ node = Nokogiri::XML::Node.new('fptr', args[:document])
25
+ node['ID'] = args[:id] if args[:id]
26
+ node['FILEID'] = args[:fileid] if args[:fileid]
27
+ node
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,37 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'metsHdr' node
4
+ #
5
+ class MetsHdr < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def createdate
12
+ self['CREATEDATE']
13
+ end
14
+
15
+ def lastmoddate
16
+ self['LASTMODDATE']
17
+ end
18
+
19
+ def recordstatus
20
+ self['RECORDSTATUS']
21
+ end
22
+
23
+ def agents
24
+ xpath('xmlns:agent').map { |node| Agent.new(node) }
25
+ end
26
+
27
+ def self.build(args)
28
+ node = Nokogiri::XML::Node.new('metsHdr', args[:document])
29
+ node['ID'] = args[:id] if args[:id]
30
+ node['CREATEDATE'] = args[:createdate] if args[:createdate]
31
+ node['LASTMODDATE'] = args[:lastmoddate] if args[:lastmoddate]
32
+ node['RECORDSTATUS'] = args[:recordstatus] if args[:recordstatus]
33
+ node
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'mptr' node
4
+ #
5
+ class Mptr < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def loctype
12
+ self['LOCTYPE']
13
+ end
14
+
15
+ def otherloctype
16
+ self['OTHERLOCTYPE']
17
+ end
18
+
19
+ def href
20
+ self['xlink:href']
21
+ end
22
+
23
+ def ark?
24
+ loctype == 'ARK'
25
+ end
26
+
27
+ def ark
28
+ href if ark?
29
+ end
30
+
31
+ def repo_id
32
+ SolrDocument.find_by_permanent_id(ark).id if ark?
33
+ end
34
+
35
+ def dereferenced_hash
36
+ { id: id, repo_id: repo_id }.compact
37
+ end
38
+
39
+ def self.build(args)
40
+ node = Nokogiri::XML::Node.new('mptr', args[:document])
41
+ node['ID'] = args[:id] if args[:id]
42
+ node['LOCTYPE'] = args[:loctype] if args[:loctype]
43
+ node['OTHERLOCTYPE'] = args[:otherloctype] if args[:otherloctype]
44
+ node['xlink:href'] = args[:href] if args[:href]
45
+ node
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,40 @@
1
+ module Ddr::Structures
2
+ #
3
+ # Wraps a Nokogiri (XML) 'structMap' node
4
+ #
5
+ class StructMap < SimpleDelegator
6
+
7
+ def id
8
+ self['ID']
9
+ end
10
+
11
+ def label
12
+ self['LABEL']
13
+ end
14
+
15
+ def type
16
+ self['TYPE']
17
+ end
18
+
19
+ def divs
20
+ xpath('xmlns:div').map { |node| Div.new(node) }
21
+ end
22
+
23
+ def dereferenced_hash
24
+ contents = []
25
+ contents.concat(divs.map { |div| div.dereferenced_hash }) unless divs.empty?
26
+ dh = { id: id, label: label, type: type }.compact
27
+ dh[:contents] = contents unless contents.empty?
28
+ dh
29
+ end
30
+
31
+ def self.build(args)
32
+ node = Nokogiri::XML::Node.new('structMap', args[:document])
33
+ node['ID'] = args[:id] if args[:id]
34
+ node['LABEL'] = args[:label] if args[:label]
35
+ node['TYPE'] = args[:type] if args[:type]
36
+ node
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,185 @@
1
+ require 'openssl'
2
+
3
+ module Ddr::Utils
4
+ extend Deprecation
5
+
6
+ def self.digest content, algorithm
7
+ raise TypeError, "Algorithm must be a string: #{algorithm.inspect}" unless algorithm.is_a?(String)
8
+ digest_class = OpenSSL::Digest.const_get(algorithm.sub("-", "").to_sym)
9
+ digest_class.new(content).to_s
10
+ rescue NameError => e
11
+ raise ArgumentError, "Invalid algorithm: #{algorithm}"
12
+ end
13
+
14
+ def self.file_or_path?(file)
15
+ file_path(file)
16
+ rescue ArgumentError
17
+ false
18
+ end
19
+
20
+ def self.file_path?(file)
21
+ # length is a sanity check
22
+ file.is_a?(String) && (file.length < 1024) && File.exist?(file)
23
+ end
24
+
25
+ def self.file_path(file)
26
+ if file.respond_to?(:path)
27
+ ::File.absolute_path(file.path)
28
+ elsif file_path?(file)
29
+ file
30
+ else
31
+ raise ArgumentError, "Argument is neither a File nor a path to an existing file."
32
+ end
33
+ end
34
+
35
+ def self.file_name_for(file)
36
+ if file.respond_to?(:original_filename) && file.original_filename.present?
37
+ file.original_filename
38
+ else
39
+ File.basename file_path(file)
40
+ end
41
+ end
42
+
43
+ def self.file_uri?(uri)
44
+ return false unless uri
45
+ URI.parse(uri).scheme == "file"
46
+ end
47
+
48
+ def self.sanitize_filename(file_name)
49
+ return unless file_name
50
+ raise ArgumentError, "file_name argument must be a string" unless file_name.is_a?(String)
51
+ raise ArgumentError, "file_name argument must not include path" if file_name.include?(File::SEPARATOR)
52
+ file_name.gsub(/[^\w\.\-]/,"_")
53
+ end
54
+
55
+ # Return file path for URI string
56
+ # Should reverse .path_to_uri
57
+ # "file:/path/to/file" => "/path/to/file"
58
+ # @param uri [String] The URI string to pathify
59
+ # @return [String] the file path
60
+ def self.path_from_uri(uri_string)
61
+ uri = URI.parse(uri_string)
62
+ unless uri.scheme == "file"
63
+ raise ArgumentError, "URI does not have the file: scheme."
64
+ end
65
+ URI.unescape(uri.path)
66
+ end
67
+
68
+ # Return URI string for file path
69
+ # Should reverse .path_from_uri
70
+ # "/path/to/file" => "file:/path/to/file"
71
+ # @param path [String] the file path
72
+ # @return [String] the file: URI string
73
+ def self.path_to_uri(path)
74
+ uri = URI.parse URI.escape(path)
75
+ uri.scheme = "file"
76
+ uri.to_s
77
+ end
78
+
79
+ def self.ds_as_of_date_time(ds)
80
+ ds.create_date_string
81
+ end
82
+
83
+ ### DDRevo ################################
84
+ # Needs replacements for ActiveFedora::Base.find_each call.
85
+ ### DDRevo ################################
86
+ # # # Find an object with a given identifier and return its PID.
87
+ # # Returns the PID if a single object is found.
88
+ # # Returns nil if no object is found.
89
+ # # Raises Ddr::Models::Error if more than one object is found.
90
+ # # Options can be provided to limit the scope of matching objects
91
+ # # model: Will only consider objects of that model
92
+ # # collection: Will only consider objects that either are that collection or which are
93
+ # # direct children of that collection (i.e., effectively searches a collection and its
94
+ # # items for an object with the given identifier)
95
+ # def self.pid_for_identifier(identifier, opts={})
96
+ # model = opts.fetch(:model, nil)
97
+ # collection = opts.fetch(:collection, nil)
98
+ # objs = []
99
+ # ActiveFedora::Base.find_each( { Ddr::Index::Fields::IDENTIFIER_ALL => identifier }, { :cast => true } ) { |o| objs << o }
100
+ # pids = []
101
+ # objs.each { |obj| pids << obj.pid }
102
+ # if model.present?
103
+ # objs.each { |obj| pids.delete(obj.pid) unless obj.is_a?(model.constantize) }
104
+ # end
105
+ # if collection.present?
106
+ # objs.each do |obj|
107
+ # pids.delete(obj.pid) unless obj == collection || obj.parent == collection
108
+ # end
109
+ # end
110
+ # case pids.size
111
+ # when 0
112
+ # nil
113
+ # when 1
114
+ # pids.first
115
+ # else
116
+ # raise Ddr::Models::Error, I18n.t('ddr.errors.multiple_object_matches', :criteria => "identifier #{identifier}")
117
+ # end
118
+ # end
119
+
120
+ ### DDRevo ################################
121
+ # This probably isn't relevant in DDRevo context.
122
+ ### DDRevo ################################
123
+ # # Returns the reflection object for a given model name and relationship name
124
+ # # E.g., relationship_object_reflection("Item", "parent") returns the reflection object for
125
+ # # an Item's parent relationship. This reflection object can then be used to obtain the
126
+ # # class of the relationship object using the reflection_object_class(reflection) method below.
127
+ # def self.relationship_object_reflection(model, relationship_name)
128
+ # reflection = nil
129
+ # if model
130
+ # begin
131
+ # reflections = model.constantize.reflections
132
+ # rescue NameError
133
+ # # nothing to do here except that we can't return the appropriate reflection
134
+ # else
135
+ # reflections.each do |reflect|
136
+ # if reflect[0].eql?(relationship_name.to_sym)
137
+ # reflection = reflect
138
+ # end
139
+ # end
140
+ # end
141
+ # end
142
+ # return reflection
143
+ # end
144
+
145
+ ### DDRevo ################################
146
+ # This probably isn't relevant in DDRevo context.
147
+ ### DDRevo ################################
148
+ # # Returns the class associated with the :class_name attribute in the options of a reflection
149
+ # # E.g., reflection_object_class(relationship_object_reflection("Item", "parent")) returns the
150
+ # # Collection class.
151
+ # def self.reflection_object_class(reflection)
152
+ # reflection_object_model = nil
153
+ # klass = nil
154
+ # if reflection[1].options[:class_name]
155
+ # reflection_object_model = reflection[1].options[:class_name]
156
+ # else
157
+ # reflection_object_model = ActiveSupport::Inflector.camelize(reflection[0])
158
+ # end
159
+ # if reflection_object_model
160
+ # begin
161
+ # klass = reflection_object_model.constantize
162
+ # rescue NameError
163
+ # # nothing to do here except that we can't return the reflection object class
164
+ # end
165
+ # end
166
+ # return klass
167
+ # end
168
+
169
+ # Returns a string suitable to index as a Solr date
170
+ # @param dt [Date, DateTime, Time] the date/time
171
+ # @return [String]
172
+ def self.solr_date(dt)
173
+ return if dt.nil?
174
+ dt.to_time.utc.iso8601
175
+ end
176
+
177
+ def self.solr_dates(dts)
178
+ dts.map { |dt| solr_date(dt) }
179
+ end
180
+
181
+ class << self
182
+ alias_method :file_name, :file_name_for
183
+ end
184
+
185
+ end