Skip to content

Commit

Permalink
Implementing serialization in background queue for async web service …
Browse files Browse the repository at this point in the history
…calls
  • Loading branch information
Yuru Taustahuzau committed Aug 10, 2014
1 parent f1a7c0b commit c29578b
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 61 deletions.
8 changes: 8 additions & 0 deletions Framework/ROADCore/ROADCore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

/* Begin PBXBuildFile section */
1176413D18E4700500B1688B /* libUtilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1176413C18E4700500B1688B /* libUtilities.a */; };
117BD9231997A84E001CA6C5 /* NSArray+RFClassSearch.m in Sources */ = {isa = PBXBuildFile; fileRef = 117BD9221997A84E001CA6C5 /* NSArray+RFClassSearch.m */; };
117BD9241997B248001CA6C5 /* NSArray+RFClassSearch.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 117BD9211997A84E001CA6C5 /* NSArray+RFClassSearch.h */; };
46AA65574E8B424882F7485B /* ROADGeneratedAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = E9BC2CF400F040A48EDF4B23 /* ROADGeneratedAttribute.m */; };
5BA3059C198FC1AB00F02E46 /* RFStringFormatterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BA3059B198FC1AB00F02E46 /* RFStringFormatterTests.m */; };
78180F0816C3D0A300B4AA31 /* ROADCore.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 78B8E72216C3CD4A0049E36B /* ROADCore.h */; };
Expand Down Expand Up @@ -63,6 +65,7 @@
dstPath = include/ROAD;
dstSubfolderSpec = 16;
files = (
117BD9241997B248001CA6C5 /* NSArray+RFClassSearch.h in CopyFiles */,
83E0CDE918D0833900B25689 /* RFLog.h in CopyFiles */,
78180F0816C3D0A300B4AA31 /* ROADCore.h in CopyFiles */,
78180F0916C3D0A800B4AA31 /* NSArray+RFEmptyArrayChecks.h in CopyFiles */,
Expand All @@ -79,6 +82,8 @@
/* Begin PBXFileReference section */
1176413618E4635400B1688B /* libUtilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libUtilities.a; path = "../Utilities/build/Debug-iphoneos/libUtilities.a"; sourceTree = "<group>"; };
1176413C18E4700500B1688B /* libUtilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libUtilities.a; path = "../Utilities/build/Debug-iphoneos/libUtilities.a"; sourceTree = "<group>"; };
117BD9211997A84E001CA6C5 /* NSArray+RFClassSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+RFClassSearch.h"; sourceTree = "<group>"; };
117BD9221997A84E001CA6C5 /* NSArray+RFClassSearch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+RFClassSearch.m"; sourceTree = "<group>"; };
5BA3059B198FC1AB00F02E46 /* RFStringFormatterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RFStringFormatterTests.m; sourceTree = "<group>"; };
634461C3604B4DB58DF380FC /* Pods-ROADCore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ROADCore.xcconfig"; path = "../Pods/Pods-ROADCore.xcconfig"; sourceTree = "<group>"; };
78B8E68E16C3CC3E0049E36B /* libROADCore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libROADCore.a; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -210,6 +215,8 @@
78B8E70116C3CD320049E36B /* NSDictionary+RFKeyedSubscript.m */,
78B8E70216C3CD320049E36B /* NSMutableDictionary+RFKeyedSubscript.h */,
78B8E70316C3CD320049E36B /* NSMutableDictionary+RFKeyedSubscript.m */,
117BD9211997A84E001CA6C5 /* NSArray+RFClassSearch.h */,
117BD9221997A84E001CA6C5 /* NSArray+RFClassSearch.m */,
);
name = CollectionCategories;
sourceTree = "<group>";
Expand Down Expand Up @@ -390,6 +397,7 @@
buildActionMask = 2147483647;
files = (
78B8E6DC16C3CCE60049E36B /* RFDynamicObject.m in Sources */,
117BD9231997A84E001CA6C5 /* NSArray+RFClassSearch.m in Sources */,
78B8E6E016C3CCE60049E36B /* RFObjectPool.m in Sources */,
78B8E70716C3CD320049E36B /* NSArray+RFEmptyArrayChecks.m in Sources */,
78B8E71716C3CD320049E36B /* NSDictionary+RFKeyedSubscript.m in Sources */,
Expand Down
38 changes: 38 additions & 0 deletions Framework/ROADCore/ROADCore/Categories/NSArray+RFClassSearch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// NSArray+RFClassSearch.h
// ROADCore
//
// Copyright (c) 2014 EPAM Systems, Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
// Neither the name of the EPAM Systems, Inc. nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// See the NOTICE file and the LICENSE file distributed with this work
// for additional information regarding copyright ownership and licensing


@interface NSArray (RFClassSearch)

- (id)RF_firstObjectWithClass:(__unsafe_unretained Class)objectClass;

@end
49 changes: 49 additions & 0 deletions Framework/ROADCore/ROADCore/Categories/NSArray+RFClassSearch.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// NSArray+RFClassSearch.m
// ROADCore
//
// Copyright (c) 2014 EPAM Systems, Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
// Neither the name of the EPAM Systems, Inc. nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// See the NOTICE file and the LICENSE file distributed with this work
// for additional information regarding copyright ownership and licensing


#import "NSArray+RFClassSearch.h"


@implementation NSArray (RFClassSearch)

- (id)RF_firstObjectWithClass:(__unsafe_unretained Class)objectClass {
for (id object in self) {
if ([object class] == objectClass) {
return object;
}
}

return nil;
}

@end
1 change: 1 addition & 0 deletions Framework/ROADCore/ROADCore/ROADCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#import "NSMutableString+RFStringFormatter.h"
#import "NSArray+RFEmptyArrayChecks.h"
#import "NSArray+RFClassSearch.h"
#import "RFDynamicObject.h"
#import "RFObjectPool.h"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/libObjCAttr/tools/binaries/ROADAttributesCodeGenerator\" -src=\"${SRCROOT}\" -src=\"${PODS_ROOT}\" -dst=\"${SRCROOT}/${TARGET_NAME}/ROADGeneratedAttributes/\"";
shellScript = "\"${PODS_ROOT}/libObjCAttr/tools/binaries/ROADAttributesCodeGenerator\" -src=\"${SRCROOT}\" -dst=\"${SRCROOT}/${TARGET_NAME}/ROADGeneratedAttributes/\"";
};
/* End PBXShellScriptBuildPhase section */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@


