lorj 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.gitreview +4 -0
  4. data/Gemfile +25 -0
  5. data/Gemfile.lock +34 -0
  6. data/LICENSE.txt +14 -0
  7. data/README.md +652 -0
  8. data/Rakefile +24 -0
  9. data/bin/cloud_test.rb +81 -0
  10. data/example/students_1/process/Students.rb +20 -0
  11. data/example/students_1/students.rb +16 -0
  12. data/example/students_2/process/Students.rb +27 -0
  13. data/example/students_2/students.rb +36 -0
  14. data/example/students_3/controller/yaml_students.rb +94 -0
  15. data/example/students_3/controller/yaml_students_controller.rb +123 -0
  16. data/example/students_3/process/students.rb +118 -0
  17. data/example/students_3/students.rb +93 -0
  18. data/example/students_4/controller/yaml_students.rb +82 -0
  19. data/example/students_4/controller/yaml_students_controller.rb +141 -0
  20. data/example/students_4/process/students.rb +112 -0
  21. data/example/students_4/students.rb +103 -0
  22. data/example/yaml_students/students.rb +78 -0
  23. data/example/yaml_students/yaml_students.rb +115 -0
  24. data/lib/concept.md +111 -0
  25. data/lib/core/core.rb +723 -0
  26. data/lib/core/definition.rb +505 -0
  27. data/lib/core/definition_internal.rb +338 -0
  28. data/lib/core/lorj-basecontroller.rb +90 -0
  29. data/lib/core/lorj-basedefinition.rb +1079 -0
  30. data/lib/core/lorj-baseprocess.rb +231 -0
  31. data/lib/core/lorj-data.rb +567 -0
  32. data/lib/core/lorj-keypath.rb +115 -0
  33. data/lib/core_process/CloudProcess.rb +334 -0
  34. data/lib/core_process/global_process.rb +406 -0
  35. data/lib/core_process/network_process.rb +603 -0
  36. data/lib/img/.directory +4 -0
  37. data/lib/img/account_data_access.png +0 -0
  38. data/lib/img/config_data_access.png +0 -0
  39. data/lib/img/forj-lib-concept.png +0 -0
  40. data/lib/lorj/version.rb +3 -0
  41. data/lib/lorj.rb +51 -0
  42. data/lib/prc-account.rb +339 -0
  43. data/lib/prc-config.rb +1023 -0
  44. data/lib/prc-logging.rb +183 -0
  45. data/lib/prc.rb +108 -0
  46. data/lib/providers/hpcloud/Hpcloud.rb +419 -0
  47. data/lib/providers/hpcloud/compute.rb +108 -0
  48. data/lib/providers/hpcloud/network.rb +117 -0
  49. data/lib/providers/hpcloud/security_groups.rb +67 -0
  50. data/lib/providers/mock/Mock.rb +141 -0
  51. data/lib/providers/openstack/Openstack.rb +47 -0
  52. data/lib/providers/templates/compute.rb +42 -0
  53. data/lib/providers/templates/core.rb +61 -0
  54. data/lib/providers/templates/network.rb +33 -0
  55. data/lorj-spec/defaults.yaml +26 -0
  56. data/lorj.gemspec +39 -0
  57. data/spec/forj-account_spec.rb +75 -0
  58. data/spec/forj-config_spec.rb +196 -0
  59. metadata +164 -0
