Class: Document

Inherits:
Kithe::Work
  • Object
show all
Includes:
ActiveModel::Validations, AttrJson::Record::QueryScopes
Defined in:
app/models/document.rb,
app/models/document/reference.rb,
app/models/document/bbox_validator.rb,
app/models/document/date_validator.rb,
app/models/document/geom_validator.rb,
app/models/document/controlled_lists.rb,
app/models/document/date_range_validator.rb

Overview

Date Range Validation

Allow: YYYY-YYYY, *-YYYY, YYYY-*, Start YYYY == End YYYY Disallow: YYYX-YYYY, YYYY-, 2000-1999, YYYY-YYYY?

Defined Under Namespace

Classes: BboxValidator, ControlledLists, DateRangeValidator, DateValidator, GeomValidator, Reference

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#skip_callbacksObject

Returns the value of attribute skip_callbacks.



15
16
17
# File 'app/models/document.rb', line 15

def skip_callbacks
  @skip_callbacks
end

Instance Method Details

#a_downloadable_resource?Boolean

Downloadable Resouce

Returns:

  • (Boolean)


89
90
91
# File 'app/models/document.rb', line 89

def a_downloadable_resource?
  references_json.include?("downloadUrl")
end

#access_jsonObject



346
347
348
349
350
# File 'app/models/document.rb', line 346

def access_json
  access = {}
  access_urls.each { |au| access[au.institution_code] = au.access_url }
  access.to_json
end

#access_urlsObject

Institutional Access URLs



423
424
425
# File 'app/models/document.rb', line 423

def access_urls
  DocumentAccess.where(friendlier_id: friendlier_id).order(institution_code: :asc)
end

#apply_downloads(references) ⇒ Object

Apply Downloads

  1. Native Aardvark Downloads

  2. Multiple Document Download Links

  3. Downloadable Document Assets



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
206
207
208
209
210
# File 'app/models/document.rb', line 162

def apply_downloads(references)
  multiple_downloads = []

  dct_downloads = references["http://schema.org/downloadUrl"]

  logger.debug("Document#dct_downloads > init: #{dct_downloads}\n\n")

  # Native Aardvark Downloads
  # - Via CSV Import or via the webform
  if dct_downloads.present?
    dct_downloads.each do |download|
      multiple_downloads << {label: download_text(send(GeoblacklightAdmin::Schema.instance.solr_fields[:format])),
                            url: download}
    end
  end

  logger.debug("Document#multiple_downloads > aardvark: #{multiple_downloads.inspect}\n\n")

  # Multiple Document Download Links
  # - Via DocumentDownloads
  if document_downloads.present?
    multiple_downloads << multiple_downloads_array
  end

  logger.debug("Document#dct_downloads > document_downloads: #{multiple_downloads.inspect}\n\n")

  # Downloadable Document Assets
  # - Via DocumentAssets (Assets)
  # - With Downloadable URI
  if downloadable_assets.present?
    downloadable_assets.each do |asset|
      logger.debug("\n\n Document#dct_downloads > dupe?: #{multiple_downloads.detect { |d| d[:url].include?(asset.file.url) }}\n\n")

      if multiple_downloads.detect { |d| d[:url].include?(asset.file.url) }
        logger.debug("\n\n Detected duplicate download URL: #{asset.file.url}\n\n")
        index = multiple_downloads.index { |d| d[:url].include?(asset.file.url) }
        multiple_downloads[index] = {label: asset_label(asset), url: asset.file.url}
      else
        logger.debug("\n\n No duplicate found - Adding downloadable asset: #{asset.file.url}\n\n")
        multiple_downloads << {label: asset_label(asset), url: asset.file.url}
      end
    end
  end

  logger.debug("Document#dct_downloads > downloadable_assets: #{multiple_downloads.inspect}\n\n")

  references[:"http://schema.org/downloadUrl"] = multiple_downloads.flatten unless multiple_downloads.empty?
  references
end

#asset_label(asset) ⇒ Object



150
151
152
153
154
155
156
# File 'app/models/document.rb', line 150

def asset_label(asset)
  if asset.label.present?
    asset.label
  else
    asset.title
  end
end

#available?Boolean

GBL SolrDocument convience methods

Returns:

  • (Boolean)


246
247
248
# File 'app/models/document.rb', line 246

def available?
  public? || same_institution?
end

#checked_endpoint(type) ⇒ Object

Provides a convenience method to access a SolrDocument’s References endpoint url without having to check and see if it is available :type => a string which if its a Geoblacklight::Constants::URI key

