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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.gitreview +4 -0
- data/Gemfile +25 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +14 -0
- data/README.md +652 -0
- data/Rakefile +24 -0
- data/bin/cloud_test.rb +81 -0
- data/example/students_1/process/Students.rb +20 -0
- data/example/students_1/students.rb +16 -0
- data/example/students_2/process/Students.rb +27 -0
- data/example/students_2/students.rb +36 -0
- data/example/students_3/controller/yaml_students.rb +94 -0
- data/example/students_3/controller/yaml_students_controller.rb +123 -0
- data/example/students_3/process/students.rb +118 -0
- data/example/students_3/students.rb +93 -0
- data/example/students_4/controller/yaml_students.rb +82 -0
- data/example/students_4/controller/yaml_students_controller.rb +141 -0
- data/example/students_4/process/students.rb +112 -0
- data/example/students_4/students.rb +103 -0
- data/example/yaml_students/students.rb +78 -0
- data/example/yaml_students/yaml_students.rb +115 -0
- data/lib/concept.md +111 -0
- data/lib/core/core.rb +723 -0
- data/lib/core/definition.rb +505 -0
- data/lib/core/definition_internal.rb +338 -0
- data/lib/core/lorj-basecontroller.rb +90 -0
- data/lib/core/lorj-basedefinition.rb +1079 -0
- data/lib/core/lorj-baseprocess.rb +231 -0
- data/lib/core/lorj-data.rb +567 -0
- data/lib/core/lorj-keypath.rb +115 -0
- data/lib/core_process/CloudProcess.rb +334 -0
- data/lib/core_process/global_process.rb +406 -0
- data/lib/core_process/network_process.rb +603 -0
- data/lib/img/.directory +4 -0
- data/lib/img/account_data_access.png +0 -0
- data/lib/img/config_data_access.png +0 -0
- data/lib/img/forj-lib-concept.png +0 -0
- data/lib/lorj/version.rb +3 -0
- data/lib/lorj.rb +51 -0
- data/lib/prc-account.rb +339 -0
- data/lib/prc-config.rb +1023 -0
- data/lib/prc-logging.rb +183 -0
- data/lib/prc.rb +108 -0
- data/lib/providers/hpcloud/Hpcloud.rb +419 -0
- data/lib/providers/hpcloud/compute.rb +108 -0
- data/lib/providers/hpcloud/network.rb +117 -0
- data/lib/providers/hpcloud/security_groups.rb +67 -0
- data/lib/providers/mock/Mock.rb +141 -0
- data/lib/providers/openstack/Openstack.rb +47 -0
- data/lib/providers/templates/compute.rb +42 -0
- data/lib/providers/templates/core.rb +61 -0
- data/lib/providers/templates/network.rb +33 -0
- data/lorj-spec/defaults.yaml +26 -0
- data/lorj.gemspec +39 -0
- data/spec/forj-account_spec.rb +75 -0
- data/spec/forj-config_spec.rb +196 -0
- 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
|