ddr-models 3.0.0.beta.3 → 3.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -3
  3. data/config/locales/ddr-models.en.yml +74 -0
  4. data/ddr-models.gemspec +3 -2
  5. data/lib/ddr/auth.rb +5 -2
  6. data/lib/ddr/auth/roles.rb +0 -2
  7. data/lib/ddr/auth/roles/role_set.rb +1 -0
  8. data/lib/ddr/derivatives/generators/png_generator.rb +1 -1
  9. data/lib/ddr/index.rb +6 -2
  10. data/lib/ddr/index/abstract_query_result.rb +1 -1
  11. data/lib/ddr/index/csv_options.rb +14 -0
  12. data/lib/ddr/index/csv_query_result.rb +39 -32
  13. data/lib/ddr/index/field.rb +11 -1
  14. data/lib/ddr/index/field_attribute.rb +22 -0
  15. data/lib/ddr/index/fields.rb +29 -20
  16. data/lib/ddr/index/filter.rb +81 -30
  17. data/lib/ddr/index/filters.rb +15 -10
  18. data/lib/ddr/index/query.rb +34 -13
  19. data/lib/ddr/index/query_builder.rb +150 -30
  20. data/lib/ddr/index/query_clause.rb +64 -19
  21. data/lib/ddr/index/query_params.rb +40 -0
  22. data/lib/ddr/index/solr_csv_options.rb +18 -0
  23. data/lib/ddr/index/sort_order.rb +28 -0
  24. data/lib/ddr/jobs.rb +5 -1
  25. data/lib/ddr/jobs/fits_file_characterization.rb +3 -41
  26. data/lib/ddr/jobs/fixity_check.rb +13 -0
  27. data/lib/ddr/jobs/job.rb +36 -0
  28. data/lib/ddr/jobs/queue.rb +27 -0
  29. data/lib/ddr/jobs/update_index.rb +13 -0
  30. data/lib/ddr/models.rb +20 -3
  31. data/lib/ddr/models/admin_set.rb +7 -3
  32. data/lib/ddr/models/contact.rb +19 -0
  33. data/lib/ddr/models/error.rb +3 -0
  34. data/lib/ddr/models/file_characterization.rb +37 -0
  35. data/lib/ddr/models/finding_aid.rb +35 -2
  36. data/lib/ddr/models/has_admin_metadata.rb +5 -1
  37. data/lib/ddr/models/has_content.rb +4 -2
  38. data/lib/ddr/models/indexing.rb +7 -0
  39. data/lib/ddr/models/licenses/license.rb +7 -3
  40. data/lib/ddr/models/solr_document.rb +2 -2
  41. data/lib/ddr/models/version.rb +1 -1
  42. data/lib/ddr/models/with_content_file.rb +37 -0
  43. data/lib/ddr/vocab/asset.rb +3 -0
  44. data/spec/derivatives/png_generator_spec.rb +8 -1
  45. data/spec/fixtures/arrow1rightred_e0.gif +0 -0
  46. data/spec/index/fields_spec.rb +197 -0
  47. data/spec/index/filter_spec.rb +155 -30
  48. data/spec/index/query_builder_spec.rb +116 -0
  49. data/spec/index/query_clause_spec.rb +58 -0
  50. data/spec/index/query_spec.rb +39 -10
  51. data/spec/jobs/fits_file_characterization_spec.rb +7 -43
  52. data/spec/jobs/fixity_check_spec.rb +22 -0
  53. data/spec/jobs/job_spec.rb +40 -0
  54. data/spec/jobs/update_index_spec.rb +22 -0
  55. data/spec/managers/derivatives_manager_spec.rb +15 -11
  56. data/spec/models/admin_set_spec.rb +28 -10
  57. data/spec/models/contact_spec.rb +42 -0
  58. data/spec/models/effective_license_spec.rb +17 -7
  59. data/spec/models/file_characterization_spec.rb +38 -0
  60. data/spec/models/finding_aid_spec.rb +31 -8
  61. data/spec/models/has_admin_metadata_spec.rb +8 -5
  62. data/spec/models/indexing_spec.rb +2 -0
  63. data/spec/models/license_spec.rb +31 -10
  64. data/spec/models/solr_document_spec.rb +23 -3
  65. data/spec/models/with_content_file_spec.rb +32 -0
  66. data/spec/spec_helper.rb +2 -0
  67. metadata +66 -28
  68. data/lib/ddr/contacts.rb +0 -25
  69. data/lib/ddr/index/query_value.rb +0 -18
  70. data/lib/ddr/models/access_controllable.rb +0 -12
  71. data/spec/auth/ldap_gateway_spec.rb +0 -9
  72. data/spec/contacts/contacts_spec.rb +0 -26
  73. data/spec/index/filters_spec.rb +0 -17
