text: //
  //  ASIS3BucketRequest.m
  //  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
  //
  //  Created by Ben Copsey on 16/03/2010.
  //  Copyright 2010 All-Seeing Interactive. All rights reserved.
  //
  
  #import "ASIS3BucketRequest.h"
  #import "ASIS3BucketObject.h"
  
  
  // Private stuff
  @interface ASIS3BucketRequest ()
  @property (retain, nonatomic) ASIS3BucketObject *currentObject;
  @property (retain) NSMutableArray *objects;
  @property (retain) NSMutableArray *commonPrefixes;
  @property (assign) BOOL isTruncated;
  @end
  
  @implementation ASIS3BucketRequest
  
  - (id)initWithURL:(NSURL *)newURL
  {
  	self = [super initWithURL:newURL];
  	[self setObjects:[[[NSMutableArray alloc] init] autorelease]];
  	[self setCommonPrefixes:[[[NSMutableArray alloc] init] autorelease]];
  	return self;
  }
  
  + (id)requestWithBucket:(NSString *)theBucket
  {
  	ASIS3BucketRequest *request = [[[self alloc] initWithURL:nil] autorelease];
  	[request setBucket:theBucket];
  	return request;
  }
  
  + (id)requestWithBucket:(NSString *)theBucket subResource:(NSString *)theSubResource
  {
  	ASIS3BucketRequest *request = [[[self alloc] initWithURL:nil] autorelease];
  	[request setBucket:theBucket];
  	[request setSubResource:theSubResource];
  	return request;
  }
  
  + (id)PUTRequestWithBucket:(NSString *)theBucket
  {
  	ASIS3BucketRequest *request = [self requestWithBucket:theBucket];
  	[request setRequestMethod:@"PUT"];
  	return request;
  }
  
  
  + (id)DELETERequestWithBucket:(NSString *)theBucket
  {
  	ASIS3BucketRequest *request = [self requestWithBucket:theBucket];
  	[request setRequestMethod:@"DELETE"];
  	return request;
  }
  
  - (void)dealloc
  {
  	[currentObject release];
  	[objects release];
  	[commonPrefixes release];
  	[prefix release];
  	[marker release];
  	[delimiter release];
  	[subResource release];
  	[bucket release];
  	[super dealloc];
  }
  
  - (NSString *)canonicalizedResource
  {
  	if ([self subResource]) {
  		return [NSString stringWithFormat:@"/%@/?%@",[self bucket],[self subResource]];
  	} 
  	return [NSString stringWithFormat:@"/%@/",[self bucket]];
  }
  
  - (void)buildURL
  {
  	NSString *baseURL;
  	if ([self subResource]) {
  		baseURL = [NSString stringWithFormat:@"%@://%@.%@/?%@",[self requestScheme],[self bucket],[[self class] S3Host],[self subResource]];
  	} else {
  		baseURL = [NSString stringWithFormat:@"%@://%@.%@",[self requestScheme],[self bucket],[[self class] S3Host]];
  	}
  	NSMutableArray *queryParts = [[[NSMutableArray alloc] init] autorelease];
  	if ([self prefix]) {
  		[queryParts addObject:[NSString stringWithFormat:@"prefix=%@",[[self prefix] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
  	}
  	if ([self marker]) {
  		[queryParts addObject:[NSString stringWithFormat:@"marker=%@",[[self marker] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
  	}
  	if ([self delimiter]) {
  		[queryParts addObject:[NSString stringWithFormat:@"delimiter=%@",[[self delimiter] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
  	}
  	if ([self maxResultCount] > 0) {
  		[queryParts addObject:[NSString stringWithFormat:@"max-keys=%i",[self maxResultCount]]];
  	}
  	if ([queryParts count]) {
  		NSString* template = @"%@?%@";
  		if ([[self subResource] length] > 0) {
  			template = @"%@&%@";
  		}
  		[self setURL:[NSURL URLWithString:[NSString stringWithFormat:template,baseURL,[queryParts componentsJoinedByString:@"&"]]]];
  	} else {
  		[self setURL:[NSURL URLWithString:baseURL]];
  
  	}
  }
  
  - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
  {
  	if ([elementName isEqualToString:@"Contents"]) {
  		[self setCurrentObject:[ASIS3BucketObject objectWithBucket:[self bucket]]];
  	}
  	[super parser:parser didStartElement:elementName namespaceURI:namespaceURI qualifiedName:qName attributes:attributeDict];
  }
  
  - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
  {
  	if ([elementName isEqualToString:@"Contents"]) {
  		[objects addObject:currentObject];
  		[self setCurrentObject:nil];
  	} else if ([elementName isEqualToString:@"Key"]) {
  		[[self currentObject] setKey:[self currentXMLElementContent]];
  	} else if ([elementName isEqualToString:@"LastModified"]) {
  		[[self currentObject] setLastModified:[[ASIS3Request S3ResponseDateFormatter] dateFromString:[self currentXMLElementContent]]];
  	} else if ([elementName isEqualToString:@"ETag"]) {
  		[[self currentObject] setETag:[self currentXMLElementContent]];
  	} else if ([elementName isEqualToString:@"Size"]) {
  		[[self currentObject] setSize:(unsigned long long)[[self currentXMLElementContent] longLongValue]];
  	} else if ([elementName isEqualToString:@"ID"]) {
  		[[self currentObject] setOwnerID:[self currentXMLElementContent]];
  	} else if ([elementName isEqualToString:@"DisplayName"]) {
  		[[self currentObject] setOwnerName:[self currentXMLElementContent]];
  	} else if ([elementName isEqualToString:@"Prefix"] && [[self currentXMLElementStack] count] > 2 && [[[self currentXMLElementStack] objectAtIndex:[[self currentXMLElementStack] count]-2] isEqualToString:@"CommonPrefixes"]) {
  		[[self commonPrefixes] addObject:[self currentXMLElementContent]];
  	} else if ([elementName isEqualToString:@"IsTruncated"]) {
  		[self setIsTruncated:[[self currentXMLElementContent] isEqualToString:@"true"]];
  	} else {
  		// Let ASIS3Request look for error messages
  		[super parser:parser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName];
  	}
  }
  
  #pragma mark NSCopying
  
  - (id)copyWithZone:(NSZone *)zone
  {
  	ASIS3BucketRequest *newRequest = [super copyWithZone:zone];
  	[newRequest setBucket:[self bucket]];
  	[newRequest setSubResource:[self subResource]];
  	[newRequest setPrefix:[self prefix]];
  	[newRequest setMarker:[self marker]];
  	[newRequest setMaxResultCount:[self maxResultCount]];
  	[newRequest setDelimiter:[self delimiter]];
  	return newRequest;
  }
  
  @synthesize bucket;
  @synthesize subResource;
  @synthesize currentObject;
  @synthesize objects;
  @synthesize commonPrefixes;
  @synthesize prefix;
  @synthesize marker;
  @synthesize maxResultCount;
  @synthesize delimiter;
  @synthesize isTruncated;
  
  @end
  