Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

implement user/tag search; adding missing release/autorelease calls; …

…fix case in zebrasView.m import
  • Loading branch information...
commit bc41aab3119434386f42f1fadbaac6c9dda973f4 1 parent 3fbef6b
@zuercher authored
View
12 Flickr.h
@@ -1,5 +1,10 @@
#import <Cocoa/Cocoa.h>
-#import <xmlParser.h>
+#import <XmlParser.h>
+
+typedef enum {
+ FTAll,
+ FTAny
+} FlickrTagMode;
@interface Flickr : NSObject {
NSMutableArray *imageQueue;
@@ -12,10 +17,15 @@
- (id)init;
- (void)enqueueInteresting;
+- (void)enqueueUserAndTags:(NSString *)userId tags:(NSArray *)tags tagMode:(FlickrTagMode)tagMode;
+- (void)enqueueUser:(NSString *)userId;
+- (void)enqueueTags:(NSArray *)tags tagMode:(FlickrTagMode)tagMode;
- (Boolean)imageAvailable;
- (NSURL *)nextImage;
+- (NSString *)enqueueInterestingUrl;
+- (NSString *)enqueueUserAndTagsUrl:(NSString *)userId tags:(NSArray *)tags tagMode:(FlickrTagMode)tagMode;
- (void)addPhotos:(NSDictionary *)response;
- (NSURL *)makeImageUrl:(NSDictionary *)photoTag;
@end
View
85 Flickr.m
@@ -1,9 +1,14 @@
-#import "flickr.h"
+#import "Flickr.h"
#import "NSMutableArray_Shuffle.h"
#define FLICKR_API_KEY @"7d5696ac966affcd63a730393aaa12f3"
#define FLICKR_API_SECRET @"3bdae98bf3c15a0b"
+#define FLICKR_INTERESTINGNESS_URL_FORMAT @"http://api.flickr.com/services/rest/?method=flickr.interestingness.getList&api_key=%@&per_page=%d"
+#define FLICKR_SEARCH_USER_URL_FORMAT @"http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=%@&per_page=%d&user_id=%@"
+#define FLICKR_SEARCH_TAGS_URL_FORMAT @"http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=%@&per_page=%d&tags=%@&tag_mode=%@"
+#define FLICKR_SEARCH_USER_AND_TAGS_URL_FORMAT @"http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=%@&per_page=%d&user_id=%@&tags=%@&tag_mode=%@"
+
// flickr.photos.search and flickr.interestingness.getList don't need signing and are GET
@implementation Flickr
@@ -35,13 +40,10 @@ - (Boolean)imageAvailable
return [imageQueue count] > 0;
}
-- (void)enqueueInteresting
+- (void)enqueue:(NSString *)url
{
- NSString *urlString = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.interestingness.getList&api_key=%@&per_page=%d",
- FLICKR_API_KEY,
- [self perPage]];
- NSLog(@"REQUEST: %@\n", urlString);
- NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]
+ NSLog(@"REQUEST: %@\n", url);
+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
@@ -52,6 +54,73 @@ - (void)enqueueInteresting
}
}
+- (NSString *)enqueueInterestingUrl
+{
+ return [NSString stringWithFormat:FLICKR_INTERESTINGNESS_URL_FORMAT,
+ FLICKR_API_KEY,
+ [self perPage]];
+}
+
+- (void)enqueueInteresting
+{
+ [self enqueue:[self enqueueInterestingUrl]];
+}
+
+- (NSString *)enqueueUserAndTagsUrl:(NSString *)userId tags:(NSArray *)tags tagMode:(FlickrTagMode)tagMode
+{
+ if (!tags) {
+ return [NSString stringWithFormat:FLICKR_SEARCH_USER_URL_FORMAT,
+ FLICKR_API_KEY,
+ [self perPage],
+ userId];
+ }
+
+ NSString *tagModeStr = (tagMode == FTAll ? @"all" : @"any");
+
+ NSString *tagsStr = @"";
+ for(NSString *tag in tags) {
+ if ([tagsStr length] > 0) {
+ tagsStr = [tagsStr stringByAppendingString:@"%2C"]; // comma
+ }
+ NSString *escapedTag = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
+ (CFStringRef)tag,
+ NULL,
+ CFSTR(";/?:@&=+,$%"),
+ kCFStringEncodingUTF8);
+ tagsStr = [tagsStr stringByAppendingString:escapedTag];
+ }
+
+ if (userId) {
+ return [NSString stringWithFormat:FLICKR_SEARCH_USER_AND_TAGS_URL_FORMAT,
+ FLICKR_API_KEY,
+ [self perPage],
+ userId,
+ tagsStr,
+ tagModeStr];
+ } else {
+ return [NSString stringWithFormat:FLICKR_SEARCH_TAGS_URL_FORMAT,
+ FLICKR_API_KEY,
+ [self perPage],
+ tagsStr,
+ tagModeStr];
+ }
+}
+
+- (void)enqueueUserAndTags:(NSString *)userId tags:(NSArray *)tags tagMode:(FlickrTagMode)tagMode
+{
+ [self enqueue:[self enqueueUserAndTagsUrl:userId tags:tags tagMode:tagMode]];
+}
+
+- (void)enqueueUser:(NSString *)userId
+{
+ [self enqueueUserAndTags:userId tags:nil tagMode:FTAll];
+}
+
+- (void)enqueueTags:(NSArray *)tags tagMode:(FlickrTagMode)tagMode
+{
+ [self enqueueUserAndTags:nil tags:tags tagMode:tagMode];
+}
+
-(NSURL *)nextImage
{
if ([imageQueue count] == 0) {
@@ -60,6 +129,7 @@ -(NSURL *)nextImage
NSURL *next = [imageQueue objectAtIndex:0];
[imageQueue removeObjectAtIndex:0];
+ [next autorelease];
return next;
}
@@ -134,6 +204,7 @@ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)err
NSLog(@"didFailWithError\n");
// TODO: track error
+ [connection release];
[responseXml setLength:0];
}
View
2  XmlParser.m
@@ -1,4 +1,4 @@
-#import "xmlParser.h"
+#import "XmlParser.h"
NSString *const XmlParserExceptionName = @"XmlParserException";
NSString *const XmlParserTextKey = @"__text";
View
218 test/FlickrTest.m
@@ -1,5 +1,5 @@
-#import "flickrTest.h"
-#import "flickr.h"
+#import "FlickrTest.h"
+#import "Flickr.h"
#define SAMPLE_ERROR @"\
<?xml version=\"1.0\" encoding=\"utf-8\" ?>\
@@ -50,6 +50,62 @@ -(void)testMakeImageUrl_ShouldConvertFlickrContentToFlickrImageUrl
NSURL *url = [f makeImageUrl:photoTag];
STAssertNotNil(url, nil);
STAssertEqualObjects(@"http://farmFARM.static.flickr.com/SERVER/ID_SECRET_b.jpg", [url absoluteString], nil);
+
+ [f release];
+}
+
+- (NSDictionary *)queryParams:(NSString *)url
+{
+ NSRange questionMarkRange;
+ questionMarkRange.location = (unsigned int)'?';
+ questionMarkRange.length = 1;
+ NSCharacterSet *questionMark = [NSCharacterSet characterSetWithRange:questionMarkRange];
+
+ NSRange ampersandRange;
+ ampersandRange.location = (unsigned int)'&';
+ ampersandRange.length = 1;
+ NSCharacterSet *ampersand = [NSCharacterSet characterSetWithRange:ampersandRange];
+
+ NSRange equalsRange;
+ equalsRange.location = (unsigned int)'=';
+ equalsRange.length = 1;
+ NSCharacterSet *equals = [NSCharacterSet characterSetWithRange:equalsRange];
+
+ NSScanner *scanner = [NSScanner scannerWithString:url];
+ [scanner scanUpToCharactersFromSet:questionMark intoString:NULL];
+ [scanner scanCharactersFromSet:questionMark intoString:NULL];
+
+ NSMutableDictionary *queryParams = [NSMutableDictionary dictionary];
+ while([scanner isAtEnd] == NO) {
+ NSString *kvPair;
+ [scanner scanUpToCharactersFromSet:ampersand intoString:&kvPair];
+ [scanner scanCharactersFromSet:ampersand intoString:NULL];
+
+ NSRange equalsPos = [kvPair rangeOfCharacterFromSet:equals];
+ NSString *key = [kvPair substringToIndex:equalsPos.location];
+ NSString *value = [kvPair substringFromIndex:(equalsPos.location + 1)];
+
+ [queryParams setObject:value forKey:key];
+ }
+
+ return queryParams;
+}
+
+- (void)testEnqueueInterestingUrl_shouldGenerateCorrectUrl
+{
+ Flickr *f = [[Flickr alloc] init];
+ [f setPerPage:99];
+
+ NSString *url = [f enqueueInterestingUrl];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEquals([queryParams count], (NSUInteger)3, nil);
+ STAssertEqualObjects([queryParams objectForKey:@"method"], @"flickr.interestingness.getList", nil);
+ STAssertNotNil([queryParams objectForKey:@"api_key"], nil);
+ STAssertEqualObjects([queryParams objectForKey:@"per_page"], @"99", nil);
+
+ [f release];
}
- (void)testEnqueueInteresting_shouldDownloadDataFromFlickr
@@ -75,6 +131,146 @@ - (void)testEnqueueInteresting_shouldDownloadDataFromFlickr
[f release];
}
+- (void)testEnqueueUserAndTagsUrl_shouldGenerateCorrectUrlWithMethodApiKeyAndPageSize
+{
+ Flickr *f = [[Flickr alloc] init];
+ [f setPerPage:99];
+
+ NSString *url = [f enqueueUserAndTagsUrl:@"bob" tags:[NSArray arrayWithObject:@"x"] tagMode:FTAll];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEquals([queryParams count], (NSUInteger)6, nil);
+ STAssertEqualObjects([queryParams objectForKey:@"method"], @"flickr.photos.search", nil);
+ STAssertNotNil([queryParams objectForKey:@"api_key"], nil);
+ STAssertEqualObjects([queryParams objectForKey:@"per_page"], @"99", nil);
+ STAssertNotNil([queryParams objectForKey:@"user_id"], nil);
+ STAssertNotNil([queryParams objectForKey:@"tags"], nil);
+ STAssertNotNil([queryParams objectForKey:@"tag_mode"], nil);
+
+ [f release];
+}
+
+- (void)testEnqueueUserAndTagsUrl_shouldGenerateCorrectUrlForUserOnly
+{
+ Flickr *f = [[Flickr alloc] init];
+
+ NSString *url = [f enqueueUserAndTagsUrl:@"bob" tags:nil tagMode:FTAll];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEquals([queryParams count], (NSUInteger)4, nil);
+ STAssertNotNil([queryParams objectForKey:@"method"], nil);
+ STAssertNotNil([queryParams objectForKey:@"api_key"], nil);
+ STAssertNotNil([queryParams objectForKey:@"per_page"], nil);
+ STAssertEqualObjects([queryParams objectForKey:@"user_id"], @"bob", nil);
+
+ [f release];
+}
+
+- (void)testEnqueueUserAndTagsUrl_shouldGenerateCorrectUrlForSingleTag
+{
+ Flickr *f = [[Flickr alloc] init];
+
+ NSString *url = [f enqueueUserAndTagsUrl:nil tags:[NSArray arrayWithObject:@"x"] tagMode:FTAll];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEquals([queryParams count], (NSUInteger)5, nil);
+ STAssertNotNil([queryParams objectForKey:@"method"], nil);
+ STAssertNotNil([queryParams objectForKey:@"api_key"], nil);
+ STAssertNotNil([queryParams objectForKey:@"per_page"], nil);
+ STAssertEqualObjects([queryParams objectForKey:@"tags"], @"x", nil);
+ STAssertEqualObjects([queryParams objectForKey:@"tag_mode"], @"all", nil);
+
+ [f release];
+}
+
+- (void)testEnqueueUserAndTagsUrl_shouldGenerateCorrectUrlForSingleTagRequiringEncoding
+{
+ Flickr *f = [[Flickr alloc] init];
+
+ NSString *url = [f enqueueUserAndTagsUrl:nil tags:[NSArray arrayWithObject:@"x&y"] tagMode:FTAll];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEqualObjects([queryParams objectForKey:@"tags"], @"x%26y", nil);
+
+ [f release];
+}
+
+- (void)testEnqueueUserAndTagsUrl_shouldGenerateCorrectUrlForMultipleTagsInAllMode
+{
+ Flickr *f = [[Flickr alloc] init];
+
+ NSString *url = [f enqueueUserAndTagsUrl:nil tags:[NSArray arrayWithObjects:@"x&y", @"z", nil] tagMode:FTAll];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEqualObjects([queryParams objectForKey:@"tags"], @"x%26y%2Cz", nil);
+ STAssertEqualObjects([queryParams objectForKey:@"tag_mode"], @"all", nil);
+
+ [f release];
+}
+
+- (void)testEnqueueUserAndTagsUrl_shouldGenerateCorrectUrlForMultipleTagsInAnyMode
+{
+ Flickr *f = [[Flickr alloc] init];
+
+ NSString *url = [f enqueueUserAndTagsUrl:nil tags:[NSArray arrayWithObjects:@"x&y", @"z", nil] tagMode:FTAny];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEqualObjects([queryParams objectForKey:@"tags"], @"x%26y%2Cz", nil);
+ STAssertEqualObjects([queryParams objectForKey:@"tag_mode"], @"any", nil);
+
+ [f release];
+}
+
+- (void)testEnqueueUserAndTagsUrl_shouldGenerateCorrectUrlForUserAndTags
+{
+ Flickr *f = [[Flickr alloc] init];
+
+ NSString *url = [f enqueueUserAndTagsUrl:@"bob" tags:[NSArray arrayWithObjects:@"x&y", @"z", nil] tagMode:FTAny];
+
+ NSDictionary *queryParams = [self queryParams:url];
+
+ STAssertEquals([queryParams count], (NSUInteger)6, nil);
+ STAssertNotNil([queryParams objectForKey:@"method"], nil);
+ STAssertNotNil([queryParams objectForKey:@"api_key"], nil);
+ STAssertNotNil([queryParams objectForKey:@"per_page"], nil);
+ STAssertEqualObjects([queryParams objectForKey:@"user_id"], @"bob", nil);
+ STAssertEqualObjects([queryParams objectForKey:@"tags"], @"x%26y%2Cz", nil);
+ STAssertEqualObjects([queryParams objectForKey:@"tag_mode"], @"any", nil);
+
+ [f release];
+}
+
+- (void)testEnqueueUserAndTags_shouldDownloadDataFromFlickr
+{
+ Flickr *f = [[Flickr alloc] init];
+ [f setPerPage:10];
+
+ [f enqueueUserAndTags:@"75877390@N00" tags:[NSArray arrayWithObject:@"Marlena"] tagMode:FTAll];
+
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+
+ Boolean available = FALSE;
+ for(int i = 0; i < 10 && !available; i++) {
+ NSLog(@"start run loop\n");
+ [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:3]];
+ NSLog(@"end run loop\n");
+
+ available = [f imageAvailable];
+ }
+
+ STAssertTrue(available, @"expected imageAvailable to be true");
+
+ [f release];
+}
+
+
+
- (void)testAddPhotos_shouldHandleErrorsWithoutCrashing
{
Flickr *f = [[Flickr alloc] init];
@@ -84,6 +280,8 @@ - (void)testAddPhotos_shouldHandleErrorsWithoutCrashing
[f addPhotos:result];
STAssertFalse([f imageAvailable], nil);
+
+ [f release];
}
- (void)testAddPhotos_shouldHandleEmptyResponseWithoutCrashing
@@ -95,6 +293,8 @@ - (void)testAddPhotos_shouldHandleEmptyResponseWithoutCrashing
[f addPhotos:result];
STAssertFalse([f imageAvailable], nil);
+
+ [f release];
}
- (void)testAddPhotos_shouldHandleMissingPhotoEntriesWithoutCrashing
@@ -106,6 +306,8 @@ - (void)testAddPhotos_shouldHandleMissingPhotoEntriesWithoutCrashing
[f addPhotos:result];
STAssertFalse([f imageAvailable], nil);
+
+ [f release];
}
- (void)testAddPhotos_shouldAddPhotosToQueue
@@ -117,6 +319,8 @@ - (void)testAddPhotos_shouldAddPhotosToQueue
[f addPhotos:result];
STAssertTrue([f imageAvailable], nil);
+
+ [f release];
}
- (void)testAddPhotos_shouldAddPhotosToQueueInRandomOrder
@@ -145,6 +349,10 @@ - (void)testAddPhotos_shouldAddPhotosToQueueInRandomOrder
STAssertEquals([randomizedOrder count], [originalOrder count], nil);
STAssertFalse([randomizedOrder isEqualToArray:originalOrder], nil);
+
+ [originalOrder release];
+ [randomizedOrder release];
+ [f release];
}
- (void)testNextImage_shouldReturnNilWhenQueueIsEmpty
@@ -152,9 +360,11 @@ - (void)testNextImage_shouldReturnNilWhenQueueIsEmpty
Flickr *f = [[Flickr alloc] init];
STAssertFalse([f imageAvailable], nil);
STAssertNil([f nextImage], nil);
+
+ [f release];
}
-- (void)textNextImage_shouldReturnImagesUntilQueueIsEmpty
+- (void)testNextImage_shouldReturnImagesUntilQueueIsEmpty
{
Flickr *f = [[Flickr alloc] init];
@@ -170,6 +380,8 @@ - (void)textNextImage_shouldReturnImagesUntilQueueIsEmpty
numPhotos++;
}
STAssertEquals(10, numPhotos, nil);
+
+ [f release];
}
@end
View
7 test/NSMutableArray_ShuffleTest.m
@@ -17,7 +17,10 @@ - (void)testShuffle_ShouldShuffleAnArray
[array shuffle];
STAssertEquals([array count], [orig count], nil);
- STAssertFalse([array isEqualToArray:orig], nil);
+ STAssertFalse([array isEqualToArray:orig], nil);
+
+ [orig release];
+ [array release];
}
- (void)testShuffle_ShouldHandleEmptyArrays
@@ -25,6 +28,7 @@ - (void)testShuffle_ShouldHandleEmptyArrays
NSMutableArray *array = [[NSMutableArray alloc] init];
STAssertNoThrow([array shuffle], nil);
STAssertEquals([array count], (NSUInteger)0, nil);
+ [array release];
}
- (void)testShuffle_ShouldHandleSingleElementArrays
@@ -34,6 +38,7 @@ - (void)testShuffle_ShouldHandleSingleElementArrays
STAssertNoThrow([array shuffle], nil);
STAssertEquals([array count], (NSUInteger)1, nil);
+ [array release];
}
@end
View
2  zebrasView.m
@@ -1,4 +1,4 @@
-#import "zebrasView.h"
+#import "ZebrasView.h"
@implementation zebrasView
Please sign in to comment.
Something went wrong with that request. Please try again.