From 186d6d400232f9ead8d92ec6385581ffca6cd22b Mon Sep 17 00:00:00 2001 From: cramakri <cramakri> Date: Thu, 15 Nov 2012 15:42:08 +0000 Subject: [PATCH] Added support for a Dead openBIS connection that does not actually retrieve data SVN: 27645 --- .../BisKit/Classes/CISDOBConnection.h | 18 +++++ .../BisKit/Classes/CISDOBConnection.m | 18 +++++ .../BisKit/Classes/CISDOBIpadServiceManager.h | 11 ++- .../BisKit/Classes/CISDOBIpadServiceManager.m | 69 ++++++++++++------- .../Tests/CISDOBIpadServiceManagerTest.m | 22 ++++++ 5 files changed, 112 insertions(+), 26 deletions(-) diff --git a/openbis-ipad/BisKit/Classes/CISDOBConnection.h b/openbis-ipad/BisKit/Classes/CISDOBConnection.h index 0d0f19df750..49f1591d450 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBConnection.h +++ b/openbis-ipad/BisKit/Classes/CISDOBConnection.h @@ -24,6 +24,13 @@ #import <Foundation/Foundation.h> #import "CISDOBShared.h" +//! The error domain for errors in the Connection layer +FOUNDATION_EXPORT NSString *const CISDOBConnectionErrorDomain; + +enum CISDOBConnectionErrorCode { + kCISDOBConnectionError_NoServerAvailable = 1, +}; + /** * \brief A connection to an openBIS server. @@ -83,3 +90,14 @@ } @end + +/** + * \brief A fake connection to openBIS + * + */ +@interface CISDOBDeadConnection : CISDOBConnection { +@private + +} + +@end diff --git a/openbis-ipad/BisKit/Classes/CISDOBConnection.m b/openbis-ipad/BisKit/Classes/CISDOBConnection.m index 9fbc5ee99e0..600770d6d2f 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBConnection.m +++ b/openbis-ipad/BisKit/Classes/CISDOBConnection.m @@ -25,6 +25,8 @@ #import "CISDOBJsonRpcCall.h" #import "CISDOBAsyncCall.h" +NSString *const CISDOBConnectionErrorDomain = @"CISDOBConnectionErrorDomain"; + // Internal connection call that includes the private state @interface CISDOBConnectionCall : CISDOBAsyncCall { @private @@ -158,6 +160,22 @@ @end +@implementation CISDOBDeadConnection + +- (void)executeCall:(CISDOBConnectionCall *)call +{ + void (^notifyBlock)(void) = ^ { + NSString *errorMessage = @"The app is not connected to an openBIS server."; + NSDictionary *userInfo = + [NSDictionary dictionaryWithObjectsAndKeys: errorMessage, NSLocalizedDescriptionKey, nil]; + NSError *error = [NSError errorWithDomain: CISDOBConnectionErrorDomain code: kCISDOBConnectionError_NoServerAvailable userInfo: userInfo]; + call.failWrapper(error); + }; + [[NSOperationQueue mainQueue] addOperationWithBlock: notifyBlock]; +} + +@end + @implementation CISDOBConnectionCall diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h index 222f7247ccc..a11a23991f7 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.h @@ -25,7 +25,11 @@ #import "CISDOBShared.h" // -// The names of the notifications posted by the service manager +// The names of the notifications posted by the service manager. +// +// The notifications include a userInfo dictionary with the following +// keys and values: +// NSUnderlyingErrorKey If in the dictionary, the error that occured when making the call. // FOUNDATION_EXPORT NSString *const CISDOBIpadServiceWillLoginNotification; FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidLoginNotification; @@ -44,12 +48,14 @@ FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidSynchEntitiesNotification; + @class CISDOBIpadService, CISDOBAsyncCall, CISDOBIpadEntity; /** * \brief A class that manages a connection to the openBIS iPad service, caching data locally as CISDOBIpadEntity objects. */ @interface CISDOBIpadServiceManager : NSObject +@property (readonly) NSURL *openbisUrl; @property (readonly, strong) CISDOBIpadService *service; @property (readonly, strong) NSURL *storeUrl; @property (readonly, strong) NSManagedObjectContext *managedObjectContext; @@ -63,6 +69,9 @@ FOUNDATION_EXPORT NSString *const CISDOBIpadServiceDidSynchEntitiesNotification; // Initialization - (id)initWithStoreUrl:(NSURL *)storeUrl openbisUrl:(NSURL *)openbisUrl trusted:(BOOL)trusted error:(NSError **)error; +// Properties +- (void)setOpenbisUrl:(NSURL *)openbisUrl trusted:(BOOL)trusted; + // Actions //! Log the user into the openBIS instance diff --git a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m index 1abd1837bdc..d640fbf9d7f 100644 --- a/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m +++ b/openbis-ipad/BisKit/Classes/CISDOBIpadServiceManager.m @@ -42,12 +42,11 @@ NSString *const CISDOBIpadServiceDidSynchEntitiesNotification = @"CISDOBIpadServ // Internal service call that includes the private state @interface CISDOBIpadServiceManagerCall : CISDOBAsyncCall -@property(weak) CISDOBIpadServiceManager *serviceManager; +@property(weak, nonatomic) CISDOBIpadServiceManager *serviceManager; @property(nonatomic) CISDOBAsyncCall *serviceCall; -@property(copy) NSString *willCallNotificationName; -@property(copy) NSString *didCallNotificationName; -@property(nonatomic) BOOL sendSynchNotifications; +@property(copy, nonatomic) NSString *willCallNotificationName; //<! The notification called before the call takes place, may be nil +@property(copy, nonatomic) NSString *didCallNotificationName; //<! The notification called after the call has completed, may be nil // Initialization - (id)initWithServiceManager:(CISDOBIpadServiceManager *)serviceManager serviceCall:(CISDOBAsyncCall *)call; @@ -73,7 +72,7 @@ NSString *const CISDOBIpadServiceDidSynchEntitiesNotification = @"CISDOBIpadServ // Actions - (void)run; -- (void)notifyCallOfResult:(id)args; +- (void)notifyCallOfResult; @end @@ -108,7 +107,13 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl { if (!(self = [super init])) return nil; - CISDOBLiveConnection *connection = [[CISDOBLiveConnection alloc] initWithUrl: openbisUrl trusted: trusted]; + CISDOBConnection *connection; + if (openbisUrl) { + connection = [[CISDOBLiveConnection alloc] initWithUrl: openbisUrl trusted: trusted]; + } else { + connection = [[CISDOBDeadConnection alloc] init]; + } + _storeUrl = [storeUrl copy]; _service = [[CISDOBIpadService alloc] initWithConnection: connection]; _managedObjectContext = GetMainThreadManagedObjectContext(self.storeUrl, error); @@ -123,6 +128,28 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl return self; } +- (NSURL *)openbisUrl +{ + if (![_service.connection isKindOfClass: [CISDOBLiveConnection class]]) return nil; + + return ((CISDOBLiveConnection *) _service.connection).url; + +} + +- (void)setOpenbisUrl:(NSURL *)openbisUrl trusted:(BOOL)trusted; +{ + if ([self.openbisUrl isEqual: openbisUrl]) return; + + CISDOBConnection *connection; + if (openbisUrl) { + connection = [[CISDOBLiveConnection alloc] initWithUrl: openbisUrl trusted: trusted]; + } else { + connection = [[CISDOBDeadConnection alloc] init]; + } + + _service = [[CISDOBIpadService alloc] initWithConnection: connection]; +} + - (NSString *)sessionToken { return ((CISDOBLiveConnection *)(self.service.connection)).sessionToken; @@ -131,10 +158,6 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl - (void)syncEntities:(NSArray *)rawEntities pruning:(BOOL)prune notifying:(CISDOBIpadServiceManagerCall *)managerCall { void (^syncBlock)(void) = ^{ - if (managerCall.didCallNotificationName) { - [[NSNotificationCenter defaultCenter] postNotificationName: managerCall.didCallNotificationName object: self]; - } - [[NSNotificationCenter defaultCenter] postNotificationName: CISDOBIpadServiceWillSynchEntitiesNotification object: self]; // Run the synchronizer in the background thread @@ -153,7 +176,7 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl notifySynchronizer.error = error; } } - [notifySynchronizer notifyCallOfResult: nil]; + [notifySynchronizer notifyCallOfResult]; }; [[NSOperationQueue mainQueue] addOperationWithBlock: notifyBlock]; }; @@ -165,11 +188,11 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl CISDOBIpadServiceManagerCall *managerCall = [[CISDOBIpadServiceManagerCall alloc] initWithServiceManager: self serviceCall: serviceCall]; serviceCall.success = ^(id result) { - // Update the cache + // Update the cache and call the managerCall success when done [self syncEntities: result pruning: prune notifying: managerCall]; }; - serviceCall.fail = ^(NSError *error) { if (managerCall.fail) managerCall.fail(error); }; + serviceCall.fail = ^(NSError *error) { [managerCall notifyFailure: error]; }; return managerCall; } @@ -186,7 +209,6 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl call.success = ^(id result) { [managerCall notifySuccess: result]; }; managerCall.willCallNotificationName = CISDOBIpadServiceWillLoginNotification; managerCall.didCallNotificationName = CISDOBIpadServiceDidLoginNotification; - managerCall.sendSynchNotifications = NO; return managerCall; } @@ -198,7 +220,6 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl managerCall.willCallNotificationName = CISDOBIpadServiceWillRetrieveRootLevelEntitiesNotification; managerCall.didCallNotificationName = CISDOBIpadServiceDidRetrieveRootLevelEntitiesNotification; - managerCall.sendSynchNotifications = YES; return managerCall; } @@ -210,7 +231,6 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl managerCall.willCallNotificationName = CISDOBIpadServiceWillDrillOnEntityNotification; managerCall.didCallNotificationName = CISDOBIpadServiceDidDrillOnEntityNotification; - managerCall.sendSynchNotifications = YES; return managerCall; } @@ -222,7 +242,6 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl managerCall.willCallNotificationName = CISDOBIpadServiceWillRetrieveDetailsForEntityNotification; managerCall.didCallNotificationName = CISDOBIpadServiceDidRetrieveDetailsForEntityNotification; - managerCall.sendSynchNotifications = YES; return managerCall; } @@ -285,25 +304,25 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl return self; } -- (void)sendCompletionNotification +- (void)sendCompletionNotification:(NSError *)errorOrNil { - if (self.sendSynchNotifications) { - // This is handled elsewhere - } else if (self.didCallNotificationName) { - [[NSNotificationCenter defaultCenter] postNotificationName: self.didCallNotificationName object: self.serviceManager]; + if (self.didCallNotificationName) { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (errorOrNil) [userInfo setValue: errorOrNil forKey: NSUnderlyingErrorKey]; + [[NSNotificationCenter defaultCenter] postNotificationName: self.didCallNotificationName object: self.serviceManager userInfo: userInfo]; } } - (void)notifySuccess:(id)result { + [self sendCompletionNotification: nil]; if (self.success) self.success(result); - [self sendCompletionNotification]; } - (void)notifyFailure:(NSError *)error { + [self sendCompletionNotification: error]; if (self.fail) self.fail(error); - [self sendCompletionNotification]; } - (void)start @@ -388,7 +407,7 @@ static NSManagedObjectContext* GetMainThreadManagedObjectContext(NSURL* storeUrl self.error = nil; } -- (void)notifyCallOfResult:(id)args +- (void)notifyCallOfResult { if (self.error) { [self.managerCall notifyFailure: self.error]; diff --git a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m index d8244a0fbc4..af33e8b762c 100644 --- a/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m +++ b/openbis-ipad/BisKit/Tests/CISDOBIpadServiceManagerTest.m @@ -248,4 +248,26 @@ [self checkFindingChildren]; } +- (void)testNilUrl +{ + [self.serviceManager setOpenbisUrl: nil trusted: YES]; + + CISDOBAsyncCall *call; + + [self assertNotLoggedIn]; + call = [self.serviceManager loginUser: GetDefaultUserName() password: GetDefaultUserPassword()]; + [self configureAndRunCallSynchronously: call]; + [self assertLoggedIn]; + + [self assertBeforeRootLevelCall]; + call = [self.serviceManager retrieveRootLevelEntities]; + [self configureAndRunCallSynchronously: call]; + STAssertTrue(self.willRetrieveRootLevel, @"Should have retrieved root level"); + STAssertTrue(self.didRetrieveRootLevel, @"Should have retrieved root level"); + // No synch should have happened + + STAssertNotNil(_callError, @"The service manager should have failed to return entities."); +} + + @end -- GitLab