lorj 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,567 @@
1
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # Module Lorj which contains several classes.
16
+ #
17
+ # Those classes describes :
18
+ # - processes (BaseProcess) : How to create/delete/edit/query object.
19
+ # - controler (BaseControler) : If a provider is defined, define how will do object creation/etc...
20
+ # - definition(BaseDefinition): Functions to declare objects, query/data mapping and setup
21
+ # this task to make it to work.
22
+ module Lorj
23
+ # This class is the Data object used by lorj object!
24
+ # This is a key component of lorj
25
+ #
26
+ # You find this object in different places.
27
+ #
28
+ # type:
29
+ # - object/data : The Data object contains any kind of data.
30
+ # This data contains 2 elements:
31
+ # - controler object : This is a ruby object managed by the controller.
32
+ # Only the controller has the knowledge to manage this kind of data.
33
+ # - attributes : This is the internal data mapping from the controller object.
34
+ # The controller helped to build this data thanks to the BaseController.get_attr / BaseController.set_attr
35
+ # Attributes are declared by the Data model in BaseDefinition. At least usually, each object has 2 attributes: :id and :name
36
+ #
37
+ # - list : The Data object contains a list of Lorj::Data
38
+ #
39
+ # If the object is of type :list, following functions are usable:
40
+ #
41
+ # - length : return numbers of Lorj::Data
42
+ # - each / each_index : loop on the list, key/value or key_index. yield can return 'remove' to remove the element from the list during loop.
43
+ #
44
+ # If the Data object is of type :data or :object or even :list, following functions are usable.
45
+ #
46
+ # - set/[]=/get/[]/exist? : Basic get/set/exist? feature.
47
+ # - type?/object_type? : Determine the type of this object. ie :data (stands for :object as well) or :list
48
+ # - to_a : Array of Data attributes
49
+ # - empty? nil? : Identify if the object is empty. Avoid to use nil?.
50
+ # - register/unregister : Used by Lorj::BaseDefinition internal @ObjectData.
51
+ # registered? : Determine if this object is stored in the global object cache.
52
+
53
+ class Lorj::Data
54
+
55
+ # Initialize Lorj::Data object
56
+ #
57
+ # * *Args* :
58
+ # - +oType+ : default is :object
59
+ # Support :data/:object for single object data
60
+ # :list for a list of object data
61
+ #
62
+ # * *Returns* :
63
+ # hash - internal data object.
64
+ #
65
+ # * *Raises* :
66
+ # No exceptions
67
+ #
68
+ def initialize(oType = :object)
69
+ oType = :data if not [:list, :object, :data].include?(oType)
70
+ @oType = oType
71
+ case oType
72
+ when :data, :object
73
+ @data = new_object
74
+ when :list
75
+ @data = new_object_list
76
+ end
77
+ end
78
+
79
+ # Return Lorj::Data object type
80
+ #
81
+ # * *Args* :
82
+ # Nothing
83
+ #
84
+ # * *Returns* :
85
+ # - +type+ : Symbol or nil
86
+ # nil if no object.
87
+ # :object for single object data
88
+ # :list for a list of object data
89
+ #
90
+ # * *Raises* :
91
+ # No exceptions
92
+ #
93
+ def type?()
94
+ @oType
95
+ end
96
+
97
+ # Return :object type of the Lorj::Data object.
98
+ #
99
+ # * *Args* :
100
+ # Nothing
101
+ #
102
+ # * *Returns* :
103
+ # - +type+ : Symbol or nil
104
+ # nil if no object.
105
+ # :object type
106
+ #
107
+ # * *Raises* :
108
+ # No exceptions
109
+ #
110
+ def object_type?()
111
+ @data[:object_type]
112
+ end
113
+
114
+ # Set a Lorj::Data object and return itself.
115
+ #
116
+ # There 3 usages:
117
+ # - Set from a Lorj::Data.
118
+ # ex: if data is already a Lorj::Data,
119
+ # copy = Lorj::Data.new()
120
+ # copy.set(data)
121
+ # - Set from an object, not Lorj::Data and not a list.
122
+ # ex:
123
+ # data = { :test => 'toto'}
124
+ # copy = Lorj::Data.new()
125
+ # copy.set(data, :object) { |oObject |
126
+ # oObject
127
+ # }
128
+ # - Set from a list of objects, not Lorj::Data and not a :object.
129
+ # ex:
130
+ # data = [{ :name => 'toto'}, {:name => 'test'}]
131
+ # copy = Lorj::Data.new()
132
+ # copy.set(data, :list, { :name => /^t/ }) { |oObject |
133
+ # oObject
134
+ # }
135
+ #
136
+ # * *Args* :
137
+ # - +data+ : Lorj::Data or any other data.
138
+ # - +ObjType: required only if data is not a Lorj::Data
139
+ # Use :object to store and extract attributes
140
+ # Use :list to extract elements, store them and extract attributes for each of them. data must support each(oObject) loop function
141
+ # - +Query+ : Optional. To store the query object used to get the list objects. It assumes ObjectType = :list
142
+ # - +yield+ : code to extract +data+ attributes from the object (:object or :list). Should return an hash containing attributes data.
143
+ #
144
+ # * *Returns* :
145
+ # - +self+ : Lorj::Data
146
+ #
147
+ # * *Raises* :
148
+ # No exceptions
149
+ #
150
+ def set(oObj, sObjType = nil, hQuery = {})
151
+ if oObj.is_a?(Lorj::Data)
152
+ oType = oObj.type?
153
+ case oType
154
+ when :data, :object
155
+ @data[:object_type] = ((sObjType.nil?)? (oObj.object_type?) : sObjType)
156
+ @data[:object] = oObj.get(:object)
157
+ @data[:attrs] = oObj.get(:attrs)
158
+ when :list
159
+ @data[:object_type] = ((sObjType.nil?)? (oObj.object_type?) : sObjType)
160
+ @data[:object] = oObj.get(:object)
161
+ @data[:list] = oObj.get(:list)
162
+ @data[:query] = oObj.get(:query)
163
+ end
164
+ return self
165
+ end
166
+
167
+ # while saving the object, a mapping work is done?
168
+ case @oType
169
+ when :data, :object
170
+ @data[:object_type] = sObjType
171
+ @data[:object] = oObj
172
+ @data[:attrs] = yield(sObjType, oObj)
173
+ when :list
174
+ @data[:object] = oObj
175
+ @data[:object_type] = sObjType
176
+ @data[:query] = hQuery
177
+ unless oObj.nil?
178
+ begin
179
+ oObj.each { | oObject |
180
+ next if oObject.nil?
181
+ begin
182
+ oDataObject = Lorj::Data.new(:object)
183
+
184
+ oDataObject.set(oObject, sObjType) { |sObjectType, oObject|
185
+ yield(sObjectType, oObject)
186
+ }
187
+ @data[:list] << oDataObject
188
+ rescue => e
189
+ raise Lorj::PrcError.new(), "'%s' Mapping attributes issue.\n%s" % [sObjType, e.message]
190
+ end
191
+ }
192
+ rescue => e
193
+ raise Lorj::PrcError.new(), "each function is not supported by '%s'.\n%s" % [oObj.class, e.message]
194
+ end
195
+ end
196
+ end
197
+ self
198
+ end
199
+
200
+ # Set the :object type
201
+ #
202
+ # * *Args* :
203
+ # - +ObjType: required only if data is not a Lorj::Data
204
+ #
205
+ # * *Returns* :
206
+ # - +self+ : Lorj::Data
207
+ #
208
+ # * *Raises* :
209
+ # No exceptions
210
+ #
211
+ def type=(sObjType)
212
+ return self if self.empty?
213
+ @data[:object_type] = sObjType
214
+ self
215
+ end
216
+
217
+ # Get value from Lorj::data
218
+ #
219
+ # * *Args* :
220
+ # - +keys+: See get function.
221
+ #
222
+ # * *Returns* :
223
+ # - +self+ : Lorj::Data
224
+ #
225
+ # * *Raises* :
226
+ # No exceptions
227
+ #
228
+ def [](*key)
229
+ get(*key)
230
+ end
231
+
232
+ # Set Lorj::data attribute value for an :object
233
+ #
234
+ # * *Args* :
235
+ # - +keys+ : attribute keys
236
+ # - +value+: Value to set
237
+ #
238
+ # * *Returns* :
239
+ # true
240
+ #
241
+ # * *Raises* :
242
+ # No exceptions
243
+ #
244
+ def []=(*key, value)
245
+ return false if @oType == :list
246
+ Lorj::rhSet(@data, value, :attrs, key)
247
+ true
248
+ end
249
+
250
+ # Get value from Lorj::data
251
+ # Depending on Lorj::Data type, you can get:
252
+ # - :object
253
+ # - get internal object data (:object)
254
+ # ex: object = data[:object]
255
+ # - get attribute data
256
+ # ex:
257
+ # data = { :name => 'toto'}
258
+ # copy = Lorj::Data.new()
259
+ # copy.set(data, :object) { |oObject |
260
+ # {:real_name => oObject[:name]}
261
+ # }
262
+ #
263
+ # puts copy[:name] # => nil
264
+ # puts copy[:real_name] # => 'toto'
265
+ # puts copy[:object] # => { :name => 'toto'}
266
+ # puts copy[:attrs] # => { :real_name => 'toto'}
267
+ # - :list
268
+ # - get internal object data (:object)
269
+ # ex: object = data[:object]
270
+ # - get stored query object data (:query)
271
+ # ex: object = data[:query]
272
+ # - get one element attribute or object data
273
+ # ex:
274
+ # data = [{ :name => 'toto'}, {:name => 'test'}]
275
+ # copy = Lorj::Data.new()
276
+ # copy.set(data, :list, { :name => /^t/ }) { |oObject |
277
+ # {:real_name => oObject[:name]}
278
+ # }
279
+ #
280
+ # puts copy[0] # => { :real_name => 'toto'}
281
+ # puts copy[0][:object] # => { :name => 'toto'}
282
+ # puts copy[0][:attrs] # => { :real_name => 'toto'}
283
+ # puts copy[1] # => { :real_name => 'test'}
284
+ # puts copy[1, :real_name] # => 'test'
285
+ # puts copy[1, :test] # => nil
286
+ #
287
+ # * *Args* :
288
+ # - +keys+: See get function.
289
+ #
290
+ # * *Returns* :
291
+ # - +self+ : Lorj::Data
292
+ #
293
+ # * *Raises* :
294
+ # No exceptions
295
+ #
296
+ def get(*key)
297
+ return @data if key.length == 0
298
+ case @oType
299
+ when :data, :object # Return only attrs or the real object.
300
+ return @data[key[0]] if key[0] == :object
301
+ return Lorj::rhGet(@data, key) if key[0] == :attrs
302
+ Lorj::rhGet(@data, :attrs, key)
303
+ when :list
304
+ return @data[key[0]] if [:object, :query].include?(key[0])
305
+ return @data[:list][key[0]] if key.length == 1
306
+ @data[:list][key[0]][key[1..-1]] # can Return only attrs or the real object.
307
+ end
308
+ end
309
+
310
+ # Get the list of elements in an array from Lorj::Data :list type.
311
+ #
312
+ # * *Args* :
313
+ # No parameters
314
+ #
315
+ # * *Returns* :
316
+ # - +Elements+ : Array of elements
317
+ #
318
+ # * *Raises* :
319
+ # No exceptions
320
+ #
321
+ def to_a()
322
+ result = []
323
+ self.each { |elem|
324
+ result<< elem[:attrs]
325
+ }
326
+ result
327
+ end
328
+
329
+ # return true if a data object exist or if an extracted attribute exist.
330
+ #
331
+ # * *Args* :
332
+ # - +keys+ : Keys to verify.
333
+ #
334
+ # * *Returns* :
335
+ # - +exist?+ : true or false.
336
+ #
337
+ # * *Raises* :
338
+ # No exceptions
339
+ #
340
+ # Examples:
341
+ # data = Lorj::Data.new()
342
+ #
343
+ # puts data.exist?(:object) # => false
344
+ #
345
+ # data.set({ :name => 'toto'}, :object) { |oObject |
346
+ # {:real_name => oObject[:name]}
347
+ # }
348
+ # list = Lorj::Data.new()
349
+ #
350
+ # puts data.exist?(:object) # => false
351
+ #
352
+ # list.set([{ :name => 'toto'}, {:name => 'test'}], :list) { |oObject |
353
+ # {:real_name => oObject[:name]}
354
+ # }
355
+ #
356
+ # puts data.exist?(:object) # => true
357
+ # puts data.exist?(:name) # => true
358
+ # puts data.exist?(:test) # => false
359
+ # puts data.exist?(:attrs, :name) # => true
360
+ # puts list.exist?(0) # => true
361
+ # puts list.exist?(0, :object) # => true
362
+ # puts list.exist?(2) # => false
363
+ # puts list.exist?(2, :object) # => false
364
+ # puts list.exist?(0, :name) # => true
365
+ # puts list.exist?(0, :test) # => false
366
+ def exist?(*key)
367
+ case @oType
368
+ when :data, :object
369
+ return true if key[0] == :object and @data.key?(key[0])
370
+ return true if key[0] == :attrs and Lorj::rhExist?(@data, key)
371
+ (Lorj::rhExist?(@data, :attrs, key) == key.length+1)
372
+ when :list
373
+ return true if key[0] == :object and @data.key?(key[0])
374
+ (Lorj::rhExist?(@data[:list][key[0]], :attrs, key[1..-1]) == key.length)
375
+ end
376
+ end
377
+
378
+ # return true if the Lorj::Data object is nil.
379
+ #
380
+ # * *Args* :
381
+ # No parameters
382
+ #
383
+ # * *Returns* :
384
+ # - true/false
385
+ #
386
+ # * *Raises* :
387
+ # No exceptions
388
+ #
389
+ def empty?()
390
+ @data[:object].nil?
391
+ end
392
+
393
+ # Redefine nil? Warning! Can be confused. Cannot see if your object is simply nil or if current object is simply empty.
394
+ # Use empty? instead.
395
+ # A warning will be raised soon to ask developer to update it.
396
+ #
397
+ # * *Args* :
398
+ # No parameters
399
+ #
400
+ # * *Returns* :
401
+ # - true/false
402
+ #
403
+ # * *Raises* :
404
+ # No exceptions
405
+ #
406
+ def nil?()
407
+ # Obsolete Use empty? instead.
408
+ @data[:object].nil?
409
+ end
410
+
411
+ # return 0, 1 or N if the Lorj::Data object is nil.
412
+ # 0 if no objects stored
413
+ # 1 if an object exist even if type :object or :list
414
+ # >1 if a list is stored. It will give the number of elements in the list.
415
+ #
416
+ # * *Args* :
417
+ # No parameters
418
+ #
419
+ # * *Returns* :
420
+ # - >=0 : Number of elements
421
+ #
422
+ # * *Raises* :
423
+ # No exceptions
424
+ #
425
+ def length()
426
+ case @oType
427
+ when :data
428
+ return 0 if self.empty?
429
+ 1
430
+ when :list
431
+ @data[:list].length
432
+ end
433
+ end
434
+
435
+ # yield loop on a list
436
+ #
437
+ # * *Args* :
438
+ # - +yield+ : sAction = yield (elem), where action can :removed to remove the element from the list.
439
+ #
440
+ # * *Returns* :
441
+ # no values
442
+ #
443
+ # * *Raises* :
444
+ # No exceptions
445
+ #
446
+ def each(sData = :list)
447
+ to_remove = []
448
+ return nil if @oType != :list or not [:object, :list].include?(sData)
449
+
450
+ @data[:list].each { |elem|
451
+ sAction = yield (elem)
452
+ case sAction
453
+ when :remove
454
+ to_remove << elem
455
+ end
456
+ }
457
+ if to_remove.length > 0
458
+ to_remove.each { | elem |
459
+ @data[:list].delete(elem)
460
+ }
461
+ end
462
+ end
463
+
464
+ # yield loop on a list
465
+ #
466
+ # * *Args* :
467
+ # - +yield+ : sAction = yield (index), where action can :removed to remove the element from the list.
468
+ #
469
+ # * *Returns* :
470
+ # no values
471
+ #
472
+ # * *Raises* :
473
+ # No exceptions
474
+ #
475
+ def each_index(sData = :list)
476
+ to_remove = []
477
+ return nil if @oType != :list or not [:object, :list].include?(sData)
478
+
479
+ @data[:list].each_index { |iIndex|
480
+ sAction = yield (iIndex)
481
+ case sAction
482
+ when :remove
483
+ to_remove << @data[:list][iIndex]
484
+ end
485
+ }
486
+ if to_remove.length > 0
487
+ to_remove.each { | elem |
488
+ @data[:list].delete(elem)
489
+ }
490
+ end
491
+ end
492
+
493
+ # A Lorj::Data can be cached by Lorj::ObjectData.
494
+ # When adding Lorj::Data to Lorj::ObjectData, Lorj::Data object will be registered.
495
+ # This function will determine if this object is registered or not.
496
+ #
497
+ # * *Args* :
498
+ # none
499
+ #
500
+ # * *Returns* :
501
+ # - registered : true or false if registered or not
502
+ #
503
+ # * *Raises* :
504
+ # No exceptions
505
+ #
506
+ def registered?()
507
+ @bRegister
508
+ end
509
+
510
+ # A Lorj::Data can be cached by Lorj::ObjectData.
511
+ # When adding Lorj::Data to Lorj::ObjectData, Lorj::Data object will be registered.
512
+ # Lorj::ObjectData will call this function to marked it as registered.
513
+ #
514
+ # * *Args* :
515
+ # none
516
+ #
517
+ # * *Returns* :
518
+ # - self
519
+ #
520
+ # * *Raises* :
521
+ # No exceptions
522
+ #
523
+ def register()
524
+ @bRegister = true
525
+ self
526
+ end
527
+
528
+ # A Lorj::Data can be cached by Lorj::ObjectData.
529
+ # When adding Lorj::Data to Lorj::ObjectData, Lorj::Data object will be registered.
530
+ # Lorj::ObjectData will call this function to marked it as unregistered.
531
+ #
532
+ # * *Args* :
533
+ # none
534
+ #
535
+ # * *Returns* :
536
+ # - self
537
+ #
538
+ # * *Raises* :
539
+ # No exceptions
540
+ #
541
+ def unregister()
542
+ @bRegister = false
543
+ self
544
+ end
545
+ private
546
+
547
+ # Define minimal @data structure for a :list object type.
548
+ def new_object_list
549
+ {
550
+ :object => nil,
551
+ :object_type => nil,
552
+ :list => [],
553
+ :query => nil
554
+ }
555
+ end
556
+
557
+ # Define minimal @data structure for a :object object type.
558
+ def new_object
559
+ oCoreObject = {
560
+ :object_type => nil,
561
+ :attrs => {},
562
+ :object => nil,
563
+ }
564
+ end
565
+
566
+ end
567
+ end
@@ -0,0 +1,115 @@
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
+
27
+ # Class to handle key or keypath on needs
28
+ # The application configuration can configure a key tree, instead of a key.
29
+ # KeyPath is used to commonly handle key or key tree.
30
+ # Thus, a Keypath can be converted in different format:
31
+ #
32
+ # Ex:
33
+ # oKey = KeyPath(:test)
34
+ # puts oKey.to_s # => 'test'
35
+ # puts oKey.sKey # => :test
36
+ # puts oKey.sKey[0] # => :test
37
+ # puts oKey.sKey[1] # => nil
38
+ # puts oKey.sFullPath # => ':test'
39
+ # puts oKey.aTree # => [:test]
40
+ #
41
+ # oKey = KeyPath([:test,:test2,:test3])
42
+ # puts oKey.to_s # => 'test/test2/test3'
43
+ # puts oKey.sKey # => :test3
44
+ # puts oKey.sKey[0] # => :test
45
+ # puts oKey.sKey[1] # => :test2
46
+ # puts oKey.sFullPath # => ':test/:test2/:ẗest3'
47
+ # puts oKey.aTree # => [:test,:test2,:test3]
48
+ #
49
+ class KeyPath
50
+
51
+ def initialize(sKeyPath = nil)
52
+
53
+ @keypath = []
54
+ self.set sKeyPath
55
+ end
56
+
57
+ def key=(sKeyPath)
58
+ self.set(sKeyPath)
59
+ end
60
+
61
+ def set(sKeyPath)
62
+
63
+ if sKeyPath.is_a?(Symbol)
64
+ @keypath = [ sKeyPath]
65
+ elsif sKeyPath.is_a?(Array)
66
+ @keypath = sKeyPath
67
+ elsif sKeyPath.is_a?(String)
68
+ if /[^\\\/]?\/[^\/]/ =~ sKeyPath or /:[^:\/]/ =~ sKeyPath
69
+ # keypath to interpret
70
+ aResult = sKeyPath.split('/')
71
+ aResult.each_index { | iIndex |
72
+ next if not aResult[iIndex].is_a?(String)
73
+ aResult[iIndex] = aResult[iIndex][1..-1].to_sym if aResult[iIndex][0] == ":"
74
+ }
75
+ @keypath = aResult
76
+ else
77
+ @keypath = [sKeyPath]
78
+ end
79
+ end
80
+ end
81
+
82
+ def aTree()
83
+ @keypath
84
+ end
85
+
86
+ def sFullPath()
87
+ return nil if @keypath.length == 0
88
+ aKeyAccess = @keypath.clone
89
+ aKeyAccess.each_index { |iIndex|
90
+ next if not aKeyAccess[iIndex].is_a?(Symbol)
91
+ aKeyAccess[iIndex] = ":" + aKeyAccess[iIndex].to_s
92
+ }
93
+ aKeyAccess.join('/')
94
+ end
95
+
96
+ def to_s
97
+ return nil if @keypath.length == 0
98
+ aKeyAccess = @keypath.clone
99
+ aKeyAccess.each_index { |iIndex|
100
+ next if not aKeyAccess[iIndex].is_a?(Symbol)
101
+ aKeyAccess[iIndex] = aKeyAccess[iIndex].to_s
102
+ }
103
+ aKeyAccess.join('/')
104
+ end
105
+
106
+ def sKey(iIndex = -1)
107
+ return nil if @keypath.length == 0
108
+ @keypath[iIndex] if self.length >= 1
109
+ end
110
+
111
+ def length()
112
+ @keypath.length
113
+ end
114
+ end
115
+ end