#import "RFDownloader+ConnectionDelegate.h"
#import <ROAD/ROADCore.h>

#import "RFWebServiceLog.h"
#import "NSError+RFWebService.h"
Expand Down Expand Up @@ -88,7 +89,7 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)aConnection {
// Checking response with error handler
RFWebServiceErrorHandler *errorHandlerAttribute = [[self.webServiceClient class] RF_attributeForClassWithAttributeType:[RFWebServiceErrorHandler class]];
if (!errorHandlerAttribute) {
errorHandlerAttribute = [[self.webServiceClient class] RF_attributeForMethod:self.methodName withAttributeType:[RFWebServiceErrorHandler class]];
errorHandlerAttribute = [self.attributes RF_firstObjectWithClass:[RFWebServiceErrorHandler class]];
}

if (errorHandlerAttribute.handlerClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,16 @@
*/
@property (assign, nonatomic, getter = isMultipartData) BOOL multipartData;

/**
* Web service client responsible for performing request.
*/
@property (nonatomic, strong, readonly) RFWebServiceClient *webServiceClient;
@property (nonatomic, strong, readonly) NSString *methodName;
/**
The serialized data from the request,
* Web service call attributes.
*/
@property (nonatomic, copy, readonly) NSArray *attributes;
/**
The serialized data from the request.
*/
@property (strong, nonatomic) id serializedData;
/**
Expand All @@ -68,7 +74,7 @@
*/
@property (atomic, assign, readonly, getter = isRequestCancelled) BOOL requestCancelled;

- (id)initWithClient:(RFWebServiceClient *)webServiceClient methodName:(NSString *)methodName authenticationProvider:(id<RFAuthenticating>)authenticaitonProvider;
- (id)initWithClient:(RFWebServiceClient *)client attributes:(NSArray *)attributes authenticationProvider:(id<RFAuthenticating>)authenticationProvider;

- (void)configureRequestForUrl:(NSURL * const)anUrl body:(NSData *)httpBody sharedHeaders:(NSDictionary *)sharedHeaders values:(NSDictionary *)values;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ - (void)stop;

@implementation RFDownloader

- (id)initWithClient:(RFWebServiceClient *)webServiceClient methodName:(NSString *)methodName authenticationProvider:(id<RFAuthenticating>)authenticaitonProvider {
- (id)initWithClient:(RFWebServiceClient *)client attributes:(NSArray *)attributes authenticationProvider:(id<RFAuthenticating>)authenticationProvider {
self = [super init];

if (self) {
_webServiceClient = webServiceClient;
_methodName = methodName;
_authenticationProvider = authenticaitonProvider;
_webServiceClient = client;
_attributes = attributes;
_authenticationProvider = authenticationProvider;
_successCodes = [NSMutableArray arrayWithObjects:[NSValue valueWithRange:NSMakeRange(200, 100)], nil];
_callAttribute = [[_webServiceClient class] RF_attributeForMethod:_methodName withAttributeType:[RFWebServiceCall class]];
_callAttribute = [attributes RF_firstObjectWithClass:[RFWebServiceCall class]];
}

return self;
Expand All @@ -100,7 +100,7 @@ - (void)configureRequestForUrl:(NSURL * const)anUrl body:(NSData * const)httpBod
// For multipart form data we have to add specific header
if (_multipartData) {
NSString *boundary;
RFMultipartData *multipartDataAttribute = [[_webServiceClient class] RF_attributeForMethod:_methodName withAttributeType:[RFMultipartData class]];
RFMultipartData *multipartDataAttribute = [self.attributes RF_firstObjectWithClass:[RFMultipartData class]];
boundary = multipartDataAttribute.boundary;
if (!boundary.length) {
// Some random default boundary
Expand All @@ -111,7 +111,7 @@ - (void)configureRequestForUrl:(NSURL * const)anUrl body:(NSData * const)httpBod
[_request addValue:contentType forHTTPHeaderField:@"Content-Type"];
}

RFWebServiceHeader * const headerAttribute = [[_webServiceClient class] RF_attributeForMethod:_methodName withAttributeType:[RFWebServiceHeader class]];
RFWebServiceHeader * const headerAttribute = [self.attributes RF_firstObjectWithClass:[RFWebServiceHeader class]];

// Adding shared headers to request
NSMutableDictionary *headerFields = [sharedHeaders mutableCopy];
Expand All @@ -128,7 +128,7 @@ - (void)configureRequestForUrl:(NSURL * const)anUrl body:(NSData * const)httpBod
[self.successCodes removeAllObjects];
[self.successCodes addObjectsFromArray:_callAttribute.successCodes];
} else {
RFWebServiceClientStatusCodes* wsca = [[self.webServiceClient class] RF_attributeForClassWithAttributeType:[RFWebServiceClientStatusCodes class]];
RFWebServiceClientStatusCodes* wsca = [self.attributes RF_firstObjectWithClass:[RFWebServiceClientStatusCodes class]];

if ([wsca.successCodes count] > 0) {
[self.successCodes removeAllObjects];
Expand All @@ -143,10 +143,9 @@ - (void)checkCacheAndStart {
return;
}

RFWebServiceCache *cacheAttribute = [[_webServiceClient class] RF_attributeForMethod:_methodName withAttributeType:[RFWebServiceCache class]];
id<RFWebServiceCachingManaging> cacheManager = [RFServiceProvider webServiceCacheManager];
RFWebResponse *cachedResponse;
if (!cacheAttribute.cacheDisabled) {
if (!self.cacheAttribute.cacheDisabled) {
cachedResponse = [cacheManager cacheWithRequest:_request];
}

Expand All @@ -168,8 +167,7 @@ - (void)start {
_looper = [[RFLooper alloc] init];
_data = [NSMutableData data];

RFWebServiceCall *callAttribute = [[_webServiceClient class] RF_attributeForMethod:_methodName withAttributeType:[RFWebServiceCall class]];
if (!callAttribute.syncCall) {
if (!_callAttribute.syncCall) {
_connection = [[NSURLConnection alloc] initWithRequest:_request delegate:self startImmediately:NO];
[_connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[_connection start];
Expand Down Expand Up @@ -237,7 +235,7 @@ - (void)downloaderFinishedWithResult:(NSData *)result response:(NSHTTPURLRespons
}

- (id<RFSerializationDelegate>)serializationDelegate {
RFWebServiceSerializer *serializerAttribute = [[self.webServiceClient class] RF_attributeForMethod:self.methodName withAttributeType:[RFWebServiceSerializer class]];
RFWebServiceSerializer *serializerAttribute = [self.attributes RF_firstObjectWithClass:[RFWebServiceSerializer class]];
id<RFSerializationDelegate> serializationDelegate;
if (serializerAttribute.serializerClass) {
serializationDelegate = [[serializerAttribute.serializerClass alloc] init];
Expand Down Expand Up @@ -314,14 +312,24 @@ -(void)performSuccessBlockOnSpecificThread {
if (self.successBlock) {
self.successBlock(_serializedData);
}

[self freeCompletionBlocks];
}

-(void)performFailureBlockOnSpecificThread {
if (self.failureBlock) {
self.failureBlock(_downloadError);
}

[self freeCompletionBlocks];
}

- (void)freeCompletionBlocks {
self.successBlock = nil;
self.failureBlock = nil;
}


#pragma mark - Utitlity

NSString * const RFAttributeTemplateEscape = @"%%";
Expand Down Expand Up @@ -377,7 +385,7 @@ - (void)cancelWithReason:(id)reason {

- (RFWebServiceCache *)cacheAttribute {
if (!_cacheAttribute) {
_cacheAttribute = [[_webServiceClient class] RF_attributeForMethod:_methodName withAttributeType:[RFWebServiceCache class]];
_cacheAttribute = [self.attributes RF_firstObjectWithClass:[RFWebServiceCache class]];
}

return _cacheAttribute;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@ static NSString * const kRFBoundaryDefaultString;


/**
Parameter encoder to create parameters for the webservice.
*Parameter encoder to create parameters for the webservice.
*/
@interface RFWebServiceCallParameterEncoder : NSObject

/**
It will create a parameter dictionary based on the parameter list array. If it needs to be serialized, the serializator object will be used. If one object is NSData, it will be sent back as a post data.
@param parameterList The list of parameters
@param webClient The web client which handle service request
@param methodName The method name is selector name which was invoked
@param serializator The serializator object
@param callbackBlock The callback block which will be called.
* It will create a parameter dictionary based on the parameter list array.
* If it needs to be serialized, the serializator object will be used.
* If one object is NSData, it will be sent back as a post data.
* @param parameterList The list of parameters
* @param attributes The attributes that determine current web service call
* @param serializator The serializator object
* @param callbackBlock The callback block which will be called.
*/
+ (void)encodeParameters:(NSArray *)parameterList forClient:(RFWebServiceClient *)webClient methodName:(NSString *)methodName withSerializator:(id<RFSerializationDelegate>)serializator callbackBlock:(void(^)(NSDictionary *parameters, NSData *postData, BOOL isMultipartData))callbackBlock;

+ (void)encodeParameters:(NSArray *)parameterList attributes:(NSArray *)attributes withSerializator:(id<RFSerializationDelegate>)serializator callbackBlock:(void(^)(NSDictionary *parameters, NSData *postData, BOOL isMultipartData))callbackBlock;
@end
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@


#import "RFWebServiceCallParameterEncoder.h"
#import <ROAD/ROADCore.h>

#import "RFSerializationDelegate.h"
#import "RFWebServiceURLBuilderParameter.h"
#import "RFFormData.h"
Expand All @@ -44,7 +46,7 @@

@implementation RFWebServiceCallParameterEncoder

+ (void)encodeParameters:(NSArray *)parameterList forClient:(RFWebServiceClient *)webClient methodName:(NSString *)methodName withSerializator:(id<RFSerializationDelegate>)serializator callbackBlock:(void(^)(NSDictionary *parameters, NSData *postData, BOOL isMultipartData))callbackBlock {
+ (void)encodeParameters:(NSArray *)parameterList attributes:(NSArray *)attributes withSerializator:(id<RFSerializationDelegate>)serializator callbackBlock:(void (^)(NSDictionary *, NSData *, BOOL))callbackBlock {

NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:[parameterList count]];
NSMutableData *bodyData;
Expand Down Expand Up @@ -75,7 +77,7 @@ + (void)encodeParameters:(NSArray *)parameterList forClient:(RFWebServiceClient
bodyData = [[NSMutableData alloc] init];
}

boundary = [self boundaryFromWebServiceClient:webClient withMethodName:methodName];
boundary = [self boundaryFromAttributes:attributes];
isMultipartData = YES;
[self addAttachment:object toBodyData:bodyData boundary:boundary];
}
Expand All @@ -88,7 +90,7 @@ + (void)encodeParameters:(NSArray *)parameterList forClient:(RFWebServiceClient
bodyData = [[NSMutableData alloc] init];
}

boundary = [self boundaryFromWebServiceClient:webClient withMethodName:methodName];
boundary = [self boundaryFromAttributes:attributes];
isMultipartData = YES;
[self addAttachments:object toBodyData:bodyData boundary:boundary];
}
Expand Down Expand Up @@ -139,8 +141,8 @@ + (void)addAttachment:(RFFormData *)attachment toBodyData:(NSMutableData *)bodyD
[bodyData appendData:nextAttachment];
}

+ (NSString *)boundaryFromWebServiceClient:(id)webServiceClient withMethodName:(NSString *)methodName {
RFMultipartData *multipartDataAttribute = [[webServiceClient class] RF_attributeForMethod:methodName withAttributeType:[RFMultipartData class]];
+ (NSString *)boundaryFromAttributes:(NSArray *)attributes {
RFMultipartData *multipartDataAttribute = [attributes RF_firstObjectWithClass:[RFMultipartData class]];
NSString *boundary;
if (!multipartDataAttribute.boundary) {
// Default boundary
Expand Down
Loading

0 comments on commit c29578b

Please sign in to comment.