data/lib/core/core.rb ADDED
@@ -0,0 +1,723 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ # Module Lorj which contains several classes.
19
+ #
20
+ # Those classes describes :
21
+ # - processes (BaseProcess) : How to create/delete/edit/query object.
22
+ # - controler (BaseControler) : If a provider is defined, define how will do object creation/etc...
23
+ # - definition(BaseDefinition): Functions to declare objects, query/data mapping and setup
24
+ # this task to make it to work.
25
+
26
+ module Lorj
27
+
28
+ # Internal Lorj function to debug lorj.
29
+ #
30
+ # * *Args* :
31
+ # - +iLevel+ : value between 1 to 5. Setting 5 is the most verbose!
32
+ # - +sMsg+ : Array of string or symbols. keys tree to follow and check existence in yVal.
33
+ #
34
+ # * *Returns* :
35
+ # - nothing
36
+ #
37
+ # * *Raises* :
38
+ # No exceptions
39
+ def Lorj::debug(iLevel, sMsg)
40
+ if iLevel <= PrcLib.core_level
41
+ PrcLib.debug("-%s- %s" % [iLevel, sMsg])
42
+ end
43
+ end
44
+
45
+ # Internal PrcError class object derived from RuntimeError.
46
+ # Internally used with raise.
47
+ # Used to identify the error origin, while an error is thrown.
48
+ class PrcError < RuntimeError
49
+ attr_reader :ForjMsg
50
+
51
+ def initialize(message = nil)
52
+ @ForjMsg = message
53
+ end
54
+ end
55
+
56
+
57
+ # This is the main lorj class.
58
+ # It interfaces your main code with the full lorj system as shown in the concept document.
59
+ # It give you access to the lorj model object designed by your process.
60
+ #
61
+ # When you start using it, your main must be as simple as you can, as you will need to move
62
+ # most of your application logic to the process.
63
+ # Your application can have several lorj objects running in your code, depending of your needs.
64
+ #
65
+ # The main things is that you can move most of your process management, usually in your code/modules
66
+ # to be part of the lorj process, make it controller independant, and gains in
67
+ # implementing several controllers to change the way to implement but not the process
68
+ # you used to build your application!
69
+ #
70
+ # Then, your application contributors can build their own controller and extend your solution!
71
+ #
72
+ # Here an example of creating a CloudServer, using CloudCore (derived from Core).
73
+ # CloudCore introduces lorj predefined CloudProcess used by forj cli.
74
+ #
75
+ # oCloud = Lorj::CloudCore.new(oConfig, 'myhpcloud')
76
+ # oConfig.set(:server_name,'myservername')
77
+ # oCloud.Create(:server)
78
+ #
79
+ # Another basic example (See example directory)
80
+ #
81
+ # oConfig = Lorj::Account.new()
82
+ # oPrc = Lorj::Core.new(oConfig, 'mySqlAccount')
83
+ # oCloud.Create(:student, { :student_name => "Robert Redford"})
84
+ #
85
+ # See BaseProcess to check how you can write a process and what kind of functions
86
+ # are available for your process to be kept controller independant.
87
+ #
88
+ # See BaseController to see how you can write a controller and what kind of functions
89
+ # are available to deal with the implementation API you need to use.
90
+ class Core
91
+
92
+ # Public access to a config object.
93
+ # A config object can be any kind of class which should provide at least following functions:
94
+ #
95
+ # - get(*key, default=nil) and [*key] : function to get a value from a key. default is a value to get if not found.
96
+ # - set(*key, value) or [*key, value]= : function to set a value to a key.
97
+ # Ex: From processes, you can set a runtime data with:
98
+ #
99
+ # config.set(key, value)
100
+ #
101
+ # OR
102
+ #
103
+ # config[key] = value
104
+ #
105
+ # - exist?(*key) : function which return false if not found, or any other value if found.
106
+ # Ex: From processes, you can get a data (runtime/account/config.yaml or defaults.yaml) with:
107
+ #
108
+ # config.get(key)
109
+ #
110
+ # OR
111
+ #
112
+ # config[key]
113
+ #
114
+ # For each functions, *key is a list of value, which becomes an array in the function.
115
+ # It should accept to manage the key tree (hash of hashes)
116
+ #
117
+ # Currently lorj comes with Lorj::Config or Lorj::Account.
118
+ # Thoses classes defines at least those 5 functions. And more.
119
+ attr_reader :config
120
+
121
+ # Core parameters are:
122
+ # oForjConfig : Optional. An instance of a configuration system which *HAVE* to provide get/set/exist?/[]/[]=
123
+ #
124
+ # processClass: Array of string or symbol, or string or symbol. Is the path or name of one or more ProcessClass to use.
125
+ # This class is dynamically loaded and derived from BaseProcess class.
126
+ # It loads the Process class content from a file '$CORE_PROCESS_PATH/<sProcessClass>.rb'
127
+ # If sProcessClass is a file path, this file will be loaded as a ruby include.
128
+ #
129
+ # <sProcessClass>.rb file name is case sensible and respect RUBY Class name convention
130
+ #
131
+ # sControllerClass: Optional. string or symbol. Is the path or name of ControllerClass to use.
132
+ # This class is dynamically loaded and derived from BaseController class.
133
+ # It loads the Controler class content from a file '$PROVIDER_PATH/<sControllerClass>.rb'
134
+ #
135
+ # The provider can redefine partially or totally some processes
136
+ # Lorj::Core will load those redefinition from file:
137
+ # $PROVIDER_PATH/<sControlerClass>Process.rb'
138
+ #
139
+ # <sControllerClass>.rb or <sControllerClass>Process.rb file name is case sensible and respect RUBY Class name convention
140
+
141
+ def initialize(oForjConfig = nil, processesClass = nil, sControllerClass = nil)
142
+ # Loading ProcessClass
143
+ # Create Process derived from respectively BaseProcess
144
+
145
+ # TODO: Replace Global variables by equivalent to PrcLib.<var>
146
+
147
+ PrcLib.core_level = 0 if PrcLib.core_level.nil?
148
+
149
+ if oForjConfig.nil?
150
+ @config = Lorj::Config.new()
151
+ oForjConfig = @config
152
+ Lorj.debug(2, "Using an internal Lorj::Config object.")
153
+ else
154
+ @config = oForjConfig
155
+ end
156
+
157
+
158
+ if processesClass.nil?
159
+ aProcessesClass = []
160
+ elsif not processesClass.is_a?(Array)
161
+ aProcessesClass = [processesClass]
162
+ else
163
+ aProcessesClass = processesClass
164
+ end
165
+
166
+ cBaseProcess = BaseProcess
167
+ cProcessClass = nil
168
+
169
+ aProcessesClass.each { | sProcessClass |
170
+ Lorj.debug(1, "Loading Process '%s'" % sProcessClass)
171
+
172
+ # And load the content from the <sProcessClass>.rb
173
+ if sProcessClass.is_a?(Symbol)
174
+ # Ensure file and processName is capitalized
175
+ sProcessClass = sProcessClass.to_s.capitalize if (/[A-Z]/ =~ sProcessClass.to_s) != 0
176
+ sFile = File.join($CORE_PROCESS_PATH, sProcessClass + '.rb')
177
+ else
178
+ if sProcessClass.include?('/')
179
+ # Consider a path to the process file. File name is the name of the class.
180
+ # We accept filename not capitalized.
181
+ sPath = File.dirname(File.expand_path(sProcessClass))
182
+ sFile = File.basename(sProcessClass)
183
+ file = File.basename(sProcessClass)
184
+ file['.rb'] = '' if file['.rb']
185
+ sProcessClass = file
186
+ sProcessClass = sProcessClass.capitalize if (/[A-Z]/ =~ sProcessClass) != 0
187
+ mFound = sProcessClass.scan(/_[a-z]/)
188
+ if mFound
189
+ mFound.each { | str |
190
+ sProcessClass[str] = str[1].capitalize
191
+ }
192
+ end
193
+ else
194
+ sPath = $CORE_PROCESS_PATH
195
+ sProcessClass = sProcessClass.capitalize if (/[A-Z]/ =~ sProcessClass) != 0
196
+ sFile = sProcessClass + '.rb'
197
+ end
198
+ # Ensure process name is capitalized
199
+ sFile = File.join(sPath, sFile)
200
+ end
201
+ if File.exists?(sFile)
202
+ cNewClass = Class.new(cBaseProcess)
203
+ sProcessClass = "%sProcess" % sProcessClass if not /Process$/ =~ sProcessClass
204
+ Lorj.debug(1, "Declaring Process '%s'" % sProcessClass)
205
+ cBaseProcess = Object.const_set(sProcessClass, cNewClass)
206
+ cProcessClass = sProcessClass
207
+ BaseDefinition.current_process(cBaseProcess)
208
+ load sFile
209
+ else
210
+ PrcLib.warning("Process file definition '%s' is missing. " % sFile)
211
+ end
212
+ }
213
+
214
+ if sControllerClass
215
+ Lorj.debug(1, "Loading Controller/definition '%s'" % sControllerClass)
216
+ # Add Provider Object -------------
217
+ if sControllerClass.is_a?(Symbol)
218
+ sPath = File.join($PROVIDERS_PATH, sControllerClass.to_s)
219
+ sControllerClass = sControllerClass.to_s.capitalize if (/[A-Z]/ =~ sControllerClass.to_s) != 0
220
+ sFile = sControllerClass.to_s + '.rb'
221
+ else
222
+ if sControllerClass.include?('/')
223
+ # Consider a path to the process file. File name is the name of the class.
224
+ sPath = File.dirname(File.expand_path(sControllerClass))
225
+ sFile = File.basename(sControllerClass)
226
+ file = File.basename(sControllerClass)
227
+ file = file.capitalize if (/[A-Z]/ =~ file) != 0
228
+ file['.rb'] = '' if file['.rb']
229
+ sControllerClass = file
230
+ sControllerClass = sControllerClass.capitalize if (/[A-Z]/ =~ sControllerClass) != 0
231
+ mFound = sControllerClass.scan(/_[a-z]/)
232
+ if mFound
233
+ mFound.each { | str |
234
+ sControllerClass[str] = str[1].capitalize
235
+ }
236
+ end
237
+ else
238
+ sPath = File.join($PROVIDERS_PATH, sControllerClass)
239
+ sControllerClass = sControllerClass.capitalize if (/[A-Z]/ =~ sControllerClass) != 0
240
+ sFile = sControllerClass + '.rb'
241
+ end
242
+ end
243
+ sFile = File.join(sPath, sFile)
244
+
245
+ # Initialize an empty class derived from BaseDefinition.
246
+ # This to ensure provider Class will be derived from this Base Class
247
+ # If this class is derived from a different Class, ruby will raise an error.
248
+
249
+ # Create Definition and Controler derived from respectively BaseDefinition and BaseControler
250
+ cBaseDefinition = Class.new(BaseDefinition)
251
+ # Finally, name that class!
252
+ Lorj.debug(2, "Declaring Definition '%s'" % sControllerClass)
253
+ Object.const_set sControllerClass, cBaseDefinition
254
+
255
+ cBaseControler = Class.new(BaseController)
256
+ Lorj.debug(2, "Declaring Controller '%s'" % [sControllerClass + 'Controller'])
257
+ Object.const_set sControllerClass + 'Controller', cBaseControler
258
+
259
+ # Loading Provider base file. This file should load a class
260
+ # which have the same name as the file.
261
+ if File.exists?(sFile)
262
+ load sFile
263
+ else
264
+ raise Lorj::PrcError.new(), "Provider file definition '%s' is missing. Cannot go on" % sFile
265
+ end
266
+
267
+ # Identify Provider Classes. Search for
268
+ # - Definition Class (sControllerClass) - Contains ForjClass Object
269
+ # - Controller Class (sControllerClass + 'Controller') - Provider Cloud controler object
270
+
271
+ # Search for Definition Class
272
+ begin
273
+ # Get it from Objects
274
+ oDefClass = Object.const_get(sControllerClass)
275
+ rescue
276
+ raise Lorj::PrcError.new(), 'Lorj::Core: Unable to find class "%s"' % sControllerClass
277
+ end
278
+
279
+ # Search for Controler Class
280
+ # - Process Class (sControllerClass + 'Process') - Provider Process object if defined
281
+ begin
282
+ # Get the same one suffixed with 'Provider' from Objects
283
+ oCoreObjectControllerClass = Object.const_get(sControllerClass + 'Controller')
284
+ rescue
285
+ raise Lorj::PrcError.new(), 'Lorj::Core: Unable to find class "%s"' % sControllerClass + 'Controller'
286
+ end
287
+
288
+ # Then, we create an BaseCloud Object with 2 objects joined:
289
+ # ForjAccount and a BaseControler Object type
290
+
291
+
292
+ else
293
+ oCoreObjectControllerClass = nil
294
+ oDefClass = BaseDefinition
295
+ end
296
+
297
+ # Add Process management object ---------------
298
+ unless cProcessClass.nil?
299
+ begin
300
+ oBaseProcessDefClass = Object.const_get(cProcessClass)
301
+ rescue
302
+ raise Lorj::PrcError.new(), 'Lorj::Core: Unable to find class "%s"' % cProcessClass
303
+ end
304
+ else
305
+ raise Lorj::PrcError.new(), 'Lorj::Core: No valid process loaded. Aborting.'
306
+ end
307
+ # Ex: Hpcloud(ForjAccount, HpcloudProvider)
308
+ if oCoreObjectControllerClass
309
+ @oCoreObject = oDefClass.new(oForjConfig, oBaseProcessDefClass.new(), oCoreObjectControllerClass.new())
310
+ else
311
+ @oCoreObject = oDefClass.new(oForjConfig, oBaseProcessDefClass.new())
312
+ end
313
+
314
+ end
315
+
316
+ # a wrapper to Create call. Use this function for code readibility.
317
+ #
318
+ # * *Args* :
319
+ # - +oCloudObj+ : Name of the object to initialize.
320
+ # - +hConfig+ : Hash of hashes containing data required to initialize the object.
321
+ # If you use this variable, any other runtime config defined
322
+ # by the Data model will be cleaned before
323
+ #
324
+ # * *Returns* :
325
+ # - +Lorj::Data+ : Represents the Object initialized.
326
+ #
327
+ # * *Raises* :
328
+ # No exceptions
329
+
330
+ def Connect(oCloudObj, hConfig = {})
331
+ return nil if not oCloudObj or not @oCoreObject
332
+ @oCoreObject.Create(oCloudObj, hConfig)
333
+ end
334
+
335
+ # Execute the creation process to create the object `oCloudObj`.
336
+ # The creation process can add any kind of complexity to
337
+ # get the a memory representation of the object manipulated during creation process.
338
+ # This means that a creation process can be (non exhaustive list of possibilities)
339
+ # - a connection initialization
340
+ # - an internal memory data structure, like hash, array, ruby object...
341
+ # - a get or create logic
342
+ # - ...
343
+ #
344
+ # * *Args* :
345
+ # - +oCloudObj+ : Name of the object to initialize.
346
+ # - +hConfig+ : Hash of hashes containing data required to initialize the object.
347
+ # If you use this variable, any other runtime config defined
348
+ # by the Data model will be cleaned before
349
+ #
350
+ # * *Returns* :
351
+ # - +Lorj::Data+ : Represents the Object initialized.
352
+ #
353
+ # * *Raises* :
354
+ # No exceptions
355
+ def Create(oCloudObj, hConfig = {})
356
+ return nil if not oCloudObj or not @oCoreObject
357
+ @oCoreObject.Create(oCloudObj, hConfig)
358
+ end
359
+
360
+ # a wrapper to Create call. Use this function for code readibility.
361
+ #
362
+ # * *Args* :
363
+ # - +oCloudObj+ : Name of the object to initialize.
364
+ # - +hConfig+ : Hash of hashes containing data required to initialize the object.
365
+ # If you use this variable, any other runtime config defined
366
+ # by the Data model will be cleaned before
367
+ #
368
+ # * *Returns* :
369
+ # - +Lorj::Data+ : Represents the Object initialized.
370
+ #
371
+ # * *Raises* :
372
+ # No exceptions
373
+
374
+ def GetOrCreate(oCloudObj, hConfig = {})
375
+ return nil if not oCloudObj or not @oCoreObject
376
+ @oCoreObject.Create(oCloudObj, hConfig)
377
+ end
378
+
379
+ # Execution of the delete process for the `oCloudObj` object.
380
+ # It requires the object to be loaded in lorj Lorj::Data objects cache.
381
+ # You can use `Create` or `Get` functions to load this object.
382
+ #
383
+ # * *Args* :
384
+ # - +oCloudObj+ : Name of the object to initialize.
385
+ # - +hConfig+ : Hash of hashes containing data required to initialize the object.
386
+ # If you use this variable, any other runtime config defined
387
+ # by the Data model will be cleaned before
388
+ #
389
+ # * *Returns* :
390
+ # - +Lorj::Data+ : Represents the Object initialized.
391
+ #
392
+ # * *Raises* :
393
+ # No exceptions
394
+
395
+ def Delete(oCloudObj, hConfig = {})
396
+ return nil if not oCloudObj or not @oCoreObject
397
+
398
+ @oCoreObject.Delete(oCloudObj, hConfig)
399
+ end
400
+
401
+ # Execution of the Query process for the `oCloudObj` object.
402
+ #
403
+ # * *Args* :
404
+ # - +oCloudObj+ : Name of the object to initialize.
405
+ # - +sQuery+ : Hash representing the query filter.
406
+ # - +hConfig+ : Hash of hashes containing data required to initialize the object.
407
+ # If you use this variable, any other runtime config defined
408
+ # by the Data model will be cleaned before
409
+ #
410
+ # * *Returns* :
411
+ # - +Lorj::Data+ : Represents the Object initialized.
412
+ #
413
+ # * *Raises* :
414
+ # No exceptions
415
+
416
+ def Query(oCloudObj, sQuery, hConfig = {})
417
+ return nil if not oCloudObj or not @oCoreObject
418
+
419
+ @oCoreObject.Query(oCloudObj, sQuery, hConfig)
420
+ end
421
+
422
+ # Execution of the Get process for the `oCloudObj` object.
423
+ #
424
+ # * *Args* :
425
+ # - +oCloudObj+ : Name of the object to initialize.
426
+ # - +sId+ : data representing the ID (attribute :id) of a Lorj::Data object.
427
+ # - +hConfig+ : Hash of hashes containing data required to initialize the object.
428
+ # If you use this variable, any other runtime config defined
429
+ # by the Data model will be cleaned before
430
+ #
431
+ # * *Returns* :
432
+ # - +Lorj::Data+ : Represents the Object initialized.
433
+ #
434
+ # * *Raises* :
435
+ # No exceptions
436
+
437
+ def Get(oCloudObj, sId, hConfig = {})
438
+ return nil if not oCloudObj or not @oCoreObject or sId.nil?
439
+
440
+ @oCoreObject.Get(oCloudObj, sId, hConfig)
441
+ end
442
+
443
+ # Execution of the Update process for the `oCloudObj` object.
444
+ # Usually, the Controller object data is updated by the process (BaseController::set_attr)
445
+ # then it should call a controller_update to really update the data in the controller.
446
+ #
447
+ # * *Args* :
448
+ # - +oCloudObj+ : Name of the object to initialize.
449
+ # - +sId+ : data representing the ID (attribute :id) of a Lorj::Data object.
450
+ # - +hConfig+ : Hash of hashes containing data required to initialize the object.
451
+ # If you use this variable, any other runtime config defined
452
+ # by the Data model will be cleaned before
453
+ #
454
+ # * *Returns* :
455
+ # - +Lorj::Data+ : Represents the Object initialized.
456
+ #
457
+ # * *Raises* :
458
+ # No exceptions
459
+
460
+ def Update(oCloudObj, hConfig = {})
461
+ return nil if not oCloudObj or not @oCoreObject
462
+
463
+ @oCoreObject.Update(oCloudObj, hConfig)
464
+ end
465
+
466
+ # Function used to ask users about setting up his account.
467
+ #
468
+ # * *Args* :
469
+ # - +oCloudObj+ : Name of the object to initialize.
470
+ # - +sAccountName+ : Account file name. If not set, Config[:account_name] is used.
471
+ # If you use this variable, any other runtime config defined
472
+ # by the Data model will be cleaned before
473
+ #
474
+ # * *Returns* :
475
+ # - +Lorj::Data+ : Represents the Object initialized.
476
+ #
477
+ # * *Raises* :
478
+ # No exceptions
479
+
480
+ def Setup(oCloudObj, sAccountName = nil)
481
+ return nil if not oCloudObj or not @oCoreObject
482
+ @oCoreObject.Setup(oCloudObj, sAccountName)
483
+ end
484
+ end
485
+
486
+ # This class based on generic Core, defines a Cloud Process to use.
487
+ class CloudCore < Core
488
+ def initialize(oConfig, sAccount = nil, aProcesses = [])
489
+
490
+ unless oConfig.is_a?(ForjAccount)
491
+ oForjAccount = Lorj::Account.new(oConfig)
492
+ unless sAccount.nil?
493
+ oForjAccount.ac_load(sAccount)
494
+ end
495
+ else
496
+ oForjAccount = oConfig
497
+ end
498
+ aProcessList = [:CloudProcess]
499
+
500
+ sControllerMod = oForjAccount.get(:provider_name)
501
+ raise Lorj::PrcError.new(), "Provider_name not set. Unable to create instance CloudCore." if sControllerMod.nil?
502
+
503
+ sControllerProcessMod = File.join($PROVIDERS_PATH, sControllerMod, sControllerMod.capitalize + "Process.rb")
504
+ if File.exist?(sControllerProcessMod)
505
+ aProcessList << sControllerProcessMod
506
+ else
507
+ Lorj.debug(1, "No Provider process defined. File '%s' not found." % sControllerProcessMod)
508
+ end
509
+
510
+ super(oForjAccount, aProcessList.concat(aProcesses), sControllerMod)
511
+ end
512
+ end
513
+
514
+ # Represents a list of key/value pairs
515
+ # if the value is a Lorj::Data(data or list), the key will be the Lorj::Data type.
516
+ #
517
+ #
518
+ #
519
+ # Used by
520
+ # - BaseDefinition to get a Lorj::Data cache.
521
+ # - Process create/query/update/delete/get to build the hParams
522
+ # The object behavior is adapted to the process usage
523
+ # By default for Lorj::Data(:object), hParams[aKey] will get or set object attributes
524
+ #
525
+ # - Controller create/query/update/delete/get to build the hParams
526
+ # The object behavior is adapted to the controller usage
527
+ # By default for Lorj::Data(:object), hParams[aKey] will get or set controller object
528
+ #
529
+ class ObjectData
530
+ # Intialize the object. By default, usage is for controller context.
531
+ #
532
+ # * *Args* :
533
+ # - +bInternal+ : Context
534
+ # - true if process context
535
+ # - false if controller context. This is the default value.
536
+ #
537
+ # * *Returns* :
538
+ # - nothing
539
+ #
540
+ # * *Raises* :
541
+ # No exceptions
542
+ def initialize(bInternal = false)
543
+
544
+ @hParams = {}
545
+ @hParams[:hdata] = {} unless bInternal
546
+ @bInternal = bInternal
547
+ end
548
+
549
+ # Get function
550
+ #
551
+ # key can be an array, a string (converted to a symbol) or a symbol.
552
+ #
553
+ # * *Args* :
554
+ # - +key+ : key tree (list of keys)
555
+ # If key[1] == :attrs, get will forcelly use the Lorj::Data object attributes
556
+ # If key[1] == :ObjectData, get will forcelly return the controller object
557
+ # otherwise, get will depends on the context:
558
+ # - controller context: will return the controller object
559
+ # - Process context: will return the Lorj::Data object attributes
560
+ # * *Returns* :
561
+ # value found or nil.
562
+ # * *Raises* :
563
+ # nothing
564
+ def [] (*key)
565
+
566
+ key = key.flatten
567
+ # Return ObjectData Element if asked. Ignore additional keys.
568
+ return @hParams[key[0]] if key[1] == :ObjectData
569
+
570
+ return @hParams if key.length == 0
571
+
572
+ oObject = Lorj::rhGet(@hParams, key[0])
573
+ return nil if oObject.nil?
574
+
575
+ # Return attributes if asked
576
+ return oObject[:attrs, key[2..-1]] if key[1] == :attrs
577
+
578
+ if oObject.is_a?(Lorj::Data)
579
+ if @bInternal
580
+ # params are retrieved in process context
581
+ # By default, if key is detected as a framework object, return its data.
582
+ return oObject[:attrs, key[1..-1]]
583
+ else
584
+ # params are retrieved in controller context
585
+ # By default, if key is detected as a controller object, return its data.
586
+ return oObject[:object, key[1..-1]]
587
+ end
588
+ end
589
+
590
+ # otherwise, simply return what is found in keys hierarchy.
591
+ Lorj::rhGet(@hParams, key)
592
+ end
593
+
594
+ # Functions used to set simple data/Object for controller/process function call.
595
+ # TODO: to revisit this function, as we may consider simple data, as Lorj::Data object
596
+ def []= (*key, value)
597
+ return nil if [:object, :query].include?(key[0])
598
+ Lorj::rhSet(@hParams, value, key)
599
+ end
600
+
601
+ # Add function. Add a Lorj::Data (data or list) to the ObjectData list.
602
+ #
603
+ # key can be an array, a string (converted to a symbol) or a symbol.
604
+ #
605
+ # * *Args* :
606
+ # - +oDataObject+ : Lorj::Data object
607
+ # * *Returns* :
608
+ # Nothing
609
+ # * *Raises* :
610
+ # nothing
611
+ def add(oDataObject)
612
+ # Requires to be a valid framework object.
613
+ raise Lorj::PrcError.new, "Invalid Framework object type '%s'." % oDataObject.class unless oDataObject.is_a?(Lorj::Data)
614
+
615
+ sObjectType = oDataObject.object_type?
616
+
617
+ if oDataObject.type? == :list
618
+ oOldDataObject = Lorj::rhGet(@hParams, :query, sObjectType)
619
+ oOldDataObject.unregister if oOldDataObject
620
+ Lorj::rhSet(@hParams, oDataObject, :query, sObjectType)
621
+ else
622
+ oOldDataObject = Lorj::rhGet(@hParams, sObjectType)
623
+ oOldDataObject.unregister if oOldDataObject
624
+ @hParams[sObjectType] = oDataObject
625
+ end
626
+ oDataObject.register
627
+ end
628
+
629
+ # delete function. delete a Lorj::Data (data or list) from the ObjectData list.
630
+ #
631
+ # key can be an array, a string (converted to a symbol) or a symbol.
632
+ #
633
+ # * *Args* :
634
+ # - +oDataObject+ : Lorj::Data object
635
+ # * *Returns* :
636
+ # Nothing
637
+ # * *Raises* :
638
+ # nothing
639
+ def delete(oObj)
640
+ if oObj.is_a?(Symbol)
641
+ sObjectType = oObj
642
+ oObj = @hParams[sObjectType]
643
+ @hParams[sObjectType] = nil
644
+ else
645
+ raise Lorj::PrcError.new(), "ObjectData: delete error. oObj is not a framework data Object. Is a '%s'" % oObj.class unless oObj.is_a?(Lorj::Data)
646
+ if oObj.type? == :list
647
+ Lorj::rhSet(@hParams, nil, :query, oObj.object_type?)
648
+ else
649
+ sObjectType = oObj.object_type?
650
+ @hParams[sObjectType] = nil
651
+ end
652
+ end
653
+ oObj.unregister unless oObj.nil?
654
+ end
655
+
656
+ # Merge 2 ObjectData.
657
+ #
658
+ # * *Args* :
659
+ # - +hHash+ : Hash of Lorj::Data. But it is possible to have different object type (not Lorj::Data)
660
+ # * *Returns* :
661
+ # hash merged
662
+ # * *Raises* :
663
+ # nothing
664
+ def << (hHash)
665
+ @hParams.merge!(hHash)
666
+ end
667
+
668
+ # check Lorj::Data attributes or object exists. Or check key/value pair existence.
669
+ #
670
+ # * *Args* :
671
+ # - +hHash+ : Hash of Lorj::Data. But it is possible to have different object type (not Lorj::Data)
672
+ # * *Returns* :
673
+ # true/false
674
+ # * *Raises* :
675
+ # PrcError
676
+ def exist?(*key)
677
+ raise Lorj::PrcError.new, "ObjectData: key is not list of values (string/symbol or array)" if not [Array, String, Symbol].include?(key.class)
678
+
679
+ key = [key] if key.is_a?(Symbol) or key.is_a?(String)
680
+
681
+ key = key.flatten
682
+
683
+ oObject = Lorj::rhGet(@hParams, key[0])
684
+ return false if oObject.nil?
685
+
686
+ if oObject.is_a?(Lorj::Data)
687
+ # Return true if ObjectData Element is found when asked.
688
+ return true if key[1] == :ObjectData and oObject.type?(key[0]) == :object
689
+
690
+ # Return true if attritutes or controller object attributes found when asked.
691
+ return oObject.exist?(key[2..-1]) if key[1] == :attrs
692
+ return oObject.exist?(key[1..-1]) if key.length > 1
693
+ true
694
+ else
695
+ # By default true if found key hierarchy
696
+ (Lorj::rhExist?(@hParams, key) == key.length)
697
+ end
698
+ end
699
+
700
+ # Determine the type of object identified by a key. Lorj::Data attributes or object exists. Or check key/value pair existence.
701
+ #
702
+ # * *Args* :
703
+ # - +key+ : Key to check in ObjectData list.
704
+ # * *Returns* :
705
+ # - nil if not found
706
+ # - :data if the key value is simply a data
707
+ # - :DataObject if the key value is a Lorj::Data
708
+ # * *Raises* :
709
+ # PrcError
710
+
711
+ def type?(key)
712
+ return nil if Lorj::rhExist?(@hParams, key) != 1
713
+ :data
714
+ :DataObject if @hParams[key].type?() == :object
715
+ end
716
+
717
+ def cObj(*key)
718
+ Lorj::rhGet(@hParams, key, :object) if Lorj::rhExist?(@hParams, key, :object) == 2
719
+ end
720
+
721
+ end
722
+
723
+ end