lib/locabulary.rb in locabulary-0.2.0 vs lib/locabulary.rb in locabulary-0.3.0
- old
+ new
@@ -1,45 +1,14 @@
require 'date'
require 'json'
+require 'locabulary/exceptions'
+require 'locabulary/items'
# @since 0.1.0
module Locabulary
- VERSION='0.2.0'.freeze
DATA_DIRECTORY = File.expand_path("../../data/", __FILE__).freeze
- class RuntimeError < ::RuntimeError
- end
-
- class Item
- include Comparable
- ATTRIBUTE_NAMES = [:predicate_name, :term_label, :term_uri, :deposit_label, :description, :grouping, :affiliation, :default_presentation_sequence, :activated_on, :deactivated_on].freeze
-
- attr_reader(*ATTRIBUTE_NAMES)
-
- def initialize(attributes={})
- ATTRIBUTE_NAMES.each do |key|
- value = attributes.fetch(key) { attributes.fetch(key.to_s, nil) }
- send("#{key}=", value)
- end
- end
-
- SORT_SEQUENCE_FOR_NIL = 100_000_000
- def <=>(other)
- value = presentation_sequence <=> other.presentation_sequence
- return value unless value == 0
- term_label <=> other.term_label
- end
-
- def presentation_sequence
- default_presentation_sequence || SORT_SEQUENCE_FOR_NIL
- end
-
- private
-
- attr_writer(*ATTRIBUTE_NAMES)
- end
-
module_function
# @api public
# @since 0.1.0
#
@@ -48,31 +17,74 @@
# about the local controlled vocabulary exposing a date that has expired.
# When we next deploy the server changes, the deactivated will go away.
def active_items_for(options = {})
predicate_name = options.fetch(:predicate_name)
as_of = options.fetch(:as_of) { Date.today }
+ builder = Items.builder_for(predicate_name: predicate_name)
active_cache[predicate_name] ||= begin
- filename = filename_for_predicate_name(predicate_name: predicate_name)
- json = JSON.parse(File.read(filename))
- predicate_name = json.fetch('predicate_name')
- json.fetch('values').each_with_object([]) do |item_values, mem|
- activated_on = Date.parse(item_values.fetch('activated_on'))
- next unless activated_on < as_of
- deactivated_on_value = item_values.fetch('deactivated_on', nil)
- if deactivated_on_value.nil?
- mem << Item.new(item_values.merge('predicate_name' => predicate_name))
- else
- deactivated_on = Date.parse(deactivated_on_value)
- next unless deactivated_on >= as_of
- mem << Item.new(item_values.merge('predicate_name' => predicate_name))
- end
- mem
- end.sort
+ collector = []
+ with_active_extraction_for(predicate_name, as_of) do |data|
+ collector << builder.call(data.merge('predicate_name' => predicate_name))
+ end
+ collector.sort
end
end
# @api public
+ # @since 0.2.0
+ def active_hierarchical_root(options = {})
+ predicate_name = options.fetch(:predicate_name)
+ as_of = options.fetch(:as_of) { Date.today }
+ builder = Items.builder_for(predicate_name: predicate_name)
+ active_hierarchical_root_cache[predicate_name] ||= begin
+ items = []
+ hierarchy_graph_keys = {}
+ top_level_slugs = Set.new
+ with_active_extraction_for(predicate_name, as_of) do |data|
+ item = builder.call(data.merge('predicate_name' => predicate_name))
+ items << item
+ top_level_slugs << item.root_slug
+ hierarchy_graph_keys[item.term_label] = item
+ end
+ associate_parents_and_childrens_for(hierarchy_graph_keys, items, predicate_name)
+ raise Exceptions::TooManyHierarchicalRootsError.new(predicate_name, top_level_slugs.to_a) if top_level_slugs.size > 1
+ hierarchy_graph_keys.fetch(top_level_slugs.first)
+ end
+ end
+
+ def associate_parents_and_childrens_for(hierarchy_graph_keys, items, predicate_name)
+ items.each do |item|
+ begin
+ hierarchy_graph_keys.fetch(item.parent_term_label).children << item unless item.parent_slugs.empty?
+ rescue KeyError => error
+ raise Exceptions::MissingHierarchicalParentError.new(predicate_name, error)
+ end
+ end
+ end
+ private :associate_parents_and_childrens_for
+
+ def with_active_extraction_for(predicate_name, as_of)
+ filename = filename_for_predicate_name(predicate_name: predicate_name)
+ json = JSON.parse(File.read(filename))
+ json.fetch('values').each do |data|
+ yield(data) if data_is_active?(data, as_of)
+ end
+ end
+ private :with_active_extraction_for
+
+ def data_is_active?(data, as_of)
+ activated_on = Date.parse(data.fetch('activated_on'))
+ return false unless activated_on < as_of
+ deactivated_on_value = data.fetch('deactivated_on', nil)
+ return true if deactivated_on_value.nil?
+ deactivated_on = Date.parse(deactivated_on_value)
+ return false unless deactivated_on >= as_of
+ true
+ end
+ private :data_is_active?
+
+ # @api public
# @since 0.1.0
def active_label_for_uri(options = {})
predicate_name = options.fetch(:predicate_name)
term_uri = options.fetch(:term_uri)
object = active_items_for(predicate_name: predicate_name).detect { |obj| obj.term_uri == term_uri }
@@ -85,62 +97,29 @@
def active_labels_for(options = {})
predicate_name = options.fetch(:predicate_name)
active_items_for(predicate_name: predicate_name).map(&:term_label)
end
-
- # @api public
- def active_nested_labels_for(options = {})
- format_active_items_for(active_labels_for(options))
- end
-
- # @api public
- def properties_for_uri(options = {})
- predicate_name = options.fetch(:predicate_name)
- term_uri = options.fetch(:term_uri)
- object = active_items_for(predicate_name: predicate_name).detect { |obj| obj.term_uri == term_uri }
- return object. if object
- term_uri
- end
-
# @api private
def filename_for_predicate_name(options = {})
predicate_name = options.fetch(:predicate_name)
filename = File.join(DATA_DIRECTORY, "#{File.basename(predicate_name)}.json")
return filename if File.exist?(filename)
- raise Locabulary::RuntimeError, "Unable to find predicate_name: #{predicate_name}"
+ raise Locabulary::Exceptions::RuntimeError, "Unable to find predicate_name: #{predicate_name}"
end
# @api private
def active_cache
@active_cache ||= {}
end
# @api private
- def reset_active_cache!
- @active_cache = nil
+ def active_hierarchical_root_cache
+ @active_hierarchical_root_cache ||= {}
end
# @api private
- def format_active_items_for(items)
- root = {}
- items.each do |item|
- key, value = build_key_and_value(item)
- root[key] ||= []
- root[key] << value
- end
- root
- end
-
- # @api private
- def build_key_and_value(text)
- text_array = text.split(/(::)/)
- return text, text if text_array.size == 1
- return text, text_array.last if text_array.size == 3
- key = ""
- (0..(text_array.size-3)).each do |index|
- key << text_array[index]
- end
- value = text_array.last
- return key, value
+ def reset_active_cache!
+ @active_cache = nil
+ @active_hierarchical_root_cache = nil
end
end