dor-services 5.1.0 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +13 -5
  2. data/config/dev_console_env.rb +45 -32
  3. data/lib/dor-services.rb +52 -49
  4. data/lib/dor/datastreams/administrative_metadata_ds.rb +2 -2
  5. data/lib/dor/datastreams/content_metadata_ds.rb +114 -144
  6. data/lib/dor/datastreams/default_object_rights_ds.rb +10 -12
  7. data/lib/dor/datastreams/desc_metadata_ds.rb +4 -4
  8. data/lib/dor/datastreams/events_ds.rb +8 -8
  9. data/lib/dor/datastreams/identity_metadata_ds.rb +40 -23
  10. data/lib/dor/datastreams/rights_metadata_ds.rb +109 -0
  11. data/lib/dor/datastreams/role_metadata_ds.rb +4 -4
  12. data/lib/dor/datastreams/simple_dublin_core_ds.rb +6 -6
  13. data/lib/dor/datastreams/version_metadata_ds.rb +29 -10
  14. data/lib/dor/models/admin_policy_object.rb +3 -3
  15. data/lib/dor/models/describable.rb +5 -4
  16. data/lib/dor/models/editable.rb +29 -33
  17. data/lib/dor/models/embargoable.rb +1 -12
  18. data/lib/dor/models/governable.rb +4 -27
  19. data/lib/dor/models/identifiable.rb +60 -58
  20. data/lib/dor/models/item.rb +5 -9
  21. data/lib/dor/models/presentable.rb +15 -2
  22. data/lib/dor/models/processable.rb +34 -30
  23. data/lib/dor/models/publishable.rb +5 -14
  24. data/lib/dor/models/{releasable.rb → releaseable.rb} +59 -15
  25. data/lib/dor/models/rightsable.rb +25 -0
  26. data/lib/dor/models/versionable.rb +6 -3
  27. data/lib/dor/models/workflow_object.rb +4 -4
  28. data/lib/dor/services/cleanup_reset_service.rb +1 -2
  29. data/lib/dor/services/cleanup_service.rb +1 -1
  30. data/lib/dor/services/registration_service.rb +0 -3
  31. data/lib/dor/services/sdr_ingest_service.rb +1 -1
  32. data/lib/dor/services/search_service.rb +1 -1
  33. data/lib/dor/utils/sdr_client.rb +23 -0
  34. data/lib/dor/version.rb +1 -1
  35. data/lib/dor/workflow/document.rb +23 -22
  36. data/lib/tasks/rdoc.rake +4 -4
  37. metadata +113 -96
  38. data/config/environments/development.rb +0 -84
  39. data/config/environments/development.rb.old +0 -84
  40. data/config/environments/test.rb +0 -84
  41. data/lib/tasks/dor.rake +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 220d7103c61a4210c39dd0a7d7f92f08c1fc3b16
4
- data.tar.gz: 7ed5456b52b9d10a701b36a3c82e02189589e806
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGQ5ZWQ0NWFjYTg0ZDc0YTFiNmMwMjM2ZmEzYzJjYTA4NzA5NmUwOA==
5
+ data.tar.gz: !binary |-
6
+ MDJmMmQ5ZGNmNzU5OWQxNmMwNjJlOWY2MTgwMTc4NWM4ZmI3YWNhYg==
5
7
  SHA512:
6
- metadata.gz: c419b64ebe780589176fa5bd7a9b77bc4b8dbade3899710e9984af0d42469327bfa62efda0d7565e9f59a9792ba82238f9e4a59d4410865c5871bbaa84c488a7
7
- data.tar.gz: 074921fed0d04103962f77d87e96d39235ff693a04c7d439b0f76e906f8977a8f47a9c71b37e43607164bfdebc5bffdded6f622b026811329bc36e7685222f03
8
+ metadata.gz: !binary |-
9
+ MzcxNDU3MjQ4NjQwODgwZTQyM2Q1OGQ4ZGYzYjdhOTI3ZTY1MzA3OGEzZjc2
10
+ MWJiYjkzN2VjNzVmYWI1NWRhMDBjMTE4MDZhMjM5Y2QzOTIwNGRlY2IwYWYy
11
+ YmQyZDc5YjY4N2I3ODcwMDZkZDE3ODRlOTM3NTY4MDY3ODhmNzI=
12
+ data.tar.gz: !binary |-
13
+ OTZiMzAzNjg3NDFlZTM3NzYwYmVmNjljMzcxYjA4YzE2Y2MwYmQ3ZjA2Zjdh
14
+ ZjY0MWVhNDlmMWE3ZWE2ZWUxNWUwN2JkNWU2NDlhZGNiYWZkZTg3MmUzZWQx
15
+ Y2FhM2I3MGFhMjc4OTk2YTk3MGU5N2YwYjkzYTQyOTQxMTIxNjY=
@@ -1,18 +1,13 @@
1
- # Copied from common-accessioning config/environments
2
-
3
- cert_dir = File.join(File.dirname(__FILE__), ".", "certs")
1
+ cert_dir = File.join(File.dirname(__FILE__), "certs")
4
2
 
