Commit 922d7a64 by Brent Gulanowski

Merge pull request #120 from Shopify/task/json-serialization

Task/json serialization
parents 620cd3cb 30e09834
//
// BUYPropertyDescriptionAdditionsTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import <CoreData/CoreData.h>
#import "BUYFlatCollectionTransformer.h"
#import "BUYDateTransformer.h"
#import "BUYIdentityTransformer.h"
#import "NSEntityDescription+BUYAdditions.h"
#import "NSPropertyDescription+BUYAdditions.h"
#import "TestModel.h"
static NSString * const BirdEntity = @"Bird";
static NSString * const BranchEntity = @"Branch";
static NSString * const LeafEntity = @"Leaf";
static NSString * const NestEntity = @"Nest";
static NSString * const ResearchEntity = @"Researcher";
static NSString * const RootEntity = @"Root";
@interface NSIndexSet (BUYTestAdditions)
+ (instancetype)indexSetWithIndexes:(NSArray *)indexes;
@end
@interface BUYCoreDataModelAdditionsTests : XCTestCase
@property (nonatomic) NSManagedObjectModel *model;
@property (nonatomic) TestModelManager *modelManager;
@end
@implementation BUYCoreDataModelAdditionsTests
+ (void)initialize
{
if (self == [BUYCoreDataModelAdditionsTests class]) {
[NSValueTransformer setValueTransformer:[BUYFlatCollectionTransformer arrayTransformer] forName:@"Array"];
[NSValueTransformer setValueTransformer:[BUYFlatCollectionTransformer setTransformer] forName:@"Set"];
}
}
- (instancetype)initWithInvocation:(NSInvocation *)invocation
{
self = [super initWithInvocation:invocation];
if (self) {
self.modelManager = [[TestModelManager alloc] init];
self.model = self.modelManager.model;
}
return self;
}
- (NSEntityDescription *)entityForName:(NSString *)entityName
{
return self.model.entitiesByName[entityName];
}
- (NSAttributeDescription *)attributeWithName:(NSString *)attributeName forEntity:(NSString *)entityName
{
return [[self entityForName:entityName] attributesByName][attributeName];
}
- (NSRelationshipDescription *)relationshipWithName:(NSString *)propertyName forEntity:(NSString *)entityName
{
return [[self entityForName:entityName] relationshipsByName][propertyName];
}
- (void)testJSONTransformerName
{
XCTAssertEqualObjects(BUYDateTransformerName, [self attributeWithName:@"date" forEntity:LeafEntity].JSONValueTransformerName);
XCTAssertEqualObjects(BUYIdentityTransformerName, [self attributeWithName:@"identifier" forEntity:RootEntity].JSONValueTransformerName);
}
- (void)testJSONPropertyKey
{
XCTAssertEqualObjects(@"createDate", [self attributeWithName:@"date" forEntity:LeafEntity].JSONPropertyKey);
}
- (void)testJSONValueTransformer
{
XCTAssertEqualObjects([BUYFlatCollectionTransformer class], [[self attributeWithName:@"tags" forEntity:LeafEntity].JSONValueTransformer class]);
}
- (void)testNilAttribute
{
NSAttributeDescription *idAttribute = [self attributeWithName:@"identifier" forEntity:RootEntity];
XCTAssertNil([idAttribute buy_JSONForValue:nil]);
XCTAssertEqualObjects([idAttribute buy_valueForJSON:nil object:nil], [NSNull null]);
}
- (void)testNullAttribute
{
NSAttributeDescription *idAttribute = [self attributeWithName:@"identifier" forEntity:RootEntity];
XCTAssertEqualObjects([idAttribute buy_JSONForValue:[NSNull null]], [NSNull null]);
XCTAssertEqualObjects([idAttribute buy_valueForJSON:[NSNull null] object:nil], [NSNull null]);
}
- (void)testInteger
{
NSAttributeDescription *idAttribute = [self attributeWithName:@"identifier" forEntity:RootEntity];
NSNumber *identifier = @10001;
XCTAssertEqualObjects(identifier, [idAttribute buy_JSONForValue:identifier]);
XCTAssertEqualObjects(identifier, [idAttribute buy_valueForJSON:identifier object:nil]);
}
- (void)testString
{
NSAttributeDescription *stringAttribute = [self attributeWithName:@"name" forEntity:RootEntity];
NSString *name = @"MyRoot";
XCTAssertEqualObjects(name, [stringAttribute buy_JSONForValue:name]);
XCTAssertEqualObjects(name, [stringAttribute buy_valueForJSON:name object:nil]);
}
- (void)testDecimalNumber
{
NSAttributeDescription *decimalAttribute = [self attributeWithName:@"age" forEntity:RootEntity];
NSString *ageString = @"145";
NSDecimalNumber *age = [NSDecimalNumber decimalNumberWithString:ageString];
XCTAssertEqualObjects(ageString, [decimalAttribute buy_JSONForValue:age]);
XCTAssertEqualObjects(age, [decimalAttribute buy_valueForJSON:ageString object:nil]);
}
- (void)testDate
{
NSAttributeDescription *dateAttribute = [self attributeWithName:@"date" forEntity:LeafEntity];
NSString *dateString = @"1970-01-01T01:17:59+0000";
NSDate *date = [NSDate dateWithTimeIntervalSince1970:4679.0];
XCTAssertEqualObjects(dateString, [dateAttribute buy_JSONForValue:date]);
XCTAssertEqualObjects(date, [dateAttribute buy_valueForJSON:dateString object:nil]);
}
- (void)testURL
{
// the Root.url attribute declares "attributeValueClass = NSURL; JSONTransformerName = BUYURL"
NSAttributeDescription *urlAttribute = [self attributeWithName:@"url" forEntity:RootEntity];
NSString *urlString = @"https://www.example.com/api/model.json?id=100";
NSURL *url = [NSURL URLWithString:urlString];
XCTAssertEqualObjects(urlString, [urlAttribute buy_JSONForValue:url]);
XCTAssertEqualObjects(url, [urlAttribute buy_valueForJSON:urlString object:nil]);
}
- (void)testFlatArray
{
NSAttributeDescription *arrayDescription = [self attributeWithName:@"ornaments" forEntity:BranchEntity];
NSString *ornamentsString = @"one two three two one";
NSArray *ornaments = @[@"one", @"two", @"three", @"two", @"one"];
XCTAssertEqualObjects(ornamentsString, [arrayDescription buy_JSONForValue:ornaments]);
XCTAssertEqualObjects(ornaments, [arrayDescription buy_valueForJSON:ornamentsString object:nil]);
}
- (void)testFlatSet
{
NSAttributeDescription *setDescription = [self attributeWithName:@"tags" forEntity:LeafEntity];
NSString *tagsString = @"blue green red";
NSSet *tags = [NSSet setWithArray:@[@"red", @"green", @"blue"]];
XCTAssertEqualObjects(tags, [setDescription buy_valueForJSON:tagsString object:nil]);
NSString *jsonString = [setDescription buy_JSONForValue:tags];
NSSet *actual = [NSSet setWithArray:[jsonString componentsSeparatedByString:@" "]];
XCTAssertEqualObjects(actual, tags);
}
- (void)testNilRelationship
{
Branch *branch = [self.modelManager buy_objectWithEntityName:BranchEntity JSONDictionary:nil];
NSRelationshipDescription *nestRelationship = [self relationshipWithName:@"nest" forEntity:BranchEntity];
XCTAssertNil([nestRelationship buy_valueForJSON:nil object:branch]);
}
- (void)testNullRelationship
{
Branch *branch = [self.modelManager buy_objectWithEntityName:BranchEntity JSONDictionary:nil];
NSRelationshipDescription *nestRelationship = [self relationshipWithName:@"nest" forEntity:BranchEntity];
XCTAssertNil([nestRelationship buy_valueForJSON:[NSNull null] object:branch]);
}
- (void)testRelationship
{
Branch *branch = [self.modelManager buy_objectWithEntityName:BranchEntity JSONDictionary:nil];
NSRelationshipDescription *nestRelationship = [self relationshipWithName:@"nest" forEntity:BranchEntity];
NSDictionary *expected = @{ @"egg_count" : @2 };
id<BUYObject> object = [nestRelationship buy_valueForJSON:expected object:branch];
NSDictionary *actual = [nestRelationship buy_JSONForValue:object];
XCTAssertEqualObjects(actual, expected);
}
- (void)testRecursiveRelationship
{
Branch *branch = [self.modelManager buy_objectWithEntityName:BranchEntity JSONDictionary:nil];
NSRelationshipDescription *nestRelationship = [self relationshipWithName:@"nest" forEntity:BranchEntity];
NSDictionary *json = @{ @"bird_id" : @501 };
id object = [nestRelationship buy_valueForJSON:json object:branch];
XCTAssertEqualObjects(@501, [[object bird] identifier]);
id actual = [nestRelationship buy_JSONForValue:object];
XCTAssertEqualObjects(actual, json);
}
- (void)testToManyRelationship
{
Branch *branch = [self.modelManager buy_objectWithEntityName:BranchEntity JSONDictionary:nil];
NSRelationshipDescription *leafRelationship = [self relationshipWithName:@"leaves" forEntity:BranchEntity];
// Semi-random leaf objects
branch.leaves = [NSSet setWithArray:@[[self leafWithDate:[self dateWithComponents:[self november4_1605]] tags:[self tagsWithIndexes:@[@1, @5, @11]]],
[self leafWithDate:[self dateWithComponents:[self june21_1970]] tags:[self tagsWithIndexes:@[@9]]],
[self leafWithDate:[self dateWithComponents:[self jan1_2000]] tags:[self tagsWithIndexes:@[@12, @0, @8, @4]]]]];
id json = [leafRelationship buy_JSONForValue:branch.leaves];
id actual = [leafRelationship buy_valueForJSON:json object:branch];
XCTAssertEqualObjects(actual, branch.leaves);
}
- (void)testManyToManyRelationship
{
Researcher *researcher = [self.modelManager buy_objectWithEntityName:ResearchEntity JSONDictionary:nil];
NSRelationshipDescription *researchersRelationship = [self relationshipWithName:@"researchers" forEntity:BirdEntity];
XCTAssertNil([researchersRelationship buy_JSONForValue:[NSSet setWithObject:researcher]]);
}
- (void)testEntityIsPrivate
{
NSEntityDescription *forestEntity = [self entityForName:[Forest entityName]];
XCTAssertTrue([forestEntity buy_isPrivate]);
}
- (void)testFetchedProperty
{
NSFetchedPropertyDescription *fetchedProperty = [[NSFetchedPropertyDescription alloc] init];
XCTAssertNil([fetchedProperty buy_valueForJSON:nil object:nil]);
XCTAssertNil([fetchedProperty buy_JSONForValue:nil]);
}
- (Leaf *)leafWithDate:(NSDate *)date tags:(NSSet *)tags
{
Leaf *leaf = [self.modelManager buy_objectWithEntityName:[Leaf entityName] JSONDictionary:nil];
leaf.date = date;
leaf.tags = tags;
return leaf;
}
- (NSSet *)tagsWithIndexes:(NSArray *)indexes
{
static NSArray *tags;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
tags = @[@"one", @"two", @"three", @"hot", @"urgent", @"important", @"red", @"green", @"blue", @"animal", @"vegetable", @"mineral", @"fungus"];
});
return [NSSet setWithArray:[tags objectsAtIndexes:[NSIndexSet indexSetWithIndexes:indexes]]];
}
- (NSDate *)dateWithComponents:(NSDateComponents *)components
{
return [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian] dateFromComponents:components];
}
- (NSDateComponents *)november4_1605
{
NSDateComponents *components = [[NSDateComponents alloc] init];
components.year = 1605;
components.month = 11;
components.day = 4;
return components;
}
- (NSDateComponents *)june21_1970
{
NSDateComponents *components = [[NSDateComponents alloc] init];
components.year = 1970;
components.month = 6;
components.day = 21;
return components;
}
- (NSDateComponents *)jan1_2000
{
NSDateComponents *components = [[NSDateComponents alloc] init];
components.year = 2000;
components.month = 1;
components.day = 1;
components.second = 1;
return components;
}
@end
@implementation NSIndexSet (BUYTestAdditions)
+ (instancetype)indexSetWithIndexes:(NSArray *)indexes
{
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
for (NSNumber *index in indexes) {
[indexSet addIndex:index.unsignedIntegerValue];
}
return indexSet;
}
@end
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10171" systemVersion="15E65" minimumToolsVersion="Xcode 7.0">
<entity name="Bird" representedClassName="Bird" syncable="YES">
<attribute name="colour" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="identifier" optional="YES" attributeType="Integer 64" defaultValueString="0" syncable="YES"/>
<relationship name="nests" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Nest" inverseName="bird" inverseEntity="Nest" syncable="YES">
<userInfo>
<entry key="JSONPropertyKey" value="nest_ids"/>
<entry key="key" value="value"/>
</userInfo>
</relationship>
<relationship name="researchers" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Researcher" inverseName="birds" inverseEntity="Researcher" syncable="YES"/>
</entity>
<entity name="Branch" representedClassName="Branch" syncable="YES">
<attribute name="ornaments" optional="YES" attributeType="Transformable" syncable="YES">
<userInfo>
<entry key="attributeValueClass" value="NSArray"/>
<entry key="JSONValueTransformer" value="Array"/>
</userInfo>
</attribute>
<relationship name="leaves" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Leaf" inverseName="branch" inverseEntity="Leaf" syncable="YES"/>
<relationship name="nest" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Nest" inverseName="branch" inverseEntity="Nest" syncable="YES"/>
<relationship name="root" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Root" inverseName="branches" inverseEntity="Root" syncable="YES"/>
</entity>
<entity name="Forest" syncable="YES">
<relationship name="trees" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Root" inverseName="forest" inverseEntity="Root" syncable="YES"/>
<userInfo>
<entry key="private" value="YES"/>
</userInfo>
</entity>
<entity name="Leaf" representedClassName="Leaf" syncable="YES">
<attribute name="date" optional="YES" attributeType="Date" syncable="YES">
<userInfo>
<entry key="JSONPropertyKey" value="createDate"/>
</userInfo>
</attribute>
<attribute name="tags" optional="YES" attributeType="Transformable" syncable="YES">
<userInfo>
<entry key="attributeValueClass" value="NSSet"/>
<entry key="JSONValueTransformer" value="Set"/>
</userInfo>
</attribute>
<relationship name="branch" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Branch" inverseName="leaves" inverseEntity="Branch" syncable="YES"/>
</entity>
<entity name="Nest" representedClassName="Nest" syncable="YES">
<attribute name="eggCount" optional="YES" attributeType="Integer 16" syncable="YES"/>
<relationship name="bird" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Bird" inverseName="nests" inverseEntity="Bird" syncable="YES">
<userInfo>
<entry key="JSONPropertyKey" value="bird_id"/>
</userInfo>
</relationship>
<relationship name="branch" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Branch" inverseName="nest" inverseEntity="Branch" syncable="YES"/>
</entity>
<entity name="Researcher" representedClassName="Researcher" syncable="YES">
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<relationship name="birds" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Bird" inverseName="researchers" inverseEntity="Bird" syncable="YES"/>
</entity>
<entity name="Root" representedClassName="Root" syncable="YES">
<attribute name="age" optional="YES" attributeType="Decimal" defaultValueString="0.0" syncable="YES"/>
<attribute name="identifier" optional="YES" attributeType="Integer 64" defaultValueString="0" syncable="YES"/>
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="url" optional="YES" attributeType="Transformable" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="NSURL"/>
<entry key="JSONTransformerName" value="BUYURL"/>
</userInfo>
</attribute>
<relationship name="branches" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Branch" inverseName="root" inverseEntity="Branch" syncable="YES"/>
<relationship name="forest" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Forest" inverseName="trees" inverseEntity="Forest" syncable="YES"/>
</entity>
<elements>
<element name="Bird" positionX="146" positionY="111" width="128" height="103"/>
<element name="Branch" positionX="-288" positionY="-3" width="128" height="105"/>
<element name="Forest" positionX="-718" positionY="57" width="128" height="58"/>
<element name="Leaf" positionX="-72" positionY="-18" width="128" height="90"/>
<element name="Nest" positionX="-72" positionY="126" width="128" height="90"/>
<element name="Root" positionX="-504" positionY="-18" width="128" height="133"/>
<element name="Researcher" positionX="-288" positionY="81" width="128" height="75"/>
</elements>
</model>
\ No newline at end of file
//
// BUYTransformerTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "BUYDateTransformer.h"
#import "BUYDecimalNumberTransformer.h"
#import "BUYFlatCollectionTransformer.h"
#import "BUYIdentityTransformer.h"
#import "BUYURLTransformer.h"
@interface BUYTransformerTests : XCTestCase
@end
@implementation BUYTransformerTests
- (void)testIdentityTransformer {
id value = @"value";
NSValueTransformer *transformer = [self identityTransformer];
id expected = value;
id actual = [transformer transformedValue:value];
XCTAssertEqualObjects(actual, expected, @"transformed value was incorrect");
actual = [transformer reverseTransformedValue:value];
XCTAssertEqualObjects(actual, expected, @"reverse transformed value was incorrect");
}
- (void)testDecimalTransformer {
id value = [NSDecimalNumber decimalNumberWithMantissa:256 exponent:-2 isNegative:NO];
id string = @"2.56";
NSValueTransformer *transformer = [[BUYDecimalNumberTransformer alloc] init];
id expected = string;
id actual = [transformer transformedValue:value];
XCTAssertEqualObjects(actual, expected, @"transformed value was incorrect");
expected = value;
actual = [transformer reverseTransformedValue:string];
XCTAssertEqualObjects(actual, expected, @"reverse transformed value was incorrect");
}
- (void)testPublicationDateTransformer {
NSValueTransformer *transformer = [BUYDateTransformer dateTransformerWithFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
NSDate *value = [self dateForTransformerTestingWithMilliseconds:0];
NSString *string = @"1970-06-21T08:11:59-0400";
id expected = string;
id actual = [transformer transformedValue:value];
XCTAssertEqualObjects(actual, expected, @"Transformed date with incorrect");
expected = value;
actual = [transformer reverseTransformedValue:string];
XCTAssertEqualObjects(actual, expected, @"Reverse transformed date with incorrect");
}
- (void)testShippingDateTransformer {
NSValueTransformer *transformer = [BUYDateTransformer dateTransformerWithFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
NSDate *value = [self dateForTransformerTestingWithMilliseconds:543];
NSString *string = @"1970-06-21T08:11:59.543-0400";
id expected = string;
id actual = [transformer transformedValue:value];
XCTAssertEqualObjects(actual, expected, @"Transformed date with incorrect");
expected = value;
actual = [transformer reverseTransformedValue:string];
XCTAssertEqualObjects(actual, expected, @"Reverse transformed date with incorrect");
}
- (NSDate *)dateForTransformerTestingWithMilliseconds:(NSInteger)milliseconds {
NSDateComponents *dc = [[NSDateComponents alloc] init];
dc.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
dc.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"EST"];
dc.year = 1970;
dc.month = 6;
dc.day = 21;
dc.hour = 8;
dc.minute = 11;
dc.second = 59;
dc.nanosecond = NSEC_PER_MSEC * milliseconds;
return dc.date;
}
- (void)testFlatArrayTransformer {
NSValueTransformer *elementTransformer = [[BUYURLTransformer alloc] init];
NSValueTransformer *arrayTransformer = [BUYFlatCollectionTransformer arrayTransformerWithElementTransformer:elementTransformer separator:@"||"];
NSString *URLString1 = @"http://www.shopify.com";
NSString *URLString2 = @"https://test-store.myshopify.com/meta.json";
NSURL *testURL = [self urlForTesting];
NSString *URLString3 = [testURL absoluteString];
NSArray *array = @[
[NSURL URLWithString:URLString1],
[NSURL URLWithString:URLString2],
testURL,
];
NSString *string = [NSString stringWithFormat:@"%@||%@||%@", URLString1, URLString2, URLString3];
id expected = string;
id actual = [arrayTransformer transformedValue:array];
XCTAssertEqualObjects(actual, expected, @"String encoding of flat array of URLs was incorrect");
expected = array;
actual = [arrayTransformer reverseTransformedValue:string];
XCTAssertEqualObjects(actual, expected, @"Array of URLs decoded from string was incorrect");
}
- (NSURL *)urlForTesting {
NSURLComponents *components = [[NSURLComponents alloc] init];
components.scheme = @"ftp";
components.host = @"private.example.com";
components.path = @"/authenticated/internal/account";
components.port = @3322;
components.query = @"settings=recent";
components.user = @"user123";
components.password = @"secret!@#$";
return [components URL];
}
- (void)testFlatSetTransformer {
NSValueTransformer *setTransformer = [BUYFlatCollectionTransformer setTransformerWithElementTransformer:[self identityTransformer] separator:@", "];
// We can't verify the intermediate string version without decoding it into a set directly,
// because we can't control the order of the values
id expected = [NSSet setWithObjects:@"A", @"B", @"C", nil];
id actual = [setTransformer reverseTransformedValue:[setTransformer transformedValue:expected]];
XCTAssertEqualObjects(actual, expected, @"Set of strings was not the same after round trip transformation");
}
- (void)testFlatOrderedSetTransformer {
NSValueTransformer *orderedSetTransformer = [BUYFlatCollectionTransformer orderedSetTransformerWithElementTransformer:[self identityTransformer] separator:@", "];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithObjects:@"1", @"2", @"3", nil];
NSString *string = @"1, 2, 3";
id expected = string;
id actual = [orderedSetTransformer transformedValue:orderedSet];
XCTAssertEqualObjects(actual, expected, @"String encoding of flat ordered set was incorrect");
expected = orderedSet;
actual = [orderedSetTransformer reverseTransformedValue:string];
XCTAssertEqualObjects(actual, expected, @"Ordered set decoded from string was incorrect");
}
- (NSValueTransformer *)identityTransformer {
return [[BUYIdentityTransformer alloc] init];
}
@end
//
// TestModel.h
// Mobile Buy SDK
//
// Created by Brent Gulanowski on 2016-04-27.
// Copyright © 2016 Shopify Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "BUYObjectProtocol.h"
#import "BUYModelManagerProtocol.h"
@class NSManagedObjectModel;
@interface TestModelManager : NSObject<BUYModelManager>
@property (nonatomic) NSManagedObjectModel *model;
@end
@interface TestModel : NSObject<BUYObject>
@property (nonatomic, strong) TestModelManager *modelManager;
@end
@class Leaf, Nest, Researcher, Root;
@interface Bird : TestModel
@property (nonatomic) NSNumber *identifier;
@property (nonatomic) NSString *colour;
@property (nonatomic) NSSet<Researcher *> *researchers;
+ (instancetype)birdWithIdentifier:(NSNumber *)identifier;
@end
@interface Branch : TestModel
@property (nonatomic) NSArray<NSString *> *ornaments;
@property (nonatomic) NSSet<Leaf *> *leaves;
@property (nonatomic) Nest *nest;
@end
@interface Forest : TestModel
@property (nonatomic) NSSet<Root *> *trees;
@end
@interface Leaf : TestModel
@property (nonatomic) NSDate *date;
@property (nonatomic) NSSet<NSString *> *tags;
@end
@interface Nest : TestModel
@property (nonatomic) NSNumber *eggCount;
@property (nonatomic) Bird *bird;
@property (nonatomic) Branch *branch;
@end
@interface Researcher : TestModel
@property (nonatomic) NSString *name;
@property (nonatomic) NSSet<Bird *> *birds;
@end
@interface Root : TestModel
@property (nonatomic) NSNumber *identifier;
@property (nonatomic) NSDecimalNumber *age;
@property (nonatomic) NSString *name;
@property (nonatomic) NSURL *url;
@property (nonatomic) NSSet<Branch *> *branches;
@property (nonatomic) Forest *forest;
@end
//
// TestModel.m
// Mobile Buy SDK
//
// Created by Brent Gulanowski on 2016-04-27.
// Copyright © 2016 Shopify Inc. All rights reserved.
//
#import "TestModel.h"
#import "NSEntityDescription+BUYAdditions.h"
#import <CoreData/CoreData.h>
@implementation TestModelManager
- (instancetype)init
{
self = [super init];
if (self) {
self.model = [NSManagedObjectModel mergedModelFromBundles:@[[NSBundle bundleForClass:[self class]]]];
}
return self;
}
- (NSEntityDescription *)buy_entityWithName:(NSString *)entityName
{
return self.model.entitiesByName[entityName];
}
- (Class)managedModelClassForEntityName:(NSString *)entityName
{
return [[self buy_entityWithName:entityName] buy_managedObjectClass];
}
- (id<BUYObject>)buy_objectWithEntityName:(NSString *)entityName JSONDictionary:(NSDictionary *)JSON
{
return [(id)[[self managedModelClassForEntityName:entityName] alloc] initWithModelManager:self JSONDictionary:JSON];
}
- (NSArray<id<BUYObject>> *)buy_objectsWithEntityName:(NSString *)entityName JSONArray:(NSArray *)JSON {
NSMutableArray *array = [NSMutableArray array];
for (NSDictionary *dict in JSON) {
[array addObject:[self buy_objectWithEntityName:entityName JSONDictionary:dict]];
}
return array;
}
// We don't need these methods for testing
- (id<BUYObject>)buy_objectWithEntityName:(NSString *)entityName identifier:(NSNumber *)identifier {
return [entityName isEqualToString:[Bird entityName]] ? [Bird birdWithIdentifier:identifier] : nil;
}
- (NSArray<id<BUYObject>> *)buy_objectsWithEntityName:(NSString *)entityName identifiers:(NSArray *)identifiers { return nil; }
- (void)buy_refreshCacheForObject:(id<BUYObject>)object {}
- (BOOL)buy_purgeObject:(id<BUYObject>)object error:(NSError *__autoreleasing *)error { return YES; }
- (BOOL)buy_purgeObjectsWithEntityName:(NSString *)entityName matchingPredicate:(NSPredicate *)predicate { return YES; }
@end
#pragma mark -
@implementation TestModel
@synthesize modelManager=_modelManager;
- (instancetype)initWithModelManager:(id<BUYModelManager>)modelManager JSONDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
self.modelManager = modelManager;
self.JSONDictionary = dictionary;
}
return self;
}
- (NSDictionary *)JSONDictionary
{
return [self.entity buy_JSONForObject:self];
}
- (void)setJSONDictionary:(NSDictionary *)JSONDictionary
{
[self.entity buy_updateObject:self withJSON:JSONDictionary];
}
- (NSDictionary *)JSONEncodedProperties
{
NSMutableDictionary *properties = [[self.entity buy_JSONEncodedProperties] mutableCopy];
for (NSString *relationshipName in self.entity.relationshipsByName) {
NSRelationshipDescription *relationship = properties[relationshipName];
if (relationship.inverseRelationship.deleteRule == NSCascadeDeleteRule) {
[properties removeObjectForKey:relationshipName];
}
}
return properties;
}
+ (NSPredicate *)fetchPredicateWithJSON:(NSDictionary *)JSONDictionary
{
return nil;
}
+ (NSString *)entityName
{
return NSStringFromClass([self class]);
}
- (NSEntityDescription *)entity
{
return [self.modelManager buy_entityWithName:[[self class] entityName]];
}
+ (BOOL)tracksDirtyProperties
{
return NO;
}
+ (BOOL)isPersistentClass
{
return NO;
}
- (BOOL)isEqual:(id)object
{
return [super isEqual:object] || [object isMemberOfClass:[self class]];
}
@end
#pragma mark - Models
@implementation Bird
+ (instancetype)birdWithIdentifier:(NSNumber *)identifier
{
Bird *bird = [[self alloc] init];
bird.identifier = identifier;
return bird;
}
- (BOOL)isEqual:(Bird *)otherModel
{
return ([super isEqual:otherModel] &&
[self.identifier isEqual:otherModel.identifier] &&
[self.colour isEqualToString:otherModel.colour]);
}
- (NSUInteger)hash
{
NSUInteger hash = self.identifier.hash;
hash = (hash << 5) ^ self.colour.hash;
return hash;
}
@end
@implementation Branch
- (BOOL)isEqual:(Branch *)otherModel
{
return ([super isEqual:otherModel] &&
[self.ornaments isEqual:otherModel.ornaments] &&
[self.leaves isEqual:otherModel.leaves]);
}
- (NSUInteger)hash
{
NSUInteger hash = self.ornaments.hash;
hash = (hash << 5) ^ self.leaves.hash;
return hash;
}
@end
@implementation Forest
- (BOOL)isEqual:(Forest *)object
{
return ([super isEqual:object] &&
[self.trees isEqual:object.trees]);
}
- (NSUInteger)hash
{
return self.trees.hash;
}
@end
@implementation Leaf
- (BOOL)isEqual:(Leaf *)object
{
return ([super isEqual:object] &&
[self.date isEqual:object.date] &&
[self.tags isEqual:object.tags]);
}
- (NSUInteger)hash
{
return (self.date.hash << 5) ^ self.tags.hash;
}
@end
@implementation Nest
- (BOOL)isEqual:(Nest *)object
{
return ([super isEqual:object] &&
[self.eggCount isEqual:object.eggCount] &&
((self.bird == nil && object.bird == nil) || [self.bird isEqual:object.bird]));
}
- (NSUInteger)hash
{
return (self.branch.hash << 5) ^ (7231UL + self.eggCount.unsignedIntegerValue);
}
@end
@implementation Researcher
- (BOOL)isEqual:(Researcher *)object
{
return ([super isEqual:object] &&
[self.name isEqual:object.name]);
}
- (NSUInteger)hash
{
return self.name.hash;
}
@end
@implementation Root
- (BOOL)isEqual:(Root *)object
{
return ([super isEqual:object] &&
[self.identifier isEqual:object.identifier] &&
[self.age isEqual:object.age] &&
[self.name isEqual:object.name] &&
[self.url isEqual:object.url] &&
[self.branches isEqual:object.branches]);
}
- (NSUInteger)hash
{
return self.identifier.hash;
}
@end
......@@ -80,6 +80,46 @@
8491103A1CCE718100E53B93 /* BUYExceptionAdditionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 849110391CCE718100E53B93 /* BUYExceptionAdditionsTests.m */; };
8491103C1CCE731900E53B93 /* BUYURLAdditionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8491103B1CCE731900E53B93 /* BUYURLAdditionsTests.m */; };
8491103E1CCE988600E53B93 /* BUYFontAdditionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8491103D1CCE988600E53B93 /* BUYFontAdditionsTests.m */; };
849110401CCE9DFB00E53B93 /* BUYCoreDataModelAdditionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8491103F1CCE9DFB00E53B93 /* BUYCoreDataModelAdditionsTests.m */; };
849110441CCE9F3F00E53B93 /* BUYTransformerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 849110431CCE9F3F00E53B93 /* BUYTransformerTests.m */; };
84980F291CB75AC200CFAB58 /* BUYObjectProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F281CB75AC200CFAB58 /* BUYObjectProtocol.h */; };
84980F2A1CB75AC200CFAB58 /* BUYObjectProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F281CB75AC200CFAB58 /* BUYObjectProtocol.h */; };
84980F2C1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F2B1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h */; };
84980F2D1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F2B1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h */; };
84980F321CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F2E1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h */; };
84980F331CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F2E1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h */; };
84980F341CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F2F1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m */; };
84980F351CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F2F1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m */; };
84980F361CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F301CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h */; };
84980F371CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F301CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h */; };
84980F381CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F311CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m */; };
84980F391CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F311CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m */; };
84980F4C1CB7613700CFAB58 /* BUYIdentityTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F4A1CB7613700CFAB58 /* BUYIdentityTransformer.h */; };
84980F4D1CB7613700CFAB58 /* BUYIdentityTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F4A1CB7613700CFAB58 /* BUYIdentityTransformer.h */; };
84980F4E1CB7613700CFAB58 /* BUYIdentityTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F4B1CB7613700CFAB58 /* BUYIdentityTransformer.m */; };
84980F4F1CB7613700CFAB58 /* BUYIdentityTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F4B1CB7613700CFAB58 /* BUYIdentityTransformer.m */; };
84980F521CB7616900CFAB58 /* BUYDecimalNumberTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F501CB7616900CFAB58 /* BUYDecimalNumberTransformer.h */; };
84980F531CB7616900CFAB58 /* BUYDecimalNumberTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F501CB7616900CFAB58 /* BUYDecimalNumberTransformer.h */; };
84980F541CB7616900CFAB58 /* BUYDecimalNumberTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F511CB7616900CFAB58 /* BUYDecimalNumberTransformer.m */; };
84980F551CB7616900CFAB58 /* BUYDecimalNumberTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F511CB7616900CFAB58 /* BUYDecimalNumberTransformer.m */; };
84980F581CB7617500CFAB58 /* BUYURLTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F561CB7617500CFAB58 /* BUYURLTransformer.h */; };
84980F591CB7617500CFAB58 /* BUYURLTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F561CB7617500CFAB58 /* BUYURLTransformer.h */; };
84980F5A1CB7617500CFAB58 /* BUYURLTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F571CB7617500CFAB58 /* BUYURLTransformer.m */; };
84980F5B1CB7617500CFAB58 /* BUYURLTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F571CB7617500CFAB58 /* BUYURLTransformer.m */; };
84980F5E1CB7617E00CFAB58 /* BUYDateTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F5C1CB7617E00CFAB58 /* BUYDateTransformer.h */; };
84980F5F1CB7617E00CFAB58 /* BUYDateTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84980F5C1CB7617E00CFAB58 /* BUYDateTransformer.h */; };
84980F601CB7617E00CFAB58 /* BUYDateTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F5D1CB7617E00CFAB58 /* BUYDateTransformer.m */; };
84980F611CB7617E00CFAB58 /* BUYDateTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84980F5D1CB7617E00CFAB58 /* BUYDateTransformer.m */; };
849810921CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8498108E1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h */; };
849810931CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8498108E1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h */; };
849810941CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8498108F1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m */; };
849810951CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8498108F1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m */; };
849810961CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 849810901CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h */; };
849810971CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 849810901CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h */; };
849810981CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 849810911CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m */; };
849810991CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 849810911CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m */; };
84CA59BC1CD1378100B2A956 /* BUYTestModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 84CA59BA1CD1378100B2A956 /* BUYTestModel.xcdatamodeld */; };
84CA59C01CD1609400B2A956 /* TestModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CA59BF1CD1609400B2A956 /* TestModel.m */; };
9003969B1B601DF400226B73 /* BUYCartLineItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396991B601DF400226B73 /* BUYCartLineItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
9003969C1B601DF400226B73 /* BUYCartLineItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 9003969A1B601DF400226B73 /* BUYCartLineItem.m */; };
900396AC1B627CB900226B73 /* BUYProductView.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396AA1B627CB900226B73 /* BUYProductView.h */; };
......@@ -362,7 +402,6 @@
BEB74A7E1B5564890005A300 /* BUYVariantSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9496B11B4D96D800B38949 /* BUYVariantSelectionViewController.m */; };
BEB74A901B55A3D00005A300 /* BUYCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB74A8E1B55A3D00005A300 /* BUYCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
BEB9AE781BA8627B00575F8A /* test_shop_data.json in Resources */ = {isa = PBXBuildFile; fileRef = BEB9AE721BA73E6C00575F8A /* test_shop_data.json */; };
BEB9AE7B1BA866D000575F8A /* BUYClientTestBase.h in Sources */ = {isa = PBXBuildFile; fileRef = BEB9AE7A1BA866D000575F8A /* BUYClientTestBase.h */; };
BEB9AE7D1BA885E300575F8A /* BUYClientTestBase.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB9AE7C1BA8685600575F8A /* BUYClientTestBase.m */; };
/* End PBXBuildFile section */
......@@ -428,6 +467,29 @@
849110391CCE718100E53B93 /* BUYExceptionAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYExceptionAdditionsTests.m; sourceTree = "<group>"; };
8491103B1CCE731900E53B93 /* BUYURLAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYURLAdditionsTests.m; sourceTree = "<group>"; };
8491103D1CCE988600E53B93 /* BUYFontAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYFontAdditionsTests.m; sourceTree = "<group>"; };
8491103F1CCE9DFB00E53B93 /* BUYCoreDataModelAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCoreDataModelAdditionsTests.m; sourceTree = "<group>"; };
849110431CCE9F3F00E53B93 /* BUYTransformerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYTransformerTests.m; sourceTree = "<group>"; };
84980F281CB75AC200CFAB58 /* BUYObjectProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYObjectProtocol.h; sourceTree = "<group>"; };
84980F2B1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYModelManagerProtocol.h; sourceTree = "<group>"; };
84980F2E1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSEntityDescription+BUYAdditions.h"; sourceTree = "<group>"; };
84980F2F1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSEntityDescription+BUYAdditions.m"; sourceTree = "<group>"; };
84980F301CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPropertyDescription+BUYAdditions.h"; sourceTree = "<group>"; };
84980F311CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSPropertyDescription+BUYAdditions.m"; sourceTree = "<group>"; };
84980F4A1CB7613700CFAB58 /* BUYIdentityTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYIdentityTransformer.h; sourceTree = "<group>"; };
84980F4B1CB7613700CFAB58 /* BUYIdentityTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYIdentityTransformer.m; sourceTree = "<group>"; };
84980F501CB7616900CFAB58 /* BUYDecimalNumberTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYDecimalNumberTransformer.h; sourceTree = "<group>"; };
84980F511CB7616900CFAB58 /* BUYDecimalNumberTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYDecimalNumberTransformer.m; sourceTree = "<group>"; };
84980F561CB7617500CFAB58 /* BUYURLTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYURLTransformer.h; sourceTree = "<group>"; };
84980F571CB7617500CFAB58 /* BUYURLTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYURLTransformer.m; sourceTree = "<group>"; };
84980F5C1CB7617E00CFAB58 /* BUYDateTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYDateTransformer.h; sourceTree = "<group>"; };
84980F5D1CB7617E00CFAB58 /* BUYDateTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYDateTransformer.m; sourceTree = "<group>"; };
8498108E1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYDeliveryRangeTransformer.h; sourceTree = "<group>"; };
8498108F1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYDeliveryRangeTransformer.m; sourceTree = "<group>"; };
849810901CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYFlatCollectionTransformer.h; sourceTree = "<group>"; };
849810911CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYFlatCollectionTransformer.m; sourceTree = "<group>"; };
84CA59BB1CD1378100B2A956 /* BUYTestModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = BUYTestModel.xcdatamodel; sourceTree = "<group>"; };
84CA59BE1CD1609400B2A956 /* TestModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestModel.h; sourceTree = "<group>"; };
84CA59BF1CD1609400B2A956 /* TestModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestModel.m; sourceTree = "<group>"; };
900396991B601DF400226B73 /* BUYCartLineItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYCartLineItem.h; sourceTree = "<group>"; };
9003969A1B601DF400226B73 /* BUYCartLineItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCartLineItem.m; sourceTree = "<group>"; };
900396AA1B627CB900226B73 /* BUYProductView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductView.h; path = "Product View/BUYProductView.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
......@@ -644,8 +706,12 @@
841ADDF21CB6C942000004B0 /* NSDecimalNumber+BUYAdditions.m */,
841ADDF31CB6C942000004B0 /* NSDictionary+BUYAdditions.h */,
841ADDF41CB6C942000004B0 /* NSDictionary+BUYAdditions.m */,
84980F2E1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h */,
84980F2F1CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m */,
841ADDF51CB6C942000004B0 /* NSException+BUYAdditions.h */,
841ADDF61CB6C942000004B0 /* NSException+BUYModelAdditions.m */,
84980F301CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h */,
84980F311CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m */,
841ADDF71CB6C942000004B0 /* NSRegularExpression+BUYAdditions.h */,
841ADDF81CB6C942000004B0 /* NSRegularExpression+BUYAdditions.m */,
841ADDF91CB6C942000004B0 /* NSString+BUYAdditions.h */,
......@@ -711,6 +777,34 @@
path = Persistent;
sourceTree = "<group>";
};
84980F271CB75A7A00CFAB58 /* Protocols */ = {
isa = PBXGroup;
children = (
84980F281CB75AC200CFAB58 /* BUYObjectProtocol.h */,
84980F2B1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h */,
);
name = Protocols;
sourceTree = "<group>";
};
84980F491CB760FA00CFAB58 /* Value Transformers */ = {
isa = PBXGroup;
children = (
84980F5C1CB7617E00CFAB58 /* BUYDateTransformer.h */,
84980F5D1CB7617E00CFAB58 /* BUYDateTransformer.m */,
84980F501CB7616900CFAB58 /* BUYDecimalNumberTransformer.h */,
84980F511CB7616900CFAB58 /* BUYDecimalNumberTransformer.m */,
8498108E1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h */,
8498108F1CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m */,
849810901CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h */,
849810911CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m */,
84980F4A1CB7613700CFAB58 /* BUYIdentityTransformer.h */,
84980F4B1CB7613700CFAB58 /* BUYIdentityTransformer.m */,
84980F561CB7617500CFAB58 /* BUYURLTransformer.h */,
84980F571CB7617500CFAB58 /* BUYURLTransformer.m */,
);
path = "Value Transformers";
sourceTree = "<group>";
};
906CF1AE1B8B660F001F7D5B /* PKContact Test Objects */ = {
isa = PBXGroup;
children = (
......@@ -735,6 +829,7 @@
90F592ED1B0D5EFE0026B382 /* Mobile Buy SDK Tests */ = {
isa = PBXGroup;
children = (
84CA59BA1CD1378100B2A956 /* BUYTestModel.xcdatamodeld */,
90F592F91B0D5F4C0026B382 /* BUYApplePayAdditionsTest.m */,
8491102E1CCE708900E53B93 /* BUYArrayAdditionsTests.m */,
90F592FA1B0D5F4C0026B382 /* BUYCartTest.m */,
......@@ -749,9 +844,11 @@
90F592F81B0D5F4C0026B382 /* BUYIntegrationTest.m */,
90F592FE1B0D5F4C0026B382 /* BUYLineItemTest.m */,
90F592FF1B0D5F4C0026B382 /* BUYObjectTests.m */,
8491103F1CCE9DFB00E53B93 /* BUYCoreDataModelAdditionsTests.m */,
8491102F1CCE708900E53B93 /* BUYRegularExpressionAdditionsTests.m */,
849110301CCE708900E53B93 /* BUYStringAdditionsTests.m */,
90F593001B0D5F4C0026B382 /* BUYTestConstants.h */,
849110431CCE9F3F00E53B93 /* BUYTransformerTests.m */,
8491103B1CCE731900E53B93 /* BUYURLAdditionsTests.m */,
BE6C07051BB1E46900BD9F7B /* mocked_responses.json */,
BE98DB5A1BB1F4D000C29564 /* OHHTTPStubsResponse+Helpers.h */,
......@@ -759,6 +856,8 @@
906CF1AE1B8B660F001F7D5B /* PKContact Test Objects */,
90F592EE1B0D5EFE0026B382 /* Supporting Files */,
BEB9AE721BA73E6C00575F8A /* test_shop_data.json */,
84CA59BE1CD1609400B2A956 /* TestModel.h */,
84CA59BF1CD1609400B2A956 /* TestModel.m */,
);
path = "Mobile Buy SDK Tests";
sourceTree = "<group>";
......@@ -900,6 +999,7 @@
F773744419C779C20039681C /* Models */ = {
isa = PBXGroup;
children = (
84980F271CB75A7A00CFAB58 /* Protocols */,
841ADE2B1CB6F320000004B0 /* Persistent */,
841ADE2A1CB6F31C000004B0 /* Transient */,
9A3B2DD31CD2829900BFF49C /* BUYAccountCredentials.h */,
......@@ -968,6 +1068,7 @@
F773744419C779C20039681C /* Models */,
90FC31AB1B50589800AFAB51 /* Product View */,
F773744519C779C20039681C /* Utils */,
84980F491CB760FA00CFAB58 /* Value Transformers */,
BE1C4DF21AE98F8E00E21624 /* View Controllers */,
);
name = Classes;
......@@ -994,6 +1095,7 @@
files = (
901931331BC5B9BC00D1134E /* BUYAddress+Additions.h in Headers */,
9019313F1BC5B9BC00D1134E /* BUYProduct+Options.h in Headers */,
84980F2A1CB75AC200CFAB58 /* BUYObjectProtocol.h in Headers */,
901931561BC5B9BC00D1134E /* BUYProductVariant+Options.h in Headers */,
901931271BC5B9BC00D1134E /* BUYAddress.h in Headers */,
901931281BC5B9BC00D1134E /* BUYApplePayHelpers.h in Headers */,
......@@ -1001,6 +1103,7 @@
9A3B2DDB1CD282DA00BFF49C /* BUYClient_Internal.h in Headers */,
9019312A1BC5B9BC00D1134E /* BUYCreditCard.h in Headers */,
9019312B1BC5B9BC00D1134E /* BUYOption.h in Headers */,
84980F4D1CB7613700CFAB58 /* BUYIdentityTransformer.h in Headers */,
9019312C1BC5B9BC00D1134E /* BUYProductVariantCell.h in Headers */,
9019312D1BC5B9BC00D1134E /* BUYTheme.h in Headers */,
9019312E1BC5B9BC00D1134E /* BUYProductDescriptionCell.h in Headers */,
......@@ -1010,6 +1113,7 @@
901931341BC5B9BC00D1134E /* BUYViewController.h in Headers */,
901931351BC5B9BC00D1134E /* BUYDiscount.h in Headers */,
901931361BC5B9BC00D1134E /* BUYProductView.h in Headers */,
849810931CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h in Headers */,
901931371BC5B9BC00D1134E /* BUYTaxLine.h in Headers */,
901931381BC5B9BC00D1134E /* BUYVariantSelectionViewController.h in Headers */,
901931391BC5B9BC00D1134E /* BUYOptionValueCell.h in Headers */,
......@@ -1021,6 +1125,7 @@
9A3B2DE11CD28E9900BFF49C /* BUYShopifyErrorCodes.h in Headers */,
9019313E1BC5B9BC00D1134E /* BUYApplePayAdditions.h in Headers */,
901931401BC5B9BC00D1134E /* BUYTheme+Additions.h in Headers */,
84980F531CB7616900CFAB58 /* BUYDecimalNumberTransformer.h in Headers */,
901931411BC5B9BC00D1134E /* BUYVariantOptionView.h in Headers */,
901931421BC5B9BC00D1134E /* BUYMaskedCreditCard.h in Headers */,
901931431BC5B9BC00D1134E /* BUYProductViewHeader.h in Headers */,
......@@ -1032,6 +1137,7 @@
841ADE241CB6C942000004B0 /* NSURLComponents+BUYAdditions.h in Headers */,
841ADE141CB6C942000004B0 /* NSException+BUYAdditions.h in Headers */,
841ADE041CB6C942000004B0 /* NSDate+BUYAdditions.h in Headers */,
84980F2D1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h in Headers */,
901931451BC5B9BC00D1134E /* UIFont+BUYAdditions.h in Headers */,
841ADE081CB6C942000004B0 /* NSDateFormatter+BUYAdditions.h in Headers */,
841ADE001CB6C942000004B0 /* NSArray+BUYAdditions.h in Headers */,
......@@ -1039,6 +1145,7 @@
841ADE1C1CB6C942000004B0 /* NSString+BUYAdditions.h in Headers */,
841ADE181CB6C942000004B0 /* NSRegularExpression+BUYAdditions.h in Headers */,
841ADE0C1CB6C942000004B0 /* NSDecimalNumber+BUYAdditions.h in Headers */,
84980F331CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */,
901931491BC5B9BC00D1134E /* BUYGiftCard.h in Headers */,
9A3B2DD61CD2829900BFF49C /* BUYAccountCredentials.h in Headers */,
9019314B1BC5B9BC00D1134E /* BUYNavigationController.h in Headers */,
......@@ -1053,14 +1160,18 @@
901931581BC5B9BC00D1134E /* BUYRuntime.h in Headers */,
901931591BC5B9BC00D1134E /* BUYCollection.h in Headers */,
9019315A1BC5B9BC00D1134E /* BUYProductImageCollectionViewCell.h in Headers */,
84980F5F1CB7617E00CFAB58 /* BUYDateTransformer.h in Headers */,
84980F591CB7617500CFAB58 /* BUYURLTransformer.h in Headers */,
9019315B1BC5B9BC00D1134E /* BUYImageKit.h in Headers */,
9019315C1BC5B9BC00D1134E /* BUYCollection+Additions.h in Headers */,
9032F2DB1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */,
9019315E1BC5B9BC00D1134E /* BUYError.h in Headers */,
84980F371CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h in Headers */,
9019315F1BC5B9BC00D1134E /* BUYProductHeaderCell.h in Headers */,
901931601BC5B9BC00D1134E /* BUYProductViewErrorView.h in Headers */,
901931611BC5B9BC00D1134E /* BUYClient.h in Headers */,
901931631BC5B9BC00D1134E /* BUYGradientView.h in Headers */,
849810971CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h in Headers */,
901931641BC5B9BC00D1134E /* BUYCartLineItem.h in Headers */,
9A3B2DCA1CD27D5B00BFF49C /* BUYCustomer.h in Headers */,
901931661BC5B9BC00D1134E /* BUYCheckout.h in Headers */,
......@@ -1079,6 +1190,7 @@
files = (
BE9A64791B503D420033E558 /* BUYAddress+Additions.h in Headers */,
BE9A646A1B503D100033E558 /* BUYProduct+Options.h in Headers */,
84980F291CB75AC200CFAB58 /* BUYObjectProtocol.h in Headers */,
BE1007951B6038150031CEE7 /* BUYProductVariant+Options.h in Headers */,
BE9A64531B503CBE0033E558 /* BUYAddress.h in Headers */,
BE9A64741B503D2E0033E558 /* BUYApplePayHelpers.h in Headers */,
......@@ -1086,6 +1198,7 @@
9A3B2DDA1CD282DA00BFF49C /* BUYClient_Internal.h in Headers */,
BE9A64551B503CC50033E558 /* BUYCreditCard.h in Headers */,
BE9A645F1B503CE90033E558 /* BUYOption.h in Headers */,
84980F4C1CB7613700CFAB58 /* BUYIdentityTransformer.h in Headers */,
BEB74A6F1B5564260005A300 /* BUYProductVariantCell.h in Headers */,
BEB74A2B1B554C150005A300 /* BUYTheme.h in Headers */,
BEB74A6B1B55641B0005A300 /* BUYProductDescriptionCell.h in Headers */,
......@@ -1095,6 +1208,7 @@
BE9A644F1B503CA90033E558 /* BUYDiscount.h in Headers */,
900396AC1B627CB900226B73 /* BUYProductView.h in Headers */,
BE9A64511B503CB00033E558 /* BUYTaxLine.h in Headers */,
849810921CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h in Headers */,
BEB74A7D1B5564870005A300 /* BUYVariantSelectionViewController.h in Headers */,
BE10079B1B6165EC0031CEE7 /* BUYOptionValueCell.h in Headers */,
BE9A64591B503CD40033E558 /* BUYImage.h in Headers */,
......@@ -1106,6 +1220,7 @@
BE9A646A1B503D100033E558 /* BUYProduct+Options.h in Headers */,
906EAE431B836DE000976165 /* BUYTheme+Additions.h in Headers */,
BEB74A7B1B5564810005A300 /* BUYVariantOptionView.h in Headers */,
84980F521CB7616900CFAB58 /* BUYDecimalNumberTransformer.h in Headers */,
BE5DC3631B71022D00B2BC1E /* BUYMaskedCreditCard.h in Headers */,
BEB74A731B5564350005A300 /* BUYProductViewHeader.h in Headers */,
BEB74A751B55643B0005A300 /* BUYProductViewHeaderBackgroundImageView.h in Headers */,
......@@ -1117,6 +1232,7 @@
841ADE0F1CB6C942000004B0 /* NSDictionary+BUYAdditions.h in Headers */,
841ADE1F1CB6C942000004B0 /* NSURL+BUYAdditions.h in Headers */,
841ADE231CB6C942000004B0 /* NSURLComponents+BUYAdditions.h in Headers */,
84980F2C1CB75B5E00CFAB58 /* BUYModelManagerProtocol.h in Headers */,
841ADE131CB6C942000004B0 /* NSException+BUYAdditions.h in Headers */,
841ADE031CB6C942000004B0 /* NSDate+BUYAdditions.h in Headers */,
841ADE071CB6C942000004B0 /* NSDateFormatter+BUYAdditions.h in Headers */,
......@@ -1124,6 +1240,7 @@
841ADE1B1CB6C942000004B0 /* NSString+BUYAdditions.h in Headers */,
841ADE171CB6C942000004B0 /* NSRegularExpression+BUYAdditions.h in Headers */,
841ADE0B1CB6C942000004B0 /* NSDecimalNumber+BUYAdditions.h in Headers */,
84980F321CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */,
BE9A64571B503CCC0033E558 /* BUYGiftCard.h in Headers */,
9A3B2DD51CD2829900BFF49C /* BUYAccountCredentials.h in Headers */,
BEB74A671B55640C0005A300 /* BUYNavigationController.h in Headers */,
......@@ -1139,14 +1256,18 @@
9A9C03431CD9369400AE79BD /* BUYCheckout_Private.h in Headers */,
BEB74A901B55A3D00005A300 /* BUYCollection.h in Headers */,
904606AF1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h in Headers */,
84980F5E1CB7617E00CFAB58 /* BUYDateTransformer.h in Headers */,
84980F581CB7617500CFAB58 /* BUYURLTransformer.h in Headers */,
900E7C841B5DA553006F3C81 /* BUYImageKit.h in Headers */,
900396F61B69563400226B73 /* BUYCollection+Additions.h in Headers */,
9032F2DA1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */,
BE47340F1B66C4EF00AA721A /* BUYError.h in Headers */,
84980F361CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h in Headers */,
BEB74A6D1B5564200005A300 /* BUYProductHeaderCell.h in Headers */,
903BCC7C1B7D1C2D00C21FEB /* BUYProductViewErrorView.h in Headers */,
BE9A64471B503C8B0033E558 /* BUYClient.h in Headers */,
BEB74A651B5563FF0005A300 /* BUYGradientView.h in Headers */,
849810961CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h in Headers */,
9003969B1B601DF400226B73 /* BUYCartLineItem.h in Headers */,
9A3B2DC91CD27D5B00BFF49C /* BUYCustomer.h in Headers */,
BE9A644B1B503C9B0033E558 /* BUYCheckout.h in Headers */,
......@@ -1327,7 +1448,9 @@
901930E41BC5B9BC00D1134E /* BUYOptionSelectionViewController.m in Sources */,
901930E51BC5B9BC00D1134E /* BUYVariantOptionView.m in Sources */,
841ADE1E1CB6C942000004B0 /* NSString+BUYAdditions.m in Sources */,
84980F5B1CB7617500CFAB58 /* BUYURLTransformer.m in Sources */,
901930E61BC5B9BC00D1134E /* BUYPresentationControllerForVariantSelection.m in Sources */,
84980F611CB7617E00CFAB58 /* BUYDateTransformer.m in Sources */,
901930E81BC5B9BC00D1134E /* BUYImage.m in Sources */,
901930E91BC5B9BC00D1134E /* BUYProductVariant.m in Sources */,
901930EA1BC5B9BC00D1134E /* BUYProductViewController.m in Sources */,
......@@ -1342,19 +1465,23 @@
901930F41BC5B9BC00D1134E /* BUYProductViewHeaderBackgroundImageView.m in Sources */,
901930F51BC5B9BC00D1134E /* BUYProductViewHeaderOverlay.m in Sources */,
901930F61BC5B9BC00D1134E /* BUYProductVariantCell.m in Sources */,
849810991CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m in Sources */,
901930F71BC5B9BC00D1134E /* BUYTheme.m in Sources */,
901930F81BC5B9BC00D1134E /* BUYProductVariant+Options.m in Sources */,
901930F91BC5B9BC00D1134E /* BUYProductViewErrorView.m in Sources */,
901930FA1BC5B9BC00D1134E /* BUYLineItem.m in Sources */,
901930FB1BC5B9BC00D1134E /* BUYCheckoutButton.m in Sources */,
849810951CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m in Sources */,
901930FC1BC5B9BC00D1134E /* BUYCollection.m in Sources */,
901930FD1BC5B9BC00D1134E /* BUYTaxLine.m in Sources */,
901930FE1BC5B9BC00D1134E /* BUYCollection+Additions.m in Sources */,
84980F351CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m in Sources */,
901930FF1BC5B9BC00D1134E /* BUYVariantOptionBreadCrumbsView.m in Sources */,
9A3B2DCC1CD27D5B00BFF49C /* BUYCustomer.m in Sources */,
901931011BC5B9BC00D1134E /* BUYTheme+Additions.m in Sources */,
901931021BC5B9BC00D1134E /* BUYStoreViewController.m in Sources */,
901931031BC5B9BC00D1134E /* BUYOptionValue.m in Sources */,
84980F551CB7616900CFAB58 /* BUYDecimalNumberTransformer.m in Sources */,
9A3B2DDE1CD28D7300BFF49C /* BUYSerializable.m in Sources */,
901931041BC5B9BC00D1134E /* BUYApplePayAdditions.m in Sources */,
901931051BC5B9BC00D1134E /* BUYOptionSelectionNavigationController.m in Sources */,
......@@ -1379,6 +1506,7 @@
901931141BC5B9BC00D1134E /* BUYProductViewFooter.m in Sources */,
841ADE261CB6C942000004B0 /* NSURLComponents+BUYAdditions.m in Sources */,
901931151BC5B9BC00D1134E /* BUYPresentationControllerWithNavigationController.m in Sources */,
84980F391CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m in Sources */,
841ADE221CB6C942000004B0 /* NSURL+BUYAdditions.m in Sources */,
901931161BC5B9BC00D1134E /* BUYShippingRate.m in Sources */,
841ADE061CB6C942000004B0 /* NSDate+BUYAdditions.m in Sources */,
......@@ -1394,6 +1522,7 @@
9019311F1BC5B9BC00D1134E /* BUYProductView.m in Sources */,
901931201BC5B9BC00D1134E /* BUYCreditCard.m in Sources */,
901931211BC5B9BC00D1134E /* BUYProductImageCollectionViewCell.m in Sources */,
84980F4F1CB7613700CFAB58 /* BUYIdentityTransformer.m in Sources */,
901931221BC5B9BC00D1134E /* BUYShop.m in Sources */,
901931231BC5B9BC00D1134E /* BUYObject.mm in Sources */,
901931241BC5B9BC00D1134E /* BUYProductDescriptionCell.m in Sources */,
......@@ -1406,8 +1535,8 @@
files = (
BEB9AE7D1BA885E300575F8A /* BUYClientTestBase.m in Sources */,
8491103E1CCE988600E53B93 /* BUYFontAdditionsTests.m in Sources */,
BEB9AE7B1BA866D000575F8A /* BUYClientTestBase.h in Sources */,
8491103A1CCE718100E53B93 /* BUYExceptionAdditionsTests.m in Sources */,
849110441CCE9F3F00E53B93 /* BUYTransformerTests.m in Sources */,
849110351CCE70CE00E53B93 /* BUYDictionaryAdditionsTests.m in Sources */,
90F5930A1B0D5F4C0026B382 /* BUYLineItemTest.m in Sources */,
849110321CCE708900E53B93 /* BUYRegularExpressionAdditionsTests.m in Sources */,
......@@ -1421,7 +1550,10 @@
90BBCD731B87B6BA00FCCE51 /* BUYPKContact.m in Sources */,
849110331CCE708900E53B93 /* BUYStringAdditionsTests.m in Sources */,
906CF1B11B8B66AE001F7D5B /* BUYCNPostalAddress.m in Sources */,
84CA59BC1CD1378100B2A956 /* BUYTestModel.xcdatamodeld in Sources */,
8491103C1CCE731900E53B93 /* BUYURLAdditionsTests.m in Sources */,
849110401CCE9DFB00E53B93 /* BUYCoreDataModelAdditionsTests.m in Sources */,
84CA59C01CD1609400B2A956 /* TestModel.m in Sources */,
906CF1AD1B8B5F7D001F7D5B /* BUYNSPersonNameComponents.m in Sources */,
BE98DB5C1BB1F4D000C29564 /* OHHTTPStubsResponse+Helpers.m in Sources */,
849110311CCE708900E53B93 /* BUYArrayAdditionsTests.m in Sources */,
......@@ -1436,7 +1568,9 @@
BEB74A7A1B55647C0005A300 /* BUYOptionSelectionViewController.m in Sources */,
BEB74A7C1B5564840005A300 /* BUYVariantOptionView.m in Sources */,
841ADE1D1CB6C942000004B0 /* NSString+BUYAdditions.m in Sources */,
84980F5A1CB7617500CFAB58 /* BUYURLTransformer.m in Sources */,
BEB74A241B554BF20005A300 /* BUYPresentationControllerForVariantSelection.m in Sources */,
84980F601CB7617E00CFAB58 /* BUYDateTransformer.m in Sources */,
BE9A645A1B503CD90033E558 /* BUYImage.m in Sources */,
BE9A64641B503CFB0033E558 /* BUYProductVariant.m in Sources */,
BEB74A2E1B554E8B0005A300 /* BUYProductViewController.m in Sources */,
......@@ -1451,19 +1585,23 @@
BEB74A761B55643E0005A300 /* BUYProductViewHeaderBackgroundImageView.m in Sources */,
9078749A1B7276BA0023775B /* BUYProductViewHeaderOverlay.m in Sources */,
BEB74A701B5564290005A300 /* BUYProductVariantCell.m in Sources */,
849810981CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m in Sources */,
BEB74A2C1B554C370005A300 /* BUYTheme.m in Sources */,
BE1007961B6038150031CEE7 /* BUYProductVariant+Options.m in Sources */,
903BCC7D1B7D1C2D00C21FEB /* BUYProductViewErrorView.m in Sources */,
BE9A645C1B503CE00033E558 /* BUYLineItem.m in Sources */,
900396B11B67BD0A00226B73 /* BUYCheckoutButton.m in Sources */,
849810941CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m in Sources */,
9089CC5E1BB48D06009726D6 /* BUYCollection.m in Sources */,
BE9A64521B503CB80033E558 /* BUYTaxLine.m in Sources */,
900396F71B69563400226B73 /* BUYCollection+Additions.m in Sources */,
84980F341CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m in Sources */,
90DE92711B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.m in Sources */,
9A3B2DCB1CD27D5B00BFF49C /* BUYCustomer.m in Sources */,
906EAE441B836DE000976165 /* BUYTheme+Additions.m in Sources */,
BE9A647F1B503D960033E558 /* BUYStoreViewController.m in Sources */,
BE9A64691B503D0C0033E558 /* BUYOptionValue.m in Sources */,
84980F541CB7616900CFAB58 /* BUYDecimalNumberTransformer.m in Sources */,
9A3B2DDD1CD28D7300BFF49C /* BUYSerializable.m in Sources */,
BE9A646D1B503D1C0033E558 /* BUYApplePayAdditions.m in Sources */,
BEB74A2A1B554BFB0005A300 /* BUYOptionSelectionNavigationController.m in Sources */,
......@@ -1488,6 +1626,7 @@
BEB74A721B5564320005A300 /* BUYProductViewFooter.m in Sources */,
841ADE251CB6C942000004B0 /* NSURLComponents+BUYAdditions.m in Sources */,
BEB74A6A1B5564190005A300 /* BUYPresentationControllerWithNavigationController.m in Sources */,
84980F381CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m in Sources */,
841ADE211CB6C942000004B0 /* NSURL+BUYAdditions.m in Sources */,
BE9A644E1B503CA60033E558 /* BUYShippingRate.m in Sources */,
841ADE051CB6C942000004B0 /* NSDate+BUYAdditions.m in Sources */,
......@@ -1503,6 +1642,7 @@
900396AD1B627CB900226B73 /* BUYProductView.m in Sources */,
BE9A64561B503CC90033E558 /* BUYCreditCard.m in Sources */,
904606B01B6BC8D700754173 /* BUYProductImageCollectionViewCell.m in Sources */,
84980F4E1CB7613700CFAB58 /* BUYIdentityTransformer.m in Sources */,
BE9A64671B503D060033E558 /* BUYShop.m in Sources */,
BE9A645E1B503CE60033E558 /* BUYObject.mm in Sources */,
BEB74A6C1B55641D0005A300 /* BUYProductDescriptionCell.m in Sources */,
......@@ -1877,6 +2017,19 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
84CA59BA1CD1378100B2A956 /* BUYTestModel.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
84CA59BB1CD1378100B2A956 /* BUYTestModel.xcdatamodel */,
);
currentVersion = 84CA59BB1CD1378100B2A956 /* BUYTestModel.xcdatamodel */;
path = BUYTestModel.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = F773741519C770CB0039681C /* Project object */;
}
......@@ -31,14 +31,14 @@
+ (NSDateFormatter*)dateFormatterForShippingRates
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ";
return dateFormatter;
}
+ (NSDateFormatter*)dateFormatterForPublications
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
return dateFormatter;
}
......
//
// NSEntityDescription+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <CoreData/CoreData.h>
@protocol BUYObject;
@interface NSEntityDescription (BUYAdditions)
/**
* A dictionary of @{ NSString : NSPropertyDescription } where the keys are property names.
* By default, returns all attributes (instances of NSAttributeDescription) and relationships (NSRelationshipDescription).
*/
@property (nonatomic, readonly, getter=buy_JSONEncodedProperties) NSDictionary *JSONEncodedProperties;
/**
* Returns the custom subclass used for instances of this entity.
*/
@property (nonatomic, readonly, getter=buy_managedObjectClass) Class managedObjectClass;
/**
* Signifies whether this entity is private to the app (not used by the endpoint).
*/
- (BOOL)buy_isPrivate;
/**
* Generate JSON, recursively, from the provided model object.
*/
- (NSDictionary *)buy_JSONForObject:(id<BUYObject>)object;
/**
* Generate JSON, recursively, for each model in the provided array.
*/
- (NSArray *)buy_JSONForArray:(NSArray<NSObject<BUYObject> *> *)array;
/**
* Update the properties of the given model object, and child objects, using the given JSON dictionary.
*/
- (void)buy_updateObject:(id<BUYObject>)object withJSON:(NSDictionary *)JSON;
@end
//
// NSEntityDescription+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "NSEntityDescription+BUYAdditions.h"
#import "BUYModelManagerProtocol.h"
#import "BUYObjectProtocol.h"
#import "NSDictionary+BUYAdditions.h"
#import "NSPropertyDescription+BUYAdditions.h"
#import "NSString+BUYAdditions.h"
@interface NSEntityDescription ()
/**
* Returns a block that maps JSON keys into a property name.
* Used when updating model objects from JSON.
*/
@property (nonatomic, readonly, getter=buy_JSONKeyEncodingMap) BUYStringMap JSONKeyEncodingMap;
/**
* Returns a block that maps property names into JSON keys.
* Used when generating JSON data from model objects.
*/
@property (nonatomic, readonly, getter=buy_JSONKeyDecodingMap) BUYStringMap JSONKeyDecodingMap;
@end
@implementation NSEntityDescription (BUYAdditions)
#pragma mark - Derived Properties
- (Class)buy_managedObjectClass
{
return NSClassFromString(self.managedObjectClassName);
}
- (BOOL)buy_isPrivate
{
return [self.userInfo[@"private"] boolValue];
}
#pragma mark - Property Lookup Conveniences
- (NSDictionary *)buy_JSONEncodedProperties
{
NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithDictionary:[self attributesByName]];
[properties addEntriesFromDictionary:[self relationshipsByName]];
return properties;
}
- (NSPropertyDescription *)buy_propertyWithName:(NSString *)name
{
return self.propertiesByName[name];
}
#pragma mark - JSON <-> Property key mapping
// TODO: profile and optimize if necessary
- (BUYStringMap)buy_JSONKeyEncodingMap
{
NSDictionary *mapping = [self buy_PropertyNameMapping];
return ^(NSString *name) {
return mapping[name] ?: [name buy_snakeCaseString];
};
}
- (BUYStringMap)buy_JSONKeyDecodingMap
{
NSDictionary *mapping = [self buy_JSONKeyMapping];
return ^(NSString *key) {
return mapping[key] ?: [key buy_camelCaseString];
};
}
#pragma mark - Property lookup
+ (NSDictionary *)buy_defaultPropertyNameMapping
{
return @{ @"identifier" : @"id" };
}
// json key -> property name
- (NSDictionary *)buy_JSONKeyMapping
{
return [[self buy_PropertyNameMapping] buy_reverseDictionary];
}
// property name -> json key
- (NSDictionary *)buy_PropertyNameMapping
{
return [self.propertiesByName buy_dictionaryByMappingValuesWithBlock:^(NSPropertyDescription *property) {
return [self buy_JSONKeyForPropertyName:property.name];
}];
}
- (NSString *)buy_JSONKeyForPropertyName:(NSString *)name
{
return [self buy_propertyWithName:name].JSONPropertyKey ?: [NSEntityDescription buy_defaultPropertyNameMapping][name];
}
#pragma mark - Object-Plist transformation
- (NSDictionary *)buy_JSONForObject:(NSObject<BUYObject> *)object
{
NSAssert([self isEqual:[object entity]], @"%@ entity cannot decode %@ objects", self.name, [object entity].name);
// The encoding map is a block which converts property names into JSON keys.
BUYStringMap encodingMap = self.JSONKeyEncodingMap;
NSMutableDictionary *results = [NSMutableDictionary dictionary];
[object.JSONEncodedProperties enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSPropertyDescription *property, BOOL *stop) {
id value = [object valueForKey:propertyName];
if (value) {
// Each property is responsible for knowing how to generate JSON for its value
// Some properties do not encode themselves in JSON, so we mut check for nil
id JSONValue = [property buy_JSONForValue:value];
if (JSONValue) {
NSString *JSONKey = encodingMap(propertyName) ?: propertyName;
results[JSONKey] = JSONValue;
}
}
}];
return results;
}
- (NSArray *)buy_JSONForArray:(NSArray<NSObject<BUYObject> *> *)array
{
return [array buy_map:^(NSObject<BUYObject> *object) {
return [self buy_JSONForObject:object];
}];
}
- (void)buy_updateObject:(NSObject<BUYObject> *)object withJSON:(NSDictionary *)JSON
{
NSAssert([self isEqual:[object entity]], @"%@ entity cannot decode %@ objects", self.name, [object entity].name);
NSDictionary *properties = self.propertiesByName;
// The decoding map is a block which converts the key in the JSON into a property name.
BUYStringMap decodingMap = self.JSONKeyDecodingMap;
// Iterate through the JSON, and generate the native value using the property object.
NSMutableDictionary *results = [NSMutableDictionary dictionary];
[JSON enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL * stop) {
NSString *propertyName = decodingMap(key) ?: key;
NSPropertyDescription *property = properties[propertyName];
// Each property is responsible for knowing how to parse JSON for its value
results[propertyName] = [property buy_valueForJSON:value object:object];
}];
[object setValuesForKeysWithDictionary:results];
}
@end
//
// NSPropertyDescription+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <CoreData/CoreData.h>
@class BUYModelManager;
@protocol BUYObject;
// property user info keys
extern NSString * const BUYJSONValueTransformerUserInfoKey; // = @"JSONValueTransformer";
extern NSString * const BUYJSONPropertyKeyUserInfoKey; // = @"JSONPropertyKey";
@interface NSPropertyDescription (BUYAdditions)
/**
* The name of a value transformer used to convert to JSON values and back.
* Uses the value specified in the property's user info dictionary under the "JSONValueTransformer" key.
*
* Currently only two transformers are supported: "BUYPublicationsDate" and "BUYShippingRateDate".
* Currently, only attributes (instances of NSAttributeDescription) use value transformers.
*/
@property (nonatomic, readonly, getter=buy_JSONValueTransformerName) NSString *JSONValueTransformerName;
/**
* The value transformer corresponding to the JSONValueTransformerName. If no name is specified,
* the value is not changed.
*/
@property (nonatomic, readonly, getter=buy_JSONValueTransformer) NSValueTransformer *JSONValueTransformer;
/**
* The name of the key to use for the property, instead of its name, when generating JSON. Requires
* adding an entry in the Property userInfo, in the Core Data model file, with the key "JSONPropertyKey".
*/
@property (nonatomic, readonly, getter=buy_JSONPropertyKey) NSString *JSONPropertyKey;
/**
* Convert the provided JSON into the appropriate data type, either simple values or model objects.
* For relationships, uses the destinationEntity to recursively fetch or create related objects as needed.
*/
- (id)buy_valueForJSON:(id)JSON object:(id<BUYObject>)object;
/**
* Convert the provided object, a value corresponding to the property on the parent object.
*
* For relationships, related object data is generated according to the following rules:
* - if the "JSONPropertyKey" is set in the user info dictionary, and it ends in "_id" (or "_ids")
* then encode the related object(s) using only their identifier(s)
* - if the inverse relationship delete rule is "Cascade", or its entity is marked private,
* or the relationship is many-to-many, do not encode the object for this relationship
* (it is inferred that the related object owns this object; this avoids a loop in the encoding)
* - otherwise, encode the full JSON representation of the related object(s)
*/
- (id)buy_JSONForValue:(id)value;
@end
@interface NSRelationshipDescription (BUYAdditions)
/**
* Used during JSON transformation. If the value is YES, parsed JSON is expected to be a number
* representing an object identifier, which will be resolved by fetching from the persistent store.
* Likewise, generated JSON will include identifiers in place of full objects.
*/
@property (nonatomic, readonly, getter=buy_encodesIdInJSON) BOOL encodesIdInJSON;
/**
* YES if the delete rule is not Cascading and the entity is not private.
*/
@property (nonatomic, readonly, getter=buy_allowsInverseEncoding) BOOL allowsInverseEncoding;
/**
* YES if this relationship and its inverse are both toMany
*/
@property (nonatomic, readonly, getter=buy_isManyToMany) BOOL manyToMany;
@end
//
// NSPropertyDescription+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "NSPropertyDescription+BUYAdditions.h"
#import "BUYModelManagerProtocol.h"
#import "BUYObjectProtocol.h"
#import "NSDecimalNumber+BUYAdditions.h"
#import "NSArray+BUYAdditions.h"
#import "NSException+BUYAdditions.h"
#import "NSEntityDescription+BUYAdditions.h"
#import "BUYDateTransformer.h"
#import "BUYDecimalNumberTransformer.h"
#import "BUYIdentityTransformer.h"
#import "BUYURLTransformer.h"
// User Info Keys
NSString * const BUYJSONValueTransformerUserInfoKey = @"JSONValueTransformer";
NSString * const BUYJSONPropertyKeyUserInfoKey = @"JSONPropertyKey";
// This is defined by mogenerator
static NSString * const BUYAttributeValueClassNameKey = @"attributeValueClassName";
#pragma mark -
@interface NSObject (BUYValueTransforming)
- (BOOL)buy_isValidObject;
+ (NSString *)buy_JSONValueTransformerName;
@end
#pragma mark -
@implementation NSPropertyDescription (BUYAdditions)
- (NSString *)buy_JSONValueTransformerName
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// default transformer
[NSValueTransformer setValueTransformer:[[BUYIdentityTransformer alloc] init] forName:BUYIdentityTransformerName];
// attribute type transformers
[NSValueTransformer setValueTransformer:[[BUYDateTransformer alloc] init] forName:BUYDateTransformerName];
[NSValueTransformer setValueTransformer:[[BUYDecimalNumberTransformer alloc] init] forName:BUYDecimalNumberTransformerName];
// value type transformers
[NSValueTransformer setValueTransformer:[[BUYURLTransformer alloc] init] forName:BUYURLTransformerName];
});
return self.userInfo[BUYJSONValueTransformerUserInfoKey];
}
- (NSString *)buy_JSONPropertyKey
{
return self.userInfo[BUYJSONPropertyKeyUserInfoKey];
}
- (NSValueTransformer *)buy_JSONValueTransformer
{
return [NSValueTransformer valueTransformerForName:self.JSONValueTransformerName];
}
- (id)buy_valueForJSON:(id)JSON object:(id<BUYObject>)object
{
@throw BUYAbstractMethod();
}
- (id)buy_JSONForValue:(id)object
{
@throw BUYAbstractMethod();
}
@end
#pragma mark -
static NSString *JSONValueTransformerNameForAttributeType(NSAttributeType type)
{
NSString *name = nil;
switch (type) {
case NSDateAttributeType:
name = BUYDateTransformerName;
break;
case NSDecimalAttributeType:
name = BUYDecimalNumberTransformerName;
break;
default:
break;
}
return name;
}
@implementation NSAttributeDescription (BUYAdditions)
- (NSString *)buy_attributeValueClassName
{
return self.userInfo[BUYAttributeValueClassNameKey];
}
- (Class)buy_attributeValueClass
{
return NSClassFromString([self buy_attributeValueClassName]);
}
- (NSString *)buy_JSONValueTransformerName
{
NSString *name = [super buy_JSONValueTransformerName];
if (name == nil) {
name = JSONValueTransformerNameForAttributeType(self.attributeType);
}
if (name == nil) {
name = [[self buy_attributeValueClass] buy_JSONValueTransformerName];
}
if (name == nil) {
name = BUYIdentityTransformerName;
}
return name;
}
- (id)buy_valueForJSON:(id)JSON object:(id<BUYObject>)object
{
// An attribute's value is determined by the specified transformer.
// An Identity transform returns the same value. `nil` is converted into `NSNull`.
id transformedValue = [JSON buy_isValidObject] ? [self.JSONValueTransformer reverseTransformedValue:JSON] : [NSNull null];
return transformedValue ?: [NSNull null];
}
- (id)buy_JSONForValue:(id)object
{
// An attribute's JSON is determined by the specified transformer.
// An identify transform returns the same value.
return [self.JSONValueTransformer transformedValue:object];
}
@end
#pragma mark -
@implementation NSRelationshipDescription (BUYAdditions)
#pragma mark - Helpers
- (NSString *)encodesIdSuffix
{
return (self.isToMany ? @"_ids" : @"_id");
}
// array -> (ordered)set
- (id)buy_transformArray:(NSArray<id<BUYObject>> *)array
{
return self.isOrdered ? [NSOrderedSet orderedSetWithArray:array] : [NSSet setWithArray:array];
}
// (ordered)set -> array
- (NSArray *)buy_arrayForCollection:(id)collection
{
return self.ordered ? [collection array] : [collection allObjects];
}
// JSON -> model
- (id)buy_objectForJSON:(id)JSON modelManager:(id<BUYModelManager>)modelManager
{
NSString *entityName = self.destinationEntity.name;
// If we are expecting an object `id` the object should already exist.
// Otherwise let the object context decide how to resolve the object and update it.
if (self.encodesIdInJSON) {
return [modelManager buy_objectWithEntityName:entityName identifier:JSON];
}
else {
return [modelManager buy_objectWithEntityName:entityName JSONDictionary:JSON];
}
}
// model -> JSON
- (id)buy_JSONForObject:(NSObject<BUYObject> *)object
{
id json = nil;
if (!self.inverseRelationship || self.inverseRelationship.allowsInverseEncoding) {
json = [self.destinationEntity buy_JSONForObject:object];
}
return json;
}
// JSON -> (ordered)set (of models)
- (id)buy_collectionForJSON:(NSArray *)JSON modelManager:(id<BUYModelManager>)modelManager
{
NSString *entityName = self.destinationEntity.name;
NSArray<id<BUYObject>> *array;
// If we are expecting an array of object `ids`, the objects should already exist.
// Otherwise, let the object context decide how to resolve the objects and update them.
// If device caching is not provided, this will return nothing.
if (self.encodesIdInJSON) {
array = [modelManager buy_objectsWithEntityName:entityName identifiers:JSON];
}
else {
array = [modelManager buy_objectsWithEntityName:entityName JSONArray:JSON];
}
// Transform the array to the correct container type (`NSSet` or `NSOrderedSet`).
return [self buy_transformArray:array];
}
// (ordered)set (of models) -> JSON
- (NSArray *)buy_JSONForCollection:(id)collection
{
return [self.destinationEntity buy_JSONForArray:[self buy_arrayForCollection:collection]];
}
#pragma mark - Property Additions Overrides
- (id)buy_valueForJSON:(id)JSON object:(id<BUYObject>)object
{
// A relationship's value is provided by the object context.
// The logic for decoding JSON is slightly different for to-one and to-many relationships.
// NOTE: by default, without a caching system, inverse relationships are not supported.
id value = nil;
if ([JSON buy_isValidObject]) {
if (self.isToMany) {
value = [self buy_collectionForJSON:JSON modelManager:object.modelManager];
}
else {
value = [self buy_objectForJSON:JSON modelManager:object.modelManager];
}
}
return value;
}
- (id)buy_JSONForValue:(id)value
{
// JSON generation for a relationship depends on the rules defined in the model.
// The model can explicitly specify using an `id` encoding.
// Alternately, if the relationship is compatible, encode the entire object.
// We do not encode related objects unless three conditions are satisfied:
// 1. the relationship is not many-to-many
// 2. the inverse relationship is not an ownership relationship
// (this is inferred from the `NSCascadeDeleteRule` used by owning objects)
// 3. the relationship is to a "private" entity (not known to the API)
id json = nil;
if (self.encodesIdInJSON) {
json = [value valueForKey:NSStringFromSelector(@selector(identifier))];
}
else if (!self.toMany) {
json = [self buy_JSONForObject:value];
}
else if (!self.manyToMany) {
json = [self buy_JSONForCollection:value];
}
return json;
}
#pragma mark - Properties
- (BOOL)buy_encodesIdInJSON
{
return [self.JSONPropertyKey hasSuffix:[self encodesIdSuffix]];
}
- (BOOL)buy_isManyToMany
{
return self.toMany && self.inverseRelationship.toMany;
}
- (BOOL)buy_allowsInverseEncoding
{
return self.deleteRule != NSCascadeDeleteRule && ![self.entity buy_isPrivate];
}
@end
#pragma mark -
@implementation NSFetchedPropertyDescription (BUYAdditions)
- (id)buy_valueForJSON:(id)JSON object:(id<BUYObject>)object
{
return nil;
}
- (id)buy_JSONForValue:(id)value
{
return nil;
}
@end
#pragma mark -
@implementation NSObject (BUYValueTransforming)
+ (NSString *)buy_JSONValueTransformerName
{
return BUYIdentityTransformerName;
}
- (BOOL)buy_isValidObject
{
return YES;
}
@end
@implementation NSNull (BUYValueTransforming)
- (BOOL)buy_isValidObject
{
return NO;
}
@end
@implementation NSURL (BUYValueTransforming)
+ (NSString *)buy_JSONValueTransformerName
{
return BUYURLTransformerName;
}
@end
//
// BUYModelManagerProtocol.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <CoreData/CoreData.h>
/**
* A protocol for defining an object that can store and retrieve model objects from a data store or other cache.
*/
@protocol BUYModelManager <NSObject>
/**
* Returns an entity given its name.
*
* @param entityName Name of the entity from the Core Data managed object model.
*
* @return The entity description matching the name.
*/
- (NSEntityDescription *)buy_entityWithName:(NSString *)entityName;
/**
* If the JSON contains a key representing the unique identifier, and there is an existing cached object that matches that identifier,
* then that object will be updated with the remaining entries in the JSON. If no such object exists, a new object is created, and
* sent -updateWithJSON:.
*
* @param entityName Name of the entity from the Core Data managed object model.
* @param JSON The JSON representing the object.
*
* @return A new or existing model object.
*/
- (id<BUYObject>)buy_objectWithEntityName:(NSString *)entityName JSONDictionary:(NSDictionary *)JSON;
- (NSArray<id<BUYObject>> *)buy_objectsWithEntityName:(NSString *)entityName JSONArray:(NSArray *)JSON;
/**
* Cache-based model managers may resolve objects based on their identifier. The alternative is to return nil.
* Only supported by models whose entity declares an "identifier" attribute.
*
* @param entityName Name of the entity from the Core Data managed object model.
* @param identifier A shopify object identifier of an existing object in the local data cache.
*
* @return An object from the cache matching the provided identifier, or nil if no matching object is found.
*/
- (id<BUYObject>)buy_objectWithEntityName:(NSString *)entityName identifier:(NSNumber *)identifier;
/**
* Find all the objects in the cache matching the provided identifiers.
*
* @param entityName Name of the entity from the Core Data managed object model.
* @param identifiers An array of Shopify object identifiers.
*
* @return An array of objects from the cache matching the provided identifiers, if any.
*/
- (NSArray<id<BUYObject>> *)buy_objectsWithEntityName:(NSString *)entityName identifiers:(NSArray *)identifiers;
/**
* If there is a local cache available, and the object is cached, it is flushed from the cache. Depending on the type of
* caching in use (if any), the provided object may no longer be valid, and references should be reset. If the cache
* supports stand-alone objects, and the object is modified or passed into the SDK, it could be re-inserted into the cache.
*
* If Core Data is used for local caching, purging is equivalent to deletion. (see -deleteObject[WithIdentifier]:error:)
*
* If the object is not in the cache (or there is no cache), does nothing.
*
* @param object An existing model object.
* @param error A pointer to an error. May be NULL.
*
* @return YES if the object was successfully removed from the cache. NO if there was an error.
*/
- (BOOL)buy_purgeObject:(id<BUYObject>)object error:(NSError **)error;
/**
* Update the cached version of the object given the current state of the object.
*
* @param object An existing model object.
*/
- (void)buy_refreshCacheForObject:(id<BUYObject>)object;
/**
*
* @param entityName Name of the entity from the Core Data managed object model.
* @param predicate An NSPredicate that identifies objects that should be deleted from the cache.
*
* @return YES if the purge was successful. NO if there was a problem.
*/
- (BOOL)buy_purgeObjectsWithEntityName:(NSString *)entityName matchingPredicate:(NSPredicate *)predicate;
@end
//
// BUYObjectProtocol.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
@class NSEntityDescription;
@protocol BUYModelManager;
/**
* The BUYObject protocol is adopted by the common superclasses of both persistent and transient model classes.
*
*/
@protocol BUYObject <NSObject>
@property (nonatomic, readonly, weak) id<BUYModelManager> modelManager;
/**
* Transient model objects need an entity for introspection.
*/
@property (nonatomic, readonly, weak) NSEntityDescription *entity;
/**
* A dictionary of @{ NSString : NSPropertyDescription } where the keys are property names.
* By default, returns the same value defined on NSEntityDescription (from BUYAdditions).
*/
@property (nonatomic, readonly) NSDictionary *JSONEncodedProperties;
/**
* Convenience static property overridden by auto-generated model files.
*/
+ (NSString *)entityName;
/**
* A derived property used to generate or apply JSON data. Values are calculated, recursively, automatically.
*/
@property (nonatomic, strong) NSDictionary *JSONDictionary;
/**
* A predicate composed of values from the JSON. For objects that do not have an "identifier"/"id" property.
*/
+ (NSPredicate *)fetchPredicateWithJSON:(NSDictionary *)JSONDictionary;
/**
* Persistent classes return YES; transient classes return NO.
*/
+ (BOOL)isPersistentClass;
/**
* Conforming classes should override to specify whether to use dirty tracking to restrict generated JSON to only changed values.
*/
+ (BOOL)tracksDirtyProperties;
@optional
- (instancetype)initWithModelManager:(id<BUYModelManager>)modelManager JSONDictionary:(NSDictionary *)dictionary;
@end
......@@ -32,4 +32,4 @@
return self;
}
@end
\ No newline at end of file
@end
//
// BUYDateTransformer.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
extern NSString * const BUYDateTransformerName; // = @"BUYDate";
/**
* Transforms a date object into a string and back using the provided format string.
*/
@interface BUYDateTransformer : NSValueTransformer
+ (instancetype)dateTransformerWithFormat:(NSString *)format;
@end
//
// BUYDateTransformer.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYDateTransformer.h"
#import "NSDateFormatter+BUYAdditions.h"
NSString * const BUYDateTransformerName = @"BUYDate";
@interface BUYDateTransformer ()
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@end
@implementation BUYDateTransformer
- (instancetype)init
{
NSDateFormatter *formatter = [NSDateFormatter dateFormatterForPublications];
formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
return [self initWithDateFormatter:formatter];
}
- (instancetype)initWithDateFormatter:(NSDateFormatter *)formatter
{
self = [super init];
if (self) {
self.dateFormatter = formatter;
}
return self;
}
- (NSString *)transformedValue:(NSDate *)value
{
return [self.dateFormatter stringFromDate:value];
}
- (NSDate *)reverseTransformedValue:(NSString *)value
{
return [self.dateFormatter dateFromString:value];
}
+ (instancetype)dateTransformerWithFormat:(NSString *)format
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:format];
return [[self alloc] initWithDateFormatter:formatter];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
+ (Class)transformedValueClass
{
return [NSString class];
}
@end
//
// BUYDecimalNumberTransformer.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
extern NSString * const BUYDecimalNumberTransformerName; // = @"BUYDecimalNumber";
/**
* Transforms a decimal number object into a string and back.
*/
@interface BUYDecimalNumberTransformer : NSValueTransformer
@end
//
// BUYDecimalNumberTransformer.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYDecimalNumberTransformer.h"
#import "NSDecimalNumber+BUYAdditions.h"
NSString * const BUYDecimalNumberTransformerName = @"BUYDecimalNumber";
@implementation BUYDecimalNumberTransformer
+ (Class)transformedValueClass
{
return [NSString class];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
- (id)transformedValue:(NSDecimalNumber *)value
{
return [value stringValue];
}
- (id)reverseTransformedValue:(id)value
{
return [NSDecimalNumber buy_decimalNumberFromJSON:value];
}
@end
//
// BUYDeliveryRangeTransformer.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
extern NSString * const BUYShippingRateDateTransformerName; // = @"BUYShippingRateDate";
extern NSString * const BUYShippingRateDateFormat; // = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ";
@interface BUYDeliveryRangeTransformer : NSValueTransformer
@end
//
// BUYDeliveryRangeTransformer.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYDeliveryRangeTransformer.h"
#import "BUYDateTransformer.h"
#import "NSArray+BUYAdditions.h"
NSString * const BUYShippingRateDateTransformerName = @"BUYShippingRateDate";
NSString * const BUYShippingRateDateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ";
@implementation BUYDeliveryRangeTransformer
+ (void)initialize
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[NSValueTransformer setValueTransformer:[BUYDateTransformer dateTransformerWithFormat:BUYShippingRateDateFormat] forName:BUYShippingRateDateTransformerName];
});
}
- (NSArray *)transformedValue:(NSArray *)value
{
NSValueTransformer *dateTransformer = [NSValueTransformer valueTransformerForName:BUYShippingRateDateTransformerName];
return [value buy_map:^(NSDate *date) {
return [dateTransformer transformedValue:date];
}];
}
- (NSArray *)reverseTransformedValue:(NSArray *)value
{
NSValueTransformer *dateTransformer = [NSValueTransformer valueTransformerForName:BUYShippingRateDateTransformerName];
return [value buy_map:^(NSString *dateString) {
return [dateTransformer reverseTransformedValue:dateString];
}];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
+ (Class)transformedValueClass
{
return [NSString class];
}
@end
//
// BUYFlatCollectionTransformer.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
/**
* Transforms an array of objects into a string with given separator.
*/
@interface BUYFlatCollectionTransformer : NSValueTransformer
+ (instancetype)arrayTransformerWithElementTransformer:(NSValueTransformer *)elementTransformer separator:(NSString *)separator;
+ (instancetype)setTransformerWithElementTransformer:(NSValueTransformer *)elementTransformer separator:(NSString *)separator;
+ (instancetype)orderedSetTransformerWithElementTransformer:(NSValueTransformer *)elementTransformer separator:(NSString *)separator;
/**
* Default to using the identity transformer and a space as separator.
*/
+ (instancetype)arrayTransformer;
+ (instancetype)setTransformer;
+ (instancetype)arrayTransformerWithSeparator:(NSString *)separator;
+ (instancetype)setTransformerWithSeparator:(NSString *)separator;
@end
//
// BUYFlatCollectionTransformer.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYFlatCollectionTransformer.h"
#import "BUYIdentityTransformer.h"
#import "NSArray+BUYAdditions.h"
@interface BUYFlatCollectionTransformer ()
@property (nonatomic, weak) Class collectionClass;
@property (nonatomic, strong) NSValueTransformer *elementTransformer;
@property (nonatomic, strong) NSString *separator;
@end
@implementation BUYFlatCollectionTransformer
+ (instancetype)collectionTransformerWithClass:(Class)klass elementTransformer:(NSValueTransformer *)elementTransformer separator:(NSString *)separator
{
BUYFlatCollectionTransformer *transformer = [[BUYFlatCollectionTransformer alloc] init];
transformer.collectionClass = klass;
transformer.separator = separator;
transformer.elementTransformer = elementTransformer;
return transformer;
}
+ (instancetype)arrayTransformerWithElementTransformer:(NSValueTransformer *)elementTransformer separator:(NSString *)separator
{
return [self collectionTransformerWithClass:[NSArray class] elementTransformer:elementTransformer separator:separator];
}
+ (instancetype)arrayTransformer
{
return [self arrayTransformerWithElementTransformer:[[BUYIdentityTransformer alloc] init] separator:@" "];
}
+ (instancetype)arrayTransformerWithSeparator:(NSString *)separator
{
return [self arrayTransformerWithElementTransformer:[[BUYIdentityTransformer alloc] init] separator:separator];
}
+ (instancetype)setTransformerWithElementTransformer:(NSValueTransformer *)elementTransformer separator:(NSString *)separator
{
return [self collectionTransformerWithClass:[NSSet class] elementTransformer:elementTransformer separator:separator];
}
+ (instancetype)setTransformerWithSeparator:(NSString *)separator
{
return [self setTransformerWithElementTransformer:[[BUYIdentityTransformer alloc] init] separator:separator];
}
+ (instancetype)setTransformer
{
return [self setTransformerWithSeparator:@" "];
}
+ (instancetype)orderedSetTransformerWithElementTransformer:(NSValueTransformer *)elementTransformer separator:(NSString *)separator
{
return [self collectionTransformerWithClass:[NSOrderedSet class] elementTransformer:elementTransformer separator:separator];
}
+ (instancetype)orderedSetTransformerWithSeparator:(NSString *)separator
{
return [self orderedSetTransformerWithElementTransformer:[[BUYIdentityTransformer alloc] init] separator:separator];
}
+ (Class)transformedValueClass
{
return [NSString class];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
- (NSString *)transformedValue:(id)value
{
return [[[value buy_array] buy_map:^(id element) {
return [_elementTransformer transformedValue:element];
}] componentsJoinedByString:self.separator];
}
- (id)reverseTransformedValue:(NSString *)value
{
NSArray *array = [[value componentsSeparatedByString:self.separator] buy_map:^(NSString *string) {
return [_elementTransformer reverseTransformedValue:string];
}];
return [_collectionClass buy_convertArray:array];
}
@end
//
// BUYIdentityTransformer.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
extern NSString * const BUYIdentityTransformerName; // = @"BUYIdentity";
/**
* Transforms a value into itself.
*/
@interface BUYIdentityTransformer : NSValueTransformer
@end
//
// BUYIdentityTransformer.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYIdentityTransformer.h"
NSString * const BUYIdentityTransformerName = @"BUYIdentity";
@implementation BUYIdentityTransformer
- (id)transformedValue:(id)value
{
return value;
}
- (id)reverseTransformedValue:(id)value
{
return value;
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
+ (Class)transformedValueClass
{
return [NSObject class];
}
@end
//
// BUYURLTransformer.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
extern NSString * const BUYURLTransformerName; // = @"BUYURL";
/**
* Transforms a URL object into a string and back.
*/
@interface BUYURLTransformer : NSValueTransformer
@end
//
// BUYURLTransformer.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYURLTransformer.h"
NSString * const BUYURLTransformerName = @"BUYURL";
@implementation BUYURLTransformer
+ (Class)transformedValueClass
{
return [NSString class];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
- (id)transformedValue:(NSURL *)value
{
return [value absoluteString];
}
- (id)reverseTransformedValue:(NSString *)value
{
return [NSURL URLWithString:value];
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment