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
@@ -0,0 +1,1079 @@
1
+ # encoding: UTF-8
2
+
3
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # Module Lorj which contains several classes.
18
+ #
19
+ # Those classes describes :
20
+ # - processes (BaseProcess) : How to create/delete/edit/query object.
21
+ # - controler (BaseControler) : If a provider is defined, define how will do object creation/etc...
22
+ # - definition(BaseDefinition): Functions to declare objects, query/data mapping and setup
23
+ # this task to make it to work.
24
+
25
+ module Lorj
26
+ # Following class defines class levels function to
27
+ # declare framework objects.
28
+ # As each process needs to define new object to deal with
29
+ # require that process to define it with definition functions
30
+ # See definition.rb for functions to use.
31
+
32
+ class BaseDefinition
33
+ # Capitalized function are called to start a process. It is done by Core class.
34
+
35
+ # Call meta lorj object creation process.
36
+ # The creation process can implement any logic like:
37
+ # - create an object in the DB.
38
+ # - check object existence in the DB. If not exists, create it.
39
+ #
40
+ # * *Args* :
41
+ # - +ObjectType+ : Meta object type to create.
42
+ # - +Config+ : Optional. Hash containing list of data to use for creation.
43
+ #
44
+ # * *Returns* :
45
+ # - +Object+ : Lorj::Data object of type +ObjectType+ created.
46
+ #
47
+ # * *Raises* :
48
+ # - Warning if the create_e process handler did not return any data. (nil)
49
+ # - Warning if the Config data passed are not required by the meta object (or dependencies) at creation time.
50
+ # - Error if ObjectType has never been declared.
51
+ # - Error if the dependencies create_e process handler did not return any data. (nil) - Loop detection.
52
+ # - Error if the create_e process handler raise an error.
53
+ #
54
+ def Create(sObjectType, hConfig = {})
55
+
56
+ if hConfig.length > 0
57
+ # cleanup runtime data to avoid conflicts between multiple calls
58
+ valid_keys = _identify_data(sObjectType, :create_e)
59
+ valid_keys.each { | sKey|
60
+ value = Lorj::rhGet(hConfig, sKey)
61
+ @oForjConfig[sKey] = value if not @oForjConfig.exist?(sKey) or @oForjConfig.exist?(sKey) == 'runtime'
62
+ Lorj::rhSet(hConfig, nil, sKey)
63
+ }
64
+ if hConfig.length > 0
65
+ PrcLib::warning("'%s' has been passed but not declared to '%s' object. Those are ignored until you add it in the model definition of '%s'" % [hConfig.keys, sObjectType, sObjectType])
66
+ end
67
+ end
68
+
69
+ return nil if not sObjectType
70
+ raise Lorj::PrcError.new(), "%s.Create: '%s' is not a known object type." % [self.class, sObjectType] if Lorj::rhExist?(@@meta_obj, sObjectType) != 1
71
+
72
+ pProc = Lorj::rhGet(@@meta_obj, sObjectType, :lambdas, :create_e)
73
+
74
+ # Check required parameters
75
+ oObjMissing = _check_required(sObjectType, :create_e, pProc).reverse
76
+
77
+ while oObjMissing.length >0
78
+ sElem = oObjMissing.pop
79
+
80
+ raise Lorj::PrcError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
81
+ oObjMissing = _check_required(sObjectType, :create_e, pProc).reverse
82
+
83
+ raise Lorj::PrcError.new(), "loop detection: '%s' is required but Create(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
84
+ end
85
+ @RuntimeContext[:oCurrentObj] = sObjectType # Context: Default object used.
86
+
87
+ if pProc.nil?
88
+ # This object is a meta object, without any data.
89
+ # Used to build other kind of objects.
90
+ oObject = Lorj::Data.new
91
+ oObject.set({}, sObjectType) {}
92
+ else
93
+ # build Function params to pass to the event handler.
94
+ aParams = _get_object_params(sObjectType, :create_e, pProc,)
95
+ Lorj.debug(2, "Create Object '%s' - Running '%s'" % [sObjectType, pProc])
96
+
97
+ # Call the process function.
98
+ # At some point, the process will call the controller, via the framework.
99
+ # This controller call via the framework has the role to
100
+ # create an ObjectData well formatted, with _return_map function
101
+ # See Definition.connect/create/update/query/get functions (lowercase)
102
+ oObject = @oForjProcess.method(pProc).call(sObjectType, aParams)
103
+ # return usually is the main object that the process called should provide.
104
+ # Save Object if the object has been created by the process, without controller
105
+ end
106
+
107
+ unless oObject.nil?
108
+ query_cleanup(sObjectType)
109
+ @ObjectData.add(oObject)
110
+ else
111
+ PrcLib::warning("'%s' has returned no data for object Lorj::Data '%s'!" % [pProc, sObjectType])
112
+ end
113
+ end
114
+
115
+ # Call meta lorj object deletion process
116
+ # There is no implementation of cascade deletion. It is up to the process to do it or not.
117
+ #
118
+ # * *Args* :
119
+ # - +ObjectType+ : Meta object type to create.
120
+ # - +Config+ : Optional. Hash containing list of data to use for creation.
121
+ #
122
+ # * *Returns* :
123
+ # - +Deleted+ : true if deleted or false otherwise.
124
+ #
125
+ # * *Raises* :
126
+ # - Warning if the create_e process handler did not return any data. (nil)
127
+ # - Warning if the Config data passed are not required by the meta object (or dependencies) at creation time.
128
+ # - Error if ObjectType has never been declared.
129
+ # - Error if the dependencies query_e process handler did not return any data. (nil) - Loop detection.
130
+ # - Error if the query_e process handler raise an error.
131
+ #
132
+ def Delete(sCloudObj, hConfig = {})
133
+ return nil if not sCloudObj
134
+
135
+ raise Lorj::PrcError.new(), "%s.Delete: '%s' is not a known object type." % [self.class, sCloudObj] if Lorj::rhExist?(@@meta_obj, sCloudObj) != 1
136
+
137
+ if hConfig.length > 0
138
+ # cleanup runtime data to avoid conflicts between multiple calls
139
+ valid_keys = _identify_data(sCloudObj, :delete_e)
140
+ valid_keys.each { | sKey|
141
+ value = Lorj::rhGet(hConfig, sKey)
142
+ @oForjConfig[sKey] = value if not @oForjConfig.exist?(sKey) or @oForjConfig.exist?(sKey) == 'runtime'
143
+ Lorj::rhSet(hConfig, nil, sKey)
144
+ }
145
+ if hConfig.length > 0
146
+ PrcLib::warning("'%s' has been passed but not declared to '%s' object. Those are ignored until you add it in the model definition of '%s'" % [hConfig.keys, sCloudObj, sCloudObj])
147
+ end
148
+ end
149
+
150
+ pProc = Lorj::rhGet(@@meta_obj, sCloudObj, :lambdas, :delete_e)
151
+
152
+ return nil if pProc.nil?
153
+
154
+ # Check required parameters
155
+ oObjMissing = _check_required(sCloudObj, :delete_e, pProc).reverse
156
+
157
+ while oObjMissing.length >0
158
+ sElem = oObjMissing.pop
159
+ if sElem == sCloudObj
160
+ debug(2, "'%s' object is not previously loaded or created." % sCloudObj) if sElem == sCloudObj
161
+ next
162
+ end
163
+ raise Lorj::PrcError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
164
+ oObjMissing = _check_required(sCloudObj, :delete_e, pProc).reverse
165
+ raise Lorj::PrcError.new(), "Unable to delete '%s' object. required '%s' data was not loaded after 'Create(%s)'. Check create handler for object type '%s'." % [sCloudObj, sElem, sElem, sElem] if oObjMissing.include?(sElem)
166
+ end
167
+ @RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
168
+
169
+ # build Function params to pass to the event handler.
170
+ aParams = _get_object_params(sCloudObj, :delete_e, pProc)
171
+
172
+ bState = @oForjProcess.method(pProc).call(sCloudObj, aParams)
173
+ # return usually is the main object that the process called should provide.
174
+ if bState
175
+ @ObjectData.delete(sCloudObj)
176
+ end
177
+
178
+ end
179
+
180
+ # Function to clean the cache for a specific meta lorj object queried.
181
+ #
182
+ # * *Args* :
183
+ # - +ObjectType+ : Meta object type to cleanup.
184
+ #
185
+ # * *Returns* :
186
+ # no data
187
+ #
188
+ # * *Raises* :
189
+ #
190
+ def query_cleanup(sCloudObj)
191
+ oList = @ObjectData[:query, sCloudObj]
192
+ unless oList.nil?
193
+ @ObjectData.delete(oList)
194
+ Lorj.debug(2, "Query cache for object '%s' cleaned." % sCloudObj)
195
+ end
196
+ end
197
+
198
+ # Function to clean the cache for a specific meta lorj object.
199
+ #
200
+ # * *Args* :
201
+ # - +ObjectType+ : Meta object type to cleanup.
202
+ #
203
+ # * *Returns* :
204
+ # no data
205
+ #
206
+ # * *Raises* :
207
+ #
208
+ def object_cleanup(sCloudObj)
209
+ oObject = @ObjectData[sCloudObj, :ObjectData]
210
+ unless oObject.nil?
211
+ @ObjectData.delete(oObject)
212
+ end
213
+ end
214
+
215
+ # Function to execute a query process. This function returns a Lorj::Data of type :list.
216
+ #
217
+ # * *Args* :
218
+ # - +ObjectType+ : Meta object type to query.
219
+ # - +Query+ : Hash. Represent the query to execute.
220
+ # - +Config+ : Optional. Hash containing list of data to use for query.
221
+ #
222
+ # * *Returns* :
223
+ # Lorj::Data of type :list
224
+ #
225
+ # * *Raises* :
226
+ #
227
+ #
228
+ def Query(sCloudObj, hQuery, hConfig = {})
229
+
230
+ return nil if not sCloudObj
231
+
232
+ raise Lorj::PrcError.new(), "$s.Get: '%s' is not a known object type." % [self.class, sCloudObj] if Lorj::rhExist?(@@meta_obj, sCloudObj) != 1
233
+
234
+ if hConfig.length > 0
235
+ # cleanup runtime data to avoid conflicts between multiple calls
236
+ valid_keys = _identify_data(sCloudObj, :query_e)
237
+ valid_keys.each { | sKey|
238
+ value = Lorj::rhGet(hConfig, sKey)
239
+ @oForjConfig[sKey] = value if not @oForjConfig.exist?(sKey) or @oForjConfig.exist?(sKey) == 'runtime'
240
+ Lorj::rhSet(hConfig, nil, sKey)
241
+ }
242
+ if hConfig.length > 0
243
+ PrcLib::warning("'%s' has been passed but not declared to '%s' object. Those are ignored until you add it in the model definition of '%s'" % [hConfig.keys, sCloudObj, sCloudObj])
244
+ end
245
+ end
246
+
247
+ # Check if we can re-use a previous query
248
+ oList = @ObjectData[:query, sCloudObj]
249
+ unless oList.nil?
250
+ if oList[:query] == hQuery
251
+ Lorj.debug(3, "Using Object '%s' query cache : %s" % [sCloudObj, hQuery])
252
+ return oList
253
+ end
254
+ end
255
+
256
+ pProc = Lorj::rhGet(@@meta_obj, sCloudObj, :lambdas, :query_e)
257
+
258
+ return nil if pProc.nil?
259
+
260
+ # Check required parameters
261
+ oObjMissing = _check_required(sCloudObj, :query_e, pProc).reverse
262
+
263
+ while oObjMissing.length >0
264
+ sElem = oObjMissing.pop
265
+ raise Lorj::PrcError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
266
+ oObjMissing = _check_required(sCloudObj, :query_e, pProc).reverse
267
+ raise Lorj::PrcError.new(), "loop detection: '%s' is required but Query(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
268
+ end
269
+ @RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
270
+
271
+ # build Function params to pass to the Process Event handler.
272
+ aParams = _get_object_params(sCloudObj, :query_e, pProc)
273
+
274
+ # Call the process function.
275
+ # At some point, the process will call the controller, via the framework.
276
+ # This controller call via the framework has the role to
277
+ # create an ObjectData well formatted, with _return_map function
278
+ # See Definition.connect/create/update/query/get functions (lowercase)
279
+ oObject = @oForjProcess.method(pProc).call(sCloudObj, hQuery, aParams)
280
+ # return usually is the main object that the process called should provide.
281
+ unless oObject.nil?
282
+ # Save Object if the object has been created by the process, without controller
283
+ @ObjectData.add(oObject)
284
+ else
285
+ PrcLib::warning("'%s' returned no collection of objects Lorj::Data for '%s'" % [pProc, sCloudObj])
286
+ end
287
+ end
288
+
289
+ # Function to execute a get process. This function returns a Lorj::Data of type :object.
290
+ #
291
+ # * *Args* :
292
+ # - +ObjectType+ : Meta object type to query.
293
+ # - +UniqId+ : Uniq ID.
294
+ # - +Config+ : Optional. Hash containing list of data to use for getting.
295
+ #
296
+ # * *Returns* :
297
+ # Lorj::Data of type :object
298
+ #
299
+ # * *Raises* :
300
+ # - Warning if the Config data passed are not required by the meta object (or dependencies) at creation time.
301
+ # - Error if ObjectType has never been declared.
302
+ # - Error if the dependencies get_e process handler did not return any data. (nil) - Loop detection.
303
+ # - Error if the get_e process handler raise an error.
304
+ #
305
+ def Get(sCloudObj, sUniqId, hConfig = {})
306
+
307
+ return nil if not sCloudObj
308
+
309
+ raise Lorj::PrcError.new(), "$s.Get: '%s' is not a known object type." % [self.class, sCloudObj] if Lorj::rhExist?(@@meta_obj, sCloudObj) != 1
310
+
311
+ if hConfig.length > 0
312
+ # cleanup runtime data to avoid conflicts between multiple calls
313
+ valid_keys = _identify_data(sCloudObj, :get_e)
314
+ valid_keys.each { | sKey|
315
+ value = Lorj::rhGet(hConfig, sKey)
316
+ @oForjConfig[sKey] = value if not @oForjConfig.exist?(sKey) or @oForjConfig.exist?(sKey) == 'runtime'
317
+ Lorj::rhSet(hConfig, nil, sKey)
318
+ }
319
+ if hConfig.length > 0
320
+ Lorj::warning("'%s' has been passed but not declared to '%s' object. Those are ignored until you add it in the model definition of '%s'" % [hConfig.keys, sCloudObj, sCloudObj])
321
+ end
322
+ end
323
+
324
+ pProc = Lorj::rhGet(@@meta_obj, sCloudObj, :lambdas, :get_e)
325
+
326
+ return nil if pProc.nil?
327
+
328
+ # Check required parameters
329
+ oObjMissing = _check_required(sCloudObj, :get_e, pProc).reverse
330
+
331
+ while oObjMissing.length >0
332
+ sElem = oObjMissing.pop
333
+ raise Lorj::PrcError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
334
+ oObjMissing = _check_required(sCloudObj, :get_e, pProc).reverse
335
+ raise Lorj::PrcError.new(), "loop detection: '%s' is required but Get(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
336
+ end
337
+ @RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
338
+
339
+ # build Function params to pass to the Process Event handler.
340
+ aParams = _get_object_params(sCloudObj, :get_e, pProc)
341
+
342
+ # Call the process function.
343
+ # At some point, the process will call the controller, via the framework.
344
+ # This controller call via the framework has the role to
345
+ # create an ObjectData well formatted, with _return_map function
346
+ # See Definition.connect/create/update/query/get functions (lowercase)
347
+ oObject = @oForjProcess.method(pProc).call(sCloudObj, sUniqId, aParams)
348
+ # return usually is the main object that the process called should provide.
349
+ unless oObject.nil?
350
+ # Save Object if the object has been created by the process, without controller
351
+ @ObjectData.add(oObject)
352
+ end
353
+ end
354
+
355
+ # Function to execute a update process. This function returns a Lorj::Data of type :object.
356
+ #
357
+ # * *Args* :
358
+ # - +ObjectType+ : Meta object type to query.
359
+ # - +Config+ : Optional. Hash containing list of data to use for updating.
360
+ #
361
+ # * *Returns* :
362
+ # Lorj::Data of type :object
363
+ #
364
+ # * *Raises* :
365
+ # - Warning if the Config data passed are not required by the meta object (or dependencies) at creation time.
366
+ # - Error if ObjectType has never been declared.
367
+ # - Error if the dependencies get_e process handler did not return any data. (nil) - Loop detection.
368
+ # - Error if the get_e process handler raise an error.
369
+ #
370
+ def Update(sCloudObj, hConfig = {})
371
+
372
+ return nil if not sCloudObj
373
+
374
+ raise Lorj::PrcError.new(), "$s.Update: '%s' is not a known object type." % [self.class, sCloudObj] if Lorj::rhExist?(@@meta_obj, sCloudObj) != 1
375
+
376
+ if hConfig.length > 0
377
+ # cleanup runtime data to avoid conflicts between multiple calls
378
+ valid_keys = _identify_data(sCloudObj, :update_e)
379
+ valid_keys.each { | sKey|
380
+ value = Lorj::rhGet(hConfig, sKey)
381
+ @oForjConfig[sKey] = value if not @oForjConfig.exist?(sKey) or @oForjConfig.exist?(sKey) == 'runtime'
382
+ Lorj::rhSet(hConfig, nil, sKey)
383
+ }
384
+ if hConfig.length > 0
385
+ PrcLib::warning("'%s' has been passed but not declared to '%s' object. Those are ignored until you add it in the model definition of '%s'" % [hConfig.keys, sCloudObj, sCloudObj])
386
+ end
387
+ end
388
+
389
+ pProc = Lorj::rhGet(@@meta_obj, sCloudObj, :lambdas, :update_e)
390
+
391
+ return nil if pProc.nil?
392
+
393
+ # Check required parameters
394
+ oObjMissing = _check_required(sCloudObj, :update_e, pProc).reverse
395
+
396
+ while oObjMissing.length >0
397
+ sElem = oObjMissing.pop
398
+ raise Lorj::PrcError.new(),"Unable to create Object '%s'" % sElem if not Create(sElem)
399
+ oObjMissing = _check_required(sCloudObj, :update_e, pProc).reverse
400
+ raise Lorj::PrcError.new(), "loop detection: '%s' is required but Update(%s) did not loaded it." % [sElem, sElem] if oObjMissing.include?(sElem)
401
+ end
402
+ @RuntimeContext[:oCurrentObj] = sCloudObj # Context: Default object used.
403
+
404
+ # build Function params to pass to the event handler.
405
+ aParams = _get_object_params(sCloudObj, :update_e, pProc)
406
+
407
+ oObject = @oForjProcess.method(pProc).call(sCloudObj, aParams)
408
+ # return usually is the main object that the process called should provide.
409
+ unless oObject.nil?
410
+ # Save Object if the object has been created by the process, without controller
411
+ @ObjectData.add(oObject)
412
+ end
413
+ end
414
+
415
+ # Function to execute a setup process.
416
+ # The setup process will ask the end user to enter values as defined by the defaults.yaml application defaults.
417
+ # For setup features implemented, see Lorj::BaseDefinition::meta_data class variable definition.
418
+ #
419
+ # Setup by default, will ask any kind of data required by a meta object and all dependencies.
420
+ # If the setup needs to add some extra fields to ask to the user, set it in /:setup/:ask_step/*:add/* section
421
+ #
422
+ # Setup uses a Config model object which requires to have at least following functions:
423
+ # - value = get(key, default)
424
+ # - set(key, value)
425
+ #
426
+ # Setup keep end user data in memory. After setup, you HAVE to save them
427
+ # If you are using Lorj::Account, use function ac_save
428
+ # If you are using Lorj::Config, use function configSave
429
+ #
430
+ # * *Args* :
431
+ # - +ObjectType+ : Meta object type to query.
432
+ # - +Config+ : Optional. Hash containing list of data to use for updating.
433
+ #
434
+ # * *Returns* :
435
+ # Lorj::Data of type :object
436
+ #
437
+ # * *Raises* :
438
+ #
439
+ def Setup(sObjectType, sAccountName)
440
+ # Loop in dependencies to get list of data object to setup
441
+ raise Lorj::PrcError,new(), "Setup: '%s' not a valid object type." if Lorj::rhExist?(@@meta_obj, sObjectType) != 1
442
+
443
+ hAskStep = Lorj::Default.get(:ask_step, :setup)
444
+ aSetup = []
445
+ hAskStep.each{ | value |
446
+ aSetup << {
447
+ :desc => value[:desc],
448
+ :explanation => value[:explanation],
449
+ :pre_step_handler => value[:pre_step_function],
450
+ :order => [[]],
451
+ :post_step_handler => value[:post_step_function]
452
+ }
453
+
454
+ }
455
+ oInspectedObjects = []
456
+ oInspectObj = [sObjectType]
457
+
458
+ @oForjConfig.ac_load(sAccountName) if sAccountName
459
+
460
+ Lorj.debug(2, "Setup is identifying account data to ask for '%s'" % sObjectType)
461
+ while oInspectObj.length() >0
462
+ # Identify data to ask
463
+ # A data to ask is a data needs from an object type
464
+ # which is declared in section of defaults.yaml
465
+ # and is declared :account to true (in defaults.yaml or in process declaration - define_data)
466
+
467
+ sObjectType = oInspectObj.pop
468
+ sAsk_step = 0
469
+ Lorj.debug(1, "Checking '%s'" % sObjectType)
470
+ hTopParams = Lorj::rhGet(@@meta_obj,sObjectType, :params)
471
+ if hTopParams[:keys].nil?
472
+ Lorj.debug(1, "Warning! Object '%s' has no data/object needs. Check the process" % sObjectType)
473
+ next
474
+ end
475
+ hTopParams[:keys].each { |sKeypath, hParams|
476
+ oKeyPath = KeyPath.new(sKeypath)
477
+ sKey = oKeyPath.sKey
478
+ case hParams[:type]
479
+ when :data
480
+ hMeta = _get_meta_data(sKey)
481
+ next if hMeta.nil?
482
+ sAsk_step = hMeta[:ask_step] if Lorj::rhExist?(hMeta, :ask_step) == 1 and hMeta[:ask_step].is_a?(Fixnum)
483
+ Lorj.debug(3, "#{sKey} is part of setup step #{sAsk_step}")
484
+ aOrder = aSetup[sAsk_step][:order]
485
+
486
+ if oInspectedObjects.include?(sKey)
487
+ Lorj.debug(2, "#{sKey} is already asked. Ignored.")
488
+ next
489
+ end
490
+ if hMeta[:account].is_a?(TrueClass)
491
+ if not hMeta[:depends_on].is_a?(Array)
492
+ PrcLib.warning("'%s' depends_on definition have to be an array." % oKeyPath.sFullPath) unless hMeta[:depends_on].nil?
493
+ iLevel = 0
494
+ bFound = true
495
+ else
496
+ # Searching highest level from dependencies.
497
+ bFound = false
498
+ iLevel = 0
499
+ hMeta[:depends_on].each { |depend_key|
500
+ aOrder.each_index { |iCurLevel|
501
+ if aOrder[iCurLevel].include?(depend_key)
502
+ bFound = true
503
+ iLevel = [iLevel, iCurLevel + 1].max
504
+ end
505
+ }
506
+ aOrder[iLevel] = [] if aOrder[iLevel].nil?
507
+ }
508
+ end
509
+ if bFound
510
+ if not aOrder[iLevel].include?(sKey)
511
+ if hMeta[:ask_sort].is_a?(Fixnum)
512
+ iOrder = hMeta[:ask_sort]
513
+ if aOrder[iLevel][iOrder].nil?
514
+ aOrder[iLevel][iOrder] = sKey
515
+ else
516
+ aOrder[iLevel].insert(iOrder, sKey)
517
+ end
518
+ Lorj.debug(3, "S%s/L%s/O%s: '%s' added in setup list. " % [sAsk_step, iLevel, iOrder, sKey])
519
+ else
520
+ aOrder[iLevel] << sKey
521
+ Lorj.debug(3, "S%s/L%s/Last: '%s' added in setup list." % [sAsk_step, iLevel, sKey])
522
+ end
523
+ end
524
+ end
525
+ oInspectedObjects << sKey
526
+ else
527
+ Lorj.debug(2, "#{sKey} used by #{sObjectType} won't be asked during setup. :account = true not set.")
528
+ end
529
+ when :CloudObject
530
+ oInspectObj << sKey if not oInspectObj.include?(sKey) and not oInspectedObjects.include?(sKey)
531
+ end
532
+ }
533
+ oInspectedObjects << sObjectType
534
+ end
535
+ Lorj.debug(2, "Setup check if needs to add unrelated data in the process")
536
+ hAskStep.each_index{ | iStep |
537
+ value = hAskStep[iStep]
538
+ if Lorj::rhExist?(value, :add) == 1
539
+ sKeysToAdd = Lorj::rhGet(value, :add)
540
+ sKeysToAdd.each { | sKeyToAdd |
541
+ bFound = false
542
+ aSetup[iStep][:order].each_index { | iOrder |
543
+ sKeysToAsk = aSetup[iStep][:order][iOrder]
544
+ unless sKeysToAsk.index(sKeyToAdd).nil?
545
+ bFound = true
546
+ break
547
+ end
548
+ }
549
+ next if bFound
550
+ iLevel = 0
551
+ iOrder = aSetup[iStep][:order].length
552
+ iAtStep = iStep
553
+ hMeta = _get_meta_data(sKeyToAdd)
554
+ if Lorj::rhExist?(hMeta, :after) == 1
555
+ sAfterKeys = hMeta[:after]
556
+ sAfterKeys = [ sAfterKeys ] if not sAfterKeys.is_a?(Array)
557
+ sAfterKeys.each{ |sAfterKey |
558
+ bFound = false
559
+ aSetup.each_index { |iStepToCheck|
560
+ aSetup[iStepToCheck][:order].each_index { | iLevelToCheck |
561
+ sKeysToAsk = aSetup[iStepToCheck][:order][iLevelToCheck]
562
+ iOrderToCheck = sKeysToAsk.index(sAfterKey)
563
+ unless iOrderToCheck.nil?
564
+ iAtStep = iStepToCheck if iStepToCheck > iAtStep
565
+ iLevel = iLevelToCheck if iLevelToCheck > iLevel
566
+ iOrder = iOrderToCheck + 1 if iOrderToCheck + 1 > iOrder
567
+ bFound = true
568
+ break
569
+ end
570
+ }
571
+ }
572
+ }
573
+ end
574
+ aSetup[iAtStep][:order][iLevel].insert(iOrder, sKeyToAdd)
575
+ Lorj.debug(3, "S%s/L%s/O%s: '%s' added in setup list at position." % [iAtStep, iLevel, iOrder, sKeyToAdd])
576
+ }
577
+ end
578
+ }
579
+
580
+ Lorj.debug(2, "Setup will ask for :\n %s" % aSetup.to_yaml)
581
+
582
+ PrcLib.info("Configuring account : '#{config[:account_name]}', provider '#{config[:provider_name]}'")
583
+
584
+ # Ask for user input
585
+ aSetup.each_index { | iStep |
586
+ Lorj.debug(2, "Ask step %s:" % iStep)
587
+ puts "%s%s%s" % [ANSI.bold, aSetup[iStep][:desc], ANSI.clear] unless aSetup[iStep][:desc].nil?
588
+ puts "%s\n\n" % ANSI.yellow(aSetup[iStep][:explanation]) unless aSetup[iStep][:explanation].nil?
589
+ aOrder = aSetup[iStep][:order]
590
+ aOrder.each_index { | iIndex |
591
+ Lorj.debug(2, "Ask order %s:" % iIndex)
592
+ aOrder[iIndex].each { | sKey |
593
+ hParam = _get_meta_data(sKey)
594
+ hParam = {} if hParam.nil?
595
+
596
+ bOk = false
597
+
598
+ if hParam[:pre_step_function]
599
+ pProc = hParam[:pre_step_function]
600
+ bOk = not(@oForjProcess.method(pProc).call(sKey))
601
+ end
602
+
603
+
604
+ sDesc = "'%s' value" % sKey
605
+ puts "#{sKey}: %s" % [hParam[:explanation]] unless Lorj::rhGet(hParam, :explanation).nil?
606
+ sDesc = hParam[:desc] unless hParam[:desc].nil?
607
+ sDefault = @oForjConfig.get(sKey, hParam[:default_value])
608
+ rValidate = nil
609
+
610
+ rValidate = hParam[:validate] unless hParam[:validate].nil?
611
+ bRequired = (hParam[:required] == true)
612
+ while not bOk
613
+ bOk = true
614
+ if not hParam[:list_values].nil?
615
+ hValues = hParam[:list_values]
616
+ sObjectToLoad = hValues[:object]
617
+
618
+ bListStrict = (hValues[:validate] == :list_strict)
619
+
620
+ case hValues[:query_type]
621
+ when :controller_call
622
+ oObject = @ObjectData[sObjectToLoad, :ObjectData]
623
+ PrcLib.message("Loading #{sObjectToLoad}.")
624
+ oObject = Create(sObjectToLoad) if oObject.nil?
625
+ return nil if oObject.nil?
626
+ oParams = ObjectData.new
627
+ oParams.add(oObject)
628
+ oParams << hValues[:query_params]
629
+ raise Lorj::PrcError.new(), "#{sKey}: query_type => :controller_call requires missing :query_call declaration (Controller function)" if hValues[:query_call].nil?
630
+ pProc = hValues[:query_call]
631
+ begin
632
+ aList = @oProvider.method(pProc).call(sObjectToLoad, oParams)
633
+ rescue => e
634
+ raise Lorj::PrcError.new(), "Error during call of '%s':\n%s" % [pProc, e.message]
635
+ end
636
+ when :query_call
637
+ sQuery = {}
638
+ sQuery = hValues[:query_params] unless hValues[:query_params].nil?
639
+ PrcLib.message("Querying #{sObjectToLoad}.")
640
+ oObjectList = Query(sObjectToLoad, sQuery)
641
+ aList = []
642
+ oObjectList.each { | oElem |
643
+ aList << oElem[hValues[:value]]
644
+ }
645
+ aList.sort!
646
+ when :process_call
647
+ raise Lorj::PrcError.new(), "#{sKey}: query_type => :process_call requires missing :query_call declaration (Provider function)" if hValues[:query_call].nil?
648
+ pProc = hValues[:query_call]
649
+ sObjectToLoad = hValues[:object]
650
+ oParams = ObjectData.new
651
+ oParams.add(oObject)
652
+ oParams << hValues[:query_params]
653
+ begin
654
+ aList = @oForjProcess.method(pProc).call(sObjectToLoad, oParams)
655
+ rescue => e
656
+ raise Lorj::PrcError.new(), "Error during call of '%s':\n%s" % [pProc, e.message]
657
+ end
658
+ else
659
+ raise Lorj::PrcError.new, "'%s' invalid. %s/list_values/values_type supports %s. " % [hValues[:values_type], sKey, [:provider_function]]
660
+ end
661
+ PrcLib.fatal(1, "%s requires a value from the '%s' query which is empty." % [sKey, sObjectToLoad])if aList.nil? and bListStrict
662
+ aList = [] if aList.nil?
663
+ if not bListStrict
664
+ aList << "other"
665
+ end
666
+ say("Enter %s" % ((sDefault.nil?)? sDesc : sDesc + " |%s|" % sDefault))
667
+ value = choose { | q |
668
+ q.choices(*aList)
669
+ q.default = sDefault if sDefault
670
+ }
671
+ if not bListStrict and value == "other"
672
+ value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
673
+ end
674
+ else
675
+ pValidateProc = hParam[:validate_function]
676
+ pAskProc = hParam[:ask_function]
677
+
678
+ if pAskProc.nil?
679
+ unless pValidateProc.nil?
680
+ value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
681
+ while not @oForjProcess.method(pValidateProc).call(value)
682
+ value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
683
+ end
684
+ else
685
+ value = _ask(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
686
+ end
687
+ else
688
+ unless pValidateProc.nil?
689
+ value = @oForjProcess.method(pAskProc).call(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
690
+ while not @oForjProcess.method(pValidateProc).call(value)
691
+ value = @oForjProcess.method(pAskProc).call(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
692
+ end
693
+ else
694
+ value = @oForjProcess.method(pAskProc).call(sDesc, sDefault, rValidate, hParam[:encrypted], bRequired)
695
+ end
696
+ end
697
+ end
698
+
699
+ @oForjConfig.set(sKey, value)
700
+ if hParam[:post_step_function]
701
+ pProc = hParam[:post_step_function]
702
+ bOk = @oForjProcess.method(pProc).call()
703
+ end
704
+ end
705
+ }
706
+ }
707
+ }
708
+ end
709
+
710
+ # Initialize Lorj BaseDefinition object
711
+
712
+ def initialize(oForjConfig, oForjProcess, oForjProvider = nil)
713
+ # Object Data object. Contains all loaded object data.
714
+ # This object is used to build hParams as well.
715
+ @ObjectData = ObjectData.new(true)
716
+ #
717
+ @RuntimeContext = {
718
+ :oCurrentObj => nil
719
+ }
720
+
721
+ @oForjConfig = oForjConfig
722
+ raise Lorj::PrcError.new(), "'%s' is not a valid ForjAccount or ForjConfig Object." % [oForjConfig.class] if not oForjConfig.is_a?(Lorj::Account) and not oForjConfig.is_a?(Lorj::Config)
723
+
724
+ @oProvider = oForjProvider
725
+ if oForjProvider
726
+ raise Lorj::PrcError.new(), "'%s' is not a valid ForjProvider Object type." % [oForjProvider.class] if not oForjProvider.is_a?(BaseController)
727
+ end
728
+
729
+ @oForjProcess = oForjProcess
730
+ raise Lorj::PrcError.new(), "'%s' is not a valid BaseProcess Object type." % [oForjProcess.class] if not oForjProcess.is_a?(BaseProcess)
731
+
732
+ @oForjProcess.set_BaseObject(self)
733
+ end
734
+
735
+ # ------------------------------------------------------
736
+ # Functions used by processes functions
737
+ # ------------------------------------------------------
738
+ # Ex: object.set_data(...)
739
+ # config
740
+
741
+
742
+ # Function to manipulate the config object.
743
+ # 2 kind of functions:
744
+ # - set (key, value) and []=(key, value)
745
+ # From processes, you can set a runtime data with:
746
+ # config.set(key, value)
747
+ # OR
748
+ # config[key] = value
749
+ #
750
+ # - get (key, default) and [](key, default)
751
+ # default is an optional value.
752
+ # From processes, you can get a data (runtime/account/config.yaml or defaults.yaml) with:
753
+ # config.get(key)
754
+ # OR
755
+ # config[key]
756
+
757
+ def config
758
+ raise Lorj::PrcError.new(), "No config object loaded." if not @oForjConfig
759
+ @oForjConfig
760
+ end
761
+
762
+ def format_query(sObjectType, oControlerObject, hQuery)
763
+ {
764
+ :object => oControlerObject,
765
+ :object_type => :object_list,
766
+ :list_type => sObjectType,
767
+ :list => [],
768
+ :query => hQuery
769
+ }
770
+ end
771
+
772
+ def format_object(sCloudObj, oMiscObject)
773
+ return nil if not sCloudObj or not [String, Symbol].include?(sCloudObj.class)
774
+
775
+ sCloudObj = sCloudObj.to_sym if sCloudObj.class == String
776
+
777
+ oCoreObject = {
778
+ :object_type => sCloudObj,
779
+ :attrs => {},
780
+ :object => oMiscObject,
781
+ }
782
+ end
783
+
784
+ def get_data_metadata(sKey)
785
+ _get_meta_data(sKey)
786
+ end
787
+
788
+ # Before doing a query, mapping fields
789
+ # Transform Object query field to Provider query Fields
790
+ def query_map(sCloudObj, hParams)
791
+ return nil if not sCloudObj or not [String, Symbol].include?(sCloudObj.class)
792
+ return {} if not hParams
793
+
794
+ sCloudObj = sCloudObj.to_sym if sCloudObj.class == String
795
+
796
+ hReturn = {}
797
+ hMap = Lorj::rhGet(@@meta_obj, sCloudObj, :query_mapping)
798
+ hParams.each { |key, value|
799
+ oKeyPath = KeyPath.new(key)
800
+ sKeyPath = oKeyPath.sFullPath
801
+ raise Lorj::PrcError.new(), "Forj query field '%s.%s' not defined by class '%s'.\n" % [sCloudObj, oKeyPath.sKey, self.class ] +
802
+ "#{ANSI.bold}ACTION REQUIRED#{ANSI.clear}:\n" +
803
+ "Missing data model 'def_attribute' or 'def_query_attribute' for '%s'??? Check the object '%s' data model." % [oKeyPath.sKey, sCloudObj] if not hMap.key?(oKeyPath.sFullPath)
804
+ oMapPath = KeyPath.new(hMap[oKeyPath.sFullPath])
805
+ hValueMapping = Lorj::rhGet(@@meta_obj, sCloudObj, :value_mapping, sKeyPath)
806
+ if hValueMapping
807
+ raise Lorj::PrcError.new(), "'%s.%s': No value mapping for '%s'" % [sCloudObj, oKeyPath.sKey, value] if Lorj::rhExist?(hValueMapping, value) != 1
808
+
809
+ Lorj::rhSet(hReturn, hValueMapping[value], oMapPath.aTree)
810
+ else
811
+ Lorj::rhSet(hReturn, value, oMapPath.aTree)
812
+ end
813
+ }
814
+ hReturn
815
+ end
816
+
817
+ # Obsolete. Used by the Process.
818
+ # Ask controller get_attr to get a data
819
+ # The result is the data of a defined data attribute.
820
+ # If the value is normally mapped (value mapped), the value is
821
+ # returned as a recognized data attribute value.
822
+ def get_attr(oObject, key)
823
+
824
+ raise Lorj::PrcError.new(), "'%s' is not a valid Object type. " % [oObject.class] if not oObject.is_a?(Hash) and Lorj::rhExist?(oObject, :object_type) != 1
825
+ sCloudObj = oObject[:object_type]
826
+ oKeyPath = KeyPath.new(key)
827
+ raise Lorj::PrcError.new(), "'%s' key is not declared as data of '%s' CloudObject. You may need to add obj_needs..." % [oKeyPath.sKey, sCloudObj] if Lorj::rhExist?(@@meta_obj, sCloudObj, :returns, oKeyPath.sFullPath) != 3
828
+ begin
829
+ oMapPath = KeyPath.new Lorj::rhGet(@@meta_obj, sCloudObj, :returns, oKeyPath.sFullPath)
830
+ hMap = oMapPath.sFullPath
831
+ value = @oProvider.get_attr(get_cObject(oObject), hMap)
832
+
833
+ hValueMapping = Lorj::rhGet(@@meta_obj, sCloudObj, :value_mapping, oKeyPath.sFullPath)
834
+
835
+ if hValueMapping
836
+ hValueMapping.each { | found_key, found_value |
837
+ if found_value == value
838
+ value = found_key
839
+ break
840
+ end
841
+ }
842
+ end
843
+ rescue => e
844
+ raise Lorj::PrcError.new(), "'%s.get_attr' fails to provide value of '%s'" % [oProvider.class, key]
845
+ end
846
+ end
847
+
848
+ # Register the object to the internal @ObjectData instance
849
+ def register(oObject, sObjectType = nil, sDataType = :object)
850
+ if oObject.is_a?(Lorj::Data)
851
+ oDataObject = oObject
852
+ else
853
+ raise Lorj::PrcError.new(), "Unable to register an object '%s' as Lorj::Data object if ObjectType is not given." % [ oObject.class ] if not sObjectType
854
+ oDataObject = Lorj::Data.new(sDataType)
855
+ oDataObject.set(oObject, sObjectType) { | sObjType, oControlerObject |
856
+ _return_map(sObjType, oControlerObject)
857
+ }
858
+ end
859
+ @ObjectData.add oDataObject
860
+ end
861
+
862
+ def DataObjects(sObjectType, *key)
863
+ @ObjectData[sObjectType, key]
864
+ end
865
+
866
+ # get an attribute/object/... from an object.
867
+ def get_data(oObj, *key)
868
+ if oObj.is_a?(Hash) and oObj.key?(:object_type)
869
+ oObjData = ObjectData.new
870
+ oObjData << oObj
871
+ else
872
+ oObjData = @ObjectData
873
+ end
874
+ oObjData[oObj, *key]
875
+ end
876
+
877
+ #~ def hParams(sCloudObj, hParams)
878
+ #~ aParams = _get_object_params(sCloudObj, ":ObjectData.hParams")
879
+ #~ end
880
+
881
+ def get_cObject(oObject)
882
+ return nil if Lorj::rhExist?(oObject, :object) != 1
883
+ Lorj::rhGet(oObject, :object)
884
+ end
885
+
886
+ # a Process can execute any kind of predefined controler task.
887
+ # Those function build hParams with Provider compliant data (mapped)
888
+ # Results are formatted as usual framework Data object and stored.
889
+ def connect(sObjectType)
890
+
891
+ hParams = _get_object_params(sObjectType, :create_e, :connect, true)
892
+ oControlerObject = @oProvider.connect(sObjectType, hParams)
893
+ oDataObject = Lorj::Data.new
894
+ oDataObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
895
+ begin
896
+ _return_map(sObjType, oObject)
897
+ rescue => e
898
+ raise Lorj::PrcError.new(), "connect %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
899
+ end
900
+ }
901
+ @ObjectData.add oDataObject
902
+ oDataObject
903
+ end
904
+
905
+ def create(sObjectType)
906
+ # The process ask the controller to create the object.
907
+ # hParams have to be fully readable by the controller.
908
+ hParams = _get_object_params(sObjectType, :create_e, :create, true)
909
+ oControlerObject = @oProvider.create(sObjectType, hParams)
910
+ oDataObject = Lorj::Data.new
911
+ oDataObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
912
+ begin
913
+ _return_map(sObjType, oObject)
914
+ rescue => e
915
+ raise Lorj::PrcError.new(), "create %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
916
+ end
917
+ }
918
+ @ObjectData.add oDataObject
919
+
920
+ oDataObject
921
+ end
922
+
923
+ # The controller must return true to inform about the real deletion
924
+ def delete(sObjectType)
925
+ hParams = _get_object_params(sObjectType, :delete_e, :delete, true)
926
+ raise Lorj::PrcError.new(), "delete Controller - %s: Object '%s' is not loaded." % [@oProvider.class, key] if not hParams.exist?(sObjectType)
927
+ bState = @oProvider.delete(sObjectType, hParams)
928
+ @ObjectData.delete(sObjectType) if bState
929
+ bState
930
+ end
931
+
932
+ def get(sObjectType, sUniqId)
933
+
934
+ hParams = _get_object_params(sObjectType, :get_e, :get, true)
935
+
936
+ oControlerObject = @oProvider.get(sObjectType, sUniqId, hParams)
937
+ oDataObject = Lorj::Data.new
938
+ oDataObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
939
+ begin
940
+ _return_map(sObjType, oObject)
941
+ rescue => e
942
+ raise Lorj::PrcError.new(), "get %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
943
+ end
944
+ }
945
+ @ObjectData.add oDataObject
946
+
947
+ oDataObject
948
+ end
949
+
950
+ def query(sObjectType, hQuery)
951
+
952
+ # Check if we can re-use a previous query
953
+ oList = @ObjectData[:query, sObjectType]
954
+ unless oList.nil?
955
+ if oList[:query] == hQuery
956
+ Lorj.debug(3, "Using Object '%s' query cache : %s" % [sObjectType, hQuery])
957
+ return oList
958
+ end
959
+ end
960
+
961
+
962
+ hParams = _get_object_params(sObjectType, :query_e, :query, true)
963
+ sProviderQuery = query_map(sObjectType, hQuery)
964
+
965
+ oControlerObject = @oProvider.query(sObjectType, sProviderQuery, hParams)
966
+
967
+ oDataObjects = Lorj::Data.new :list
968
+ oDataObjects.set(oControlerObject, sObjectType, hQuery) { | sObjType, key |
969
+ begin
970
+ _return_map(sObjType, key)
971
+ rescue => e
972
+ raise Lorj::PrcError.new(), "query %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
973
+ end
974
+ }
975
+
976
+ Lorj.debug(2, "Object %s - queried. Found %s object(s)." % [sObjectType, oDataObjects.length()])
977
+
978
+ @ObjectData.add oDataObjects
979
+ oDataObjects
980
+ end
981
+
982
+ def update(sObjectType)
983
+ # Need to detect data updated and update the Controler object with the controler
984
+
985
+ hParams = _get_object_params(sObjectType, :update_e, :update, true)
986
+
987
+ oObject = @ObjectData[sObjectType, :ObjectData]
988
+ oControlerObject = oObject[:object]
989
+
990
+ bUpdated = false
991
+ oObject[:attrs].each { |key, value |
992
+ oKeyPath = KeyPath.new(key)
993
+ oMapPath = KeyPath.new Lorj::rhGet(@@meta_obj, sObjectType, :returns, oKeyPath.sFullPath)
994
+ old_value = @oProvider.get_attr(oControlerObject, oMapPath.aTree)
995
+ if value != old_value
996
+ bUpdated = true
997
+ @oProvider.set_attr(oControlerObject, oMapPath.aTree, value)
998
+ Lorj.debug(2, "%s.%s - Updating: %s = %s (old : %s)" % [@oForjProcess.class, sObjectType, key, value, old_value])
999
+ end
1000
+ }
1001
+
1002
+ bDone = @oProvider.update(sObjectType, oObject, hParams) if bUpdated
1003
+
1004
+ raise Lorj::PrcError.new, "Controller function 'update' must return True or False. Class returned: '%s'" % bDone.class if not [TrueClass, FalseClass].include?(bDone.class)
1005
+
1006
+ Lorj.debug(1, "%s.%s - updated." % [@oForjProcess.class, sObjectType]) if bDone
1007
+ oObject.set(oControlerObject, sObjectType) { | sObjType, oObject |
1008
+ begin
1009
+ _return_map(sObjType, oObject)
1010
+ rescue => e
1011
+ raise Lorj::PrcError.new(), "update %s.%s : %s" % [@oForjProcess.class, sObjectType, e.message]
1012
+ end
1013
+ }
1014
+ bDone
1015
+ end
1016
+
1017
+
1018
+ private
1019
+
1020
+ # -------------------------------------------------------------------------
1021
+ # Functions available for Process to communicate with the controler Object
1022
+ # -------------------------------------------------------------------------
1023
+ def cloud_obj_requires(sCloudObj, res = {})
1024
+ aCaller = caller
1025
+ aCaller.pop
1026
+
1027
+ return res if @ObjectData.exist?(sCloudObj)
1028
+ #~ return res if Lorj::rhExist?(@CloudData, sCloudObj) == 1
1029
+
1030
+ Lorj::rhGet(@@meta_obj,sCloudObj, :params).each { |key, hParams|
1031
+ case hParams[:type]
1032
+ when :data
1033
+ if hParams.key?(:array)
1034
+ hParams[:array].each{ | aElem |
1035
+ aElem = aElem.clone
1036
+ aElem.pop # Do not go until last level, as used to loop next.
1037
+ Lorj::rhGet(hParams, aElem).each { | subkey, hSubParam |
1038
+ next if aElem.length == 0 and [:array, :type].include?(subkey)
1039
+ if hSubParams[:required] and @oForjConfig.get(subkey).nil?
1040
+ res[subkey] = hSubParams
1041
+ end
1042
+ }
1043
+ }
1044
+ else
1045
+ if hParams[:required] and @oForjConfig.get(key).nil?
1046
+ res[key] = hParams
1047
+ end
1048
+ end
1049
+ when :CloudObject
1050
+ #~ if hParams[:required] and Lorj::rhExist?(@CloudData, sCloudObj) != 1
1051
+ if hParams[:required] and not @ObjectData.exist?(sCloudObj)
1052
+ res[key] = hParams
1053
+ cloud_obj_requires(key, res)
1054
+ end
1055
+ end
1056
+ }
1057
+ res
1058
+ end
1059
+
1060
+ def get_object(sCloudObj)
1061
+ #~ return nil if Lorj::rhExist?(@CloudData, sCloudObj) != 1
1062
+ return nil if not @ObjectData.exist?(sCloudObj)
1063
+ @ObjectData[sCloudObj, :ObjectData]
1064
+ #~ Lorj::rhGet(@CloudData, sCloudObj)
1065
+ end
1066
+
1067
+ def objectExist?(sCloudObj)
1068
+ @ObjectData.exist?(sCloudObj)
1069
+ #~ (Lorj::rhExist?(@CloudData, sCloudObj) != 1)
1070
+ end
1071
+
1072
+ def get_forjKey(oCloudData, key)
1073
+ return nil if not @ObjectData.exist?(sCloudObj)
1074
+ @ObjectData[sCloudObj, :attrs, key]
1075
+ #~ return nil if Lorj::rhExist?(oCloudData, sCloudObj) != 1
1076
+ #~ Lorj::rhGet(oCloudData, sCloudObj, :attrs, key)
1077
+ end
1078
+ end
1079
+ end