Module: Dor::Identifiable

Extended by:
ActiveSupport::Concern
Includes:
Eventable, Upgradable, SolrDocHelper
Included in:
Abstract, AdminPolicyObject, Collection, Publishable, Set, WorkflowObject
Defined in:
lib/dor/models/identifiable.rb

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

@@collection_hash =

Module-level variables, shared between ALL mixin includers (and ALL their includers/extenders)! used for caching found values

{}
@@apo_hash =
{}

Instance Method Summary collapse

Methods included from Upgradable

add_upgrade_callback, included, run_upgrade_callbacks, #upgrade!

Methods included from Eventable

#add_event

Methods included from SolrDocHelper

#add_solr_value

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args) ⇒ Object

Syntactic sugar for identifying applied DOR Concerns e.g., obj.is_identifiable? is the same as obj.is_a?(Dor::Identifiable)



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/dor/models/identifiable.rb', line 41

def method_missing(sym, *args)
  if sym.to_s =~ /^is_(.+)\?$/
    begin
      klass = Dor.const_get $1.capitalize.to_sym
      return self.is_a?(klass)
    rescue NameError
      return false
    end
  else
    super
  end
end

Instance Method Details

#add_other_Id(type, val) ⇒ Object



109
110
111
112
113
114
# File 'lib/dor/models/identifiable.rb', line 109

def add_other_Id(type, val)
  if .otherId(type).length > 0
    raise 'There is an existing entry for ' + type + ', consider using update_other_Id().'
  end
  .add_otherId(type + ':' + val)
end

#add_tag(tag) ⇒ Object

Add an administrative tag to an item, you will need to seperately save the item to write it to fedora

Parameters:

  • tag (string)

    The tag you wish to add



178
179
180
181
182
# File 'lib/dor/models/identifiable.rb', line 178

def add_tag(tag)
   = 
  normalized_tag = validate_and_normalize_tag(tag, .tags)
  .add_value(:tag, normalized_tag)
end

#content_type_tagObject

helper method to get just the content type tag



34
35
36
37
# File 'lib/dor/models/identifiable.rb', line 34

def content_type_tag
   = tags.select {|tag| tag.include?('Process : Content Type')}
  .size == 1 ? [0].split(':').last.strip : ''
end

#druid_regexRegex

a regex that can be used to identify a full druid with prefix (e.g. druid:oo000oo0001)

Returns:

  • (Regex)

    a regular expression to identify a full druid



216
217
218
# File 'lib/dor/models/identifiable.rb', line 216

def druid_regex
  /druid:#{pid_regex}/
end


200
201
202
203
204
205
206
# File 'lib/dor/models/identifiable.rb', line 200

def get_related_obj_display_title(related_obj, default_title)
  return default_title unless related_obj

  desc_md_ds = related_obj.datastreams['descMetadata']
  desc_md_ds_title = desc_md_ds ? desc_md_ds.title_info.main_title.first : nil
  desc_md_ds_title.present? ? desc_md_ds_title : default_title
end

#identity_metadata_sourceString

Returns calculated value for Solr index.

Returns:

  • (String)

    calculated value for Solr index



83
84
85
86
87
88
89
90
91
92
# File 'lib/dor/models/identifiable.rb', line 83

def 
  if .otherId('catkey').first ||
     .otherId('barcode').first
    'Symphony'
  elsif .otherId('mdtoolkit').first
    'Metadata Toolkit'
  else
    'DOR'
  end
end

#initialize(attrs = {}) ⇒ Object



21
22
23
24
25
26
# File 'lib/dor/models/identifiable.rb', line 21

def initialize(attrs = {})
  if Dor::Config.suri.mint_ids && !attrs[:pid]
    attrs = attrs.merge!({:pid => Dor::SuriService.mint_id, :new_object => true})
  end
  super
end

#normalize_tag(tag_str) ⇒ Object

take a tag string and return a normalized tag string



142
143
144
# File 'lib/dor/models/identifiable.rb', line 142

def normalize_tag(tag_str)
  normalize_tag_arr(split_tag_to_arr(tag_str))
end

#normalize_tag_arr(tag_arr) ⇒ Object

turn a tag array back into a tag string with a standard format



137
138
139
# File 'lib/dor/models/identifiable.rb', line 137

def normalize_tag_arr(tag_arr)
  tag_arr.join(' : ')
end

#pid_regexRegex

a regex that can be used to identify the last part of a druid (e.g. oo000oo0001)

Returns:

  • (Regex)

    a regular expression to identify the ID part of the druid



210
211
212
# File 'lib/dor/models/identifiable.rb', line 210

def pid_regex
  /[a-zA-Z]{2}[0-9]{3}[a-zA-Z]{2}[0-9]{4}/
end

#remove_druid_prefix(druid = id) ⇒ String

Since purl does not use the druid: prefix but much of dor does, use this function to strip the druid: if needed

Returns:

  • (String)

    the druid sans the druid: or if there was no druid: prefix, the entire string you passed



222
223
224
225
# File 'lib/dor/models/identifiable.rb', line 222

