QutBioacoustics/baw-workers

View on GitHub
lib/baw-workers/storage/analysis_cache.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'pathname'

module BawWorkers
  module Storage
    # Provides access to analysis cache storage.
    class AnalysisCache
      include BawWorkers::Storage::Common

      JOB_ID_SYSTEM = 'system'

      public

      # Create a new BawWorkers::Storage::AnalysisCache.
      # @param [Array<String>] storage_paths
      # @return [void]
      def initialize(storage_paths)
        # array of top-level folder paths to store cached analysis results
        @storage_paths = storage_paths
        @separator = '_'
        @extension_indicator = '.'
      end

      # Get the file name
      # @param [Hash] opts
      # @return [String] file name for stored file
      def file_name(opts)
        validate_file_name(opts)

        BawWorkers::Validation.normalise_path(opts[:file_name], nil)
      end

      # Get file names
      # @param [Hash] opts
      # @return [Array<String>]
      def file_names(opts)
        [file_name(opts)]
      end

      # Construct the partial path to an analysis result file.
      # @param [Hash] opts
      # @return [String] partial path to analysis result file.
      def partial_path(opts)
        validate_job_id(opts)
        validate_uuid(opts)
        validate_sub_folders(opts)

        # ./<job_id>/<guid first 2 chars>/<full guid>/<subfolder(s)>/

        job_id = opts[:job_id].to_s.strip.downcase
        guid_chars = opts[:uuid][0, 2].downcase
        guid = opts[:uuid].downcase
        sub_folder = File.join(*opts[:sub_folders])

        partial_path = File.join(job_id, guid_chars, guid, sub_folder)

        BawWorkers::Validation.normalise_path(partial_path, nil)
      end

      # Construct the path to an analysis results root folder.
      # @param [Hash] opts
      # @return [String] path to analysis results root folder.
      def job_path(opts)
        validate_job_id(opts)

        # ./<job_id>

        job_id = opts[:job_id].to_s.strip.downcase

        partial_path = File.join(job_id)

        BawWorkers::Validation.normalise_path(partial_path, nil)
      end

      # Get all possible root paths for an analysis job.
      # @param [Hash] opts
      # @return [Array<String>]
      def possible_job_paths_dir(opts)
        # partial_path is implemented in each store.
        @storage_paths.map { |path| File.join(path, job_path(opts)) }
      end


      # Extract information from a file name.
      # @param [String] file_path
      # @return [Hash] info
      def parse_file_path(file_path)

        # check that file_path starts with one of the possible base directories
        base_dirs = possible_dirs
        base_dirs_matched = base_dirs.select { |base_dir| file_path.start_with?(base_dir) }
        fail ArgumentError, "Must start with one of '#{base_dirs.join('\', \'')}': #{file_path} " if base_dirs_matched.size != 1

        # remove base dir from file_path
        relative_path = file_path.sub(base_dirs_matched.first, '')

        # clean file_path so it is more likely to match
        relative_path_clean =  BawWorkers::Validation.normalise_path(relative_path, nil)

        # extract parts of path
        path_parts = Pathname(relative_path_clean).each_filename.to_a

        job_id = path_parts[0].to_i.to_s == path_parts[0].to_s ? path_parts[0].to_i : JOB_ID_SYSTEM

        opts = {
            job_id: job_id,
            uuid: path_parts[2],
            sub_folders: path_parts[3..-2],
            file_name: path_parts[-1]
        }

        validate_job_id(opts)
        validate_uuid(opts)
        validate_sub_folders(opts)
        validate_file_name(opts)

        opts
      end

    end
  end
end