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,145 @@
1
+
2
+ ###
3
+ # @private
4
+ #
5
+ # Internal helper for parsing args of the format: method, method( global_id ), method( index_name, value ),
6
+ # method( index_instance, value ), method( index_name => value ), method( index_instance => value ).
7
+ module ::Persistence::Object::ParsePersistenceArgs
8
+
9
+ #########################################
10
+ # parse_args_for_index_value_no_value #
11
+ #########################################
12
+
13
+ ###
14
+ # Parse *args for index, key_value, no_value.
15
+ #
16
+ # @param args [Array] An array of args of the format: method, method( global_id ), method( index_name, value ),
17
+ # method( index_instance, value ), method( index_name => value ), method( index_instance => value ).
18
+ #
19
+ # @param require_value [true,false] Whether key value must be provided; will throw exception if true and
20
+ # key value is not provided.
21
+ #
22
+ # @return [Array] Array containing index instance, key value, whether key value was provided.
23
+ #
24
+ def parse_args_for_index_value_no_value( args, require_value = false )
25
+
26
+ # * nil
27
+ # - Cursor to primary bucket
28
+ # * :index
29
+ # - Cursor to index
30
+ # * :index => persistence_key
31
+ # - Object(s) for indexed key value
32
+
33
+ index = nil
34
+ key_value = nil
35
+ no_value = nil
36
+ case args.count
37
+
38
+ when 0
39
+
40
+ no_value = true
41
+ if require_value
42
+ raise ::Persistence::Exception::KeyValueRequired,
43
+ 'Key value required.'
44
+ end
45
+
46
+ when 1
47
+
48
+ index_or_id = args[ 0 ]
49
+ if index_or_id.is_a?( Symbol ) or
50
+ index_or_id.is_a?( String )
51
+
52
+ index = indexes[ index_or_id ]
53
+ unless index
54
+ raise ::Persistence::Exception::ExplicitIndexRequired,
55
+ 'Explicit index ' + index_or_id.to_s + ' did not exist.'
56
+ end
57
+ no_value = true
58
+
59
+ elsif index_or_id.respond_to?( :index_object )
60
+
61
+ index = index_or_id
62
+ no_value = true
63
+
64
+ elsif index_or_id.is_a?( Hash )
65
+
66
+ key_value = index_or_id.values[ 0 ]
67
+ index_name = index_or_id.keys[ 0 ]
68
+ if index_name.is_a?( Symbol ) or
69
+ index_name.is_a?( String )
70
+
71
+ index = indexes[ index_name ]
72
+ unless index
73
+ raise ::Persistence::Exception::ExplicitIndexRequired,
74
+ 'Explicit index :' + index_name.to_s + ' did not exist.'
75
+ end
76
+
77
+ end
78
+ no_value = false
79
+
80
+ else
81
+
82
+ # persistence_id - anything other than Symbol, String, Hash
83
+ key_value = args[ 0 ]
84
+ no_value = false
85
+
86
+ end
87
+
88
+ when 2
89
+
90
+ index_or_name = args[ 0 ]
91
+
92
+ index = index_or_name.respond_to?( :index_object ) ? index_or_name : indexes[ index_or_name ]
93
+ key_value = args[ 1 ]
94
+
95
+ if ! index and ! key_value
96
+ raise ::Persistence::Exception::ExplicitIndexRequired,
97
+ 'Index ' + index_or_name.to_s + ' did not exist.'
98
+ end
99
+ no_value = false
100
+
101
+ else
102
+
103
+ raise 'Unexpected arguments ' + args.inspect + '.'
104
+
105
+ end
106
+
107
+ # if we have a file we need to persist it like we would a sub-object
108
+ if key_value.is_a?( File )
109
+ key_value = process_file_key( key_value )
110
+ end
111
+
112
+ return index, key_value, no_value
113
+
114
+ end
115
+
116
+ ######################
117
+ # process_file_key #
118
+ ######################
119
+
120
+ ###
121
+ # Internal helper method to handle instances of File as key.
122
+ #
123
+ # @param file_key [File] File instance to process as key.
124
+ #
125
+ # @return [Persistence::Object::Flat::File::Path,Persistence::Object::Flat::File::Contents] Processed key.
126
+ #
127
+ def process_file_key( file_key )
128
+
129
+ # do we have a file key? if so we need to replace it with File::Path or File::Contents
130
+
131
+ processed_key = nil
132
+
133
+ if persists_files_by_path?
134
+ processed_key = ::Persistence::Object::Flat::File::Path.new( file_key.path )
135
+ else
136
+ starting_pos = file_key.pos
137
+ processed_key = ::Persistence::Object::Flat::File::Contents.new( file_key.readlines.join )
138
+ file_key.pos = starting_pos
139
+ end
140
+
141
+ return processed_key
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,9 @@
1
+
2
+ ###
3
+ # Public interface to storage port. Provides consist interface to adapter implementation.
4
+ #
5
+ class ::Persistence::Port
6
+
7
+ include ::Persistence::Port::PortInterface
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+
2
+ ###
3
+ # Public interface to bucket in storage port. Provides consistent interface to adapter implementation.
4
+ #
5
+ class ::Persistence::Port::Bucket
6
+
7
+ include ::Persistence::Port::Bucket::BucketInterface
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+
2
+ ###
3
+ # Bucket indexes run on each object inserted into bucket.
4
+ #
5
+ class ::Persistence::Port::Bucket::BucketIndex
6
+
7
+ include ::Persistence::Object::Index::BlockIndex::BlockIndexInterface
8
+
9
+ end
@@ -0,0 +1,685 @@
1
+
2
+ ###
3
+ # Interface for Bucket implementation. Provided separately for easy overriding.
4
+ #
5
+ module ::Persistence::Port::Bucket::BucketInterface
6
+
7
+ include ::Persistence::Object::Flat::File::FilePersistence
8
+
9
+ include ::Enumerable
10
+
11
+ ################
12
+ # initialize #
13
+ ################
14
+
15
+ ###
16
+ #
17
+ # @param parent_port Port where this bucket is active. Can be nil if no port is yet enabled.
18
+ #
19
+ # @param bucket_name Name of the bucket to open in port.
20
+ #
21
+ def initialize( parent_port, bucket_name )
22
+
23
+ @name = bucket_name
24
+
25
+ @indexes = { }
26
+ @pending_indexes = [ ]
27
+
28
+ if parent_port
29
+ initialize_for_port( parent_port )
30
+ end
31
+
32
+ end
33
+
34
+ #########################
35
+ # initialize_for_port #
36
+ #########################
37
+
38
+ ###
39
+ # Initialize bucket for a port that has been enabled.
40
+ #
41
+ # @param port Parent port in which to initialize bucket.
42
+ #
43
+ def initialize_for_port( port )
44
+
45
+ if port = ::Persistence.port_for_name_or_port( port ) and port.enabled?
46
+
47
+ @parent_port = ::Persistence.port_for_name_or_port( port )
48
+
49
+ if @parent_port.enabled?
50
+ @adapter_bucket = @parent_port.adapter.persistence_bucket( @name )
51
+ end
52
+
53
+ @indexes.each do |this_index_name, this_index_instance|
54
+ this_index_instance.initialize_for_bucket( self )
55
+ end
56
+
57
+ @pending_indexes.delete_if do |this_pending_index|
58
+ this_pending_index.initialize_for_bucket( self )
59
+ true
60
+ end
61
+
62
+ else
63
+
64
+ disable
65
+
66
+ end
67
+
68
+ end
69
+
70
+ ####################
71
+ # adapter_bucket #
72
+ ####################
73
+
74
+ ###
75
+ # Retrieve parallel adapter bucket instance.
76
+ #
77
+ # @return [Object] Adapter bucket instance.
78
+ #
79
+ def adapter_bucket
80
+
81
+ unless @adapter_bucket
82
+ raise 'Persistence port must be enabled first.'
83
+ end
84
+
85
+ return @adapter_bucket
86
+
87
+ end
88
+
89
+ ##########
90
+ # name #
91
+ ##########
92
+
93
+ ###
94
+ # @!attribute [accessor] Name of bucket
95
+ #
96
+ # @return [Symbol,String] Name.
97
+ #
98
+ attr_accessor :name
99
+
100
+ #################
101
+ # parent_port #
102
+ #################
103
+
104
+ attr_accessor :parent_port
105
+
106
+ #############
107
+ # disable #
108
+ #############
109
+
110
+ ###
111
+ # @private
112
+ #
113
+ # Disable bucket when port disables. Internal helper method necessary to ensure
114
+ # that old references don't stick around.
115
+ #
116
+ def disable
117
+
118
+ @adapter_bucket = nil
119
+ @parent_port = nil
120
+
121
+ @indexes.each do |this_index_name, this_index|
122
+ this_index.disable
123
+ end
124
+
125
+ end
126
+
127
+ ##################
128
+ # create_index #
129
+ ##################
130
+
131
+ ###
132
+ # Create a bucket index, which is a block index that runs on each inserted object, regardless of type.
133
+ #
134
+ def create_index( index_name, sort_by_proc = nil, & indexing_block )
135
+
136
+ return create_bucket_index( index_name, false, sort_by_proc, & indexing_block )
137
+
138
+ end
139
+
140
+ ##################################
141
+ # create_index_with_duplicates #
142
+ ##################################
143
+
144
+ ###
145
+ # Create a bucket index that permits duplicates.
146
+ #
147
+ def create_index_with_duplicates( index_name, sort_by_proc = nil, sort_duplicates_by_proc = nil, & indexing_block )
148
+
149
+ return create_bucket_index( index_name, true, sort_by_proc, sort_duplicates_by_proc, & indexing_block )
150
+
151
+ end
152
+
153
+ ################
154
+ # pend_index #
155
+ ################
156
+
157
+ ###
158
+ # @private
159
+ #
160
+ # Pend index instance for port to be enabled.
161
+ #
162
+ # @param index_instance Instance of index that is waiting for port to be enabled.
163
+ #
164
+ def pend_index( index_instance )
165
+
166
+ @pending_indexes.push( index_instance )
167
+
168
+ end
169
+
170
+ ###########
171
+ # index #
172
+ ###########
173
+
174
+ ###
175
+ # Retrieve index.
176
+ #
177
+ # @param index_name [Symbol,String] Name of index
178
+ #
179
+ # @param ensure_exists [true,false] Whether exception should be thrown if index does not exist.
180
+ #
181
+ # @return [Persistence::Object::Index] Index instance
182
+ #
183
+ def index( index_name, ensure_exists = false )
184
+
185
+ index_instance = nil
186
+
187
+ unless index_instance = @indexes[ index_name ]
188
+ if ensure_exists
189
+ raise ::ArgumentError, 'No index found by name ' << index_name.to_s + '.'
190
+ end
191
+ end
192
+
193
+ return index_instance
194
+
195
+ end
196
+
197
+ ################
198
+ # has_index? #
199
+ ################
200
+
201
+ ###
202
+ # Query whether attribute index(es) exist for object.
203
+ #
204
+ # @overload has_attribute_index?( index_name, ... )
205
+ #
206
+ # @param index_name Name of requested index.
207
+ #
208
+ # @return [true,false] Whether index(es) exist.
209
+ #
210
+ def has_index?( *indexes )
211
+
212
+ has_index = false
213
+
214
+ indexes.each do |this_index|
215
+ break unless has_index = @indexes.has_key?( index_name )
216
+ end
217
+
218
+ return has_index
219
+
220
+ end
221
+
222
+ ###########
223
+ # count #
224
+ ###########
225
+
226
+ ###
227
+ # Get the number of objects in index. See {::Enumerable}.
228
+ #
229
+ # @return [Integer] Number of objects in bucket.
230
+ #
231
+ def count( *args, & count_block )
232
+
233
+ return_value = 0
234
+
235
+ if block_given?
236
+ return_value = super( & count_block )
237
+ elsif args.empty?
238
+ return_value = adapter_bucket.count
239
+ else
240
+ return_value = super( *args )
241
+ end
242
+
243
+ return return_value
244
+
245
+ end
246
+
247
+ #############################
248
+ # delete_index_for_object #
249
+ #############################
250
+
251
+ ###
252
+ # @private
253
+ #
254
+ # Delete indexed entries for object.
255
+ #
256
+ # @param object Object that owns indexed entries.
257
+ #
258
+ # @param index_name Name of index.
259
+ #
260
+ def delete_index_for_object( object, index_name )
261
+
262
+ return delete_index_for_object_id( object.persistence_id )
263
+
264
+ end
265
+
266
+ ################################
267
+ # delete_index_for_object_id #
268
+ ################################
269
+
270
+ ###
271
+ # @private
272
+ #
273
+ # Delete indexed entries for object.
274
+ #
275
+ # @param global_id Object persistence ID that owns indexed entries.
276
+ #
277
+ # @param index_name Name of index.
278
+ #
279
+ def delete_index_for_object_id( global_id, index_name )
280
+
281
+ return adapter_bucket.delete_index_for_object_id( global_id )
282
+
283
+ end
284
+
285
+ ###################
286
+ # get_attribute #
287
+ ###################
288
+
289
+ ###
290
+ # @private
291
+ #
292
+ # Get attribute for object from port.
293
+ #
294
+ # @param object Object that owns indexed entries.
295
+ #
296
+ # @param attribute_name Name of attribute.
297
+ #
298
+ def get_attribute( object, attribute_name )
299
+
300
+ primary_key = primary_key_for_attribute_name( object, attribute_name )
301
+
302
+ attribute_value = adapter_bucket.get_attribute( object, primary_key )
303
+
304
+ if attribute_value.is_a?( ::Persistence::Object::Complex::ComplexObject )
305
+ attribute_value.persistence_port = object.persistence_port
306
+ attribute_value = attribute_value.persist
307
+ end
308
+
309
+ return attribute_value
310
+
311
+ end
312
+
313
+ ####################
314
+ # put_attribute! #
315
+ ####################
316
+
317
+ ###
318
+ # @private
319
+ #
320
+ # Put attribute for object to port.
321
+ #
322
+ # @param object Object that owns indexed entries.
323
+ #
324
+ # @param attribute_name Name of attribute.
325
+ #
326
+ # @param attribute_value Value to put.
327
+ #
328
+ def put_attribute!( object, attribute_name, attribute_value )
329
+
330
+ primary_key = primary_key_for_attribute_name( object, attribute_name )
331
+
332
+ return adapter_bucket.put_attribute!( object, primary_key, attribute_value )
333
+
334
+ end
335
+
336
+ #################
337
+ # put_object! #
338
+ #################
339
+
340
+ ###
341
+ # @private
342
+ #
343
+ # Put object properties to persistence port.
344
+ #
345
+ # @param object Object to persist to port.
346
+ #
347
+ def put_object!( object )
348
+
349
+ return adapter_bucket.put_object!( object )
350
+
351
+ end
352
+
353
+ ################
354
+ # get_object #
355
+ ################
356
+
357
+ ###
358
+ # @private
359
+ #
360
+ # Get object from persistence port.
361
+ #
362
+ # @param global_id Object persistence ID to persist from port.
363
+ #
364
+ # @return [Object] Persisted object instance.
365
+ #
366
+ def get_object( global_id )
367
+
368
+ object = nil
369
+
370
+ # get the class
371
+ if klass = @parent_port.get_class_for_object_id( global_id )
372
+
373
+ object = klass.new
374
+
375
+ object.persistence_id = global_id
376
+
377
+ # if we have non-atomic attributes, load them
378
+ unless klass.non_atomic_attribute_readers.empty?
379
+
380
+ if persistence_hash_from_port = get_object_hash( global_id )
381
+
382
+ object.load_persistence_hash( object.persistence_port, persistence_hash_from_port )
383
+
384
+ end
385
+
386
+ end
387
+
388
+ end
389
+
390
+ return object
391
+
392
+ end
393
+
394
+ #####################
395
+ # get_object_hash #
396
+ #####################
397
+
398
+ ###
399
+ # @private
400
+ #
401
+ # Get object properties from persistence port.
402
+ #
403
+ # @param global_id Object persistence ID to persist from port.
404
+ #
405
+ # @return [Hash] Persistence hash from port.
406
+ #
407
+ def get_object_hash( global_id )
408
+
409
+ return adapter_bucket.get_object( global_id )
410
+
411
+ end
412
+
413
+ #####################
414
+ # get_flat_object #
415
+ #####################
416
+
417
+ ###
418
+ # @private
419
+ #
420
+ # Get flat object from persistence port.
421
+ #
422
+ # @param global_id Object persistence ID to persist from port.
423
+ #
424
+ # @return [Object] Persisted object instance.
425
+ #
426
+ def get_flat_object( global_id )
427
+
428
+ flat_object = nil
429
+
430
+ if persistence_value_hash = adapter_bucket.get_object( global_id )
431
+
432
+ if persistence_value_key_data = persistence_value_hash.first
433
+ flat_object = persistence_value_key_data[ 1 ]
434
+ flat_object.persistence_id = global_id
435
+ end
436
+ end
437
+
438
+ return flat_object
439
+
440
+ end
441
+
442
+ ####################
443
+ # delete_object! #
444
+ ####################
445
+
446
+ ###
447
+ # @private
448
+ #
449
+ # Delete object from persistence port.
450
+ #
451
+ # @param global_id Object persistence ID to delete from port.
452
+ #
453
+ # @return [Hash] Persistence hash from port.
454
+ #
455
+ def delete_object!( global_id )
456
+
457
+ return adapter_bucket.delete_object!( global_id )
458
+
459
+ end
460
+
461
+ #######################
462
+ # delete_attribute! #
463
+ #######################
464
+
465
+ ###
466
+ # @private
467
+ #
468
+ # Delete attribute for object from port.
469
+ #
470
+ # @param object Object that owns indexed entries.
471
+ #
472
+ # @param attribute_name Name of attribute.
473
+ #
474
+ def delete_attribute!( object, attribute_name )
475
+
476
+ primary_key = primary_key_for_attribute_name( object, attribute_name )
477
+
478
+ return adapter_bucket.delete_attribute!( object, primary_key )
479
+
480
+ end
481
+
482
+ ####################################
483
+ # primary_key_for_attribute_name #
484
+ ####################################
485
+
486
+ ###
487
+ # @private
488
+ #
489
+ # Generate primary key for storage for attribute name on object.
490
+ #
491
+ # @param object Object for which attribute is being stored.
492
+ #
493
+ # @param attribute_name Name of attribute.
494
+ #
495
+ # @return [String] Primary key.
496
+ #
497
+ def primary_key_for_attribute_name( object, attribute_name )
498
+
499
+ return adapter_bucket.primary_key_for_attribute_name( object, attribute_name )
500
+
501
+ end
502
+
503
+ ################################
504
+ # persists_files_by_content? #
505
+ ################################
506
+
507
+ def persists_files_by_content?
508
+
509
+ persists_files_by_content = nil
510
+
511
+ persists_files_by_content = super
512
+
513
+ if persists_files_by_content.nil?
514
+ persists_files_by_content = parent_port.persists_files_by_content?
515
+ end
516
+
517
+ return persists_files_by_content
518
+
519
+ end
520
+
521
+ #############################
522
+ # persists_files_by_path? #
523
+ #############################
524
+
525
+ def persists_files_by_path?
526
+
527
+ persists_files_by_path = nil
528
+
529
+ persists_files_by_path = super
530
+
531
+ if persists_files_by_path.nil?
532
+ persists_files_by_path = parent_port.persists_files_by_path?
533
+ end
534
+
535
+ return persists_files_by_path
536
+
537
+ end
538
+
539
+ #####################################
540
+ # persists_file_paths_as_objects? #
541
+ #####################################
542
+
543
+ def persists_file_paths_as_objects?
544
+
545
+ persists_file_paths_as_objects = nil
546
+
547
+ persists_file_paths_as_objects = super
548
+
549
+ if persists_file_paths_as_objects.nil?
550
+ persists_file_paths_as_objects = parent_port.persists_file_paths_as_objects?
551
+ end
552
+
553
+ return persists_file_paths_as_objects
554
+
555
+ end
556
+
557
+ #####################################
558
+ # persists_file_paths_as_strings? #
559
+ #####################################
560
+
561
+ def persists_file_paths_as_strings?
562
+
563
+ persists_file_paths_as_strings = nil
564
+
565
+ persists_file_paths_as_strings = super
566
+
567
+ if persists_file_paths_as_strings.nil?
568
+ persists_file_paths_as_strings = parent_port.persists_file_paths_as_strings?
569
+ end
570
+
571
+ return persists_file_paths_as_strings
572
+
573
+ end
574
+
575
+ ############
576
+ # cursor #
577
+ ############
578
+
579
+ ###
580
+ # Create and return cursor instance for this bucket.
581
+ #
582
+ # @return [Persistence::Cursor] New cursor instance.
583
+ #
584
+ def cursor( *args, & block )
585
+
586
+ cursor_instance = ::Persistence::Cursor.new( self )
587
+
588
+ if args.count > 0
589
+ cursor_instance.persisted?( *args )
590
+ end
591
+
592
+ if block_given?
593
+ cursor_instance = cursor_instance.instance_eval( & block )
594
+ cursor_instance.close
595
+ end
596
+
597
+ return cursor_instance
598
+
599
+ end
600
+
601
+ ###################
602
+ # atomic_cursor #
603
+ ###################
604
+
605
+ ###
606
+ # Create and return cursor instance for this index enabled to load all object properties as atomic.
607
+ # See Persistence::Cursor#atomize.
608
+ #
609
+ # @return [Persistence::Cursor] New cursor instance.
610
+ #
611
+ def atomic_cursor( *args )
612
+
613
+ return cursor( *args ).atomize
614
+
615
+ end
616
+
617
+ ##########
618
+ # each #
619
+ ##########
620
+
621
+ ###
622
+ # Iterate objects in current bucket.
623
+ #
624
+ # @yield [object] Current object.
625
+ #
626
+ # @yieldparam object Object stored in bucket.
627
+ #
628
+ def each( & block )
629
+
630
+ return atomic_cursor.each( & block )
631
+
632
+ end
633
+
634
+ ##################################################################################################
635
+ private ######################################################################################
636
+ ##################################################################################################
637
+
638
+ #########################
639
+ # create_bucket_index #
640
+ #########################
641
+
642
+ ###
643
+ # Internal helper method for common code to create bucket indexs.
644
+ #
645
+ # @param index_name Name of index to create.
646
+ #
647
+ # @param permits_duplicates Whether index should permit duplicates.
648
+ #
649
+ # @param sort_by_proc [Proc] Proc to use for sorting objects.
650
+ #
651
+ # @param sort_duplicates_by_proc [Proc] Proc to use for sorting duplicate objects.
652
+ #
653
+ # @yield [object] Block to create index keys on object.
654
+ # @yieldparam object [Object] Object to index.
655
+ #
656
+ # @return [Persistence::Port::Bucket::BucketIndex]
657
+ #
658
+ def create_bucket_index( index_name,
659
+ permits_duplicates,
660
+ sort_by_proc = nil,
661
+ sort_duplicates_by_proc = nil,
662
+ & indexing_block )
663
+
664
+ if index_instance = @indexes[ index_name ] and
665
+ index_instance.permits_duplicates? != permits_duplicates
666
+
667
+ raise 'Index ' << index_name.to_s + ' has already been declared, ' <<
668
+ 'and new duplicates declaration does not match existing declaration.'
669
+
670
+ end
671
+
672
+ index_instance = ::Persistence::Port::Bucket::BucketIndex.new( index_name,
673
+ self,
674
+ permits_duplicates,
675
+ sort_by_proc,
676
+ sort_duplicates_by_proc,
677
+ & indexing_block )
678
+
679
+ @indexes[ index_name ] = index_instance
680
+
681
+ return index_instance
682
+
683
+ end
684
+
685
+ end