5
3
  Dor::Config.configure do
6
- fedora do
7
- url 'https://sul-dor-dev.stanford.edu/fedora'
8
- end
9
4
 
10
5
  ssl do
11
6
  cert_file File.join(cert_dir,"robots-dor-dev.crt")
12
- key_file File.join(cert_dir,"robots-dor-dev.key")
13
- key_pass ''
7
+ key_file File.join(cert_dir,"robots-dor-dev.key")
8
+ key_pass ''
14
9
  end
15
-
10
+
16
11
  suri do
17
12
  mint_ids true
18
13
  id_namespace 'druid'
@@ -20,46 +15,64 @@ Dor::Config.configure do
20
15
  user 'labware'
21
16
  pass 'lyberteam'
22
17
  end
23
-
18
+
24
19
  metadata do
25
- exist.url 'http://viewer:l3l%40nd@lyberapps-dev.stanford.edu/exist/rest/'
20
+ exist.url 'http://viewer:l3l%40nd@lyberapps-dev.stanford.edu/exist/rest/'
26
21
  catalog.url 'http://lyberservices-prod.stanford.edu/catalog/mods'
27
22
  end
28
-
23
+
29
24
  stacks do
30
25
  document_cache_host 'purl-dev.stanford.edu'
31
- document_cache_user 'lyberadmin'
32
- local_workspace_root '/dor/workspace'
33
- storage_root '/stacks'
34
- host 'stacks-dev.stanford.edu'
35
- user 'lyberadmin'
36
- local_stacks_root '/stacks'
26
+ local_stacks_root '/stacks'
37
27
  local_document_cache_root '/purl/document_cache'
28
+ local_workspace_root '/dor/workspace'
38
29
  end
39
-
40
- gsearch.url 'https://sul-dor-dev.stanford.edu/solr/gsearch'
41
- solrizer.url 'https://sul-dor-dev.stanford.edu/solr'
42
- workflow.url 'https://lyberservices-dev.stanford.edu/workflow/'
43
- dor_services.url 'https://dorAdmin:dorAdmin@sul-lyberservices-dev.stanford.edu/dor/v1'
30
+
31
+ solrizer.url 'http://sul-solr.stanford.edu/solr/argo_test'
32
+ fedora.url 'https://sul-dor-test.stanford.edu/fedora'
33
+ workflow.url 'https://lyberservices-dev.stanford.edu/workflow/'
34
+ dor_services.url 'https://dorAdmin:dorAdmin@sul-lyberservices-dev.stanford.edu/dor'
44
35
 
45
36
  cleanup do
46
37
  local_workspace_root '/dor/workspace'
47
- local_export_home '/dor/export'
38
+ local_export_home '/dor/export'
48
39
  end
49
40
 
50
41
  sdr do
42
+ url 'https://sdrAdmin:sdrAdmin@sdr-services-test.stanford.edu/sdr/'
51
43
  local_workspace_root '/dor/workspace'
52
- local_export_home '/dor/export'
44
+ local_export_home '/dor/export'
53
45
  datastreams do
54
- contentMetadata 'required'
55
- descMetadata 'required'
56
- identityMetadata 'required'
57
- provenanceMetadata 'required'
58
- relationshipMetadata 'required'
59
- rightsMetadata 'optional'
60
- sourceMetadata 'optional'
46
+ administrativeMetadata 'optional'
47
+ contentMetadata 'optional'
48
+ descMetadata 'required'
49
+ defaultObjectRights 'optional'
50
+ events 'optional'
51
+ embargoMetadata 'optional'
52
+ identityMetadata 'required'
53
+ provenanceMetadata 'required'
54
+ relationshipMetadata 'required'
55
+ rightsMetadata 'optional'
56
+ roleMetadata 'optional'
57
+ sourceMetadata 'optional'
58
+ technicalMetadata 'optional'
59
+ versionMetadata 'required'
60
+ workflows 'optional'
61
61
  end
62
62
  end
63
63
 
64
+ accessioning_robot_sleep_time 30
65
+
64
66
  end
65
67
 
68
+
69
+ #WORKFLOW_URI = 'http://lyberservices-test.stanford.edu/workflow'
70
+
71
+ # Constants for Dor::WorkflowService
72
+ #module Dor
73
+ # CREATE_WORKFLOW = DOR_CREATE_WORKFLOW = true
74
+ # WF_URI = 'http://lyberservices-test.stanford.edu/workflow'
75
+ #end
76
+
77
+ # External application locations
78
+ JHOVE_HOME = File.join(ENV['HOME'], 'jhoveToolkit')
data/lib/dor-services.rb CHANGED
@@ -4,7 +4,7 @@ require 'active_support/core_ext/module/attribute_accessors'
4
4
  module Dor
