# # = Ruby Whois # # An intelligent pure Ruby WHOIS client and parser. # # # Category:: Net # Package:: Whois # Author:: Simone Carletti # License:: MIT License # #-- # #++ require 'strscan' require 'time' require 'whois/answer/contact' require 'whois/answer/registrar' module Whois class Answer class Parser # # = Base Answer Parser # # This class is intended to be the base abstract class for all # server-specific parser implementations. # # == Available Methods # # The Base class is for the most part auto-generated via meta programming. # This is the reason why RDoc can't detect and document all available methods. # class Base attr_reader :part def initialize(part) @part = part end ::Whois::Answer::Parser.registrable_methods.each do |method| define_method(method) do raise PropertyNotImplemented, "You should overwrite this method." end end # Returns true if the property passed as symbol # is supported by current parser. # # parser.supported? :disclaimer # # => false # # parser.register_method(:disclaimer) {} # parser.supported? :disclaimer # # => true # # This method is different than respond_to?. # While respond_to? always returns true for any registrable property, # including those not effectively implemented, # this method only returns true if the parser implements property. # Also, supported? returns false if property exists as a method # but it's not a property method. # # parser.respond_to?(:disclaimer) # # => true # parser.supported?(:disclaimer) # # => false # # parser.register_method(:disclaimer) {} # parser.respond_to?(:disclaimer) # # => true # parser.supported?(:disclaimer) # # => true # # parser.respond_to?(:contact) # # => true # parser.supported?(:contact) # # => false # def supported?(property) method_registered?(property.to_s.to_sym) end # This is an internal method primaly used as a common access point # to get the content to be parsed as a string. # # The main reason behind this method is because I changed the internal # representation of the data to be parsed more than once # and I always had to rewrite all single parsers in order to reflect these changes. # Now, as far as the parser access the data via the content method, # there's no need to change each single implementation in case the content source changes. # # That said, the only constraints about this method is to return the data to be parsed as string. # def content part.response end @@method_registry = {} # # :call-seq: # method_registry => hash # method_registry(:key) => array # # Returns the @@method_registry if key is nil, # otherwise returns the value in @@method_registry for given key. # # @@method_registry is always a Hash while @@method_registry[:key] # is always an array. If @@method_registry[:key] doesn't exist, this method # automatically initializes it to an empty array. # def self.method_registry(key = nil) if key.nil? @@method_registry else @@method_registry[key] ||= [] end end # Returns true if method is registered for current class. # # method_registered?(:disclaimer) # # => false # # register_method(:discaimer) {} # method_registered?(:disclaimer) # # => true # def self.method_registered?(method) method_registry(self).include?(method) end # # :call-seq: # register_method(:method) { } # register_method(:method) { |parameter| ... } # register_method(:method) { |parameter, ...| ... } # # Creates method with the content of block # and automatically registers method for current class. # # register_method(:discaimer) do # ... # end # # register_method(:changed?) do |other| # ... # end # # method_registered?(:disclaimer) # # => true # def self.register_method(method, &block) method_registry(self) << method define_method(method, &block) end # Instance-level version of Base.method_registered?. def method_registered?(method) self.class.method_registered?(method) end # Instance-level version of Base.register_method. def register_method(method, &block) self.class.register_method(method, &block) end end end end end