class Whois::Parser

Constants

METHODS
PROPERTIES
PROPERTY_STATE_NOT_IMPLEMENTED
PROPERTY_STATE_NOT_SUPPORTED
PROPERTY_STATE_SUPPORTED
VERSION

The current library version.

Attributes

record[R]

@return [Whois::Record] The record referenced by this parser.

Public Class Methods

autoload(name) click to toggle source

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
bug!(error, message) click to toggle source

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
host_to_parser(host) click to toggle source

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
new(record) click to toggle source

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
parser_for(part) click to toggle source

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
parser_klass(host) click to toggle source

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

define_method_method(method) click to toggle source

@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
define_property_method(method) click to toggle source

@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

changed?(other) click to toggle source

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
contacts() click to toggle source

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
parsers() click to toggle source

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
property_any_not_implemented?(property) click to toggle source

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
property_any_supported?(property) click to toggle source

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
respond_to?(symbol, include_private = false) click to toggle source

Checks if this class respond to given method.

Overrides the default implementation to add support for {PROPERTIES} and {METHODS}.

@return [Boolean]

Calls superclass method
# File lib/whois/parser.rb, line 197
def respond_to?(symbol, include_private = false)
  respond_to_parser_method?(symbol) || super
end
response_incomplete?() click to toggle source

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
response_throttled?() click to toggle source

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
response_unavailable?() click to toggle source

Loop through all the parts to check if at least one part is an unavailable response.

@return [Boolean]

@see Whois::Record#response_unavailable? @see Whois::Parsers::Base#response_unavailable?

# File lib/whois/parser.rb, line 314
def response_unavailable?
  any_is?(parsers, :response_unavailable?)
end
unchanged?(other) click to toggle source

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

all_in_parallel?(*args) { |*map { |arg| arg }| ... } click to toggle source

@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
any_is?(collection, symbol) click to toggle source

@api private

# File lib/whois/parser.rb, line 439
def any_is?(collection, symbol)
  collection.any? { |item| item.is(symbol) }
end
delegate_method_to_parsers(method, *args, &block) click to toggle source
# 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
delegate_property_to_parsers(method, *args, &block) click to toggle source
# 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
init_parsers() click to toggle source

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
method_missing(method, *args, &block) click to toggle source
# 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
respond_to_parser_method?(symbol) click to toggle source
# File lib/whois/parser.rb, line 341
def respond_to_parser_method?(symbol)
  PROPERTIES.include?(symbol) || METHODS.include?(symbol)
end
select_parser(&block) click to toggle source

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