5
5
  @@registered_classes = {}
6
6
  mattr_reader :registered_classes
7
- INDEX_VERSION_FIELD = 'dor_services_version_facet'
7
+ INDEX_VERSION_FIELD = 'dor_services_version_ssi'
8
8
 
9
9
  class << self
10
10
 
@@ -40,7 +40,7 @@ module Dor
40
40
  resp.docs.collect do |solr_doc|
41
41
  doc_version = solr_doc[INDEX_VERSION_FIELD].first rescue '0.0.0'
42
42
  doc_version = Gem::Version.new(doc_version)
43
- object_type = Array(solr_doc[ActiveFedora::SolrService.solr_name('objectType',:facetable)]).first
43
+ object_type = Array(solr_doc[ActiveFedora::SolrService.solr_name('objectType', :symbol)]).first
44
44
  object_class = registered_classes[object_type] || ActiveFedora::Base
45
45
  if opts[:lightweight] and doc_version >= Gem::Version.new('3.1.0')
46
46
  begin
@@ -78,63 +78,66 @@ module Dor
78
78
  require 'druid-tools'
79
79
 
80
80
  # datastreams
81
- autoload :AdministrativeMetadataDS, 'dor/datastreams/administrative_metadata_ds'
82
- autoload :ContentMetadataDS, 'dor/datastreams/content_metadata_ds'
83
- autoload :DescMetadataDS, 'dor/datastreams/desc_metadata_ds'
84
- autoload :EmbargoMetadataDS, 'dor/datastreams/embargo_metadata_ds'
85
- autoload :EventsDS, 'dor/datastreams/events_ds'
86
- autoload :GeoMetadataDS, 'dor/datastreams/geo_metadata_ds'
87
- autoload :IdentityMetadataDS, 'dor/datastreams/identity_metadata_ds'
88
- autoload :RoleMetadataDS, 'dor/datastreams/role_metadata_ds'
89
- autoload :WorkflowDefinitionDs, 'dor/datastreams/workflow_definition_ds'
90
- autoload :WorkflowDs, 'dor/datastreams/workflow_ds'
91
- autoload :VersionMetadataDS, 'dor/datastreams/version_metadata_ds'
92
- autoload :DefaultObjectRightsDS, 'dor/datastreams/default_object_rights_ds'
93
- autoload :SimpleDublinCoreDs, 'dor/datastreams/simple_dublin_core_ds'
81
+ autoload :AdministrativeMetadataDS, 'dor/datastreams/administrative_metadata_ds'
82
+ autoload :ContentMetadataDS, 'dor/datastreams/content_metadata_ds'
83
+ autoload :DescMetadataDS, 'dor/datastreams/desc_metadata_ds'
84
+ autoload :EmbargoMetadataDS, 'dor/datastreams/embargo_metadata_ds'
85
+ autoload :EventsDS, 'dor/datastreams/events_ds'
86
+ autoload :GeoMetadataDS, 'dor/datastreams/geo_metadata_ds'
87
+ autoload :IdentityMetadataDS, 'dor/datastreams/identity_metadata_ds'
88
+ autoload :RightsMetadataDS, 'dor/datastreams/rights_metadata_ds'
89
+ autoload :RoleMetadataDS, 'dor/datastreams/role_metadata_ds'
90
+ autoload :WorkflowDefinitionDs, 'dor/datastreams/workflow_definition_ds'
91
+ autoload :WorkflowDs, 'dor/datastreams/workflow_ds'
92
+ autoload :VersionMetadataDS, 'dor/datastreams/version_metadata_ds'
93
+ autoload :DefaultObjectRightsDS, 'dor/datastreams/default_object_rights_ds'
94
+ autoload :SimpleDublinCoreDs, 'dor/datastreams/simple_dublin_core_ds'
94
95
 
95
96
  # DOR Concerns
96
97
  autoload :Identifiable, 'dor/models/identifiable'
97
- autoload :Itemizable, 'dor/models/itemizable'
98
- autoload :Processable, 'dor/models/processable'
99
- autoload :Governable, 'dor/models/governable'
100
- autoload :Describable, 'dor/models/describable'
101
- autoload :Publishable, 'dor/models/publishable'
102
- autoload :Shelvable, 'dor/models/shelvable'
103
- autoload :Embargoable, 'dor/models/embargoable'
104
- autoload :Preservable, 'dor/models/preservable'
98
+ autoload :Itemizable, 'dor/models/itemizable'
99
+ autoload :Processable, 'dor/models/processable'
100
+ autoload :Governable, 'dor/models/governable'
101
+ autoload :Describable, 'dor/models/describable'
102
+ autoload :Publishable, 'dor/models/publishable'
103
+ autoload :Shelvable, 'dor/models/shelvable'
104
+ autoload :Embargoable, 'dor/models/embargoable'
105
+ autoload :Preservable, 'dor/models/preservable'
105
106
  autoload :Assembleable, 'dor/models/assembleable'
