diff --git a/openbis-ipad/.gitignore b/openbis-ipad/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..cbe04f77c802e3c00bbc7816eec78857e46b33ed --- /dev/null +++ b/openbis-ipad/.gitignore @@ -0,0 +1 @@ +openBIS/Research/openBISData.sqlite diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h index cebbfedcdae23b9f313cec6b4319e4c0cc0f1c71..596d73d069ddb643501569e2751a02c9f6e012e7 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h @@ -93,8 +93,9 @@ typedef void (^MocSaveBlock)(CISDOBIpadServiceManager *serviceManager, NSArray * // Properties - (void)setOpenbisUrl:(NSURL *)openbisUrl trusted:(BOOL)trusted; -// Actions - +// +// Server Actions -- actions that communicate with the server +// //! Log the user into the openBIS instance - (CISDOBAsyncCall *)loginUser:(NSString *)user password:(NSString *)password; @@ -110,7 +111,15 @@ typedef void (^MocSaveBlock)(CISDOBIpadServiceManager *serviceManager, NSArray * //! Get images for the entity, if there are any. The success block will be called with a CISDOBIpadImage object that describes the location of the image and contains the bytes for the image. - (CISDOBAsyncCall *)imagesForEntity:(CISDOBIpadEntity *)entity; +//! Get drill information from the openBIS ipad service and store the results in the managedObjectContext. +- (CISDOBAsyncCall *)drillOnEntities:(NSArray *)entities; + +//! Get detail information from the openBIS ipad service and store the results in the managedObjectContext. +- (CISDOBAsyncCall *)detailsForEntities:(NSArray *)entities; + +// // 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; diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m index cf30587447df798dbad991a07b38965b51a637fc..bc8febf968ed802385b4981148af5c1ca6872bc0 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m @@ -233,6 +233,38 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl return call; } +- (CISDOBAsyncCall *)drillOnEntities:(NSArray *)entities +{ + NSMutableArray *refcons = [NSMutableArray arrayWithCapacity: [entities count]]; + for (CISDOBIpadEntity *entity in entities) { + [refcons addObject: entity.refcon]; + } + + CISDOBAsyncCall *call = [self.service drillOnEntities: entities refcons: refcons]; + CISDOBIpadServiceManagerCall *managerCall = [self managerCallWrappingServiceCall: call]; + + managerCall.willCallNotificationName = CISDOBIpadServiceWillDrillOnEntityNotification; + managerCall.didCallNotificationName = CISDOBIpadServiceDidDrillOnEntityNotification; + + return managerCall; +} + +- (CISDOBAsyncCall *)detailsForEntities:(NSArray *)entities +{ + NSMutableArray *refcons = [NSMutableArray arrayWithCapacity: [entities count]]; + for (CISDOBIpadEntity *entity in entities) { + [refcons addObject: entity.refcon]; + } + + CISDOBAsyncCall *call = [self.service detailsForEntities: entities refcons: refcons]; + CISDOBIpadServiceManagerCall *managerCall = [self managerCallWrappingServiceCall: call]; + + managerCall.willCallNotificationName = CISDOBIpadServiceWillRetrieveDetailsForEntityNotification; + managerCall.didCallNotificationName = CISDOBIpadServiceDidRetrieveDetailsForEntityNotification; + + return managerCall; +} + - (NSArray *)allIpadEntitiesOrError:(NSError **)error; { NSFetchRequest* request = [self fetchRequestForEntities]; diff --git a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m index 859f4fe70b076c3be6a7796b022dd8ae9ac33edd..e2456679f6e8b2307094c5d3d4e3eccf348da396 100644 --- a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m +++ b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m @@ -253,6 +253,25 @@ [self assertAfterDetails]; } +- (void)performDrillOnCollection:(NSArray *)drillEntities +{ + CISDOBAsyncCall *call; + [self assertBeforeDrill]; + call = [self.serviceManager drillOnEntities: drillEntities]; + [self configureAndRunCallSynchronously: call]; + STAssertNotNil(_callResult, @"The iPad service should have returned some entities."); + [self assertAfterDrill]; +} + +- (void)performDetailsOnCollection:(NSArray *)detailsEntities +{ + CISDOBAsyncCall *call; + call = [self.serviceManager detailsForEntities: detailsEntities]; + [self configureAndRunCallSynchronously: call]; + STAssertNotNil(_callResult, @"The iPad service should have returned some entities."); + [self assertAfterDetails]; +} + - (void)testPersistEntities { [self performLogin]; @@ -275,6 +294,28 @@ [self checkFindingChildren]; } +- (void)testPersistDrillAndDetailsOnCollections +{ + [self performLogin]; + [self performRootLevelCall]; + + + // Get drill information on some entity + NSArray *entitiesWithChildren = [self entitiesWithChildren]; + STAssertTrue([entitiesWithChildren count] > 0, @"There should be some entities with children"); + CISDOBIpadEntity *drillEntity = [entitiesWithChildren objectAtIndex: 0]; + [self performDrill: drillEntity]; + + + // Get detail information on some entities + CISDOBIpadEntity *detailsEntity = [entitiesWithChildren objectAtIndex: 1]; + [self assertBeforeDetails]; + [self performDetails: detailsEntity]; + + // Check that the children could be found + [self checkFindingChildren]; +} + - (void)retrieveRootLevelEntitiesSimulatingRemovalOfEntity:(CISDOBIpadEntity *)entityToRemove { // Make a root level call, but do have some entities removed from the list diff --git a/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate b/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate index 0855a75a6164ac041e65c09845f8de5c0bda9d28..4ab4ac45e5a3fbb10800e55c4a20e54be6698d40 100644 Binary files a/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate and b/openbis-ipad/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/openbis-ipad/openBIS/Research/openBISData/main.m b/openbis-ipad/openBIS/Research/openBISData/main.m index a767c8b4330595e055fb1880e7423cc77199be91..d34c15aff3aef78e29a4073d06f9ffd153c9289c 100644 --- a/openbis-ipad/openBIS/Research/openBISData/main.m +++ b/openbis-ipad/openBIS/Research/openBISData/main.m @@ -27,6 +27,7 @@ #import "CISDOBConnection.h" #import "CISDOBAsyncCall.h" #import "CISDOBIpadService.h" +#import "CISDOBIpadServiceManager.h" static NSManagedObjectModel *managedObjectModel() { @@ -89,7 +90,7 @@ NSManagedObjectContext* GetDatabaseManagedObjectContext(NSURL* storeURL, NSError return moc; } -id RunCallSynchronously(CISDOBAsyncCall *call, int seconds) +id RunCallSynchronously(CISDOBAsyncCall *call) { BOOL __block callCompleted = NO; id __block callResult = nil; @@ -107,6 +108,7 @@ id RunCallSynchronously(CISDOBAsyncCall *call, int seconds) [call start]; + int seconds = call.timeoutInterval; for(int i = 0; i < seconds && !callCompleted; ++i) { // Run the runloop until an answer is returned CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, 0); @@ -127,12 +129,8 @@ void CollectAllEntities(NSMutableArray *permIds, NSMutableArray *refcons, NSMana } } -void CollectAllDrillableEntities(NSMutableArray *permIds, NSMutableArray *refcons, NSManagedObjectContext *moc, NSError **error) +void CollectAllDrillableEntities(NSMutableArray *permIds, NSMutableArray *refcons, NSArray *elements, NSError **error) { - NSFetchRequest* request = [[NSFetchRequest alloc] init]; - NSEntityDescription* entity = [NSEntityDescription entityForName: @"CISDOBIpadEntity" inManagedObjectContext: moc]; - [request setEntity: entity]; - NSArray* elements = [moc executeFetchRequest: request error: error]; for (CISDOBIpadEntity *entity in elements) { if ([entity.childrenPermIds count] > 0) { [permIds addObject: entity.permId]; @@ -141,118 +139,61 @@ void CollectAllDrillableEntities(NSMutableArray *permIds, NSMutableArray *refcon } } -void 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; - if ([matchedEntities count] > 0) { - entity = [matchedEntities objectAtIndex: 0]; - [entity updateFromRawEntity: rawEntity]; - } else { - entity = [NSEntityDescription insertNewObjectForEntityForName: @"CISDOBIpadEntity" inManagedObjectContext: moc]; - [entity initializeFromRawEntity: rawEntity]; - } -} - -BOOL SaveManagedObjectContext(NSManagedObjectContext *moc, NSError **error) -{ - // Save the managed object context - BOOL success = [moc save: error]; - if (!success) { - NSLog(@"Error while saving %@", (error && [*error localizedDescription] != nil) ? [*error localizedDescription] : @"Unknown Error"); - exit(1); - } - return success; -} - -void RetrieveRootLevel(CISDOBIpadService *service, int waitTime, NSManagedObjectContext *moc, NSError **error) +void RetrieveRootLevel(CISDOBIpadServiceManager *serviceManager, NSError **error) { CISDOBAsyncCall *call; - call = [service listRootLevelEntities]; - NSArray *rawEntities = RunCallSynchronously(call, waitTime); - - NSEntityDescription *entity = [NSEntityDescription entityForName: @"CISDOBIpadEntity" inManagedObjectContext: moc]; - NSManagedObjectModel *model = [entity managedObjectModel]; - - for (CISDOBIpadRawEntity *rawEntity in rawEntities) { - SynchEntityWithManagedObjectContext(rawEntity, model, moc, error); - } - SaveManagedObjectContext(moc, error); + call = [serviceManager retrieveRootLevelEntities]; + RunCallSynchronously(call); } -void RetrieveDrillEntities(CISDOBIpadService *service, int waitTime, NSManagedObjectContext *moc, NSError **error) +void RetrieveDrillEntities(CISDOBIpadServiceManager *serviceManager, NSError **error) { - NSMutableArray *drillPermIds = [NSMutableArray array]; - NSMutableArray *drillRefcons = [NSMutableArray array]; - CollectAllDrillableEntities(drillPermIds, drillRefcons, moc, error); + NSArray *allIpadEntities = [serviceManager allIpadEntitiesOrError: error]; + if (!allIpadEntities) return; CISDOBAsyncCall *call; - call = [service drillOnEntities: drillPermIds refcons: drillRefcons]; - NSArray *rawEntities = RunCallSynchronously(call, waitTime); - - NSEntityDescription *entity = [NSEntityDescription entityForName: @"CISDOBIpadEntity" inManagedObjectContext: moc]; - NSManagedObjectModel *model = [entity managedObjectModel]; - - for (CISDOBIpadRawEntity *rawEntity in rawEntities) { - SynchEntityWithManagedObjectContext(rawEntity, model, moc, error); - } - SaveManagedObjectContext(moc, error); + call = [serviceManager drillOnEntities: allIpadEntities]; + RunCallSynchronously(call); } -void RetrieveDetailEntities(CISDOBIpadService *service, int waitTime, NSManagedObjectContext *moc, NSError **error) +void RetrieveDetailEntities(CISDOBIpadServiceManager *serviceManager, NSError **error) { - NSMutableArray *allPermIds = [NSMutableArray array]; - NSMutableArray *allRefcons = [NSMutableArray array]; - CollectAllEntities(allPermIds, allRefcons, moc, error); + NSArray *allIpadEntities = [serviceManager allIpadEntitiesOrError: error]; + if (!allIpadEntities) return; CISDOBAsyncCall *call; - call = [service detailsForEntities: allPermIds refcons: allRefcons]; - NSArray *rawEntities = RunCallSynchronously(call, waitTime); - - NSEntityDescription *entity = [NSEntityDescription entityForName: @"CISDOBIpadEntity" inManagedObjectContext: moc]; - NSManagedObjectModel *model = [entity managedObjectModel]; - - for (CISDOBIpadRawEntity *rawEntity in rawEntities) { - SynchEntityWithManagedObjectContext(rawEntity, model, moc, error); - } - SaveManagedObjectContext(moc, error); + call = [serviceManager detailsForEntities: allIpadEntities]; + RunCallSynchronously(call); } -void InitializeDatabase(NSManagedObjectContext *moc, NSError **error) +void InitializeDatabase(CISDOBIpadServiceManager *serviceManager, NSError **error) { - NSURL *url = [NSURL URLWithString: @"https://localhost:8443"]; - CISDOBLiveConnection *connection = [[CISDOBLiveConnection alloc] initWithUrl: url trusted: YES]; - CISDOBIpadService *service = [[CISDOBIpadService alloc] initWithConnection: connection]; - int waitTime = ((int) service.connection.timeoutInterval) * 2; - CISDOBAsyncCall *call; - call = [service loginUser: @"admin" password: @"password"]; - RunCallSynchronously(call, waitTime); + call = [serviceManager loginUser: @"admin" password: @"password"]; + RunCallSynchronously(call); - RetrieveRootLevel(service, waitTime, moc, error); - RetrieveDrillEntities(service, waitTime, moc, error); - RetrieveDetailEntities(service, waitTime, moc, error); + RetrieveRootLevel(serviceManager, error); + RetrieveDrillEntities(serviceManager, error); + RetrieveDetailEntities(serviceManager, error); } int main(int argc, const char * argv[]) { - + // TODO Switch to a version that uses the ipad service manager @autoreleasepool { // Create the managed object context NSError *error; // This is just hard-coded NSURL *databaseUrl = [NSURL fileURLWithPath: @"/Users/cramakri/_local/git/openbis-ipad/openBIS/Research/openBISData.sqlite"]; - NSManagedObjectContext *moc = GetDatabaseManagedObjectContext(databaseUrl, &error); - if (!moc) { - NSLog(@"Could not create database %@", ([error localizedDescription] != nil) ? [error localizedDescription] : error); + NSURL *url = [NSURL URLWithString: @"https://localhost:8443"]; + CISDOBIpadServiceManager *serviceManager = [[CISDOBIpadServiceManager alloc] initWithStoreUrl: databaseUrl openbisUrl: url trusted: YES error: &error]; + + if (!serviceManager) { + NSLog(@"Could not create service manager %@", ([error localizedDescription] != nil) ? [error localizedDescription] : error); exit(1); } NSLog(@"START Init DB"); NSDate *start = [NSDate date]; - InitializeDatabase(moc, &error); + InitializeDatabase(serviceManager, &error); NSDate *end = [NSDate date]; NSLog(@"END Init DB (%.2f sec) %@", [end timeIntervalSinceDate: start], databaseUrl); diff --git a/openbis-ipad/openBIS/openBIS.xcodeproj/project.pbxproj b/openbis-ipad/openBIS/openBIS.xcodeproj/project.pbxproj index 90aa2c2da8f2297ceca08cf4d952d3c40cce26e2..648d10f89cf06757f5acc42c3719c14b56fdc82f 100644 --- a/openbis-ipad/openBIS/openBIS.xcodeproj/project.pbxproj +++ b/openbis-ipad/openBIS/openBIS.xcodeproj/project.pbxproj @@ -10,13 +10,13 @@ 3605B05C1653EE8500CEC7F8 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3605B05B1653EE8500CEC7F8 /* Settings.bundle */; }; 3611F7B1169D5D8E0072B61A /* CISDOBAuthenticationChallengeConfirmationDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 3611F7B0169D5D8E0072B61A /* CISDOBAuthenticationChallengeConfirmationDialog.m */; }; 362B81EC163FFB6C00127554 /* CISDOBIpadServiceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 362B81EB163FFB6C00127554 /* CISDOBIpadServiceManager.m */; }; - 364D509E161C6ADB00A739B0 /* openBISData.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 364D509C161C6ADB00A739B0 /* openBISData.sqlite */; }; 3656C9B4165A7A7E00E9B0FA /* CISDOBImageViewPopoverController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3656C9B3165A7A7E00E9B0FA /* CISDOBImageViewPopoverController.m */; }; 3656C9C6165ABC5D00E9B0FA /* Zoom.png in Resources */ = {isa = PBXBuildFile; fileRef = 3656C9C5165ABC5D00E9B0FA /* Zoom.png */; }; 3656C9C9165ABD4C00E9B0FA /* Zoom-small.png in Resources */ = {isa = PBXBuildFile; fileRef = 3656C9C8165ABD4C00E9B0FA /* Zoom-small.png */; }; 3687D8FF162D3AB500622690 /* openbis-icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 3687D8FD162D3AB500622690 /* openbis-icon-72.png */; }; 3687D900162D3AB500622690 /* openbis-icon-144.png in Resources */ = {isa = PBXBuildFile; fileRef = 3687D8FE162D3AB500622690 /* openbis-icon-144.png */; }; 36BDE60016555869007EC62A /* CISDOBLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 36BDE5FF16555869007EC62A /* CISDOBLoginViewController.m */; }; + 36D853DD16A3FE6C00B94F90 /* CISDOBIpadServiceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 362B81EB163FFB6C00127554 /* CISDOBIpadServiceManager.m */; }; 36F71E79161C3AE900C87277 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 36F71E78161C3AE900C87277 /* UIKit.framework */; }; 36F71E7B161C3AE900C87277 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 36F71E7A161C3AE900C87277 /* Foundation.framework */; }; 36F71E7D161C3AE900C87277 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 36F71E7C161C3AE900C87277 /* CoreGraphics.framework */; }; @@ -86,7 +86,6 @@ 362B81EA163FFB6C00127554 /* CISDOBIpadServiceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CISDOBIpadServiceManager.h; sourceTree = "<group>"; }; 362B81EB163FFB6C00127554 /* CISDOBIpadServiceManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CISDOBIpadServiceManager.m; sourceTree = "<group>"; }; 364D5098161C6A3600A739B0 /* readme.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = readme.md; sourceTree = "<group>"; }; - 364D509C161C6ADB00A739B0 /* openBISData.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = openBISData.sqlite; sourceTree = "<group>"; }; 3656C9B2165A7A7E00E9B0FA /* CISDOBImageViewPopoverController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CISDOBImageViewPopoverController.h; sourceTree = "<group>"; }; 3656C9B3165A7A7E00E9B0FA /* CISDOBImageViewPopoverController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CISDOBImageViewPopoverController.m; sourceTree = "<group>"; }; 3656C9C5165ABC5D00E9B0FA /* Zoom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Zoom.png; sourceTree = "<group>"; }; @@ -181,7 +180,6 @@ 364D509A161C6ADB00A739B0 /* DevData */ = { isa = PBXGroup; children = ( - 364D509C161C6ADB00A739B0 /* openBISData.sqlite */, ); path = DevData; sourceTree = SOURCE_ROOT; @@ -438,7 +436,6 @@ 36F71E91161C3AE900C87277 /* Default-568h@2x.png in Resources */, 36F71E94161C3AE900C87277 /* MainStoryboard_iPhone.storyboard in Resources */, 36F71E97161C3AE900C87277 /* MainStoryboard_iPad.storyboard in Resources */, - 364D509E161C6ADB00A739B0 /* openBISData.sqlite in Resources */, 3687D8FF162D3AB500622690 /* openbis-icon-72.png in Resources */, 3687D900162D3AB500622690 /* openbis-icon-144.png in Resources */, 3605B05C1653EE8500CEC7F8 /* Settings.bundle in Resources */, @@ -508,6 +505,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 36D853DD16A3FE6C00B94F90 /* CISDOBIpadServiceManager.m in Sources */, 36F71F28161C4F0400C87277 /* CISDOBAsyncCall.m in Sources */, 36F71F2A161C4F0400C87277 /* CISDOBConnection.m in Sources */, 36F71F2C161C4F0400C87277 /* CISDOBIpadEntity.m in Sources */, diff --git a/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate b/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate index 0541e9700bee812153d1af8c5da942e469f02d8c..1d63046308fd528344e3d4d1d915f74b9c382b20 100644 Binary files a/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate and b/openbis-ipad/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate differ