Module: Dor::Contentable

Extended by:
ActiveSupport::Concern
Included in:
Item
Defined in:
lib/dor/models/concerns/contentable.rb

Instance Method Summary collapse

Instance Method Details

#add_constituent(druid) ⇒ Object

Adds a RELS-EXT constituent relationship to the given druid

Parameters:

  • druid (String)

    the parent druid of the constituent relationship e.g.: <fedora:isConstituentOf rdf:resource=“info:fedora/druid:hj097bm8879” />



232
233
234
# File 'lib/dor/models/concerns/contentable.rb', line 232

def add_constituent(druid)
  add_relationship :is_constituent_of, ActiveFedora::Base.find(druid)
end

#add_file(file, resource, file_name, mime_type = nil, publish = 'no', shelve = 'no', preserve = 'no') ⇒ Object

add a file to a resource, not to be confused with add a resource to an object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/dor/models/concerns/contentable.rb', line 6

def add_file(file, resource, file_name, mime_type = nil, publish = 'no', shelve = 'no', preserve = 'no')
  xml = datastreams['contentMetadata'].ng_xml
  # make sure the resource exists
  raise 'resource doesnt exist.' if xml.search('//resource[@id=\'' + resource + '\']').length == 0
  sftp = Net::SFTP.start(Config.content.content_server, Config.content.content_user, :auth_methods => ['publickey'])
  druid_tools = DruidTools::Druid.new(pid, Config.content.content_base_dir)
  location = druid_tools.path(file_name)
  oldlocation = location.gsub('/' + pid.gsub('druid:', ''), '')
  md5  = Digest::MD5.file(file.path).hexdigest
  sha1 = Digest::SHA1.file(file.path).hexdigest
  size = File.size?(file.path)
  # update contentmd
  file_hash = {:name => file_name, :md5 => md5, :publish => publish, :shelve => shelve, :preserve => preserve, :size => size.to_s, :sha1 => sha1, :mime_type => mime_type}
  begin
    sftp.stat!(location.gsub(file_name, ''))
    begin
      sftp.stat!(location)
      raise "The file #{file_name} already exists!"
    rescue Net::SFTP::StatusException
      sftp.upload!(file.path, location)
      .add_file file_hash, resource
    end
  rescue Net::SFTP::StatusException
    # directory layout doesn't match the new style, so use the old style.
    begin
      sftp.stat!(oldlocation)
      raise "The file #{file_name} already exists!"
    rescue Net::SFTP::StatusException
      # file doesn't already exist, which is good. Add it
      sftp.upload!(file.path, oldlocation)
      .add_file file_hash, resource
    end
  end
  # can only arrive at this point if a non status exception occurred.
end

#copy_file_resources(source_obj_pids) ⇒ Object

Appends contentMetadata file resources from the source objects to this object

Parameters:

  • source_obj_pids (Array<String>)

    ids of the secondary objects that will get their contentMetadata merged into this one



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/dor/models/concerns/contentable.rb', line 158

