My favorites | Sign in
Project Home Downloads Wiki Issues Source
Checkout   Browse   Changes  
Changes to /trunk/Source/BaseClasses/GDataEntryBase.m
r695 vs. r707 Compare: vs.  Format:
Revision r707
Go to: 
Project members, sign in to write a code review
/trunk/Source/BaseClasses/GDataEntryBase.m   r695 /trunk/Source/BaseClasses/GDataEntryBase.m   r707
1 /* Copyright (c) 2007 Google Inc. 1 /* Copyright (c) 2007 Google Inc.
2 * 2 *
3 * Licensed under the Apache License, Version 2.0 (the "License"); 3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with 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 5 * You may obtain a copy of the License at
6 * 6 *
7 * http://www.apache.org/licenses/LICENSE-2.0 7 * http://www.apache.org/licenses/LICENSE-2.0
8 * 8 *
9 * Unless required by applicable law or agreed to in writing, software 9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, 10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and 12 * See the License for the specific language governing permissions and
13 * limitations under the License. 13 * limitations under the License.
14 */ 14 */
15 15
16 // 16 //
17 // GDataEntryBase.m 17 // GDataEntryBase.m
18 // 18 //
19 19
20 #define GDATAENTRYBASE_DEFINE_GLOBALS 1 20 #define GDATAENTRYBASE_DEFINE_GLOBALS 1
21 21
22 #import "GDataEntryBase.h" 22 #import "GDataEntryBase.h"
23 #import "GDataMIMEDocument.h"
24 #import "GDataBaseElements.h" 23 #import "GDataBaseElements.h"
24 #import "GTMMIMEDocument.h"
25 25
26 @implementation GDataEntryBase 26 @implementation GDataEntryBase
27 27
28 + (NSString *)standardEntryKind { 28 + (NSString *)standardEntryKind {
29 29
30 // overridden by entry subclasses 30 // overridden by entry subclasses
31 // 31 //
32 // Feeds and entries typically have a "kind" atom:category element 32 // Feeds and entries typically have a "kind" atom:category element
33 // indicating their contents; see 33 // indicating their contents; see
34 // http://code.google.com/apis/gdata/elements.html#Introduction 34 // http://code.google.com/apis/gdata/elements.html#Introduction
35 // 35 //
36 // Subclasses may override this method with the "term" attribute string 36 // Subclasses may override this method with the "term" attribute string
37 // for their kind category. This is used in the plain -init method, 37 // for their kind category. This is used in the plain -init method,
38 // and from +registerEntryClass 38 // and from +registerEntryClass
39 // 39 //
40 40
41 return nil; 41 return nil;
42 } 42 }
43 43
44 + (NSString *)standardKindAttributeValue { 44 + (NSString *)standardKindAttributeValue {
45 45
46 // overridden by entry subclasses 46 // overridden by entry subclasses
47 // 47 //
48 // Feeds and entries in core v2.1 and later have a kind attribute rather than 48 // Feeds and entries in core v2.1 and later have a kind attribute rather than
49 // kind categories 49 // kind categories
50 // 50 //
51 // Subclasses may override this method with the proper kind attribute string 51 // Subclasses may override this method with the proper kind attribute string
52 // used to identify this class 52 // used to identify this class
53 // 53 //
54 return nil; 54 return nil;
55 } 55 }
56 56
57 + (NSDictionary *)baseGDataNamespaces { 57 + (NSDictionary *)baseGDataNamespaces {
58 NSDictionary *namespaces = [NSDictionary dictionaryWithObjectsAndKeys: 58 NSDictionary *namespaces = [NSDictionary dictionaryWithObjectsAndKeys:
59 kGDataNamespaceAtom, @"", 59 kGDataNamespaceAtom, @"",
60 kGDataNamespaceGData, kGDataNamespaceGDataPrefix, 60 kGDataNamespaceGData, kGDataNamespaceGDataPrefix,
61 kGDataNamespaceAtomPub, kGDataNamespaceAtomPubPrefix, 61 kGDataNamespaceAtomPub, kGDataNamespaceAtomPubPrefix,
62 nil]; 62 nil];
63 return namespaces; 63 return namespaces;
64 } 64 }
65 65
66 + (id)entry { 66 + (id)entry {
67 GDataEntryBase *entry = [self object]; 67 GDataEntryBase *entry = [self object];
68 68
69 [entry setNamespaces:[GDataEntryBase baseGDataNamespaces]]; 69 [entry setNamespaces:[GDataEntryBase baseGDataNamespaces]];
70 return entry; 70 return entry;
71 } 71 }
72 72
73 - (void)addExtensionDeclarations { 73 - (void)addExtensionDeclarations {
74 74
75 [super addExtensionDeclarations]; 75 [super addExtensionDeclarations];
76 76
77 Class entryClass = [self class]; 77 Class entryClass = [self class];
78 78
79 [self addExtensionDeclarationForParentClass:entryClass 79 [self addExtensionDeclarationForParentClass:entryClass
80 childClasses: 80 childClasses:
81 // GData extensions 81 // GData extensions
82 [GDataResourceID class], 82 [GDataResourceID class],
83 83
84 // Atom extensions 84 // Atom extensions
85 [GDataAtomID class], 85 [GDataAtomID class],
86 [GDataAtomPublishedDate class], 86 [GDataAtomPublishedDate class],
87 [GDataAtomUpdatedDate class], 87 [GDataAtomUpdatedDate class],
88 [GDataAtomTitle class], 88 [GDataAtomTitle class],
89 [GDataAtomSummary class], 89 [GDataAtomSummary class],
90 [GDataAtomContent class], 90 [GDataAtomContent class],
91 [GDataAtomRights class], 91 [GDataAtomRights class],
92 [GDataLink class], 92 [GDataLink class],
93 [GDataAtomAuthor class], 93 [GDataAtomAuthor class],
94 [GDataAtomContributor class], 94 [GDataAtomContributor class],
95 [GDataCategory class], 95 [GDataCategory class],
96 96
97 // deletion marking support 97 // deletion marking support
98 [GDataDeleted class], 98 [GDataDeleted class],
99 99
100 // atom publishing control support 100 // atom publishing control support
101 [GDataAtomPubControl class], 101 [GDataAtomPubControl class],
102 [GDataAtomPubEditedDate class], 102 [GDataAtomPubEditedDate class],
103 103
104 // batch support 104 // batch support
105 [GDataBatchOperation class], [GDataBatchID class], 105 [GDataBatchOperation class], [GDataBatchID class],
106 [GDataBatchStatus class], [GDataBatchInterrupted class], 106 [GDataBatchStatus class], [GDataBatchInterrupted class],
107 nil]; 107 nil];
108 108
109 [self addAttributeExtensionDeclarationForParentClass:entryClass 109 [self addAttributeExtensionDeclarationForParentClass:entryClass
110 childClass:[GDataETagAttribute class]]; 110 childClass:[GDataETagAttribute class]];
111 [self addAttributeExtensionDeclarationForParentClass:entryClass 111 [self addAttributeExtensionDeclarationForParentClass:entryClass
112 childClass:[GDataFieldsAttribute class]]; 112 childClass:[GDataFieldsAttribute class]];
113 [self addAttributeExtensionDeclarationForParentClass:entryClass 113 [self addAttributeExtensionDeclarationForParentClass:entryClass
114 childClass:[GDataKindAttribute class]]; 114 childClass:[GDataKindAttribute class]];
115 } 115 }
116 116
117 - (id)init { 117 - (id)init {
118 self = [super init]; 118 self = [super init];
119 if (self) { 119 if (self) {
120 // if the subclass declares a kind, then add a category element or 120 // if the subclass declares a kind, then add a category element or
121 // a kind attribute 121 // a kind attribute
122 NSString *categoryKind = [[self class] standardEntryKind]; 122 NSString *categoryKind = [[self class] standardEntryKind];
123 if (categoryKind) { 123 if (categoryKind) {
124 GDataCategory *category; 124 GDataCategory *category;
125 125
126 category = [GDataCategory categoryWithScheme:kGDataCategoryScheme 126 category = [GDataCategory categoryWithScheme:kGDataCategoryScheme
127 term:categoryKind]; 127 term:categoryKind];
128 [self addCategory:category]; 128 [self addCategory:category];
129 } 129 }
130 130
131 NSString *attributeKind = [[self class] standardKindAttributeValue]; 131 NSString *attributeKind = [[self class] standardKindAttributeValue];
132 if (attributeKind) { 132 if (attributeKind) {
133 [self setKind:attributeKind]; 133 [self setKind:attributeKind];
134 } 134 }
135 } 135 }
136 return self; 136 return self;
137 } 137 }
138 138
139 - (void)dealloc { 139 - (void)dealloc {
140 [uploadData_ release]; 140 [uploadData_ release];
141 [uploadFileHandle_ release]; 141 [uploadFileHandle_ release];
142 [uploadLocationURL_ release]; 142 [uploadLocationURL_ release];
143 [uploadMIMEType_ release]; 143 [uploadMIMEType_ release];
144 [uploadSlug_ release]; 144 [uploadSlug_ release];
145 145
146 [super dealloc]; 146 [super dealloc];
147 } 147 }
148 148
149 - (BOOL)isEqual:(GDataEntryBase *)other { 149 - (BOOL)isEqual:(GDataEntryBase *)other {
150 if (self == other) return YES; 150 if (self == other) return YES;
151 if (![other isKindOfClass:[GDataEntryBase class]]) return NO; 151 if (![other isKindOfClass:[GDataEntryBase class]]) return NO;
152 152
153 return [super isEqual:other] 153 return [super isEqual:other]
154 && AreEqualOrBothNil([self uploadData], [other uploadData]) 154 && AreEqualOrBothNil([self uploadData], [other uploadData])
155 && AreEqualOrBothNil([self uploadMIMEType], [other uploadMIMEType]) 155 && AreEqualOrBothNil([self uploadMIMEType], [other uploadMIMEType])
156 && AreEqualOrBothNil([self uploadSlug], [other uploadSlug]) 156 && AreEqualOrBothNil([self uploadSlug], [other uploadSlug])
157 && AreBoolsEqual([self shouldUploadDataOnly], [other shouldUploadDataOnly]); 157 && AreBoolsEqual([self shouldUploadDataOnly], [other shouldUploadDataOnly]);
158 } 158 }
159 159
160 - (id)copyWithZone:(NSZone *)zone { 160 - (id)copyWithZone:(NSZone *)zone {
161 GDataEntryBase* newEntry = [super copyWithZone:zone]; 161 GDataEntryBase* newEntry = [super copyWithZone:zone];
162 162
163 [newEntry setUploadData:[self uploadData]]; 163 [newEntry setUploadData:[self uploadData]];
164 [newEntry setUploadFileHandle:[self uploadFileHandle]]; 164 [newEntry setUploadFileHandle:[self uploadFileHandle]];
165 [newEntry setUploadLocationURL:[self uploadLocationURL]]; 165 [newEntry setUploadLocationURL:[self uploadLocationURL]];
166 [newEntry setUploadMIMEType:[self uploadMIMEType]]; 166 [newEntry setUploadMIMEType:[self uploadMIMEType]];
167 [newEntry setUploadSlug:[self uploadSlug]]; 167 [newEntry setUploadSlug:[self uploadSlug]];
168 [newEntry setShouldUploadDataOnly:[self shouldUploadDataOnly]]; 168 [newEntry setShouldUploadDataOnly:[self shouldUploadDataOnly]];
169 169
170 return newEntry; 170 return newEntry;
171 } 171 }
172 172
173 #if !GDATA_SIMPLE_DESCRIPTIONS 173 #if !GDATA_SIMPLE_DESCRIPTIONS
174 174
175 - (NSMutableArray *)itemsForDescription { 175 - (NSMutableArray *)itemsForDescription {
176 176
177 // make a list of the interesting parts of links 177 // make a list of the interesting parts of links
178 NSArray *linkNames = [GDataLink linkNamesFromLinks:[self links]]; 178 NSArray *linkNames = [GDataLink linkNamesFromLinks:[self links]];
179 NSString *linksStr = [linkNames componentsJoinedByString:@","]; 179 NSString *linksStr = [linkNames componentsJoinedByString:@","];
180 180
181 struct GDataDescriptionRecord descRecs[] = { 181 struct GDataDescriptionRecord descRecs[] = {
182 { @"v", @"serviceVersion", kGDataDescValueLabeled }, 182 { @"v", @"serviceVersion", kGDataDescValueLabeled },
183 { @"title", @"title.stringValue", kGDataDescValueLabeled }, 183 { @"title", @"title.stringValue", kGDataDescValueLabeled },
184 { @"summary", @"summary.stringValue", kGDataDescValueLabeled }, 184 { @"summary", @"summary.stringValue", kGDataDescValueLabeled },
185 { @"content", @"content.stringValue", kGDataDescValueLabeled }, 185 { @"content", @"content.stringValue", kGDataDescValueLabeled },
186 { @"contentSrc", @"content.sourceURI", kGDataDescValueLabeled }, 186 { @"contentSrc", @"content.sourceURI", kGDataDescValueLabeled },
187 { @"etag", @"ETag", kGDataDescValueLabeled }, 187 { @"etag", @"ETag", kGDataDescValueLabeled },
188 { @"kind", @"kind", kGDataDescValueLabeled }, 188 { @"kind", @"kind", kGDataDescValueLabeled },
189 { @"fields", @"fieldSelection", kGDataDescValueLabeled }, 189 { @"fields", @"fieldSelection", kGDataDescValueLabeled },
190 { @"resourceID", @"resourceID", kGDataDescValueLabeled }, 190 { @"resourceID", @"resourceID", kGDataDescValueLabeled },
191 { @"authors", @"authors", kGDataDescArrayCount }, 191 { @"authors", @"authors", kGDataDescArrayCount },
192 { @"contributors", @"contributors", kGDataDescArrayCount }, 192 { @"contributors", @"contributors", kGDataDescArrayCount },
193 { @"categories", @"categories", kGDataDescArrayCount }, 193 { @"categories", @"categories", kGDataDescArrayCount },
194 { @"links", linksStr, kGDataDescValueIsKeyPath }, 194 { @"links", linksStr, kGDataDescValueIsKeyPath },
195 { @"edited", @"editedDate.RFC3339String", kGDataDescValueLabeled }, 195 { @"edited", @"editedDate.RFC3339String", kGDataDescValueLabeled },
196 { @"id", @"identifier", kGDataDescValueLabeled }, 196 { @"id", @"identifier", kGDataDescValueLabeled },
197 { @"app:control", @"atomPubControl", kGDataDescValueLabeled }, 197 { @"app:control", @"atomPubControl", kGDataDescValueLabeled },
198 { @"batchOp", @"batchOperation.type", kGDataDescValueLabeled }, 198 { @"batchOp", @"batchOperation.type", kGDataDescValueLabeled },
199 { @"batchID", @"batchID.stringValue", kGDataDescValueLabeled }, 199 { @"batchID", @"batchID.stringValue", kGDataDescValueLabeled },
200 { @"batchStatus", @"batchStatus.code", kGDataDescValueLabeled }, 200 { @"batchStatus", @"batchStatus.code", kGDataDescValueLabeled },
201 { @"batchInterrupted", @"batchInterrupted", kGDataDescValueLabeled }, 201 { @"batchInterrupted", @"batchInterrupted", kGDataDescValueLabeled },
202 { @"MIMEType", @"uploadMIMEType", kGDataDescValueLabeled }, 202 { @"MIMEType", @"uploadMIMEType", kGDataDescValueLabeled },
203 { @"slug", @"uploadSlug", kGDataDescValueLabeled }, 203 { @"slug", @"uploadSlug", kGDataDescValueLabeled },
204 { @"uploadDataOnly", @"shouldUploadDataOnly", kGDataDescBooleanPresent }, 204 { @"uploadDataOnly", @"shouldUploadDataOnly", kGDataDescBooleanPresent },
205 { @"UploadData", @"uploadData", kGDataDescNonZeroLength }, 205 { @"UploadData", @"uploadData", kGDataDescNonZeroLength },
206 { @"deleted", @"isDeleted", kGDataDescBooleanPresent }, 206 { @"deleted", @"isDeleted", kGDataDescBooleanPresent },
207 { nil, nil, (GDataDescRecTypes)0 } 207 { nil, nil, (GDataDescRecTypes)0 }
208 }; 208 };
209 209
210 NSMutableArray *items = [super itemsForDescription]; 210 NSMutableArray *items = [super itemsForDescription];
211 [self addDescriptionRecords:descRecs toItems:items]; 211 [self addDescriptionRecords:descRecs toItems:items];
212 return items; 212 return items;
213 } 213 }
214 #endif 214 #endif
215 215
216 - (NSXMLElement *)XMLElement { 216 - (NSXMLElement *)XMLElement {
217 NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:@"entry"]; 217 NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:@"entry"];
218 return element; 218 return element;
219 } 219 }
220 220
221 #pragma mark - 221 #pragma mark -
222 222
223 - (NSDictionary *)contentHeaders { 223 - (NSDictionary *)contentHeaders {
224 // This is also called from GDataServiceBase so it knows what headers to use 224 // This is also called from GDataServiceBase so it knows what headers to use
225 // when uploading data chunked but without XML (so the body is empty.) 225 // when uploading data chunked but without XML (so the body is empty.)
226 return [NSDictionary dictionaryWithObjectsAndKeys: 226 return [NSDictionary dictionaryWithObjectsAndKeys:
227 [self uploadMIMEType], @"Content-Type", 227 [self uploadMIMEType], @"Content-Type",
228 @"1.0", @"MIME-Version", 228 @"1.0", @"MIME-Version",
229 [self uploadSlug], @"Slug", // slug may be nil 229 [self uploadSlug], @"Slug", // slug may be nil
230 nil]; 230 nil];
231 } 231 }
232 232
233 - (BOOL)generateContentInputStream:(NSInputStream **)outInputStream 233 - (BOOL)generateContentInputStream:(NSInputStream **)outInputStream
234 length:(unsigned long long *)outLength 234 length:(unsigned long long *)outLength
235 headers:(NSDictionary **)outHeaders { 235 headers:(NSDictionary **)outHeaders {
236 236
237 // check if a subclass is providing data 237 // check if a subclass is providing data
238 NSData *uploadData = [self uploadData]; 238 NSData *uploadData = [self uploadData];
239 239
240 if (uploadData == nil) { 240 if (uploadData == nil) {
241 // read from the file handle, if one was provided 241 // read from the file handle, if one was provided
242 NSFileHandle *fileHandle = [self uploadFileHandle]; 242 NSFileHandle *fileHandle = [self uploadFileHandle];
243 if (fileHandle) { 243 if (fileHandle) {
244 [fileHandle seekToFileOffset:0]; 244 [fileHandle seekToFileOffset:0];
245 uploadData = [fileHandle readDataToEndOfFile]; 245 uploadData = [fileHandle readDataToEndOfFile];
246 } 246 }
247 } 247 }
248 248
249 NSString *uploadMIMEType = [self uploadMIMEType]; 249 NSString *uploadMIMEType = [self uploadMIMEType];
250 NSString *slug = [self uploadSlug]; 250 NSString *slug = [self uploadSlug];
251 251
252 BOOL hasUploadData = ([uploadData length] > 0); 252 BOOL hasUploadData = ([uploadData length] > 0);
253 BOOL hasUploadMIMEType = ([uploadMIMEType length] > 0); 253 BOOL hasUploadMIMEType = ([uploadMIMEType length] > 0);
254 GDATA_DEBUG_ASSERT(hasUploadData == hasUploadMIMEType, 254 GDATA_DEBUG_ASSERT(hasUploadData == hasUploadMIMEType,
255 @"upload data must be paired with MIME type"); 255 @"upload data must be paired with MIME type");
256 256
257 BOOL shouldUploadDataOnly = [self shouldUploadDataOnly]; 257 BOOL shouldUploadDataOnly = [self shouldUploadDataOnly];
258 GDATA_DEBUG_ASSERT(!shouldUploadDataOnly 258 GDATA_DEBUG_ASSERT(!shouldUploadDataOnly
259 || (hasUploadData && hasUploadMIMEType), 259 || (hasUploadData && hasUploadMIMEType),
260 @"missing data"); 260 @"missing data");
261 261
262 if (shouldUploadDataOnly && hasUploadData && hasUploadMIMEType) { 262 if (shouldUploadDataOnly && hasUploadData && hasUploadMIMEType) {
263 // we're not uploading the XML, so we don't need a multipart MIME document, 263 // we're not uploading the XML, so we don't need a multipart MIME document,
264 // just a stream with the upload data 264 // just a stream with the upload data
265 *outInputStream = [NSInputStream inputStreamWithData:uploadData]; 265 *outInputStream = [NSInputStream inputStreamWithData:uploadData];
266 *outLength = [uploadData length]; 266 *outLength = [uploadData length];
267 *outHeaders = [self contentHeaders]; 267 *outHeaders = [self contentHeaders];
268 return YES; 268 return YES;
269 } 269 }
270 270
271 if (!hasUploadData || !hasUploadMIMEType) { 271 if (!hasUploadData || !hasUploadMIMEType) {
272 // if there's no upload data, just fall back on the superclass since we 272 // if there's no upload data, just fall back on the superclass since we
273 // don't need a stream 273 // don't need a stream
274 return [super generateContentInputStream:outInputStream 274 return [super generateContentInputStream:outInputStream
275 length:outLength 275 length:outLength
276 headers:outHeaders]; 276 headers:outHeaders];
277 } 277 }
278 278
279 // make a MIME document with an XML part and a binary part 279 // make a MIME document with an XML part and a binary part
280 NSDictionary* xmlHeader = [NSDictionary dictionaryWithObjectsAndKeys: 280 NSDictionary* xmlHeader = [NSDictionary dictionaryWithObjectsAndKeys:
281 @"application/atom+xml; charset=UTF-8", @"Content-Type", nil]; 281 @"application/atom+xml; charset=UTF-8", @"Content-Type", nil];
282 282
283 NSString *xmlString = [[self XMLElement] XMLString]; 283 NSString *xmlString = [[self XMLElement] XMLString];
284 NSData *xmlBody = [xmlString dataUsingEncoding:NSUTF8StringEncoding]; 284 NSData *xmlBody = [xmlString dataUsingEncoding:NSUTF8StringEncoding];
285 285
286 NSDictionary *binHeader = [NSDictionary dictionaryWithObjectsAndKeys: 286 NSDictionary *binHeader = [NSDictionary dictionaryWithObjectsAndKeys:
287 uploadMIMEType, @"Content-Type", 287 uploadMIMEType, @"Content-Type",
288 @"binary", @"Content-Transfer-Encoding", nil]; 288 @"binary", @"Content-Transfer-Encoding", nil];
289 289
290 GDataMIMEDocument* doc = [GDataMIMEDocument MIMEDocument]; 290 GTMMIMEDocument* doc = [GTMMIMEDocument MIMEDocument];
291 291
292 [doc addPartWithHeaders:xmlHeader body:xmlBody]; 292 [doc addPartWithHeaders:xmlHeader body:xmlBody];
293 [doc addPartWithHeaders:binHeader body:uploadData]; 293 [doc addPartWithHeaders:binHeader body:uploadData];
294 294
295 // generate the input stream, and make a header which includes the 295 // generate the input stream, and make a header which includes the
296 // boundary used between parts of the mime document 296 // boundary used between parts of the mime document
297 NSString *partBoundary = nil; // typically this will be END_OF_PART 297 NSString *partBoundary = nil; // typically this will be END_OF_PART
298 298
299 [doc generateInputStream:outInputStream 299 [doc generateInputStream:outInputStream
300 length:outLength 300 length:outLength
301 boundary:&partBoundary]; 301 boundary:&partBoundary];
302 302
303 NSString *streamTypeTemplate = @"multipart/related; boundary=\"%@\""; 303 NSString *streamTypeTemplate = @"multipart/related; boundary=\"%@\"";
304 NSString *streamType = [NSString stringWithFormat:streamTypeTemplate, 304 NSString *streamType = [NSString stringWithFormat:streamTypeTemplate,
305 partBoundary]; 305 partBoundary];
306 306
307 *outHeaders = [NSDictionary dictionaryWithObjectsAndKeys: 307 *outHeaders = [NSDictionary dictionaryWithObjectsAndKeys:
308 streamType, @"Content-Type", 308 streamType, @"Content-Type",
309 @"1.0", @"MIME-Version", 309 @"1.0", @"MIME-Version",
310 slug, @"Slug", // slug may be nil 310 slug, @"Slug", // slug may be nil
311 nil]; 311 nil];
312 312
313 return YES; 313 return YES;
314 } 314 }
315 315
316 #pragma mark Dynamic object generation - Entry registration 316 #pragma mark Dynamic object generation - Entry registration
317 317
318 // 318 //
319 // entry registration & lookup for dynamic object generation 319 // entry registration & lookup for dynamic object generation
320 // 320 //
321 321
322 static NSMutableDictionary *gEntryClassKindMap = nil; 322 static NSMutableDictionary *gEntryClassKindMap = nil;
323 323
324 + (void)registerEntryClass { 324 + (void)registerEntryClass {
325 325
326 NSString *categoryKind = [self standardEntryKind]; 326 NSString *categoryKind = [self standardEntryKind];
327 if (categoryKind) { 327 if (categoryKind) {
328 [self registerClass:self 328 [self registerClass:self
329 inMap:&gEntryClassKindMap 329 inMap:&gEntryClassKindMap
330 forCategoryWithScheme:kGDataCategoryScheme 330 forCategoryWithScheme:kGDataCategoryScheme
331 term:categoryKind]; 331 term:categoryKind];
332 } 332 }
333 333
334 NSString *attributeKind = [self standardKindAttributeValue]; 334 NSString *attributeKind = [self standardKindAttributeValue];
335 if (attributeKind) { 335 if (attributeKind) {
336 [self registerClass:self 336 [self registerClass:self
337 inMap:&gEntryClassKindMap 337 inMap:&gEntryClassKindMap
338 forCategoryWithScheme:nil 338 forCategoryWithScheme:nil
339 term:attributeKind]; 339 term:attributeKind];
340 } 340 }
341 341
342 GDATA_DEBUG_ASSERT(attributeKind != nil || categoryKind != nil, 342 GDATA_DEBUG_ASSERT(attributeKind != nil || categoryKind != nil,
343 @"cannot register entry without a kind"); 343 @"cannot register entry without a kind");
344 } 344 }
345 345
346 + (void)registerEntryClass:(Class)theClass 346 + (void)registerEntryClass:(Class)theClass
347 forCategoryWithScheme:(NSString *)scheme 347 forCategoryWithScheme:(NSString *)scheme
348 term:(NSString *)term { 348 term:(NSString *)term {
349 349
350 // temporary bridge method - will be removed when subclasses all call 350 // temporary bridge method - will be removed when subclasses all call
351 // -registerEntryClass 351 // -registerEntryClass
352 [self registerClass:theClass 352 [self registerClass:theClass
353 inMap:&gEntryClassKindMap 353 inMap:&gEntryClassKindMap
354 forCategoryWithScheme:scheme 354 forCategoryWithScheme:scheme
355 term:term]; 355 term:term];
356 } 356 }
357 357
358 + (Class)entryClassForCategoryWithScheme:(NSString *)scheme 358 + (Class)entryClassForCategoryWithScheme:(NSString *)scheme
359 term:(NSString *)term { 359 term:(NSString *)term {
360 return [self classForCategoryWithScheme:scheme 360 return [self classForCategoryWithScheme:scheme
361 term:term 361 term:term
362 fromMap:gEntryClassKindMap]; 362 fromMap:gEntryClassKindMap];
363 } 363 }
364 364
365 + (Class)entryClassForKindAttributeValue:(NSString *)kind { 365 + (Class)entryClassForKindAttributeValue:(NSString *)kind {
366 return [self classForCategoryWithScheme:nil 366 return [self classForCategoryWithScheme:nil
367 term:kind 367 term:kind
368 fromMap:gEntryClassKindMap]; 368 fromMap:gEntryClassKindMap];
369 } 369 }
370 370
371 #pragma mark Getters and Setters 371 #pragma mark Getters and Setters
372 372
373 - (NSString *)ETag { 373 - (NSString *)ETag {
374 NSString *str = [self attributeValueForExtensionClass:[GDataETagAttribute class]]; 374 NSString *str = [self attributeValueForExtensionClass:[GDataETagAttribute class]];
375 return str; 375 return str;
376 } 376 }
377 377
378 - (void)setETag:(NSString *)str { 378 - (void)setETag:(NSString *)str {
379 [self setAttributeValue:str forExtensionClass:[GDataETagAttribute class]]; 379 [self setAttributeValue:str forExtensionClass:[GDataETagAttribute class]];
380 } 380 }
381 381
382 - (NSString *)fieldSelection { 382 - (NSString *)fieldSelection {
383 NSString *str = [self attributeValueForExtensionClass:[GDataFieldsAttribute class]]; 383 NSString *str = [self attributeValueForExtensionClass:[GDataFieldsAttribute class]];
384 return str; 384 return str;
385 } 385 }
386 386
387 - (void)setFieldSelection:(NSString *)str { 387 - (void)setFieldSelection:(NSString *)str {
388 [self setAttributeValue:str forExtensionClass:[GDataFieldsAttribute class]]; 388 [self setAttributeValue:str forExtensionClass:[GDataFieldsAttribute class]];
389 } 389 }
390 390
391 - (NSString *)kind { 391 - (NSString *)kind {
392 NSString *str = [self attributeValueForExtensionClass:[GDataKindAttribute class]]; 392 NSString *str = [self attributeValueForExtensionClass:[GDataKindAttribute class]];
393 return str; 393 return str;
394 } 394 }
395 395
396 - (void)setKind:(NSString *)str { 396 - (void)setKind:(NSString *)str {
397 [self setAttributeValue:str forExtensionClass:[GDataKindAttribute class]]; 397 [self setAttributeValue:str forExtensionClass:[GDataKindAttribute class]];
398 } 398 }
399 399
400 - (NSString *)resourceID { 400 - (NSString *)resourceID {
401 GDataResourceID *obj = [self objectForExtensionClass:[GDataResourceID class]]; 401 GDataResourceID *obj = [self objectForExtensionClass:[GDataResourceID class]];
402 return [obj stringValue]; 402 return [obj stringValue];
403 } 403 }
404 404
405 - (void)setResourceID:(NSString *)str { 405 - (void)setResourceID:(NSString *)str {
406 GDataResourceID *obj = [GDataResourceID valueWithString:str]; 406 GDataResourceID *obj = [GDataResourceID valueWithString:str];
407 [self setObject:obj forExtensionClass:[GDataResourceID class]]; 407 [self setObject:obj forExtensionClass:[GDataResourceID class]];
408 } 408 }
409 409
410 - (NSString *)identifier { 410 - (NSString *)identifier {
411 GDataAtomID *obj = [self objectForExtensionClass:[GDataAtomID class]]; 411 GDataAtomID *obj = [self objectForExtensionClass:[GDataAtomID class]];
412 return [obj stringValue]; 412 return [obj stringValue];
413 } 413 }
414 414
415 - (void)setIdentifier:(NSString *)str { 415 - (void)setIdentifier:(NSString *)str {
416 GDataAtomID *obj = [GDataAtomID valueWithString:str]; 416 GDataAtomID *obj = [GDataAtomID valueWithString:str];
417 [self setObject:obj forExtensionClass:[GDataAtomID class]]; 417 [self setObject:obj forExtensionClass:[GDataAtomID class]];
418 } 418 }
419 419
420 - (GDataDateTime *)publishedDate { 420 - (GDataDateTime *)publishedDate {
421 GDataAtomPublishedDate *obj; 421 GDataAtomPublishedDate *obj;
422 422
423 obj = [self objectForExtensionClass:[GDataAtomPublishedDate class]]; 423 obj = [self objectForExtensionClass:[GDataAtomPublishedDate class]];
424 return [obj dateTimeValue]; 424 return [obj dateTimeValue];
425 } 425 }
426 426
427 - (void)setPublishedDate:(GDataDateTime *)dateTime { 427 - (void)setPublishedDate:(GDataDateTime *)dateTime {
428 GDataAtomPublishedDate *obj; 428 GDataAtomPublishedDate *obj;
429 429
430 obj = [GDataAtomPublishedDate valueWithDateTime:dateTime]; 430 obj = [GDataAtomPublishedDate valueWithDateTime:dateTime];
431 [self setObject:obj forExtensionClass:[GDataAtomPublishedDate class]]; 431 [self setObject:obj forExtensionClass:[GDataAtomPublishedDate class]];
432 } 432 }
433 433
434 - (GDataDateTime *)updatedDate { 434 - (GDataDateTime *)updatedDate {
435 GDataAtomUpdatedDate *obj; 435 GDataAtomUpdatedDate *obj;
436 436
437 obj = [self objectForExtensionClass:[GDataAtomUpdatedDate class]]; 437 obj = [self objectForExtensionClass:[GDataAtomUpdatedDate class]];
438 return [obj dateTimeValue]; 438 return [obj dateTimeValue];
439 } 439 }
440 440
441 - (void)setUpdatedDate:(GDataDateTime *)dateTime { 441 - (void)setUpdatedDate:(GDataDateTime *)dateTime {
442 GDataAtomUpdatedDate *obj; 442 GDataAtomUpdatedDate *obj;
443 443
444 obj = [GDataAtomUpdatedDate valueWithDateTime:dateTime]; 444 obj = [GDataAtomUpdatedDate valueWithDateTime:dateTime];
445 [self setObject:obj forExtensionClass:[GDataAtomUpdatedDate class]]; 445 [self setObject:obj forExtensionClass:[GDataAtomUpdatedDate class]];
446 } 446 }
447 447
448 - (GDataDateTime *)editedDate { 448 - (GDataDateTime *)editedDate {
449 GDataValueElementConstruct *obj; 449 GDataValueElementConstruct *obj;
450 450
451 obj = [self objectForExtensionClass:[GDataAtomPubEditedDate class]]; 451 obj = [self objectForExtensionClass:[GDataAtomPubEditedDate class]];
452 return [obj dateTimeValue]; 452 return [obj dateTimeValue];
453 } 453 }
454 454
455 - (void)setEditedDate:(GDataDateTime *)dateTime { 455 - (void)setEditedDate:(GDataDateTime *)dateTime {
456 GDataValueElementConstruct *obj; 456 GDataValueElementConstruct *obj;
457 457
458 obj = [GDataAtomPubEditedDate valueWithDateTime:dateTime]; 458 obj = [GDataAtomPubEditedDate valueWithDateTime:dateTime];
459 [self setObject:obj forExtensionClass:[GDataAtomPubEditedDate class]]; 459 [self setObject:obj forExtensionClass:[GDataAtomPubEditedDate class]];
460 } 460 }
461 461
462 - (GDataTextConstruct *)title { 462 - (GDataTextConstruct *)title {
463 GDataAtomTitle *obj = [self objectForExtensionClass:[GDataAtomTitle class]]; 463 GDataAtomTitle *obj = [self objectForExtensionClass:[GDataAtomTitle class]];
464 return obj; 464 return obj;
465 } 465 }
466 466
467 - (void)setTitle:(GDataTextConstruct *)obj { 467 - (void)setTitle:(GDataTextConstruct *)obj {
468 [self setObject:obj forExtensionClass:[GDataAtomTitle class]]; 468 [self setObject:obj forExtensionClass:[GDataAtomTitle class]];
469 } 469 }
470 470
471 - (void)setTitleWithString:(NSString *)str { 471 - (void)setTitleWithString:(NSString *)str {
472 GDataAtomTitle *obj = [GDataAtomTitle textConstructWithString:str]; 472 GDataAtomTitle *obj = [GDataAtomTitle textConstructWithString:str];
473 [self setObject:obj forExtensionClass:[GDataAtomTitle class]]; 473 [self setObject:obj forExtensionClass:[GDataAtomTitle class]];
474 } 474 }
475 475
476 - (GDataTextConstruct *)summary { 476 - (GDataTextConstruct *)summary {
477 GDataAtomSummary *obj = [self objectForExtensionClass:[GDataAtomSummary class]]; 477 GDataAtomSummary *obj = [self objectForExtensionClass:[GDataAtomSummary class]];
478 return obj; 478 return obj;
479 } 479 }
480 480
481 - (void)setSummary:(GDataTextConstruct *)obj { 481 - (void)setSummary:(GDataTextConstruct *)obj {
482 [self setObject:obj forExtensionClass:[GDataAtomSummary class]]; 482 [self setObject:obj forExtensionClass:[GDataAtomSummary class]];
483 } 483 }
484 484
485 - (void)setSummaryWithString:(NSString *)str { 485 - (void)setSummaryWithString:(NSString *)str {
486 GDataAtomSummary *obj = [GDataAtomSummary textConstructWithString:str]; 486 GDataAtomSummary *obj = [GDataAtomSummary textConstructWithString:str];
487 [self setObject:obj forExtensionClass:[GDataAtomSummary class]]; 487 [self setObject:obj forExtensionClass:[GDataAtomSummary class]];
488 } 488 }
489 489
490 - (GDataEntryContent *)content { 490 - (GDataEntryContent *)content {
491 GDataAtomContent *obj; 491 GDataAtomContent *obj;
492 492
493 obj = [self objectForExtensionClass:[GDataAtomContent class]]; 493 obj = [self objectForExtensionClass:[GDataAtomContent class]];
494 return obj; 494 return obj;
495 } 495 }
496 496
497 - (void)setContent:(GDataEntryContent *)obj { 497 - (void)setContent:(GDataEntryContent *)obj {
498 [self setObject:obj forExtensionClass:[GDataAtomContent class]]; 498 [self setObject:obj forExtensionClass:[GDataAtomContent class]];
499 } 499 }
500 500
501 - (void)setContentWithString:(NSString *)str { 501 - (void)setContentWithString:(NSString *)str {
502 GDataAtomContent *obj = [GDataAtomContent contentWithString:str]; 502 GDataAtomContent *obj = [GDataAtomContent contentWithString:str];
503 [self setObject:obj forExtensionClass:[GDataAtomContent class]]; 503 [self setObject:obj forExtensionClass:[GDataAtomContent class]];
504 } 504 }
505 505
506 - (GDataTextConstruct *)rightsString { 506 - (GDataTextConstruct *)rightsString {
507 GDataTextConstruct *obj; 507 GDataTextConstruct *obj;
508 508
509 obj = [self objectForExtensionClass:[GDataAtomRights class]]; 509 obj = [self objectForExtensionClass:[GDataAtomRights class]];
510 return obj; 510 return obj;
511 } 511 }
512 512
513 - (void)setRightsString:(GDataTextConstruct *)obj { 513 - (void)setRightsString:(GDataTextConstruct *)obj {
514 [self setObject:obj forExtensionClass:[GDataAtomRights class]]; 514 [self setObject:obj forExtensionClass:[GDataAtomRights class]];
515 } 515 }
516 516
517 - (void)setRightsStringWithString:(NSString *)str { 517 - (void)setRightsStringWithString:(NSString *)str {
518 GDataAtomRights *obj; 518 GDataAtomRights *obj;
519 519
520 obj = [GDataAtomRights textConstructWithString:str]; 520 obj = [GDataAtomRights textConstructWithString:str];
521 [self setObject:obj forExtensionClass:[GDataAtomRights class]]; 521 [self setObject:obj forExtensionClass:[GDataAtomRights class]];
522 } 522 }
523 523
524 - (NSArray *)links { 524 - (NSArray *)links {
525 NSArray *array = [self objectsForExtensionClass:[GDataLink class]]; 525 NSArray *array = [self objectsForExtensionClass:[GDataLink class]];
526 return array; 526 return array;
527 } 527 }
528 528
529 - (void)setLinks:(NSArray *)array { 529 - (void)setLinks:(NSArray *)array {
530 [self setObjects:array forExtensionClass:[GDataLink class]]; 530 [self setObjects:array forExtensionClass:[GDataLink class]];
531 } 531 }
532 532
533 - (void)addLink:(GDataLink *)obj { 533 - (void)addLink:(GDataLink *)obj {
534 [self addObject:obj forExtensionClass:[GDataLink class]]; 534 [self addObject:obj forExtensionClass:[GDataLink class]];
535 } 535 }
536 536
537 - (NSArray *)authors { 537 - (NSArray *)authors {
538 NSArray *array = [self objectsForExtensionClass:[GDataAtomAuthor class]]; 538 NSArray *array = [self objectsForExtensionClass:[GDataAtomAuthor class]];
539 return array; 539 return array;
540 } 540 }
541 541
542 - (void)setAuthors:(NSArray *)array { 542 - (void)setAuthors:(NSArray *)array {
543 [self setObjects:array forExtensionClass:[GDataAtomAuthor class]]; 543 [self setObjects:array forExtensionClass:[GDataAtomAuthor class]];
544 } 544 }
545 545
546 - (void)addAuthor:(GDataPerson *)obj { 546 - (void)addAuthor:(GDataPerson *)obj {
547 [self addObject:obj forExtensionClass:[GDataAtomAuthor class]]; 547 [self addObject:obj forExtensionClass:[GDataAtomAuthor class]];
548 } 548 }
549 549
550 - (NSArray *)contributors { 550 - (NSArray *)contributors {
551 NSArray *array = [self objectsForExtensionClass:[GDataAtomContributor class]]; 551 NSArray *array = [self objectsForExtensionClass:[GDataAtomContributor class]];
552 return array; 552 return array;
553 } 553 }
554 554
555 - (void)setContributors:(NSArray *)array { 555 - (void)setContributors:(NSArray *)array {
556 [self setObjects:array forExtensionClass:[GDataAtomContributor class]]; 556 [self setObjects:array forExtensionClass:[GDataAtomContributor class]];
557 } 557 }
558 558
559 - (void)addContributor:(GDataPerson *)obj { 559 - (void)addContributor:(GDataPerson *)obj {
560 [self addObject:obj forExtensionClass:[GDataAtomContributor class]]; 560 [self addObject:obj forExtensionClass:[GDataAtomContributor class]];
561 } 561 }
562 562
563 - (NSArray *)categories { 563 - (NSArray *)categories {
564 NSArray *array = [self objectsForExtensionClass:[GDataCategory class]]; 564 NSArray *array = [self objectsForExtensionClass:[GDataCategory class]];
565 return array; 565 return array;
566 } 566 }
567 567
568 - (void)setCategories:(NSArray *)array { 568 - (void)setCategories:(NSArray *)array {
569 [self setObjects:array forExtensionClass:[GDataCategory class]]; 569 [self setObjects:array forExtensionClass:[GDataCategory class]];
570 } 570 }
571 571
572 - (void)addCategory:(GDataCategory *)obj { 572 - (void)addCategory:(GDataCategory *)obj {
573 [self addObject:obj forExtensionClass:[GDataCategory class]]; 573 [self addObject:obj forExtensionClass:[GDataCategory class]];
574 } 574 }
575 575
576 - (void)removeCategory:(GDataCategory *)obj { 576 - (void)removeCategory:(GDataCategory *)obj {
577 [self removeObject:obj forExtensionClass:[GDataCategory class]]; 577 [self removeObject:obj forExtensionClass:[GDataCategory class]];
578 } 578 }
579 579
580 // File uploading 580 // File uploading
581 581
582 - (NSData *)uploadData { 582 - (NSData *)uploadData {
583 return uploadData_; 583 return uploadData_;
584 } 584 }
585 585
586 - (void)setUploadData:(NSData *)data { 586 - (void)setUploadData:(NSData *)data {
587 [uploadData_ autorelease]; 587 [uploadData_ autorelease];
588 uploadData_ = [data retain]; 588 uploadData_ = [data retain];
589 } 589 }
590 590
591 - (NSFileHandle *)uploadFileHandle { 591 - (NSFileHandle *)uploadFileHandle {
592 return uploadFileHandle_; 592 return uploadFileHandle_;
593 } 593 }
594 594
595 - (void)setUploadFileHandle:(NSFileHandle *)data { 595 - (void)setUploadFileHandle:(NSFileHandle *)data {
596 [uploadFileHandle_ autorelease]; 596 [uploadFileHandle_ autorelease];
597 uploadFileHandle_ = [data retain]; 597 uploadFileHandle_ = [data retain];
598 } 598 }
599 599
600 - (NSURL *)uploadLocationURL { 600 - (NSURL *)uploadLocationURL {
601 return uploadLocationURL_; 601 return uploadLocationURL_;
602 } 602 }
603 603
604 - (void)setUploadLocationURL:(NSURL *)url { 604 - (void)setUploadLocationURL:(NSURL *)url {
605 [uploadLocationURL_ autorelease]; 605 [uploadLocationURL_ autorelease];
606 uploadLocationURL_ = [url retain]; 606 uploadLocationURL_ = [url retain];
607 } 607 }
608 608
609 - (NSString *)uploadMIMEType { 609 - (NSString *)uploadMIMEType {
610 return uploadMIMEType_; 610 return uploadMIMEType_;
611 } 611 }
612 612
613 - (void)setUploadMIMEType:(NSString *)str { 613 - (void)setUploadMIMEType:(NSString *)str {
614 [uploadMIMEType_ autorelease]; 614 [uploadMIMEType_ autorelease];
615 uploadMIMEType_ = [str copy]; 615 uploadMIMEType_ = [str copy];
616 } 616 }
617 617
618 - (NSString *)uploadSlug { 618 - (NSString *)uploadSlug {
619 return uploadSlug_; 619 return uploadSlug_;
620 } 620 }
621 621
622 - (void)setUploadSlug:(NSString *)str { 622 - (void)setUploadSlug:(NSString *)str {
623 [uploadSlug_ autorelease]; 623 [uploadSlug_ autorelease];
624 624
625 // encode per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7 625 // encode per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7
626 NSString *encoded = [GDataUtilities stringByPercentEncodingUTF8ForString:str]; 626 NSString *encoded = [GDataUtilities stringByPercentEncodingUTF8ForString:str];
627 uploadSlug_ = [encoded copy]; 627 uploadSlug_ = [encoded copy];
628 } 628 }
629 629
630 - (BOOL)shouldUploadDataOnly { 630 - (BOOL)shouldUploadDataOnly {
631 return shouldUploadDataOnly_; 631 return shouldUploadDataOnly_;
632 } 632 }
633 633
634 - (void)setShouldUploadDataOnly:(BOOL)flag { 634 - (void)setShouldUploadDataOnly:(BOOL)flag {
635 shouldUploadDataOnly_ = flag; 635 shouldUploadDataOnly_ = flag;
636 } 636 }
637 637
638 // extension for deletion marking 638 // extension for deletion marking
639 - (BOOL)isDeleted { 639 - (BOOL)isDeleted {
640 GDataDeleted *deleted = [self objectForExtensionClass:[GDataDeleted class]]; 640 GDataDeleted *deleted = [self objectForExtensionClass:[GDataDeleted class]];
641 return (deleted != nil); 641 return (deleted != nil);
642 } 642 }
643 643
644 - (void)setIsDeleted:(BOOL)isDeleted { 644 - (void)setIsDeleted:(BOOL)isDeleted {
645 if (isDeleted) { 645 if (isDeleted) {
646 // set the extension 646 // set the extension
647 [self setObject:[GDataDeleted deleted] forExtensionClass:[GDataDeleted class]]; 647 [self setObject:[GDataDeleted deleted] forExtensionClass:[GDataDeleted class]];
648 } else { 648 } else {
649 // remove the extension 649 // remove the extension
650 [self setObject:nil forExtensionClass:[GDataDeleted class]]; 650 [self setObject:nil forExtensionClass:[GDataDeleted class]];
651 } 651 }
652 } 652 }
653 653
654 // extensions for Atom publishing control 654 // extensions for Atom publishing control
655 655
656 - (GDataAtomPubControl *)atomPubControl { 656 - (GDataAtomPubControl *)atomPubControl {
657 return [self objectForExtensionClass:[GDataAtomPubControl class]]; 657 return [self objectForExtensionClass:[GDataAtomPubControl class]];
658 } 658 }
659 659
660 - (void)setAtomPubControl:(GDataAtomPubControl *)obj { 660 - (void)setAtomPubControl:(GDataAtomPubControl *)obj {
661 [self setObject:obj forExtensionClass:[GDataAtomPubControl class]]; 661 [self setObject:obj forExtensionClass:[GDataAtomPubControl class]];
662 } 662 }
663 663
664 // extensions for batch support 664 // extensions for batch support
665 665
666 - (GDataBatchOperation *)batchOperation { 666 - (GDataBatchOperation *)batchOperation {
667 return (GDataBatchOperation *) [self objectForExtensionClass:[GDataBatchOperation class]]; 667 return (GDataBatchOperation *) [self objectForExtensionClass:[GDataBatchOperation class]];
668 } 668 }
669 669
670 - (void)setBatchOperation:(GDataBatchOperation *)obj { 670 - (void)setBatchOperation:(GDataBatchOperation *)obj {
671 [self setObject:obj forExtensionClass:[GDataBatchOperation class]]; 671 [self setObject:obj forExtensionClass:[GDataBatchOperation class]];
672 } 672 }
673 673
674 - (GDataBatchID *)batchID { 674 - (GDataBatchID *)batchID {
675 return (GDataBatchID *) [self objectForExtensionClass:[GDataBatchID class]]; 675 return (GDataBatchID *) [self objectForExtensionClass:[GDataBatchID class]];
676 } 676 }
677 677
678 - (void)setBatchID:(GDataBatchID *)obj { 678 - (void)setBatchID:(GDataBatchID *)obj {
679 [self setObject:obj forExtensionClass:[GDataBatchID class]]; 679 [self setObject:obj forExtensionClass:[GDataBatchID class]];
680 } 680 }
681 681
682 - (void)setBatchIDWithString:(NSString *)str { 682 - (void)setBatchIDWithString:(NSString *)str {
683 GDataBatchID *obj = [GDataBatchID batchIDWithString:str]; 683 GDataBatchID *obj = [GDataBatchID batchIDWithString:str];
684 [self setBatchID:obj]; 684 [self setBatchID:obj];
685 } 685 }
686 686
687 - (GDataBatchStatus *)batchStatus { 687 - (GDataBatchStatus *)batchStatus {
688 return (GDataBatchStatus *) [self objectForExtensionClass:[GDataBatchStatus class]]; 688 return (GDataBatchStatus *) [self objectForExtensionClass:[GDataBatchStatus class]];
689 } 689 }
690 690
691 - (void)setBatchStatus:(GDataBatchStatus *)obj { 691 - (void)setBatchStatus:(GDataBatchStatus *)obj {
692 [self setObject:obj forExtensionClass:[GDataBatchStatus class]]; 692 [self setObject:obj forExtensionClass:[GDataBatchStatus class]];
693 } 693 }
694 694
695 - (GDataBatchInterrupted *)batchInterrupted { 695 - (GDataBatchInterrupted *)batchInterrupted {
696 return (GDataBatchInterrupted *) [self objectForExtensionClass:[GDataBatchInterrupted class]]; 696 return (GDataBatchInterrupted *) [self objectForExtensionClass:[GDataBatchInterrupted class]];
697 } 697 }
698 698
699 - (void)setBatchInterrupted:(GDataBatchInterrupted *)obj { 699 - (void)setBatchInterrupted:(GDataBatchInterrupted *)obj {
700 [self setObject:obj forExtensionClass:[GDataBatchInterrupted class]]; 700 [self setObject:obj forExtensionClass:[GDataBatchInterrupted class]];
701 } 701 }
702 702
703 + (NSDictionary *)batchNamespaces { 703 + (NSDictionary *)batchNamespaces {
704 NSDictionary *namespaces = [NSDictionary dictionaryWithObjectsAndKeys: 704 NSDictionary *namespaces = [NSDictionary dictionaryWithObjectsAndKeys:
705 kGDataNamespaceBatch, kGDataNamespaceBatchPrefix, nil]; 705 kGDataNamespaceBatch, kGDataNamespaceBatchPrefix, nil];
706 return namespaces; 706 return namespaces;
707 } 707 }
708 708
709 #pragma mark - 709 #pragma mark -
710 710
711 - (NSArray *)categoriesWithScheme:(NSString *)scheme { 711 - (NSArray *)categoriesWithScheme:(NSString *)scheme {
712 NSArray *array = [GDataCategory categoriesWithScheme:scheme 712 NSArray *array = [GDataCategory categoriesWithScheme:scheme
713 fromCategories:[self categories]]; 713 fromCategories:[self categories]];
714 return array; 714 return array;
715 } 715 }
716 716
717 - (GDataCategory *)kindCategory { 717 - (GDataCategory *)kindCategory {
718 GDataCategory *cat = [GDataUtilities firstObjectFromArray:[self categories] 718 GDataCategory *cat = [GDataUtilities firstObjectFromArray:[self categories]
719 withValue:kGDataCategoryScheme 719 withValue:kGDataCategoryScheme
720 forKeyPath:@"scheme"]; 720 forKeyPath:@"scheme"];
721 return cat; 721 return cat;
722 } 722 }
723 723
724 - (NSArray *)linksWithRelAttributeValue:(NSString *)relValue { 724 - (NSArray *)linksWithRelAttributeValue:(NSString *)relValue {
725 725
726 NSArray *array = [GDataUtilities objectsFromArray:[self links] 726 NSArray *array = [GDataUtilities objectsFromArray:[self links]
727 withValue:relValue 727 withValue:relValue
728 forKeyPath:@"rel"]; 728 forKeyPath:@"rel"];
729 return array; 729 return array;
730 } 730 }
731 731
732 - (GDataLink *)linkWithRelAttributeValue:(NSString *)rel { 732 - (GDataLink *)linkWithRelAttributeValue:(NSString *)rel {
733 733
734 return [GDataLink linkWithRel:rel 734 return [GDataLink linkWithRel:rel
735 type:nil 735 type:nil
736 fromLinks:[self links]]; 736 fromLinks:[self links]];
737 } 737 }
738 738
739 - (GDataLink *)linkWithRelAttributeValue:(NSString *)rel 739 - (GDataLink *)linkWithRelAttributeValue:(NSString *)rel
740 type:(NSString *)type { 740 type:(NSString *)type {
741 return [GDataLink linkWithRel:rel 741 return [GDataLink linkWithRel:rel
742 type:type 742 type:type
743 fromLinks:[self links]]; 743 fromLinks:[self links]];
744 } 744 }
745 745
746 - (GDataLink *)feedLink { 746 - (GDataLink *)feedLink {
747 return [self linkWithRelAttributeValue:kGDataLinkRelFeed]; 747 return [self linkWithRelAttributeValue:kGDataLinkRelFeed];
748 } 748 }
749 749
750 - (GDataLink *)editLink { 750 - (GDataLink *)editLink {
751 return [self linkWithRelAttributeValue:@"edit"]; 751 return [self linkWithRelAttributeValue:@"edit"];
752 } 752 }
753 753
754 - (GDataLink *)editMediaLink { 754 - (GDataLink *)editMediaLink {
755 return [self linkWithRelAttributeValue:@"edit-media"]; 755 return [self linkWithRelAttributeValue:@"edit-media"];
756 } 756 }
757 757
758 - (GDataLink *)alternateLink { 758 - (GDataLink *)alternateLink {
759 return [self linkWithRelAttributeValue:@"alternate"]; 759 return [self linkWithRelAttributeValue:@"alternate"];
760 } 760 }
761 761
762 - (GDataLink *)relatedLink { 762 - (GDataLink *)relatedLink {
763 return [self linkWithRelAttributeValue:@"related"]; 763 return [self linkWithRelAttributeValue:@"related"];
764 } 764 }
765 765
766 - (GDataLink *)postLink { 766 - (GDataLink *)postLink {
767 return [self linkWithRelAttributeValue:kGDataLinkRelPost]; 767 return [self linkWithRelAttributeValue:kGDataLinkRelPost];
768 } 768 }
769 769
770 - (GDataLink *)selfLink { 770 - (GDataLink *)selfLink {
771 return [self linkWithRelAttributeValue:@"self"]; 771 return [self linkWithRelAttributeValue:@"self"];
772 } 772 }
773 773
774 - (GDataLink *)HTMLLink { 774 - (GDataLink *)HTMLLink {
775 return [self linkWithRelAttributeValue:@"alternate" 775 return [self linkWithRelAttributeValue:@"alternate"
776 type:kGDataLinkTypeHTML]; 776 type:kGDataLinkTypeHTML];
777 } 777 }
778 778
779 - (GDataLink *)uploadEditLink { 779 - (GDataLink *)uploadEditLink {
780 return [self linkWithRelAttributeValue:kGDataLinkRelResumableEdit]; 780 return [self linkWithRelAttributeValue:kGDataLinkRelResumableEdit];
781 } 781 }
782 782
783 - (BOOL)canEdit { 783 - (BOOL)canEdit {
784 return ([self editLink] != nil); 784 return ([self editLink] != nil);
785 } 785 }
786 @end 786 @end
Powered by Google Project Hosting