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,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