OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
6 #error "This file requires ARC support." | |
7 #endif | |
8 | |
9 #import "remoting/ios/data_store.h" | |
10 | |
11 @interface DataStore (Private) | |
12 - (NSString*)itemArchivePath; | |
13 @end | |
14 | |
15 @implementation DataStore { | |
16 @private | |
17 NSMutableArray* _allHosts; | |
18 NSManagedObjectContext* _context; | |
19 NSManagedObjectModel* _model; | |
20 } | |
21 | |
22 // Create or Get a static data store | |
23 + (DataStore*)sharedStore { | |
24 static DataStore* sharedStore = nil; | |
25 static dispatch_once_t onceToken; | |
26 dispatch_once(&onceToken, | |
27 ^{ sharedStore = [[super allocWithZone:nil] init]; }); | |
28 | |
29 return sharedStore; | |
30 } | |
31 | |
32 // General methods | |
33 + (id)allocWithZone:(NSZone*)zone { | |
34 return [self sharedStore]; | |
35 } | |
36 | |
37 // Load data store from SQLLite backing store | |
38 - (id)init { | |
39 self = [super init]; | |
40 | |
41 if (self) { | |
42 // Read in ChromotingModel.xdatamodeld | |
43 _model = [NSManagedObjectModel mergedModelFromBundles:nil]; | |
44 | |
45 NSPersistentStoreCoordinator* psc = [[NSPersistentStoreCoordinator alloc] | |
46 initWithManagedObjectModel:_model]; | |
47 | |
48 NSString* path = [self itemArchivePath]; | |
49 NSURL* storeUrl = [NSURL fileURLWithPath:path]; | |
50 | |
51 NSError* error = nil; | |
52 | |
53 NSDictionary* tryOptions = @{ | |
54 NSMigratePersistentStoresAutomaticallyOption : @YES, | |
55 NSInferMappingModelAutomaticallyOption : @YES | |
56 }; | |
57 NSDictionary* makeOptions = | |
58 @{NSMigratePersistentStoresAutomaticallyOption : @YES}; | |
59 | |
60 if (![psc addPersistentStoreWithType:NSSQLiteStoreType | |
61 configuration:nil | |
62 URL:storeUrl | |
63 options:tryOptions | |
64 error:&error]) { | |
65 // An incompatible version of the store exists, delete it and start over | |
66 [[NSFileManager defaultManager] removeItemAtURL:storeUrl error:nil]; | |
67 | |
68 [psc addPersistentStoreWithType:NSSQLiteStoreType | |
69 configuration:nil | |
70 URL:storeUrl | |
71 options:makeOptions | |
72 error:&error]; | |
73 [NSException raise:@"Open failed" | |
74 format:@"Reason: %@", [error localizedDescription]]; | |
75 } | |
76 | |
77 // Create the managed object context | |
78 _context = [[NSManagedObjectContext alloc] init]; | |
79 [_context setPersistentStoreCoordinator:psc]; | |
80 | |
81 // The managed object context can manage undo, but we don't need it | |
82 [_context setUndoManager:nil]; | |
83 | |
84 _allHosts = nil; | |
85 } | |
86 return self; | |
87 } | |
88 | |
89 // Committing to backing store | |
90 - (BOOL)saveChanges { | |
91 NSError* err = nil; | |
92 BOOL successful = [_context save:&err]; | |
93 return successful; | |
94 } | |
95 | |
96 // Looking up the backing store path | |
97 - (NSString*)itemArchivePath { | |
98 NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains( | |
99 NSDocumentDirectory, NSUserDomainMask, YES); | |
100 | |
101 // Get one and only document directory from that list | |
102 NSString* documentDirectory = [documentDirectories objectAtIndex:0]; | |
103 | |
104 return [documentDirectory stringByAppendingPathComponent:@"store.data"]; | |
105 } | |
106 | |
107 // Return an array of all known hosts, if the list hasn't been loaded yet, then | |
108 // load it now | |
109 - (NSArray*)allHosts { | |
110 if (!_allHosts) { | |
111 NSFetchRequest* request = [[NSFetchRequest alloc] init]; | |
112 | |
113 NSEntityDescription* e = | |
114 [[_model entitiesByName] objectForKey:@"HostPreferences"]; | |
115 | |
116 [request setEntity:e]; | |
117 | |
118 NSError* error; | |
119 NSArray* result = [_context executeFetchRequest:request error:&error]; | |
120 if (!result) { | |
121 [NSException raise:@"Fetch failed" | |
122 format:@"Reason: %@", [error localizedDescription]]; | |
123 } | |
124 _allHosts = [result mutableCopy]; | |
125 } | |
126 | |
127 return _allHosts; | |
128 } | |
129 | |
130 // Return a HostPreferences if it already exists, otherwise create a new | |
131 // HostPreferences to use | |
132 - (const HostPreferences*)createHost:(NSString*)hostId { | |
133 | |
134 const HostPreferences* p = [self getHostForId:hostId]; | |
135 | |
136 if (p == nil) { | |
137 p = [NSEntityDescription insertNewObjectForEntityForName:@"HostPreferences" | |
138 inManagedObjectContext:_context]; | |
139 p.hostId = hostId; | |
140 [_allHosts addObject:p]; | |
141 } | |
142 return p; | |
143 } | |
144 | |
145 - (void)removeHost:(HostPreferences*)p { | |
146 [_context deleteObject:p]; | |
147 [_allHosts removeObjectIdenticalTo:p]; | |
148 } | |
149 | |
150 // Search the store for any matching HostPreferences | |
151 // return the 1st match or nil | |
152 - (const HostPreferences*)getHostForId:(NSString*)hostId { | |
153 NSFetchRequest* request = [[NSFetchRequest alloc] init]; | |
154 | |
155 NSEntityDescription* e = | |
156 [[_model entitiesByName] objectForKey:@"HostPreferences"]; | |
157 [request setEntity:e]; | |
158 | |
159 NSPredicate* predicate = | |
160 [NSPredicate predicateWithFormat:@"(hostId = %@)", hostId]; | |
161 [request setPredicate:predicate]; | |
162 | |
163 NSError* error; | |
164 NSArray* result = [_context executeFetchRequest:request error:&error]; | |
165 if (!result) { | |
166 [NSException raise:@"Fetch failed" | |
167 format:@"Reason: %@", [error localizedDescription]]; | |
168 } | |
169 | |
170 for (HostPreferences* curHost in result) { | |
171 return curHost; | |
172 } | |
173 return nil; | |
174 } | |
175 | |
176 @end | |
OLD | NEW |