class Nucleon::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:

Public Class Methods

new() click to toggle source

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:

Calls superclass method Nucleon::Core::new
   # File lib/core/environment.rb
64 def initialize
65   super({
66     :plugin_types => {},
67     :load_info    => {},
68     :active_info  => {}
69   }, {}, true, true, false)
70 
71   @instance_map = Config.new
72 end

Public Instance Methods

active_plugins(namespace = nil, plugin_type = nil, provider = nil) click to toggle source

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:

See also:

    # File lib/core/environment.rb
550 def active_plugins(namespace = nil, plugin_type = nil, provider = nil)
551   active_info = get_hash(:active_info)
552 
553   namespace   = namespace.to_sym if namespace
554   plugin_type = sanitize_id(plugin_type) if plugin_type
555   provider    = sanitize_id(provider) if provider
556   results     = {}
557 
558   if namespace && active_info.has_key?(namespace)
559     if plugin_type && active_info[namespace].has_key?(plugin_type)
560       if provider && ! active_info[namespace][plugin_type].keys.empty?
561         active_info[namespace][plugin_type].each do |instance_name, plugin|
562           plugin                 = active_info[namespace][plugin_type][instance_name]
563           results[instance_name] = plugin if plugin.plugin_provider == provider
564         end
565       elsif ! provider
566         results = active_info[namespace][plugin_type]
567       end
568     elsif ! plugin_type
569       results = active_info[namespace]
570     end
571   elsif ! namespace
572     results = active_info
573   end
574   results
575 end
autoload() { |namespace, plugin_type, provider, plugin| ... } click to toggle source

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:

    # File lib/core/environment.rb
378 def autoload # :yields: namespace, plugin_type, provider, plugin
379   load_info = loaded_plugins
380 
381   load_info.keys.each do |namespace|
382     load_info[namespace].keys.each do |plugin_type|
383       load_info[namespace][plugin_type].each do |provider, plugin|
384         require plugin[:file]
385 
386         load_info[namespace][plugin_type][provider][:class] = class_const(plugin[:class_components])
387 
388         yield(namespace, plugin_type, provider, plugin) if block_given?
389       end
390     end
391   end
392 end
class_const(name, separator = '::') click to toggle source

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:

    # File lib/core/environment.rb
629 def class_const(name, separator = '::')
630   components = class_name(name, separator, TRUE)
631   constant   = Object
632 
633   components.each do |component|
634     constant = constant.const_defined?(component) ?
635                 constant.const_get(component) :
636                 constant.const_missing(component)
637   end
638   constant
639 end
class_name(name, separator = '::', want_array = false) click to toggle source

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

    # File lib/core/environment.rb
593 def class_name(name, separator = '::', want_array = false)
594   components = []
595 
596   case name
597   when String, Symbol
598     components = name.to_s.split(separator)
599   when Array
600     components = name.flatten
601   end
602 
603   components.collect! do |value|
604     value    = value.to_s.strip
605     value[0] = value.capitalize[0] if value =~ /^[a-z]/
606     value
607   end
608 
609   if want_array
610     return components
611   end
612   components.join(separator)
613 end
create_plugin(namespace, plugin_type, provider, options = {}) { |type_info, options| ... } click to toggle source

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

  • Errors

  • Yields

    • nil, Hash<Symbol|ANY>

      type_info Provider load information if it has been loaded

    • Hash

      options Create options (plugin initialization configurations)

See:

See also:

    # File lib/core/environment.rb
429 def create_plugin(namespace, plugin_type, provider, options = {}, &code) # :yields: type_info, options
430   namespace   = namespace.to_sym
431   plugin_type = sanitize_id(plugin_type)
432   provider    = sanitize_id(provider)
433   options     = Util::Data.clone(options)
434   plugin      = nil
435   result      = nil
436 
437   unless plugin_type_defined?(namespace, plugin_type)
438     return plugin
439   end
440 
441   if type_info = Util::Data.clone(loaded_plugin(namespace, plugin_type, provider))
442     ids             = array(type_info[:class].register_ids).flatten
443     instance_config = Config.new(options, {}, true, false)
444     ensure_new      = instance_config.delete(:new, false)
445 
446     instance_options = Util::Data.subset(instance_config.export, ids, true)
447     instance_name    = "#{provider}_" + Nucleon.sha1(instance_options)
448     plugin           = get([ :active_info, namespace, plugin_type, instance_name ])
449 
450     if ensure_new || ! ( instance_name && plugin )
451       type_info[:instance_name] = instance_name
452 
453       result  = code.call(type_info, options) if code
454       options = result if result.is_a?(Hash)
455 
456       options[:meta] = Config.new(type_info, {}, true, false).import(hash(options[:meta]))
457 
458       options.delete(:new)
459 
460       plugin = type_info[:class].new(namespace, plugin_type, provider, options)
461       set([ :active_info, namespace, plugin_type, instance_name ], plugin)
462 
463       @instance_map.append([ namespace, plugin_type, plugin.plugin_name.to_sym ], instance_name.to_sym)
464     end
465   end
466   plugin
467 end
define_plugin(namespace, plugin_type, base_path, file) { |data| ... } click to toggle source

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

  • Errors

  • Yields

