class Moab::StorageObjectValidator

Given a druid path, are the contents actually a well-formed Moab? Shameless green: repetitious code included.

Constants

CONTENT_DIR
CONTENT_SUB_DIRS_DETECTED
DATA_DIR
EXPECTED_DATA_SUB_DIRS
EXPECTED_VERSION_SUB_DIRS
EXTRA_CHILD_DETECTED
FILES_IN_VERSION_DIR
IMPLICIT_DIRS
INCORRECT_DIR_CONTENTS

error codes

MANIFESTS_DIR
MANIFEST_INVENTORY_PATH
METADATA_DIR
METADATA_SUB_DIRS_DETECTED
MISSING_DIR
NO_FILES_IN_CONTENT_DIR
NO_FILES_IN_MANIFEST_DIR
NO_FILES_IN_METADATA_DIR
NO_MANIFEST_INVENTORY
NO_SIGNATURE_CATALOG
SIGNATURE_CATALOG_PATH
TEST_OBJECT_VERSIONS_NOT_IN_ORDER
VERSION_DIR_BAD_FORMAT
VERSION_DIR_PATTERN

Attributes

storage_obj_path[R]

Public Class Methods

error_code_to_messages() click to toggle source
# File lib/moab/storage_object_validator.rb, line 51
def self.error_code_to_messages
  @error_code_to_messages ||=
    {
      INCORRECT_DIR_CONTENTS => 'Incorrect items under %<addl>s directory',
      MISSING_DIR => 'Missing directory: %<addl>s',
      EXTRA_CHILD_DETECTED => 'Unexpected item in path: %<addl>s',
      VERSION_DIR_BAD_FORMAT => "Version directory name not in 'v00xx' format: %<addl>s",
      FILES_IN_VERSION_DIR => 'Version directory %<addl>s should not contain files; only the manifests and data directories',
      NO_SIGNATURE_CATALOG => 'Version %<addl>s: Missing signatureCatalog.xml',
      NO_MANIFEST_INVENTORY => 'Version %<addl>s: Missing manifestInventory.xml',
      NO_FILES_IN_MANIFEST_DIR => 'Version %<addl>s: No files present in manifest dir',
      METADATA_SUB_DIRS_DETECTED => 'Version %<version>s: metadata directory should only contain files, not directories. Found directory: %<dir>s',
      TEST_OBJECT_VERSIONS_NOT_IN_ORDER => 'Should contain only sequential version directories. Current directories: %<addl>s',
      NO_FILES_IN_METADATA_DIR => 'Version %<addl>s: No files present in metadata dir',
      NO_FILES_IN_CONTENT_DIR => 'Version %<addl>s: No files present in content dir',
      CONTENT_SUB_DIRS_DETECTED => 'Version %<version>s: content directory should only contain files, not directories. Found directory: %<dir>s'
    }.freeze
end
new(storage_object) click to toggle source
# File lib/moab/storage_object_validator.rb, line 38
def initialize(storage_object)
  @storage_obj_path = storage_object.object_pathname
  @directory_entries_hash = {}
end

Public Instance Methods

validation_errors(allow_content_subdirs = true) click to toggle source
# File lib/moab/storage_object_validator.rb, line 43
def validation_errors(allow_content_subdirs = true)
  errors = []
  errors.concat check_correctly_named_version_dirs
  errors.concat check_sequential_version_dirs if errors.empty?
  errors.concat check_correctly_formed_moab(allow_content_subdirs) if errors.empty?
  errors
end

Private Instance Methods

basename(path) click to toggle source
# File lib/moab/storage_object_validator.rb, line 200
def basename(path)
  path.split(File::SEPARATOR)[-1]
end
check_correctly_formed_moab(allow_content_subdirs = true) click to toggle source
# File lib/moab/storage_object_validator.rb, line 95
def check_correctly_formed_moab(allow_content_subdirs = true)
  errors = []
  version_directories.each do |version_dir|
    version_path = File.join(storage_obj_path, version_dir)
    version_error_count = errors.size
    errors.concat check_version_sub_dirs(version_path, version_dir)
    errors.concat check_required_manifest_files(version_path, version_dir) if version_error_count == errors.size
    errors.concat check_data_directory(version_path, version_dir, allow_content_subdirs) if version_error_count == errors.size
  end
  errors
