nano-store 0.2.3

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 (57) hide show
  1. data/.gitignore +3 -0
  2. data/.gitmodules +3 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +193 -0
  7. data/Rakefile +1 -0
  8. data/app/app_delegate.rb +5 -0
  9. data/lib/nano-store.rb +1 -0
  10. data/lib/nano_store/bag.rb +98 -0
  11. data/lib/nano_store/model.rb +142 -0
  12. data/lib/nano_store/nano_store.rb +36 -0
  13. data/lib/nano_store/store_extension.rb +150 -0
  14. data/lib/nano_store/version.rb +3 -0
  15. data/lib/nano_store.rb +14 -0
  16. data/nano-store.gemspec +17 -0
  17. data/resources/.gitignore +0 -0
  18. data/spec/bag_spec.rb +66 -0
  19. data/spec/model_spec.rb +130 -0
  20. data/spec/nano_store_spec.rb +48 -0
  21. data/spec/store_extension_spec.rb +110 -0
  22. data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.h +542 -0
  23. data/vendor/NanoStore/Classes/Advanced/NSFNanoEngine.m +1781 -0
  24. data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.h +137 -0
  25. data/vendor/NanoStore/Classes/Advanced/NSFNanoResult.m +265 -0
  26. data/vendor/NanoStore/Classes/Private/NSFNanoBag_Private.h +37 -0
  27. data/vendor/NanoStore/Classes/Private/NSFNanoEngine_Private.h +69 -0
  28. data/vendor/NanoStore/Classes/Private/NSFNanoExpression_Private.h +35 -0
  29. data/vendor/NanoStore/Classes/Private/NSFNanoGlobals_Private.h +99 -0
  30. data/vendor/NanoStore/Classes/Private/NSFNanoObject_Private.h +35 -0
  31. data/vendor/NanoStore/Classes/Private/NSFNanoPredicate_Private.h +35 -0
  32. data/vendor/NanoStore/Classes/Private/NSFNanoResult_Private.h +43 -0
  33. data/vendor/NanoStore/Classes/Private/NSFNanoSearch_Private.h +48 -0
  34. data/vendor/NanoStore/Classes/Private/NSFNanoStore_Private.h +57 -0
  35. data/vendor/NanoStore/Classes/Private/NanoStore_Private.h +37 -0
  36. data/vendor/NanoStore/Classes/Public/NSFNanoBag.h +306 -0
  37. data/vendor/NanoStore/Classes/Public/NSFNanoBag.m +485 -0
  38. data/vendor/NanoStore/Classes/Public/NSFNanoExpression.h +125 -0
  39. data/vendor/NanoStore/Classes/Public/NSFNanoExpression.m +103 -0
  40. data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.h +323 -0
  41. data/vendor/NanoStore/Classes/Public/NSFNanoGlobals.m +145 -0
  42. data/vendor/NanoStore/Classes/Public/NSFNanoObject.h +298 -0
  43. data/vendor/NanoStore/Classes/Public/NSFNanoObject.m +187 -0
  44. data/vendor/NanoStore/Classes/Public/NSFNanoObjectProtocol.h +119 -0
  45. data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.h +123 -0
  46. data/vendor/NanoStore/Classes/Public/NSFNanoPredicate.m +130 -0
  47. data/vendor/NanoStore/Classes/Public/NSFNanoSearch.h +381 -0
  48. data/vendor/NanoStore/Classes/Public/NSFNanoSearch.m +835 -0
  49. data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.h +124 -0
  50. data/vendor/NanoStore/Classes/Public/NSFNanoSortDescriptor.m +79 -0
  51. data/vendor/NanoStore/Classes/Public/NSFNanoStore.h +475 -0
  52. data/vendor/NanoStore/Classes/Public/NSFNanoStore.m +1375 -0
  53. data/vendor/NanoStore/Classes/Public/NanoStore.h +463 -0
  54. data/vendor/NanoStore/LICENSE +25 -0
  55. data/vendor/NanoStore/NanoStore.bridgesupport +1215 -0
  56. data/vendor/NanoStore/README.md +411 -0
  57. metadata +118 -0
