Class: Identifier::Global

Inherits:
Identifier show all
Includes:
Shared::DwcOccurrenceHooks, SoftValidation
Defined in:
app/models/identifier/global.rb

Overview

The identifier that is globally unique.

Curators of a specific project assert one canonical global identifier per type for each object, this identifier is identified by having .relation.nil?. If the curators feel there are multiple global identifiers for a given instance they must provide an explicit relationship between the canonical identifier and the alternate identifiers.

Defined Under Namespace

Classes: Doi, GenBankAccessionCode, Isbn, Issn, Lccn, Lsid, MorphbankSpecimenNumber, Orcid, Uri, Uuid, WebOfScience, Wikidata, ZoologicalRecord

Constant Summary

Constants included from SoftValidation

SoftValidation::ANCESTORS_WITH_SOFT_VALIDATIONS

Constants included from Shared::DualAnnotator

Shared::DualAnnotator::ALWAYS_COMMUNITY

Instance Attribute Summary collapse

Attributes inherited from Identifier

#cached, #cached_numeric_identifier, #identifier, #identifier_object_id, #namespace_id, #project_id, #type

Instance Method Summary collapse

Methods included from SoftValidation

#clear_soft_validations, #fix_for, #fix_soft_validations, #soft_fixed?, #soft_valid?, #soft_validate, #soft_validated?, #soft_validations, #soft_validators

Methods inherited from Identifier

#build_cached_numeric_identifier, #is_local?, prototype_identifier, #set_cached, #type_name

Methods included from Shared::IsData

#errors_excepting, #full_error_messages_excepting, #identical, #is_community?, #is_destroyable?, #is_editable?, #is_in_use?, #is_in_users_projects?, #metamorphosize, #similar

Methods included from Shared::Labels

#labeled?

Methods included from Housekeeping

#has_polymorphic_relationship?

Methods included from Shared::PolymorphicAnnotator

#annotated_object_is_persisted?

Methods inherited from ApplicationRecord

transaction_with_retry

Instance Attribute Details

#relationString

Defines the relationship between the curator asserted canonical identifier and other identifiers of the same type. Must be provided for every global identifier of the same type beyond the first. Relations are drawn from skos (www.w3.org/TR/skos-reference/#mapping)

Returns:

  • (String)


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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/models/identifier/global.rb', line 14

class Identifier::Global < Identifier

  include SoftValidation

  # Only implemented for a couple, but for now DRYer to keep here
  include Shared::DwcOccurrenceHooks

  validates :namespace_id, absence: true
 
  # DEPRECATED: unused in 10 years, benefit seems doubtful.
  validates :relation, inclusion: {in: ::SKOS_RELATIONS.keys}, allow_nil: true

  # Identifier can only be used once, i.e. mapped to a single TW concept
  validates_uniqueness_of :identifier, scope: [:project_id]

  soft_validate(:sv_resolves?, set: :resolved)

  def is_global?
    true
  end

  def dwc_occurrences

    return DwcOccurrence.none unless %w{
     Identifier::Global::Wikidata
     Identifier::Global::Orcid
    }.include?(type)

    # Collectors
    a = DwcOccurrence.joins("JOIN collection_objects co on dwc_occurrence_object_id = co.id AND dwc_occurrence_object_type = 'CollectionObject'")
      .joins('JOIN collecting_events ce on co.collecting_event_id = ce.id')
      .joins("JOIN roles r on r.type = 'Collector' AND r.role_object_type = 'CollectingEvent' AND r.role_object_id = ce.id")
      .joins("JOIN identifiers i on i.identifier_object_id = r.person_id AND i.identifier_object_type = 'Person' AND i.type =  '#{type}' ")
      .where(i: {id:})
      .distinct

    # Determiners
    b = DwcOccurrence
      .joins("JOIN collection_objects co on dwc_occurrence_object_id = co.id AND dwc_occurrence_object_type = 'CollectionObject'")
      .joins("JOIN taxon_determinations td on co.id = td.taxon_determination_object_id AND td.taxon_determination_object_type = 'CollectionObject'")
      .joins("JOIN roles r on r.type = 'Determiner' AND r.role_object_type = 'TaxonDetermination' AND r.role_object_id = td.id")
      .joins("JOIN identifiers i on i.identifier_object_id = r.person_id AND i.identifier_object_type = 'Person' AND i.type = '#{type}'")
      .where(r: {id:})
      .distinct

    ::Queries.union(::DwcOccurrence, [a,b])
  end

  protected

  def build_cached
    identifier
  end

  # TODO: add a resolution method so that this works on theings like wikidata Q numbers
  def sv_resolves?
    responded = identifier.present? && (Utilities::Net.resolves?(identifier) rescue false)
    soft_validations.add(:identifier, "Identifier '#{identifier}' does not resolve.") unless responded
    responded
  end

end

Instance Method Details

#build_cachedObject (protected)



64
65
66
# File 'app/models/identifier/global.rb', line 64

def build_cached
  identifier
end

#dwc_occurrencesObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/models/identifier/global.rb', line 35

def dwc_occurrences

  return DwcOccurrence.none unless %w{
   Identifier::Global::Wikidata
   Identifier::Global::Orcid
  }.include?(type)

  # Collectors
  a = DwcOccurrence.joins("JOIN collection_objects co on dwc_occurrence_object_id = co.id AND dwc_occurrence_object_type = 'CollectionObject'")
    .joins('JOIN collecting_events ce on co.collecting_event_id = ce.id')
    .joins("JOIN roles r on r.type = 'Collector' AND r.role_object_type = 'CollectingEvent' AND r.role_object_id = ce.id")
    .joins("JOIN identifiers i on i.identifier_object_id = r.person_id AND i.identifier_object_type = 'Person' AND i.type =  '#{type}' ")
    .where(i: {id:})
    .distinct

  # Determiners
  b = DwcOccurrence
    .joins("JOIN collection_objects co on dwc_occurrence_object_id = co.id AND dwc_occurrence_object_type = 'CollectionObject'")
    .joins("JOIN taxon_determinations td on co.id = td.taxon_determination_object_id AND td.taxon_determination_object_type = 'CollectionObject'")
    .joins("JOIN roles r on r.type = 'Determiner' AND r.role_object_type = 'TaxonDetermination' AND r.role_object_id = td.id")
    .joins("JOIN identifiers i on i.identifier_object_id = r.person_id AND i.identifier_object_type = 'Person' AND i.type = '#{type}'")
    .where(r: {id:})
    .distinct

  ::Queries.union(::DwcOccurrence, [a,b])
end

#is_global?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'app/models/identifier/global.rb', line 31

def is_global?
  true
end

#sv_resolves?Boolean (protected)

TODO: add a resolution method so that this works on theings like wikidata Q numbers

Returns:

  • (Boolean)


69
70
71
72
73
# File 'app/models/identifier/global.rb', line 69

def sv_resolves?
  responded = identifier.present? && (Utilities::Net.resolves?(identifier) rescue false)
  soft_validations.add(:identifier, "Identifier '#{identifier}' does not resolve.") unless responded
  responded
end