106
- autoload :Upgradable, 'dor/models/upgradable'
107
- autoload :Eventable, 'dor/models/eventable'
108
- autoload :Versionable, 'dor/models/versionable'
109
- autoload :Contentable, 'dor/models/contentable'
110
- autoload :Editable, 'dor/models/editable'
111
- autoload :Geoable, 'dor/models/geoable'
112
- autoload :Presentable, 'dor/models/presentable'
113
- autoload :Releasable, 'dor/models/releasable'
107
+ autoload :Upgradable, 'dor/models/upgradable'
108
+ autoload :Eventable, 'dor/models/eventable'
109
+ autoload :Versionable, 'dor/models/versionable'
110
+ autoload :Contentable, 'dor/models/contentable'
111
+ autoload :Editable, 'dor/models/editable'
112
+ autoload :Discoverable, 'dor/models/discoverable'
113
+ autoload :Geoable, 'dor/models/geoable'
114
+ autoload :Presentable, 'dor/models/presentable'
115
+ autoload :Releaseable, 'dor/models/releaseable'
116
+ autoload :Rightsable, 'dor/models/rightsable'
114
117
 
115
118
 
116
119
  # ActiveFedora Classes
117
- autoload :Abstract, 'dor/models/item'
118
- autoload :Item, 'dor/models/item'
119
- autoload :Set, 'dor/models/set'
120
+ autoload :Abstract, 'dor/models/item'
121
+ autoload :Item, 'dor/models/item'
122
+ autoload :Set, 'dor/models/set'
120
123
  autoload :Collection, 'dor/models/collection'
121
124
  autoload :AdminPolicyObject, 'dor/models/admin_policy_object'
122
- autoload :WorkflowObject, 'dor/models/workflow_object'
125
+ autoload :WorkflowObject, 'dor/models/workflow_object'
123
126
 
124
127
  # Services
125
- autoload :SearchService, 'dor/services/search_service'
126
- autoload :MetadataService, 'dor/services/metadata_service'
127
- autoload :RegistrationService, 'dor/services/registration_service'
128
- autoload :SuriService, 'dor/services/suri_service'
129
- autoload :WorkflowService, 'dor/services/workflow_service'
130
- autoload :DigitalStacksService, 'dor/services/digital_stacks_service'
131
- autoload :SdrIngestService, 'dor/services/sdr_ingest_service'
132
- autoload :CleanupService, 'dor/services/cleanup_service'
128
+ autoload :SearchService, 'dor/services/search_service'
129
+ autoload :MetadataService, 'dor/services/metadata_service'
130
+ autoload :RegistrationService, 'dor/services/registration_service'
131
+ autoload :SuriService, 'dor/services/suri_service'
132
+ autoload :WorkflowService, 'dor/services/workflow_service'
133
+ autoload :DigitalStacksService, 'dor/services/digital_stacks_service'
134
+ autoload :SdrIngestService, 'dor/services/sdr_ingest_service'
135
+ autoload :CleanupService, 'dor/services/cleanup_service'
133
136
  autoload :ProvenanceMetadataService, 'dor/services/provenance_metadata_service'
134
- autoload :TechnicalMetadataService, 'dor/services/technical_metadata_service'
135
- autoload :MergeService, 'dor/services/merge_service'
136
- autoload :ResetWorkspaceService, 'dor/services/reset_workspace_service'
137
- autoload :CleanupResetService, 'dor/services/cleanup_reset_service'
137
+ autoload :TechnicalMetadataService, 'dor/services/technical_metadata_service'
138
+ autoload :MergeService, 'dor/services/merge_service'
139
+ autoload :ResetWorkspaceService, 'dor/services/reset_workspace_service'
140
+ autoload :CleanupResetService, 'dor/services/cleanup_reset_service'
138
141
 
139
142
  # Versioning Classes
140
143
  module Versioning
@@ -143,8 +146,8 @@ module Dor
143
146
 
144
147
  # Workflow Classes
145
148
  module Workflow
146
- autoload :Graph, 'dor/workflow/graph'
147
- autoload :Process, 'dor/workflow/process'
149
+ autoload :Graph, 'dor/workflow/graph'
150
+ autoload :Process, 'dor/workflow/process'
148
151
  autoload :Document, 'dor/workflow/document'
149
152
  end
150
153
  end
@@ -17,14 +17,14 @@ class AdministrativeMetadataDS < ActiveFedora::OmDatastream
17
17
  t.registration :index_as => [:not_searchable] do
18
18
  t.agreementId
