class RayyanFormats::Base

Constants

DEFAULT_MAX_FILE_SIZE
MAX_SKIP_LINES

Attributes

base_id[RW]
exported_first_line[RW]
next_id[RW]

Public Class Methods

available_plugins() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 52
def available_plugins
  # list all known plugins in runtime
  # http://stackoverflow.com/a/3680719/441849
  RayyanFormats::Plugins.constants
  .map(&RayyanFormats::Plugins.method(:const_get))
  .grep(Class)
end
description(*arguments, &block) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 37
def description(*arguments, &block)
  @plugin_description = arguments.first if arguments.length > 0
  @plugin_description
end
export_extensions_str() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 50
def export_extensions_str; @@export_extensions_str end
extension(*arguments, &block) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 32
def extension(*arguments, &block)
  @plugin_extension = arguments.first if arguments.length > 0
  @plugin_extension
end
get_export_plugin(ext) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 83
def get_export_plugin(ext)
  plugin = match_export_plugin(ext)
  raise "Unsupported file format for export: #{ext}, please use one of: #{export_extensions_str}" unless plugin
  plugin.new
end
import(source, converter = nil, &block) click to toggle source

converter is a lambda(body, ext) that returns converted body Example for no-op lambda: Base.import(source, ->(body, ext) { body })

# File lib/rayyan-formats-core/base.rb, line 66
def import(source, converter = nil, &block)
  filename = source.name
  original_ext = File.extname(filename).delete('.')
  plugin = match_import_plugin(original_ext)
  raise "Unsupported file format for import: #{original_ext}, please use one of: #{import_extensions_str}" unless plugin

  # check file size, otherwise the worker process will crash for huge files
  file = source.attachment
  raise "The file is too big to process, should be less than #{max_file_size} bytes in size" if file.size > max_file_size

  body = file.read
  body = converter.call(body, original_ext) if converter
  plugin.do_import(body, filename, converter, &block)
ensure
  file.close if file
end
import_extensions_str() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 49
def import_extensions_str; @@import_extensions_str end
initialize_class(plugins_list = []) click to toggle source

class static initializer

# File lib/rayyan-formats-core/base.rb, line 11
def initialize_class(plugins_list = [])
  @@max_file_size ||= DEFAULT_MAX_FILE_SIZE
  @@plugins = plugins_list.reject{|klass|
    [RayyanFormats::Plugins::PlainText, RayyanFormats::Plugins::CSV].include? klass
  } << RayyanFormats::Plugins::PlainText << RayyanFormats::Plugins::CSV
  @@import_extensions_str = @@plugins.map{|plugin|
    plugin.extension if plugin.can_import?
  }.compact.join(", ")
  @@export_extensions_str = @@plugins.map{|plugin|
    plugin.extension if plugin.can_export?
  }.compact.join(", ")
  @@logger ||= DummyLogger.new
  @@plugins
end
is_text?(ext) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 60
def is_text?(ext)
  match_import_plugin(ext) == RayyanFormats::Plugins::PlainText
end
logger() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 48
def logger; @@logger end
logger=(value) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 47
def logger=(value); @@logger = value || DummyLogger.new end
max_file_size() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 46
def max_file_size; @@max_file_size end
max_file_size=(value) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 45
def max_file_size=(value); @@max_file_size = value end
new() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 192
def initialize
  @base_id = "id#{(rand*1e8).round}_"
  @next_id = 0
end
plugins() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 44
def plugins; @@plugins end
plugins=(list) click to toggle source

public base methods

# File lib/rayyan-formats-core/base.rb, line 43
def plugins=(list); initialize_class list end
title(*arguments, &block) click to toggle source

plugin DSL simple setters/getters

# File lib/rayyan-formats-core/base.rb, line 27
def title(*arguments, &block)
  @plugin_title = arguments.first if arguments.length > 0
  @plugin_title
end

Protected Class Methods

can_export?() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 149
def can_export?
  !!@plugin_export_block
