Module: Dor::Processable

Extended by:
ActiveSupport::Concern
Included in:
Abstract
Defined in:
lib/dor/models/concerns/processable.rb

Constant Summary collapse

STATUS_CODE_DISP_TXT =

verbiage we want to use to describe an item when it has completed a particular step

{
  0 => 'Unknown Status', # if there are no milestones for the current version, someone likely messed up the versioning process.
  1 => 'Registered',
  2 => 'In accessioning',
  3 => 'In accessioning (described)',
  4 => 'In accessioning (described, published)',
  5 => 'In accessioning (described, published, deposited)',
  6 => 'Accessioned',
  7 => 'Accessioned (indexed)',
  8 => 'Accessioned (indexed, ingested)',
  9 => 'Opened'
}.freeze
STEPS =

milestones from accessioning and the order they happen in

{
  'registered'  => 1,
  'submitted'   => 2,
  'described'   => 3,
  'published'   => 4,
  'deposited'   => 5,
  'accessioned' => 6,
  'indexed'     => 7,
  'shelved'     => 8,
  'opened'      => 9
}.freeze

Instance Method Summary collapse

Instance Method Details

#build_datastream(datastream, force = false, is_required = false) ⇒ SomeDatastream

Builds that datastream using the content of a file if such a file exists and is newer than the object’s current datastream; otherwise, builds the datastream by calling build_fooMetadata_datastream.

Parameters:

  • datastream (String)

    name of a datastream (e.g. “fooMetadata”)

  • force (Boolean) (defaults to: false)

    overwrite existing datastream

  • is_required (Boolean) (defaults to: false)

Returns:

  • (SomeDatastream)


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/dor/models/concerns/processable.rb', line 73

def build_datastream(datastream, force = false, is_required = false)
  # See if datastream exists as a file and if the file's timestamp is newer than datastream's timestamp.
  ds       = datastreams[datastream]
  filename = (datastream)
  use_file = filename && (ds.createDate.nil? || File.mtime(filename) >= ds.createDate)
  # Build datastream.
  if use_file
    content = File.read(filename)
    ds.content = content
    ds.ng_xml = Nokogiri::XML(content) if ds.respond_to?(:ng_xml)
    ds.save unless ds.digital_object.new?
  elsif force || empty_datastream?(ds)
    meth = "build_#{datastream}_datastream".to_sym
    if respond_to?(meth)
      send(meth, ds)
      ds.save unless ds.digital_object.new?
    end
  end
  # Check for success.
  raise "Required datastream #{datastream} could not be populated!" if is_required && empty_datastream?(ds)
  ds
end

#cleanupObject



96
97
98
# File 'lib/dor/models/concerns/processable.rb', line 96

def cleanup
  CleanupService.cleanup(self)
end

#create_workflow(name, create_ds = true, priority = 0) ⇒ Object

Initilizes workflow for the object in the workflow service

It will set the priorty of the new workflow to the current_priority if it is > 0
It will set lane_id from the item's APO default workflow lane

Parameters:

  • name (String)

    of the workflow to be initialized

  • create_ds (Boolean) (defaults to: true)

    create a ‘workflows’ datastream in Fedora for the object

  • priority (Integer) (defaults to: 0)

    the workflow’s priority level



155
156
157
158
159
160
161
# File 'lib/dor/models/concerns/processable.rb', line 155

def create_workflow(name, create_ds = true, priority = 0)
  priority = workflows.current_priority if priority == 0
  opts = { :create_ds => create_ds, :lane_id => default_workflow_lane }
  opts[:priority] = priority if priority > 0
  Dor::Config.workflow.client.create_workflow(Dor::WorkflowObject.initial_repo(name), pid, name, Dor::WorkflowObject.initial_workflow(name), opts)
  workflows.content(true) # refresh the copy of the workflows datastream
end

#empty_datastream?(datastream) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
52
53
54
55
56
# File 'lib/dor/models/concerns/processable.rb', line 49