19
19
  t.itemTag
20
- t.workflow_id :path => 'workflow/@id', :index_as => [:symbol, :facetable]
20
+ t.workflow_id :path => 'workflow/@id', :index_as => [:symbol]
21
21
  t.default_collection :path => 'collection/@id'
22
22
  end
23
23
  t.workflow :path => 'registration/workflow'
24
24
  t.deposit :index_as => [:not_searchable]
25
25
 
26
26
  t.accessioning :index_as => [:not_searchable] do
27
- t.workflow_id :path => 'workflow/@id', :index_as => [:facetable]
27
+ t.workflow_id :path => 'workflow/@id', :index_as => [:symbol]
28
28
  end
29
29
 
30
30
  t.preservation :index_as => [:not_searchable]
@@ -1,26 +1,26 @@
1
1
  module Dor
2
- class ContentMetadataDS < ActiveFedora::OmDatastream
2
+ class ContentMetadataDS < ActiveFedora::OmDatastream
3
3
  include Upgradable
4
4
  include SolrDocHelper
5
5
 
6
6
  set_terminology do |t|
7
- t.root :path => 'contentMetadata', :index_as => [:not_searchable]
8
- t.contentType :path => '/contentMetadata/@type', :index_as => [:not_searchable]
9
- t.stacks :path=> '/contentMetadata/@stacks', :index_as => [:not_searchable]
7
+ t.root :path => 'contentMetadata', :index_as => [:not_searchable]
8
+ t.contentType :path => '/contentMetadata/@type', :index_as => [:not_searchable]
9
+ t.stacks :path => '/contentMetadata/@stacks', :index_as => [:not_searchable]
10
10
  t.resource(:index_as => [:not_searchable]) do
11
- t.id_ :path => { :attribute => 'id' }
12
- t.sequence :path => { :attribute => 'sequence' }#, :data_type => :integer
13
- t.type_ :path => { :attribute => 'type' }, :index_as => [:displayable]
11
+ t.id_ :path => { :attribute => 'id' }
12
+ t.sequence :path => { :attribute => 'sequence' }#, :data_type => :integer
13
+ t.type_ :path => { :attribute => 'type' }, :index_as => [:displayable]
14
14
  t.attribute(:path => 'attr', :index_as => [:not_searchable]) do
15
- t.name :path => { :attribute => 'name' }, :index_as => [:not_searchable]
15
+ t.name :path => { :attribute => 'name' }, :index_as => [:not_searchable]
16
16
  end
17
17
  t.file(:index_as => [:not_searchable]) do
18
- t.id_ :path => { :attribute => 'id' }
18
+ t.id_ :path => { :attribute => 'id' }
19
19
  t.mimeType :path => { :attribute => 'mimeType' }, :index_as => [:displayable]
20
20
  t.dataType :path => { :attribute => 'dataType' }, :index_as => [:displayable]
21
- t.size :path => { :attribute => 'size' }, :index_as => [:displayable]#, :data_type => :long
22
- t.shelve :path => { :attribute => 'shelve' }, :index_as => [:not_searchable]#, :data_type => :boolean
23
- t.publish :path => { :attribute => 'publish' }, :index_as => [:not_searchable]#, :data_type => :boolean
21
+ t.size :path => { :attribute => 'size' }, :index_as => [:displayable]#, :data_type => :long
22
+ t.shelve :path => { :attribute => 'shelve' }, :index_as => [:not_searchable]#, :data_type => :boolean
23
+ t.publish :path => { :attribute => 'publish' }, :index_as => [:not_searchable]#, :data_type => :boolean
24
24
  t.preserve :path => { :attribute => 'preserve' }, :index_as => [:not_searchable]#, :data_type => :boolean
25
25
  t.checksum do
26
26
  t.type_ :path => { :attribute => 'type' }
@@ -35,69 +35,50 @@ module Dor
35
35
 
36
36
  def public_xml
37
37
  result = self.ng_xml.clone
38
- result.xpath('/contentMetadata/resource[not(file[(@deliver="yes" or @publish="yes")])]').each { |n| n.remove }
39
- result.xpath('/contentMetadata/resource/file[not(@deliver="yes" or @publish="yes")]').each { |n| n.remove }
38
+ result.xpath('/contentMetadata/resource[not(file[(@deliver="yes" or @publish="yes")])]' ).each { |n| n.remove }
39
+ result.xpath('/contentMetadata/resource/file[not(@deliver="yes" or @publish="yes")]' ).each { |n| n.remove }
40
40
  result.xpath('/contentMetadata/resource/file').xpath('@preserve|@shelve|@publish|@deliver').each { |n| n.remove }
41
- result.xpath('/contentMetadata/resource/file/checksum').each { |n| n.remove }
41
+ result.xpath('/contentMetadata/resource/file/checksum' ).each { |n| n.remove }
42
42
  result
