persistence 0.0.1.alpha → 0.0.1

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 (138) hide show
  1. data/CHANGELOG.md +4 -0
  2. data/README.md +260 -17
  3. data/lib/namespaces.rb +55 -0
  4. data/lib/persistence.rb +38 -3
  5. data/lib/persistence/adapter/abstract.rb +22 -0
  6. data/lib/persistence/adapter/abstract/enable_disable.rb +107 -0
  7. data/lib/persistence/adapter/abstract/primary_key/id_property_string.rb +33 -0
  8. data/lib/persistence/adapter/abstract/primary_key/simple.rb +29 -0
  9. data/lib/persistence/adapter/mock.rb +9 -0
  10. data/lib/persistence/adapter/mock/adapter_interface.rb +102 -0
  11. data/lib/persistence/adapter/mock/bucket.rb +9 -0
  12. data/lib/persistence/adapter/mock/bucket/bucket_interface.rb +260 -0
  13. data/lib/persistence/adapter/mock/bucket/index.rb +9 -0
  14. data/lib/persistence/adapter/mock/bucket/index/index_interface.rb +155 -0
  15. data/lib/persistence/adapter/mock/cursor.rb +9 -0
  16. data/lib/persistence/adapter/mock/cursor/cursor_interface.rb +238 -0
  17. data/lib/persistence/cursor.rb +11 -0
  18. data/lib/persistence/cursor/atomic.rb +110 -0
  19. data/lib/persistence/cursor/cursor_interface.rb +337 -0
  20. data/lib/persistence/exception/block_required.rb +7 -0
  21. data/lib/persistence/exception/conflicting_index_already_declared.rb +7 -0
  22. data/lib/persistence/exception/duplicate_violates_unique_index.rb +7 -0
  23. data/lib/persistence/exception/explicit_index_required.rb +7 -0
  24. data/lib/persistence/exception/indexing_block_failed_to_generate_keys.rb +7 -0
  25. data/lib/persistence/exception/indexing_object_requires_keys.rb +7 -0
  26. data/lib/persistence/exception/key_value_required.rb +7 -0
  27. data/lib/persistence/exception/no_port_enabled.rb +7 -0
  28. data/lib/persistence/object.rb +21 -0
  29. data/lib/persistence/object/autodetermine.rb +74 -0
  30. data/lib/persistence/object/class_instance.rb +1884 -0
  31. data/lib/persistence/object/complex.rb +17 -0
  32. data/lib/persistence/object/complex/array.rb +14 -0
  33. data/lib/persistence/object/complex/array/class_instance.rb +37 -0
  34. data/lib/persistence/object/complex/array/object_instance.rb +54 -0
  35. data/lib/persistence/object/complex/attributes.rb +1808 -0
  36. data/lib/persistence/object/complex/attributes/attributes_array.rb +32 -0
  37. data/lib/persistence/object/complex/attributes/attributes_hash.rb +187 -0
  38. data/lib/persistence/object/complex/attributes/default_atomic_non_atomic.rb +102 -0
  39. data/lib/persistence/object/complex/attributes/hash_to_port.rb +40 -0
  40. data/lib/persistence/object/complex/class_and_object_instance.rb +132 -0
  41. data/lib/persistence/object/complex/class_instance.rb +267 -0
  42. data/lib/persistence/object/complex/complex_object.rb +111 -0
  43. data/lib/persistence/object/complex/hash.rb +14 -0
  44. data/lib/persistence/object/complex/hash/class_instance.rb +40 -0
  45. data/lib/persistence/object/complex/hash/object_instance.rb +63 -0
  46. data/lib/persistence/object/complex/index/attribute_index.rb +10 -0
  47. data/lib/persistence/object/complex/index/attribute_index/attribute_index_interface.rb +43 -0
  48. data/lib/persistence/object/complex/object_instance.rb +469 -0
  49. data/lib/persistence/object/flat.rb +17 -0
  50. data/lib/persistence/object/flat/class_instance.rb +34 -0
  51. data/lib/persistence/object/flat/file.rb +14 -0
  52. data/lib/persistence/object/flat/file/class_instance.rb +122 -0
  53. data/lib/persistence/object/flat/file/contents.rb +7 -0
  54. data/lib/persistence/object/flat/file/file_persistence.rb +147 -0
  55. data/lib/persistence/object/flat/file/object_instance.rb +116 -0
  56. data/lib/persistence/object/flat/file/path.rb +9 -0
  57. data/lib/persistence/object/flat/object_instance.rb +24 -0
  58. data/lib/persistence/object/index.rb +479 -0
  59. data/lib/persistence/object/index/block_index.rb +10 -0
  60. data/lib/persistence/object/index/block_index/block_index_interface.rb +110 -0
  61. data/lib/persistence/object/index/explicit_index.rb +10 -0
  62. data/lib/persistence/object/index/explicit_index/explicit_index_interface.rb +57 -0
  63. data/lib/persistence/object/index_hash.rb +40 -0
  64. data/lib/persistence/object/object_instance.rb +322 -0
  65. data/lib/persistence/object/parse_persistence_args.rb +145 -0
  66. data/lib/persistence/port.rb +9 -0
  67. data/lib/persistence/port/bucket.rb +9 -0
  68. data/lib/persistence/port/bucket/bucket_index.rb +9 -0
  69. data/lib/persistence/port/bucket/bucket_interface.rb +685 -0
  70. data/lib/persistence/port/controller.rb +263 -0
  71. data/lib/persistence/port/port_interface.rb +417 -0
  72. data/lib/requires.rb +146 -0
  73. data/spec/Integration_spec.rb +53 -0
  74. data/spec/Persistence_spec.rb +175 -0
  75. data/spec/example_objects.rb +6 -0
  76. data/spec/example_objects/complex_object.rb +7 -0
  77. data/spec/example_objects/complex_object/array_object.rb +7 -0
  78. data/spec/example_objects/complex_object/hash_object.rb +7 -0
  79. data/spec/example_objects/flat_object.rb +7 -0
  80. data/spec/example_objects/flat_object/file_object.rb +7 -0
  81. data/spec/persistence/adapter/enable_disable_spec.rb +29 -0
  82. data/spec/persistence/adapter/mock/cursor_spec.rb +64 -0
  83. data/spec/persistence/adapter/mock_helpers.rb +27 -0
  84. data/spec/persistence/adapter/mock_helpers/bucket.rb +10 -0
  85. data/spec/persistence/adapter/mock_helpers/integration/dictionary_hash.rb +4 -0
  86. data/spec/persistence/adapter/mock_helpers/integration/note.rb +18 -0
  87. data/spec/persistence/adapter/mock_helpers/integration/notes_array.rb +4 -0
  88. data/spec/persistence/adapter/mock_helpers/integration/user.rb +44 -0
  89. data/spec/persistence/adapter/mock_helpers/integration/user/address.rb +18 -0
  90. data/spec/persistence/adapter/mock_helpers/integration/user/dictionary_entry.rb +12 -0
  91. data/spec/persistence/adapter/mock_helpers/integration/user/sub_account.rb +15 -0
  92. data/spec/persistence/adapter/mock_helpers/object.rb +87 -0
  93. data/spec/persistence/adapter/mock_helpers/port.rb +21 -0
  94. data/spec/persistence/adapter/mock_spec.rb +211 -0
  95. data/spec/persistence/adapter/primary_key/id_property_string_spec.rb +27 -0
  96. data/spec/persistence/adapter/primary_key/simple_spec.rb +19 -0
  97. data/spec/persistence/adapter/spec_abstract/adapter_spec.rb +223 -0
  98. data/spec/persistence/adapter/spec_abstract/cursor_spec.rb +116 -0
  99. data/spec/persistence/cursor/atomic_spec.rb +86 -0
  100. data/spec/persistence/cursor/object_and_class_instance_spec.rb +73 -0
  101. data/spec/persistence/cursor_spec.rb +128 -0
  102. data/spec/persistence/object/complex/attributes/persistence_hash/array_instance_spec.rb +51 -0
  103. data/spec/persistence/object/complex/attributes/persistence_hash/hash_instance_spec.rb +56 -0
  104. data/spec/persistence/object/complex/attributes_spec.rb +1717 -0
  105. data/spec/persistence/object/complex/complex_spec.rb +922 -0
  106. data/spec/persistence/object/complex/index/attribute_index_spec.rb +76 -0
  107. data/spec/persistence/object/flat/bignum_spec.rb +33 -0
  108. data/spec/persistence/object/flat/class_instance_spec.rb +30 -0
  109. data/spec/persistence/object/flat/class_spec.rb +38 -0
  110. data/spec/persistence/object/flat/complex_spec.rb +36 -0
  111. data/spec/persistence/object/flat/false_class_spec.rb +34 -0
  112. data/spec/persistence/object/flat/file/class_instance_spec.rb +54 -0
  113. data/spec/persistence/object/flat/file/object_instance_spec.rb +143 -0
  114. data/spec/persistence/object/flat/file_spec.rb +64 -0
  115. data/spec/persistence/object/flat/fixnum_spec.rb +32 -0
  116. data/spec/persistence/object/flat/float_spec.rb +32 -0
  117. data/spec/persistence/object/flat/indexing_spec.rb +38 -0
  118. data/spec/persistence/object/flat/rational_spec.rb +33 -0
  119. data/spec/persistence/object/flat/regexp_spec.rb +32 -0
  120. data/spec/persistence/object/flat/string_spec.rb +34 -0
  121. data/spec/persistence/object/flat/symbol_spec.rb +32 -0
  122. data/spec/persistence/object/flat/true_class_spec.rb +32 -0
  123. data/spec/persistence/object/indexes/block_index_spec.rb +119 -0
  124. data/spec/persistence/object/indexes/explicit_index_spec.rb +112 -0
  125. data/spec/persistence/object/parse_persistence_args_spec.rb +65 -0
  126. data/spec/persistence/object_spec.rb +310 -0
  127. data/spec/persistence/port/bucket/bucket_interface_spec.rb +146 -0
  128. data/spec/persistence/port/bucket/index/bucket_index_spec.rb +67 -0
  129. data/spec/persistence/port/bucket_spec.rb +20 -0
  130. data/spec/persistence/port/controller_spec.rb +60 -0
  131. data/spec/persistence/port/port_interface_spec.rb +105 -0
  132. metadata +178 -21
  133. data/.gitignore +0 -17
  134. data/Gemfile +0 -4
  135. data/LICENSE +0 -22
  136. data/Rakefile +0 -2
  137. data/lib/persistence/version.rb +0 -3
  138. data/persistence.gemspec +0 -17
