Skip to content

Commit

Permalink
Create a set of local models
Browse files Browse the repository at this point in the history
These models are routable and mutable so the work more like rails defaults unlikethe dry-struct models
  • Loading branch information
jcoyne committed Apr 12, 2022
1 parent 126bd77 commit 3dff47c
Show file tree
Hide file tree
Showing 12 changed files with 646 additions and 0 deletions.
24 changes: 24 additions & 0 deletions app/models/access_template.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

class AccessTemplate < ApplicationModel
define_attribute_methods :license, :copyright, :use_statement, :view, :download

attribute :license
attribute :copyright
attribute :use_statement
attribute :view
attribute :download

def initialize(cocina_model = Cocina::Models::AdminPolicyAccessTemplate.new)
super
end

# When the object is initialized, copy the properties from the cocina model to the entity:
def setup_properties!
self.license = model.license
self.copyright = model.copyright
self.use_statement = model.useAndReproductionStatement
self.view = model.view
self.download = model.download
end
end
36 changes: 36 additions & 0 deletions app/models/admin_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

class AdminPolicy < ApplicationModel
define_attribute_methods :id, :version, :label, :admin_policy_id,
:registration_workflows, :collections_for_registration, :access_template, :roles

attribute :id
attribute :version
attribute :label
attribute :admin_policy_id
attribute :registration_workflows
attribute :collections_for_registration
attribute :access_template
attribute :roles

# When the object is initialized, copy the properties from the cocina model to the entity:
def setup_properties!
self.id = model.externalIdentifier
self.version = model.version
self.label = model.label
self.admin_policy_id = model.administrative.hasAdminPolicy
self.registration_workflows = model.administrative.registrationWorkflow
self.collections_for_registration = model.administrative.collectionsForRegistration
self.access_template = AccessTemplate.new(model.administrative.accessTemplate)
self.roles = model.administrative.roles
end

def save
raise 'not implemented'
# @model = AdminPolicyChangeSetPersister.update(model, self)
end

def self.model_name
::ActiveModel::Name.new(nil, nil, 'AdminPolicy')
end
end
31 changes: 31 additions & 0 deletions app/models/application_model.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

# @abstract
class ApplicationModel
include ActiveModel::Dirty
include ActiveModel::API

def self.attribute(name)
define_method name do
instance_variable_get(:"@#{name}")
end

define_method :"#{name}=" do |val|
send(:"#{name}_will_change!") unless val == instance_variable_get(:"@#{name}")
instance_variable_set(:"@#{name}", val)
end
end

def initialize(cocina = nil)
@model = cocina
setup_properties!
clear_changes_information
end

# The original cocina data
attr_reader :model

def persisted?
id.present?
end
end
39 changes: 39 additions & 0 deletions app/models/collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

class Collection < ApplicationModel
define_attribute_methods :id, :version, :admin_policy_id, :catkeys, :copyright,
:license, :source_id, :use_statement, :view_access

attribute :id
attribute :version
attribute :admin_policy_id
attribute :catkeys
attribute :copyright
attribute :license
attribute :source_id
attribute :use_statement
attribute :view_access

# When the object is initialized, copy the properties from the cocina model to the form:
def setup_properties!
self.id = model.externalIdentifier
self.version = model.version
self.admin_policy_id = model.administrative.hasAdminPolicy

self.catkeys = Catkey.symphony_links(model) if model.identification
self.copyright = model.access.copyright
self.use_statement = model.access.useAndReproductionStatement
self.license = model.access.license
self.source_id = model.identification&.sourceId

self.view_access = model.access.view
end

def save
@model = CollectionPersister.update(model, self)
end

def self.model_name
::ActiveModel::Name.new(nil, nil, 'Collection')
end
end
18 changes: 18 additions & 0 deletions app/models/embargo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

class Embargo < ApplicationModel
define_attribute_methods :release_date, :view_access, :download_access, :access_location

attribute :release_date
attribute :view_access
attribute :download_access
attribute :access_location

# When the object is initialized, copy the properties from the cocina model to the entity:
def setup_properties!
self.release_date = model.releaseDate
self.view_access = model.view
self.download_access = model.download
self.access_location = model.location
end
end
21 changes: 21 additions & 0 deletions app/models/file_set.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

class FileSet < ApplicationModel
define_attribute_methods :files, :type, :label

attribute :files
attribute :type
attribute :label

# When the object is initialized, copy the properties from the cocina model to the entity:
def setup_properties!
self.type = model.type
self.label = model.label
self.files = model.structural.contains.map { |cocina| ManagedFile.new(cocina) }
end

# has the collection or any of its members changed?
def changed?
super || files.any?(&:changed?)
end
end
78 changes: 78 additions & 0 deletions app/models/item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# frozen_string_literal: true

class Item < ApplicationModel
define_attribute_methods :id, :version, :type, :admin_policy_id, :catkeys,
:collection_ids, :copyright, :embargo, :license,
:source_id, :use_statement, :barcode,
:view_access, :download_access, :access_location, :controlled_digital_lending,
:file_sets, :members, :release_tags