will return a coresponding Geoblacklight::Reference


334
335
336
337
# File 'app/models/document.rb', line 334

def checked_endpoint(type)
  type = references.send(type)
  type.endpoint if type.present?
end

#created_at_dtObject



352
353
354
# File 'app/models/document.rb', line 352

def created_at_dt
  created_at&.utc&.iso8601
end

#current_versionObject



417
418
419
420
# File 'app/models/document.rb', line 417

def current_version
  # Will return 0 if no PaperTrail version exists yet
  versions&.last&.index || 0
end

#data_dictionary_downloadObject



300
301
302
# File 'app/models/document.rb', line 300

def data_dictionary_download
  references.data_dictionary.to_hash if references.data_dictionary.present?
end

#date_range_jsonObject



365
366
367
368
369
370
371
372
373
374
375
376
# File 'app/models/document.rb', line 365

def date_range_json
  date_ranges = []
  unless send(GeoblacklightAdmin::Schema.instance.solr_fields[:date_range]).all?(&:blank?)
    send(GeoblacklightAdmin::Schema.instance.solr_fields[:date_range]).each do |date_range|
      start_d, end_d = date_range.split("-")
      start_d = "*" if start_d == "YYYY" || start_d.nil?
      end_d = "*" if end_d == "YYYY" || end_d.nil?
      date_ranges << "[#{start_d} TO #{end_d}]" if start_d.present?
    end
  end
  date_ranges
end

#dct_references_s_to_csv(key, destination) ⇒ Object



409
410
411
412
413
414
415
# File 'app/models/document.rb', line 409

def dct_references_s_to_csv(key, destination)
  send(destination).detect do |ref|
    ref.category == GeoblacklightAdmin::Schema.instance.dct_references_mappings[key]
  end.value
rescue NoMethodError
  nil
end

#dct_title_sObject

Ensures a manually created “title” makes it into the attr_json “title”



361
362
363
# File 'app/models/document.rb', line 361

def dct_title_s
  title
end

#derive_dcat_bboxObject

Convert GEOM for Solr Indexing



460
461
462
463
464
465
466
467
468
# File 'app/models/document.rb', line 460

def derive_dcat_bbox
  if send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]).present?
    # "W,S,E,N" convert to "ENVELOPE(W,E,N,S)"
    w, s, e, n = send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]).split(",")
    "ENVELOPE(#{w},#{e},#{n},#{s})"
  else
    ""
  end
end

#derive_dcat_centroidObject



470
471
472
473
474
475
476
477
# File 'app/models/document.rb', line 470

def derive_dcat_centroid
  if send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]).present?
    w, s, e, n = send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]).split(",")
    "#{(n.to_f + s.to_f) / 2},#{(e.to_f + w.to_f) / 2}"
  else
    ""
  end
end

#derive_locn_geometryObject



427
428
429
430
431
432
433
434
435
# File 'app/models/document.rb', line 427

def derive_locn_geometry
  if send(GeoblacklightAdmin::Schema.instance.solr_fields[:geometry]).present?
    send(GeoblacklightAdmin::Schema.instance.solr_fields[:geometry])
  elsif send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]).present?
    derive_polygon
  else
    ""
  end
end

#derive_polygonObject

Convert BBOX to GEOM Polygon



438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'app/models/document.rb', line 438

def derive_polygon
  if send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]).present?
    # Guard against a whole world polygons
    if send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]) == "-180,-90,180,90"
      "ENVELOPE(-180,180,90,-90)"
    else
      # "W,S,E,N" convert to "POLYGON((W N, E N, E S, W S, W N))"
      w, s, e, n = send(GeoblacklightAdmin::Schema.instance.solr_fields[:bounding_box]).split(",")
      "POLYGON((#{w} #{n}, #{e} #{n}, #{e} #{s}, #{w} #{s}, #{w} #{n}))"
    end
  else
    ""
  end
end

#direct_downloadObject



275
276
277
# File 'app/models/document.rb', line 275

def direct_download
  references.download.to_hash if references.download.present?
end

#display_noteObject



279
280
281
# File 'app/models/document.rb', line 279

def display_note
  send(Settings.FIELDS.DISPLAY_NOTE) || ""
end

#document_assetsObject

DocumentAssets - Thumbnails, Attachments, etc @TODO: Redundant? Kithe also includes a members association



39
40
41
42
43
44
45
# File 'app/models/document.rb', line 39

def document_assets
  scope = Kithe::Asset
  scope = scope.where(parent_id: id)

  # scope = scope.page(params[:page]).per(20).order(created_at: :desc)
  scope.includes(:parent)