43
43
  end
44
44
  def add_file(file, resource_name)
45
45
  xml=self.ng_xml
46
46
  resource_nodes = xml.search('//resource[@id=\''+resource_name+'\']')
47
- if resource_nodes.length==0
48
- raise 'resource doesnt exist.'
49
- end
47
+ raise 'resource doesnt exist.' if resource_nodes.length==0
50
48
  node=resource_nodes.first
51
49
  file_node=Nokogiri::XML::Node.new('file',xml)
52
50
  file_node['id']=file[:name]
53
- file_node['shelve']=file[:shelve] ? file[:shelve] : ''
54
- file_node['publish']=file[:publish] ? file[:publish] : ''
55
- file_node['preserve']=file[:preserve] ? file[:preserve] : ''
51
+ file_node['shelve' ] = file[:shelve ] ? file[:shelve ] : ''
52
+ file_node['publish' ] = file[:publish ] ? file[:publish ] : ''
53
+ file_node['preserve'] = file[:preserve] ? file[:preserve] : ''
56
54
  node.add_child(file_node)
57
55
 
58
- if file[:md5]
59
- checksum_node=Nokogiri::XML::Node.new('checksum',xml)
60
- checksum_node['type']='md5'
61
- checksum_node.content=file[:md5]
62
- file_node.add_child(checksum_node)
63
- end
64
- if file[:sha1]
65
- checksum_node=Nokogiri::XML::Node.new('checksum',xml)
66
- checksum_node['type']='sha1'
67
- checksum_node.content=file[:sha1]
56
+ [:md5, :sha1].each do |algo|
57
+ next unless file[algo]
58
+ checksum_node = Nokogiri::XML::Node.new('checksum',xml)
59
+ checksum_node['type'] = algo.to_s
60
+ checksum_node.content = file[algo]
68
61
  file_node.add_child(checksum_node)
69
62
  end
70
- if file[:size]
71
- file_node['size']=file[:size]
72
- end
73
- if file[:mime_type]
74
- file_node['mimetype']=file[:mime_type]
75
- end
63
+ file_node['size' ] = file[:size ] if file[:size ]
64
+ file_node['mimetype'] = file[:mime_type] if file[:mime_type]
76
65
  self.content=xml.to_s
77
66
  self.save
78
67
  end
79
68
 
80
- def add_resource(files,resource_name, position,type="file")
69
+ def add_resource(files,resource_name, position,type="file")
81
70
  xml=self.ng_xml
82
71
  if xml.search('//resource[@id=\''+resource_name+'\']').length>0
83
72
  raise 'resource '+resource_name+' already exists'
84
73
  end
85
74
  node=nil
86
75
 
87
- max=-1
88
- xml.search('//resource').each do |node|
89
- if node['sequence'].to_i>max
90
- max=node['sequence'].to_i
91
- end
92
- end
76
+ max = xml.search('//resource').map{ |node| node['sequence'].to_i }.max
93
77
  #renumber all of the resources that will come after the newly added one
94
78
  while max>position do
95
79
  node=xml.search('//resource[@sequence=\'' + position + '\']')
96
- if node.length>0
97
- node=node.first
98
- node[sequence]=max+1
99
- end
100
- max=max-1
80
+ node.first[sequence]=max+1 if node.length>0
81
+ max-=1
101
82
  end
102
83
  node=Nokogiri::XML::Node.new('resource',xml)
103
84
  node['sequence']=position.to_s
@@ -117,7 +98,7 @@ module Dor
117
98
  file_node.add_child(checksum_node)
118
99
  }
119
100
  file_node['size'] = file[:size] if file[:size]
120
- end
101
+ end
121
102
  xml.search('//contentMetadata').first.add_child(node)
122
103
  self.content=xml.to_s
123
104
  self.save
@@ -125,20 +106,12 @@ module Dor
125
106
 
126
107
  def remove_resource resource_name
127
108
  xml=self.ng_xml
128
- position=-1
129
-
130
- resources=xml.search('//resource[@id=\''+resource_name+'\']')
131
- if resources.length!=1
132
- raise 'Resource is missing or duplicated!'
133
- end
134
- position=resources.first['sequence']
135
- resources.first.remove
136
- position=position.to_i+1
109
+ node = singular_node('//resource[@id=\''+resource_name+'\']')
110
+ position = node['sequence'].to_i+1
111
+ node.remove
137
112
  while true
138
113
  res=xml.search('//resource[@sequence=\''+position.to_s+'\']')
139
- if(res.length==0)
140
- break
141
- end
114
+ break if res.length==0
142
115
  res['sequence']=position.to_s
143
116
  position=position+1
144
117
  end
@@ -184,54 +157,50 @@ module Dor
184
157
  self.content=xml.to_s
185
158
  self.save
186
159
  end