end
check_correctly_named_version_dirs() click to toggle source
# File lib/moab/storage_object_validator.rb, line 76
def check_correctly_named_version_dirs
  errors = []
  errors << result_hash(MISSING_DIR, 'no versions exist') unless version_directories.count > 0
  version_directories.each do |version_dir|
    errors << result_hash(VERSION_DIR_BAD_FORMAT, version_dir) unless VERSION_DIR_PATTERN.match?(version_dir)
  end
  errors
end
check_data_directory(version_path, version, allow_content_subdirs = true) click to toggle source
# File lib/moab/storage_object_validator.rb, line 117
def check_data_directory(version_path, version, allow_content_subdirs = true)
  errors = []
  data_dir_path = File.join(version_path, DATA_DIR)
  data_sub_dirs = directory_entries(data_dir_path)
  errors.concat check_data_sub_dirs(version, data_sub_dirs)
  errors.concat check_metadata_dir_files_only(version_path) if errors.empty?
  if data_sub_dirs.include?('content') && errors.empty?
    errors.concat check_optional_content_dir(version_path, allow_content_subdirs)
  end
  errors
end
check_data_sub_dirs(version, data_sub_dirs) click to toggle source
# File lib/moab/storage_object_validator.rb, line 129
def check_data_sub_dirs(version, data_sub_dirs)
  return found_unexpected(data_sub_dirs, version, EXPECTED_DATA_SUB_DIRS) if data_sub_dirs.size > EXPECTED_DATA_SUB_DIRS.size

  errors = []
  errors.concat missing_dir(data_sub_dirs, version, [METADATA_DIR]) unless data_sub_dirs.include?(METADATA_DIR)
  unless data_sub_dirs.to_set.subset?(EXPECTED_DATA_SUB_DIRS.to_set)
    errors.concat found_unexpected(data_sub_dirs, version, EXPECTED_DATA_SUB_DIRS)
  end
  errors
end
check_metadata_dir_files_only(version_path) click to toggle source
# File lib/moab/storage_object_validator.rb, line 151
def check_metadata_dir_files_only(version_path)
  errors = []
  metadata_dir_path = File.join(version_path, DATA_DIR, METADATA_DIR)
  errors << result_hash(NO_FILES_IN_METADATA_DIR, basename(version_path)) if directory_entries(metadata_dir_path).empty?
  metadata_sub_dir = contains_sub_dir?(metadata_dir_path)
  if metadata_sub_dir
    errors << result_hash(METADATA_SUB_DIRS_DETECTED, version: basename(version_path), dir: metadata_sub_dir)
  end
  errors
end
check_optional_content_dir(version_path, allow_content_subdirs = true) click to toggle source
# File lib/moab/storage_object_validator.rb, line 140
def check_optional_content_dir(version_path, allow_content_subdirs = true)
  errors = []
  content_dir_path = File.join(version_path, DATA_DIR, CONTENT_DIR)
  errors << result_hash(NO_FILES_IN_CONTENT_DIR, basename(version_path)) if directory_entries(content_dir_path).empty?
  content_sub_dir = contains_sub_dir?(content_dir_path)
  if content_sub_dir && !allow_content_subdirs
    errors << result_hash(CONTENT_SUB_DIRS_DETECTED, version: basename(version_path), dir: content_sub_dir)
  end
  errors
end
check_required_manifest_files(dir, version) click to toggle source
# File lib/moab/storage_object_validator.rb, line 225
def check_required_manifest_files(dir, version)
  return [result_hash(NO_FILES_IN_MANIFEST_DIR, version)] unless contains_file?(File.join(dir, MANIFESTS_DIR))

  errors = []
  errors << result_hash(NO_MANIFEST_INVENTORY, version) unless File.exist?(File.join(dir, MANIFEST_INVENTORY_PATH))
  errors << result_hash(NO_SIGNATURE_CATALOG, version) unless File.exist?(File.join(dir, SIGNATURE_CATALOG_PATH))
  errors
end
check_sequential_version_dirs() click to toggle source

call only if the version directories are “correctly named” vdddd

# File lib/moab/storage_object_validator.rb, line 86
def check_sequential_version_dirs
  version_directories.each_with_index do |dir_name, index|
    next if dir_name[1..].to_i == index + 1 # version numbering starts at 1, array indexing at 0

    return [result_hash(TEST_OBJECT_VERSIONS_NOT_IN_ORDER, version_directories)]
  end
  []
