class Whois::Parser
Constants
- METHODS
- PROPERTIES
- PROPERTY_STATE_NOT_IMPLEMENTED
- PROPERTY_STATE_NOT_SUPPORTED
- PROPERTY_STATE_SUPPORTED
- VERSION
The current library version.
Attributes
@return [Whois::Record] The record referenced by this parser.
Public Class Methods
Requires the file at whois/parsers/#{name}
.
@param [String] name The file name to load.
@return [void]
# File lib/whois/parser.rb, line 174 def self.autoload(name) require "whois/parsers/#{name}" end
Appends `Please report issue to` to the message and raises a new error
with the final message.
@param [Exception] error @param [String] message @return [void]
@api private @private
# File lib/whois/parser.rb, line 66 def self.bug!(error, message) raise error, message.dup + " Please report the issue at" + " http://github.com/weppos/whois-parser/issues" end
Converts host
to the corresponding parser class name.
@param [String] host The server host. @return [String] The class name.
@example
Parser.host_to_parser("whois.nic.it") # => "WhoisNicIt" Parser.host_to_parser("whois.nic-info.it") # => "WhoisNicInfoIt"
# File lib/whois/parser.rb, line 161 def self.host_to_parser(host) host.to_s.downcase. gsub(/[.-]/, '_'). gsub(/(?:^|_)(.)/) { $1.upcase }. gsub(/\A(\d+)\z/) { "Host#{$1}" } end
Initializes and return a new parser from record
.
@param [Whois::Record] record
# File lib/whois/parser.rb, line 187 def initialize(record) @record = record end
Returns the proper parser instance for given part
. The parser class is selected according to the value of the #host
attribute for given part
.
@param [Whois::Record::Part] part The part to get the parser for.
@return [Whois::Parsers::Base]
An instance of the specific parser for given part. The instance is expected to be a child of {Whois::Parsers::Base}.
@example
# Parser for a known host Parser.parser_for("whois.example.com") # => #<Whois::Parsers::WhoisExampleCom> # Parser for an unknown host Parser.parser_for("missing.example.com") # => #<Whois::Parsers::Blank>
# File lib/whois/parser.rb, line 114 def self.parser_for(part) parser_klass(part.host).new(part) rescue LoadError Parsers.const_defined?("Blank") || autoload("blank") Parsers::Blank.new(part) end
Detects the proper parser class according to given host
and returns the class constant.
This method autoloads missing parser classes. If you want to define a custom parser, simple make sure the class is loaded in the Ruby environment before this method is called.
@param [String] host The server host.
@return [Class] The instance of Class representing the parser Class
corresponding to <tt>host</tt>. If <tt>host</tt> doesn't have a specific parser implementation, then returns the {Whois::Parsers::Blank} {Class}. The {Class} is expected to be a child of {Whois::Parsers::Base}.
@raises LoadError If the class is not found.
@example
Parser.parser_klass("whois.example.com") # => Whois::Parsers::WhoisExampleCom
# File lib/whois/parser.rb, line 142 def self.parser_klass(host) name = host_to_parser(host) Parsers.const_defined?(name) || autoload(host) Parsers.const_get(name) end
Private Class Methods
@api private
# File lib/whois/parser.rb, line 333 def self.define_method_method(method) class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method}(*args, &block) delegate_method_to_parsers(:#{method}, *args, &block) end RUBY end
@api private
# File lib/whois/parser.rb, line 324 def self.define_property_method(method) class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method}(*args, &block) delegate_property_to_parsers(:#{method}, *args, &block) end RUBY end
Public Instance Methods
Loop through all the record parts to check if at least one part changed.
@param [Whois::Parser] other The other parser instance to compare. @return [Boolean]
@see Whois::Record#changed? @see Whois::Parsers::Base#changed?
# File lib/whois/parser.rb, line 260 def changed?(other) !unchanged?(other) end
Collects and returns all the contacts from all the record parts.
@return [Array<Whois::Record::Contact>]
@see Whois::Record#contacts @see Whois::Parsers::Base#contacts
# File lib/whois/parser.rb, line 242 def contacts parsers.map(&:contacts).flatten end
Returns an array with all host-specific parsers initialized for the parts contained into this parser. The array is lazy-initialized.
@return [Array<Whois::Parsers::Base>]
# File lib/whois/parser.rb, line 208 def parsers @parsers ||= init_parsers end
Checks if the property
passed as symbol is “not implemented” in any of the parsers.
@return [Boolean]
# File lib/whois/parser.rb, line 228 def property_any_not_implemented?(property) parsers.any? { |parser| parser.class.property_state?(property, Whois::Parser::PROPERTY_STATE_NOT_IMPLEMENTED) } end
Checks if the property
passed as symbol is supported in any of the parsers.
@return [Boolean]
@see Whois::Parsers::Base.property_supported?
# File lib/whois/parser.rb, line 219 def property_any_supported?(property) parsers.any? { |parser| parser.property_supported?(property) } end
Checks if this class respond to given method.
Overrides the default implementation to add support for {PROPERTIES} and {METHODS}.
@return [Boolean]
# File lib/whois/parser.rb, line 197 def respond_to?(symbol, include_private = false) respond_to_parser_method?(symbol) || super end
Loop through all the parts to check if at least one part is an incomplete response.
@return [Boolean]
@see Whois::Record#response_incomplete? @see Whois::Parsers::Base#response_incomplete?
# File lib/whois/parser.rb, line 290 def response_incomplete? any_is?(parsers, :response_incomplete?) end
Loop through all the parts to check if at least one part is a throttle response.
@return [Boolean]
@see Whois::Record#response_throttled? @see Whois::Parsers::Base#response_throttled?
# File lib/whois/parser.rb, line 302 def response_throttled? any_is?(parsers, :response_throttled?) end
The opposite of {#changed?}.
@param [Whois::Parser] other The other parser instance to compare. @return [Boolean]
@see Whois::Record#unchanged? @see Whois::Parsers::Base#unchanged?
# File lib/whois/parser.rb, line 272 def unchanged?(other) unless other.is_a?(self.class) raise(ArgumentError, "Can't compare `#{self.class}' with `#{other.class}'") end equal?(other) || parsers.size == other.parsers.size && all_in_parallel?(parsers, other.parsers) { |one, two| one.unchanged?(two) } end
Private Instance Methods
@api private
# File lib/whois/parser.rb, line 427 def all_in_parallel?(*args) count = args.first.size index = 0 while index < count return false unless yield(*args.map { |arg| arg[index] }) index += 1 end true end
@api private
# File lib/whois/parser.rb, line 439 def any_is?(collection, symbol) collection.any? { |item| item.is(symbol) } end
# File lib/whois/parser.rb, line 369 def delegate_method_to_parsers(method, *args, &block) if parsers.empty? raise ParserError, "Unable to select a parser because the Record is empty" elsif (parser = select_parser { |p| p.respond_to?(method) }) parser.send(method, *args, &block) else nil end end
# File lib/whois/parser.rb, line 357 def delegate_property_to_parsers(method, *args, &block) if parsers.empty? raise ParserError, "Unable to select a parser because the Record is empty" elsif (parser = select_parser { |p| p.class.property_state?(method, PROPERTY_STATE_SUPPORTED) }) parser.send(method, *args, &block) elsif (parser = select_parser { |p| p.class.property_state?(method, PROPERTY_STATE_NOT_SUPPORTED) }) parser.send(method, *args, &block) else raise AttributeNotImplemented, "Unable to find a parser for property `#{method}'" end end
Loops through all record parts, for each part tries to guess the appropriate parser object whenever available, and returns the final array of server-specific parsers.
Parsers
are initialized in reverse order for performance reason.
@return [Array<Class>] An array of Class,
where each item is the parts reverse-N specific parser {Class}. Each {Class} is expected to be a child of {Whois::Parsers::Base}.
@example
parser.parts # => [whois.foo.com, whois.bar.com] parser.parsers # => [Whois::Parsers::WhoisBarCom, Whois::Parsers::WhoisFooCom]
@api private
# File lib/whois/parser.rb, line 398 def init_parsers record.parts.reverse.map { |part| self.class.parser_for(part) } end
Whois::ParserExtensions::WhoisRecord#method_missing
# File lib/whois/parser.rb, line 345 def method_missing(method, *args, &block) if PROPERTIES.include?(method) self.class.define_property_method(method) send(method, *args, &block) elsif METHODS.include?(method) self.class.define_method_method(method) send(method, *args, &block) else super end end
# File lib/whois/parser.rb, line 341 def respond_to_parser_method?(symbol) PROPERTIES.include?(symbol) || METHODS.include?(symbol) end
Selects the first parser in {#parsers} where blocks evaluates to true.
@return [Whois::Parsers::Base]
The parser for which the block returns true.
@return [nil]
If the parser wasn't found.
@yield [parser]
@example
select_parser { |parser| parser.class.property_state?(:nameserver, :any) } # => #<Whois::Parsers::WhoisExampleCom> select_parser { |parser| parser.class.property_state?(:nameservers, PROPERTY_STATE_SUPPORTED) } # => nil
@api private
# File lib/whois/parser.rb, line 419 def select_parser(&block) parsers.each do |parser| return parser if block.call(parser) end nil end