@@ -1,12 +1,16 @@
1
- require "ddr_aux/client"
1
+ require "active_resource"
2
2
 
3
3
  module Ddr::Models
4
- class AdminSet < DdrAux::Client::AdminSet
4
+ class AdminSet < ActiveResource::Base
5
+
6
+ self.site = ENV["DDR_AUX_API_URL"]
5
7
 
6
8
  def self.call(obj)
7
9
  if obj.admin_set
8
- find(code: obj.admin_set)
10
+ new get(:find, code: obj.admin_set)
9
11
  end
12
+ rescue ActiveResource::ResourceNotFound => e
13
+ raise Ddr::Models::NotFoundError, e
10
14
  end
11
15
 
12
16
  def to_s
@@ -0,0 +1,19 @@
1
+ require "active_resource"
2
+
3
+ module Ddr::Models
4
+ class Contact < ActiveResource::Base
5
+
6
+ self.site = ENV["DDR_AUX_API_URL"]
7
+
8
+ def self.call(slug)
9
+ new get(:find, slug: slug)
10
+ rescue ActiveResource::ResourceNotFound => e
11
+ raise Ddr::Models::NotFoundError, e
12
+ end
13
+
14
+ def to_s
15
+ name
16
+ end
17
+
18
+ end
19
+ end
@@ -11,5 +11,8 @@ module Ddr
11
11
 
12
12
  # Content model casting error
13
13
  class ContentModelError < Error; end
14
+
15
+ # A model instance was not found
16
+ class NotFoundError < Error; end
14
17
  end
15
18
  end
@@ -0,0 +1,37 @@
1
+ require "delegate"
2
+ require "shellwords"
3
+
4
+ module Ddr::Models
5
+ class FileCharacterization < SimpleDelegator
6
+
7
+ class FITSError < Error; end
8
+
9
+ def self.call(obj)
10
+ new(obj).call
11
+ end
12
+
13
+ def call
14
+ with_content_file do |path|
15
+ fits_output = run_fits(path)
16
+ reload
17
+ fits.content = fits_output
18
+ save!
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def run_fits(path)
25
+ output = `#{fits_command} -i #{Shellwords.escape(path)}`
26
+ unless $?.success?
27
+ raise FITSError, output
28
+ end
29
+ output
30
+ end
31
+
32
+ def fits_command
33
+ File.join(Ddr::Models.fits_home, 'fits.sh')
34
+ end
35
+
36
+ end
37
+ end
@@ -1,22 +1,55 @@
1
+ require "nokogiri"
2
+
1
3
  module Ddr::Models
2
4
  class FindingAid
3
5
 
4
6
  attr_reader :ead_id
5
7
 
8
+ EAD_XMLNS = "urn:isbn:1-931666-22-9"
9
+
6
10
  def initialize(ead_id)
7
11
  @ead_id = ead_id
8
12
  end
9
13
 
10
14
  def url
11
- @url ||= doc.css("eadid").attr("url").text
15
+ doc.css("eadid").attr("url").text
12
16
  end
13
17
 
18
+ # The finding aid title
14
19
  def title
15
- @title ||= doc.css("titleproper").children.first.text.strip
20
+ doc.css("titleproper").children.first.text.strip
21
+ end
22
+
23
+ def repository
24
+ collection.xpath('ead:did/ead:repository/ead:corpname', ead: EAD_XMLNS).text
25
+ end
26
+
27
+ def collection_date_span
28
+ collection.xpath('ead:did/ead:unitdate[@type="inclusive"]', ead: EAD_XMLNS).text
29
+ end
30
+
31
+ def collection_number
32
+ collection.xpath('ead:did/ead:unitid', ead: EAD_XMLNS).text
33
+ end
34
+
35
+ def collection_title
36
+ collection.xpath('ead:did/ead:unittitle', ead: EAD_XMLNS).text
37
+ end
38
+
39
+ def extent
40
+ collection.xpath('ead:did/ead:physdesc/ead:extent', ead: EAD_XMLNS).map(&:text).join("; ")
41
+ end
42
+
43
+ def abstract
44
+ collection.xpath('ead:did/ead:abstract', ead: EAD_XMLNS).text
16
45
  end
