From df1c14ea9a7fa14fb55ced79966130f88f7db8eb Mon Sep 17 00:00:00 2001 From: cramakri <cramakri> Date: Thu, 1 Nov 2012 12:17:21 +0000 Subject: [PATCH] Added pruning of potentially outdated information. SVN: 27444 --- .../BisKit/Classes/CISDOBIpadEntity.h | 2 + .../BisKit/Classes/CISDOBIpadEntity.m | 2 + .../BisKit/Classes/CISDOBIpadServiceManager.h | 1 + .../BisKit/Classes/CISDOBIpadServiceManager.m | 74 +++++++++++++------ .../contents | 7 +- 5 files changed, 60 insertions(+), 26 deletions(-) diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.h b/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.h index 7376be327e7..5a93a3d26d5 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.h +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.h @@ -41,6 +41,8 @@ @property (nonatomic, retain) NSString * permId; @property (nonatomic, retain) NSString * refconJson; @property (readonly) id refcon; +@property (nonatomic, retain) NSString * serverUrlString; +@property (nonatomic, retain) NSDate * lastUpdateDate; // Potentially nil properties @property (nonatomic, retain) NSString * summaryHeader; diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.m b/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.m index e356f825160..0a4c2d1a85c 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.m +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadEntity.m @@ -45,6 +45,8 @@ id ObjectFromJsonData(NSString *jsonData, NSError **error) @dynamic childrenPermIdsJson; @dynamic propertiesJson; @dynamic rootLevel; +@dynamic serverUrlString; +@dynamic lastUpdateDate; @synthesize image; diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h index b1a5743c8cd..d6d4a095b73 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h @@ -58,6 +58,7 @@ // Local Actions -- actions that do not require a network connection - (NSArray *)allIpadEntitiesOrError:(NSError **)error; - (NSArray *)entitiesByPermId:(NSArray *)permIds error:(NSError **)error; +- (NSArray *)entitiesNotUpdatedSince:(NSDate *)date error:(NSError **)error; - (NSFetchRequest *)entityFetchRequest; - (NSArray *)executeFetchRequest:(NSFetchRequest *)fetchRequest error:(NSError **)error; diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m index b6ddd1cd29b..c4c85041a64 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m @@ -61,25 +61,6 @@ static NSManagedObjectContext* GetDatabaseManagedObjectContext(NSURL* storeUrl, return moc; } -static BOOL SynchEntityWithManagedObjectContext(CISDOBIpadRawEntity *rawEntity, NSManagedObjectModel *model, NSManagedObjectContext *moc, NSError **error) -{ - // Create new entities in the moc, and store them. - CISDOBIpadEntity *entity; - NSDictionary *fetchVariables = [NSDictionary dictionaryWithObject: [NSArray arrayWithObject: rawEntity.permId] forKey: @"PERM_IDS"]; - NSFetchRequest *request = [model fetchRequestFromTemplateWithName: @"EntitiesByPermIds" substitutionVariables: fetchVariables]; - NSArray *matchedEntities = [moc executeFetchRequest: request error: error]; - if (!matchedEntities) return NO; - if ([matchedEntities count] > 0) { - entity = [matchedEntities objectAtIndex: 0]; - [entity updateFromRawEntity: rawEntity]; - } else { - entity = [NSEntityDescription insertNewObjectForEntityForName: @"CISDOBIpadEntity" inManagedObjectContext: moc]; - [entity initializeFromRawEntity: rawEntity]; - } - return YES; -} - - @implementation CISDOBIpadServiceManager @@ -101,25 +82,57 @@ static BOOL SynchEntityWithManagedObjectContext(CISDOBIpadRawEntity *rawEntity, return self; } -- (BOOL)syncEntities:(NSArray *)rawEntities error:(NSError **)error +- (BOOL)synchEntity:(CISDOBIpadRawEntity *)rawEntity lastUpdateDate:(NSDate *)date error:(NSError **)error { +{ + // Create new entities in the moc, and store them. + CISDOBIpadEntity *entity; + NSArray *matchedEntities = [self entitiesByPermId: [NSArray arrayWithObject: rawEntity.permId] error: error]; + if (!matchedEntities) return NO; + if ([matchedEntities count] > 0) { + entity = [matchedEntities objectAtIndex: 0]; + [entity updateFromRawEntity: rawEntity]; + } else { + entity = [NSEntityDescription insertNewObjectForEntityForName: @"CISDOBIpadEntity" inManagedObjectContext: self.managedObjectContext]; + [entity initializeFromRawEntity: rawEntity]; + } + entity.lastUpdateDate = date; + entity.serverUrlString = [((CISDOBLiveConnection *)(self.service.connection)).url absoluteString]; + + return YES; +} +} + +- (BOOL)syncEntities:(NSArray *)rawEntities pruning:(BOOL)prune error:(NSError **)error +{ + NSDate *lastUpdateDate = [NSDate date]; BOOL success; for (CISDOBIpadRawEntity *rawEntity in rawEntities) { - success = SynchEntityWithManagedObjectContext(rawEntity, self.managedObjectModel, self.managedObjectContext, error); + success = [self synchEntity: rawEntity lastUpdateDate: lastUpdateDate error: error]; if (!success) return NO; } + // If pruning is requested, remove entities that cannot be reached from the server result set. + // TODO : we should treat the intial results as a root set and trace out to do a gc, but the simpler implementation is just to remove everything that is not mentioned + if (prune) { + // Remove all entities that were not mentioned + NSArray *entitiesToDelete = [self entitiesNotUpdatedSince: lastUpdateDate error: error]; + for (CISDOBIpadEntity *entity in entitiesToDelete) { + [self.managedObjectContext deleteObject: entity]; + } + } + success = [self.managedObjectContext save: error]; return success; } -- (CISDOBIpadServiceManagerCall *)managerCallWrappingServiceCall:(CISDOBAsyncCall *)serviceCall +- (CISDOBIpadServiceManagerCall *)managerCallWrappingServiceCall:(CISDOBAsyncCall *)serviceCall pruning:(BOOL)prune { CISDOBIpadServiceManagerCall *managerCall = [[CISDOBIpadServiceManagerCall alloc] initWithServiceManager: self serviceCall: serviceCall]; serviceCall.success = ^(id result) { // Update the cache NSError *error; - BOOL didSync = [self syncEntities: result error: &error]; + BOOL didSync = [self syncEntities: result pruning: prune error: &error]; if (!didSync) { serviceCall.fail(error); } else if (managerCall.success) { @@ -132,6 +145,11 @@ static BOOL SynchEntityWithManagedObjectContext(CISDOBIpadRawEntity *rawEntity, return managerCall; } +- (CISDOBIpadServiceManagerCall *)managerCallWrappingServiceCall:(CISDOBAsyncCall *)serviceCall +{ + return [self managerCallWrappingServiceCall: serviceCall pruning: NO]; +} + - (CISDOBAsyncCall *)loginUser:(NSString *)user password:(NSString *)password { return [self.service loginUser: user password: password]; @@ -140,7 +158,8 @@ static BOOL SynchEntityWithManagedObjectContext(CISDOBIpadRawEntity *rawEntity, - (CISDOBAsyncCall *)retrieveRootLevelEntities { CISDOBAsyncCall *call = [self.service listRootLevelEntities]; - return [self managerCallWrappingServiceCall: call]; + // get rid of entities not mentioned in the original call + return [self managerCallWrappingServiceCall: call pruning: YES]; } - (CISDOBAsyncCall *)drillOnEntity:(CISDOBIpadEntity *)entity @@ -168,6 +187,13 @@ static BOOL SynchEntityWithManagedObjectContext(CISDOBIpadRawEntity *rawEntity, return [self executeFetchRequest: request error: error]; } +- (NSArray *)entitiesNotUpdatedSince:(NSDate *)date error:(NSError **)error +{ + NSDictionary *fetchVariables = [NSDictionary dictionaryWithObject: date forKey: @"LAST_UPDATE_DATE"]; + NSFetchRequest *request = [self.managedObjectModel fetchRequestFromTemplateWithName: @"EntitiesNotUpdatedSince" substitutionVariables: fetchVariables]; + return [self executeFetchRequest: request error: error]; +} + - (NSFetchRequest *)entityFetchRequest { NSFetchRequest *request = [[NSFetchRequest alloc] init]; diff --git a/openbis-ipad/BisKit/Classes/persistent-data-model.xcdatamodeld/persistent-data-model.xcdatamodel/contents b/openbis-ipad/BisKit/Classes/persistent-data-model.xcdatamodeld/persistent-data-model.xcdatamodel/contents index 50b6c58dc1e..156f3a1b456 100644 --- a/openbis-ipad/BisKit/Classes/persistent-data-model.xcdatamodeld/persistent-data-model.xcdatamodel/contents +++ b/openbis-ipad/BisKit/Classes/persistent-data-model.xcdatamodeld/persistent-data-model.xcdatamodel/contents @@ -6,19 +6,22 @@ <attribute name="childrenPermIdsJson" optional="YES" attributeType="String" indexed="YES" syncable="YES"/> <attribute name="identifier" optional="YES" attributeType="String" indexed="YES" syncable="YES"/> <attribute name="imageUrl" optional="YES" attributeType="String" syncable="YES"/> + <attribute name="lastUpdateDate" optional="YES" attributeType="Date" indexed="YES" syncable="YES"/> <attribute name="permId" optional="YES" attributeType="String" indexed="YES" syncable="YES"/> <attribute name="properties" optional="YES" transient="YES" syncable="YES"/> <attribute name="propertiesJson" optional="YES" attributeType="String" syncable="YES"/> <attribute name="refcon" optional="YES" transient="YES" syncable="YES"/> <attribute name="refconJson" optional="YES" attributeType="String" syncable="YES"/> - <attribute name="rootLevel" optional="YES" attributeType="Boolean" syncable="YES"/> + <attribute name="rootLevel" optional="YES" attributeType="Boolean" indexed="YES" syncable="YES"/> + <attribute name="serverUrlString" optional="YES" attributeType="String" syncable="YES"/> <attribute name="summary" optional="YES" attributeType="String" syncable="YES"/> <attribute name="summaryHeader" optional="YES" attributeType="String" syncable="YES"/> </entity> <fetchRequest name="EntitiesByPermIds" entity="CISDOBIpadEntity" predicateString="permId IN $PERM_IDS" fetchBatchSize="20"/> + <fetchRequest name="EntitiesNotUpdatedSince" entity="CISDOBIpadEntity" predicateString="lastUpdateDate < $LAST_UPDATE_DATE"/> <fetchRequest name="EntityAndChildren" entity="CISDOBIpadEntity" predicateString="SELF == $ENTITY OR permId IN $CHILDREN" fetchBatchSize="20"/> <fetchRequest name="RootEntities" entity="CISDOBIpadEntity" predicateString="rootLevel == 0" fetchBatchSize="20"/> <elements> - <element name="CISDOBIpadEntity" positionX="0" positionY="0" width="128" height="240"/> + <element name="CISDOBIpadEntity" positionX="0" positionY="0" width="128" height="270"/> </elements> </model> \ No newline at end of file -- GitLab