module Fluent::Plugin

def self.add_plugin_dir(dir)

def self.add_plugin_dir(dir)
  REGISTRIES.each do |r|
    r.paths.push(dir)
  end
  nil
end

def self.lookup_type_from_class(klass_or_its_name)

def self.lookup_type_from_class(klass_or_its_name)
  klass = if klass_or_its_name.is_a? Class
            klass_or_its_name
          elsif klass_or_its_name.is_a? String
            eval(klass_or_its_name) # const_get can't handle qualified klass name (ex: A::B)
          else
            raise ArgumentError, "invalid argument type #{klass_or_its_name.class}: #{klass_or_its_name}"
          end
  REGISTRIES.reduce(nil){|a, r| a || r.reverse_lookup(klass) }
end

def self.new_buffer(type, parent: nil)

def self.new_buffer(type, parent: nil)
  new_impl('buffer', BUFFER_REGISTRY, type, parent)
end

def self.new_filter(type)

def self.new_filter(type)
  new_impl('filter', FILTER_REGISTRY, type)
end

def self.new_formatter(type, parent: nil)

def self.new_formatter(type, parent: nil)
  new_impl('formatter', FORMATTER_REGISTRY, type, parent)
end

def self.new_impl(kind, registry, type, parent=nil)

def self.new_impl(kind, registry, type, parent=nil)
  # "'type' not found" is handled by registry
  obj = registry.lookup(type)
  impl = case
         when obj.is_a?(Class)
           obj.new
         when obj.respond_to?(:call) && obj.arity == 0
           obj.call
         else
           raise Fluent::ConfigError, "#{kind} plugin '#{type}' is not a Class nor callable (without arguments)."
         end
  if parent && impl.respond_to?("owner=")
    impl.owner = parent
  end
  impl.extend FeatureAvailabilityChecker
  impl
end

def self.new_input(type)

def self.new_input(type)
  new_impl('input', INPUT_REGISTRY, type)
end

def self.new_output(type)

def self.new_output(type)
  new_impl('output', OUTPUT_REGISTRY, type)
end

def self.new_parser(type, parent: nil)

def self.new_parser(type, parent: nil)
  if type[0] == '/' && type[-1] == '/'
    # This usage is not recommended for new API... create RegexpParser directly
    require 'fluent/parser'
    impl = Fluent::TextParser.lookup(type)
    impl.extend FeatureAvailabilityChecker
    impl
  else
    new_impl('parser', PARSER_REGISTRY, type, parent)
  end
end

def self.new_storage(type, parent: nil)

def self.new_storage(type, parent: nil)
  new_impl('storage', STORAGE_REGISTRY, type, parent)
end

def self.register_buffer(type, klass)

def self.register_buffer(type, klass)
  register_impl('buffer', BUFFER_REGISTRY, type, klass)
end

def self.register_filter(type, klass)

def self.register_filter(type, klass)
  register_impl('filter', FILTER_REGISTRY, type, klass)
end

def self.register_formatter(type, klass_or_proc)

def self.register_formatter(type, klass_or_proc)
  if klass_or_proc.respond_to?(:call) && klass_or_proc.arity == 3 # Proc.new { |tag, time, record| }
    # This usage is not recommended for new API
    require 'fluent/formatter'
    register_impl('formatter', FORMATTER_REGISTRY, type, Proc.new { Fluent::TextFormatter::ProcWrappedFormatter.new(klass_or_proc) })
  else
    register_impl('formatter', FORMATTER_REGISTRY, type, klass_or_proc)
  end
end

def self.register_impl(kind, registry, type, value)

def self.register_impl(kind, registry, type, value)
  if !value.is_a?(Class) && !value.respond_to?(:call)
    raise Fluent::ConfigError, "Invalid implementation as #{kind} plugin: '#{type}'. It must be a Class, or callable."
  end
  registry.register(type, value)
  $log.trace "registered #{kind} plugin '#{type}'" if defined?($log)
  nil
end

def self.register_input(type, klass)

def self.register_input(type, klass)
  register_impl('input', INPUT_REGISTRY, type, klass)
end

def self.register_output(type, klass)

def self.register_output(type, klass)
  register_impl('output', OUTPUT_REGISTRY, type, klass)
end

def self.register_parser(type, klass_or_proc)

def self.register_parser(type, klass_or_proc)
  if klass_or_proc.is_a?(Regexp)
    # This usage is not recommended for new API
    require 'fluent/parser'
    register_impl('parser', PARSER_REGISTRY, type, Proc.new { Fluent::TextParser::RegexpParser.new(klass_or_proc) })
  else
    register_impl('parser', PARSER_REGISTRY, type, klass_or_proc)
  end
end

def self.register_storage(type, klass)

def self.register_storage(type, klass)
  register_impl('storage', STORAGE_REGISTRY, type, klass)
end