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
+ # Index class for Mock adapter. Interface implementation provided in module so methods can be easily overridden.
4
+ #
5
+ class ::Persistence::Adapter::Mock::Bucket::Index
6
+
7
+ include ::Persistence::Adapter::Mock::Bucket::Index::IndexInterface
8
+
9
+ end
@@ -0,0 +1,155 @@
1
+
2
+ ###
3
+ # Interface implementation for Index class instances.
4
+ #
5
+ module ::Persistence::Adapter::Mock::Bucket::Index::IndexInterface
6
+
7
+ ################
8
+ # initialize #
9
+ ################
10
+
11
+ ###
12
+ #
13
+ # @param index_name
14
+ # @param parent_bucket
15
+ # @param permits_duplicates
16
+ #
17
+ def initialize( index_name, parent_bucket, permits_duplicates )
18
+
19
+ @name = index_name
20
+
21
+ @keys = { }
22
+ @reverse_keys = { }
23
+ @permits_duplicates = permits_duplicates
24
+ @parent_bucket = parent_bucket
25
+
26
+ end
27
+
28
+ ###################
29
+ # parent_bucket #
30
+ ###################
31
+
32
+ ###
33
+ # Track parent bucket for this index.
34
+ #
35
+ # @!attribute[r]
36
+ #
37
+ # @return [Persistence::Adapter::Mock::Bucket] Parent bucket instance.
38
+ #
39
+ attr_accessor :parent_bucket
40
+
41
+ ############
42
+ # cursor #
43
+ ############
44
+
45
+ ###
46
+ # Create and return cursor instance for this index.
47
+ #
48
+ # @return [Persistence::Adapter::Mock::Cursor] New cursor instance.
49
+ #
50
+ def cursor
51
+
52
+ return ::Persistence::Adapter::Mock::Cursor.new( @parent_bucket, self )
53
+
54
+ end
55
+
56
+ ###########
57
+ # count #
58
+ ###########
59
+
60
+ ###
61
+ # Get the number of indexed objects in this index.
62
+ #
63
+ # @return [Integer] Number of indexed objects in this index.
64
+ #
65
+ def count
66
+
67
+ return @keys.count
68
+
69
+ end
70
+
71
+ #########################
72
+ # permits_duplicates? #
73
+ #########################
74
+
75
+ ###
76
+ # Reports whether this index permits duplicate indexed entries per key.
77
+ #
78
+ # @return [true,false] Whether index permits duplicate entries.
79
+ #
80
+ def permits_duplicates?
81
+
82
+ return @permits_duplicates
83
+
84
+ end
85
+
86
+ #####################
87
+ # index_object_id #
88
+ #####################
89
+
90
+ ###
91
+ # Index object ID for index key.
92
+ #
93
+ # @param global_id Object persistence ID for object lookup.
94
+ # @param key Key to index for later lookup of object ID in index.
95
+ #
96
+ # @return self
97
+ #
98
+ def index_object_id( global_id, key )
99
+
100
+ @keys[ key ] = global_id
101
+ @reverse_keys[ global_id ] = key
102
+
103
+ return self
104
+
105
+ end
106
+
107
+ ###################
108
+ # get_object_id #
109
+ ###################
110
+
111
+ ###
112
+ # Retrieve indexed object ID for index key.
113
+ #
114
+ # @param key Previously indexed key for lookup in index.
115
+ #
116
+ # @return
117
+ #
118
+ def get_object_id( key )
119
+
120
+ return @keys[ key ]
121
+
122
+ end
123
+
124
+ ################################
125
+ # delete_keys_for_object_id! #
126
+ ################################
127
+
128
+ ###
129
+ # Delete all keys in this index for object ID.
130
+ #
131
+ # @param global_id Object persistence ID for object lookup.
132
+ #
133
+ # @return self
134
+ #
135
+ def delete_keys_for_object_id!( global_id )
136
+
137
+ index_value_or_keys = @reverse_keys.delete( global_id )
138
+
139
+ if index_value_or_keys.is_a?( Array )
140
+
141
+ index_value_or_keys.each do |this_key|
142
+ @keys.delete( this_key )
143
+ end
144
+
145
+ else
146
+
147
+ @keys.delete( index_value_or_keys )
148
+
149
+ end
150
+
151
+ return self
152
+
153
+ end
154
+
155
+ end
@@ -0,0 +1,9 @@
1
+
2
+ ###
3
+ # Cursor class for Mock adapter. Interface implementation provided in module so methods can be easily overridden.
4
+ #
5
+ class ::Persistence::Adapter::Mock::Cursor
6
+
7
+ include ::Persistence::Adapter::Mock::Cursor::CursorInterface
8
+
9
+ end
@@ -0,0 +1,238 @@
1
+
2
+ ###
3
+ # Interface implementation for Mock adapter Cursor class instances.
4
+ #
5
+ module ::Persistence::Adapter::Mock::Cursor::CursorInterface
6
+
7
+ ################
8
+ # initialize #
9
+ ################
10
+
11
+ ###
12
+ #
13
+ # @param bucket Cursor will open on bucket instance.
14
+ # @param index Cursor will open on index instance.
15
+ #
16
+ def initialize( bucket, index )
17
+
18
+ @persistence_bucket = bucket
19
+ @index = index
20
+
21
+ @id_source = index ? index.instance_variable_get( :@keys )
22
+ : bucket.instance_variable_get( :@objects )
23
+
24
+ @current_position = ( @id_source || { } ).each
25
+
26
+ end
27
+
28
+ ############################
29
+ # supports_bucket_order? #
30
+ ############################
31
+
32
+ def supports_bucket_order?
33
+
34
+ return true
35
+
36
+ end
37
+
38
+ ###########################
39
+ # supports_index_order? #
40
+ ###########################
41
+
42
+ def supports_index_order?
43
+
44
+ return true
45
+
46
+ end
47
+
48
+ ###########
49
+ # close #
50
+ ###########
51
+
52
+ ###
53
+ # Declare use of cursor complete.
54
+ #
55
+ def close
56
+
57
+ # nothing required
58
+
59
+ end
60
+
61
+ ################
62
+ # persisted? #
63
+ ################
64
+
65
+ ###
66
+ # Query whether keys are persisted in cursor's current context.
67
+ # Responsible for setting the cursor position.
68
+ #
69
+ # @overload persisted?( key, ... )
70
+ #
71
+ # @param [Object] Key to look up.
72
+ #
73
+ # @return [true,false] Whether key(s) exist in cursor's current context.
74
+ #
75
+ def persisted?( *args )
76
+
77
+ # persisted? is responsible for setting the cursor position
78
+
79
+ key = nil
80
+ # we expect 0 or 1 arg
81
+ if args.count > 0
82
+ key = args[ 0 ]
83
+ else
84
+ # if we have no key we are asking if keys exist
85
+ @current_position.rewind
86
+
87
+ return @id_source.count > 0 ? true : false
88
+ end
89
+
90
+ has_key = false
91
+
92
+ # rewind to beginning of bucket
93
+ @current_position.rewind
94
+
95
+ # iterate until we find our key
96
+ begin
97
+
98
+ while @current_item = @current_position.next
99
+ if @current_item[ 0 ] == key
100
+ has_key = true
101
+ break
102
+ end
103
+ end
104
+
105
+ rescue StopIteration
106
+
107
+ @current_item = nil
108
+
109
+ end
110
+
111
+ return has_key
112
+
113
+ end
114
+
115
+ ###########
116
+ # first #
117
+ ###########
118
+
119
+ ###
120
+ # Return the first object in cursor's current context.
121
+ # Responsible for setting the cursor position.
122
+ #
123
+ # @return [Object] First object in cursor's current context.
124
+ #
125
+ def first
126
+
127
+ # first should set the cursor position and return the first ID or object hash
128
+
129
+ begin
130
+ @current_item = @current_position.rewind.peek
131
+ rescue StopIteration
132
+ @current_item = nil
133
+ end
134
+
135
+ return current
136
+
137
+ end
138
+
139
+ ###############
140
+ # first_key #
141
+ ###############
142
+
143
+ ###
144
+ # Return the first key in cursor's current context.
145
+ # Responsible for setting the cursor position.
146
+ #
147
+ # @return [Object] First key in cursor's current context.
148
+ #
149
+ def first_key
150
+ begin
151
+ @current_item = @current_position.rewind.peek
152
+ rescue StopIteration
153
+ @current_item = nil
154
+ end
155
+ return current_key
156
+ end
157
+
158
+ #############
159
+ # current #
160
+ #############
161
+
162
+ ###
163
+ # Return the current object in cursor's current context.
164
+ #
165
+ # @return [Object] Current object in cursor's current context.
166
+ #
167
+ def current
168
+
169
+ # current should return the current ID or object hash
170
+
171
+ current_id = nil
172
+
173
+ if @current_item
174
+ if @index
175
+ current_id = @current_item[ 1 ]
176
+ else
177
+ current_id = @current_item[ 0 ]
178
+ end
179
+ end
180
+
181
+ return current_id
182
+
183
+ end
184
+
185
+ #################
186
+ # current_key #
187
+ #################
188
+
189
+ ###
190
+ # Return the current key in cursor's current context.
191
+ #
192
+ # @return [Object] Current object in cursor's current context.
193
+ #
194
+ def current_key
195
+ current_key = nil
196
+ if @current_item
197
+ current_key = @current_item[ 0 ]
198
+ end
199
+ return current_key
200
+ end
201
+
202
+ ##########
203
+ # next #
204
+ ##########
205
+
206
+ ###
207
+ # Return the next object in cursor's current context.
208
+ #
209
+ # @return [Object] Next object in cursor's current context.
210
+ #
211
+ def next
212
+ begin
213
+ @current_item = @current_position.next
214
+ rescue StopIteration
215
+ @current_item = nil
216
+ end
217
+ return current
218
+ end
219
+
220
+ ##############
221
+ # next_key #
222
+ ##############
223
+
224
+ ###
225
+ # Return the next key in cursor's current context.
226
+ #
227
+ # @return [Object] Next key in cursor's current context.
228
+ #
229
+ def next_key
230
+ begin
231
+ @current_item = @current_position.next
232
+ rescue StopIteration
233
+ @current_item = nil
234
+ end
235
+ return current_key
236
+ end
237
+
238
+ end
@@ -0,0 +1,11 @@
1
+
2
+ ###
3
+ # Cursor class. Interface implementation provided in module so methods can be easily overridden.
4
+ #
5
+ class ::Persistence::Cursor
6
+
7
+ include ::Enumerable
8
+
9
+ include ::Persistence::Cursor::CursorInterface
10
+
11
+ end
@@ -0,0 +1,110 @@
1
+
2
+ ###
3
+ # Cursor subclass that automatically performs atomic lookups on attributes.
4
+ #
5
+ module ::Persistence::Cursor::Atomic
6
+
7
+ ################
8
+ # get_object #
9
+ ################
10
+
11
+ ###
12
+ # Get object for persistence ID using atomic attribute loading, regardless how attributes are declared.
13
+ #
14
+ # @param global_id Persistence ID to retrieve object.
15
+ #
16
+ # @return [Object] Object being retrieved for persistence ID.
17
+ #
18
+ def get_object( global_id )
19
+
20
+ klass = @persistence_bucket.parent_port.get_class_for_object_id( global_id )
21
+
22
+ object = nil
23
+
24
+ if klass
25
+ object = klass.new
26
+ object.persistence_id = global_id
27
+ object.attrs_atomic!
28
+ end
29
+
30
+ return object
31
+
32
+ end
33
+
34
+ #############
35
+ # persist #
36
+ #############
37
+
38
+ ###
39
+ # Load object with specified persistence ID.
40
+ #
41
+ # @param key Key to retrieve.
42
+ #
43
+ # @return [Object] Object for persistence ID.
44
+ #
45
+ def persist( key )
46
+
47
+ return super.attrs_atomic!
48
+
49
+ end
50
+
51
+ ###########
52
+ # first #
53
+ ###########
54
+
55
+ ###
56
+ # Persist first object in cursor context.
57
+ #
58
+ # @param [Integer] count How many objects to persist from start of cursor context.
59
+ #
60
+ # @return [Object,Array<Object>] Object or objects requested.
61
+ #
62
+ def first( count = 1 )
63
+ first_values = super
64
+ if first_values.is_a?( Array )
65
+ first_values.each do |this_value|
66
+ this_value.attrs_atomic!
67
+ end
68
+ elsif first_values
69
+ first_values.attrs_atomic!
70
+ end
71
+ return first_values
72
+ end
73
+
74
+ #############
75
+ # current #
76
+ #############
77
+
78
+ ###
79
+ # Persist current object in cursor context.
80
+ #
81
+ # @return [Object,Array<Object>] Object requested.
82
+ #
83
+ def current
84
+ current_value = super
85
+ current_value.attrs_atomic! if current_value
86
+ return current_value
87
+ end
88
+
89
+ ##########
90
+ # next #
91
+ ##########
92
+
93
+ ###
94
+ # Return the next object in cursor's current context.
95
+ #
96
+ # @return [Object] Next object in cursor's current context.
97
+ #
98
+ def next( count = 1 )
99
+ next_values = super
100
+ if next_values.is_a?( Array )
101
+ next_values.each do |this_value|
102
+ this_value.attrs_atomic!
103
+ end
104
+ elsif next_values
105
+ next_values.attrs_atomic!
106
+ end
107
+ return next_values
108
+ end
109
+
110
+ end