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,33 @@
1
+
2
+ ###
3
+ # @private
4
+ ###
5
+ # Provides primary key with the object's persistence_id and the attribute name, connected by
6
+ # self.class::Delimiter in including adapter class.
7
+ #
8
+ module ::Persistence::Adapter::Abstract::PrimaryKey::IDPropertyString
9
+
10
+ Delimiter = '.'
11
+
12
+ ####################################
13
+ # primary_key_for_attribute_name #
14
+ ####################################
15
+
16
+ ###
17
+ # Returns a primary key for storage in adapter (self). Generated from object instance and attribute name.
18
+ # Any further constraints are a function of the adapter's requirements, not of Persistence.
19
+ # This implementation returns a string with the object's persistence_id and the attribute name, connected by
20
+ # self.class::Delimiter in including adapter class.
21
+ #
22
+ # @param object Object instance for which to generate primary key.
23
+ # @param attribute_name Attribute name key refers to.
24
+ #
25
+ # @return String Primary key for use in adapter (self).
26
+ #
27
+ def primary_key_for_attribute_name( object, attribute_name )
28
+
29
+ return object.persistence_id.to_s << self.class::Delimiter << attribute_name.to_s
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,29 @@
1
+
2
+ ###
3
+ # @private
4
+ ###
5
+ # Provides primary key with attribute name to including adapter class.
6
+ #
7
+ module ::Persistence::Adapter::Abstract::PrimaryKey::Simple
8
+
9
+ ####################################
10
+ # primary_key_for_attribute_name #
11
+ ####################################
12
+
13
+ ###
14
+ # Returns a primary key for storage in adapter (self). Generated from object instance and attribute name.
15
+ # Any further constraints are a function of the adapter's requirements, not of Persistence.
16
+ # This implementation simply returns the attribute name.
17
+ #
18
+ # @param object Object instance for which to generate primary key.
19
+ # @param attribute_name Attribute name key refers to.
20
+ #
21
+ # @return String Primary key for use in adapter (self).
22
+ #
23
+ def primary_key_for_attribute_name( object, attribute_name )
24
+
25
+ return attribute_name
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,9 @@
1
+
2
+ ###
3
+ # Port class for Mock adapter. Interface implementation provided in module so methods can be easily overridden.
4
+ #
5
+ class ::Persistence::Adapter::Mock
6
+
7
+ include ::Persistence::Adapter::Mock::AdapterInterface
8
+
9
+ end
@@ -0,0 +1,102 @@
1
+
2
+ ###
3
+ # Interface implementation for storage port in Mock adapter.
4
+ #
5
+ module ::Persistence::Adapter::Mock::AdapterInterface
6
+
7
+ include ::Persistence::Adapter::Abstract::EnableDisable
8
+
9
+ ################
10
+ # initialize #
11
+ ################
12
+
13
+ def initialize( home_directory = nil )
14
+
15
+ super() if defined?( super )
16
+
17
+ @bucket_for_id = { }
18
+ @class_for_id = { }
19
+ @buckets = { }
20
+
21
+ end
22
+
23
+ ########################
24
+ # persistence_bucket #
25
+ ########################
26
+
27
+ def persistence_bucket( bucket )
28
+
29
+ bucket_instance = nil
30
+
31
+ unless bucket_instance = @buckets[ bucket ]
32
+ bucket_instance = ::Persistence::Adapter::Mock::Bucket.new( bucket )
33
+ bucket_instance.parent_adapter = self
34
+ @buckets[ bucket ] = bucket_instance
35
+ end
36
+
37
+ return bucket_instance
38
+
39
+ end
40
+
41
+ ###################################
42
+ # get_bucket_name_for_object_id #
43
+ ###################################
44
+
45
+ def get_bucket_name_for_object_id( global_id )
46
+
47
+ return @bucket_for_id[ global_id ]
48
+
49
+ end
50
+
51
+ #############################
52
+ # get_class_for_object_id #
53
+ #############################
54
+
55
+ def get_class_for_object_id( global_id )
56
+
57
+ return @class_for_id[ global_id ]
58
+
59
+ end
60
+
61
+ #################################
62
+ # delete_bucket_for_object_id #
63
+ #################################
64
+
65
+ def delete_bucket_for_object_id( global_id )
66
+
67
+ return @bucket_for_id.delete( global_id )
68
+
69
+ end
70
+
71
+ ################################
72
+ # delete_class_for_object_id #
73
+ ################################
74
+
75
+ def delete_class_for_object_id( global_id )
76
+
77
+ return @class_for_id.delete( global_id )
78
+
79
+ end
80
+
81
+ ##########################################
82
+ # ensure_object_has_globally_unique_id #
83
+ ##########################################
84
+
85
+ def ensure_object_has_globally_unique_id( object )
86
+
87
+ unless object.persistence_id
88
+
89
+ # in which case we need to create a new ID
90
+ @id_sequence = ( @id_sequence ||= -1 ) + 1
91
+ global_id = @id_sequence
92
+ @bucket_for_id[ global_id ] = object.persistence_bucket.name
93
+ @class_for_id[ global_id ] = object.class
94
+ object.persistence_id = global_id
95
+
96
+ end
97
+
98
+ return object.persistence_id
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,9 @@
1
+
2
+ ###
3
+ # Bucket class for Mock adapter. Interface implementation provided in module so methods can be easily overridden.
4
+ #
5
+ class ::Persistence::Adapter::Mock::Bucket
6
+
7
+ include ::Persistence::Adapter::Mock::Bucket::BucketInterface
8
+
9
+ end
@@ -0,0 +1,260 @@
1
+
2
+ ###
3
+ # Interface implementation for Bucket class instances.
4
+ #
5
+ module ::Persistence::Adapter::Mock::Bucket::BucketInterface
6
+
7
+ include ::Persistence::Adapter::Abstract::PrimaryKey::Simple
8
+
9
+ attr_accessor :parent_adapter, :name
10
+
11
+ ################
12
+ # initialize #
13
+ ################
14
+
15
+ ###
16
+ #
17
+ # @param name Name of bucket.
18
+ #
19
+ def initialize( name )
20
+
21
+ super() if defined?( super )
22
+
23
+ @name = name
24
+
25
+ @objects = { }
26
+ @indexes = { }
27
+
28
+ end
29
+
30
+ ###########
31
+ # count #
32
+ ###########
33
+
34
+ ###
35
+ # Get the number of objects in this bucket.
36
+ #
37
+ # @return [Integer] Number of objects in this bucket.
38
+ #
39
+ def count
40
+
41
+ return @objects.count
42
+
43
+ end
44
+
45
+ #################
46
+ # put_object! #
47
+ #################
48
+
49
+ ###
50
+ # Store object properties in this bucket.
51
+ #
52
+ # @param object Object whose properties are being stored.
53
+ #
54
+ # @return [Integer] Object persistence ID.
55
+ #
56
+ def put_object!( object )
57
+
58
+ parent_adapter.ensure_object_has_globally_unique_id( object )
59
+ object_persistence_hash = object.persistence_hash_to_port
60
+ @objects[ object.persistence_id ] = object_persistence_hash
61
+
62
+ return object.persistence_id
63
+
64
+ end
65
+
66
+ ################
67
+ # get_object #
68
+ ################
69
+
70
+ ###
71
+ # Retrieve object properties from this bucket.
72
+ #
73
+ # @param global_id Object persistence ID to retrieve object properties.
74
+ #
75
+ # @return [Integer] Object persistence ID.
76
+ #
77
+ def get_object( global_id )
78
+
79
+ return @objects[ global_id ]
80
+
81
+ end
82
+
83
+ ####################
84
+ # delete_object! #
85
+ ####################
86
+
87
+ ###
88
+ # Delete object properties from this bucket.
89
+ #
90
+ # @param global_id Object persistence ID to delete object properties.
91
+ #
92
+ # @return [Hash{Symbol,String=>Object}] Hash of property data deleted from port.
93
+ #
94
+ def delete_object!( global_id )
95
+
96
+ persistence_hash_in_port = @objects[ global_id ]
97
+
98
+ # and now delete the object's ID reference
99
+ @objects.delete( global_id )
100
+ parent_adapter.delete_bucket_for_object_id( global_id )
101
+ parent_adapter.delete_class_for_object_id( global_id )
102
+
103
+ return persistence_hash_in_port
104
+
105
+ end
106
+
107
+ ####################
108
+ # put_attribute! #
109
+ ####################
110
+
111
+ ###
112
+ # Store object property in this bucket.
113
+ #
114
+ # @param object Object whose properties are being stored.
115
+ # @param attribute_name Name of property being stored.
116
+ # @param attribute_value Value of property to store.
117
+ #
118
+ # @return self
119
+ #
120
+ def put_attribute!( object, attribute_name, attribute_value )
121
+
122
+ @objects[ object.persistence_id ] ||= { }
123
+ @objects[ object.persistence_id ][ attribute_name ] = ( attribute_name.is_a?( Symbol ) ? attribute_value : attribute_value.dup )
124
+
125
+ return self
126
+
127
+ end
128
+
129
+ ###################
130
+ # get_attribute #
131
+ ###################
132
+
133
+ ###
134
+ # Get object property stored in this bucket.
135
+ #
136
+ # @param object Object whose properties are being stored.
137
+ # @param attribute_name Name of property being stored.
138
+ #
139
+ # @return Value of property stored in this bucket for object.
140
+ #
141
+ def get_attribute( object, attribute_name )
142
+
143
+ @objects[ object.persistence_id ] ||= { }
144
+
145
+ return @objects[ object.persistence_id ][ attribute_name ]
146
+
147
+ end
148
+
149
+ #######################
150
+ # delete_attribute! #
151
+ #######################
152
+
153
+ ###
154
+ # Delete object property stored in this bucket.
155
+ #
156
+ # @param object Object whose properties are being stored.
157
+ # @param attribute_name Name of property being stored.
158
+ #
159
+ # @return Value of property deleted from this bucket for object.
160
+ #
161
+ def delete_attribute!( object, attribute_name )
162
+
163
+ deleted_value = nil
164
+
165
+ if @objects[ object.persistence_id ]
166
+ deleted_value = @objects[ object.persistence_id ].delete( attribute_name )
167
+ end
168
+
169
+ return deleted_value
170
+
171
+ end
172
+
173
+ ############
174
+ # cursor #
175
+ ############
176
+
177
+ ###
178
+ # Create and return cursor instance for this bucket.
179
+ #
180
+ # @return [Persistence::Adapter::Mock::Cursor] New cursor instance.
181
+ #
182
+ def cursor
183
+
184
+ return ::Persistence::Adapter::Mock::Cursor.new( self, nil )
185
+
186
+ end
187
+
188
+ ##################
189
+ # create_index #
190
+ ##################
191
+
192
+ ###
193
+ # Create and return index for this bucket.
194
+ #
195
+ # @param index_name Name to be used for index.
196
+ # @param permits_duplicates Whether index permits duplicate entries for the same key.
197
+ #
198
+ # @return [Persistence::Adapter::Mock::Bucket::Index] New index instance.
199
+ #
200
+ def create_index( index_name, permits_duplicates )
201
+
202
+ index_instance = ::Persistence::Adapter::Mock::Bucket::Index.new( index_name, self, permits_duplicates )
203
+ @indexes[ index_name ] = index_instance
204
+
205
+ return index_instance
206
+
207
+ end
208
+
209
+ ###########
210
+ # index #
211
+ ###########
212
+
213
+ ###
214
+ # Get index for this bucket.
215
+ #
216
+ # @param index_name Name of desired index.
217
+ #
218
+ # @return [Persistence::Adapter::Mock::Bucket::Index] Index instance for name.
219
+ #
220
+ def index( index_name )
221
+
222
+ return @indexes[ index_name ]
223
+
224
+ end
225
+
226
+ ##################
227
+ # delete_index #
228
+ ##################
229
+
230
+ ###
231
+ # Delete index for this bucket.
232
+ #
233
+ # @param index_name Index name to be deleted.
234
+ #
235
+ # @return [Persistence::Adapter::Mock::Bucket::Index] Deleted index instance.
236
+ #
237
+ def delete_index( index_name )
238
+
239
+ return @indexes.delete( index_name )
240
+
241
+ end
242
+
243
+ ################
244
+ # has_index? #
245
+ ################
246
+
247
+ ###
248
+ # Reports whether bucket has index by name.
249
+ #
250
+ # @param index_name Index name being queried.
251
+ #
252
+ # @return [true,false] Whether bucket has index by name.
253
+ #
254
+ def has_index?( index_name )
255
+
256
+ return @indexes.has_key?( index_name )
257
+
258
+ end
259
+
260
+ end