lib/core/environment.rb in nucleon-0.2.2 vs lib/core/environment.rb in nucleon-0.2.3

- old
+ new

@@ -1,341 +1,761 @@ - module Nucleon -class Environment - - #----------------------------------------------------------------------------- +# +# == Plugin environment +# +# The Nucleon::Environment class defines a container for registered plugins and +# autoloaded providers. +# +# One of the primary functions of the Nucleon library is to provide a very +# flexible extensible architectural base for Ruby applications needing ready +# made modularity. To fulfill our objectives, the Nucleon library defines +# plugin managers managed as a global multition. +# +# These managers should be able to fail gracefully and recover to the state +# they left off if a plugin provider crashes. To acomplish this, each manager +# is a Celluloid actor that manages a globally defined environment (also within +# a multition). This environment contains all of the plugins and providers +# that they manager has registered and loaded. +# +# Three collections are managed: +# +# 1. Defined plugin types +# +# The environment maintains a collection of registered plugin types with a +# default provider. Default providers can easily be changed in runtime as +# needs change. +# +# 2. Plugin load info +# +# Whenever a plugin is defined and initialized by the manager a specification +# is created and maintained that lets the manager know details about the +# plugin, such as where the base plugin resides, namespace, type, etc... +# +# 3. Active plugins +# +# The environment maintains a registry of all of the plugin instances across +# the application. These active plugins are accessed by the manager, usually +# through the facade. When we work with plugins in the application, we are +# usually working with these instances. +# +# +# See also: +# - Nucleon::Manager +# - Nucleon::Plugin::Base +# +class Environment < Core + + #***************************************************************************** # Constructor / Destructor - + + # Initialize a new Nucleon environment + # + # IMORTANT: The environment constructor should accept no parameters! + # + # * *Parameters* + # + # * *Returns* + # - [Void] This method does not return a value + # + # * *Errors* + # + # See also: + # - Nucleon::Manager + # def initialize - @plugin_types = {} - - @load_info = {} - @active_info = {} + super({ + :plugin_types => {}, + :load_info => {}, + :active_info => {} + }, {}, true, true, false) + + @instance_map = Config.new end - - #----------------------------------------------------------------------------- + + #***************************************************************************** # Plugin type accessor / modifiers - + + # Return all of the defined namespaces in the plugin environment. + # + # * *Parameters* + # + # * *Returns* + # - [Array<Symbol>] Array of defined plugin namespaces + # + # * *Errors* + # + # See: + # - Nucleon::Config#get_hash + # def namespaces - @plugin_types.keys + get_hash(:plugin_types).keys end - - #--- - + + # Return all of the defined plugin types in a plugin namespace. + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # + # * *Returns* + # - [Array<Symbol>] Array of defined plugin types + # + # * *Errors* + # + # See: + # - Nucleon::Config#get_hash + # def plugin_types(namespace) - namespace = namespace.to_sym - - return [] unless @plugin_types.has_key?(namespace) - @plugin_types[namespace].keys + get_hash([ :plugin_types, namespace ]).keys end - - #--- - + + # Define a new plugin type in a specified namespace. + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name within namespace + # - [nil, String, Symbol] *default_provider* Default provider (defaults to none) + # + # * *Returns* + # - [Nucleon::Environment] Returns reference to self for compound operations + # + # * *Errors* + # + # See: + # - Nucleon::Config#set + # + # See also: + # - #sanitize_id + # def define_plugin_type(namespace, plugin_type, default_provider = nil) - namespace = namespace.to_sym - - @plugin_types[namespace] = {} unless @plugin_types.has_key?(namespace) - @plugin_types[namespace][sanitize_id(plugin_type)] = default_provider + set([ :plugin_types, namespace, sanitize_id(plugin_type) ], default_provider) end - - #--- - + + # Define one or more new plugin types in a specified namespace. + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [Hash<String, Symbol|String, Symbol>] *type_info* Plugin type, default provider pairs + # + # * *Returns* + # - [Nucleon::Environment] Returns reference to self for compound operations + # + # * *Errors* + # + # See: + # - #define_plugin_type + # def define_plugin_types(namespace, type_info) if type_info.is_a?(Hash) type_info.each do |plugin_type, default_provider| define_plugin_type(namespace, plugin_type, default_provider) end end + self end - - #--- - + + # Check if a specified plugin type has been defined + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name to check within namespace + # + # * *Returns* + # - [Boolean] Returns true if plugin type exists, false otherwise + # + # * *Errors* + # + # See: + # - Nucleon::Config#get_hash + # + # See also: + # - #sanitize_id + # def plugin_type_defined?(namespace, plugin_type) - namespace = namespace.to_sym - - return false unless @plugin_types.has_key?(namespace) - @plugin_types[namespace].has_key?(sanitize_id(plugin_type)) + get_hash([ :plugin_types, namespace ]).has_key?(sanitize_id(plugin_type)) end - - #--- - + + # Return the default provider currently registered for a plugin type + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name to fetch default provider + # + # * *Returns* + # - [nil, Symbol] Returns default provider if plugin type exists, nil otherwise + # + # * *Errors* + # + # See: + # - Nucleon::Config#get + # + # See also: + # - #sanitize_id + # def plugin_type_default(namespace, plugin_type) - namespace = namespace.to_sym - - return nil unless @plugin_types.has_key?(namespace) - @plugin_types[namespace][sanitize_id(plugin_type)] + get([ :plugin_types, namespace, sanitize_id(plugin_type) ]) end - - #----------------------------------------------------------------------------- + + + #***************************************************************************** # Loaded plugin accessor / modifiers - - def define_plugin(namespace, plugin_type, base_path, file, &code) + + # Define a new plugin provider of a specified plugin type. + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name to fetch default provider + # - [String] *base_path* Base load path of the plugin provider + # - [String] *file* File that contains the provider definition + # + # * *Returns* + # - [Nucleon::Environment] Returns reference to self for compound operations + # + # * *Errors* + # + # * *Yields* + # - [Hash<Symbol|ANY>] *data* Plugin load information + # + # See: + # - Nucleon::Config#get_hash + # - Nucleon::Config#set + # + # See also: + # - #sanitize_id + # - #parse_plugin_info + # + def define_plugin(namespace, plugin_type, base_path, file, &code) # :yields: data namespace = namespace.to_sym plugin_type = sanitize_id(plugin_type) - - @load_info[namespace] = {} unless @load_info.has_key?(namespace) - @load_info[namespace][plugin_type] = {} unless @load_info[namespace].has_key?(plugin_type) - plugin_info = parse_plugin_info(namespace, plugin_type, base_path, file) - - unless @load_info[namespace][plugin_type].has_key?(plugin_info[:provider]) + + unless get_hash([ :load_info, namespace, plugin_type ]).has_key?(plugin_info[:provider]) data = { :namespace => namespace, :type => plugin_type, :base_path => base_path, :file => file, - :provider => plugin_info[:provider], - :directory => plugin_info[:directory], + :provider => plugin_info[:provider], + :directory => plugin_info[:directory], :class_components => plugin_info[:class_components] } code.call(data) if code - - @load_info[namespace][plugin_type][plugin_info[:provider]] = data + + set([ :load_info, namespace, plugin_type, plugin_info[:provider] ], data) end + self end - - #--- - + + # Return the load information for a specified plugin provider if it exists + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name of provider + # - [String, Symbol] *provider* Plugin provider to return load information + # + # * *Returns* + # - [nil, Hash<Symbol|ANY>] Returns provider load information if provider exists, nil otherwise + # + # * *Errors* + # + # See: + # - Nucleon::Config#get + # + # See also: + # - #sanitize_id + # def loaded_plugin(namespace, plugin_type, provider) - namespace = namespace.to_sym - plugin_type = sanitize_id(plugin_type) - provider = sanitize_id(provider) - info = nil - - if @load_info.has_key?(namespace) && - @load_info[namespace].has_key?(plugin_type) && - @load_info[namespace][plugin_type].has_key?(provider) - - info = @load_info[namespace][plugin_type][provider] - end - info + get([ :load_info, namespace, sanitize_id(plugin_type), sanitize_id(provider) ], nil) end - - #--- - + + # Return the load information for namespaces, plugin types, providers if it exists + # + # * *Parameters* + # - [nil, String, Symbol] *namespace* Namespace to return load information + # - [nil, String, Symbol] *plugin_type* Plugin type name to return load information + # - [nil, String, Symbol] *provider* Plugin provider to return load information + # - [ANY] *default* Default results if nothing found (empty hash by default) + # + # * *Returns* + # - [nil, Hash<Symbol|Symbol|Symbol|Symbol|ANY>] Returns all load information if no parameters given + # - [nil, Hash<Symbol|Symbol|Symbol|ANY>] Returns namespace load information if only namespace given + # - [nil, Hash<Symbol|Symbol|ANY>] Returns plugin type load information if namespace and plugin type given + # - [nil, Hash<Symbol|ANY>] Returns provider load information if namespace, plugin type, and provider given + # + # * *Errors* + # + # See: + # - Nucleon::Config#get_hash + # + # See also: + # - #sanitize_id + # def loaded_plugins(namespace = nil, plugin_type = nil, provider = nil, default = {}) + load_info = get_hash(:load_info) + namespace = namespace.to_sym if namespace plugin_type = sanitize_id(plugin_type) if plugin_type provider = sanitize_id(provider) if provider results = default - - if namespace && @load_info.has_key?(namespace) - if plugin_type && @load_info[namespace].has_key?(plugin_type) - if provider && @load_info[namespace][plugin_type].has_key?(provider) - results = @load_info[namespace][plugin_type][provider] + + if namespace && load_info.has_key?(namespace) + if plugin_type && load_info[namespace].has_key?(plugin_type) + if provider && load_info[namespace][plugin_type].has_key?(provider) + results = load_info[namespace][plugin_type][provider] elsif ! provider - results = @load_info[namespace][plugin_type] + results = load_info[namespace][plugin_type] end elsif ! plugin_type - results = @load_info[namespace] + results = load_info[namespace] end elsif ! namespace - results = @load_info + results = load_info end results end - - #--- - + + # Check if a specified plugin type has been loaded + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name to check + # + # * *Returns* + # - [Boolean] Returns true if plugin type has been loaded, false otherwise + # + # * *Errors* + # + # See: + # - Nucleon::Config#get_hash + # + # See also: + # - #sanitize_id + # def plugin_has_type?(namespace, plugin_type) - namespace = namespace.to_sym - - return false unless @load_info.has_key?(namespace) - @load_info[namespace].has_key?(sanitize_id(plugin_type)) + get_hash([ :load_info, namespace ]).has_key?(sanitize_id(plugin_type)) end - - #--- - + + # Check if a specified plugin provider has been loaded + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name to check + # - [String, Symbol] *provider* Plugin provider name to check + # + # * *Returns* + # - [Boolean] Returns true if plugin provider has been loaded, false otherwise + # + # * *Errors* + # + # See: + # - Nucleon::Config#get_hash + # + # See also: + # - #sanitize_id + # def plugin_has_provider?(namespace, plugin_type, provider) - namespace = namespace.to_sym - plugin_type = sanitize_id(plugin_type) - provider = sanitize_id(provider) - - return false unless @load_info.has_key?(namespace) && @load_info[namespace].has_key?(plugin_type) - @load_info[namespace][plugin_type].has_key?(provider) + get_hash([ :load_info, namespace, sanitize_id(plugin_type) ]).has_key?(sanitize_id(provider)) end - - #----------------------------------------------------------------------------- + + # Autoload all of the defined plugins + # + # * *Parameters* + # + # * *Returns* + # - [Void] This method does not return a value + # + # * *Errors* + # - TODO + # + # * *Yields* + # - [Symbol] *namespace* Plugin namespace + # - [Symbol] *plugin_type* Plugin type + # - [Symbol] *provider* Plugin provider + # - [Hash<Symbol|ANY>] *plugin* Plugin load information + # + # See: + # - #loaded_plugins + # - #class_const + # + def autoload # :yields: namespace, plugin_type, provider, plugin + load_info = loaded_plugins + + load_info.keys.each do |namespace| + load_info[namespace].keys.each do |plugin_type| + load_info[namespace][plugin_type].each do |provider, plugin| + require plugin[:file] + + load_info[namespace][plugin_type][provider][:class] = class_const(plugin[:class_components]) + + yield(namespace, plugin_type, provider, plugin) if block_given? + end + end + end + end + + + #***************************************************************************** # Active plugin accessor / modifiers - - def create_plugin(namespace, plugin_type, provider, options = {}, &code) + + # Create a new plugin instance of a specified provider + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name of provider + # - [String, Symbol] *provider* Plugin provider to return load information + # - [Hash] *options* Create options (plugin initialization configurations) + # + # * *Returns* + # - [nil, Nucleon::Plugin::Base] Returns plugin instance (inherited from Nucleon::Plugin::Base) + # + # * *Errors* + # + # * *Yields* + # - [nil, Hash<Symbol|ANY>] *type_info* Provider load information if it has been loaded + # - [Hash] *options* Create options (plugin initialization configurations) + # + # See: + # - Nucleon::Plugin::Base + # - Nucleon::Config#get + # - Nucleon::Config#set + # + # See also: + # - #sanitize_id + # - #plugin_type_defined? + # - #loaded_plugin + # - Nucleon::Config + # - Nucleon::Config::array + # - Nucleon::Util::Data::subset + # - Nucleon::Facade#sha1 + # + def create_plugin(namespace, plugin_type, provider, options = {}, &code) # :yields: type_info, options namespace = namespace.to_sym plugin_type = sanitize_id(plugin_type) provider = sanitize_id(provider) - + options = Util::Data.clone(options) + plugin = nil + result = nil + unless plugin_type_defined?(namespace, plugin_type) - return nil + return plugin end - - if type_info = loaded_plugin(namespace, plugin_type, provider) - ids = Util::Data.array(type_info[:class].register_ids).flatten + + if type_info = Util::Data.clone(loaded_plugin(namespace, plugin_type, provider)) + ids = array(type_info[:class].register_ids).flatten instance_config = Config.new(options) ensure_new = instance_config.delete(:new, false) - - instance_options = Util::Data.subset(instance_config.export, ids, true) + + instance_options = Util::Data.subset(instance_config.export, ids, true) instance_name = "#{provider}_" + Nucleon.sha1(instance_options) - - @active_info[namespace] = {} unless @active_info.has_key?(namespace) - @active_info[namespace][plugin_type] = {} unless @active_info[namespace].has_key?(plugin_type) - - if ensure_new || ! ( instance_name && @active_info[namespace][plugin_type].has_key?(instance_name) ) + plugin = get([ :active_info, namespace, plugin_type, instance_name ]) + + if ensure_new || ! ( instance_name && plugin ) type_info[:instance_name] = instance_name - - options = code.call(type_info, options) if code - plugin = type_info[:class].new(namespace, plugin_type, provider, options) - - @active_info[namespace][plugin_type][instance_name] = plugin + + result = code.call(type_info, options) if code + options = result if result.is_a?(Hash) + + options[:meta] = Config.new(type_info).import(hash(options[:meta])) + + options.delete(:new) + + plugin = type_info[:class].new(namespace, plugin_type, provider, options) + set([ :active_info, namespace, plugin_type, instance_name ], plugin) + + @instance_map.append([ namespace, plugin_type, plugin.plugin_name.to_sym ], instance_name.to_sym) end - return @active_info[namespace][plugin_type][instance_name] - end - nil + end + plugin end - - #--- - + + # Return a plugin instance by name if it exists + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains the plugin + # - [String, Symbol] *plugin_type* Plugin type name + # - [String, Symbol] *plugin_name* Plugin name to return + # + # * *Returns* + # - [nil, Nucleon::Plugin::Base] Returns a plugin instance of name specified if it exists + # + # * *Errors* + # + # See: + # - Nucleon::Plugin::Base + # - Nucleon::Config#get_hash + # + # See also: + # - #sanitize_id + # def get_plugin(namespace, plugin_type, plugin_name) - namespace = namespace.to_sym - plugin_type = sanitize_id(plugin_type) - - if @active_info.has_key?(namespace) && @active_info[namespace].has_key?(plugin_type) - @active_info[namespace][plugin_type].each do |instance_name, plugin| - if plugin.plugin_name.to_s == plugin_name.to_s - return plugin - end - end + namespace = namespace.to_sym + plugin_type = sanitize_id(plugin_type) + + instances = get_hash([ :active_info, namespace, plugin_type ]) + instance_ids = array(@instance_map.get([ namespace, plugin_type, plugin_name.to_s.to_sym ])) + + if instance_ids.size + return instances[instance_ids[0]] end - nil + nil end - - #--- - - def remove_plugin(namespace, plugin_type, instance_name, &code) - namespace = namespace.to_sym - plugin_type = sanitize_id(plugin_type) - - if @active_info.has_key?(namespace) && @active_info[namespace].has_key?(plugin_type) - plugin = @active_info[namespace][plugin_type] - @active_info[namespace][plugin_type].delete(instance_name) - code.call(plugin) if code - end + + # Remove a plugin instance from the environment + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains the plugin + # - [String, Symbol] *plugin_type* Plugin type name + # - [String, Symbol] *instance_name* Plugin instance name to tremove + # + # * *Returns* + # - [nil, Nucleon::Plugin::Base] Returns the plugin instance that was removed from environment + # + # * *Errors* + # + # * *Yields* + # - [Nucleon::Plugin::Base] *plugin* Plugin object being removed (cleanup) + # + # See: + # - Nucleon::Plugin::Base + # - Nucleon::Config#delete + # + # See also: + # - #sanitize_id + # + def remove_plugin(namespace, plugin_type, instance_name, &code) # :yields: plugin + plugin = delete([ :active_info, namespace, sanitize_id(plugin_type), instance_name ]) + code.call(plugin) if code && plugin + plugin end - - #--- - + + # Return active plugins for namespaces, plugin types, providers if specified + # + # * *Parameters* + # - [nil, String, Symbol] *namespace* Namespace to return plugin instance + # - [nil, String, Symbol] *plugin_type* Plugin type name to return plugin instance + # - [nil, String, Symbol] *provider* Plugin provider to return plugin instance + # + # * *Returns* + # - [nil, Hash<Symbol|Symbol|Symbol|Symbol|Nucleon::Plugin::Base>] Returns all plugin instances if no parameters given + # - [nil, Hash<Symbol|Symbol|Symbol|Nucleon::Plugin::Base>] Returns namespace plugin instances if only namespace given + # - [nil, Hash<Symbol|Symbol|Nucleon::Plugin::Base>] Returns plugin type instances if namespace and plugin type given + # - [nil, Hash<Symbol|Nucleon::Plugin::Base>] Returns provider instances if namespace, plugin type, and provider given + # + # * *Errors* + # + # See: + # - Nucleon::Config#get_hash + # + # See also: + # - #sanitize_id + # def active_plugins(namespace = nil, plugin_type = nil, provider = nil) + active_info = get_hash(:active_info) + namespace = namespace.to_sym if namespace plugin_type = sanitize_id(plugin_type) if plugin_type provider = sanitize_id(provider) if provider results = {} - - if namespace && @active_info.has_key?(namespace) - if plugin_type && @active_info[namespace].has_key?(plugin_type) - if provider && ! @active_info[namespace][plugin_type].keys.empty? - @active_info[namespace][plugin_type].each do |instance_name, plugin| - plugin = @active_info[namespace][plugin_type][instance_name] + + if namespace && active_info.has_key?(namespace) + if plugin_type && active_info[namespace].has_key?(plugin_type) + if provider && ! active_info[namespace][plugin_type].keys.empty? + active_info[namespace][plugin_type].each do |instance_name, plugin| + plugin = active_info[namespace][plugin_type][instance_name] results[instance_name] = plugin if plugin.plugin_provider == provider end elsif ! provider - results = @active_info[namespace][plugin_type] + results = active_info[namespace][plugin_type] end elsif ! plugin_type - results = @active_info[namespace] + results = active_info[namespace] end elsif ! namespace - results = @active_info - end + results = active_info + end results - end - - #----------------------------------------------------------------------------- + end + + #***************************************************************************** # Utilities - - def class_name(name, separator = '::', want_array = FALSE) + + # Return a fully formed class name as a string + # + # * *Parameters* + # - [String, Symbol, Array] *name* Class name components + # - [String, Symbol] *separator* Class component separator (default '::') + # - [Boolean] *want_array* Whether or not to return array of final components or string version + # + # * *Returns* + # - [String] Returns fully rendered class name as string unless want_array is true + # - [Array] Returns array of final class components if want_array is true + # + # * *Errors* + # + def class_name(name, separator = '::', want_array = false) components = [] - + case name when String, Symbol components = name.to_s.split(separator) when Array - components = name + components = name.flatten end - + components.collect! do |value| - value = value.to_s.strip - value[0] = value.capitalize[0] if value =~ /^[a-z]/ + value = value.to_s.strip + value[0] = value.capitalize[0] if value =~ /^[a-z]/ value end - + if want_array return components - end + end components.join(separator) end - - #--- - + + # Return a fully formed class name as a machine usable constant + # + # * *Parameters* + # - [String, Symbol, Array] *name* Class name components + # - [String, Symbol] *separator* Class component separator (default '::') + # + # * *Returns* + # - [Class Constant] Returns class constant for fully formed class name of given components + # + # * *Errors* + # + # See also: + # - #class_name + # def class_const(name, separator = '::') components = class_name(name, separator, TRUE) constant = Object - + components.each do |component| - constant = constant.const_defined?(component) ? - constant.const_get(component) : + constant = constant.const_defined?(component) ? + constant.const_get(component) : constant.const_missing(component) end constant end - - #--- - + + # Sanitize an identifier for internal plugin environment use. + # + # * *Parameters* + # - [String, Symbol] *id_component* Identifier to sanitize + # + # * *Returns* + # - [Symbol] Returns a sanitized symbol representing the given id component + # + # * *Errors* + # def sanitize_id(id_component) id_component.to_s.gsub(/([a-z0-9])(?:\-|\_)?([A-Z])/, '\1_\2').downcase.to_sym end protected :sanitize_id - - #--- - + + # Sanitize a class identifier for internal use. + # + # * *Parameters* + # - [String, Symbol] *class_component* Class identifier to sanitize + # + # * *Returns* + # - [String] Returns a sanitized string representing the given class component + # + # * *Errors* + # def sanitize_class(class_component) - class_component.to_s.split('_').collect {|elem| elem.slice(0,1).capitalize + elem.slice(1..-1) }.join('') + class_component.to_s.split('_').collect {|elem| elem.slice(0,1).capitalize + elem.slice(1..-1) }.join('') end protected :sanitize_class - - #--- - + + # Return a class constant representing a base plugin class generated from namespace and plugin_type. + # + # * *Parameters* + # - [String, Symbol] *namespace* Plugin namespace to constantize + # - [String, Symbol] *plugin_type* Plugin type to constantize + # + # * *Returns* + # - [String] Returns a class constant representing the plugin namespace and type + # + # * *Errors* + # + # See also: + # - #class_const + # - #sanitize_class + # def plugin_class(namespace, plugin_type) - class_const([ sanitize_class(namespace), :plugin, sanitize_class(plugin_type) ]) + class_const([ sanitize_class(namespace), :plugin, sanitize_class(plugin_type) ]) end - - #--- - + + # Return a class constant representing a plugin provider class generated from + # namespace, plugin_type, and provider name. + # + # The provider name can be entered as an array if it is included in sub modules. + # + # * *Parameters* + # - [String, Symbol] *namespace* Plugin namespace to constantize + # - [String, Symbol] *plugin_type* Plugin type to constantize + # - [String, Symbol, Array] *provider* Plugin provider name to constantize + # + # * *Returns* + # - [String] Returns a class constant representing the plugin provider + # + # * *Errors* + # + # See also: + # - #class_const + # - #sanitize_class + # + def provider_class(namespace, plugin_type, provider) + class_const([ sanitize_class(namespace), sanitize_class(plugin_type), provider ]) + end + + # Parse plugin information for a specified namespace and plugin type. + # + # * *Parameters* + # - [String, Symbol] *namespace* Namespace that contains plugin types + # - [String, Symbol] *plugin_type* Plugin type name to fetch default provider + # - [String] *base_path* Base load path of the plugin provider + # - [String] *file* File that contains the provider definition + # + # * *Returns* + # - [Hash<Symbol|ANY>] Returns a hash of the parsed plugin information + # + # * *Errors* + # + # See also: + # - #sanitize_id + # - #sanitize_class + # def parse_plugin_info(namespace, plugin_type, base_path, file) - dir_components = base_path.split(File::SEPARATOR) + dir_components = base_path.split(File::SEPARATOR) file_components = file.split(File::SEPARATOR) - + file_name = file_components.pop.sub(/\.rb/, '') directory = file_components.join(File::SEPARATOR) - + file_class = sanitize_class(file_name) group_components = directory.sub(/^#{base_path}#{File::SEPARATOR}?/, '').split(File::SEPARATOR) - + class_components = [ sanitize_class(namespace), sanitize_class(plugin_type) ] - - if ! group_components.empty? + + if ! group_components.empty? group_name = group_components.collect {|elem| elem.downcase }.join('_') provider = [ group_name, file_name ].join('_') - + group_components = group_components.collect {|elem| sanitize_class(elem) } class_components = [ class_components, group_components, file_class ].flatten else provider = file_name class_components = [ class_components, file_class ].flatten end - - { - :directory => directory, - :provider => sanitize_id(provider), + + { + :directory => directory, + :provider => sanitize_id(provider), :class_components => class_components - } + } end protected :parse_plugin_info end end