17
46
 
18
47
  private
19
48
 
49
+ def collection
50
+ doc.xpath('//ead:archdesc[@level="collection"]', ead: EAD_XMLNS)
51
+ end
52
+
20
53
  # @raise [OpenURI::HTTPError] if 404, etc.
21
54
  def doc
22
55
  @doc ||= Nokogiri::XML(open(ead_xml_url))
@@ -14,6 +14,10 @@ module Ddr::Models
14
14
  predicate: Ddr::Vocab::Asset.adminSet,
15
15
  multiple: false
16
16
 
17
+ property :aspace_id,
18
+ predicate: Ddr::Vocab::Asset.archivesSpaceId,
19
+ multiple: false
20
+
17
21
  property :depositor,
18
22
  predicate: RDF::Vocab::MARCRelators.dpt,
19
23
  multiple: false
@@ -98,7 +102,7 @@ module Ddr::Models
98
102
  end
99
103
 
100
104
  def research_help
101
- Ddr::Contacts.get(research_help_contact) if research_help_contact
105
+ Ddr::Models::Contact.call(research_help_contact) if research_help_contact
102
106
  end
103
107
 
104
108
  def effective_license
@@ -1,5 +1,3 @@
1
- require 'openssl'
2
-
3
1
  module Ddr
4
2
  module Models
5
3
  module HasContent
@@ -107,6 +105,10 @@ module Ddr
107
105
  !extractedText.empty?
108
106
  end
109
107
 
108
+ def with_content_file(&block)
109
+ WithContentFile.new(self, &block)
110
+ end
111
+
110
112
  protected
111
113
 
112
114
  def update_derivatives
@@ -4,6 +4,10 @@ module Ddr
4
4
 
5
5
  include Ddr::Index::Fields
6
6
 
7
+ def self.const_missing(name)
8
+ Ddr::Index::Fields.const_missing(name)
9
+ end
10
+
7
11
  def to_solr(solr_doc=Hash.new, opts={})
8
12
  solr_doc = super(solr_doc, opts)
9
13
  solr_doc.merge index_fields
