class Lorj::Core
This is the main lorj class. It interfaces your main code with the full lorj system as shown in the concept document. It gives you access to the lorj model object designed by your process.
When you start using it, your main must be as simple as you can, as you will need to move most of your application logic to the process. Your application can have several lorj objects running in your code, depending of your needs.
The main things is that you can move most of your process management, usually in your code/modules to be part of the lorj process, make it controller independant, and gains in implementing several controllers to change the way to implement but not the process, you used to build your application!
Then, your application contributors can build their own controller and extend your solution!
Here an example of creating a CloudServer, using Lorj_cloud module See github.com/forj-oss/lorj-cloud
require 'lorj_cloud' process = { :process_module => 'cloud', :controller_name => 'openstack' } cloud = Lorj::Core.new(nil, [process]) cloud.setup(:server) # Ask end user about required data cloud.create(:server, :server_name => 'myservername')
Another basic example.
require 'lorj' process = { :process_name => 'myprocess', :process_path => '<myprocess_path>', :controller_name => :mock } core = Lorj::Core.new(nil, [process]) core.create(:myobject, :parameter1 => "value")
You can learn on lorj by example, see examples/
See BaseProcess
to check how you can write a process and what kind of functions are available for your process to be kept controller independant.
See BaseController
to see how you can write a controller and what kind of functions are available to deal with the implementation API you need to use.
Define private initialize functions for processes
Define private Initialize functions for controllers
Define internal private functions for controllers
Define private Initialize functions for controllers
Attributes
Public access to a config object. A config object can be any kind of class which should provide at least following functions:
-
get(*key, default=nil) and [*key] : function to get a value from a key. default is a value to get if not found.
-
set(*key, value) or [*key, value]= : function to set a value to a key. Ex: From processes, you can set a runtime data with:
config.set(key, value)
OR
config[key] = value
-
exist?(*key) : function which return false if not found, or any other value if found. Ex: From processes, you can get a data (runtime/account/config.yaml or defaults.yaml) with:
config.get(key)
OR
config[key]
For each functions, *key is a list of value, which becomes an array in the function. It should accept to manage the key tree (hash of hashes)
Currently lorj comes with Lorj::Config
or Lorj::Account
. Thoses classes defines at least those 5 functions. And more.
Public Class Methods
Core
parameters are: the_config : Optional. An instance of a configuration system which HAVE to provide get/set/exist?/[]/=
-
Args:
-
Processes
:Array
of processes with controller This array, contains a list of process to load and optionnaly a controller.You can define your own process or a process module. The array is structured as follow:
-
each element contains a
Hash
with: If you are using a process module, set the following:-
:process_module : Name of the process module to load
If you are not using a Process module, you need to set the following:
-
:process_path : Path to a local process code. This path must contains at least 'process' subdir. And if needed a 'controllers' path
-
:process_name : Name of the local process
Optionnally, you can set a controller name to use with the process.
-
:controller_name: Name of the controller to use.
-
:controller_path: Path to the controller file.
-
-
# File lib/core/core.rb, line 410 def initialize(the_config = nil, processes = nil, controller_class = nil) # Loading ProcessClass # Create Process derived from respectively BaseProcess PrcLib.core_level = 0 if PrcLib.core_level.nil? init_core_config(the_config) PrcLib.model.config = @config model = initialize_model # Compatibility with old 'new syntax' # `processes` will get an Array of string/symbol or simply a string/symbol # `controller_class` is used to define the controller to load. # string/symbol processes = adapt_core_parameters(processes, controller_class) # Load Application processes init_processes(model, processes) PrcLib.runtime_fail 'Lorj::Core: No valid process loaded. '\ 'Aborting.' if model[:process_class].nil? # Create Core object with the application model loaded # (processes & controller) initialize_core_object(model) PrcLib.model.clear_heap PrcLib.processes model[:processes] end
Public Instance Methods
high level function to load process
# File lib/core/core_internal.rb, line 256 def _process_load(model, my_process) if load_process(model, my_process[:process_path]) controller_class = my_process[:controller_path] controller_class = my_process[:controller_name] if controller_class.nil? init_controller(model, controller_class) if controller_class else PrcLib.warning("Process '%s' not properly loaded.", my_process[:process_path]) end end
Load data definition in process data layers
# File lib/core/core_internal.rb, line 355 def _process_load_data(config, index, name, file, config_class = PRC::BaseConfig) return unless config.layer_index(name).nil? return if file.nil? layer = PRC::CoreConfig.define_layer(:name => name, :config => config_class.new, :load => true, :set => false) unless File.exist?(file) PrcLib.warning("Process '%s', data file '%s' doesn't exist."\ ' Not loaded.', name, file) return end begin unless layer[:config].load(file) PrcLib.warning("Process '%s', data file '%s' was not loaded.", name, file) end rescue => e PrcLib.error("Process '%s', unable to load data file '%s'. %s", name, file, e.message) end config.layer_add(layer.merge(:index => (config.layers.length - index))) end
function prepare of loading a local process
# File lib/core/core_internal.rb, line 269 def _process_local_to_load(index, my_process, a_process) my_process[:process_path] = a_process[:process_path] if a_process[:process_name].nil? my_process[:process_name] = File.basename(a_process[:process_path]) else my_process[:process_name] = a_process[:process_name] end if a_process[:controller_path] my_process[:controller_path] = a_process[:controller_path] else my_process[:controller_name] = a_process[:controller_name] end defaults_file = a_process[:defaults] if defaults_file.nil? path = a_process[:process_path] path['.rb'] = '' defaults_file = File.join(path, 'defaults.yaml') end _process_load_data(config, index, a_process[:process_name], defaults_file, PRC::SectionConfig) data_file = a_process[:data] if defaults_file.nil? path = a_process[:process_path] path['.rb'] = '' data_file = File.join(path, 'data.yaml') end _process_load_data(Lorj.data, index, a_process[:process_name], data_file) # TODO: Implement Object definition as a config layer. # _process_load_definition(definition, index, a_process[:process_name], # a_process[:definition]) my_process end
Load process definition in process layers Function currently not developped.
def _process_load_definition(a_process) end
# File lib/core/core_internal.rb, line 390 def _process_module_set_ctr(my_process, controllers, controller_name) return if controller_name.nil? unless controller_name.is_a?(String) controller_name = controller_name.to_s end controller_path = controllers[controller_name] if controller_path.nil? PrcLib.warning("Controller '%s' was not found. Please check. The "\ "process may not work. \nValid one are '%s'", controller_name, controllers.keys) return end my_process[:controller_path] = controller_path my_process[:controller_name] = controller_name end
Function prepare of loading a module process.
# File lib/core/core_internal.rb, line 313 def _process_module_to_load(index, my_process, a_process) name = a_process[:process_module] if name.nil? PrcLib.warning(':process_module is empty. Process not properly loaded.') return end name = name.to_s if name.is_a?(Symbol) unless Lorj.processes.key?(name) PrcLib.warning("Unable to find Process module '%s'. Process not "\ 'properly loaded.', name) return end module_process = Lorj.processes[name] my_process[:process_name] = name my_process[:process_path] = module_process.process my_process[:lib_name] = module_process.lib_name if a_process[:controller_path] my_process[:controller_path] = a_process[:controller_path] return my_process end _process_module_set_ctr(my_process, module_process.controllers, a_process[:controller_name]) _process_load_data(config, index, name, module_process.defaults_file, PRC::SectionConfig) _process_load_data(Lorj.data, index, name, module_process.data_file) # TODO: Implement Object definition as a config layer. # _process_load_definition(definition, index, name, # module_process.definition) my_process end
Function to export a Lorj
Account
in an encrypted Hash
.
For details about this functions, see #Lorj::BaseDefinition.account_export
-
Args :
-
map
:Hash
map of fields to extract. if map is nil, the export function will loop in the list of keys in the 'account' layer. -
with_name
: True to extract :name and :provider as well. True by default.
-
-
returns :
OR
-
nil if issues.
-
# File lib/core/core.rb, line 378 def account_export(map = nil, with_name = true, account_only = false, processes_options = {}) return nil if @core_object.nil? @core_object.account_export(map, with_name, account_only, processes_options) end
Function to import an encrypted Hash
as a Lorj
Account
.
For details about this functions, see #Lorj::BaseDefinition.account_data_import
To import an exported data, consider calling Lorj.account_import
.
-
Args :
-
data
:Hash
. data to import. -
name
: By default, it import in the same name described in the data. But we can change it with this parameter.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 358 def account_import(data, name = nil) return nil if @core_object.nil? @core_object.account_data_import(data, name) end
Function which determine the class name from the file name. rules:
-
First character : Capitalized
-
Any character prefixed by '_' : capitalized. '_' is removed.
-
Args :
-
the_process_file
: Process file to analyze.
-
-
Returns :
-
ProcessClassName : string representing the name of the class.
-
# File lib/core/core_internal.rb, line 463 def classname_from_file(file) the_process_class = File.basename(file) the_process_class['.rb'] = '' if the_process_class['.rb'] if (/[A-Z]/ =~ the_process_class) != 0 the_process_class = the_process_class.capitalize end match_found = the_process_class.scan(/_[a-z]/) if match_found # Ruby 1.8 : 'ab'[1] => 98 and 'ab'[1, 1] => 'b' # Ruby 1.9 + : 'ab'[1] => 'b' and 'ab'[1, 1] => 'b' match_found.each { |str| the_process_class[str] = str[1, 1].capitalize } end the_process_class end
a wrapper to Create call. Use this function for code readibility.
-
Args :
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 127 def connect(oCloudObj, hConfig = nil) return nil if !oCloudObj || !@core_object @core_object.process_create(oCloudObj, hConfig) end
Execute the creation process to create the object `oCloudObj`. The creation process can add any kind of complexity to get the a memory representation of the object manipulated during creation process. This means that a creation process can be (non exhaustive list of possibilities)
-
a connection initialization
-
an internal memory data structure, like hash, array, ruby object…
-
a get or create logic
-
…
-
Args :
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 155 def create(oCloudObj, hConfig = nil) return nil if !oCloudObj || !@core_object @core_object.process_create(oCloudObj, hConfig) end
Execution of the delete process for the `oCloudObj` object. It requires the object to be loaded in lorj Lorj::Data
objects cache. You can use `Create` or `Get` functions to load this object.
-
Args :
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 197 def delete(oCloudObj, hConfig = nil) return nil if !oCloudObj || !@core_object @core_object.process_delete(oCloudObj, hConfig) end
Execution of the Get process for the `oCloudObj` object.
-
Args :
-
oCloudObj
: Name of the object to initialize. -
sId
: data representing the ID (attribute :id) of aLorj::Data
object.
-
hConfig
:Hash
of hashes containing data required to initializethe object.
If you use this variable, any other runtime config defined by the
Data
model will be cleaned before
-
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 242 def get(oCloudObj, sId, hConfig = nil) return nil if !oCloudObj || !@core_object || sId.nil? @core_object.process_get(oCloudObj, sId, hConfig) end
a wrapper to Create call. Use this function for code readibility.
-
Args :
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 175 def get_or_create(oCloudObj, hConfig = nil) return nil if !oCloudObj || !@core_object @core_object.process_create(oCloudObj, hConfig) end
Function to load a process.
-
Args :
-
the_process_
: Process to load. Can be a string ora path to a file
-
-
Returns :
-
load_status : true if loaded, false otherwise
-
# File lib/core/core_internal.rb, line 438 def load_process(model, the_process) Lorj.debug(1, "Loading Process '%s'", the_process) if the_process.include?('/') file = File.expand_path(the_process) else file = processfile_from_default(model, the_process) end return PrcLib.warning("Process file definition '%s' is missing. ", file) unless File.exist?(file) load_processfile(model, file, classname_from_file(file)) end
Function analyzing the process class parameter and return the list of processes in an array of processes.
-
Args :
-
processes_parameter
: Parameter to interpret. supports:- nil => return [] - String/Symbol => return [String/Symbol] - Array => return Array
-
-
Returns :
-
array_processes :
Array
of processes.
-
# File lib/core/core_internal.rb, line 422 def processes_as_array(processes_parameter) return [] if processes_parameter.nil? return [processes_parameter] unless processes_parameter.is_a?(Array) processes_parameter end
Execution of the Query process for the `oCloudObj` object.
-
Args :
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 219 def query(oCloudObj, sQuery, hConfig = nil) return nil if !oCloudObj || !@core_object @core_object.process_query(oCloudObj, sQuery, hConfig) end
Execution of the Update process for the `oCloudObj` object. Usually, the Controller object data is updated by the process (BaseController::set_attr) then it should call a controller_update to really update the data in the controller.
-
Args :
-
oCloudObj
: Name of the object to initialize. -
sId
: data representing the ID (attribute :id) of aLorj::Data
object.
-
hConfig
:Hash
of hashes containing data required to initializethe object.
If you use this variable, any other runtime config defined by the
Data
model will be cleaned before
-
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 296 def refresh(object) return false unless object.is_a?(Lorj::Data) && !object.empty? && object.type == :object @core_object.process_update(object) end
Function to add an object to Lorj
cache.
This function is typically used when a previous query has been executed and you want to keep the object in lorj cache. Lorj
cache is used by create/delete/etc… To avoid requerying or creating those objects (+dependencies) if missing.
-
Args :
-
oObject
: object to register. -
sObjectType
:Object
type to register. By default, the object type is determined by theObject
itself if this object is anObjectData
. Otherwise, you need to define the object type.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 339 def register(oObject, sObjectType = nil) return nil if !oObject || !@core_object @core_object.register(oObject, sObjectType) end
Function used to ask users about setting up his account.
-
Args :
-
oCloudObj
: Name of the object to initialize. -
sAccountName
: Obsolete. You have to load the account data beforeIf you use this variable, any other runtime config defined by the
Data
model will be cleaned before
-
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 318 def setup(oCloudObj, _sAccountName = nil) return nil if !oCloudObj || !@core_object @core_object.process_setup(oCloudObj) end
Execution of the Update process for the `oCloudObj` object. Usually, the Controller object data is updated by the process (BaseController::set_attr) then it should call a controller_update to really update the data in the controller.
-
Args :
-
oCloudObj
: Name of the object to initialize. -
sId
: data representing the ID (attribute :id) of aLorj::Data
object.
-
hConfig
:Hash
of hashes containing data required to initializethe object.
If you use this variable, any other runtime config defined by the
Data
model will be cleaned before
-
-
Returns :
-
Lorj::Data
: Represents theObject
initialized.
-
-
Raises : No exceptions
# File lib/core/core.rb, line 269 def update(oCloudObj, hConfig = nil) return nil if !oCloudObj || !@core_object @core_object.process_update(oCloudObj, hConfig) end
Private Instance Methods
# File lib/core/core.rb, line 479 def _adapt_with_controller(processes_built, controller) return if controller.nil? if controller.include?('/') processes_built[-1][:controller_path] = controller processes_built[-1][:controller_name] = File.basename(controller) else processes_built[-1][:controller_name] = controller end end
This function is used to keep compatibility with old way to load processes and controllers If processes is a Array
of Hash
=> new way otherwise we need to create it.
# File lib/core/core.rb, line 446 def adapt_core_parameters(processes, controller) return [] unless processes.is_a?(Array) return [] if processes.length == 0 return processes if processes[0].is_a?(Hash) PrcLib.warning('lorj initialization with Process & controller parameters'\ ' is obsolete. Read Lorj::Core.new to update it and '\ 'eliminate this warning') # Declare processes processes = processes_as_array(processes) processes_built = [] processes.each do |process| process = process.to_s if process.is_a?(Symbol) a_process = {} if process.include?('/') a_process[:process_path] = process a_process[:process_name] = File.basename(process) else a_process[:process_module] = process end processes_built << a_process end _adapt_with_controller(processes_built, controller) processes_built end
Determine the controller file path from the single name. Uses PrcLib.controller_path
as path to load this process.
-
Args :
-
the_controller_class
: Controller to load.
-
-
Returns :
-
file : absolute file path.
-
# File lib/core/core_internal.rb, line 199 def controllerfile_from_default(_model, the_controller, suffix = '') File.join(PrcLib.controller_path, the_controller, the_controller + suffix + '.rb') end
Function to ensure a Class_name as already been loaded or not It raises an error if not.
# File lib/core/core_internal.rb, line 44 def ensure_class_exist(class_name) # Ensure Process class exists --------------- Object.const_get(class_name) rescue => e raise Lorj::PrcError.new, format('Lorj::Core: Unable to find class'\ " '%s'\n%s", class_name, e.message) end
Function to initialize itself with application controller.
-
Args :
-
model
: Application model loaded. -
controller
: Processes to load. supports :- nil => return [] - String/Symbol => return [String/Symbol] - Array => return Array
-
-
Returns :
-
model : Application model loaded.
-
# File lib/core/core_internal.rb, line 87 def init_controller(model, the_controller) Lorj.debug(1, "Loading Controller/definition '%s'", the_controller) ok = load_controller(model, the_controller) PrcLib.warning("Controller '%s' not properly loaded.", the_controller) unless ok model end
Initialize a basic Config
Object
and use the one passed as parameter. It sets @config instance attribute
# File lib/core/core_internal.rb, line 66 def init_core_config(the_config) if the_config.nil? @config = Lorj::Config.new Lorj.debug(2, 'Using an internal Lorj::Config object.') else @config = the_config end end
Function to initialize itself with application processes.
-
Args :
-
model
: Application model loaded. -
processes
:Array
of processes and controller to load-
each element contains a
Hash
with: If you are using a process module, set the following:-
:process_module : Name of the process module to load
If you are not using a Process module, you need to set the following
-
:process_path : Path to a local process code. This path must contains at least 'process' subdir. And if needed a 'controllers' path
-
:process_name : Name of the local process
-
:defaults : Define the defaults data setting for the process
-
:data : Define process data definition.
Optionnally, you can set a controller name to use with the process.
-
:controller_name: Name of the controller to use.
-
:controller_path: Path to the controller file.
-
-
-
-
Returns :
-
model : Application model loaded.
-
# File lib/core/core_internal.rb, line 232 def init_processes(model, processes) processes.each_index do |index| my_process = {} a_process = processes[index] if a_process.key?(:process_module) my_process = _process_module_to_load(index, my_process, a_process) else my_process = _process_local_to_load(index, my_process, a_process) end next if my_process.nil? model[:processes] << my_process _process_load(model, my_process) end model end
Create core objects Create a BaseDefinition
object => Core
Attach Config
, Process and Controller object
# File lib/core/core_internal.rb, line 27 def initialize_core_object(model) ensure_class_exist(model[:process_class_name]) # Ex: Hpcloud(ForjAccount, HpcloudProvider) def_class = model[:def_class] if model[:controller_class] @core_object = def_class.new(@config, model[:process_class].new, model[:controller_class].new) else @core_object = def_class.new(@config, model[:process_class].new) end end
Initialize the Application model structure for Initialization
-
Returns :
-
model : Basic model.
-
# File lib/core/core_internal.rb, line 56 def initialize_model { :def_class => BaseDefinition, :processes => [], :process_class => nil, :process_class_name => nil, :controller_class => nil, :controller_class_name => nil } end
Function to load a controller. This function helps to load a Controller process (See load_process_controller_file) if exists and load the core controller file (Seeload_controllerfile)
-
Args :
-
the_controller
: Controller to load. Can be a string ora path to a file
-
-
Returns :
-
load_status : true if loaded, false otherwise
-
# File lib/core/core_internal.rb, line 110 def load_controller(model, the_controller) load_process_controller(model, the_controller) the_controller = the_controller.to_s unless the_controller.is_a?(String) if the_controller.include?('/') file = File.expand_path(the_controller) else file = controllerfile_from_default(model, the_controller) end return PrcLib.warning('Controller not loaded: Controller file '\ "definition '%s' is missing.", file) unless File.exist?(file) load_controllerfile(model, file, classname_from_file(file)) end
Load a Controller file in ruby.
-
Args :
-
model
: Application/controller model loaded. -
file
: Process file to load. -
controller
: Controller name or file to load.
-
-
Returns :
-
loaded : load status
-
# File lib/core/core_internal.rb, line 166 def load_controllerfile(model, file, the_controller) # Initialize an empty class derived from BaseDefinition. # This to ensure provider Class will be derived from this Base Class # If this class is derived from a different Class, ruby will raise an # error. # Create Definition and Controler derived from respectively # BaseDefinition and BaseControler base_definition_class = Class.new(BaseDefinition) # Finally, name that class! Lorj.debug(2, "Declaring Definition '%s'", the_controller) Object.const_set the_controller, base_definition_class model[:controller_class_name] = the_controller + 'Controller' base_controller_class = Class.new(BaseController) Lorj.debug(2, "Declaring Controller '%s'", model[:controller_class_name]) model[:controller_class] = Object.const_set model[:controller_class_name], base_controller_class # Loading Provider base file. This file should load a class # which have the same name as the file. load file end
Load a Controller process file in ruby. If controller is a file, the process file name will be suffixed by _process, before the .rb file name.
If controller is just a name (String/Symbol), it will load a file suffixed by _process.rb from PrcLib.controller_path
-
Args :
-
model
: Application/controller model loaded. -
controller
: Symbol/String. Controller name or file to load.
-
-
Returns :
-
loaded : load status
-
# File lib/core/core_internal.rb, line 139 def load_process_controller(model, the_controller) Lorj.debug(1, "Loading process for controller '%s'", the_controller) the_controller = the_controller.to_s unless the_controller.is_a?(String) if the_controller.include?('/') the_controller_process = the_controller.clone the_controller_process['.rb'] = '_process.rb' file = File.expand_path(the_controller_process) else file = controllerfile_from_default(model, the_controller, '_process') end return Lorj.debug(2, 'Process not loaded: Process controller file '\ "definition '%s' is missing.", file) unless File.exist?(file) load_processfile(model, file, classname_from_file(file)) end
Load a process file in ruby.
-
Args :
-
file
: Process file to load.
-
-
Returns :
-
loaded : load status
-
# File lib/core/core_internal.rb, line 507 def load_processfile(model, file, the_process_class) model[:process_class] = BaseProcess if model[:process_class].nil? new_class = Class.new(model[:process_class]) unless /Process$/ =~ the_process_class the_process_class = format('%sProcess', the_process_class) end Lorj.debug(1, "Declaring Process '%s'", the_process_class) model[:process_class] = Object.const_set(the_process_class, new_class) model[:process_class_name] = the_process_class BaseDefinition.current_process(model[:process_class]) load file end
Determine the process file path from the single name. Uses PrcLib.process_path
as path to load this process.
-
Args :
-
the_process_class
: Process to load.
-
-
Returns :
-
file : absolute file path composed by:
PrcLib.process_path/the_process_class + '.rb'
-
# File lib/core/core_internal.rb, line 496 def processfile_from_default(_model, the_process_class) File.join(PrcLib.process_path, the_process_class + '.rb') end