module PIM::Services::DataModelLoaders::DataModelFileRepository

Helper module to mix into classes needing to read out the data model file format from YAML or JSON

Public Class Methods

create_data_model_dbm_database(source_filename, target_dirname: nil, target_basename: nil, target_extname: DBMDatabase::TYPE_GDBM_EXTNAME, type: DBMDatabase::TYPE_GDBM, format: DBMDatabase::FORMAT_JSON) click to toggle source

Creates a data model dbm database for the specified YAML file. By default creates a GDBM database with the data stored in a JSON format.

# File services.rb, line 1413
def self.create_data_model_dbm_database source_filename,
                                        target_dirname: nil,
                                        target_basename: nil,
                                        target_extname: DBMDatabase::TYPE_GDBM_EXTNAME,
                                        type: DBMDatabase::TYPE_GDBM,
                                        format: DBMDatabase::FORMAT_JSON

  raise "Source file '#{source_filename}' not found" unless File.exist?(source_filename)
  yaml = YAML.load_file(source_filename)

  source_extname = File.extname(source_filename)
  target_dirname ||= File.dirname(source_filename)
  target_basename ||= File.basename(source_filename, source_extname)

  dbm_filename = File.expand_path(target_basename + target_extname, target_dirname)
  if File.exist?(dbm_filename)
    PIM.log_info "DBM file '#{dbm_filename}' already exists and will be cleared!"
    database = DBMDatabase.new(dbm_filename, action: :open)
    PIM.log_debug "Existing dbm file had #{database.size} entries"
    database.close_database
  end

  FileUtils.mkdir_p(target_dirname)
  database = DBMDatabase.new(dbm_filename, action: :create, type: type, format: format, version: DBMDatabase::VERSION_1_0)

  attributes = read_attributes(yaml)
  attributes.values.each do |attribute|
    database.put(make_key('attributes', attribute), deep_compact(attribute))
  end
  PIM.log_debug "attributes entries: #{attributes.size}"

  categories = read_categories(yaml)
  categories.each_pair do |name, category|
    database.put(make_key('categories', name, object_key: nil), deep_compact(category))
  end
  PIM.log_debug "categories entries: #{categories.size}"

  option_lists, option_list_options, option_list_groups = read_option_lists(yaml)

  option_lists.values.each do |option_list|
    database.put(make_key('option_lists', option_list), deep_compact(option_list))
  end
  PIM.log_debug "option_lists entries: #{option_lists.size}"

  count = 0
  option_list_options.each_pair do |option_list_name, options|
    database.put(make_key('option_list_options', nil, parent_key: nil, parent: option_list_name), deep_compact(options.keys))
    options.each_pair do |key, option|
      next if key.nil?
      database.put(make_key('option_list_options', option, parent_key: nil, parent: option_list_name), deep_compact(option))
    end
    count += 1 + options.size
  end
  PIM.log_debug "option_list_options entries: #{count}"

  count = 0
  option_list_groups.each_pair do |option_list_name, groups|
    database.put(make_key('option_list_groups', nil, parent_key: nil, parent: option_list_name), deep_compact(groups.keys))
    groups.each_pair do |key, group|
      next if key.nil?
      database.put(make_key('option_list_groups', group, parent_key: nil, parent: option_list_name), deep_compact(group))
    end
    count += 1 + groups.size
  end
  PIM.log_debug "option_list_groups entries: #{count}"

  validation_rules, validation_rules_by_attributes, validation_rules_by_tags = read_validation_rules(yaml)

  validation_rules.values.each do |validation_rule|
    database.put(make_key('validation_rules', validation_rule), deep_compact(validation_rule))
  end
  PIM.log_debug "validation_rules entries: #{validation_rules.size}"

  validation_rules_by_attributes.each_pair do |attribute_name, rule_names|
    database.put(make_key('validation_rules_by_attributes', attribute_name, object_key: nil), deep_compact(rule_names))
  end
  PIM.log_debug "validation_rules_by_attributes entries: #{validation_rules_by_attributes.size}"

  validation_rules_by_tags.each_pair do |tag_name, rule_names|
    database.put(make_key('validation_rules_by_tags', tag_name, object_key: nil), deep_compact(rule_names))
  end
  PIM.log_debug "validation_rules_by_tags entries: #{validation_rules_by_tags.size}"

  PIM.log_info "Wrote DBM file '#{dbm_filename}' with a total of #{database.size} entries"

  database.close_database

  return dbm_filename

