nano-store 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
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