persistence 0.0.1.alpha → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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