@@ -0,0 +1,9 @@
1
+
2
+ ###
3
+ # Subclass of {::String} used for persisting file paths and automatically re-creating File instances from them.
4
+ #
5
+ class ::Persistence::Object::Flat::File::Path < ::String
6
+
7
+ attr_accessor :mode
8
+
9
+ end
@@ -0,0 +1,24 @@
1
+
2
+ ###
3
+ # Instance methods for flat objects enabled with persistence capabilities.
4
+ #
5
+ module ::Persistence::Object::Flat::ObjectInstance
6
+
7
+ ##############################
8
+ # persistence_hash_to_port #
9
+ ##############################
10
+
11
+ ###
12
+ # @private
13
+ #
14
+ # Generate hash representing object.
15
+ #
16
+ # @return [Hash] Hash representing information to reproduce object instance.
17
+ #
18
+ def persistence_hash_to_port
19
+
20
+ return { persistence_bucket.primary_key_for_attribute_name( self, self.class.to_s ) => self }
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,479 @@
1
+
2
+ ###
3
+ # Common module to all index instances that serves as base index type.
4
+ #
5
+ module ::Persistence::Object::Index
6
+
7
+ include ::CascadingConfiguration::Setting
8
+
9
+ include ::Enumerable
10
+
11
+ ################
12
+ # initialize #
13
+ ################
14
+
15
+ ###
16
+ #
17
+ # @param index_name Name of index.
18
+ #
19
+ # @param parent_bucket Bucket index is on.
20
+ #
21
+ # @param permits_duplicates Whether index permits duplicate entries.
22
+ #
23
+ # @param sorting_proc_or_sort_names Proc to use for sorting or name of sort method.
24
+ #
25
+ # @param duplicates_sorting_proc_or_sort_names Proc to use for sorting duplicates or name of sort method.
26
+ #
27
+ # @param ancestor_index_instance Instance to use as ancestor for configuration values.
28
+ #
29
+ def initialize( index_name,
30
+ parent_bucket,
31
+ permits_duplicates = nil,
32
+ sorting_proc_or_sort_names = nil,
33
+ duplicates_sorting_proc_or_sort_names = nil,
34
+ ancestor_index_instance = nil )
35
+
36
+ if index_name
37
+ self.name = index_name
38
+ end
39
+
40
+ if ancestor_index_instance
41
+ encapsulation = ::CascadingConfiguration::Core::Encapsulation.encapsulation( :default )
42
+ encapsulation.register_child_for_parent( self, ancestor_index_instance )
43
+ end
44
+
45
+ unless permits_duplicates.nil?
46
+ self.permits_duplicates = permits_duplicates
47
+ end
48
+
49
+ if sorting_proc_or_sort_names or duplicates_sorting_proc_or_sort_names
50
+ init_sorting_procs( sorting_proc_or_sort_names, duplicates_sorting_proc_or_sort_names )
51
+ end
52
+
53
+ initialize_for_bucket( parent_bucket )
54
+
55
+ end
56
+
57
+ ##########
58
+ # name #
59
+ ##########
60
+
61
+ ###
62
+ # Index name
63
+ #
64
+ # @return [Symbol,String] Index name.
65
+ #
66
+ attr_setting :name
67
+
68
+ ########################
69
+ # permits_duplicates #
70
+ ########################
71
+
72
+ ###
73
+ # Query whether index permits duplicates.
74
+ #
75
+ # @return [true,false] Whether index permits duplicates.
76
+ #
77
+ attr_setting :permits_duplicates?
78
+
79
+ self.permits_duplicates = false
80
+
81
+ ###################
82
+ # parent_bucket #
83
+ ###################
84
+
85
+ ###
86
+ # Get reference to bucket index indexes.
87
+ #
88
+ # @return [Persistence::Port::Bucket] Bucket index is on.
89
+ #
90
+ attr_reader :parent_bucket
91
+
92
+ ###########################
93
+ # initialize_for_bucket #
94
+ ###########################
95
+
96
+ ###
97
+ # @private
98
+ #
99
+ # Initialize for parent bucket.
100
+ #
101
+ # @param parent_bucket Reference to bucket index indexes.
102
+ #
103
+ def initialize_for_bucket( parent_bucket )
104
+
105
+ @parent_bucket = parent_bucket
106
+
107
+ # object indexes are held and run by the classes/modules that define them
108
+ # synchronize the index instance with the parent bucket's adapter instance
109
+
110
+ if adapter_bucket = parent_bucket.instance_variable_get( :@adapter_bucket )
111
+
112
+ index_name = name
113
+
114
+ if adapter_bucket.has_index?( index_name )
115
+
116
+ @adapter_index = adapter_bucket.index( index_name )
117
+
118
+ # if index has aleady been declared and permits_duplicates does not match, raise error
119
+ # double ! ensures equality for false == nil
120
+ if ! permits_duplicates? != ! @adapter_index.permits_duplicates?
121
+ raise ::Persistence::Exception::ConflictingIndexAlreadyDeclared,
122
+ 'Index ' + index_name.to_s + ' has already been declared, ' +
123
+ 'and new duplicates declaration does not match existing declaration.'
124
+ end
125
+
126
+ else
127
+
128
+ # get adapter index instance in adapter bucket
129
+ @adapter_index = parent_bucket.adapter_bucket.create_index( index_name, permits_duplicates? )
130
+
131
+ end
132
+
133
+ else
134
+
135
+ parent_bucket.pend_index( self )
136
+
137
+ end
138
+
139
+ end
140
+
141
+ #############
142
+ # disable #
143
+ #############
144
+
145
+ ###
146
+ # @private
147
+ #
148
+ # Disable bucket. Used internally by port when port is disabled.
149
+ #
150
+ def disable
151
+
152
+ @adapter_index = nil
153
+
154
+ end
155
+
156
+ ########################
157
+ # init_sorting_procs #
158
+ ########################
159
+
160
+ ###
161
+ # @private
162
+ #
163
+ # Initializes sorting procs from procs or sorting method names.
164
+ #
165
+ # @param sorting_proc_or_sort_name Proc to use for sorting or name of sort method.
166
+ #
167
+ # @param duplicates_sorting_proc_or_sort_name Proc to use for sorting duplicates or name of sort method.
168
+ #
169
+ def init_sorting_procs( sorting_proc_or_sort_name, duplicates_sorting_proc_or_sort_name )
170
+
171
+ if sorting_proc_or_sort_name
172
+
173
+ if sorting_proc_or_sort_name.is_a?( ::Proc )
174
+
175
+ @sorting_procs = sorting_proc_or_sort_name
176
+
177
+ else
178
+
179
+ @sorting_procs = sorting_proc_for_sort_name( sorting_proc_or_sort_name )
180
+
181
+ end
182
+
183
+ end
184
+
185
+ if duplicates_sorting_proc_or_sort_name
186
+
187
+ if duplicates_sorting_proc_or_sort_name.is_a?( ::Proc )
188
+
189
+ @duplicates_sorting_procs = duplicates_sorting_proc_or_sort_name
190
+
191
+ else
192
+
193
+ @duplicates_sorting_procs = sorting_proc_for_sort_name( sorting_proc_or_sort_name )
194
+
195
+ end
196
+
197
+ end
198
+
199
+ end
200
+
201
+ ################################
202
+ # sorting_proc_for_sort_name #
203
+ ################################
204
+
205
+ ###
206
+ # @private
207
+ #
208
+ # Get sorting proc associated with sorting method name. PENDING.
209
+ #
210
+ # @param sort_name Name of sorting method.
211
+ #
212
+ # @return [Proc] Sorting proc.
213
+ #
214
+ def sorting_proc_for_sort_name( sort_name )
215
+
216
+ raise 'Pending'
217
+
218
+ sorting_proc = nil
219
+
220
+ case sort_name
221
+
222
+ when :alpha
223
+
224
+ when :numeric
225
+
226
+ when :alpha_numeric
227
+
228
+ when :numeric_alpha
229
+
230
+ when :upper_lower
231
+
232
+ when :lower_upper
233
+
234
+ when :upper_lower_numeric
235
+
236
+ when :lower_upper_numeric
237
+
238
+ when :numeric_upper_lower
239
+
240
+ when :numeric_lower_upper
241
+
242
+ when :reverse_alpha
243
+
244
+ when :reverse_alpha_numeric
245
+
246
+ when :reverse_numeric_alpha
247
+
248
+ when :reverse_upper_lower_numeric
249
+
250
+ when :reverse_lower_upper_numeric
251
+
252
+ when :reverse_numeric_upper_lower
253
+
254
+ when :reverse_numeric_lower_upper
255
+
256
+ end
257
+
258
+ return sorting_proc
259
+
260
+ end
261
+
262
+ ############
263
+ # cursor #
264
+ ############
265
+
266
+ ###
267
+ # Create and return cursor instance for this index.
268
+ #
269
+ # @return [Persistence::Cursor] New cursor instance.
270
+ #
271
+ def cursor( *args, & block )
272
+
273
+ cursor_instance = ::Persistence::Cursor.new( @parent_bucket, self )
274
+
275
+ if args.count > 0
276
+ cursor_instance.persisted?( *args )
277
+ end
278
+
279
+ if block_given?
280
+ cursor_instance = cursor_instance.instance_eval( & block )
281
+ cursor_instance.close
282
+ end
283
+
284
+ return cursor_instance
285
+
286
+ end
287
+
288
+ ###################
289
+ # atomic_cursor #
290
+ ###################
291
+
292
+ ###
293
+ # Create and return cursor instance for this index enabled to load all object properties as atomic.
294
+ # See Persistence::Cursor#atomize.
295
+ #
296
+ # @return [Persistence::Cursor] New cursor instance.
297
+ #
298
+ def atomic_cursor( *args, & block )
299
+
300
+ return cursor( *args, & block ).atomize
301
+
302
+ end
303
+
304
+ ##########
305
+ # each #
306
+ ##########
307
+
308
+ ###
309
+ # Iterate objects in current bucket.
310
+ #
311
+ # @yield [object] Current object.
312
+ #
313
+ # @yieldparam object Object stored in index.
314
+ #
315
+ def each( & block )
316
+
317
+ return atomic_cursor.each( & block )
318
+
319
+ end
320
+
321
+ ############################
322
+ # index_existing_objects #
323
+ ############################
324
+
325
+ ###
326
+ # Index objects that currently exist in parent bucket.
327
+ #
328
+ # @return self
329
+ #
330
+ def index_existing_objects
331
+
332
+ @parent_bucket.each do |this_object|
333
+ index_object( this_object )
334
+ end
335
+
336
+ return self
337
+
338
+ end
339
+ alias_method :sync_index, :index_existing_objects
340
+
341
+ ###################
342
+ # adapter_index #
343
+ ###################
344
+
345
+ ###
346
+ # Get adapter index (provided by adapter) associated with bucket index (provided by
347
+ # {Persistence::Object::Index Persistence::Object::Index}).
348
+ #
349
+ def adapter_index
350
+
351
+ unless @adapter_index
352
+ raise 'Persistence port must be enabled first.'
353
+ end
354
+
355
+ return @adapter_index
356
+
357
+ end
358
+
359
+ ###########
360
+ # count #
361
+ ###########
362
+
363
+ ###
364
+ # Get the number of objects in index. See {::Enumerable}.
365
+ #
366
+ # @return [Integer] Number of objects in current cursor context.
367
+ #
368
+ def count( *args, & block )
369
+
370
+ return_value = 0
371
+
372
+ if block_given?
373
+ return_value = super( & block )
374
+ elsif args.empty?
375
+ return_value = adapter_index.count
376
+ else
377
+ return_value = super( *args )
378
+ end
379
+
380
+ return return_value
381
+
382
+ end
383
+
384
+ ################
385
+ # persisted? #
386
+ ################
387
+
388
+ ###
389
+ # Query whether key exists in index.
390
+ #
391
+ # @return [true,false] Whether key exists in index.
392
+ #
393
+ def persisted?( key )
394
+
395
+ return get_object_id( key ) ? true : false
396
+
397
+ end
398
+
399
+ ###################
400
+ # get_object_id #
401
+ ###################
402
+
403
+ ###
404
+ # Get object ID for key in index.
405
+ #
406
+ # @return [Object] Object persistence ID associated with key.
407
+ #
408
+ def get_object_id( key )
409
+
410
+ return adapter_index.get_object_id( key )
411
+
412
+ end
413
+
414
+ ##################
415
+ # index_object #
416
+ ##################
417
+
418
+ ###
419
+ # Index key for object instance.
420
+ #
421
+ # @param object [Object] Object to index.
422
+ #
423
+ # @param key [Object] Key to use for index entry.
424
+ #
425
+ def index_object( object, key )
426
+
427
+ return index_object_id( object.persistence_id, key )
428
+
429
+ end
430
+
431
+ #####################
432
+ # index_object_id #
433
+ #####################
434
+
435
+ ###
436
+ # Index key for object persistence ID.
437
+ #
438
+ # @param global_id [Object] Persistence ID associated with object to index.
439
+ #
440
+ # @param key [Object] Key to use for index entry.
441
+ #
442
+ def index_object_id( global_id, key )
443
+
444
+ return adapter_index.index_object_id( global_id, key )
445
+
446
+ end
447
+
448
+ #############################
449
+ # delete_keys_for_object! #
450
+ #############################
451
+
452
+ ###
453
+ # Delete keys associated with object instance.
454
+ #
455
+ # @param object [Object] Object to index.
456
+ #
457
+ def delete_keys_for_object!( object )
458
+
459
+ return delete_keys_for_object_id!( object.persistence_id )
460
+
461
+ end
462
+
463
+ ################################
464
+ # delete_keys_for_object_id! #
465
+ ################################
466
+
467
+ ###
468
+ # Delete keys associated with object persistence ID.
469
+ #
470
+ # @param global_id [Object] Persistence ID associated with object to index.
471
+ #
472
+ def delete_keys_for_object_id!( global_id )
473
+
474
+ return adapter_index.delete_keys_for_object_id!( global_id )
475
+
476
+ end
477
+
478
+
479
+ end