bio-miga/miga

View on GitHub
lib/miga/project.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
93%
# @package MiGA
# @license Artistic-2.0

require 'miga/dataset'
require 'miga/project/result'
require 'miga/project/dataset'
require 'miga/project/hooks'

##
# MiGA representation of a project
class MiGA::Project < MiGA::MiGA
  include MiGA::Project::Result
  include MiGA::Project::Dataset
  include MiGA::Project::Hooks

  ##
  # Absolute path to the project folder
  attr_reader :path

  ##
  # Information about the project as MiGA::Metadata
  attr_reader :metadata

  ##
  # If true, it doesn't save changes
  attr_accessor :do_not_save

  ##
  # Create a new MiGA::Project at +path+, if it doesn't exist and +update+ is
  # false, or load an existing one.
  def initialize(path, update = false)
    @datasets = {}
    @do_not_save = false
    @path = File.absolute_path(path)
    self.create if !update && !Project.exist?(self.path)
    self.load if self.metadata.nil?
    self.metadata[:type] = :mixed if type.nil?
    raise "Unrecognized project type: #{type}" if @@KNOWN_TYPES[type].nil?
  end

  ##
  # Create an empty project
  def create
    unless MiGA::MiGA.initialized?
      warn 'Projects cannot be processed yet, first run: miga init'
    end

    dirs = @@FOLDERS.map { |d| File.join(path, d) }
    dirs += @@DATA_FOLDERS.map { |d| File.join(path, 'data', d) }
    dirs.each { |d| FileUtils.mkdir_p(d) }
    @metadata = MiGA::Metadata.new(
      File.join(path, 'miga.project.json'),
      datasets: [], name: File.basename(path)
    )
    d_path = File.join(path, 'daemon', 'daemon.json')
    File.open(d_path, 'w') { |fh| fh.puts '{}' } unless File.exist?(d_path)
    pull_hook :on_create
    self.load
  end

  ##
  # Save any changes persistently. Do nothing if +do_not_save+ is true
  def save
    save! unless do_not_save
  end

  ##
  # Save any changes persistently, regardless of +do_not_save+
  def save!
    metadata.save!
    pull_hook :on_save
    self.load
  end

  ##
  # (Re-)load project data and metadata
  def load
    @datasets = {}
    @dataset_names_hash = nil
    @dataset_names_set = nil
    @metadata = MiGA::Metadata.load "#{path}/miga.project.json"
    raise "Couldn't find project metadata at #{path}" if metadata.nil?

    pull_hook :on_load
  end

  ##
  # Name of the project
  def name
    metadata[:name]
  end

  ##
  # Type of project
  def type
    metadata[:type]
  end

  ##
  # Is this a clade project?
  def clade?
    %i[clade plasmids].include? type
  end

  ##
  # Same as active? For backward compatibility
  alias is_clade? clade?

  ##
  # Is this a project for multi-organism datasets?
  def multi?
    @@KNOWN_TYPES[type][:multi]
  end

  ##
  # Same as multi? For backward compatibility
  alias is_multi? multi?

  ##
  # Does the project support the use of universal markers?
  def markers?
    @@KNOWN_TYPES[type][:markers]
  end

  ##
  # Is this project active? Currently a dummy function, returns
  # always true.
  def active?
    true
  end

  ##
  # Load or recover the project's daemon
  def daemon
    require 'miga/daemon'
    @daemon ||= MiGA::Daemon.new(self)
  end

  ##
  # Retrieves the option with name +key+ from the project's metadata,
  # extending support to relative paths in +:ref_project+ and
  # +:db_proj_dir+
  def option_by_metadata(key)
    case key.to_sym
    when :ref_project, :db_proj_dir
      y = metadata[key]
      y = File.expand_path(y, path) if y && y =~ /^[^\/]/
      return y
    end

    super
  end
end