314 lines
10 KiB
Objective-C
314 lines
10 KiB
Objective-C
/* Copyright (c) 2011 Google Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#if !__has_feature(objc_arc)
|
|
#error "This file needs to be compiled with ARC enabled."
|
|
#endif
|
|
|
|
#include <objc/runtime.h>
|
|
|
|
#import "GTLRQuery.h"
|
|
#import "GTLRRuntimeCommon.h"
|
|
#import "GTLRService.h"
|
|
#import "GTLRUtilities.h"
|
|
|
|
@interface GTLRQuery () <GTLRRuntimeCommon>
|
|
@end
|
|
|
|
@implementation GTLRQuery {
|
|
NSMutableDictionary *_childCache;
|
|
GTLRServiceExecutionParameters *_executionParameters;
|
|
}
|
|
|
|
@synthesize additionalURLQueryParameters = _additionalURLQueryParameters,
|
|
additionalHTTPHeaders = _additionalHTTPHeaders,
|
|
bodyObject = _bodyObject,
|
|
completionBlock = _completionBlock,
|
|
downloadAsDataObjectType = _downloadAsDataObjectType,
|
|
expectedObjectClass = _expectedObjectClass,
|
|
httpMethod = _httpMethod,
|
|
JSON = _json,
|
|
loggingName = _loggingName,
|
|
pathParameterNames = _pathParameterNames,
|
|
pathURITemplate = _pathURITemplate,
|
|
queryInvalid = _queryInvalid,
|
|
requestID = _requestID,
|
|
resumableUploadPathURITemplateOverride = _resumableUploadPathURITemplateOverride,
|
|
shouldSkipAuthorization = _shouldSkipAuthorization,
|
|
simpleUploadPathURITemplateOverride = _simpleUploadPathURITemplateOverride,
|
|
uploadParameters = _uploadParameters,
|
|
useMediaDownloadService = _useMediaDownloadService;
|
|
|
|
#if DEBUG
|
|
- (instancetype)init {
|
|
[self doesNotRecognizeSelector:_cmd];
|
|
self = nil;
|
|
return self;
|
|
}
|
|
#endif
|
|
|
|
- (instancetype)initWithPathURITemplate:(NSString *)pathURITemplate
|
|
HTTPMethod:(nullable NSString *)httpMethod
|
|
pathParameterNames:(nullable NSArray<NSString *> *)pathParameterNames {
|
|
self = [super init];
|
|
if (self) {
|
|
_requestID = [[self class] nextRequestID];
|
|
|
|
_pathURITemplate = [pathURITemplate copy];
|
|
_httpMethod = [httpMethod copy];
|
|
_pathParameterNames = [pathParameterNames copy];
|
|
|
|
if (_pathURITemplate.length == 0) {
|
|
self = nil;
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (id)copyWithZone:(NSZone *)zone {
|
|
GTLR_DEBUG_ASSERT(!self.queryInvalid, @"Cannot copy an executed query: %@", self);
|
|
|
|
GTLRQuery *query =
|
|
[[[self class] allocWithZone:zone] initWithPathURITemplate:self.pathURITemplate
|
|
HTTPMethod:self.httpMethod
|
|
pathParameterNames:self.pathParameterNames];
|
|
|
|
if (_json.count > 0) {
|
|
// Deep copy the parameters
|
|
CFPropertyListRef ref = CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
|
|
(__bridge CFPropertyListRef)(_json),
|
|
kCFPropertyListMutableContainers);
|
|
query.JSON = CFBridgingRelease(ref);
|
|
}
|
|
|
|
// Using the executionParameters ivar avoids creating the object.
|
|
query.executionParameters = self.executionParameters;
|
|
|
|
// Copied in the same order as synthesized above.
|
|
query.additionalHTTPHeaders = self.additionalHTTPHeaders;
|
|
query.additionalURLQueryParameters = self.additionalURLQueryParameters;
|
|
query.bodyObject = self.bodyObject;
|
|
query.completionBlock = self.completionBlock;
|
|
query.downloadAsDataObjectType = self.downloadAsDataObjectType;
|
|
query.expectedObjectClass = self.expectedObjectClass;
|
|
// http method passed to init above.
|
|
// JSON copied above.
|
|
query.loggingName = self.loggingName;
|
|
// pathParameterNames passed to init above.
|
|
// pathURITemplate passed to init above.
|
|
query.queryInvalid = self.queryInvalid;
|
|
query.requestID = self.requestID;
|
|
query.resumableUploadPathURITemplateOverride = self.resumableUploadPathURITemplateOverride;
|
|
query.shouldSkipAuthorization = self.shouldSkipAuthorization;
|
|
query.simpleUploadPathURITemplateOverride = self.simpleUploadPathURITemplateOverride;
|
|
query.uploadParameters = self.uploadParameters;
|
|
query.useMediaDownloadService = self.useMediaDownloadService;
|
|
|
|
return query;
|
|
}
|
|
|
|
#if DEBUG
|
|
- (NSString *)description {
|
|
NSArray *keys = self.JSON.allKeys;
|
|
NSArray *params = [keys sortedArrayUsingSelector:@selector(compare:)];
|
|
NSString *paramsSummary = @"";
|
|
if (params.count > 0) {
|
|
paramsSummary = [NSString stringWithFormat:@" params:(%@)",
|
|
[params componentsJoinedByString:@","]];
|
|
}
|
|
|
|
NSString *invalidStr = @"";
|
|
if (self.queryInvalid) {
|
|
invalidStr = @" [callbacks released]";
|
|
}
|
|
|
|
keys = self.additionalURLQueryParameters.allKeys;
|
|
NSArray *urlQParams = [keys sortedArrayUsingSelector:@selector(compare:)];
|
|
NSString *urlQParamsSummary = @"";
|
|
if (urlQParams.count > 0) {
|
|
urlQParamsSummary = [NSString stringWithFormat:@" urlQParams:(%@)",
|
|
[urlQParams componentsJoinedByString:@","]];
|
|
}
|
|
|
|
GTLRObject *bodyObj = self.bodyObject;
|
|
NSString *bodyObjSummary = @"";
|
|
if (bodyObj != nil) {
|
|
bodyObjSummary = [NSString stringWithFormat:@" bodyObject:%@", [bodyObj class]];
|
|
}
|
|
|
|
NSString *uploadStr = @"";
|
|
GTLRUploadParameters *uploadParams = self.uploadParameters;
|
|
if (uploadParams) {
|
|
uploadStr = [NSString stringWithFormat:@" %@", uploadParams];
|
|
}
|
|
|
|
NSString *httpMethod = self.httpMethod;
|
|
if (httpMethod == nil) {
|
|
httpMethod = @"GET";
|
|
}
|
|
|
|
NSString *dataObjectType = self.downloadAsDataObjectType;
|
|
NSString *downloadStr = @"";
|
|
if (dataObjectType.length > 0) {
|
|
downloadStr =
|
|
[NSString stringWithFormat:@" downloadDataAs:%@", dataObjectType];
|
|
}
|
|
|
|
return [NSString stringWithFormat:@"%@ %p:%@%@ {%@ pathTemplate:%@%@%@%@%@}",
|
|
[self class], self, invalidStr, downloadStr,
|
|
httpMethod, self.pathURITemplate,
|
|
paramsSummary, urlQParamsSummary, bodyObjSummary, uploadStr];
|
|
}
|
|
#endif // DEBUG
|
|
|
|
- (BOOL)isBatchQuery {
|
|
return NO;
|
|
}
|
|
|
|
- (void)invalidateQuery {
|
|
self.queryInvalid = YES;
|
|
self.completionBlock = nil;
|
|
self.executionParameters = nil;
|
|
}
|
|
|
|
- (GTLRServiceExecutionParameters *)executionParameters {
|
|
@synchronized(self) {
|
|
if (!_executionParameters) {
|
|
_executionParameters = [[GTLRServiceExecutionParameters alloc] init];
|
|
}
|
|
return _executionParameters;
|
|
}
|
|
}
|
|
|
|
- (void)setExecutionParameters:(nullable GTLRServiceExecutionParameters *)executionParameters {
|
|
@synchronized(self) {
|
|
_executionParameters = executionParameters;
|
|
}
|
|
}
|
|
|
|
- (BOOL)hasExecutionParameters {
|
|
return self.executionParameters.hasParameters;
|
|
}
|
|
|
|
+ (NSString *)nextRequestID {
|
|
static NSUInteger lastRequestID = 0;
|
|
NSString *result;
|
|
|
|
@synchronized([GTLRQuery class]) {
|
|
++lastRequestID;
|
|
result = [NSString stringWithFormat:@"gtlr_%lu", (unsigned long)lastRequestID];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#pragma mark GTLRRuntimeCommon Support
|
|
|
|
- (void)setJSONValue:(id)obj forKey:(NSString *)key {
|
|
NSMutableDictionary *dict = self.JSON;
|
|
if (dict == nil && obj != nil) {
|
|
dict = [NSMutableDictionary dictionaryWithCapacity:1];
|
|
self.JSON = dict;
|
|
}
|
|
[dict setValue:obj forKey:key];
|
|
}
|
|
|
|
- (id)JSONValueForKey:(NSString *)key {
|
|
id obj = [self.JSON objectForKey:key];
|
|
return obj;
|
|
}
|
|
|
|
// There is no property for _childCache as there shouldn't be KVC/KVO
|
|
// support for it, since it's an implementation detail.
|
|
|
|
- (void)setCacheChild:(id)obj forKey:(NSString *)key {
|
|
if (_childCache == nil && obj != nil) {
|
|
_childCache = [[NSMutableDictionary alloc] initWithObjectsAndKeys:obj, key, nil];
|
|
} else {
|
|
[_childCache setValue:obj forKey:key];
|
|
}
|
|
}
|
|
|
|
- (id)cacheChildForKey:(NSString *)key {
|
|
id obj = [_childCache objectForKey:key];
|
|
return obj;
|
|
}
|
|
|
|
#pragma mark Methods for Subclasses to Override
|
|
|
|
+ (NSDictionary<NSString *, NSString *> *)parameterNameMap {
|
|
return nil;
|
|
}
|
|
|
|
+ (NSDictionary<NSString *, Class> *)arrayPropertyToClassMap {
|
|
return nil;
|
|
}
|
|
|
|
#pragma mark Runtime Utilities
|
|
|
|
static NSMutableDictionary *gQueryParameterNameMapCache = nil;
|
|
static NSMutableDictionary *gQueryArrayPropertyToClassMapCache = nil;
|
|
|
|
+ (void)initialize {
|
|
// Note that +initialize is guaranteed by the runtime to be called in a thread-safe manner.
|
|
if (gQueryParameterNameMapCache == nil) {
|
|
gQueryParameterNameMapCache = [[NSMutableDictionary alloc] init];
|
|
}
|
|
if (gQueryArrayPropertyToClassMapCache == nil) {
|
|
gQueryArrayPropertyToClassMapCache = [[NSMutableDictionary alloc] init];
|
|
}
|
|
}
|
|
|
|
+ (NSDictionary *)propertyToJSONKeyMapForClass:(Class<GTLRRuntimeCommon>)aClass {
|
|
NSDictionary *resultMap =
|
|
[GTLRRuntimeCommon mergedClassDictionaryForSelector:@selector(parameterNameMap)
|
|
startClass:aClass
|
|
ancestorClass:[GTLRQuery class]
|
|
cache:gQueryParameterNameMapCache];
|
|
return resultMap;
|
|
}
|
|
|
|
+ (NSDictionary *)arrayPropertyToClassMapForClass:(Class<GTLRRuntimeCommon>)aClass {
|
|
NSDictionary *resultMap =
|
|
[GTLRRuntimeCommon mergedClassDictionaryForSelector:@selector(arrayPropertyToClassMap)
|
|
startClass:aClass
|
|
ancestorClass:[GTLRQuery class]
|
|
cache:gQueryArrayPropertyToClassMapCache];
|
|
return resultMap;
|
|
}
|
|
|
|
#pragma mark Runtime Support
|
|
|
|
- (id<GTLRObjectClassResolver>)objectClassResolver {
|
|
// Stub method just needed for RuntimeCommon.
|
|
return nil;
|
|
}
|
|
|
|
+ (Class<GTLRRuntimeCommon>)ancestorClass {
|
|
return [GTLRQuery class];
|
|
}
|
|
|
|
+ (BOOL)resolveInstanceMethod:(SEL)sel {
|
|
BOOL resolved = [GTLRRuntimeCommon resolveInstanceMethod:sel onClass:self];
|
|
if (resolved) return YES;
|
|
|
|
return [super resolveInstanceMethod:sel];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation GTLRQueryCollectionImpl
|
|
@dynamic pageToken;
|
|
@end
|