160
+
187
161
  # Terminology-based solrization is going to be painfully slow for large
188
162
  # contentMetadata streams. Just select the relevant elements instead.
163
+ # TODO: Call super()?
189
164
  def to_solr(solr_doc=Hash.new, *args)
190
165
  doc = self.ng_xml
191
- if doc.root['type']
192
- shelved_file_count=0
193
- content_file_count=0
194
- resource_type_counts={}
195
- resource_count=0
196
- preserved_size=0
197
- first_shelved_image=nil
198
- add_solr_value(solr_doc, "content_type", doc.root['type'], :string, [:facetable, :symbol])
199
- doc.xpath('contentMetadata/resource').sort { |a,b| a['sequence'].to_i <=> b['sequence'].to_i }.each do |resource|
200
- resource_count+=1
201
- if(resource['type'])
202
- if resource_type_counts[resource['type']]
203
- resource_type_counts[resource['type']]+=1
204
- else
205
- resource_type_counts[resource['type']]=1
206
- end
207
- end
208
- resource.xpath('file').each do |file|
209
- content_file_count+=1
210
- if file['shelve'] == 'yes'
211
- shelved_file_count+=1
212
- if first_shelved_image.nil? && file['id'].match(/jp2$/)
213
- first_shelved_image=file['id']
214
- end
215
- end
216
- if file['preserve'] == 'yes'
217
- preserved_size += file['size'].to_i
166
+ return solr_doc unless doc.root['type']
167
+
168
+ preserved_size=0
169
+ counts = Hash.new(0) # default count is zero
170
+ resource_type_counts = Hash.new(0) # default count is zero
171
+ first_shelved_image=nil
172
+
173
+ doc.xpath('contentMetadata/resource').sort { |a,b| a['sequence'].to_i <=> b['sequence'].to_i }.each do |resource|
174
+ counts['resource']+=1
175
+ resource_type_counts[resource['type']]+=1 if resource['type']
176
+ resource.xpath('file').each do |file|
177
+ counts['content_file']+=1
178
+ preserved_size += file['size'].to_i if file['preserve'] == 'yes'
179
+ if file['shelve'] == 'yes'
180
+ counts['shelved_file']+=1
181
+ if first_shelved_image.nil? && file['id'].match(/jp2$/)
182
+ first_shelved_image=file['id']
218
183
  end
219
184
  end
220
185
  end
221
- add_solr_value(solr_doc, "content_file_count", content_file_count.to_s, :string, [:searchable, :displayable])
222
- add_solr_value(solr_doc, "shelved_content_file_count", shelved_file_count.to_s, :string, [:searchable, :displayable])
223
- add_solr_value(solr_doc, "resource_count", resource_count.to_s, :string, [:searchable, :displayable])
224
- add_solr_value(solr_doc, "preserved_size", preserved_size.to_s, :string, [:searchable, :displayable])
225
- resource_type_counts.each do |key, count|
226
- add_solr_value(solr_doc, "resource_types", key, :string, [:symbol])
227
- add_solr_value(solr_doc, key+"_resource_count", count.to_s, :string, [:searchable, :displayable])
228
- end
229
- unless first_shelved_image.nil?
230
- add_solr_value(solr_doc, "first_shelved_image", first_shelved_image, :string, [:displayable])
231
- end
232
186
  end
187
+ solr_doc["content_type_ssim" ] = doc.root['type']
188
+ solr_doc["content_file_count_itsi" ] = counts['content_file']
189
+ solr_doc["shelved_content_file_count_itsi"] = counts['shelved_file']
190
+ solr_doc["resource_count_itsi" ] = counts['resource']
191
+ solr_doc["preserved_size_dbtsi" ] = preserved_size # double (trie) to support very large sizes
192
+ solr_doc["resource_types_ssim" ] = resource_type_counts.keys if resource_type_counts.size > 0
193
+ resource_type_counts.each do |key, count|
194
+ solr_doc["#{key}_resource_count_itsi"] = count
195
+ end
196
+ # first_shelved_image is neither indexed nor multiple
197
+ solr_doc["first_shelved_image_ss"] = first_shelved_image unless first_shelved_image.nil?
233
198
  solr_doc
234
199
  end
200
+
201
+ #@param old_name [String] unique id attribute of the file element
202
+ #@param new_name [String] new unique id value being assigned
203
+ #@return [Nokogiri::XML::Element] the file node
235
204
  def rename_file old_name, new_name
236
205
  xml=self.ng_xml
237
206
  file_node=xml.search('//file[@id=\''+old_name+'\']').first
@@ -240,63 +209,52 @@ module Dor
240
209
  self.save
241
210
  end
242
211
 
212
+ #Updates old label OR creates a new one if necessary
213
+ #@param resource_name [String] unique id attribute of the resource
214
+ #@param new_label [String] label value being assigned
215
+ #@return [Nokogiri::XML::Element] the resource node
243
216
  def update_resource_label resource_name, new_label