end

#download_text(format) ⇒ Object

Wraps download text with proper_case_format



231
232
233
234
235
236
237
238
239
240
241
# File 'app/models/document.rb', line 231

def download_text(format)
  download_format = proper_case_format(format)
  prefix = "Original "
  begin
    format = download_format
  rescue
    # Need to rescue if format doesn't exist
  end
  value = prefix + format.to_s
  value.html_safe
end

#downloadable?Boolean

Returns:

  • (Boolean)


271
272
273
# File 'app/models/document.rb', line 271

def downloadable?
  (direct_download || download_types.present? || iiif_download) && available?
end

#downloadable_assetsObject



47
48
49
# File 'app/models/document.rb', line 47

def downloadable_assets
  document_assets.select { |a| a.dct_references_uri_key == "download" }
end

#external_urlObject



304
305
306
# File 'app/models/document.rb', line 304

def external_url
  references.url&.endpoint
end

#file_formatObject



325
326
327
# File 'app/models/document.rb', line 325

def file_format
  send(Settings.FIELDS.FORMAT) || ""
end

#gbl_mdModified_dtObject



356
357
358
# File 'app/models/document.rb', line 356

def gbl_mdModified_dt
  updated_at&.utc&.iso8601
end

#geom_fieldObject



312
313
314
# File 'app/models/document.rb', line 312

def geom_field
  send(Settings.FIELDS.GEOMETRY) || ""
end

#geometryObject



316
317
318
319
# File 'app/models/document.rb', line 316

def geometry
  # @TODO
  # @geometry ||= Geoblacklight::Geometry.new(geom_field)
end

#hgl_downloadObject



283
284
285
# File 'app/models/document.rb', line 283

def hgl_download
  references.hgl.to_hash if references.hgl.present?
end

#iiif_downloadObject



296
297
298
# File 'app/models/document.rb', line 296

def iiif_download
  references.iiif.to_hash if references.iiif.present?
end

#iso_language_mappingObject

Convert three char language code to proper string



480
481
482
483
484
485
486
487
488
489
# File 'app/models/document.rb', line 480

def iso_language_mapping
  mapping = []

  if send(GeoblacklightAdmin::Schema.instance.solr_fields[:language]).present?
    send(GeoblacklightAdmin::Schema.instance.solr_fields[:language]).each do |lang|
      mapping << GeoblacklightAdmin::IsoLanguageCodes.call[lang]
    end
  end
  mapping
end

#item_viewerObject



11
12
13
# File 'app/models/document.rb', line 11

def item_viewer
  GeoblacklightAdmin::ItemViewer.new(references)
end

#itemtypeObject



308
309
310
# File 'app/models/document.rb', line 308

def itemtype
  "http://schema.org/Dataset"
end

#local?Boolean

Returns:

  • (Boolean)


258
259
260
261
# File 'app/models/document.rb', line 258

def local?
  local = send(Settings.FIELDS.PROVIDER) || ""
  local.casecmp(Settings.INSTITUTION)&.zero?
end

#local_restricted?Boolean

Returns:

  • (Boolean)


254
255
256
# File 'app/models/document.rb', line 254

def local_restricted?
  local? && restricted?
end

#multiple_downloads_arrayObject



212
213
214
# File 'app/models/document.rb', line 212

def multiple_downloads_array
  document_downloads.collect { |d| {label: d.label, url: d.value} }
end

#oembedObject



287
288
289
# File 'app/models/document.rb', line 287

def oembed
  references.oembed.endpoint if references.oembed.present?
end

#proper_case_format(format) ⇒ Object

From GBL

Looks up properly formatted names for formats



220
221
222
223
224
225
226
# File 'app/models/document.rb', line 220

def proper_case_format(format)
  if I18n.exists?("geoblacklight.formats.#{format.to_s.parameterize(separator: "_")}")
    I18n.t("geoblacklight.formats.#{format.to_s.parameterize(separator: "_")}")
  else
    format
  end
end

#public?Boolean

Returns:

  • (Boolean)


250
251
252
# File 'app/models/document.rb', line 250

def public?
  rights_field_data.present? && rights_field_data.casecmp("public").zero?
end

#raw_solr_documentObject



70
71
72
# File 'app/models/document.rb', line 70

def raw_solr_document
  Blacklight.default_index.connection.get("select", {params: {q: "id:\"#{geomg_id_s}\""}})["response"]["docs"][0]
end

#referencesObject

