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
+ # 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