dor-services 6.8.0 → 7.0.0
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.
- checksums.yaml +4 -4
- data/config/config_defaults.yml +0 -27
- data/config/dev_console_env.rb.example +0 -17
- data/lib/dor-services.rb +9 -73
- data/lib/dor/config.rb +1 -30
- data/lib/dor/datastreams/content_metadata_ds.rb +8 -0
- data/lib/dor/datastreams/desc_metadata_ds.rb +19 -0
- data/lib/dor/datastreams/identity_metadata_ds.rb +65 -0
- data/lib/dor/datastreams/rights_metadata_ds.rb +14 -2
- data/lib/dor/datastreams/workflow_definition_ds.rb +1 -1
- data/lib/dor/datastreams/workflow_ds.rb +0 -15
- data/lib/dor/indexers/identifiable_indexer.rb +8 -4
- data/lib/dor/indexers/releasable_indexer.rb +7 -1
- data/lib/dor/models/abstract.rb +143 -8
- data/lib/dor/models/admin_policy_object.rb +0 -3
- data/lib/dor/models/collection.rb +0 -2
- data/lib/dor/models/concerns/embargoable.rb +7 -60
- data/lib/dor/models/etd.rb +100 -0
- data/lib/dor/models/item.rb +12 -28
- data/lib/dor/models/part.rb +18 -0
- data/lib/dor/models/set.rb +0 -2
- data/lib/dor/services/collection_service.rb +36 -0
- data/lib/dor/services/embargo_service.rb +93 -0
- data/lib/dor/services/ontology.rb +0 -18
- data/lib/dor/services/public_desc_metadata_service.rb +7 -11
- data/lib/dor/services/search_service.rb +0 -40
- data/lib/dor/version.rb +1 -1
- data/lib/dor/workflow/document.rb +0 -7
- metadata +15 -78
- data/lib/dor/models/concerns/assembleable.rb +0 -18
- data/lib/dor/models/concerns/contentable.rb +0 -185
- data/lib/dor/models/concerns/describable.rb +0 -82
- data/lib/dor/models/concerns/eventable.rb +0 -18
- data/lib/dor/models/concerns/geoable.rb +0 -14
- data/lib/dor/models/concerns/governable.rb +0 -101
- data/lib/dor/models/concerns/identifiable.rb +0 -172
- data/lib/dor/models/concerns/itemizable.rb +0 -42
- data/lib/dor/models/concerns/preservable.rb +0 -46
- data/lib/dor/models/concerns/processable.rb +0 -86
- data/lib/dor/models/concerns/publishable.rb +0 -76
- data/lib/dor/models/concerns/releaseable.rb +0 -118
- data/lib/dor/models/concerns/rightsable.rb +0 -25
- data/lib/dor/models/concerns/shelvable.rb +0 -15
- data/lib/dor/models/concerns/versionable.rb +0 -72
- data/lib/dor/services/ability.rb +0 -77
- data/lib/dor/services/cleanup_reset_service.rb +0 -103
- data/lib/dor/services/datastream_builder.rb +0 -96
- data/lib/dor/services/decommission_service.rb +0 -31
- data/lib/dor/services/digital_stacks_service.rb +0 -125
- data/lib/dor/services/dublin_core_service.rb +0 -45
- data/lib/dor/services/file_metadata_merge_service.rb +0 -71
- data/lib/dor/services/indexing_service.rb +0 -131
- data/lib/dor/services/merge_service.rb +0 -105
- data/lib/dor/services/public_xml_service.rb +0 -116
- data/lib/dor/services/publish_metadata_service.rb +0 -99
- data/lib/dor/services/reset_workspace_service.rb +0 -27
- data/lib/dor/services/sdr_ingest_service.rb +0 -172
- data/lib/dor/services/secondary_file_name_service.rb +0 -10
- data/lib/dor/services/shelving_service.rb +0 -69
- data/lib/dor/services/technical_metadata_service.rb +0 -232
- data/lib/dor/services/version_service.rb +0 -84
- data/lib/dor/utils/sdr_client.rb +0 -94
data/lib/dor/services/ability.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dor
|
4
|
-
class Ability
|
5
|
-
class << self
|
6
|
-
def can_manage_item?(roles)
|
7
|
-
intersect roles, groups_which_manage_item
|
8
|
-
end
|
9
|
-
|
10
|
-
def can_manage_desc_metadata?(roles)
|
11
|
-
intersect roles, groups_which_manage_desc_metadata
|
12
|
-
end
|
13
|
-
|
14
|
-
def can_manage_system_metadata?(roles)
|
15
|
-
intersect roles, groups_which_manage_system_metadata
|
16
|
-
end
|
17
|
-
|
18
|
-
def can_manage_content?(roles)
|
19
|
-
intersect roles, groups_which_manage_content
|
20
|
-
end
|
21
|
-
|
22
|
-
def can_manage_rights?(roles)
|
23
|
-
intersect roles, groups_which_manage_rights
|
24
|
-
end
|
25
|
-
|
26
|
-
def can_manage_embargo?(roles)
|
27
|
-
intersect roles, groups_which_manage_embargo
|
28
|
-
end
|
29
|
-
|
30
|
-
def can_view_content?(roles)
|
31
|
-
intersect roles, groups_which_view_content
|
32
|
-
end
|
33
|
-
|
34
|
-
def can_view_metadata?(roles)
|
35
|
-
intersect roles, groups_which_view_metadata
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def groups_which_manage_item
|
41
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor']
|
42
|
-
end
|
43
|
-
|
44
|
-
def groups_which_manage_desc_metadata
|
45
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor', 'dor-apo-metadata']
|
46
|
-
end
|
47
|
-
|
48
|
-
def groups_which_manage_system_metadata
|
49
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor']
|
50
|
-
end
|
51
|
-
|
52
|
-
def groups_which_manage_content
|
53
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor']
|
54
|
-
end
|
55
|
-
|
56
|
-
def groups_which_manage_rights
|
57
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor']
|
58
|
-
end
|
59
|
-
|
60
|
-
def groups_which_manage_embargo
|
61
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor']
|
62
|
-
end
|
63
|
-
|
64
|
-
def groups_which_view_content
|
65
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor', 'dor-viewer', 'sdr-viewer']
|
66
|
-
end
|
67
|
-
|
68
|
-
def groups_which_view_metadata
|
69
|
-
['dor-administrator', 'sdr-administrator', 'dor-apo-manager', 'dor-apo-depositor', 'dor-viewer', 'sdr-viewer']
|
70
|
-
end
|
71
|
-
|
72
|
-
def intersect(arr1, arr2)
|
73
|
-
(arr1 & arr2).length > 0
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
module Dor
|
6
|
-
# Remove all traces of the object's data files from the workspace and export areas
|
7
|
-
class CleanupResetService
|
8
|
-
# @param [String] druid The identifier for the object whose reset data is to be removed
|
9
|
-
# @return [void] remove copy of the reset data that was exported to preservation core
|
10
|
-
def self.cleanup_by_reset_druid(druid)
|
11
|
-
last_version = get_druid_last_version(druid)
|
12
|
-
cleanup_reset_workspace_content(druid, last_version, Config.cleanup.local_workspace_root)
|
13
|
-
cleanup_assembly_content(druid, Config.cleanup.local_assembly_root)
|
14
|
-
cleanup_reset_export(druid, last_version)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.get_druid_last_version(druid)
|
18
|
-
druid_obj = Dor.find(druid)
|
19
|
-
last_version = druid_obj.current_version.to_i
|
20
|
-
|
21
|
-
# if the current version is still open, avoid this versioned directory
|
22
|
-
last_version -= 1 if Dor::Config.workflow.client.lifecycle('dor', druid, 'accessioned').nil?
|
23
|
-
last_version
|
24
|
-
end
|
25
|
-
|
26
|
-
# @param [String] druid The identifier for the object whose reset data is to be removed
|
27
|
-
# @param [String] base The base directory to delete from
|
28
|
-
# @param [Integer] last_version The last version that the data should be removed until version 1
|
29
|
-
# @return [void] remove all the object's reset data files from the workspace area equal to less than the last_version
|
30
|
-
def self.cleanup_reset_workspace_content(druid, last_version, base)
|
31
|
-
base_druid = DruidTools::Druid.new(druid, base)
|
32
|
-
base_druid_tree = base_druid.pathname.to_s
|
33
|
-
# if it is truncated tree /aa/111/aaa/1111/content,
|
34
|
-
# we should follow the regular cleanup technique
|
35
|
-
|
36
|
-
reset_directories = get_reset_dir_list(last_version, base_druid_tree)
|
37
|
-
reset_directories.each do |path|
|
38
|
-
FileUtils.rm_rf(path)
|
39
|
-
end
|
40
|
-
base_druid.prune_ancestors(base_druid.pathname.parent)
|
41
|
-
end
|
42
|
-
|
43
|
-
# @param [String] base_druid_tree The base directory to delete from
|
44
|
-
# @param [Integer] last_version The last version that the data should be removed until version 1
|
45
|
-
# @return [void] prepares a list of reset directories that should be removed
|
46
|
-
def self.get_reset_dir_list(last_version, base_druid_tree)
|
47
|
-
reset_directories = []
|
48
|
-
(1..last_version).each do |i|
|
49
|
-
reset_path = "#{base_druid_tree}_v#{i}"
|
50
|
-
reset_directories.append(reset_path) if File.exist?(reset_path)
|
51
|
-
end
|
52
|
-
reset_directories
|
53
|
-
end
|
54
|
-
|
55
|
-
# @param [String] druid The identifier for the object whose reset bags data is to be removed
|
56
|
-
# @return [void] remove copy of the reset data that was exported to preservation core
|
57
|
-
def self.cleanup_reset_export(druid, last_version)
|
58
|
-
id = druid.split(':').last
|
59
|
-
base_bag_directory = File.join(Config.cleanup.local_export_home, id)
|
60
|
-
|
61
|
-
bag_dir_list = get_reset_bag_dir_list(last_version, base_bag_directory)
|
62
|
-
bag_dir_list.each do |bag_dir|
|
63
|
-
Pathname(bag_dir).rmtree
|
64
|
-
end
|
65
|
-
|
66
|
-
bag_tar_list = get_reset_bag_tar_list(last_version, base_bag_directory)
|
67
|
-
bag_tar_list.each do |bag_tar|
|
68
|
-
Pathname(bag_tar).rmtree
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# @param [Integer] last_version The last version that the data should be removed until version 1
|
73
|
-
# @param [String] base_bag_directory The base bag directory including the export home and druid id
|
74
|
-
# @return [void] prepares a list of reset bag directories that should be removed
|
75
|
-
def self.get_reset_bag_dir_list(last_version, base_bag_directory)
|
76
|
-
reset_bags = []
|
77
|
-
(1..last_version).each do |i|
|
78
|
-
reset_path = "#{base_bag_directory}_v#{i}"
|
79
|
-
reset_bags.append(reset_path) if File.exist?(reset_path)
|
80
|
-
end
|
81
|
-
reset_bags
|
82
|
-
end
|
83
|
-
|
84
|
-
# @param [String] base_bag_directory The base bag directory including the export home and druid id
|
85
|
-
# @param [Integer] last_version The last version that the data should be removed until version 1
|
86
|
-
# @return [void] prepares a list of reset bag tars that should be removed
|
87
|
-
def self.get_reset_bag_tar_list(last_version, base_bag_directory)
|
88
|
-
reset_bags = []
|
89
|
-
(1..last_version).each do |i|
|
90
|
-
reset_path = "#{base_bag_directory}_v#{i}.tar"
|
91
|
-
reset_bags.append(reset_path) if File.exist?(reset_path)
|
92
|
-
end
|
93
|
-
reset_bags
|
94
|
-
end
|
95
|
-
|
96
|
-
# @param [String] druid The identifier for the object whose data is to be removed
|
97
|
-
# @param [String] base The base directory to delete from
|
98
|
-
# @return [void] remove the object's data files from the assembly area
|
99
|
-
def self.cleanup_assembly_content(druid, base)
|
100
|
-
DruidTools::Druid.new(druid, base).prune!
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dor
|
4
|
-
# The ContentMetadata and DescMetadata robot are allowed to build the
|
5
|
-
# datastream by reading a file from the /dor/workspace that matches the
|
6
|
-
# datastream name. This allows assembly or pre-assembly to prebuild the
|
7
|
-
# datastreams from templates or using other means
|
8
|
-
# (like the assembly-objectfile gem) and then have those datastreams picked
|
9
|
-
# up and added to the object during accessionWF.
|
10
|
-
#
|
11
|
-
# This class builds that datastream using the content of a file if such a file
|
12
|
-
# exists and is newer than the object's current datastream (see above); otherwise,
|
13
|
-
# builds the datastream by calling build_fooMetadata_datastream.
|
14
|
-
class DatastreamBuilder
|
15
|
-
# @param [ActiveFedora::Base] object The object that contains the datastream
|
16
|
-
# @param [ActiveFedora::Datastream] datastream The datastream object
|
17
|
-
# @param [Boolean] force Should we overwrite existing datastream?
|
18
|
-
# @param [Boolean] required If set to true, raise an error if we can't build the datastream
|
19
|
-
# @return [ActiveFedora::Datastream]
|
20
|
-
def initialize(object:, datastream:, force: false, required: false)
|
21
|
-
@object = object
|
22
|
-
@datastream = datastream
|
23
|
-
@force = force
|
24
|
-
@required = required
|
25
|
-
raise 'Datastream required, but none provided' if required && !datastream
|
26
|
-
end
|
27
|
-
|
28
|
-
def build
|
29
|
-
return unless datastream
|
30
|
-
|
31
|
-
# See if datastream exists as a file and if the file's timestamp is newer than datastream's timestamp.
|
32
|
-
if file_newer_than_datastream?
|
33
|
-
create_from_file(filename)
|
34
|
-
elsif force || empty_datastream?
|
35
|
-
create_default
|
36
|
-
end
|
37
|
-
# Check for success.
|
38
|
-
raise "Required datastream #{datastream_name} could not be populated!" if required && empty_datastream?
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
attr_reader :datastream, :force, :object, :required
|
44
|
-
|
45
|
-
def filename
|
46
|
-
@filename ||= find_metadata_file
|
47
|
-
end
|
48
|
-
|
49
|
-
# @return [String] datastream name (dsid)
|
50
|
-
def datastream_name
|
51
|
-
datastream.dsid
|
52
|
-
end
|
53
|
-
|
54
|
-
def file_newer_than_datastream?
|
55
|
-
filename && (!datastream_date || file_date > datastream_date)
|
56
|
-
end
|
57
|
-
|
58
|
-
def file_date
|
59
|
-
File.mtime(filename)
|
60
|
-
end
|
61
|
-
|
62
|
-
def datastream_date
|
63
|
-
datastream.createDate
|
64
|
-
end
|
65
|
-
|
66
|
-
def create_from_file(filename)
|
67
|
-
content = File.read(filename)
|
68
|
-
datastream.content = content
|
69
|
-
datastream.ng_xml = Nokogiri::XML(content) if datastream.respond_to?(:ng_xml)
|
70
|
-
datastream.save unless datastream.digital_object.new?
|
71
|
-
end
|
72
|
-
|
73
|
-
def create_default
|
74
|
-
meth = "build_#{datastream_name}_datastream".to_sym
|
75
|
-
return unless object.respond_to?(meth)
|
76
|
-
|
77
|
-
object.public_send(meth, datastream)
|
78
|
-
datastream.save unless datastream.digital_object.new?
|
79
|
-
end
|
80
|
-
|
81
|
-
# Tries to find a file for the datastream.
|
82
|
-
# @return [String, nil] path to datastream or nil
|
83
|
-
def find_metadata_file
|
84
|
-
druid = DruidTools::Druid.new(object.pid, Dor::Config.stacks.local_workspace_root)
|
85
|
-
druid.find_metadata("#{datastream_name}.xml")
|
86
|
-
end
|
87
|
-
|
88
|
-
def empty_datastream?
|
89
|
-
return true if datastream.new?
|
90
|
-
|
91
|
-
return datastream.content.to_s.empty? unless datastream.class.respond_to?(:xml_template)
|
92
|
-
|
93
|
-
datastream.content.to_s.empty? || EquivalentXml.equivalent?(datastream.content, datastream.class.xml_template)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dor
|
4
|
-
# Responsible for decommissioning objects
|
5
|
-
class DecommissionService
|
6
|
-
# @param [Dor::Item] object
|
7
|
-
def initialize(object)
|
8
|
-
@object = object
|
9
|
-
end
|
10
|
-
|
11
|
-
attr_reader :object
|
12
|
-
|
13
|
-
# Clears RELS-EXT relationships, sets the isGovernedBy relationship to the SDR Graveyard APO
|
14
|
-
# @param [String] tag optional String of text that is concatenated to the identityMetadata/tag "Decommissioned : "
|
15
|
-
def decommission(tag)
|
16
|
-
# remove isMemberOf and isMemberOfCollection relationships
|
17
|
-
object.clear_relationship :is_member_of
|
18
|
-
object.clear_relationship :is_member_of_collection
|
19
|
-
# remove isGovernedBy relationship
|
20
|
-
object.clear_relationship :is_governed_by
|
21
|
-
# add isGovernedBy to graveyard APO druid:sw909tc7852
|
22
|
-
# SEARCH BY dc title for 'SDR Graveyard'
|
23
|
-
object.add_relationship :is_governed_by, ActiveFedora::Base.find(Dor::SearchService.sdr_graveyard_apo_druid)
|
24
|
-
# eliminate contentMetadata. set it to <contentMetadata/> ?
|
25
|
-
object.contentMetadata.content = '<contentMetadata/>'
|
26
|
-
# eliminate rightsMetadata. set it to <rightsMetadata/> ?
|
27
|
-
object.rightsMetadata.content = '<rightsMetadata/>'
|
28
|
-
TagService.add object, "Decommissioned : #{tag}"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,125 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'net/ssh'
|
4
|
-
require 'net/sftp'
|
5
|
-
|
6
|
-
module Dor
|
7
|
-
class DigitalStacksService
|
8
|
-
# Delete files from stacks that have change type 'deleted', 'copydeleted', or 'modified'
|
9
|
-
# @param [Pathname] stacks_object_pathname the stacks location of the digital object
|
10
|
-
# @param [Moab::FileGroupDifference] content_diff the content file version differences report
|
11
|
-
def self.remove_from_stacks(stacks_object_pathname, content_diff)
|
12
|
-
%i[deleted copydeleted modified].each do |change_type|
|
13
|
-
subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset}
|
14
|
-
subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
|
15
|
-
moab_signature = moab_file.signatures.first # {Moab::FileSignature}
|
16
|
-
file_pathname = stacks_object_pathname.join(moab_file.basis_path)
|
17
|
-
delete_file(file_pathname, moab_signature)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Delete a file, but only if it exists and matches the expected signature
|
23
|
-
# @param [Pathname] file_pathname The location of the file to be deleted
|
24
|
-
# @param [Moab::FileSignature] moab_signature The fixity values of the file
|
25
|
-
# @return [Boolean] true if file deleted, false otherwise
|
26
|
-
def self.delete_file(file_pathname, moab_signature)
|
27
|
-
if file_pathname.exist? && (file_pathname.size == moab_signature.size)
|
28
|
-
file_signature = Moab::FileSignature.new.signature_from_file(file_pathname)
|
29
|
-
if file_signature == moab_signature
|
30
|
-
file_pathname.delete
|
31
|
-
return true
|
32
|
-
end
|
33
|
-
end
|
34
|
-
false
|
35
|
-
end
|
36
|
-
|
37
|
-
# Rename files from stacks that have change type 'renamed' using an intermediate temp filename.
|
38
|
-
# The 2-step renaming allows chained or cyclic renames to occur without file collisions.
|
39
|
-
# @param [Pathname] stacks_object_pathname the stacks location of the digital object
|
40
|
-
# @param [Moab::FileGroupDifference] content_diff the content file version differences report
|
41
|
-
def self.rename_in_stacks(stacks_object_pathname, content_diff)
|
42
|
-
subset = content_diff.subset(:renamed) # {Moab::FileGroupDifferenceSubset
|
43
|
-
|
44
|
-
# 1st Pass - rename files from original name to checksum-based name
|
45
|
-
subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
|
46
|
-
moab_signature = moab_file.signatures.first # {Moab::FileSignature}
|
47
|
-
original_pathname = stacks_object_pathname.join(moab_file.basis_path)
|
48
|
-
temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
|
49
|
-
rename_file(original_pathname, temp_pathname, moab_signature)
|
50
|
-
end
|
51
|
-
|
52
|
-
# 2nd Pass - rename files from checksum-based name to new name
|
53
|
-
subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
|
54
|
-
moab_signature = moab_file.signatures.first # {Moab::FileSignature}
|
55
|
-
temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
|
56
|
-
new_pathname = stacks_object_pathname.join(moab_file.other_path)
|
57
|
-
rename_file(temp_pathname, new_pathname, moab_signature)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# Rename a file, but only if it exists and has the expected signature
|
62
|
-
# @param [Pathname] old_pathname The original location/name of the file being renamed
|
63
|
-
# @param [Pathname] new_pathname The new location/name of the file
|
64
|
-
# @param [Moab::FileSignature] moab_signature The fixity values of the file
|
65
|
-
# @return [Boolean] true if file renamed, false otherwise
|
66
|
-
def self.rename_file(old_pathname, new_pathname, moab_signature)
|
67
|
-
if old_pathname.exist? && (old_pathname.size == moab_signature.size)
|
68
|
-
file_signature = Moab::FileSignature.new.signature_from_file(old_pathname)
|
69
|
-
if file_signature == moab_signature
|
70
|
-
new_pathname.parent.mkpath
|
71
|
-
old_pathname.rename(new_pathname)
|
72
|
-
return true
|
73
|
-
end
|
74
|
-
end
|
75
|
-
false
|
76
|
-
end
|
77
|
-
|
78
|
-
# Add files to stacks that have change type 'added', 'copyadded' or 'modified'.
|
79
|
-
# @param [Pathname] workspace_content_pathname The dor workspace location of the digital object's content fies
|
80
|
-
# @param [Pathname] stacks_object_pathname the stacks location of the digital object's shelved files
|
81
|
-
# @param [Moab::FileGroupDifference] content_diff the content file version differences report
|
82
|
-
def self.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, content_diff)
|
83
|
-
return false if workspace_content_pathname.nil?
|
84
|
-
|
85
|
-
%i[added copyadded modified].each do |change_type|
|
86
|
-
subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset
|
87
|
-
subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
|
88
|
-
moab_signature = moab_file.signatures.last # {Moab::FileSignature}
|
89
|
-
filename = change_type == :modified ? moab_file.basis_path : moab_file.other_path
|
90
|
-
workspace_pathname = workspace_content_pathname.join(filename)
|
91
|
-
stacks_pathname = stacks_object_pathname.join(filename)
|
92
|
-
copy_file(workspace_pathname, stacks_pathname, moab_signature)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
true
|
96
|
-
end
|
97
|
-
|
98
|
-
# Copy a file to stacks, but only if it does not yet exist with the expected signature
|
99
|
-
# @param [Pathname] workspace_pathname The location of the file in the DOR workspace
|
100
|
-
# @param [Pathname] stacks_pathname The location of the file in the stacks
|
101
|
-
# @param [Moab::FileSignature] moab_signature The fixity values of the file
|
102
|
-
# @return [Boolean] true if file copied, false otherwise
|
103
|
-
def self.copy_file(workspace_pathname, stacks_pathname, moab_signature)
|
104
|
-
if stacks_pathname.exist?
|
105
|
-
file_signature = Moab::FileSignature.new.signature_from_file(stacks_pathname)
|
106
|
-
stacks_pathname.delete if file_signature != moab_signature
|
107
|
-
end
|
108
|
-
unless stacks_pathname.exist?
|
109
|
-
stacks_pathname.parent.mkpath
|
110
|
-
FileUtils.cp workspace_pathname.to_s, stacks_pathname.to_s
|
111
|
-
# Change permissions
|
112
|
-
FileUtils.chmod 'u=rw,go=r', stacks_pathname.to_s
|
113
|
-
return true
|
114
|
-
end
|
115
|
-
false
|
116
|
-
end
|
117
|
-
|
118
|
-
# Assumes the digital stacks storage root is mounted to the local file system
|
119
|
-
# TODO: since this is delegating to the Druid, this method may not be necessary
|
120
|
-
def self.prune_stacks_dir(id)
|
121
|
-
stacks_druid_tree = DruidTools::StacksDruid.new(id, Config.stacks.local_stacks_root)
|
122
|
-
stacks_druid_tree.prune!
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dor
|
4
|
-
class DublinCoreService
|
5
|
-
MODS_TO_DC_XSLT = Nokogiri::XSLT(File.new(File.expand_path(File.dirname(__FILE__) + '/mods2dc.xslt')))
|
6
|
-
XMLNS_OAI_DC = 'http://www.openarchives.org/OAI/2.0/oai_dc/'
|
7
|
-
class CrosswalkError < RuntimeError; end
|
8
|
-
|
9
|
-
def initialize(work, include_collection_as_related_item: true)
|
10
|
-
@work = work
|
11
|
-
@include_collection = include_collection_as_related_item
|
12
|
-
end
|
13
|
-
|
14
|
-
# Generates Dublin Core from the MODS in the descMetadata datastream using the LoC mods2dc stylesheet
|
15
|
-
# Should not be used for the Fedora DC datastream
|
16
|
-
# @raise [CrosswalkError] Raises an Exception if the generated DC is empty or has no children
|
17
|
-
# @return [Nokogiri::XML::Document] the DublinCore XML document object
|
18
|
-
def ng_xml
|
19
|
-
dc_doc = MODS_TO_DC_XSLT.transform(desc_md)
|
20
|
-
dc_doc.xpath('/oai_dc:dc/*[count(text()) = 0]', oai_dc: XMLNS_OAI_DC).remove # Remove empty nodes
|
21
|
-
raise CrosswalkError, "Dor::Item#generate_dublin_core produced incorrect xml (no root):\n#{dc_doc.to_xml}" if dc_doc.root.nil?
|
22
|
-
raise CrosswalkError, "Dor::Item#generate_dublin_core produced incorrect xml (no children):\n#{dc_doc.to_xml}" if dc_doc.root.children.size == 0
|
23
|
-
|
24
|
-
dc_doc
|
25
|
-
end
|
26
|
-
|
27
|
-
# @return [String] the DublinCore XML document object
|
28
|
-
def to_xml
|
29
|
-
ng_xml.to_xml
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def desc_md
|
35
|
-
return PublicDescMetadataService.new(work).ng_xml(include_access_conditions: false) if include_collection?
|
36
|
-
|
37
|
-
work.descMetadata.ng_xml
|
38
|
-
end
|
39
|
-
|
40
|
-
def include_collection?
|
41
|
-
@include_collection
|
42
|
-
end
|
43
|
-
attr_reader :work
|
44
|
-
end
|
45
|
-
end
|