/Source/externals/GData/Source/Networking/GDataServerError.m

http://google-email-uploader-mac.googlecode.com/ · Objective C · 350 lines · 229 code · 78 blank · 43 comment · 29 complexity · 3c3112c9d261f72e2a3d4b60227da225 MD5 · raw file

  1. /* Copyright (c) 2008 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. #define GDATASERVERERROR_DEFINE_GLOBALS 1
  16. #import "GDataServerError.h"
  17. #import "GDataObject.h" // for namespace
  18. #import "GDataUtilities.h" // for AreEqualOrBothNil
  19. //
  20. // GDataServerErrorGroup
  21. //
  22. @interface GDataServerErrorGroup (PrivateMethods)
  23. - (NSArray *)serverErrorsWithData:(NSData *)data;
  24. @end
  25. @implementation GDataServerErrorGroup
  26. - (id)initWithData:(NSData *)data {
  27. self = [super init];
  28. if (self) {
  29. NSArray *errors = [self serverErrorsWithData:data];
  30. if (errors) {
  31. [self setErrors:errors];
  32. } else {
  33. // failed to parse errors
  34. [self release];
  35. return nil;
  36. }
  37. }
  38. return self;
  39. }
  40. - (NSString *)description {
  41. return [NSString stringWithFormat:@"%@ %p: {errors: %@}",
  42. [self class], self, [self errors]];
  43. }
  44. - (NSUInteger)hash {
  45. return (NSUInteger) (void *) [GDataServerErrorGroup class];
  46. }
  47. - (BOOL)isEqual:(GDataServerErrorGroup *)other {
  48. if (self == other) return YES;
  49. if (![other isKindOfClass:[GDataServerErrorGroup class]]) return NO;
  50. return AreEqualOrBothNil([self errors], [other errors]);
  51. }
  52. - (id)copyWithZone:(NSZone *)zone {
  53. GDataServerErrorGroup* newObj = [[[self class] allocWithZone:zone] init];
  54. NSArray *errorsCopy = [[[NSArray alloc] initWithArray:[self errors]
  55. copyItems:YES] autorelease];
  56. [newObj setErrors:errorsCopy];
  57. return newObj;
  58. }
  59. - (void)dealloc {
  60. [errors_ release];
  61. [super dealloc];
  62. }
  63. #pragma mark -
  64. - (NSArray *)errors {
  65. return errors_;
  66. }
  67. - (void)setErrors:(NSArray *)array {
  68. [errors_ autorelease];
  69. errors_ = [array retain];
  70. }
  71. - (GDataServerError *)mainError {
  72. if ([errors_ count] > 0) {
  73. GDataServerError *obj = [errors_ objectAtIndex:0];
  74. return obj;
  75. }
  76. return nil;
  77. }
  78. #pragma mark -
  79. // -serverErrorsWithData is used by the initFromData: method
  80. //
  81. // convert the data to an XML document, step through the <error> elements,
  82. // and make each into a GDataServerError object
  83. //
  84. // returns nil if the data cannot be parsed or no error elements are found
  85. //
  86. // data is expected to look like:
  87. //
  88. // <?xml version="1.0" ?>
  89. // <errors xmlns="http://schemas.google.com/g/2005">
  90. // <error>
  91. // <domain>GData</domain>
  92. // <code>invalidUri</code>
  93. // <internalReason>Badly formatted URI</internalReason>
  94. // </error>
  95. // </errors>
  96. - (NSArray *)serverErrorsWithData:(NSData *)data {
  97. NSMutableArray *serverErrors = [NSMutableArray array];
  98. NSError *docError = nil;
  99. NSXMLDocument *xmlDoc;
  100. xmlDoc = [[[NSXMLDocument alloc] initWithData:data
  101. options:0
  102. error:&docError] autorelease];
  103. if (xmlDoc != nil) {
  104. // step through all <error> elements and make a GDataServerError instance
  105. // for each
  106. NSXMLElement *errorsElem = [xmlDoc rootElement];
  107. NSArray *errorElems = [errorsElem elementsForLocalName:@"error"
  108. URI:kGDataNamespaceGData];
  109. for (NSXMLElement *errorElem in errorElems) {
  110. GDataServerError *serverError;
  111. serverError = [[[GDataServerError alloc] initWithXMLElement:errorElem] autorelease];
  112. if (serverError != nil) {
  113. [serverErrors addObject:serverError];
  114. }
  115. }
  116. }
  117. if ([serverErrors count] > 0) {
  118. return serverErrors;
  119. }
  120. // failed to parse, or found no errors
  121. #if DEBUG
  122. NSString *errStr;
  123. errStr = [[[NSString alloc] initWithData:data
  124. encoding:NSUTF8StringEncoding] autorelease];
  125. NSLog(@"Could not parse error: %@\n Error XML data: %@", docError, errStr);
  126. #endif
  127. return nil;
  128. }
  129. @end
  130. //
  131. // GDataServerError
  132. //
  133. @interface GDataServerError (PrivateMethods)
  134. + (NSString *)errorStringForParentElement:(NSXMLElement *)parent
  135. childName:(NSString *)childName;
  136. @end
  137. @implementation GDataServerError
  138. - (id)initWithXMLElement:(NSXMLElement *)element {
  139. self = [super init];
  140. if (self) {
  141. NSString *domain = [GDataServerError errorStringForParentElement:element
  142. childName:@"domain"];
  143. [self setDomain:domain];
  144. NSString *code = [GDataServerError errorStringForParentElement:element
  145. childName:@"code"];
  146. [self setCode:code];
  147. NSString *reason = [GDataServerError errorStringForParentElement:element
  148. childName:@"internalReason"];
  149. [self setInternalReason:reason];
  150. NSString *help = [GDataServerError errorStringForParentElement:element
  151. childName:@"extendedHelp"];
  152. [self setExtendedHelpURI:help];
  153. NSString *report = [GDataServerError errorStringForParentElement:element
  154. childName:@"sendReport"];
  155. [self setSendReportURI:report];
  156. }
  157. return self;
  158. }
  159. - (NSString *)description {
  160. NSMutableArray *arr = [NSMutableArray array];
  161. if (domain_) {
  162. [arr addObject:[NSString stringWithFormat:@"domain=\"%@\"", domain_]];
  163. }
  164. if (code_) {
  165. [arr addObject:[NSString stringWithFormat:@"code=\"%@\"", code_]];
  166. }
  167. if (internalReason_) {
  168. [arr addObject:[NSString stringWithFormat:@"reason=\"%@\"", internalReason_]];
  169. }
  170. if (extendedHelpURI_) {
  171. [arr addObject:[NSString stringWithFormat:@"help=\"%@\"", extendedHelpURI_]];
  172. }
  173. if (sendReportURI_) {
  174. [arr addObject:[NSString stringWithFormat:@"report=\"%@\"", sendReportURI_]];
  175. }
  176. NSString *str = [arr componentsJoinedByString:@" "];
  177. return [NSString stringWithFormat:@"%@ %p: {%@}", [self class], self, str];
  178. }
  179. - (NSUInteger)hash {
  180. return (NSUInteger) (void *) [GDataServerError class];
  181. }
  182. - (BOOL)isEqual:(GDataServerError *)other {
  183. if (self == other) return YES;
  184. if (![other isKindOfClass:[GDataServerError class]]) return NO;
  185. return AreEqualOrBothNil([self domain], [other domain])
  186. && AreEqualOrBothNil([self code], [other code])
  187. && AreEqualOrBothNil([self internalReason], [other internalReason])
  188. && AreEqualOrBothNil([self extendedHelpURI], [other extendedHelpURI])
  189. && AreEqualOrBothNil([self sendReportURI], [other sendReportURI]);
  190. }
  191. - (id)copyWithZone:(NSZone *)zone {
  192. GDataServerError* newObj = [[[self class] allocWithZone:zone] init];
  193. [newObj setDomain:[self domain]];
  194. [newObj setCode:[self code]];
  195. [newObj setInternalReason:[self internalReason]];
  196. [newObj setExtendedHelpURI:[self extendedHelpURI]];
  197. [newObj setSendReportURI:[self sendReportURI]];
  198. return newObj;
  199. }
  200. - (void)dealloc {
  201. [domain_ release];
  202. [code_ release];
  203. [internalReason_ release];
  204. [extendedHelpURI_ release];
  205. [sendReportURI_ release];
  206. [super dealloc];
  207. }
  208. #pragma mark -
  209. - (NSString *)summary {
  210. NSString *summary;
  211. NSString *domain = [self domain];
  212. NSString *code = [self code];
  213. NSString *internalReason = [self internalReason];
  214. if ([internalReason length] > 0) {
  215. summary = [NSString stringWithFormat:@"%@ error %@: \"%@\"",
  216. domain, code, internalReason];
  217. } else {
  218. summary = [NSString stringWithFormat:@"%@ error %@", domain, code];
  219. }
  220. return summary;
  221. }
  222. #pragma mark -
  223. - (NSString *)domain {
  224. return domain_;
  225. }
  226. - (void)setDomain:(NSString *)str {
  227. [domain_ autorelease];
  228. domain_ = [str copy];
  229. }
  230. - (NSString *)code {
  231. return code_;
  232. }
  233. - (void)setCode:(NSString *)str {
  234. [code_ autorelease];
  235. code_ = [str copy];
  236. }
  237. - (NSString *)internalReason {
  238. return internalReason_;
  239. }
  240. - (void)setInternalReason:(NSString *)str {
  241. [internalReason_ autorelease];
  242. internalReason_ = [str copy];
  243. }
  244. - (NSString *)extendedHelpURI {
  245. return extendedHelpURI_;
  246. }
  247. - (void)setExtendedHelpURI:(NSString *)str {
  248. [extendedHelpURI_ autorelease];
  249. extendedHelpURI_ = [str copy];
  250. }
  251. - (NSString *)sendReportURI {
  252. return sendReportURI_;
  253. }
  254. - (void)setSendReportURI:(NSString *)str {
  255. [sendReportURI_ autorelease];
  256. sendReportURI_ = [str copy];
  257. }
  258. #pragma mark -
  259. // internal utility routine to get the string value of the named child element,
  260. // assuming the GData namespace
  261. + (NSString *)errorStringForParentElement:(NSXMLElement *)parent
  262. childName:(NSString *)childName {
  263. NSArray *array = [parent elementsForLocalName:childName
  264. URI:kGDataNamespaceGData];
  265. if ([array count] > 0) {
  266. NSXMLElement *elem = [array objectAtIndex:0];
  267. NSString *str = [elem stringValue];
  268. return str;
  269. }
  270. return nil;
  271. }
  272. @end