+(void) refreshFeedWithType:(BSYammerFeedType) feedType threadType:(BSYammerFeedThreadType) threadType olderThan:(BSYammerMessage*) oldestMessage newerThan:(BSYammerMessage*) latestMessage associatedWith:(NSManagedObject*) associatedEntity fromAccount:(BSYammerContext*) accountContext limit:(int) maxMessages toManagedObjectContext:(NSManagedObjectContext*) objectContext completionHandler:(void(^)(NSArray* objectIDs,NSError* errorOrNil)) completionHandler { NSString* requestURLString; NSNumber* oldestMessageID = oldestMessage.yammerMessageID; NSNumber* latestMessageID = latestMessage.yammerMessageID; NSNumber* associatedID = [associatedEntity primaryYammerID]; switch (feedType) { case BSYammerFeedAllCompany: requestURLString = @"https://www.yammer.com/api/v1/messages.json"; break; case BSYammerFeedSent: requestURLString = @"https://www.yammer.com/api/v1/messages/sent.json"; break; case BSYammerFeedReceived: requestURLString = @"https://www.yammer.com/api/v1/messages/received.json"; break; case BSYammerFeedPrivate: requestURLString = @"https://www.yammer.com/api/v1/messages/private.json"; break; case BSYammerFeedFollowing: requestURLString = @"https://www.yammer.com/api/v1/messages/following.json"; break; case BSYammerFeedFromUser: requestURLString = [NSString stringWithFormat:@"https://www.yammer.com/api/v1/messages/from_user/%qu.json",[associatedID unsignedLongLongValue]]; break; case BSYammerFeedAboutTopic: requestURLString = [NSString stringWithFormat:@"https://www.yammer.com/api/v1/messages/about_topic/%qu.json",[associatedID unsignedLongLongValue]]; break; case BSYammerFeedInGroup: requestURLString = [NSString stringWithFormat:@"https://www.yammer.com/api/v1/messages/in_group/%qu.json",[associatedID unsignedLongLongValue]]; break; case BSYammerFeedLikedBy: requestURLString = [NSString stringWithFormat:@"https://www.yammer.com/api/v1/messages/liked_by/%qu.json",[associatedID unsignedLongLongValue]]; break; case BSYammerFeedInThread: requestURLString = [NSString stringWithFormat:@"https://www.yammer.com/api/v1/messages/in_thread/%qu.json",[associatedID unsignedLongLongValue]]; break; case BSYammerFeedConversation: { if ([associatedEntity isKindOfClass:[BSYammerMessage class]]) { BSYammerMessage* msg = (BSYammerMessage*) associatedEntity; requestURLString = [NSString stringWithFormat:@"https://www.yammer.com/api/v1/messages/in_thread/%qu.json",[msg.yammerThreadID unsignedLongLongValue]]; } } break; default: ErrorLog(@"Unsupported feed type: %d",feedType); return; } NSURL* requestURL = [NSURL URLWithString:requestURLString]; NSMutableDictionary* requestParameters = [NSMutableDictionary dictionaryWithCapacity:4]; switch (threadType) { case BSYammerFeedCollapsedThread: requestParameters[@"threaded"] = @"true"; break; case BSYammerFeedExtendedThread: requestParameters[@"threaded"] = @"extended"; default: break; } if (oldestMessageID) { requestParameters[@"older_than"] = [NSString stringWithFormat:@"%qu",[oldestMessageID unsignedLongLongValue]]; } if (latestMessageID) { requestParameters[@"newer_than"] = [NSString stringWithFormat:@"%qu",[latestMessageID unsignedLongLongValue]]; } if (maxMessages > 0) { requestParameters[@"limit"] = [NSString stringWithFormat:@"%d",maxMessages]; } NSOperationQueue* callbackQueue = [NSOperationQueue callbackQueue]; BSYammerCacheMeta* yammerMeta = [BSYammerCacheMeta defaultInstance]; void (^postProcessingBlock)(id,NSData*,NSError*) = ^(id jsonResult,NSData* rawData,NSError* errorOrNil) { if (errorOrNil) { ErrorLog(@"Error on post-processing: %@",errorOrNil); [callbackQueue addOperationWithBlock:^{ completionHandler(nil,errorOrNil); }]; return; } else if (! [jsonResult isKindOfClass:[NSDictionary class]]) { ErrorLog(@"Wrong JSON data: %@",jsonResult); NSMutableDictionary* userInfo = [NSMutableDictionary dictionaryWithCapacity:3]; if (jsonResult) { userInfo[NSLocalizedDescriptionKey] = NSLocalizedString(@"Yammer returned an invalid data.", @"Error description"); userInfo[BSYammerCacheJSONObjectKey] = jsonResult; } else { userInfo[NSLocalizedDescriptionKey] = NSLocalizedString(@"Yammer returned no data.", @"Error description"); } userInfo[NSURLErrorKey] = requestURL; NSError* returnError = [NSError errorWithDomain:BSYammerCacheErrorDomain code:BSYammerCacheInvalidJSONFormat userInfo:userInfo]; [callbackQueue addOperationWithBlock:^{ completionHandler(nil,returnError); }]; return; } NSDictionary* resultDictionary = (NSDictionary*) jsonResult; NSArray* messages = resultDictionary[@"messages"]; NSArray* references = resultDictionary[@"references"]; //NSDictionary* threadedExtended = resultDictionary[@"threaded_extended"]; [objectContext performBlock:^{ // parse references before messages since they contains referred objects if (references.count > 0) { [yammerMeta refreshTypedJSONArray:references inManagedObjectContext:objectContext]; } NSArray* refreshedObjects = [self refreshFromJSONArray:messages inManagedObjectContext:objectContext]; NSMutableArray* returnObjectIDs = [NSMutableArray arrayWithCapacity:refreshedObjects.count]; for (BSYammerMessage* managedObject in refreshedObjects) { if (![managedObject isKindOfClass:[BSYammerMessage class]]) { continue; } if (feedType == BSYammerFeedFollowing) { managedObject.followed = @(YES); } [returnObjectIDs addObject:[managedObject objectID]]; } [callbackQueue addOperationWithBlock:^{ completionHandler(returnObjectIDs,nil); }]; }]; }; [accountContext jsonRequestWithURL:requestURL method:@"GET" parameters:requestParameters completionBlock:postProcessingBlock]; }