attribute :id
attribute :version
attribute :type
attribute :admin_policy_id
attribute :catkeys
attribute :collection_ids
attribute :copyright
attribute :embargo
attribute :license
attribute :source_id
attribute :use_statement
attribute :barcode
attribute :view_access
attribute :download_access
attribute :access_location
attribute :controlled_digital_lending
attribute :file_sets
attribute :members
attribute :release_tags

# When the object is initialized, copy the properties from the cocina model to the entity:
def setup_properties!
self.id = model.externalIdentifier
self.version = model.version
self.type = model.type
self.admin_policy_id = model.administrative.hasAdminPolicy

self.catkeys = Catkey.symphony_links(model)
self.barcode = model.identification.barcode
self.source_id = model.identification.sourceId

setup_acccess_properties!

self.collection_ids = Array(model.structural&.isMemberOf)
self.file_sets = model.structural.contains.map { |cocina| FileSet.new(cocina) }
self.members = Array(model.structural.hasMemberOrders&.first&.members)
self.release_tags = model.administrative.releaseTags
end

def setup_acccess_properties!
self.copyright = model.access.copyright
self.use_statement = model.access.useAndReproductionStatement
self.license = model.access.license

self.view_access = model.access.view
self.download_access = model.access.download
self.access_location = model.access.location
self.controlled_digital_lending = model.access.controlledDigitalLending
self.embargo = Embargo.new(model.access.embargo) if model.access.embargo
end

def save
@model = ItemPersister.update(model, self)
end

# This checks to see if the embargo or any of the properties of the embargo changed
def embargo_changed?
super || embargo&.changed?
end

# has the collection or any of its members changed?
def file_sets_changed?
super || file_sets.any?(&:changed?)
end

def self.model_name
::ActiveModel::Name.new(nil, nil, 'Item')
end
end
60 changes: 60 additions & 0 deletions app/models/managed_file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true

class ManagedFile < ApplicationModel
define_attribute_methods :view_access, :download_access, :access_location,
:controlled_digital_lending, :publish, :shelve, :preserve,
:filename, :mime_type, :size, :use, :height, :width

attribute :view_access
attribute :download_access
attribute :access_location
attribute :controlled_digital_lending
attribute :publish
attribute :shelve
attribute :preserve
attribute :filename
attribute :mime_type
attribute :size
attribute :use
attribute :height
attribute :width

# When the object is initialized, copy the properties from the cocina model to the entity:
def setup_properties!
self.filename = model.filename
self.mime_type = model.hasMimeType
self.size = model.size
self.use = model.use

self.view_access = model.access.view
self.download_access = model.access.download
self.access_location = model.access.location
self.controlled_digital_lending = model.access.controlledDigitalLending

self.publish = model.administrative.publish
self.shelve = model.administrative.shelve
self.preserve = model.administrative.sdrPreserve

self.height = model.presentation&.height
self.width = model.presentation&.width
end

def administrative_changed?
publish_changed? || shelve_changed? || preserve_changed?
end

# Assigns the correct access and ensures publsh and shelve are false
def dark!
citation_only!
self.publish = false
self.shelve = false
end

# Assigns the correct access so the object shows on PURL, but doesn't reveal any files
def citation_only!
self.view_access = 'dark'
self.download_access = 'none'
self.controlled_digital_lending = false
self.access_location = nil
end
end
74 changes: 74 additions & 0 deletions app/services/collection_persister.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

# Writes updates to Cocina collections
class CollectionPersister
# @param [Cocina::Models::Collection] model the orignal state of the collection
# @param [Collection] change_set the values to update.
# @return [Cocina::Models::Collection] the model with updates applied
def self.update(model, change_set)
new(model, change_set).update
end

def initialize(model, change_set)
@model = model
@change_set = change_set
end

def update
updated_model = update_identification(model)
.then { |updated| updated_access(updated) }
.then { |updated| updated_administrative(updated) }

Repository.store(updated_model)
end

private

# The map between the change set fields and the Cocina field names
ACCESS_FIELDS = {
copyright: :copyright,
license: :license,
use_statement: :useAndReproductionStatement,
view_access: :access
}.freeze

attr_reader :model, :change_set

delegate :admin_policy_id, :catkeys, *ACCESS_FIELDS.keys,
:source_id_changed?, :catkeys_changed?, :admin_policy_id_changed?,
:copyright_changed?, :license_changed?, :use_statement_changed?,
:view_access_changed?, to: :change_set

def access_changed?
ACCESS_FIELDS.keys.any? { |field| public_send("#{field}_changed?") }
end

def updated_access(updated)
return updated unless access_changed?

updated.new(access: updated.access.new(updated_access_properties))
end

def updated_access_properties
{}.tap do |access_properties|
ACCESS_FIELDS.each do |field, cocina_field|
access_properties[cocina_field] = public_send(field).presence if public_send("#{field}_changed?")
end
end
end

def update_identification(updated)
return updated unless source_id_changed? || catkeys_changed?

identification_props = updated.identification&.to_h || {}
identification_props[:catalogLinks] = Catkey.serialize(model, catkeys) if catkeys_changed?
updated.new(identification: identification_props.compact.presence)
end

def updated_administrative(updated)
return updated unless admin_policy_id_changed?

updated_administrative = updated.administrative.new(hasAdminPolicy: admin_policy_id)
updated.new(administrative: updated_administrative)
end
end
Loading

0 comments on commit 3dff47c

Please sign in to comment.