def empty_datastream?(datastream)
  return true if datastream.new?
  if datastream.class.respond_to?(:xml_template)
    datastream.content.to_s.empty? || EquivalentXml.equivalent?(datastream.content, datastream.class.xml_template)
  else
    datastream.content.to_s.empty?
  end
end

#find_metadata_file(datastream) ⇒ String?

Tries to find a file for the datastream.

Parameters:

  • datastream (String)

    name of a datastream

Returns:

  • (String, nil)

    path to datastream or nil



61
62
63
64
# File 'lib/dor/models/concerns/processable.rb', line 61

def (datastream)
  druid = DruidTools::Druid.new(pid, Dor::Config.stacks.local_workspace_root)
  druid.("#{datastream}.xml")
end

#initialize_workflow(name, create_ds = true, priority = 0) ⇒ Object



163
164
165
166
# File 'lib/dor/models/concerns/processable.rb', line 163

def initialize_workflow(name, create_ds = true, priority = 0)
  warn 'WARNING: initialize_workflow is deprecated, use create_workflow instead'
  create_workflow(name, create_ds, priority)
end

#milestonesObject



100
101
102
# File 'lib/dor/models/concerns/processable.rb', line 100

def milestones
  @milestones ||= Dor::Config.workflow.client.get_milestones('dor', pid)
end

#set_workflows_datastream_locationObject

This is a work-around for some strange logic in ActiveFedora that don’t allow self.workflows.new? to work if we load the object using .load_instance_from_solr.



42
43
44
45
46
47
# File 'lib/dor/models/concerns/processable.rb', line 42

def set_workflows_datastream_location
  return if self.respond_to?(:inner_object) && inner_object.is_a?(ActiveFedora::SolrDigitalObject)
  return unless workflows.new?
  workflows.mimeType   = 'application/xml'
  workflows.dsLocation = File.join(Dor::Config.workflow.url, "dor/objects/#{pid}/workflows")
end

#status(include_time = false) ⇒ String

Returns single composed status from status_info.

Parameters:

  • include_time (Boolean) (defaults to: false)

Returns:

  • (String)

    single composed status from status_info



137
138
139
140
141
142
143
144
145
146
147
# File 'lib/dor/models/concerns/processable.rb', line 137

def status(include_time = false)
  status_info_hash = status_info
  current_version = status_info_hash[:current_version]
  status_code = status_info_hash[:status_code]
  status_time = status_info_hash[:status_time]

  # use the translation table to get the appropriate verbage for the latest step
  result = "v#{current_version} #{STATUS_CODE_DISP_TXT[status_code]}"
  result += " #{format_date(status_time)}" if include_time
  result
end

#status_infoHash{Symbol => Object}

Returns including :current_version, :status_code and :status_time.

Returns:

  • (Hash{Symbol => Object})

    including :current_version, :status_code and :status_time



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/dor/models/concerns/processable.rb', line 105

def status_info
  current_version = '1'
  begin
    current_version = .current_version_id
  rescue
  end

  current_milestones = []
  # only get steps that are part of accessioning and part of the current version. That can mean they were archived with the current version
  # number, or they might be active (no version number).
  milestones.each do |m|
    if STEPS.keys.include?(m[:milestone]) && (m[:version].nil? || m[:version] == current_version)
      current_milestones << m unless m[:milestone] == 'registered' && current_version.to_i > 1
    end
  end

  status_code = 0
  status_time = nil
  # for each milestone in the current version, see if it comes after the current 'last' step, if so, make it the last and record the date/time
  current_milestones.each do |m|
    m_name = m[:milestone]
    m_time = m[:at].utc.xmlschema
    next unless STEPS.keys.include?(m_name) && (!status_time || m_time > status_time)
    status_code = STEPS[m_name]
    status_time = m_time
  end

  {:current_version => current_version, :status_code => status_code, :status_time => status_time}
end