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” />



235
236
237
# File 'lib/dor/models/concerns/contentable.rb', line 235

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



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
41
42
43
# File 'lib/dor/models/concerns/contentable.rb', line 8

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



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
203
204
205
# File 'lib/dor/models/concerns/contentable.rb', line 161

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 : ”



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

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



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/dor/models/concerns/contentable.rb', line 71

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



67
68
69
# File 'lib/dor/models/concerns/contentable.rb', line 67

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



154
155
156
157
# File 'lib/dor/models/concerns/contentable.rb', line 154

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



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

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



207
208
209
# File 'lib/dor/models/concerns/contentable.rb', line 207

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)


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

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



118
119
120
121
122
123
124
125
# File 'lib/dor/models/concerns/contentable.rb', line 118

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)


104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/dor/models/concerns/contentable.rb', line 104

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



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

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