def copy_file_resources(source_obj_pids)
  primary_cm = .ng_xml
  .ng_xml_will_change!
  base_id = primary_cm.at_xpath('/contentMetadata/@objectId').value
  max_sequence = primary_cm.at_xpath('/contentMetadata/resource[last()]/@sequence').value.to_i

  source_obj_pids.each do |src_pid|
    source_obj = Dor.find src_pid
    source_cm = source_obj..ng_xml

    # Copy the resources from each source object
    source_cm.xpath('/contentMetadata/resource').each do |old_resource|
      max_sequence += 1
      resource_copy = old_resource.clone
      resource_copy['sequence'] = "#{max_sequence}"

      # Append sequence number to each secondary filename, then
      # look for filename collisions with the primary object
      resource_copy.xpath('file').each do |secondary_file|
        secondary_file['id'] = new_secondary_file_name(secondary_file['id'], max_sequence)

        if primary_cm.at_xpath("//file[@id = '#{secondary_file['id']}']")
          raise Dor::Exception, "File '#{secondary_file['id']}' from secondary object #{src_pid} already exist in primary object: #{pid}"
        end
      end

      if old_resource['type']
        resource_copy['id'] = "#{old_resource['type']}_#{max_sequence}"
      else
        resource_copy['id'] = "#{base_id}_#{max_sequence}"
      end

      lbl = old_resource.at_xpath 'label'
      if lbl && lbl.text =~ /^(.*)\s+\d+$/
        resource_copy.at_xpath('label').content = "#{$1} #{max_sequence}"
      end

      primary_cm.at_xpath('/contentMetadata/resource[last()]').add_next_sibling resource_copy
      attr_node = primary_cm.create_element 'attr', src_pid, :name => 'mergedFromPid'
      resource_copy.first_element_child.add_previous_sibling attr_node
      attr_node = primary_cm.create_element 'attr', old_resource['id'], :name => 'mergedFromResource'
      resource_copy.first_element_child.add_previous_sibling attr_node
    end
  end
end

#decommission(tag) ⇒ Object Also known as: decomission

Clears RELS-EXT relationships, sets the isGovernedBy relationship to the SDR Graveyard APO

Parameters:

  • tag (String)

    optional String of text that is concatenated to the identityMetadata/tag “Decommissioned : ”



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/dor/models/concerns/contentable.rb', line 210

def decommission(tag)
  # remove isMemberOf and isMemberOfCollection relationships
  clear_relationship :is_member_of
  clear_relationship :is_member_of_collection
  # remove isGovernedBy relationship
  clear_relationship :is_governed_by
  # add isGovernedBy to graveyard APO druid:sw909tc7852
  # SEARCH BY dc title for 'SDR Graveyard'
  add_relationship :is_governed_by, ActiveFedora::Base.find(Dor::SearchService.sdr_graveyard_apo_druid)
  # eliminate contentMetadata. set it to <contentMetadata/> ?
  .content = '<contentMetadata/>'
  # eliminate rightsMetadata. set it to <rightsMetadata/> ?
  .content = '<rightsMetadata/>'
  add_tag "Decommissioned : #{tag}"
end

#get_file(file) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/dor/models/concerns/contentable.rb', line 68

def get_file(file)
  druid_tools = DruidTools::Druid.new(pid, Config.content.content_base_dir)
  location = druid_tools.path(file)
  oldlocation = location.gsub('/' + file, '').gsub('/' + pid.gsub('druid:', ''), '') + '/' + file
  sftp = Net::SFTP.start(Config.content.content_server, Config.content.content_user, :auth_methods => ['publickey'])
  begin
    data = sftp.download!(location)
  rescue
    data = sftp.download!(oldlocation)
  end
  data
end

#get_preserved_file(file, version) ⇒ Object



64
65
66
# File 'lib/dor/models/concerns/contentable.rb', line 64

def get_preserved_file(file, version)
  Sdr::Client.get_preserved_file_content(pid, file, version)
end

#is_file_in_workspace?(filename) ⇒ Boolean

Returns whether the file in question is present in the object’s workspace.

Parameters:

  • filename (String)

Returns:

  • (Boolean)

    whether the file in question is present in the object’s workspace



151
152
153
154
# File 'lib/dor/models/concerns/contentable.rb', line 151

def is_file_in_workspace?(filename)
  druid_obj = DruidTools::Druid.new(pid, Dor::Config.stacks.local_workspace_root)
  !druid_obj.find_content(filename).nil?
end

#list_filesArray

list files in the workspace

Returns:

  • (Array)

    workspace files



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/dor/models/concerns/contentable.rb', line 126

