//
// ServiceProxyBase.h
#import <Foundation/Foundation.h>
#define kErrorMessage @"ErrorMessage"
#define kResponseValue @"ResponseValue"
#define kResult @"Result"
@interface ServiceProxyBase : NSObject
{
@protected
NSString *baseUrlString;
NSString *serviceUrlName;
}
+ (id)proxy;
- (id)init;
- (BOOL)isValidResult:(NSDictionary *)json;
- (NSArray *)executeServiceWithName:(NSString const *)serviceName parameters:(NSArray *)params;
- (NSArray *)extractResults:(NSData *)jsonData;
@end
// ServiceProxyBase.m
#import "ServiceProxyBase.h"
#import "NSString+Helpers.h"
#import "Logger.h"
#import "Constants.h"
@implementation ServiceProxyBase
+ (id)proxy
{
return nil;
}
- (id)init
{
self = [super init];
if (self)
{
baseUrlString = [[NSUserDefaults standardUserDefaults] objectForKey:BaseUrlKey];
}
return self;
}
- (NSURL *)constructUrlForFunctionWithName:(const NSString *)functionName andParameters:(NSArray *)params
{
if ([baseUrlString isEmpty] || [functionName isEmpty])
{
NSLog(NSLocalizedString(@"ErrorBaseUrlMissing", @"Missing component(s) to construct url"));
return nil;
}
if (![baseUrlString hasSuffix:@"/"])
baseUrlString = [baseUrlString stringByAppendingString:@"/"];
if (![serviceUrlName hasSuffix:@"/"])
serviceUrlName = [serviceUrlName stringByAppendingString:@"/"];
NSMutableString *paramString = nil;
if (params && params.count > 0)
{
paramString = [NSMutableString string];
for (NSString *value in params)
{
[paramString appendFormat:@"/%@", value];
}
paramString = [NSMutableString stringWithString:[paramString substringToIndex:paramString.length]];
}
NSMutableString *urlString =
[NSMutableString stringWithFormat:@"%@%@%@%@", baseUrlString, serviceUrlName, functionName,
paramString ? paramString : @""];
return [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
- (BOOL)isValidResult:(NSDictionary *)json
{
return [[json objectForKey:kErrorMessage] isKindOfClass:[NSNull class]];
}
- (NSArray *)executeServiceWithName:(NSString const *)serviceName parameters:(NSArray *)params
{
NSURL *url = [self constructUrlForFunctionWithName:serviceName
andParameters:params];
NSLog(@"executing url %@", url.absoluteString);
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:15];
NSURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error)
{
[Logger logMessage:error.localizedDescription ofType:LogMessageTypeError];
return nil;
}
if (!data)
{
NSString *message =
[NSString stringWithFormat:@"No data is returned for url %@", url];
[Logger logMessage:message ofType:LogMessageTypeError];
return nil;
}
return [self extractResults:data];
}
- (NSArray *)extractResults:(NSData *)jsonData
{
NSError *error;
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments
error:&error];
if (error)
{
NSDictionary *userInfo = @{kResponseValue : [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding]};
[Logger logMessage:error.localizedDescription ofType:LogMessageTypeError additionalInfo:userInfo];
return nil;
}
return [[jsonObject objectForKey:kResult] isKindOfClass:[NSNull class]] ? nil : [jsonObject objectForKey:kResult];
}
@end
//Logger.h
#import <Foundation/Foundation.h>
typedef enum
{
LogMessageTypeInfo,
LogMessageTypeWarn,
LogMessageTypeError
} LogMessageType;
@interface Logger : NSObject
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type;
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type additionalInfo:(NSDictionary *)userInfo;
@end
//Logger.m
#import "Logger.h"
@implementation Logger
{
}
// TODO: expand this to service calls
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type
{
NSString *typeString = [self stringFromMessageType:type];
NSLog(@"%@: %@", typeString, message);
}
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type additionalInfo:(NSDictionary *)userInfo
{
NSLog(@"%@: %@, additional information = <%@>", [self stringFromMessageType:type], message, userInfo);
}
#pragma mark - helper
+ (NSString *)stringFromMessageType:(LogMessageType)type
{
NSString *typeString;
switch (type)
{
case LogMessageTypeError:
typeString = @"Error";
break;
case LogMessageTypeInfo:
typeString = @"Info";
break;
case LogMessageTypeWarn:
typeString = @"Warning";
break;
}
return typeString;
}
@end
//NSString+Helpers.h
#import <Foundation/Foundation.h>
@interface NSString (Helpers)
- (BOOL)isEmpty;
+ (NSString *)stringFromBool:(BOOL)b;
@end
//NSString+Helpers.m
#import "NSString+Helpers.h"
@implementation NSString (Helpers)
- (BOOL)isEmpty
{
return self.length == 0;
}
+ (NSString *)stringFromBool:(BOOL)b
{
return b ? @"true" : @"false";
}
+ (NSString *)stringFromPaymentType:(PaymentType)type
{
switch (type)
{
case PaymentTypeCash:
return @"PaymentTypeCash";
case PaymentTypeCard:
return @"PaymentTypeCard";
}
return nil;
}
@end
//Constact.h
#define MainApp @"AppMain"
#define BaseUrlKey @"baseUrl"
#define Login @"Login"
#define LoggedIn @"LoggedIn"
#define StoreID @"1"
//Call the above service
NSArray *result = [self executeServiceWithName:serviceName
parameters:itemDetailArray];
or
dispatch_queue_t queue = dispatch_queue_create("au.com.estrado.productServices.SaveTransaction", NULL);
NSMutableArray *transactionDetailsArray=[[NSMutableArray alloc] initWithArray:self.items];
dispatch_async(queue, ^
{
//TODO: remove hard coding of customer and staff IDs
//TODO: check the state of the execution, if it fails then do not clear the transaction
NSLog(@"%@",transactionDetailsArray);
[[ItemDataController dataController] processTransactionWithDetails:transactionDetailsArray
forCustomerWithId:1
servedByStaffWithId:2
withPaymentType:paymentType
isRefund:isRefund];
});
// ServiceProxyBase.h
#import <Foundation/Foundation.h>
#define kErrorMessage @"ErrorMessage"
#define kResponseValue @"ResponseValue"
#define kResult @"Result"
@interface ServiceProxyBase : NSObject
{
@protected
NSString *baseUrlString;
NSString *serviceUrlName;
}
+ (id)proxy;
- (id)init;
- (BOOL)isValidResult:(NSDictionary *)json;
- (NSArray *)executeServiceWithName:(NSString const *)serviceName parameters:(NSArray *)params;
- (NSArray *)extractResults:(NSData *)jsonData;
@end
// ServiceProxyBase.m
#import "ServiceProxyBase.h"
#import "NSString+Helpers.h"
#import "Logger.h"
#import "Constants.h"
@implementation ServiceProxyBase
+ (id)proxy
{
return nil;
}
- (id)init
{
self = [super init];
if (self)
{
baseUrlString = [[NSUserDefaults standardUserDefaults] objectForKey:BaseUrlKey];
}
return self;
}
- (NSURL *)constructUrlForFunctionWithName:(const NSString *)functionName andParameters:(NSArray *)params
{
if ([baseUrlString isEmpty] || [functionName isEmpty])
{
NSLog(NSLocalizedString(@"ErrorBaseUrlMissing", @"Missing component(s) to construct url"));
return nil;
}
if (![baseUrlString hasSuffix:@"/"])
baseUrlString = [baseUrlString stringByAppendingString:@"/"];
if (![serviceUrlName hasSuffix:@"/"])
serviceUrlName = [serviceUrlName stringByAppendingString:@"/"];
NSMutableString *paramString = nil;
if (params && params.count > 0)
{
paramString = [NSMutableString string];
for (NSString *value in params)
{
[paramString appendFormat:@"/%@", value];
}
paramString = [NSMutableString stringWithString:[paramString substringToIndex:paramString.length]];
}
NSMutableString *urlString =
[NSMutableString stringWithFormat:@"%@%@%@%@", baseUrlString, serviceUrlName, functionName,
paramString ? paramString : @""];
return [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
- (BOOL)isValidResult:(NSDictionary *)json
{
return [[json objectForKey:kErrorMessage] isKindOfClass:[NSNull class]];
}
- (NSArray *)executeServiceWithName:(NSString const *)serviceName parameters:(NSArray *)params
{
NSURL *url = [self constructUrlForFunctionWithName:serviceName
andParameters:params];
NSLog(@"executing url %@", url.absoluteString);
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:15];
NSURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error)
{
[Logger logMessage:error.localizedDescription ofType:LogMessageTypeError];
return nil;
}
if (!data)
{
NSString *message =
[NSString stringWithFormat:@"No data is returned for url %@", url];
[Logger logMessage:message ofType:LogMessageTypeError];
return nil;
}
return [self extractResults:data];
}
- (NSArray *)extractResults:(NSData *)jsonData
{
NSError *error;
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments
error:&error];
if (error)
{
NSDictionary *userInfo = @{kResponseValue : [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding]};
[Logger logMessage:error.localizedDescription ofType:LogMessageTypeError additionalInfo:userInfo];
return nil;
}
return [[jsonObject objectForKey:kResult] isKindOfClass:[NSNull class]] ? nil : [jsonObject objectForKey:kResult];
}
@end
//Logger.h
#import <Foundation/Foundation.h>
typedef enum
{
LogMessageTypeInfo,
LogMessageTypeWarn,
LogMessageTypeError
} LogMessageType;
@interface Logger : NSObject
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type;
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type additionalInfo:(NSDictionary *)userInfo;
@end
//Logger.m
#import "Logger.h"
@implementation Logger
{
}
// TODO: expand this to service calls
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type
{
NSString *typeString = [self stringFromMessageType:type];
NSLog(@"%@: %@", typeString, message);
}
+ (void)logMessage:(NSString *)message ofType:(LogMessageType)type additionalInfo:(NSDictionary *)userInfo
{
NSLog(@"%@: %@, additional information = <%@>", [self stringFromMessageType:type], message, userInfo);
}
#pragma mark - helper
+ (NSString *)stringFromMessageType:(LogMessageType)type
{
NSString *typeString;
switch (type)
{
case LogMessageTypeError:
typeString = @"Error";
break;
case LogMessageTypeInfo:
typeString = @"Info";
break;
case LogMessageTypeWarn:
typeString = @"Warning";
break;
}
return typeString;
}
@end
//NSString+Helpers.h
#import <Foundation/Foundation.h>
@interface NSString (Helpers)
- (BOOL)isEmpty;
+ (NSString *)stringFromBool:(BOOL)b;
@end
//NSString+Helpers.m
#import "NSString+Helpers.h"
@implementation NSString (Helpers)
- (BOOL)isEmpty
{
return self.length == 0;
}
+ (NSString *)stringFromBool:(BOOL)b
{
return b ? @"true" : @"false";
}
+ (NSString *)stringFromPaymentType:(PaymentType)type
{
switch (type)
{
case PaymentTypeCash:
return @"PaymentTypeCash";
case PaymentTypeCard:
return @"PaymentTypeCard";
}
return nil;
}
@end
//Constact.h
#define MainApp @"AppMain"
#define BaseUrlKey @"baseUrl"
#define Login @"Login"
#define LoggedIn @"LoggedIn"
#define StoreID @"1"
//Call the above service
NSArray *result = [self executeServiceWithName:serviceName
parameters:itemDetailArray];
or
dispatch_queue_t queue = dispatch_queue_create("au.com.estrado.productServices.SaveTransaction", NULL);
NSMutableArray *transactionDetailsArray=[[NSMutableArray alloc] initWithArray:self.items];
dispatch_async(queue, ^
{
//TODO: remove hard coding of customer and staff IDs
//TODO: check the state of the execution, if it fails then do not clear the transaction
NSLog(@"%@",transactionDetailsArray);
[[ItemDataController dataController] processTransactionWithDetails:transactionDetailsArray
forCustomerWithId:1
servedByStaffWithId:2
withPaymentType:paymentType
isRefund:isRefund];
});