Index Transformations - *_json functions



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/models/document.rb', line 112

def references
  references = ActiveSupport::HashWithIndifferentAccess.new

  # Prep value arrays
  send(GeoblacklightAdmin::Schema.instance.solr_fields[:reference]).each do |ref|
    references[Document::Reference::REFERENCE_VALUES[ref.category.to_sym][:uri]] = []
  end

  # Seed value arrays
  send(GeoblacklightAdmin::Schema.instance.solr_fields[:reference]).each do |ref|
    # @TODO: Need to support multiple entries per key here
    references[Document::Reference::REFERENCE_VALUES[ref.category.to_sym][:uri]] << ref.value
  end

  logger.debug("\n\nDocument#references > seeded: #{references}")

  # Apply Downloads
  references = apply_downloads(references)

  logger.debug("Document#references > downloads: #{references}\n\n")

  # Need to flatten the arrays here to avoid the following potential error:
  # - ArgumentError: Please use symbols for polymorphic route arguments.
  # - Via: app/helpers/geoblacklight_helper.rb:224:in `render_references_url'
  references.each do |key, value|
    next if key == "http://schema.org/downloadUrl"
    if value.is_a?(Array) && value.length == 1
      references[key] = value.first
    end
  end

  references
end

#references_jsonObject



146
147
148
# File 'app/models/document.rb', line 146

def references_json
  references.to_json
end

#restricted?Boolean

Returns:

  • (Boolean)


263
264
265
# File 'app/models/document.rb', line 263

def restricted?
  rights_field_data.blank? || rights_field_data.casecmp("restricted").zero?
end

#rights_field_dataObject



267
268
269
# File 'app/models/document.rb', line 267

def rights_field_data
  send(Settings.FIELDS.ACCESS_RIGHTS) || ""
end

#same_institution?Boolean

Returns:

  • (Boolean)


291
292
293
294
# File 'app/models/document.rb', line 291

def same_institution?
  institution = send(Settings.FIELDS.PROVIDER) || ""
  institution.casecmp(Settings.INSTITUTION.downcase).zero?
end

#set_geometryObject



453
454
455
456
457
# File 'app/models/document.rb', line 453

def set_geometry
  return unless locn_geometry.blank? && self&.dcat_bbox&.present?

  self.locn_geometry = derive_polygon
end

#solr_year_jsonObject Also known as: gbl_indexYear_im



378
379
380
381
382
383
# File 'app/models/document.rb', line 378

def solr_year_json
  return [] if send(GeoblacklightAdmin::Schema.instance.solr_fields[:date_range]).blank?

  start_d, _end_d = send(GeoblacklightAdmin::Schema.instance.solr_fields[:date_range]).first.split("-")
  [start_d] if start_d.presence
end

#state_machineObject

@TODO: Rename this to publication_state_machine



57
58
59
# File 'app/models/document.rb', line 57

def state_machine
  @state_machine ||= DocumentStateMachine.new(self, transition_class: DocumentTransition)
end

#thumbnailObject

Thumbnail is a special case of document_assets



342
343
344
# File 'app/models/document.rb', line 342

def thumbnail
  members.find { |m| m.respond_to?(:thumbnail) && m.thumbnail? }
end

#thumbnail_state_machineObject



66
67
68
# File 'app/models/document.rb', line 66

def thumbnail_state_machine
  @thumbnail_state_machine ||= DocumentThumbnailStateMachine.new(self, transition_class: DocumentThumbnailTransition)
end

#to_csvObject

Export Transformations - to_*



387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'app/models/document.rb', line 387

def to_csv
  attributes = GeoblacklightAdmin::Schema.instance.exportable_fields
  attributes.map do |key, value|
    if value[:delimited]
      send(value[:destination])&.join("|")
    elsif value[:destination] == "dct_references_s"
      # @TODO: Downloads need to be handled differently
      # - Need to support multiple entries per key here
      # - Need to respect label and url
      dct_references_s_to_csv(key, value[:destination])
    elsif value[:destination] == "b1g_publication_state_s"
      send(:current_state)
    else
      send(value[:destination])
    end
  end
end

#to_trajectObject



405
406
407
# File 'app/models/document.rb', line 405

def to_traject
  Kithe::Model.find_by_friendlier_id(friendlier_id).update_index(writer: Traject::DebugWriter.new({}))
end

#wxs_identifierObject



321
322
323
# File 'app/models/document.rb', line 321

def wxs_identifier
  send(Settings.FIELDS.WXS_IDENTIFIER) || ""
end