class Noid::Template
Constants
- VALID_PATTERN
Attributes
Public Class Methods
@param [String] template A Template
is a coded string of the form Prefix.Mask that governs how identifiers will be minted.
# File lib/noid/template.rb, line 8 def initialize(template) @template = template parse! end
Public Instance Methods
# File lib/noid/template.rb, line 49 def ==(other) return false unless other.is_a? Noid::Template template == other.template end
calculate a checkdigit for the str @param [String] str @return [String] checkdigit
# File lib/noid/template.rb, line 35 def checkdigit(str) Noid::XDIGIT[str.split('').map { |x| Noid::XDIGIT.index(x).to_i }.each_with_index.map { |n, idx| n * (idx + 1) }.inject { |sum, n| sum + n } % Noid::XDIGIT.length] end
maximum sequence value for the template
# File lib/noid/template.rb, line 56 def max @max ||= if generator == 'z' nil else size_list.inject(1) { |total, x| total * x } end end
minimum sequence value
# File lib/noid/template.rb, line 41 def min @min ||= 0 end
# File lib/noid/template.rb, line 13 def mint(n) str = prefix str += n2xdig(n) str += checkdigit(str) if checkdigit? str end
# File lib/noid/template.rb, line 45 def to_s template end
Is the string valid against this template string and checksum? @param [String] str @return bool
# File lib/noid/template.rb, line 24 def valid?(str) match = validation_regex.match(str) return false if match.nil? return checkdigit(match[1]) == match[3] if checkdigit? true end
Protected Instance Methods
# File lib/noid/template.rb, line 118 def character_list characters.split('') end
total size of a given template character value @param [String] c
# File lib/noid/template.rb, line 133 def character_space(c) case c when 'e' Noid::XDIGIT.length when 'd' 10 end end
# File lib/noid/template.rb, line 101 def character_to_pattern(c) case c when 'e', 'k' xdigit_pattern when 'd' '\d' else '' end end
# File lib/noid/template.rb, line 126 def checkdigit? @checkdigit end
# File lib/noid/template.rb, line 122 def mask generator + characters end
convert a minter position to a noid string under this template @param [Integer] n @return [String]
# File lib/noid/template.rb, line 146 def n2xdig(n) xdig = size_list.reverse.map { |size| value = n % size n /= size Noid::XDIGIT[value] }.compact.join('') if generator == 'z' size = size_list.last while n > 0 value = n % size n /= size xdig += Noid::XDIGIT[value] end end raise 'Exhausted noid sequence pool' if n > 0 xdig.reverse end
parse template and put the results into instance variables raise an exception if there is a parse error
# File lib/noid/template.rb, line 88 def parse! match = VALID_PATTERN.match(template) raise Noid::TemplateError, "Malformed noid template '#{template}'" unless match @prefix = match[1] @generator = match[2] @characters = match[3] @checkdigit = (match[4] == 'k') end
Return a list giving the number of possible characters at each position
# File lib/noid/template.rb, line 114 def size_list @size_list ||= character_list.map { |c| character_space(c) } end
A noid has the structure (prefix)(code)(checkdigit) the regexp has the following captures
1 - the prefix and the code 2 - the changing id characters (not the prefix and not the checkdigit) 3 - the checkdigit, if there is one. This field is missing if there is no checkdigit
# File lib/noid/template.rb, line 72 def validation_regex @validation_regex ||= begin character_pattern = '' # the first character in the mask after the type character is the most significant # acc. to the Noid spec (p.9): # https://wiki.ucop.edu/display/Curation/NOID?preview=/16744482/16973835/noid.pdf character_pattern += character_to_pattern(character_list.first) + "*" if generator == 'z' character_pattern += character_list.map { |c| character_to_pattern(c) }.join %r{\A(#{Regexp.escape(prefix)}(#{character_pattern}))(#{character_to_pattern('k') if checkdigit?})\Z} end end
# File lib/noid/template.rb, line 97 def xdigit_pattern @xdigit_pattern ||= '[' + Noid::XDIGIT.join('') + ']' end