dor-services 5.1.0 → 5.1.1

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 (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