lib/csl/locale/term.rb in csl-1.0.0.pre10 vs lib/csl/locale/term.rb in csl-1.0.0.pre11
- old
+ new
@@ -9,54 +9,113 @@
undef_method :[]=
def initialize(attributes = {})
super(attributes)
- @registry, children[:term] = Hash.new { |h,k| h[k] = [] }, []
+ children[:term] = []
+ @registry = Term::Registry.new
+ @ordinals = Term::Registry.new
+
yield self if block_given?
end
alias each each_child
- def lookup(query)
- query = { :name => query } unless query.is_a?(Hash)
+ def lookup(name, options = {})
+ options[:name] = name = name.to_s
- terms = if query[:name].is_a?(Regexp)
- registry.select { |name, _| name =~ query[:name] }.flatten(1)
+ term = registry[name].detect { |t| t.match?(options) }
+ return term unless term.nil? && options.delete(:'gender-form')
+
+ registry[name].detect { |t| t.match?(options) }
+ end
+ alias [] lookup
+
+ def ordinalize_modulo(number, divisor, options = {})
+ ordinal = ordinalize(number, options)
+ return unless ordinal && ordinal.match_modulo?(divisor)
+ ordinal
+ end
+
+ def ordinalize(number, options = {})
+ return unless has_ordinals?
+
+ if number == :default
+ options[:name] = 'ordinal'
else
- registry[query[:name].to_s]
+ options[:name] = 'ordinal-%02d' % number
end
+
+ if options[:form].to_s =~ /^long/i
+ options.delete :form
+ options[:name][0,0] = 'long-'
+ end
+
+ ordinal = ordinals[number].detect { |t| t.match?(options) }
+ return ordinal unless ordinal.nil? && options.delete(:'gender-form')
+
+ ordinals[number].detect { |t| t.match?(options) }
+ end
- terms.detect { |t| t.match?(query) }
+ # @return [Boolean] whether or not regular terms are registered at this node
+ def has_terms?
+ not registry.empty?
end
- alias [] lookup
- def lookup_modulo(query, divisor)
- term = lookup(query)
- return if term.nil? || !term.match_modulo?(divisor)
- term
+ # @return [Boolean] whether or not ordinal terms are registered at this node
+ def has_ordinals?
+ not ordinals.empty?
end
+
+ def has_legacy_ordinals?
+ has_ordinals? && !ordinals.key?(:default)
+ end
+ def drop_ordinals
+ tmp = ordinals.values.flatten(1)
+ ordinals.clear
+ delete_children tmp
+ end
+
private
# @!attribute [r] registry
# @return [Hash] a private registry to map term names to the respective
# term objects for quick term look-up
attr_reader :registry
+ # @!attribute [r] ordinals
+ # @return [Hash] a private registry to map ordinals to the respective
+ # term objects for quick ordinal look-up
+ attr_reader :ordinals
+
def added_child(term)
raise ValidationError, "failed to register term #{term.inspect}: name attribute missing" unless
term.attribute?(:name)
- registry[term[:name]].push(term)
+ if term.ordinal?
+ store = ordinals[term.ordinal]
+ else
+ store = registry[term[:name]]
+ end
+
+ delete_children store.select { |value| term.exact_match? value }
+
+ store.push(term)
+
term
end
def deleted_child(term)
- registry[term[:name]].delete(term)
+ if term.ordinal?
+ ordinals[term.ordinal].delete(term)
+ else
+ registry[term[:name]].delete(term)
+ end
end
+
end
class Term < Node
attr_struct :name, :form, :gender, :'gender-form', :match
attr_children :single, :multiple
@@ -74,11 +133,11 @@
#
# @return [Boolean] whether or not the ordinal term matches the
# passed-in divisor.
def match_modulo?(divisor)
return false unless ordinal?
-
+
case attributes.match
when '2-digits'
divisor.to_i == 100
when '1-digit'
divisor.to_i == 10
@@ -86,28 +145,34 @@
divisor.to_i == 1
else
true
end
end
-
alias matches_modulo? match_modulo?
-
+
# @return [Boolean] whether or not this term is an ordinal term
def ordinal?
- /^ordinal(-\d\d+)?$/ === attributes.name
+ /^(long-)?ordinal(-\d\d+)?$/ === attributes.name
end
-
+
+ # @return [Fixnum, :default, nil]
+ def ordinal
+ return unless ordinal?
+ return :default if attributes.name == 'ordinal'
+ attributes.name[/\d+/].to_i
+ end
+
def gendered?
- !attributes.gender.blank?
+ not attributes.gender.blank?
end
def neutral?
- !gendered?
+ not gendered?
end
def textnode?
- !text.blank?
+ not text.blank?
end
def singularize
return text if textnode?
children.single.to_s
@@ -198,9 +263,14 @@
else
false
end
end
+ class Registry < ::Hash
+ def initialize
+ super { |h,k| h[k] = [] }
+ end
+ end
end
TextNode.types << Term
end
end
\ No newline at end of file