nano-store 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.gitmodules +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +193 -0
- data/Rakefile +1 -0
- data/app/app_delegate.rb +5 -0
- data/lib/nano-store.rb +1 -0
- data/lib/nano_store/bag.rb +98 -0
- data/lib/nano_store/model.rb +142 -0
- data/lib/nano_store/nano_store.rb +36 -0
- data/lib/nano_store/store_extension.rb +150 -0
- data/lib/nano_store/version.rb +3 -0
- data/lib/nano_store.rb +14 -0
- data/nano-store.gemspec +17 -0
- data/resources/.gitignore +0 -0
- data/spec/bag_spec.rb +66 -0
- data/spec/model_spec.rb +130 -0
- data/spec/nano_store_spec.rb +48 -0
- data/spec/store_extension_spec.rb +110 -0
- data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.h +542 -0
- data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.m +1781 -0
- data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.h +137 -0
- data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.m +265 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoBag_Private.h +37 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoEngine_Private.h +69 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoExpression_Private.h +35 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoGlobals_Private.h +99 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoObject_Private.h +35 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoPredicate_Private.h +35 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoResult_Private.h +43 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoSearch_Private.h +48 -0
- data/vendor/NanoStore/Classes/Private/NSFNanoStore_Private.h +57 -0
- data/vendor/NanoStore/Classes/Private/NanoStore_Private.h +37 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoBag.h +306 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoBag.m +485 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoExpression.h +125 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoExpression.m +103 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.h +323 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.m +145 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoObject.h +298 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoObject.m +187 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoObjectProtocol.h +119 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.h +123 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.m +130 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoSearch.h +381 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoSearch.m +835 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.h +124 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.m +79 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoStore.h +475 -0
- data/vendor/NanoStore/Classes/Public/NSFNanoStore.m +1375 -0
- data/vendor/NanoStore/Classes/Public/NanoStore.h +463 -0
- data/vendor/NanoStore/LICENSE +25 -0
- data/vendor/NanoStore/NanoStore.bridgesupport +1215 -0
- data/vendor/NanoStore/README.md +411 -0
- metadata +118 -0
@@ -0,0 +1,298 @@
|
|
1
|
+
/*
|
2
|
+
NSFNanoObject.h
|
3
|
+
NanoStore
|
4
|
+
|
5
|
+
Copyright (c) 2010 Webbo, L.L.C. All rights reserved.
|
6
|
+
|
7
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
8
|
+
provided that the following conditions are met:
|
9
|
+
|
10
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
11
|
+
and the following disclaimer.
|
12
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
13
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
14
|
+
* Neither the name of Webbo nor the names of its contributors may be used to endorse or promote
|
15
|
+
products derived from this software without specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
18
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
19
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
|
20
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
21
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
23
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
24
|
+
SUCH DAMAGE.
|
25
|
+
*/
|
26
|
+
|
27
|
+
/*! @file NSFNanoObject.h
|
28
|
+
@brief A generic class that implements all the basic behavior required of a NanoStore object.
|
29
|
+
*/
|
30
|
+
|
31
|
+
/** @class NSFNanoObject
|
32
|
+
The basic unit of data in NanoStore is called NanoObject. A NanoObject is any object which conforms to the NSFNanoObjectProtocol protocol.
|
33
|
+
|
34
|
+
@section notaflatworld_sec It's not a flat World
|
35
|
+
|
36
|
+
Most database solutions force the developer to think in a two-dimensional space (rows and columns), forcing the developer to plan the schema ahead of
|
37
|
+
time. This situation is not ideal because in most cases schema refinements could be required, oftentimes impacting the code as well.
|
38
|
+
|
39
|
+
NanoStore goes beyond that allowing the developer to store objects in their natural form. These objects must conform to the NSFNanoObjectProtocol
|
40
|
+
protocol, providing NanoStore with the NSDictionary that will be stored. By using a dictionary data can be inspected very quickly, and it also allows the
|
41
|
+
structure to be defined in a hierarchical fashion as well, due to the fact that it includes support for nested collections (of type NSDictionary and NSArray.)
|
42
|
+
Each inner-object is indexed automatically, thus allowing to quickly find objects which contain a specific key and/or value.
|
43
|
+
|
44
|
+
By default, NanoStore allows objects to be stored without any sense of relationship to other objects. This simple format, while powerful, is limited because
|
45
|
+
the developer has to keep track of the relationships among objects. Some applications may need to relate objects, some of them perhaps of different nature or class
|
46
|
+
type. This is exactly what NanoBag (represented by the NSFNanoBag class) does: it allows any object conforming to the NSFNanoObjectProtocol protocol to be
|
47
|
+
added to the bag. By saving the bag with one single call, the new and/or modified are taken care of seamlessly.
|
48
|
+
|
49
|
+
The NSFNanoBag API is rich, allowing the developer to add, remove, reload and undo its changes, deflate it (thus saving memory) and inflate it whenever it's
|
50
|
+
required. In addition, it provides methods to obtain all bags, specific bags matching some keys, and bags containing a specific object
|
51
|
+
(see NSFNanoStore for more information).
|
52
|
+
|
53
|
+
<b>Structure of a NanoObject object</b>
|
54
|
+
|
55
|
+
At its core, a NanoObject is nothing more than a wrapper around two properties:
|
56
|
+
|
57
|
+
- A dictionary which contains the metadata (provided by the developer)
|
58
|
+
- A key (UUID) that identifies the object (provided by NanoStore)
|
59
|
+
|
60
|
+
The dictionary <i>must</i> be serializable, which means that only the following data types are allowed:
|
61
|
+
|
62
|
+
- NSArray
|
63
|
+
- NSDictionary
|
64
|
+
- NSString
|
65
|
+
- NSData (*)
|
66
|
+
- NSDate
|
67
|
+
- NSNumber
|
68
|
+
|
69
|
+
(*) The data type NSData is allowed, but it will be excluded from the indexing process.
|
70
|
+
|
71
|
+
To save and retrieve objects from the document store, NanoStore moves the data around by encapsulating it in NanoObjects. In order to store the objects in
|
72
|
+
NanoStore the developer has three options:
|
73
|
+
|
74
|
+
- Use the NSFNanoObject class directly
|
75
|
+
- Expand your custom classes by inheriting from NSFNanoObject
|
76
|
+
- Expand your custom classes by implementing the NSFNanoObjectProtocol protocol
|
77
|
+
|
78
|
+
Regardless of the route you decide to take, NanoStore will be able to store and retrieve objects from the document store seamlessly. The beauty of this system is that
|
79
|
+
NanoStore returns the object as it was stored, that is, instantiating an object of the class that was originally stored.
|
80
|
+
|
81
|
+
@note
|
82
|
+
If the document store is opened by another application that doesn't implement the object that was stored, NanoStore will instantiate a
|
83
|
+
NSFNanoObject instead, thus allowing the app to retrieve the data seamlessly. If the object is then updated by this application, the original
|
84
|
+
class name will be honored.
|
85
|
+
|
86
|
+
<b>Example:</b>
|
87
|
+
|
88
|
+
- App A stores an object of class <i>Car</i>.
|
89
|
+
- App B retrieves the object, but since it doesn't know anything about the class <i>Car</i>, NanoStore returns a NSFNanoObject.
|
90
|
+
- App B updates the object, perhaps adding a timestamp or additional information. NanoStore saves it as a <i>Car</i>, not as a NSFNanoObject.
|
91
|
+
- App A retrieves the updated object as a <i>Car</i> object, in exactly the same format as it was originally stored.
|
92
|
+
|
93
|
+
@section workingwithnanoobject_sec Working with a NanoObject
|
94
|
+
|
95
|
+
There are three basic operations that NanoStore can perform with a NanoObject:
|
96
|
+
|
97
|
+
- Add it to the document store
|
98
|
+
- Update an existing object in the document store
|
99
|
+
- Remove it from the document store
|
100
|
+
|
101
|
+
To add an object, instantiate a \link NSFNanoObject::nanoObject NanoObject, \endlink populate it and add it to the document store.
|
102
|
+
|
103
|
+
@details <b>Example:</b>
|
104
|
+
@code
|
105
|
+
// Instantiate a NanoStore and open it
|
106
|
+
NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
|
107
|
+
|
108
|
+
// Generate an empty NanoObject
|
109
|
+
NSFNanoObject *object = [NSFNanoObject nanoObject];
|
110
|
+
|
111
|
+
// Add some data
|
112
|
+
[object setObject:@"Doe" forKey:@"kLastName"];
|
113
|
+
[object setObject:@"John" forKey:@"kFirstName"];
|
114
|
+
[object setObject:[NSArray arrayWithObjects:@"jdoe@foo.com", @"jdoe@bar.com", nil] forKey:@"kEmails"];
|
115
|
+
|
116
|
+
// Add it to the document store
|
117
|
+
[nanoStore addObject:object error:nil];
|
118
|
+
|
119
|
+
// Close the document store
|
120
|
+
[nanoStore closeWithError:nil];
|
121
|
+
@endcode
|
122
|
+
|
123
|
+
Alternatively, you can instantiate a \link NSFNanoObject::nanoObject NanoObject \endlink providing a dictionary via \link NSFNanoObject::nanoObjectWithDictionary: + (NSFNanoObject*)nanoObjectWithDictionary:(NSDictionary *)theDictionary. \endlink
|
124
|
+
NanoStore will assign a UUID automatically when the \link NSFNanoObject::nanoObjectWithDictionary: NanoObject \endlink
|
125
|
+
is instantiated. This means that requesting the key from the \link NSFNanoObject::nanoObjectWithDictionary: NanoObject \endlink will return a valid UUID.
|
126
|
+
The same holds true for objects that inherit from NSFNanoObject. However, classes that implement the NSFNanoObjectProtocol protocol should
|
127
|
+
make sure they return a valid key via \link NSFNanoObjectProtocol::nanoObjectKey - (NSString *)nanoObjectKey \endlink
|
128
|
+
|
129
|
+
@warning
|
130
|
+
If an attempt is made to add or remove an object without a valid key, an exception of type \ref NSFGlobals::NSFNanoObjectBehaviorException
|
131
|
+
"NSFNanoObjectBehaviorException" will be raised.
|
132
|
+
|
133
|
+
To update an object, simply modify the object and add it to the document store. NanoStore will replace the existing object with the one being added.
|
134
|
+
|
135
|
+
@details <b>Example:</b>
|
136
|
+
@code
|
137
|
+
// Instantiate and open a NanoStore
|
138
|
+
NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
|
139
|
+
|
140
|
+
// Assuming the dictionary exists, instantiate a NanoObject
|
141
|
+
NSDictionary *info = ...;
|
142
|
+
NSFNanoObject *object = [NSFNanoObject nanoObjectWithDictionary:info];
|
143
|
+
|
144
|
+
// Add the NanoObject to the document store
|
145
|
+
[nanoStore addObject:object error:nil];
|
146
|
+
|
147
|
+
// Update the NanoObject with new data
|
148
|
+
[object setObject:@"foo" forKey:@"SomeKey"];
|
149
|
+
|
150
|
+
// Update the NanoObject in the document store
|
151
|
+
[nanoStore addObject:object error:nil];
|
152
|
+
@endcode
|
153
|
+
|
154
|
+
To remove an object, there are several options available. The most common methods are found in NSFNanoStore:
|
155
|
+
|
156
|
+
- \link NSFNanoStore::removeObject:error: - (BOOL)removeObject:(id <NSFNanoObjectProtocol>)theObject error:(out NSError **)outError \endlink
|
157
|
+
- \link NSFNanoStore::removeObjectsWithKeysInArray:error: - (BOOL)removeObjectsWithKeysInArray:(NSArray *)theKeys error:(out NSError **)outError \endlink
|
158
|
+
- \link NSFNanoStore::removeObjectsInArray:error: - (BOOL)removeObjectsInArray:(NSArray *)theObjects error:(out NSError **)outError \endlink
|
159
|
+
|
160
|
+
@details <b>Example:</b>
|
161
|
+
@code
|
162
|
+
// Instantiate and open a NanoStore
|
163
|
+
NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
|
164
|
+
|
165
|
+
// Assuming the dictionary exists, instantiate a NanoObject
|
166
|
+
NSDictionary *info = ...;
|
167
|
+
NSFNanoObject *object = [NSFNanoObject nanoObjectWithDictionary:info];
|
168
|
+
|
169
|
+
// Add the NanoObject to the document store
|
170
|
+
[nanoStore addObject:object error:nil];
|
171
|
+
|
172
|
+
// Remove the object
|
173
|
+
[nanoStore removeObject:object error:nil];
|
174
|
+
|
175
|
+
// ... or you could pass the key instead
|
176
|
+
[nanoStore removeObjectsWithKeysInArray:[NSArray arrayWithObjects:[object nanoObjectKey], nil] error:nil];
|
177
|
+
@endcode
|
178
|
+
*/
|
179
|
+
|
180
|
+
#import "NanoStore.h"
|
181
|
+
|
182
|
+
@interface NSFNanoObject : NSObject <NSFNanoObjectProtocol, NSCopying>
|
183
|
+
|
184
|
+
/** * The UUID of the NanoObject. */
|
185
|
+
@property (nonatomic, copy, readonly) NSString *key;
|
186
|
+
/** * The user-supplied information of the NanoObject. */
|
187
|
+
@property (nonatomic, copy, readonly) NSDictionary *info;
|
188
|
+
/** * The class name used to store the NanoObject. */
|
189
|
+
@property (nonatomic, copy, readonly) NSString *originalClassString;
|
190
|
+
|
191
|
+
/** @name Creating and Initializing a NanoObject
|
192
|
+
*/
|
193
|
+
|
194
|
+
//@{
|
195
|
+
|
196
|
+
/** * Creates and returns an empty NanoObject.
|
197
|
+
* @return An empty NanoObject upon success, nil otherwise.
|
198
|
+
*/
|
199
|
+
|
200
|
+
+ (NSFNanoObject*)nanoObject;
|
201
|
+
|
202
|
+
/** * Creates and returns a NanoObject with the given dictionary.
|
203
|
+
* @param theDictionary the information associated with the object. Must not be nil.
|
204
|
+
* @return An initialized object upon success, nil otherwise.
|
205
|
+
* @attention The dictionary must be serializable. For more information, please read the Property List Programming Guide.
|
206
|
+
* @see \link initFromDictionaryRepresentation: - (id)initFromDictionaryRepresentation:(NSDictionary *)theDictionary \endlink
|
207
|
+
*/
|
208
|
+
|
209
|
+
+ (NSFNanoObject*)nanoObjectWithDictionary:(NSDictionary *)theDictionary;
|
210
|
+
|
211
|
+
/** * Initializes a newly allocated NanoObject with the given dictionary.
|
212
|
+
* @param theDictionary the information associated with the object. Must not be nil.
|
213
|
+
* @return An initialized object upon success, nil otherwise.
|
214
|
+
* @attention The dictionary must be serializable. For more information, please read the Property List Programming Guide.
|
215
|
+
* @see \link nanoObjectWithDictionary: + (NSFNanoObject*)nanoObjectWithDictionary:(NSDictionary *)theDictionary \endlink
|
216
|
+
*/
|
217
|
+
|
218
|
+
- (id)initFromDictionaryRepresentation:(NSDictionary *)theDictionary;
|
219
|
+
|
220
|
+
//@}
|
221
|
+
|
222
|
+
/** @name Setting and Removing Contents
|
223
|
+
*/
|
224
|
+
|
225
|
+
//@{
|
226
|
+
|
227
|
+
/** * Adds a given key-value pair to the NanoObject.
|
228
|
+
* @param anObject the value for key. Must not be nil.
|
229
|
+
* @param aKey the key for value. Must not be nil.
|
230
|
+
* @note Raises an NSInvalidArgumentException if <i>aKey</i> or <i>anObject</i> is nil. If you need to represent a nil value in the dictionary, use NSNull.
|
231
|
+
* @see \link removeObjectForKey: - (void)removeObjectForKey:(NSString *)aKey \endlink
|
232
|
+
*/
|
233
|
+
|
234
|
+
- (void)setObject:(id)anObject forKey:(NSString *)aKey;
|
235
|
+
|
236
|
+
/** * Returns the value associated with a given key.
|
237
|
+
* @param aKey the key for value. Must not be nil.
|
238
|
+
* @note Raises an NSInvalidArgumentException if <i>aKey</i> or <i>anObject</i> is nil. If you need to represent a nil value in the dictionary, use NSNull.
|
239
|
+
* @see \link setObject:forKey: - (void)setObject:(id)anObject forKey:(NSString *)aKey \endlink
|
240
|
+
*/
|
241
|
+
|
242
|
+
- (id)objectForKey:(NSString *)aKey;
|
243
|
+
|
244
|
+
/** * Removes a given key and its associated value from the NanoObject.
|
245
|
+
* @param aKey the key to remove. Must not be nil.
|
246
|
+
* @note Does nothing if <i>aKey</i> does not exist.
|
247
|
+
* @see \link setObject:forKey: - (void)setObject:(id)anObject forKey:(NSString *)aKey \endlink
|
248
|
+
*/
|
249
|
+
|
250
|
+
- (void)removeObjectForKey:(NSString *)aKey;
|
251
|
+
|
252
|
+
/** * Empties the NanoObject of its entries.
|
253
|
+
* @see \link removeObjectForKey: - (void)removeObjectForKey:(NSString *)aKey \endlink
|
254
|
+
* @see \link removeObjectsForKeys: - (void)removeObjectsForKeys:(NSArray *)keyArray \endlink
|
255
|
+
*/
|
256
|
+
|
257
|
+
- (void)removeAllObjects;
|
258
|
+
|
259
|
+
/** * Removes from the NanoObject entries specified by elements in a given array.
|
260
|
+
* @param keyArray An array of objects specifying the keys to remove.
|
261
|
+
* @note If a key in <i>keyArray</i> does not exist, the entry is ignored.
|
262
|
+
* @see \link removeAllObjects - (void)removeAllObjects \endlink
|
263
|
+
* @see \link removeObjectForKey: - (void)removeObjectForKey:(NSString *)aKey \endlink
|
264
|
+
*/
|
265
|
+
|
266
|
+
- (void)removeObjectsForKeys:(NSArray *)keyArray;
|
267
|
+
|
268
|
+
//@}
|
269
|
+
|
270
|
+
/** @name Miscellaneous
|
271
|
+
*/
|
272
|
+
|
273
|
+
//@{
|
274
|
+
|
275
|
+
/** * Compares the receiving NanoObject to another NanoObject.
|
276
|
+
* @param otherNanoObject is a NanoObject.
|
277
|
+
* @return YES if the contents of otherNanoObject are equal to the contents of the receiving NanoObject, otherwise NO.
|
278
|
+
*/
|
279
|
+
|
280
|
+
- (BOOL)isEqualToNanoObject:(NSFNanoObject *)otherNanoObject;
|
281
|
+
|
282
|
+
/** * Returns a dictionary that contains the information stored in the object.
|
283
|
+
* @note Check properties info and key to find out the current state of the object.
|
284
|
+
* @see \link description - (NSString *)description \endlink
|
285
|
+
*/
|
286
|
+
|
287
|
+
- (NSDictionary *)dictionaryRepresentation;
|
288
|
+
|
289
|
+
/** * Returns a string representation of the bag.
|
290
|
+
* @note Check properties info and key to find out the current state of the object.
|
291
|
+
* @see \link dictionaryRepresentation - (NSString *)dictionaryRepresentation \endlink
|
292
|
+
*/
|
293
|
+
|
294
|
+
- (NSString *)description;
|
295
|
+
|
296
|
+
//@}
|
297
|
+
|
298
|
+
@end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
/*
|
2
|
+
NSFNanoObject.m
|
3
|
+
NanoStore
|
4
|
+
|
5
|
+
Copyright (c) 2010 Webbo, L.L.C. All rights reserved.
|
6
|
+
|
7
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
8
|
+
provided that the following conditions are met:
|
9
|
+
|
10
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
11
|
+
and the following disclaimer.
|
12
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
13
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
14
|
+
* Neither the name of Webbo nor the names of its contributors may be used to endorse or promote
|
15
|
+
products derived from this software without specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
18
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
19
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
|
20
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
21
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
23
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
24
|
+
SUCH DAMAGE.
|
25
|
+
*/
|
26
|
+
|
27
|
+
#import "NSFNanoObject.h"
|
28
|
+
#import "NSFNanoObject_Private.h"
|
29
|
+
#import "NSFNanoGlobals_Private.h"
|
30
|
+
|
31
|
+
@implementation NSFNanoObject
|
32
|
+
{
|
33
|
+
NSMutableDictionary *info;
|
34
|
+
}
|
35
|
+
|
36
|
+
@synthesize info, key, originalClassString;
|
37
|
+
|
38
|
+
+ (NSFNanoObject*)nanoObject
|
39
|
+
{
|
40
|
+
NSString *theKey = [NSFNanoEngine stringWithUUID];
|
41
|
+
return [[self alloc]initNanoObjectFromDictionaryRepresentation:nil forKey:theKey store:nil];
|
42
|
+
}
|
43
|
+
|
44
|
+
+ (NSFNanoObject*)nanoObjectWithDictionary:(NSDictionary *)aDictionary
|
45
|
+
{
|
46
|
+
NSString *theKey = [NSFNanoEngine stringWithUUID];
|
47
|
+
return [[self alloc]initNanoObjectFromDictionaryRepresentation:aDictionary forKey:theKey store:nil];
|
48
|
+
}
|
49
|
+
|
50
|
+
- (id)initFromDictionaryRepresentation:(NSDictionary *)aDictionary
|
51
|
+
{
|
52
|
+
NSString *theKey = [NSFNanoEngine stringWithUUID];
|
53
|
+
return [self initNanoObjectFromDictionaryRepresentation:aDictionary forKey:theKey store:nil];
|
54
|
+
}
|
55
|
+
|
56
|
+
- (NSString*)description
|
57
|
+
{
|
58
|
+
NSMutableString *description = [NSMutableString string];
|
59
|
+
|
60
|
+
[description appendString:@"\n"];
|
61
|
+
[description appendString:[NSString stringWithFormat:@"NanoObject address : 0x%x\n", self]];
|
62
|
+
[description appendString:[NSString stringWithFormat:@"Original class : %@\n", (nil != originalClassString) ? originalClassString : NSStringFromClass ([self class])]];
|
63
|
+
[description appendString:[NSString stringWithFormat:@"Key : %@\n", key]];
|
64
|
+
[description appendString:[NSString stringWithFormat:@"Info : %ld key/value pairs\n", [info count]]];
|
65
|
+
|
66
|
+
return description;
|
67
|
+
}
|
68
|
+
|
69
|
+
- (void)setObject:(id)anObject forKey:(NSString *)aKey
|
70
|
+
{
|
71
|
+
[info setObject:anObject forKey:aKey];
|
72
|
+
}
|
73
|
+
|
74
|
+
- (id)objectForKey:(NSString *)aKey
|
75
|
+
{
|
76
|
+
return [info objectForKey:aKey];
|
77
|
+
}
|
78
|
+
|
79
|
+
- (void)removeObjectForKey:(NSString *)aKey
|
80
|
+
{
|
81
|
+
[info removeObjectForKey:aKey];
|
82
|
+
}
|
83
|
+
|
84
|
+
- (void)removeAllObjects
|
85
|
+
{
|
86
|
+
[info removeAllObjects];
|
87
|
+
}
|
88
|
+
|
89
|
+
- (void)removeObjectsForKeys:(NSArray *)keyArray
|
90
|
+
{
|
91
|
+
[info removeObjectsForKeys:keyArray];
|
92
|
+
}
|
93
|
+
|
94
|
+
- (BOOL)isEqualToNanoObject:(NSFNanoObject *)otherNanoObject
|
95
|
+
{
|
96
|
+
if (self == otherNanoObject) {
|
97
|
+
return YES;
|
98
|
+
}
|
99
|
+
|
100
|
+
BOOL success = YES;
|
101
|
+
|
102
|
+
if (originalClassString != otherNanoObject.originalClassString) {
|
103
|
+
if (NO == [originalClassString isEqualToString:otherNanoObject.originalClassString]) {
|
104
|
+
success = NO;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
if (YES == success) {
|
109
|
+
success = [info isEqualToDictionary:otherNanoObject.info];
|
110
|
+
}
|
111
|
+
|
112
|
+
return success;
|
113
|
+
}
|
114
|
+
|
115
|
+
- (NSDictionary *)dictionaryRepresentation
|
116
|
+
{
|
117
|
+
return self.info;
|
118
|
+
}
|
119
|
+
|
120
|
+
/** \cond */
|
121
|
+
|
122
|
+
- (id)init
|
123
|
+
{
|
124
|
+
if ((self = [super init])) {
|
125
|
+
key = nil;
|
126
|
+
info = [NSMutableDictionary new];
|
127
|
+
originalClassString = nil;
|
128
|
+
}
|
129
|
+
|
130
|
+
return self;
|
131
|
+
}
|
132
|
+
|
133
|
+
#pragma mark -
|
134
|
+
|
135
|
+
- (id)initNanoObjectFromDictionaryRepresentation:(NSDictionary *)aDictionary forKey:(NSString *)aKey store:(NSFNanoStore *)aStore
|
136
|
+
{
|
137
|
+
// We allow a nil dictionary because: 1) it's interpreted as empty and 2) reduces memory consumption on the caller if no data is being passed.
|
138
|
+
|
139
|
+
if (nil == aKey)
|
140
|
+
[[NSException exceptionWithName:NSFUnexpectedParameterException
|
141
|
+
reason:[NSString stringWithFormat:@"*** -[%@ %s]: aKey is nil.", [self class], _cmd]
|
142
|
+
userInfo:nil]raise];
|
143
|
+
|
144
|
+
if ((self = [self init])) {
|
145
|
+
[info addEntriesFromDictionary:aDictionary];
|
146
|
+
key = [aKey copy];
|
147
|
+
}
|
148
|
+
|
149
|
+
return self;
|
150
|
+
}
|
151
|
+
|
152
|
+
- (id)copyWithZone:(NSZone *)zone
|
153
|
+
{
|
154
|
+
NSFNanoObject *copy = [[[self class]allocWithZone:zone]initNanoObjectFromDictionaryRepresentation:[self dictionaryRepresentation] forKey:[NSFNanoEngine stringWithUUID] store:nil];
|
155
|
+
return copy;
|
156
|
+
}
|
157
|
+
|
158
|
+
|
159
|
+
- (NSDictionary *)nanoObjectDictionaryRepresentation
|
160
|
+
{
|
161
|
+
return [self dictionaryRepresentation];
|
162
|
+
}
|
163
|
+
|
164
|
+
- (NSString *)nanoObjectKey
|
165
|
+
{
|
166
|
+
return self.key;
|
167
|
+
}
|
168
|
+
|
169
|
+
- (id)rootObject
|
170
|
+
{
|
171
|
+
return info;
|
172
|
+
}
|
173
|
+
|
174
|
+
#pragma mark -
|
175
|
+
#pragma mark Private Methods
|
176
|
+
#pragma mark -
|
177
|
+
|
178
|
+
- (void)_setOriginalClassString:(NSString *)theClassString
|
179
|
+
{
|
180
|
+
if (originalClassString != theClassString) {
|
181
|
+
originalClassString = theClassString;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
/** \endcond */
|
186
|
+
|
187
|
+
@end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
/*
|
2
|
+
NSFNanoObjectProtocol.h
|
3
|
+
NanoStore
|
4
|
+
|
5
|
+
Copyright (c) 2010 Webbo, L.L.C. All rights reserved.
|
6
|
+
|
7
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
8
|
+
provided that the following conditions are met:
|
9
|
+
|
10
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
11
|
+
and the following disclaimer.
|
12
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
13
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
14
|
+
* Neither the name of Webbo nor the names of its contributors may be used to endorse or promote
|
15
|
+
products derived from this software without specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
18
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
19
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
|
20
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
21
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
23
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
24
|
+
SUCH DAMAGE.
|
25
|
+
*/
|
26
|
+
|
27
|
+
/*! @file NSFNanoObjectProtocol.h
|
28
|
+
@brief A protocol declaring the interface that objects interfacing with NanoStore must implement.
|
29
|
+
*/
|
30
|
+
|
31
|
+
/** @protocol NSFNanoObjectProtocol
|
32
|
+
* A protocol declaring the interface that objects interfacing with NanoStore must implement.
|
33
|
+
*
|
34
|
+
* @note
|
35
|
+
* Check NSFNanoBag or NSFNanoObject to see a concrete example of how NSFNanoObjectProtocol is implemented.
|
36
|
+
*/
|
37
|
+
|
38
|
+
@class NSFNanoStore;
|
39
|
+
|
40
|
+
@protocol NSFNanoObjectProtocol
|
41
|
+
|
42
|
+
@required
|
43
|
+
|
44
|
+
/** * Initializes a newly allocated object containing a given key and value associated with a document store.
|
45
|
+
* @param theDictionary the information associated with the object.
|
46
|
+
* @param aKey the key associated with the information.
|
47
|
+
* @param theStore the document store where the object is stored.
|
48
|
+
* @return An initialized object upon success, nil otherwise.
|
49
|
+
* @details <b>Example:</b>
|
50
|
+
@code
|
51
|
+
- (id)initNanoObjectFromDictionaryRepresentation:(NSDictionary *)aDictionary forKey:(NSString *)aKey store:(NSFNanoStore *)aStore
|
52
|
+
{
|
53
|
+
if (self = [self init]) {
|
54
|
+
info = [aDictionary retain];
|
55
|
+
key = [aKey copy];
|
56
|
+
}
|
57
|
+
|
58
|
+
return self;
|
59
|
+
}
|
60
|
+
@endcode
|
61
|
+
*/
|
62
|
+
|
63
|
+
- (id)initNanoObjectFromDictionaryRepresentation:(NSDictionary *)theDictionary forKey:(NSString *)aKey store:(NSFNanoStore *)theStore;
|
64
|
+
|
65
|
+
/** * Returns a dictionary that contains the information stored in the object.
|
66
|
+
* @see \link nanoObjectKey - (NSString *)nanoObjectKey \endlink
|
67
|
+
*/
|
68
|
+
|
69
|
+
- (NSDictionary *)nanoObjectDictionaryRepresentation;
|
70
|
+
|
71
|
+
/** * Returns the key associated with the object.
|
72
|
+
* @note
|
73
|
+
* The class NSFNanoEngine contains a convenience method for this purpose: \ref NSFNanoEngine::stringWithUUID "+(NSString*)stringWithUUID"
|
74
|
+
*
|
75
|
+
* @see \link nanoObjectDictionaryRepresentation - (NSDictionary *)nanoObjectDictionaryRepresentation \endlink
|
76
|
+
*/
|
77
|
+
|
78
|
+
- (NSString *)nanoObjectKey;
|
79
|
+
|
80
|
+
/** * Returns a reference to the object holding the private data or information that will be used for sorting.
|
81
|
+
* Most custom objects will return <i>self</i>, as is the case for NSFNanoBag. Since we can sort a bag by <i>name</i>, <i>key</i> or <i>hasUnsavedChanges</i>,
|
82
|
+
* NanoStore requires a hint to find the attribute. This hint is the root object, which KVC uses to perform the sort. Taking NSFNanoBag as an example:
|
83
|
+
@code
|
84
|
+
@interface NSFNanoBag : NSObject <NSFNanoObjectProtocol, NSCopying>
|
85
|
+
{
|
86
|
+
NSFNanoStore *store;
|
87
|
+
NSString *name;
|
88
|
+
NSString *key;
|
89
|
+
BOOL hasUnsavedChanges;
|
90
|
+
}
|
91
|
+
@endcode
|
92
|
+
* The implementation of <i>rootObject</i> would look like so:
|
93
|
+
@code
|
94
|
+
- (id)rootObject
|
95
|
+
{
|
96
|
+
return self;
|
97
|
+
}
|
98
|
+
@endcode
|
99
|
+
* Other objects may point directly to the collection that holds the information. NSFNanoObject stores all its data in the <i>info</i> dictionary, so the
|
100
|
+
* implementation looks like this:
|
101
|
+
@code
|
102
|
+
- (id)rootObject
|
103
|
+
{
|
104
|
+
return info;
|
105
|
+
}
|
106
|
+
@endcode
|
107
|
+
* Assuming that <i>info</i> contains a key named <i>City</i>, we would specify a NSFNanoSortDescriptor which would sort the cities like so:
|
108
|
+
@code
|
109
|
+
NSFNanoSortDescriptor *sortedCities = [[NSFNanoSortDescriptor alloc]initWithAttribute:@"City" ascending:YES];
|
110
|
+
@endcode
|
111
|
+
* If we had returned <i>self</i> as the root object, the sort descriptor would have to be written like so:
|
112
|
+
@code
|
113
|
+
NSFNanoSortDescriptor *sortedCities = [[NSFNanoSortDescriptor alloc]initWithAttribute:@"info.City" ascending:YES];
|
114
|
+
@endcode
|
115
|
+
*/
|
116
|
+
|
117
|
+
- (id)rootObject;
|
118
|
+
|
119
|
+
@end
|