See:

See also:

    # File lib/core/environment.rb
225 def define_plugin(namespace, plugin_type, base_path, file, &code) # :yields: data
226   namespace   = namespace.to_sym
227   plugin_type = sanitize_id(plugin_type)
228   plugin_info = parse_plugin_info(namespace, plugin_type, base_path, file)
229 
230   unless get_hash([ :load_info, namespace, plugin_type ]).has_key?(plugin_info[:provider])
231     data = {
232       :namespace        => namespace,
233       :type             => plugin_type,
234       :base_path        => base_path,
235       :file             => file,
236       :provider         => plugin_info[:provider],
237       :directory        => plugin_info[:directory],
238       :class_components => plugin_info[:class_components]
239     }
240     code.call(data) if code
241 
242     set([ :load_info, namespace, plugin_type, plugin_info[:provider] ], data)
243   end
244   self
245 end
define_plugin_type(namespace, plugin_type, default_provider = nil) click to toggle source

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

  • Errors

See:

See also:

    # File lib/core/environment.rb
128 def define_plugin_type(namespace, plugin_type, default_provider = nil)
129   set([ :plugin_types, namespace, sanitize_id(plugin_type) ], default_provider)
130 end
define_plugin_types(namespace, type_info) click to toggle source

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

  • Errors

See:

    # File lib/core/environment.rb
146 def define_plugin_types(namespace, type_info)
147   if type_info.is_a?(Hash)
148     type_info.each do |plugin_type, default_provider|
149       define_plugin_type(namespace, plugin_type, default_provider)
150     end
151   end
152   self
153 end
get_plugin(namespace, plugin_type, plugin_name) click to toggle source

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

  • Errors

See:

See also:

    # File lib/core/environment.rb
488 def get_plugin(namespace, plugin_type, plugin_name)
489   namespace    = namespace.to_sym
490   plugin_type  = sanitize_id(plugin_type)
491 
492   instances    = get_hash([ :active_info, namespace, plugin_type ])
493   instance_ids = array(@instance_map.get([ namespace, plugin_type, plugin_name.to_s.to_sym ]))
494 
495   if instance_ids.size
496     return instances[instance_ids[0]]
497   end
498   nil
499 end
loaded_plugin(namespace, plugin_type, provider) click to toggle source

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:

See also:

    # File lib/core/environment.rb
265 def loaded_plugin(namespace, plugin_type, provider)
266   get([ :load_info, namespace, sanitize_id(plugin_type), sanitize_id(provider) ], nil)
267 end
loaded_plugins(namespace = nil, plugin_type = nil, provider = nil, default = {}) click to toggle source

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:

See also:

    # File lib/core/environment.rb
291 def loaded_plugins(namespace = nil, plugin_type = nil, provider = nil, default = {})
292   load_info   = get_hash(:load_info)
293 
294   namespace   = namespace.to_sym if namespace
295   plugin_type = sanitize_id(plugin_type) if plugin_type
296   provider    = sanitize_id(provider) if provider
297   results     = default
298 
299   if namespace && load_info.has_key?(namespace)
300     if plugin_type && load_info[namespace].has_key?(plugin_type)
301       if provider && load_info[namespace][plugin_type].has_key?(provider)
302         results = load_info[namespace][plugin_type][provider]
303       elsif ! provider
304         results = load_info[namespace][plugin_type]
305       end
306     elsif ! plugin_type
307       results = load_info[namespace]
308     end
309   elsif ! namespace
310     results = load_info
311   end
312   results
313 end
namespaces() click to toggle source

