FIRStorageMetadata.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright 2017 Google
  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. #import "FIRStorageMetadata.h"
  15. #import "FIRStorageConstants.h"
  16. #import "FIRStorageConstants_Private.h"
  17. #import "FIRStorageMetadata_Private.h"
  18. #import "FIRStorageUtils.h"
  19. // TODO: consider rewriting this using GTLR (GTLRStorageObjects.h)
  20. @implementation FIRStorageMetadata
  21. #pragma mark - Initializers
  22. - (instancetype)init {
  23. return [self initWithDictionary:[NSDictionary dictionary]];
  24. }
  25. - (instancetype)initWithDictionary:(NSDictionary *)dictionary {
  26. self = [super init];
  27. if (self) {
  28. _initialMetadata = [dictionary copy];
  29. _bucket = dictionary[kFIRStorageMetadataBucket];
  30. _cacheControl = dictionary[kFIRStorageMetadataCacheControl];
  31. _contentDisposition = dictionary[kFIRStorageMetadataContentDisposition];
  32. _contentEncoding = dictionary[kFIRStorageMetadataContentEncoding];
  33. _contentLanguage = dictionary[kFIRStorageMetadataContentLanguage];
  34. _contentType = dictionary[kFIRStorageMetadataContentType];
  35. _customMetadata = dictionary[kFIRStorageMetadataCustomMetadata];
  36. _size = [dictionary[kFIRStorageMetadataSize] longLongValue];
  37. _generation = [dictionary[kFIRStorageMetadataGeneration] longLongValue];
  38. _metageneration = [dictionary[kFIRStorageMetadataMetageneration] longLongValue];
  39. _timeCreated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataTimeCreated]];
  40. _updated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataUpdated]];
  41. _md5Hash = dictionary[kFIRStorageMetadataMd5Hash];
  42. // GCS "name" is our path, our "name" is just the last path component of the path
  43. _path = dictionary[kFIRStorageMetadataName];
  44. _name = [_path lastPathComponent];
  45. }
  46. return self;
  47. }
  48. #pragma mark - NSObject overrides
  49. - (instancetype)copyWithZone:(NSZone *)zone {
  50. FIRStorageMetadata *clone =
  51. [[[self class] allocWithZone:zone] initWithDictionary:[self dictionaryRepresentation]];
  52. clone.initialMetadata = [self.initialMetadata copy];
  53. return clone;
  54. }
  55. - (BOOL)isEqual:(id)object {
  56. if (self == object) {
  57. return YES;
  58. }
  59. if (![object isKindOfClass:[FIRStorageMetadata class]]) {
  60. return NO;
  61. }
  62. BOOL isEqualObject = [self isEqualToFIRStorageMetadata:(FIRStorageMetadata *)object];
  63. return isEqualObject;
  64. }
  65. - (BOOL)isEqualToFIRStorageMetadata:(FIRStorageMetadata *)metadata {
  66. return [[self dictionaryRepresentation] isEqualToDictionary:[metadata dictionaryRepresentation]];
  67. }
  68. - (NSUInteger)hash {
  69. NSUInteger hash = [[self dictionaryRepresentation] hash];
  70. return hash;
  71. }
  72. - (NSString *)description {
  73. NSDictionary *metadataDictionary = [self dictionaryRepresentation];
  74. return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, metadataDictionary];
  75. }
  76. #pragma mark - Public methods
  77. - (NSDictionary *)dictionaryRepresentation {
  78. NSMutableDictionary *metadataDictionary = [[NSMutableDictionary alloc] initWithCapacity:13];
  79. if (_bucket) {
  80. metadataDictionary[kFIRStorageMetadataBucket] = _bucket;
  81. }
  82. if (_cacheControl) {
  83. metadataDictionary[kFIRStorageMetadataCacheControl] = _cacheControl;
  84. }
  85. if (_contentDisposition) {
  86. metadataDictionary[kFIRStorageMetadataContentDisposition] = _contentDisposition;
  87. }
  88. if (_contentEncoding) {
  89. metadataDictionary[kFIRStorageMetadataContentEncoding] = _contentEncoding;
  90. }
  91. if (_contentLanguage) {
  92. metadataDictionary[kFIRStorageMetadataContentLanguage] = _contentLanguage;
  93. }
  94. if (_contentType) {
  95. metadataDictionary[kFIRStorageMetadataContentType] = _contentType;
  96. }
  97. if (_md5Hash) {
  98. metadataDictionary[kFIRStorageMetadataMd5Hash] = _md5Hash;
  99. }
  100. if (_customMetadata) {
  101. metadataDictionary[kFIRStorageMetadataCustomMetadata] = _customMetadata;
  102. }
  103. if (_generation) {
  104. NSString *generationString = [NSString stringWithFormat:@"%lld", _generation];
  105. metadataDictionary[kFIRStorageMetadataGeneration] = generationString;
  106. }
  107. if (_metageneration) {
  108. NSString *metagenerationString = [NSString stringWithFormat:@"%lld", _metageneration];
  109. metadataDictionary[kFIRStorageMetadataMetageneration] = metagenerationString;
  110. }
  111. if (_timeCreated) {
  112. metadataDictionary[kFIRStorageMetadataTimeCreated] = [self RFC3339StringFromDate:_timeCreated];
  113. }
  114. if (_updated) {
  115. metadataDictionary[kFIRStorageMetadataUpdated] = [self RFC3339StringFromDate:_updated];
  116. }
  117. if (_path) {
  118. metadataDictionary[kFIRStorageMetadataName] = _path;
  119. }
  120. if (_size) {
  121. metadataDictionary[kFIRStorageMetadataSize] = [NSNumber numberWithLongLong:_size];
  122. }
  123. return [metadataDictionary copy];
  124. }
  125. - (BOOL)isFile {
  126. return _type == FIRStorageMetadataTypeFile;
  127. }
  128. - (BOOL)isFolder {
  129. return _type == FIRStorageMetadataTypeFolder;
  130. }
  131. #pragma mark - Private methods
  132. + (void)removeMatchingMetadata:(NSMutableDictionary *)metadata
  133. oldMetadata:(NSDictionary *)oldMetadata {
  134. for (NSString *metadataKey in [oldMetadata allKeys]) {
  135. id oldValue = [oldMetadata objectForKey:metadataKey];
  136. id newValue = [metadata objectForKey:metadataKey];
  137. if (oldValue && !newValue) {
  138. [metadata setObject:[NSNull null] forKey:metadataKey];
  139. } else if ([oldValue isKindOfClass:[NSString class]] &&
  140. [newValue isKindOfClass:[NSString class]]) {
  141. if ([oldValue isEqualToString:newValue]) {
  142. [metadata removeObjectForKey:metadataKey];
  143. }
  144. } else if ([oldValue isKindOfClass:[NSDictionary class]] &&
  145. [newValue isKindOfClass:[NSDictionary class]]) {
  146. NSMutableDictionary *nestedMetadata = [newValue mutableCopy];
  147. [self removeMatchingMetadata:nestedMetadata oldMetadata:oldValue];
  148. [metadata setObject:[nestedMetadata copy] forKey:metadataKey];
  149. }
  150. }
  151. }
  152. - (NSDictionary *)updatedMetadata {
  153. NSMutableDictionary *metadataUpdate = [[self dictionaryRepresentation] mutableCopy];
  154. [FIRStorageMetadata removeMatchingMetadata:metadataUpdate oldMetadata:_initialMetadata];
  155. return [metadataUpdate copy];
  156. }
  157. #pragma mark - RFC 3339 conversions
  158. static NSDateFormatter *sRFC3339DateFormatter;
  159. static void setupDateFormatterOnce(void) {
  160. static dispatch_once_t onceToken;
  161. dispatch_once(&onceToken, ^{
  162. sRFC3339DateFormatter = [[NSDateFormatter alloc] init];
  163. NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  164. [sRFC3339DateFormatter setLocale:enUSPOSIXLocale];
  165. [sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZZZ"];
  166. [sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
  167. });
  168. }
  169. - (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString {
  170. setupDateFormatterOnce();
  171. NSDate *rfc3339Date = [sRFC3339DateFormatter dateFromString:dateString];
  172. return rfc3339Date;
  173. }
  174. - (nullable NSString *)RFC3339StringFromDate:(NSDate *)date {
  175. setupDateFormatterOnce();
  176. NSString *rfc3339String = [sRFC3339DateFormatter stringFromDate:date];
  177. return rfc3339String;
  178. }
  179. @end