end
check_version_sub_dirs(version_path, version) click to toggle source
# File lib/moab/storage_object_validator.rb, line 107
def check_version_sub_dirs(version_path, version)
  version_sub_dirs = directory_entries(version_path)
  count = version_sub_dirs.size
  return expected_version_sub_dirs(version_path, version) if count == EXPECTED_VERSION_SUB_DIRS.size
  return found_unexpected(version_sub_dirs, version, EXPECTED_VERSION_SUB_DIRS) if count > EXPECTED_VERSION_SUB_DIRS.size
  return missing_dir(version_sub_dirs, version, EXPECTED_VERSION_SUB_DIRS) if count < EXPECTED_VERSION_SUB_DIRS.size

  []
end
contains_file?(path) click to toggle source
# File lib/moab/storage_object_validator.rb, line 192
def contains_file?(path)
  directory_entries(path).detect { |entry| File.file?(File.join(path, entry)) }
end
contains_sub_dir?(path) click to toggle source
# File lib/moab/storage_object_validator.rb, line 188
def contains_sub_dir?(path)
  directory_entries(path).detect { |entry| File.directory?(File.join(path, entry)) }
end
directory_entries(path) click to toggle source

This method removes the implicit ‘.’ and ‘..’ directories. Returns an array of strings.

# File lib/moab/storage_object_validator.rb, line 164
def directory_entries(path)
  @directory_entries_hash[path] ||= Dir.entries(path).sort - IMPLICIT_DIRS
end
error_code_msg(response_code, addl = nil) click to toggle source
# File lib/moab/storage_object_validator.rb, line 215
def error_code_msg(response_code, addl = nil)
  arg_hash = {}
  if addl.is_a?(Hash)
    arg_hash.merge!(addl)
  else
    arg_hash[:addl] = addl
  end
  self.class.error_code_to_messages[response_code] % arg_hash
end
expected_version_sub_dirs(version_path, version) click to toggle source
# File lib/moab/storage_object_validator.rb, line 180
def expected_version_sub_dirs(version_path, version)
  errors = []
  version_sub_dirs = directory_entries(version_path)
  errors << result_hash(INCORRECT_DIR_CONTENTS, version) unless version_sub_dirs == EXPECTED_VERSION_SUB_DIRS
  errors << result_hash(FILES_IN_VERSION_DIR, version) if contains_file?(version_path)
  errors
end
found_unexpected(array, version, required_sub_dirs) click to toggle source

@return [Array<Hash<Integer => String>>]

# File lib/moab/storage_object_validator.rb, line 169
def found_unexpected(array, version, required_sub_dirs)
  unexpected = (array - required_sub_dirs)
  [result_hash(EXTRA_CHILD_DETECTED, "#{unexpected} Version: #{version}")]
end
missing_dir(array, version, required_sub_dirs) click to toggle source

@return [Array<Hash<Integer => String>>]

# File lib/moab/storage_object_validator.rb, line 175
def missing_dir(array, version, required_sub_dirs)
  missing = (required_sub_dirs - array)
  [result_hash(MISSING_DIR, "#{missing} Version: #{version}")]
end
object_id_from_manifest_inventory() click to toggle source
# File lib/moab/storage_object_validator.rb, line 234
def object_id_from_manifest_inventory
  latest_manifest_inventory = File.join(storage_obj_path, version_directories.last, MANIFEST_INVENTORY_PATH)
  Nokogiri::XML(File.open(latest_manifest_inventory)).at_xpath('//fileInventory/@objectId').value
end
result_hash(response_code, msg_args = nil) click to toggle source

@param [Integer] response_code one of the recognized values in error_code_to_messages @param [Hash<Symbol => String>, String] msg_args Value(s) folded into the error message @return [Hash<Integer => String>] single key/value Hash @example Usage

sov.result_hash(10, '/some/dir')
sov.result_hash(10, addl: '/some/dir') # equivalent
sov.result_hash(8, version: '3', dir: '/other/dir')
# File lib/moab/storage_object_validator.rb, line 211
def result_hash(response_code, msg_args = nil)
  { response_code => error_code_msg(response_code, msg_args) }
end
sub_dirs(path) click to toggle source
# File lib/moab/storage_object_validator.rb, line 196
def sub_dirs(path)
  directory_entries(path).select { |entry| File.directory?(File.join(path, entry)) }
end
version_directories() click to toggle source
# File lib/moab/storage_object_validator.rb, line 72
def version_directories
  @version_directories ||= directory_entries(storage_obj_path)
end