def remove_druid_prefix(druid=id)
  result=druid.match(/#{pid_regex}/)
  result.nil? ? druid : result[0]  # if no matches, return the string passed in, otherwise return the match 
end

#remove_other_Id(type, val = nil) ⇒ Object



123
124
125
126
127
128
# File 'lib/dor/models/identifiable.rb', line 123

def remove_other_Id(type, val = nil)
  .ng_xml.search('//otherId[@name=\'' + type + '\']')
    .select { |node| val.nil? || node.content == val }
    .each(&:remove)
    .any?
end

#remove_tag(tag) ⇒ Object



184
185
186
187
188
189
190
# File 'lib/dor/models/identifiable.rb', line 184

def remove_tag(tag)
  normtag = normalize_tag(tag)
  .ng_xml.search('//tag')
    .select { |node| normalize_tag(node.content) == normtag }
    .each(&:remove)
    .any?
end

#source_idObject

Convenience method



95
96
97
# File 'lib/dor/models/identifiable.rb', line 95

def source_id
  .sourceId
end

#source_id=(source_id) ⇒ String Also known as: set_source_id

Convenience method

Parameters:

  • source_id (String)

    the new source identifier

Returns:

  • (String)

    same value, as per Ruby assignment convention

Raises:

  • (ArgumentError)

    see IdentityMetadataDS for logic



103
104
105
# File 'lib/dor/models/identifiable.rb', line 103

def source_id=(source_id)
  .sourceId = source_id
end

#split_tag_to_arr(tag_str) ⇒ Object

turns a tag string into an array with one element per tag part. split on “:”, disregard leading and trailing whitespace on tokens.



132
133
134
# File 'lib/dor/models/identifiable.rb', line 132

def split_tag_to_arr(tag_str)
  tag_str.split(':').map {|str| str.strip}
end

#tagsObject

helper method to get the tags as an array



29
30
31
# File 'lib/dor/models/identifiable.rb', line 29

def tags
  .tag
end

#to_solr(solr_doc = {}, *args) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/dor/models/identifiable.rb', line 59

def to_solr(solr_doc = {}, *args)
  assert_content_model
  super(solr_doc, *args)

  solr_doc[Dor::INDEX_VERSION_FIELD] = Dor::VERSION
  solr_doc['indexed_at_dtsi'] = Time.now.utc.xmlschema
  datastreams.values.each do |ds|
    add_solr_value(solr_doc, 'ds_specs', ds.datastream_spec_string, :string, [:symbol]) unless ds.new?
  end

  add_solr_value(solr_doc, 'title_sort', label, :string, [:stored_sortable])

  rels_doc = Nokogiri::XML(datastreams['RELS-EXT'].content)
  ns_hash = {'hydra' => 'http://projecthydra.org/ns/relations#', 'fedora' => 'info:fedora/fedora-system:def/relations-external#', 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'}
  apos = rels_doc.search('//rdf:RDF/rdf:Description/hydra:isGovernedBy', ns_hash)
  collections = rels_doc.search('//rdf:RDF/rdf:Description/fedora:isMemberOfCollection', ns_hash)
  solrize_related_obj_titles(solr_doc, apos, @@apo_hash, 'apo_title', 'nonhydrus_apo_title', 'hydrus_apo_title')
  solrize_related_obj_titles(solr_doc, collections, @@collection_hash, 'collection_title', 'nonhydrus_collection_title', 'hydrus_collection_title')

  solr_doc['metadata_source_ssi'] = 
  solr_doc
end

#update_other_Id(type, new_val, val = nil) ⇒ Object



116
117
118
119
120
121
# File 'lib/dor/models/identifiable.rb', line 116

def update_other_Id(type, new_val, val = nil)
  .ng_xml.search('//otherId[@name=\'' + type + '\']')
    .select { |node| val.nil? || node.content == val }
    .each  { |node| node.content = new_val }
    .any?
end

#update_tag(old_tag, new_tag) ⇒ Object



192
193
194
195
196
197
198
# File 'lib/dor/models/identifiable.rb', line 192

def update_tag(old_tag, new_tag)
  normtag = normalize_tag(old_tag)
  .ng_xml.search('//tag')
    .select { |node| normalize_tag(node.content) == normtag }
    .each  { |node| node.content = normalize_tag(new_tag)  }
    .any?
end

#validate_and_normalize_tag(tag_str, existing_tag_list) ⇒ Object

take a proposed tag string and a list of the existing tags for the object being edited. if the proposed tag is valid, return it in normalized form. if not, raise an exception with an explanatory message.



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/dor/models/identifiable.rb', line 149

def validate_and_normalize_tag(tag_str, existing_tag_list)
  tag_arr = validate_tag_format(tag_str)

  # note that the comparison for duplicate tags is case-insensitive, but we don't change case as part of the normalized version
  # we return, because we want to preserve the user's intended case.
  normalized_tag = normalize_tag_arr(tag_arr)
  dupe_existing_tag = existing_tag_list.detect { |existing_tag| normalize_tag(existing_tag).casecmp(normalized_tag) == 0 }
  if dupe_existing_tag
    raise "An existing tag (#{dupe_existing_tag}) is the same, consider using update_tag?"
  end
  normalized_tag
end

#validate_tag_format(tag_str) ⇒ Array

Ensure that an administrative tag meets the proper mininum format

Parameters:

  • tag_str (String)

    the tag

Returns:

  • (Array)

    the tag split into an array via ‘:’



165
166
167
168
169
170
171
172
173
174
# File 'lib/dor/models/identifiable.rb', line 165

def validate_tag_format(tag_str)
  tag_arr = split_tag_to_arr(tag_str)
  if tag_arr.length < 2
    raise ArgumentError, "Invalid tag structure: tag '#{tag_str}' must have at least 2 elements"
  end
  if tag_arr.detect {|str| str.empty?}
    raise ArgumentError, "Invalid tag structure: tag '#{tag_str}' contains empty elements"
  end
  tag_arr
end