end
deep_compact(object) click to toggle source
# File services.rb, line 1511
def self.deep_compact object
  return PIM::Utils.deep_compact(PIM::Utils.as_json(object))
end
make_key(base_name, object, object_key: 'name', parent: nil, parent_key: 'name') click to toggle source
# File services.rb, line 1504
def self.make_key base_name, object, object_key: 'name', parent: nil, parent_key: 'name'
  keys = Array(base_name)
  keys << (parent_key.nil? ? parent : parent[parent_key]) unless parent.nil?
  keys << (object_key.nil? ? object : object[object_key]) unless object.nil?
  keys.join(':')
end

Public Instance Methods

read_attributes(data_model_definitions) click to toggle source
# File services.rb, line 1247
def read_attributes data_model_definitions

  attributes_repository = {}

  attributes = PIM.get_value(data_model_definitions, :attributes) || []
  attributes.each do |attribute|
    name = PIM.get_value(attribute, :name)
    attributes_repository[name.to_s] = attribute
  end

  return attributes_repository
end
read_categories(data_model_definitions) click to toggle source
# File services.rb, line 1260
def read_categories data_model_definitions

  categories_repository = {}

  categories = PIM.get_value(data_model_definitions, :categories) || []
  categories.each do |category|
    name = PIM.get_value(category, :name)
    code = PIM.get_value(category, :code)
    categories_repository[name.to_s] = category
    categories_repository[code.to_s] = category unless code.nil?
  end

  return categories_repository
end
read_groups(option_list) click to toggle source
# File services.rb, line 1343
def read_groups option_list

  groups = (PIM.get_value(option_list, :groups) || [])
  return groups.map do |key, value|

    unless PIM.is_hash?(value)

      # Value is a list of options
      value = { options: Array(value) }

    end

    group = OptionListGroup.new(**value)
    group.name = key if group.name.nil?

    [key, group]

  end.to_h

end
read_option_lists(data_model_definitions) click to toggle source
# File services.rb, line 1275
def read_option_lists data_model_definitions

  option_lists_repository = {}
  option_list_options_repository = {}
  option_list_groups_repository = {}

  option_lists = PIM.get_value(data_model_definitions, :option_lists) || []
  option_lists.each do |option_list|

    options = read_options(option_list)
    groups = read_groups(option_list)

    # Add groups to options
    groups.values.each do |group|

      next if group.options.nil?
      group.options.each do |option_name|
        option = options[option_name]
        next if option.nil?
        option.groups ||= Set.new
        option.groups << group.name
      end

    end

    # Don't redundantly store options and groups in option_list!
    option_list.delete('options')
    option_list.delete('groups')

    option_list = OptionList.new(**option_list)
    option_list_name = option_list.name

    option_lists_repository[option_list_name] = option_list

    # Add list of all options to repository 'ALL' key
    options[nil] = options.keys
    option_list_options_repository[option_list_name] = options

    # Add list of all groups to repository 'ALL' key
    groups[nil] = groups.keys
    option_list_groups_repository[option_list_name] = groups

  end

  return option_lists_repository, option_list_options_repository, option_list_groups_repository
end
read_options(option_list) click to toggle source
# File services.rb, line 1322
def read_options option_list

  options = (PIM.get_value(option_list, :options) || [])
  return options.map do |key, value|

    unless PIM.is_hash?(value)

      # Value is a label
      value = { label: value }

    end

    option = OptionListOption.new(**value)
    option.name = key if option.name.nil?

    [key, option]

  end.to_h

end
read_validation_rules(data_model_definitions) click to toggle source
# File services.rb, line 1364
def read_validation_rules data_model_definitions

  validation_rules_repository = {}
  validation_rules_by_attributes_repository = {}
  validation_rules_by_tags_repository = {}

  validation_rules = PIM.get_value(data_model_definitions, :validation_rules) || []
  validation_rules.each do |validation_rule|

    validation_rule = ValidationRule.new(validation_rule)
    validation_rule_name = validation_rule.name

    validation_rules_repository[validation_rule_name] = validation_rule

    all_attributes = Set.new(validation_rule.validated_attributes) + Set.new(validation_rule.dependent_attributes)
    all_attributes.each do |attribute|
      (validation_rules_by_attributes_repository[attribute] ||= []) << validation_rule_name
    end

    tags = validation_rule.tags
    unless tags.nil? or tags.empty?
      tags.each do |tag|
        (validation_rules_by_tags_repository[tag] ||= []) << validation_rule_name
      end
    end

  end

  return validation_rules_repository, validation_rules_by_attributes_repository, validation_rules_by_tags_repository
end