@@ -13,8 +17,10 @@ module Ddr
13
17
  fields = {
14
18
  ACCESS_ROLE => roles.to_json,
15
19
  ADMIN_SET => admin_set,
20
+ ASPACE_ID => aspace_id,
16
21
  ATTACHED_FILES => attached_files_profile.to_json,
17
22
  BOX_NUMBER_FACET => desc_metadata_values('box_number'),
23
+ CONTRIBUTOR_FACET => desc_metadata_values('contributor'),
18
24
  CREATOR_FACET => descMetadata.creator,
19
25
  DATE_FACET => descMetadata.date,
20
26
  DATE_SORT => date_sort,
@@ -34,6 +40,7 @@ module Ddr
34
40
  RESOURCE_ROLE => roles.in_resource_scope.agents,
35
41
  SERIES_FACET => desc_metadata_values('series'),
36
42
  SPATIAL_FACET => desc_metadata_values('spatial'),
43
+ SUBJECT_FACET => desc_metadata_values('subject'),
37
44
  TITLE => title_display,
38
45
  TYPE_FACET => descMetadata.type,
39
46
  WORKFLOW_STATE => workflow_state,
@@ -1,17 +1,21 @@
1
- require "ddr_aux/client"
1
+ require "active_resource"
2
2
 
3
3
  module Ddr::Models
4
- class License < DdrAux::Client::License
4
+ class License < ActiveResource::Base
5
5
  extend Deprecation
6
6
 
7
+ self.site = ENV["DDR_AUX_API_URL"]
8
+
7
9
  attr_accessor :object_id
8
10
 
9
11
  def self.call(obj)
10
12
  if obj.license
11
- license = find(url: obj.license)
13
+ license = new get(:find, url: obj.license)
12
14
  license.object_id = obj.id
13
15
  license
14
16
  end
17
+ rescue ActiveResource::ResourceNotFound => e
18
+ raise Ddr::Models::NotFoundError, e
15
19
  end
16
20
 
17
21
  def pid
@@ -90,7 +90,7 @@ module Ddr::Models
90
90
  end
91
91
 
92
92
  def has_datastream?(dsID)
93
- datastreams[dsID].present?
93
+ datastreams.key?(dsID) && datastreams[dsID]["size"].present?
94
94
  end
95
95
 
96
96
  def has_admin_policy?
@@ -200,7 +200,7 @@ module Ddr::Models
200
200
 
201
201
  def research_help
202
202
  research_help_contact = self[Ddr::Index::Fields::RESEARCH_HELP_CONTACT] || inherited_research_help_contact
203
- Ddr::Contacts.get(research_help_contact) if research_help_contact
203
+ Ddr::Models::Contact.call(research_help_contact) if research_help_contact
204
204
  end
205
205
 
206
206
  def parent_uri
@@ -1,5 +1,5 @@
1
1
  module Ddr
2
2
  module Models
3
- VERSION = "3.0.0.beta.3"
3
+ VERSION = "3.0.0.beta.4"
4
4
  end
5
5
  end
@@ -0,0 +1,37 @@
1
+ require "tempfile"
2
+ require "delegate"
3
+
4
+ module Ddr::Models
5
+ class WithContentFile < SimpleDelegator
6
+
7
+ def initialize(obj, &block)
8
+ super(obj)
9
+ with_temp_file &block
10
+ end
11
+
12
+ # Yields path of tempfile containing content to block
13
+ # @yield [String] the path to the tempfile containing content
14
+ def with_temp_file
15
+ filename = original_filename || content.default_file_name
16
+ basename = [ File.basename(filename, ".*"), File.extname(filename) ]
17
+ infile = Tempfile.open(basename, Ddr::Models.tempdir, encoding: 'ascii-8bit')
18
+ begin
19
+ infile.write(content.content)
20
+ infile.close
21
+ verify_checksum!(infile)
22
+ yield infile.path
23
+ ensure
24
+ infile.close unless infile.closed?
25
+ File.unlink(infile)
26
+ end
27
+ end
28
+
29
+ def verify_checksum!(file)
30
+ digest = Ddr::Utils.digest(File.read(file), content.checksum.algorithm)
31
+ if digest != content.checksum.value
32
+ raise ChecksumInvalid, "The checksum of the downloaded file does not match the stored checksum of the content."
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -18,6 +18,9 @@
18
18
  property "eadId",
19
19
  label: "EAD ID"
20
20
 
21
+ property "archivesSpaceId",
22
+ label: "ArchivesSpace Identifier"
23
+
21
24
  property "multiresImageFilePath",
22
25
  label: "Multires Image File Path"
23
26
 
@@ -16,7 +16,14 @@ module Ddr::Derivatives
16
16
  expect(File.size(output_path)).to be > 0
17
17
  end
18
18
  end
19
+ context "animated gif source" do
20
+ let(:source_path) { File.join(Ddr::Models::Engine.root, "spec", "fixtures", "arrow1rightred_e0.gif") }
21
+ it "should generate a non-empty file" do
22
+ generator.generate(source_path, output_path)
23
+ expect(File.size(output_path)).to be > 0
24
+ end
25
+ end
19
26
  end
20
27
 
21
28
  end
22
- end
29
+ end
Binary file
@@ -0,0 +1,197 @@
1
+ module Ddr::Index
2
+ RSpec.describe Fields do
3
+
4
+ describe "module methods" do
5
+ specify {
6
+ expect(Fields.techmd).to contain_exactly(
7
+ Fields::TECHMD_COLOR_SPACE,
8
+ Fields::TECHMD_CREATING_APPLICATION,
9
+ Fields::TECHMD_CREATION_TIME,
10
+ Fields::TECHMD_FILE_SIZE,
11
+ Fields::TECHMD_FITS_VERSION,
12
+ Fields::TECHMD_FITS_DATETIME,
13
+ Fields::TECHMD_FORMAT_LABEL,
14
+ Fields::TECHMD_FORMAT_VERSION,
15
+ Fields::TECHMD_IMAGE_HEIGHT,
16
+ Fields::TECHMD_IMAGE_WIDTH,
17
+ Fields::TECHMD_MEDIA_TYPE,
18
+ Fields::TECHMD_MODIFICATION_TIME,
19
+ Fields::TECHMD_PRONOM_IDENTIFIER,
20
+ Fields::TECHMD_VALID,
21
+ Fields::TECHMD_WELL_FORMED
22
+ )
23
+ }
24
+ end
25
+
26
+ describe "constants" do
27
+ describe "ID" do
28
+ subject { Fields::ID }
29
+ its(:label) { is_expected.to eq "Fedora PID" }
30
+ its(:heading) { is_expected.to eq "pid" }
31
+ end
32
+
33
+ describe "PID" do
34
+ subject { Fields::PID }
35
+ its(:label) { is_expected.to eq "Fedora PID" }
36
+ its(:heading) { is_expected.to eq "pid" }
37
+ end
38
+
39
+ describe "ACCESS_ROLE" do
40
+ subject { Fields::ACCESS_ROLE }
41
+ its(:label) { is_expected.to eq "Access Role" }
42
+ its(:heading) { is_expected.to eq "access_role" }
43
+ end
44
+
45
+ describe "ACTIVE_FEDORA_MODEL" do
46
+ subject { Fields::ACTIVE_FEDORA_MODEL }
47
+ its(:label) { is_expected.to eq "Model" }
48
+ its(:heading) { is_expected.to eq "model" }
49
+ end
50
+
51
+ describe "ADMIN_SET" do
52
+ subject { Fields::ADMIN_SET }
53
+ its(:label) { is_expected.to eq "Admin Set" }
54
+ its(:heading) { is_expected.to eq "admin_set" }
55
+ end
56
+
57
+ describe "ASPACE_ID" do
58
+ subject { Fields::ASPACE_ID }
59
+ its(:label) { is_expected.to eq "ArchivesSpace ID" }
60
+ its(:heading) { is_expected.to eq "aspace_id" }
61
+ end
62
+
63
+ describe "DOI" do
64
+ subject { Fields::DOI }
65
+ its(:label) { is_expected.to eq "DOI" }
66
+ its(:heading) { is_expected.to eq "doi" }
67
+ end
68
+
69
+ describe "EAD_ID" do
70
+ subject { Fields::EAD_ID }
71
+ its(:label) { is_expected.to eq "EAD ID" }
72
+ its(:heading) { is_expected.to eq "ead_id" }
73
+ end
74
+
75
+ describe "LOCAL_ID" do
76
+ subject { Fields::LOCAL_ID }
77
+ its(:label) { is_expected.to eq "Local ID" }
78
+ its(:heading) { is_expected.to eq "local_id" }
79
+ end
80
+
81
+ describe "OBJECT_CREATE_DATE" do
82
+ subject { Fields::OBJECT_CREATE_DATE }
83
+ its(:label) { is_expected.to eq "Creation Date" }
84
+ its(:heading) { is_expected.to eq "creation_date" }
85
+ end
86
+
87
+ describe "OBJECT_MODIFIED_DATE" do
88
+ subject { Fields::OBJECT_MODIFIED_DATE }
89
+ its(:label) { is_expected.to eq "Modification Date" }
90
+ its(:heading) { is_expected.to eq "modification_date" }
91
+ end
92
+
93
+ describe "PERMANENT_ID" do
94
+ subject { Fields::PERMANENT_ID }
95
+ its(:label) { is_expected.to eq "Permanent ID" }
96
+ its(:heading) { is_expected.to eq "permanent_id" }
97
+ end
98
+
99
+ describe "PERMANENT_URL" do
100
+ subject { Fields::PERMANENT_URL }
101
+ its(:label) { is_expected.to eq "Permanent URL" }
102
+ its(:heading) { is_expected.to eq "permanent_url" }
103
+ end
104
+
105
+ describe "TECHMD_COLOR_SPACE" do
106
+ subject { Fields::TECHMD_COLOR_SPACE }
107
+ its(:label) { is_expected.to eq "Color Space" }
108
+ its(:heading) { is_expected.to eq "color_space" }
109
+ end
110
+
111
+ describe "TECHMD_CREATING_APPLICATION" do
112
+ subject { Fields::TECHMD_CREATING_APPLICATION }
113
+ its(:label) { is_expected.to eq "Creating Application" }
114
+ its(:heading) { is_expected.to eq "creating_application" }
115
+ end
116
+
117
+ describe "TECHMD_CREATION_TIME" do
118
+ subject { Fields::TECHMD_CREATION_TIME }
119
+ its(:label) { is_expected.to eq "Creation Time" }
120
+ its(:heading) { is_expected.to eq "creation_time" }
121
+ end
122
+
123
+ describe "TECHMD_FILE_SIZE" do
124
+ subject { Fields::TECHMD_FILE_SIZE }
125
+ its(:label) { is_expected.to eq "File Size" }
126
+ its(:heading) { is_expected.to eq "file_size" }
127
+ end
128
+
129
+ describe "TECHMD_FITS_VERSION" do
130
+ subject { Fields::TECHMD_FITS_VERSION }
131
+ its(:label) { is_expected.to eq "FITS Version" }
132
+ its(:heading) { is_expected.to eq "fits_version" }
133
+ end
134
+
135
+ describe "TECHMD_FITS_DATETIME" do
136
+ subject { Fields::TECHMD_FITS_DATETIME }
137
+ its(:label) { is_expected.to eq "FITS Run At" }
138
+ its(:heading) { is_expected.to eq "fits_datetime" }
139
+ end
140
+
141
+ describe "TECHMD_FORMAT_LABEL" do
142
+ subject { Fields::TECHMD_FORMAT_LABEL }
143
+ its(:label) { is_expected.to eq "Format Label" }
144
+ its(:heading) { is_expected.to eq "format_label" }
145
+ end
146
+
147
+ describe "TECHMD_FORMAT_VERSION" do
148
+ subject { Fields::TECHMD_FORMAT_VERSION }
149
+ its(:label) { is_expected.to eq "Format Version" }
150
+ its(:heading) { is_expected.to eq "format_version" }
151
+ end
152
+
153
+ describe "TECHMD_IMAGE_HEIGHT" do
154
+ subject { Fields::TECHMD_IMAGE_HEIGHT }
155
+ its(:label) { is_expected.to eq "Image Height" }
156
+ its(:heading) { is_expected.to eq "image_height" }
157
+ end
158
+
159
+ describe "TECHMD_IMAGE_WIDTH" do
160
+ subject { Fields::TECHMD_IMAGE_WIDTH }
161
+ its(:label) { is_expected.to eq "Image Width" }
162
+ its(:heading) { is_expected.to eq "image_width" }
163
+ end
164
+
165
+ describe "TECHMD_MEDIA_TYPE" do
166
+ subject { Fields::TECHMD_MEDIA_TYPE }
167
+ its(:label) { is_expected.to eq "Media Type" }
168
+ its(:heading) { is_expected.to eq "media_type" }
169
+ end
170
+
171
+ describe "TECHMD_MODIFICATION_TIME" do
172
+ subject { Fields::TECHMD_MODIFICATION_TIME }
173
+ its(:label) { is_expected.to eq "Modification Time" }
174
+ its(:heading) { is_expected.to eq "modification_time" }
175
+ end
176
+
177
+ describe "TECHMD_PRONOM_IDENTIFIER" do
178
+ subject { Fields::TECHMD_PRONOM_IDENTIFIER }
179
+ its(:label) { is_expected.to eq "PRONOM Unique ID" }
180
+ its(:heading) { is_expected.to eq "pronom_uid" }
181
+ end
182
+
183
+ describe "TECHMD_VALID" do
184
+ subject { Fields::TECHMD_VALID }
185
+ its(:label) { is_expected.to eq "Valid" }
186
+ its(:heading) { is_expected.to eq "valid" }
187
+ end
188
+
189
+ describe "TECHMD_WELL_FORMED" do
190
+ subject { Fields::TECHMD_WELL_FORMED }
191
+ its(:label) { is_expected.to eq "Well-formed" }
192
+ its(:heading) { is_expected.to eq "well_formed" }
193
+ end
194
+ end
195
+
196
+ end
197
+ end