Return all of the defined namespaces in the plugin environment.

  • Parameters

  • Returns

    • Array<Symbol>

      Array of defined plugin namespaces

  • Errors

See:

   # File lib/core/environment.rb
89 def namespaces
90   get_hash(:plugin_types).keys
91 end
plugin_class(namespace, plugin_type) click to toggle source

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:

    # File lib/core/environment.rb
686 def plugin_class(namespace, plugin_type)
687   class_const([ sanitize_class(namespace), :plugin, sanitize_class(plugin_type) ])
688 end
plugin_has_provider?(namespace, plugin_type, provider) click to toggle source

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:

See also:

    # File lib/core/environment.rb
354 def plugin_has_provider?(namespace, plugin_type, provider)
355   get_hash([ :load_info, namespace, sanitize_id(plugin_type) ]).has_key?(sanitize_id(provider))
356 end
plugin_has_type?(namespace, plugin_type) click to toggle source

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:

See also:

    # File lib/core/environment.rb
332 def plugin_has_type?(namespace, plugin_type)
333   get_hash([ :load_info, namespace ]).has_key?(sanitize_id(plugin_type))
334 end
plugin_type_default(namespace, plugin_type) click to toggle source

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:

See also:

    # File lib/core/environment.rb
193 def plugin_type_default(namespace, plugin_type)
194   get([ :plugin_types, namespace, sanitize_id(plugin_type) ])
195 end
plugin_type_defined?(namespace, plugin_type) click to toggle source

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:

See also:

    # File lib/core/environment.rb
172 def plugin_type_defined?(namespace, plugin_type)
173   get_hash([ :plugin_types, namespace ]).has_key?(sanitize_id(plugin_type))
174 end
plugin_types(namespace) click to toggle source

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:

    # File lib/core/environment.rb
106 def plugin_types(namespace)
107   get_hash([ :plugin_types, namespace ]).keys
108 end
provider_class(namespace, plugin_type, provider) click to toggle source

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:

    # File lib/core/environment.rb
709 def provider_class(namespace, plugin_type, provider)
710   class_const([ sanitize_class(namespace), sanitize_class(plugin_type), provider ])
711 end
remove_plugin(namespace, plugin_type, instance_name) { |plugin| ... } click to toggle source

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

  • Errors

  • Yields

See:

See also:

    # File lib/core/environment.rb
523 def remove_plugin(namespace, plugin_type, instance_name, &code) # :yields: plugin
524   plugin = delete([ :active_info, namespace, sanitize_id(plugin_type), instance_name ])
525   code.call(plugin) if code && plugin
526   plugin
527 end

Protected Instance Methods

parse_plugin_info(namespace, plugin_type, base_path, file) click to toggle source

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:

    # File lib/core/environment.rb
730 def parse_plugin_info(namespace, plugin_type, base_path, file)
731   dir_components   = base_path.split(File::SEPARATOR)
732   file_components  = file.split(File::SEPARATOR)
733 
734   file_name        = file_components.pop.sub(/\.rb/, '')
735   directory        = file_components.join(File::SEPARATOR)
736 
737   file_class       = sanitize_class(file_name)
738   group_components = directory.sub(/^#{base_path}#{File::SEPARATOR}?/, '').split(File::SEPARATOR)
739 
740   class_components = [ sanitize_class(namespace), sanitize_class(plugin_type) ]
741 
742   if ! group_components.empty?
743     group_name       = group_components.collect {|elem| elem.downcase  }.join('_')
744     provider         = [ group_name, file_name ].join('_')
745 
746     group_components = group_components.collect {|elem| sanitize_class(elem) }
747     class_components = [ class_components, group_components, file_class ].flatten
748   else
749     provider         = file_name
750     class_components = [ class_components, file_class ].flatten
751   end
752 
753   {
754     :directory        => directory,
755     :provider         => sanitize_id(provider),
756     :class_components => class_components
757   }
758 end
sanitize_class(class_component) click to toggle source

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

    # File lib/core/environment.rb
666 def sanitize_class(class_component)
667   class_component.to_s.split('_').collect {|elem| elem.slice(0,1).capitalize + elem.slice(1..-1) }.join('')
668 end
sanitize_id(id_component) click to toggle source

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

    # File lib/core/environment.rb
651 def sanitize_id(id_component)
652   id_component.to_s.gsub(/([a-z0-9])(?:\-|\_)?([A-Z])/, '\1_\2').downcase.to_sym
653 end