@@ -0,0 +1,485 @@
1
+ /*
2
+ NSFNanoBag.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 "NSFNanoBag.h"
28
+ #import "NSFNanoBag_Private.h"
29
+ #import "NSFNanoGlobals.h"
30
+ #import "NSFNanoGlobals_Private.h"
31
+ #import "NSFNanoStore_Private.h"
32
+ #import "NSFNanoSearch_Private.h"
33
+
34
+ @implementation NSFNanoBag
35
+ {
36
+ @protected
37
+ /** \cond */
38
+ NSMutableDictionary *savedObjects;
39
+ NSMutableDictionary *unsavedObjects;
40
+ NSMutableDictionary *removedObjects;
41
+ /** \endcond */
42
+ }
43
+
44
+ @synthesize store, name, key, savedObjects, unsavedObjects, removedObjects, hasUnsavedChanges;
45
+
46
+ + (NSFNanoBag*)bag
47
+ {
48
+ return [[self alloc]initBagWithName:nil andObjects:[NSArray array]];
49
+ }
50
+
51
+ + (NSFNanoBag*)bagWithObjects:(NSArray *)someObjects
52
+ {
53
+ return [[self alloc]initBagWithName:nil andObjects:someObjects];
54
+ }
55
+
56
+ + bagWithName:(NSString *)theName
57
+ {
58
+ return [[self alloc]initBagWithName:theName andObjects:[NSArray array]];
59
+ }
60
+
61
+ + bagWithName:(NSString *)theName andObjects:(NSArray *)someObjects
62
+ {
63
+ return [[self alloc]initBagWithName:theName andObjects:someObjects];
64
+ }
65
+
66
+ - (id)initBagWithName:(NSString *)theName andObjects:(NSArray *)someObjects
67
+ {
68
+ if ((self = [self init])) {
69
+ NSError *outError = nil;
70
+ if (NO == [self addObjectsFromArray:someObjects error:&outError]) {
71
+ NSLog(@"%@", [NSString stringWithFormat:@"*** -[%@ %s]: a problem occurred while initializing the NanoBag, leaving it in an inconsistent state. Reason: %@.", [self class], _cmd, [outError localizedDescription]]);
72
+ }
73
+
74
+ name = [theName copy];
75
+ hasUnsavedChanges = YES;
76
+ }
77
+
78
+ return self;
79
+ }
80
+
81
+ /** \cond */
82
+
83
+ - (id)init
84
+ {
85
+ if ((self = [super init])) {
86
+ key = [NSFNanoEngine stringWithUUID];
87
+ savedObjects = [NSMutableDictionary new];
88
+ unsavedObjects = [NSMutableDictionary new];
89
+ removedObjects = [NSMutableDictionary new];
90
+
91
+ hasUnsavedChanges = NO;
92
+ }
93
+
94
+ return self;
95
+ }
96
+
97
+ - (id)copyWithZone:(NSZone *)zone
98
+ {
99
+ NSFNanoBag *copy = [[[self class]allocWithZone:zone]initNanoObjectFromDictionaryRepresentation:[self dictionaryRepresentation] forKey:[NSFNanoEngine stringWithUUID] store:store];
100
+ return copy;
101
+ }
102
+
103
+
104
+ - (id)rootObject
105
+ {
106
+ return self;
107
+ }
108
+
109
+ #pragma mark -
110
+
111
+ - (void)setName:(NSString *)aName
112
+ {
113
+ name = [aName copy];
114
+ hasUnsavedChanges = YES;
115
+ }
116
+
117
+ /** \endcond */
118
+
119
+ - (NSString *)name
120
+ {
121
+ return name;
122
+ }
123
+
124
+ - (NSUInteger)count
125
+ {
126
+ return savedObjects.count + unsavedObjects.count;
127
+ }
128
+
129
+ - (NSString*)description
130
+ {
131
+ NSMutableString *description = [NSMutableString string];
132
+
133
+ [description appendString:@"\n"];
134
+ [description appendString:[NSString stringWithFormat:@"NanoBag address : 0x%x\n", self]];
135
+ [description appendString:[NSString stringWithFormat:@"Name : %@\n", (nil != name) ? name : @"<untitled>"]];
136
+ [description appendString:[NSString stringWithFormat:@"Document store : 0x%x\n", store]];
137
+ [description appendString:[NSString stringWithFormat:@"Has unsaved changes? : %@\n", (hasUnsavedChanges ? @"YES" : @"NO")]];
138
+ [description appendString:[NSString stringWithFormat:@"Saved objects : %ld key/value pairs\n", [savedObjects count]]];
139
+ [description appendString:[NSString stringWithFormat:@"Unsaved objects : %ld key/value pairs\n", [unsavedObjects count]]];
140
+ [description appendString:[NSString stringWithFormat:@"Removed objects : %ld key/value pairs\n", [removedObjects count]]];
141
+
142
+ return description;
143
+ }
144
+
145
+ - (BOOL)isEqualToNanoBag:(NSFNanoBag *)otherNanoBag
146
+ {
147
+ if (self == otherNanoBag) {
148
+ return YES;
149
+ }
150
+
151
+ BOOL success = YES;
152
+
153
+ NSArray *sortedArraySelf = [[[self savedObjects]allKeys]sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
154
+ NSArray *sortedArrayOther = [[[otherNanoBag savedObjects]allKeys]sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
155
+ if (NO == [sortedArraySelf isEqualToArray:sortedArrayOther]) {
156
+ success = NO;
157
+ } else {
158
+ sortedArraySelf = [[[self unsavedObjects]allKeys]sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
159
+ sortedArrayOther = [[[otherNanoBag unsavedObjects]allKeys]sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
160
+ if (NO == [sortedArraySelf isEqualToArray:sortedArrayOther]) {
161
+ success = NO;
162
+ } else {
163
+ sortedArraySelf = [[[self removedObjects]allKeys]sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
164
+ sortedArrayOther = [[[otherNanoBag removedObjects]allKeys]sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
165
+ if (NO == [sortedArraySelf isEqualToArray:sortedArrayOther]) {
166
+ success = NO;
167
+ }
168
+ }
169
+ }
170
+
171
+ return success;
172
+ }
173
+
174
+ - (NSDictionary *)dictionaryRepresentation
175
+ {
176
+ // Iterate the objects collecting the object keys
177
+ NSMutableArray *objectKeys = [NSMutableArray new];
178
+ for (NSString *objectKey in self.savedObjects) {
179
+ [objectKeys addObject:objectKey];
180
+ }
181
+ for (NSString *objectKey in self.unsavedObjects) {
182
+ [objectKeys addObject:objectKey];
183
+ }
184
+
185
+ NSMutableDictionary *info = [NSMutableDictionary dictionary];
186
+
187
+ if (nil != name) {
188
+ [info setObject:name forKey:NSF_Private_NSFNanoBag_Name];
189
+ }
190
+ [info setObject:self.key forKey:NSF_Private_NSFNanoBag_NSFKey];
191
+ [info setObject:objectKeys forKey:NSF_Private_NSFNanoBag_NSFObjectKeys];
192
+
193
+ return info;
194
+ }
195
+
196
+ #pragma mark -
197
+
198
+ - (BOOL)addObject:(id <NSFNanoObjectProtocol>)object error:(out NSError **)outError
199
+ {
200
+ if (NO == [(id)object conformsToProtocol:@protocol(NSFNanoObjectProtocol)]) {
201
+ [[NSException exceptionWithName:NSFNonConformingNanoObjectProtocolException
202
+ reason:[NSString stringWithFormat:@"*** -[%@ %s]: the object does not conform to NSFNanoObjectProtocol.", [self class], _cmd]
203
+ userInfo:nil]raise];
204
+ }
205
+
206
+ NSString *objectKey = [(id)object nanoObjectKey];
207
+ NSDictionary *info = [(id)object dictionaryRepresentation];
208
+
209
+ if (objectKey && info) {
210
+ [savedObjects removeObjectForKey:objectKey];
211
+ [unsavedObjects setObject:object forKey:objectKey];
212
+ [removedObjects removeObjectForKey:objectKey];
213
+ hasUnsavedChanges = YES;
214
+ } else {
215
+ NSString *message = nil;
216
+ if (nil == objectKey)
217
+ message = [NSString stringWithFormat:@"*** -[%@ %s]: unexpected NSFNanoObject behavior. Reason: the object's key is nil.", [self class], _cmd];
218
+ else
219
+ message = [NSString stringWithFormat:@"*** -[%@ %s]: unexpected NSFNanoObject behavior. Reason: the object's dictionary is nil.", [self class], _cmd];
220
+
221
+ [[NSException exceptionWithName:NSFNanoObjectBehaviorException reason:message userInfo:nil]raise];
222
+ }
223
+
224
+ return YES;
225
+ }
226
+
227
+ - (BOOL)addObjectsFromArray:(NSArray *)someObjects error:(out NSError **)outError
228
+ {
229
+ if (nil == someObjects) {
230
+ if (nil != outError) {
231
+ *outError = [NSError errorWithDomain:NSFDomainKey
232
+ code:NSFNanoStoreErrorKey
233
+ userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %s]: the object cannot be added because the list provided is nil.", [self class], _cmd]
234
+ forKey:NSLocalizedFailureReasonErrorKey]];
235
+ }
236
+ return NO;
237
+ }
238
+
239
+ BOOL success = YES;
240
+
241
+ for (id object in someObjects) {
242
+ if (NO == [self addObject:object error:outError]) {
243
+ success = NO;
244
+ }
245
+ }
246
+
247
+ return success;
248
+ }
249
+
250
+ - (void)removeObject:(id <NSFNanoObjectProtocol>)object
251
+ {
252
+ if (NO == [(id)object conformsToProtocol:@protocol(NSFNanoObjectProtocol)]) {
253
+ [[NSException exceptionWithName:NSFNonConformingNanoObjectProtocolException
254
+ reason:[NSString stringWithFormat:@"*** -[%@ %s]: the object does not conform to NSFNanoObjectProtocol.", [self class], _cmd]
255
+ userInfo:nil]raise];
256
+ }
257
+
258
+ [self removeObjectWithKey:[(id)object nanoObjectKey]];
259
+ }
260
+
261
+ - (void)removeAllObjects
262
+ {
263
+ NSMutableDictionary *objects = [[NSMutableDictionary alloc]initWithCapacity:(savedObjects.count + removedObjects.count)];
264
+
265
+ // Save the object and its key
266
+ for (id object in savedObjects) {
267
+ [objects setObject:object forKey:[object performSelector:@selector(key)]];
268
+ }
269
+
270
+ // Save the previously removed objects (if any)
271
+ [objects addEntriesFromDictionary:removedObjects];
272
+
273
+ [savedObjects removeAllObjects];
274
+ [unsavedObjects removeAllObjects];
275
+ [removedObjects setDictionary:objects];
276
+ hasUnsavedChanges = YES;
277
+
278
+ }
279
+
280
+ - (void)removeObjectsInArray:(NSArray *)someObjects
281
+ {
282
+ for (id object in someObjects) {
283
+ [self removeObject:object];
284
+ }
285
+ }
286
+
287
+ - (void)removeObjectWithKey:(NSString *)objectKey
288
+ {
289
+ if (nil == objectKey) {
290
+ [[NSException exceptionWithName:NSFNanoObjectBehaviorException
291
+ reason:[NSString stringWithFormat:@"*** -[%@ %s]: unexpected NSFNanoObject behavior. Reason: the object's key is nil.", [self class], _cmd]
292
+ userInfo:nil]raise];
293
+ }
294
+
295
+ // Is the object an existing one?
296
+ id object = [savedObjects objectForKey:objectKey];
297
+ if (nil != object) {
298
+ [savedObjects removeObjectForKey:objectKey];
299
+ } else {
300
+ // Is the object still unsaved?
301
+ object = [unsavedObjects objectForKey:objectKey];
302
+ if (nil != object) {
303
+ [unsavedObjects removeObjectForKey:objectKey];
304
+ }
305
+ }
306
+
307
+ if (nil == object) {
308
+ // The object doesn't exist, so there is no need to mark the bag as dirty
309
+ } else {
310
+ [removedObjects setObject:object forKey:objectKey];
311
+ hasUnsavedChanges = YES;
312
+ }
313
+ }
314
+
315
+ - (void)removeObjectsWithKeysInArray:(NSArray *)someKeys
316
+ {
317
+ for (NSString *objectKey in someKeys) {
318
+ [self removeObjectWithKey:objectKey];
319
+ }
320
+ }
321
+
322
+ - (BOOL)saveAndReturnError:(out NSError **)outError
323
+ {
324
+ if (NO == self.hasUnsavedChanges) {
325
+ return YES;
326
+ }
327
+
328
+ if (nil == store) {
329
+ if (nil != outError) {
330
+ *outError = [NSError errorWithDomain:NSFDomainKey
331
+ code:NSFNanoStoreErrorKey
332
+ userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %s]: unable to save the bag. Reason: the store has not been set.", [self class], _cmd]
333
+ forKey:NSLocalizedFailureReasonErrorKey]];
334
+ }
335
+ return NO;
336
+ }
337
+
338
+ return [self _saveInStore:store error:outError];
339
+ }
340
+
341
+ #pragma mark -
342
+
343
+ - (void)deflateBag
344
+ {
345
+ NSArray *savedObjectsCopy = [[NSArray alloc]initWithArray:[savedObjects allKeys]];
346
+
347
+ for (id saveObjectKey in savedObjectsCopy) {
348
+ [savedObjects setObject:[NSNull null] forKey:saveObjectKey];
349
+ }
350
+
351
+ }
352
+
353
+ - (void)inflateBag
354
+ {
355
+ NSArray *objectKeys = [savedObjects allKeys];
356
+ [self _inflateObjectsWithKeys:objectKeys];
357
+ }
358
+
359
+ - (BOOL)reloadBagWithError:(out NSError **)outError
360
+ {
361
+ // If the bag is not associated to a document store, there is no need to continue
362
+ if (nil == store) {
363
+ return YES;
364
+ }
365
+
366
+ // Refresh the bag to match the contents stored on the database
367
+ [self _inflateObjectsWithKeys:[NSArray arrayWithObject:key]];
368
+ NSFNanoBag *savedBag = [savedObjects objectForKey:key];
369
+ if (nil != savedBag) {
370
+ [savedObjects removeAllObjects];
371
+ [savedObjects addEntriesFromDictionary:savedBag.savedObjects];
372
+ for (NSString *objectKey in unsavedObjects) {
373
+ [savedObjects removeObjectForKey:objectKey];
374
+ }
375
+ } else {
376
+ if (nil != outError) {
377
+ *outError = [NSError errorWithDomain:NSFDomainKey
378
+ code:NSFNanoStoreErrorKey
379
+ userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"*** -[%@ %s]: the bag could not be refreshed.", [self class], _cmd]
380
+ forKey:NSLocalizedFailureReasonErrorKey]];
381
+ }
382
+ return NO;
383
+ }
384
+
385
+ return YES;
386
+ }
387
+
388
+ - (BOOL)undoChangesWithError:(out NSError **)outError
389
+ {
390
+ [savedObjects removeAllObjects];
391
+ [unsavedObjects removeAllObjects];
392
+ [removedObjects removeAllObjects];
393
+
394
+ hasUnsavedChanges = NO;
395
+
396
+ return [self reloadBagWithError:outError];
397
+ }
398
+
399
+ #pragma mark -
400
+ #pragma mark Private Methods
401
+ #pragma mark -
402
+
403
+ /** \cond */
404
+
405
+ - (id)initNanoObjectFromDictionaryRepresentation:(NSDictionary *)dictionary forKey:(NSString *)aKey store:(NSFNanoStore *)aStore
406
+ {
407
+ if ((self = [self init])) {
408
+ name = [[dictionary objectForKey:NSF_Private_NSFNanoBag_Name]copy];
409
+ store = aStore;
410
+ key = aKey;
411
+ savedObjects = [NSMutableDictionary new];
412
+ unsavedObjects = [NSMutableDictionary new];
413
+ removedObjects = [NSMutableDictionary new];
414
+
415
+ NSArray *objectKeys = [dictionary objectForKey:NSF_Private_NSFNanoBag_NSFObjectKeys];
416
+
417
+ [self _inflateObjectsWithKeys:objectKeys];
418
+
419
+ hasUnsavedChanges = NO;
420
+ }
421
+
422
+ return self;
423
+ }
424
+
425
+ - (NSDictionary *)nanoObjectDictionaryRepresentation
426
+ {
427
+ return [self dictionaryRepresentation];
428
+ }
429
+
430
+ - (NSString *)nanoObjectKey
431
+ {
432
+ return key;
433
+ }
434
+
435
+ - (void)_setStore:(NSFNanoStore *)aStore
436
+ {
437
+ store = aStore;
438
+ }
439
+
440
+ - (BOOL)_saveInStore:(NSFNanoStore *)someStore error:(out NSError **)outError
441
+ {
442
+ // Save the unsaved objects first...
443
+ NSArray *contentsToBeSaved = [unsavedObjects allValues];
444
+ if ([contentsToBeSaved count] > 0) {
445
+ [someStore _addObjectsFromArray:contentsToBeSaved forceSave:YES error:outError];
446
+ }
447
+
448
+ // Move the existing objects to the unsaved list, in order to save the bag
449
+ [unsavedObjects addEntriesFromDictionary:savedObjects];
450
+ [savedObjects removeAllObjects];
451
+ [removedObjects removeAllObjects];
452
+
453
+ // Save the unsaved bag...
454
+ BOOL success = [someStore _addObjectsFromArray:[NSArray arrayWithObject:self] forceSave:YES error:outError];
455
+
456
+ if (YES == success) {
457
+ [unsavedObjects removeAllObjects];
458
+ success = [self reloadBagWithError:outError];
459
+ if (YES == success) {
460
+ hasUnsavedChanges = NO;
461
+ }
462
+ return success;
463
+ }
464
+
465
+ return success;
466
+ }
467
+
468
+ - (void)_inflateObjectsWithKeys:(NSArray *)someKeys
469
+ {
470
+ if ([someKeys count] != 0) {
471
+ NSFNanoSearch *search = [NSFNanoSearch searchWithStore:store];
472
+ NSString *quotedString = [NSFNanoSearch _quoteStrings:someKeys joiningWithDelimiter:@","];
473
+ NSString *theSQLStatement = [NSString stringWithFormat:@"SELECT NSFKey, NSFPlist, NSFObjectClass FROM NSFKeys WHERE NSFKey IN (%@)", quotedString];
474
+
475
+ NSDictionary *results = [search executeSQL:theSQLStatement returnType:NSFReturnObjects error:nil];
476
+
477
+ if (nil != results) {
478
+ [savedObjects addEntriesFromDictionary:results];
479
+ }
480
+ }
481
+ }
482
+
483
+ /** \endcond */
484
+
485
+ @end
@@ -0,0 +1,125 @@
1
+ /*
2
+ NSFNanoExpression.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
+ #import <Foundation/Foundation.h>
28
+
29
+ #import "NSFNanoGlobals.h"
30
+
31
+ @class NSFNanoPredicate;
32
+
33
+ /*! @file NSFNanoExpression.h
34
+ @brief A unit that describes a series of predicates and its operators.
35
+ */
36
+
37
+ /** @class NSFNanoExpression
38
+ * A unit that describes a series of predicates and its operators.
39
+ * @details <b>Example:</b>
40
+ @code
41
+ // Instantiate a NanoStore and open it
42
+ NSFNanoStore *nanoStore = [NSFNanoStore createAndOpenStoreWithType:NSFMemoryStoreType path:nil error:nil];
43
+
44
+ // Prepare the expression
45
+ NSFNanoPredicate *attribute = [NSFNanoPredicate predicateWithColumn:NSFAttributeColumn matching:NSFEqualTo value:@"FirstName"];
46
+ NSFNanoPredicate *value = [NSFNanoPredicate predicateWithColumn:NSFValueColumn matching:NSFEqualTo value:@"Joe"];
47
+ NSFNanoExpression *expression = [NSFNanoExpression expressionWithPredicate:attribute];
48
+ [expression addPredicate:value withOperator:NSFAnd];
49
+
50
+ // Setup the search with the document store and a given expression
51
+ NSFNanoSearch *search = [NSFNanoSearch searchWithStore:nanoStore];
52
+ [search setExpressions:[NSArray arrayWithObject:expression]];
53
+
54
+ // Obtain the matching objects
55
+ NSDictionary *searchResults = [search searchObjectsWithReturnType:NSFReturnObjects error:nil];
56
+
57
+ // Close the document store
58
+ [nanoStore closeWithError:nil];
59
+ @endcode
60
+ */
61
+
62
+ @interface NSFNanoExpression : NSObject
63
+
64
+ /** * Array of NSFNanoPredicate */
65
+ @property (nonatomic, readonly) NSArray *predicates;
66
+ /** * Array of NSNumber wrapping \link NSFGlobals::NSFOperator NSFOperator \endlink */
67
+ @property (nonatomic, readonly) NSArray *operators;
68
+
69
+ /** @name Creating and Initializing Expressions
70
+ */
71
+
72
+ //@{
73
+
74
+ /** * Creates and returns an expression with a given predicate.
75
+ * @param thePredicate the predicate used to initialize the expression. Must not be nil.
76
+ * @return An expression upon success, nil otherwise.
77
+ * @warning The parameter thePredicate must not be nil.
78
+ * @throws NSFUnexpectedParameterException is thrown if the predicate is nil.
79
+ * @see \link initWithPredicate: - (id)initWithPredicate:(NSFNanoPredicate *)aPredicate \endlink
80
+ */
81
+
82
+ + (NSFNanoExpression*)expressionWithPredicate:(NSFNanoPredicate *)thePredicate;
83
+
84
+ /** * Initializes a newly allocated expression with a given expression.
85
+ * @param thePredicate the predicate used to initialize the expression. Must not be nil.
86
+ * @return An expression upon success, nil otherwise.
87
+ * @warning The parameter thePredicate must not be nil.
88
+ * @throws NSFUnexpectedParameterException is thrown if the predicate is nil.
89
+ * @see \link expressionWithPredicate: + (NSFNanoExpression*)expressionWithPredicate:(NSFNanoPredicate *)thePredicate \endlink
90
+ */
91
+
92
+ - (id)initWithPredicate:(NSFNanoPredicate *)thePredicate;
93
+
94
+ //@}
95
+
96
+ /** @name Adding a Predicate
97
+ */
98
+
99
+ //@{
100
+
101
+ /** * Adds a predicate to the expression.
102
+ * @param thePredicate is added to the expression.
103
+ * @param theOperator specifies the operation (AND/OR) to be applied.
104
+ * @warning The parameter thePredicate must not be nil.
105
+ * @throws NSFUnexpectedParameterException is thrown if the predicate is nil.
106
+ */
107
+
108
+ - (void)addPredicate:(NSFNanoPredicate *)thePredicate withOperator:(NSFOperator)theOperator;
109
+
110
+ //@}
111
+
112
+ /** @name Miscellaneous
113
+ */
114
+
115
+ //@{
116
+
117
+ /** * Returns a string representation of the expression.
118
+ * @note Check properties predicates and operators to find out the current state of the expression.
119
+ */
120
+
121
+ - (NSString *)description;
122
+
123
+ //@}
124
+
125
+ @end