244
- xml=self.ng_xml
245
- resource_node=xml.search('//resource[@id=\''+resource_name+'\']')
246
- if(resource_node.length!=1)
247
- raise 'Resource not found or duplicate found.'
248
- end
249
- labels=xml.search('//resource[@id=\''+resource_name+'\']/label')
217
+ node = singular_node('//resource[@id=\''+resource_name+'\']')
218
+ labels = node.xpath('./label')
250
219
  if(labels.length==0)
251
220
  #create a label
252
- label_node = Nokogiri::XML::Node.new('label',xml)
221
+ label_node = Nokogiri::XML::Node.new('label',self.ng_xml)
253
222
  label_node.content=new_label
254
- resource_node.first.add_child(label_node)
223
+ node.add_child(label_node)
255
224
  else
256
225
  labels.first.content=new_label
257
226
  end
227
+ return node
258
228
  end
259
- def update_resource_type resource, new_type
260
- xml=self.ng_xml
261
- resource_node=xml.search('//resource[@id=\''+resource_name+'\']')
262
- if(resource_node.length!=1)
263
- raise 'Resource not found or duplicate found.'
264
- end
265
- resource_node.first['type']=new_type
229
+
230
+ #@param resource_name [String] unique id attribute of the resource
231
+ #@param new_type [String] type value being assigned
232
+ def update_resource_type resource_name, new_type
233
+ singular_node('//resource[@id=\''+resource_name+'\']')['type']=new_type
266
234
  end
267
235
 
236
+ #You just *had* to have ordered lists in XML, didn't you?
237
+ #Re-enumerate the sequence numbers affected
238
+ #@param resource_name [String] unique id attribute of the resource
239
+ #@param new_position [Integer, String] new sequence number of the resource, or a string that looks like one
240
+ #@return [Nokogiri::XML::Element] the resource node
268
241
  def move_resource resource_name, new_position
269
- xml=self.ng_xml
270
- file_node=xml.search('//resource[@id=\''+resource_name+'\']')
271
- if(file_node.length!=1)
272
- raise 'Resource not found or duplicate found.'
273
- end
274
- position=file_node.first['sequence'].to_i
275
- #is the resource being moved earlier in the sequence or later?
276
- new_position=new_position.to_i
277
- if new_position>position
278
- counter=position
279
- while true
280
- if counter == position
281
- break
282
- end
283
- item=xml.search('/resource[@id=\''+counter.to_s+'\']').first
284
- counter=counter+1
285
- item['sequence']=counter.to_s
286
- end
287
- else
288
- counter=position
289
- while true
290
- if counter == new_position
291
- break
292
- end
293
- item=xml.search('/resource[@id=\''+counter.to_s+'\']').first
294
- counter=counter-1
295
- item['sequence']=counter.to_s
296
- end
242
+ node = singular_node('//resource[@id=\''+resource_name+'\']')
243
+ position = node['sequence'].to_i
244
+ new_position = new_position.to_i # tolerate strings as a Legacy behavior
245
+ return node if position == new_position
246
+ #otherwise, is the resource being moved earlier in the sequence or later?
247
+ up = new_position>position
248
+ others = new_position..(up ? position-1 : position+1) # a range
249
+ others.each do |i|
250
+ item = self.ng_xml.at_xpath('/resource[@sequence=\''+i.to_s+'\']')
251
+ item['sequence'] = (up ? i-1 : i+1).to_s # if you're going up, everything else comes down and vice versa
297
252
  end
253
+ node['sequence'] = new_position.to_s # set the node we already had last, so we don't hit it twice!
254
+ return node
298
255
  end
299
- #Set the content type to and the resource types for all resources
256
+
257
+ #Set the content type and the resource types for all resources
300
258
  #@param new_type [String] the new content type, ex book
301
259
  #@param new_resource_type [String] the new type for all resources, ex book
302
260
  def set_content_type old_type, old_resource_type, new_type, new_resource_type
@@ -309,6 +267,18 @@ module Dor
309
267
  end
310
268
  self.content=xml.to_s
311
269
  end
270
+
271
+ # Only use this when you want the behavior of raising an exception if anything besides exactly one matching node
272
+ # is found. Otherwise just use .xpath, .at_xpath or .search.
273
+ #@param xpath [String] accessor invocation for Nokogiri xpath
274
+ #@return [Nokogiri::XML::Element] the matched element
275
+ def singular_node xpath
276
+ node = self.ng_xml.search(xpath)
277
+ len = node.length
278
+ raise "#{xpath} not found" if len < 1
279
+ raise "#{xpath} duplicated: #{len} found" if len != 1
280
+ node.first
281
+ end
312
282
  end
313
283
 
314
284
  end