def list_files
  filename = 'none'
  files = []
  sftp = Net::SFTP.start(Config.content.content_server, Config.content.content_user, :auth_methods => ['publickey'])
  druid_tools = DruidTools::Druid.new(pid, Config.content.content_base_dir)
  location = druid_tools.path(filename).gsub(filename, '')
  oldlocation = location.gsub('/' + pid.gsub('druid:', ''), '')
  begin
    sftp.dir.entries(location, '*') do |file|
      files << file.name
    end
  rescue
    begin
      sftp.dir.glob(oldlocation, '*') do |file|
        files << file.name
      end
    rescue Net::SFTP::StatusException
      return files
    end
  end
  files
end

#new_secondary_file_name(old_name, sequence_num) ⇒ Object



204
205
206
# File 'lib/dor/models/concerns/contentable.rb', line 204

def new_secondary_file_name(old_name, sequence_num)
  old_name =~ /^(.*)\.(.*)$/ ? "#{$1}_#{sequence_num}.#{$2}" : "#{old_name}_#{sequence_num}"
end

#remove_file(filename) ⇒ Object

Parameters:

  • filename (String)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/dor/models/concerns/contentable.rb', line 82

def remove_file(filename)
  druid_tools = DruidTools::Druid.new(pid, Config.content.content_base_dir)
  location = druid_tools.path(filename)
  oldlocation = location.gsub('/' + pid.gsub('druid:', ''), '')
  sftp = Net::SFTP.start(Config.content.content_server, Config.content.content_user, :auth_methods => ['publickey'])
  begin
    sftp.remove!(location)
  rescue
    # if the file doesnt exist, that is ok, not all files will be present in the workspace
    begin
      sftp.remove!(oldlocation)
    rescue Net::SFTP::StatusException
    end
  end
  .remove_file filename
end

#remove_resource(resource_name) ⇒ Object

Parameters:

  • resource_name (String)

    ID of the resource elememnt



115
116
117
118
119
120
121
122
# File 'lib/dor/models/concerns/contentable.rb', line 115

def remove_resource(resource_name)
  # run delete for all of the files in the resource
  .ng_xml.search('//resource[@id=\'' + resource_name + '\']/file').each do |file|
    remove_file(file['id'])
  end
  # remove the resource record from the metadata and renumber the resource sequence
  .remove_resource resource_name
end

#rename_file(old_name, new_name) ⇒ Object

Parameters:

  • old_name (String)
  • new_name (String)


101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/dor/models/concerns/contentable.rb', line 101

def rename_file(old_name, new_name)
  druid_tools = DruidTools::Druid.new(pid, Config.content.content_base_dir)
  location = druid_tools.path(old_name)
  oldlocation = location.gsub('/' + pid.gsub('druid:', ''), '')
  sftp = Net::SFTP.start(Config.content.content_server, Config.content.content_user, :auth_methods => ['publickey'])
  begin
    sftp.rename!(location, location.gsub(old_name, new_name))
  rescue
    sftp.rename!(oldlocation, oldlocation.gsub(old_name, new_name))
  end
  .rename_file(old_name, new_name)
end

#replace_file(file, file_name) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/dor/models/concerns/contentable.rb', line 42

def replace_file(file, file_name)
  sftp = Net::SFTP.start(Config.content.content_server, Config.content.content_user, :auth_methods => ['publickey'])
  item = Dor.find(pid)
  druid_tools = DruidTools::Druid.new(pid, Config.content.content_base_dir)
  location = druid_tools.path(file_name)
  oldlocation = location.gsub('/' + pid.gsub('druid:', ''), '')
  md5  = Digest::MD5.file(file.path).hexdigest
  sha1 = Digest::SHA1.file(file.path).hexdigest
  size = File.size?(file.path)
  # update contentmd
  file_hash = {:name => file_name, :md5 => md5, :size => size.to_s, :sha1 => sha1}
  begin
    sftp.stat!(location)
    sftp.upload!(file.path, location)
    # this doesnt allow renaming files
    item..update_file(file_hash, file_name)
  rescue
    sftp.upload!(file.path, oldlocation)
    item..update_file(file_hash, file_name)
  end
end