sul-dlss/dor-services-app

View on GitHub
app/services/constituent_service.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

# Adds a constituent relationship between a virtual object and constituent objects
# by taking the following actions:
#  1. altering the structural metadata of the virtual object
#  2. saving the virtual object
class ConstituentService
  VERSION_DESCRIPTION = 'Virtual object created'

  # @param [String] virtual_object_druid the identifier of the virtual object
  def initialize(virtual_object_druid:)
    @virtual_object_druid = virtual_object_druid
  end

  # This resets the structural metadata of the virtual object and then adds the constituent resources.
  # Typically this is only called one time (with a list of all the identifiers) because
  # subsequent calls will erase the previous changes.
  # @param [Array<String>] constituent_druids the identifiers of the constituent objects
  # @raise [ItemQueryService::UncombinableItemError] if a constituent object cannot be added to a virtual object
  # @raise [Preservation::Client::Error] if bad response from preservation catalog.
  # @raise [VersionService::VersioningError] if the object hasn't been opened for versioning, or if accessionWF has
  #   already been instantiated or the current version is missing a description
  # @return [NilClass, Hash] true if successful, hash of errors otherwise (if combinable validation fails)
  def add(constituent_druids:)
    errors = ItemQueryService.validate_combinable_items(virtual_object: virtual_object_druid, constituents: constituent_druids)

    return errors if errors.any?

    # Make sure the virtual object is open before making modifications
    updated_virtual_object = if VersionService.open?(druid: virtual_object.externalIdentifier, version: virtual_object.version)
                               virtual_object
                             else
                               VersionService.open(cocina_object: virtual_object,
                                                   description: VERSION_DESCRIPTION)
                             end

    updated_virtual_object = ResetContentMetadataService.reset(cocina_item: updated_virtual_object, constituent_druids:)

    UpdateObjectService.update(updated_virtual_object)

    VersionService.close(druid: updated_virtual_object.externalIdentifier, version: updated_virtual_object.version)

    Indexer.reindex(cocina_object: updated_virtual_object)

    publish_constituents!(constituent_druids)

    nil
  end

  private

  attr_reader :virtual_object_druid

  def virtual_object
    @virtual_object ||= ItemQueryService.find_combinable_item(virtual_object_druid)
  end

  def publish_constituents!(constituent_druids)
    constituent_druids.each do |constituent_druid|
      Publish::MetadataTransferService.publish(druid: constituent_druid)
    end
  end
end