GTLRQuery.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /* Copyright (c) 2011 Google Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <objc/runtime.h>
  16. //#import <GoogleAPIClientForREST/GTLRQuery.h>
  17. //#import <GoogleAPIClientForREST/GTLRRuntimeCommon.h>
  18. //#import <GoogleAPIClientForREST/GTLRService.h>
  19. //#import <GoogleAPIClientForREST/GTLRUtilities.h>
  20. #import "GTLRQuery.h"
  21. #import "GTLRRuntimeCommon.h"
  22. #import "GTLRService.h"
  23. #import "GTLRUtilities.h"
  24. #import "GTLRDefines.h"
  25. @interface GTLRQuery () <GTLRRuntimeCommon>
  26. @end
  27. @implementation GTLRQuery {
  28. NSMutableDictionary *_childCache;
  29. GTLRServiceExecutionParameters *_executionParameters;
  30. }
  31. @synthesize additionalURLQueryParameters = _additionalURLQueryParameters,
  32. additionalHTTPHeaders = _additionalHTTPHeaders,
  33. bodyObject = _bodyObject,
  34. completionBlock = _completionBlock,
  35. downloadAsDataObjectType = _downloadAsDataObjectType,
  36. expectedObjectClass = _expectedObjectClass,
  37. httpMethod = _httpMethod,
  38. JSON = _json,
  39. loggingName = _loggingName,
  40. pathParameterNames = _pathParameterNames,
  41. pathURITemplate = _pathURITemplate,
  42. queryInvalid = _queryInvalid,
  43. requestID = _requestID,
  44. resumableUploadPathURITemplateOverride = _resumableUploadPathURITemplateOverride,
  45. shouldSkipAuthorization = _shouldSkipAuthorization,
  46. simpleUploadPathURITemplateOverride = _simpleUploadPathURITemplateOverride,
  47. uploadParameters = _uploadParameters,
  48. useMediaDownloadService = _useMediaDownloadService;
  49. #if DEBUG
  50. - (instancetype)init {
  51. [self doesNotRecognizeSelector:_cmd];
  52. self = nil;
  53. return self;
  54. }
  55. #endif
  56. - (instancetype)initWithPathURITemplate:(NSString *)pathURITemplate
  57. HTTPMethod:(nullable NSString *)httpMethod
  58. pathParameterNames:(nullable NSArray<NSString *> *)pathParameterNames {
  59. self = [super init];
  60. if (self) {
  61. _requestID = [[self class] nextRequestID];
  62. _pathURITemplate = [pathURITemplate copy];
  63. _httpMethod = [httpMethod copy];
  64. _pathParameterNames = [pathParameterNames copy];
  65. if (_pathURITemplate.length == 0) {
  66. self = nil;
  67. }
  68. }
  69. return self;
  70. }
  71. - (id)copyWithZone:(NSZone *)zone {
  72. GTLR_DEBUG_ASSERT(!self.queryInvalid, @"Cannot copy an executed query: %@", self);
  73. GTLRQuery *query =
  74. [[[self class] allocWithZone:zone] initWithPathURITemplate:self.pathURITemplate
  75. HTTPMethod:self.httpMethod
  76. pathParameterNames:self.pathParameterNames];
  77. if (_json.count > 0) {
  78. // Deep copy the parameters
  79. CFPropertyListRef ref = CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
  80. (__bridge CFPropertyListRef)(_json),
  81. kCFPropertyListMutableContainers);
  82. query.JSON = CFBridgingRelease(ref);
  83. }
  84. // Using the executionParameters ivar avoids creating the object.
  85. query.executionParameters = self.executionParameters;
  86. // Copied in the same order as synthesized above.
  87. query.additionalHTTPHeaders = self.additionalHTTPHeaders;
  88. query.additionalURLQueryParameters = self.additionalURLQueryParameters;
  89. query.bodyObject = self.bodyObject;
  90. query.completionBlock = self.completionBlock;
  91. query.downloadAsDataObjectType = self.downloadAsDataObjectType;
  92. query.expectedObjectClass = self.expectedObjectClass;
  93. // http method passed to init above.
  94. // JSON copied above.
  95. query.loggingName = self.loggingName;
  96. // pathParameterNames passed to init above.
  97. // pathURITemplate passed to init above.
  98. query.queryInvalid = self.queryInvalid;
  99. query.requestID = self.requestID;
  100. query.resumableUploadPathURITemplateOverride = self.resumableUploadPathURITemplateOverride;
  101. query.shouldSkipAuthorization = self.shouldSkipAuthorization;
  102. query.simpleUploadPathURITemplateOverride = self.simpleUploadPathURITemplateOverride;
  103. query.uploadParameters = self.uploadParameters;
  104. query.useMediaDownloadService = self.useMediaDownloadService;
  105. return query;
  106. }
  107. #if DEBUG
  108. - (NSString *)description {
  109. NSArray *keys = self.JSON.allKeys;
  110. NSArray *params = [keys sortedArrayUsingSelector:@selector(compare:)];
  111. NSString *paramsSummary = @"";
  112. if (params.count > 0) {
  113. paramsSummary = [NSString stringWithFormat:@" params:(%@)",
  114. [params componentsJoinedByString:@","]];
  115. }
  116. NSString *invalidStr = @"";
  117. if (self.queryInvalid) {
  118. invalidStr = @" [callbacks released]";
  119. }
  120. keys = self.additionalURLQueryParameters.allKeys;
  121. NSArray *urlQParams = [keys sortedArrayUsingSelector:@selector(compare:)];
  122. NSString *urlQParamsSummary = @"";
  123. if (urlQParams.count > 0) {
  124. urlQParamsSummary = [NSString stringWithFormat:@" urlQParams:(%@)",
  125. [urlQParams componentsJoinedByString:@","]];
  126. }
  127. GTLRObject *bodyObj = self.bodyObject;
  128. NSString *bodyObjSummary = @"";
  129. if (bodyObj != nil) {
  130. bodyObjSummary = [NSString stringWithFormat:@" bodyObject:%@", [bodyObj class]];
  131. }
  132. NSString *uploadStr = @"";
  133. GTLRUploadParameters *uploadParams = self.uploadParameters;
  134. if (uploadParams) {
  135. uploadStr = [NSString stringWithFormat:@" %@", uploadParams];
  136. }
  137. NSString *httpMethod = self.httpMethod;
  138. if (httpMethod == nil) {
  139. httpMethod = @"GET";
  140. }
  141. NSString *dataObjectType = self.downloadAsDataObjectType;
  142. NSString *downloadStr = @"";
  143. if (dataObjectType.length > 0) {
  144. downloadStr =
  145. [NSString stringWithFormat:@" downloadDataAs:%@", dataObjectType];
  146. }
  147. return [NSString stringWithFormat:@"%@ %p:%@%@ {%@ pathTemplate:%@%@%@%@%@}",
  148. [self class], self, invalidStr, downloadStr,
  149. httpMethod, self.pathURITemplate,
  150. paramsSummary, urlQParamsSummary, bodyObjSummary, uploadStr];
  151. }
  152. #endif // DEBUG
  153. - (BOOL)isBatchQuery {
  154. return NO;
  155. }
  156. - (void)invalidateQuery {
  157. self.queryInvalid = YES;
  158. self.completionBlock = nil;
  159. self.executionParameters = nil;
  160. }
  161. - (GTLRServiceExecutionParameters *)executionParameters {
  162. @synchronized(self) {
  163. if (!_executionParameters) {
  164. _executionParameters = [[GTLRServiceExecutionParameters alloc] init];
  165. }
  166. return _executionParameters;
  167. }
  168. }
  169. - (void)setExecutionParameters:(nullable GTLRServiceExecutionParameters *)executionParameters {
  170. @synchronized(self) {
  171. _executionParameters = executionParameters;
  172. }
  173. }
  174. - (BOOL)hasExecutionParameters {
  175. return self.executionParameters.hasParameters;
  176. }
  177. + (NSString *)nextRequestID {
  178. static NSUInteger lastRequestID = 0;
  179. NSString *result;
  180. @synchronized([GTLRQuery class]) {
  181. ++lastRequestID;
  182. result = [NSString stringWithFormat:@"gtlr_%lu", (unsigned long)lastRequestID];
  183. }
  184. return result;
  185. }
  186. #pragma mark GTLRRuntimeCommon Support
  187. - (void)setJSONValue:(id)obj forKey:(NSString *)key {
  188. NSMutableDictionary *dict = self.JSON;
  189. if (dict == nil && obj != nil) {
  190. dict = [NSMutableDictionary dictionaryWithCapacity:1];
  191. self.JSON = dict;
  192. }
  193. [dict setValue:obj forKey:key];
  194. }
  195. - (id)JSONValueForKey:(NSString *)key {
  196. id obj = [self.JSON objectForKey:key];
  197. return obj;
  198. }
  199. // There is no property for _childCache as there shouldn't be KVC/KVO
  200. // support for it, since it's an implementation detail.
  201. - (void)setCacheChild:(id)obj forKey:(NSString *)key {
  202. if (_childCache == nil && obj != nil) {
  203. _childCache = [[NSMutableDictionary alloc] initWithObjectsAndKeys:obj, key, nil];
  204. } else {
  205. [_childCache setValue:obj forKey:key];
  206. }
  207. }
  208. - (id)cacheChildForKey:(NSString *)key {
  209. id obj = [_childCache objectForKey:key];
  210. return obj;
  211. }
  212. #pragma mark Methods for Subclasses to Override
  213. + (NSDictionary<NSString *, NSString *> *)parameterNameMap {
  214. return nil;
  215. }
  216. + (NSDictionary<NSString *, Class> *)arrayPropertyToClassMap {
  217. return nil;
  218. }
  219. #pragma mark Runtime Utilities
  220. static NSMutableDictionary *gQueryParameterNameMapCache = nil;
  221. static NSMutableDictionary *gQueryArrayPropertyToClassMapCache = nil;
  222. + (void)initialize {
  223. // Note that +initialize is guaranteed by the runtime to be called in a thread-safe manner.
  224. if (gQueryParameterNameMapCache == nil) {
  225. gQueryParameterNameMapCache = [[NSMutableDictionary alloc] init];
  226. }
  227. if (gQueryArrayPropertyToClassMapCache == nil) {
  228. gQueryArrayPropertyToClassMapCache = [[NSMutableDictionary alloc] init];
  229. }
  230. }
  231. + (NSDictionary *)propertyToJSONKeyMapForClass:(Class<GTLRRuntimeCommon>)aClass {
  232. NSDictionary *resultMap =
  233. [GTLRRuntimeCommon mergedClassDictionaryForSelector:@selector(parameterNameMap)
  234. startClass:aClass
  235. ancestorClass:[GTLRQuery class]
  236. cache:gQueryParameterNameMapCache];
  237. return resultMap;
  238. }
  239. + (NSDictionary *)arrayPropertyToClassMapForClass:(Class<GTLRRuntimeCommon>)aClass {
  240. NSDictionary *resultMap =
  241. [GTLRRuntimeCommon mergedClassDictionaryForSelector:@selector(arrayPropertyToClassMap)
  242. startClass:aClass
  243. ancestorClass:[GTLRQuery class]
  244. cache:gQueryArrayPropertyToClassMapCache];
  245. return resultMap;
  246. }
  247. #pragma mark Runtime Support
  248. - (id<GTLRObjectClassResolver>)objectClassResolver {
  249. // Stub method just needed for RuntimeCommon.
  250. return nil;
  251. }
  252. + (Class<GTLRRuntimeCommon>)ancestorClass {
  253. return [GTLRQuery class];
  254. }
  255. + (BOOL)resolveInstanceMethod:(SEL)sel {
  256. BOOL resolved = [GTLRRuntimeCommon resolveInstanceMethod:sel onClass:self];
  257. if (resolved) return YES;
  258. return [super resolveInstanceMethod:sel];
  259. }
  260. @end
  261. @implementation GTLRQueryCollectionImpl
  262. @dynamic pageToken;
  263. @end