end
can_import?() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 145
def can_import?
  !!@plugin_import_block
end
detect(*arguments, &block) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 109
def detect(*arguments, &block)
  if arguments.length == 0
    @plugin_detect_block = block
  else
    logger.debug "Detecting #{self.title}"
    @plugin_detect_block.call(*arguments, &block)
  end
end
detect_import_format(file_content) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 135
def detect_import_format(file_content)
  lines = file_content.split(/\n\r|\r\n|\n|\r/)
  raise 'Empty file' if lines.length == 0
  detect_import_format_recursive(lines, 0)
end
do_export(*arguments, &block) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 101
def do_export(*arguments, &block)
  if arguments.length == 0
    @plugin_export_block = block
  else
    @plugin_export_block.call(*arguments, &block)
  end
end
do_import(*arguments, &block) click to toggle source

plugin DSL block setters/getters

# File lib/rayyan-formats-core/base.rb, line 92
def do_import(*arguments, &block)
  if arguments.length == 0
    @plugin_import_block = block
  else
    logger.debug "Inside #{self.title} parser for file: #{arguments[1] rescue ''}"
    @plugin_import_block.call(*arguments, &block)
  end
end
get_abstracts(target, options, &block) click to toggle source

helper methods for plugins

# File lib/rayyan-formats-core/base.rb, line 119
def get_abstracts(target, options, &block)
  return nil unless options[:include_abstracts] && target.abstracts && target.abstracts.length > 0
  block.call target.abstracts.map{|abstract|
    if abstract.instance_of?(Hash)
      label = abstract[:label] ? "#{abstract[:label]}: " : nil
      "#{label}#{abstract[:content]}"
    else
      abstract
    end
  }
end
is_core?() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 141
def is_core?
  !!@plugin_detect_block
end
match_export_plugin(ext) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 160
def match_export_plugin(ext)
  match_plugin(ext){|plugin| plugin.can_export?}
end
match_import_plugin(ext) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 153
def match_import_plugin(ext)
  plugin = match_plugin(ext){|plugin| plugin.can_import?}
  return nil if plugin.nil?
  # force core extensions to txt to pass by encoding and plugin detection filters
  return plugin.is_core? ? RayyanFormats::Plugins::PlainText : plugin
end
try_join_arr(val) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 131
def try_join_arr(val)
  val.join("\n") rescue val
end

Private Class Methods

detect_import_format_recursive(lines, skipped) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 170
def detect_import_format_recursive(lines, skipped)
  # return plugin based on contect or raise error if unsupported
  first_line = lines[skipped].lstrip
  csv_plugin = RayyanFormats::Plugins::CSV
  plugin = plugins.find{|plugin|
    plugin != csv_plugin && plugin.is_core? && plugin.send(:detect, first_line, lines)
  }
  if plugin
    return plugin, lines[skipped..-1]
  elsif skipped < MAX_SKIP_LINES && skipped + 1 < lines.length
    return detect_import_format_recursive(lines, skipped + 1)
  elsif csv_plugin.send(:detect, lines.first, lines) # nothing detected, csv last resort
    return csv_plugin, lines
  else
    raise "Unsupported file contents, please use a proper way to export your files into one of these formats: #{import_extensions_str}"
  end
end
match_plugin(ext, &block) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 166
def match_plugin(ext, &block)
  plugins.find{|plugin| plugin.extension == ext.downcase && block.call(plugin)}
end

Public Instance Methods

export(target, options = {}) click to toggle source
# File lib/rayyan-formats-core/base.rb, line 202
def export(target, options = {})
  # delegate to the protected method
  options = options.merge(include_header: !!!exported_first_line, unique_id: get_unique_id)
  output = self.class.send(:do_export, target, options)
  @exported_first_line = true
  output
end
get_unique_id() click to toggle source
# File lib/rayyan-formats-core/base.rb, line 197
def get_unique_id
  @next_id += 1
  "#{@base_id}#{@next_id}"
end