├── .gitignore ├── BookMigration.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── hwaxxer.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── hwaxxer.xcuserdatad │ ├── xcdebugger │ └── Breakpoints.xcbkptlist │ └── xcschemes │ ├── BookMigration.xcscheme │ └── xcschememanagement.plist ├── BookMigration ├── BookMigration-Info.plist ├── BookMigration-Prefix.pch ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── MHWAppDelegate.h ├── MHWAppDelegate.m ├── MHWBookToBookPolicy.h ├── MHWBookToBookPolicy.m ├── MHWCoreDataController.h ├── MHWCoreDataController.m ├── MHWMigrationManager.h ├── MHWMigrationManager.m ├── MHWUserToUserPolicy.h ├── MHWUserToUserPolicy.m ├── MHWViewController.h ├── MHWViewController.m ├── Model.xcdatamodeld │ ├── .xccurrentversion │ ├── Model1.xcdatamodel │ │ └── contents │ ├── Model2.xcdatamodel │ │ └── contents │ └── Model3.xcdatamodel │ │ └── contents ├── Model1.sqlite ├── Model1_to_Model2.xcmappingmodel │ └── xcmapping.xml ├── Model2_to_Model3.xcmappingmodel │ └── xcmapping.xml ├── Model2_to_Model3_User.xcmappingmodel │ └── xcmapping.xml ├── NSFileManager+MHWAdditions.h ├── NSFileManager+MHWAdditions.m ├── NSManagedObjectModel+MHWAdditions.h ├── NSManagedObjectModel+MHWAdditions.m ├── NSMigrationManager+Lookup.h ├── NSMigrationManager+Lookup.m ├── en.lproj │ ├── InfoPlist.strings │ ├── MHWViewController_iPad.xib │ └── MHWViewController_iPhone.xib └── main.m ├── BookMigrationTests ├── BookMigrationTests-Info.plist ├── MHWCoreDataTests.h ├── MHWCoreDataTests.m ├── MHWMigrationFromModel1Tests.h ├── MHWMigrationFromModel1Tests.m ├── MHWMigrationFromModel2Tests.h ├── MHWMigrationFromModel2Tests.m └── en.lproj │ └── InfoPlist.strings ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /BookMigration.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 738AC53017D26D01004DE3E5 /* MHWCoreDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 738AC52F17D26D01004DE3E5 /* MHWCoreDataTests.m */; }; 11 | 739100B817CBF03500383BD0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100B717CBF03500383BD0 /* UIKit.framework */; }; 12 | 739100BA17CBF03500383BD0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100B917CBF03500383BD0 /* Foundation.framework */; }; 13 | 739100BC17CBF03500383BD0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100BB17CBF03500383BD0 /* CoreGraphics.framework */; }; 14 | 739100C217CBF03500383BD0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 739100C017CBF03500383BD0 /* InfoPlist.strings */; }; 15 | 739100C417CBF03500383BD0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 739100C317CBF03500383BD0 /* main.m */; }; 16 | 739100C817CBF03500383BD0 /* MHWAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 739100C717CBF03500383BD0 /* MHWAppDelegate.m */; }; 17 | 739100CA17CBF03500383BD0 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 739100C917CBF03500383BD0 /* Default.png */; }; 18 | 739100CC17CBF03500383BD0 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 739100CB17CBF03500383BD0 /* Default@2x.png */; }; 19 | 739100CE17CBF03500383BD0 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 739100CD17CBF03500383BD0 /* Default-568h@2x.png */; }; 20 | 739100D117CBF03500383BD0 /* MHWViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 739100D017CBF03500383BD0 /* MHWViewController.m */; }; 21 | 739100D417CBF03500383BD0 /* MHWViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 739100D217CBF03500383BD0 /* MHWViewController_iPhone.xib */; }; 22 | 739100D717CBF03500383BD0 /* MHWViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 739100D517CBF03500383BD0 /* MHWViewController_iPad.xib */; }; 23 | 739100DF17CBF03500383BD0 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100DE17CBF03500383BD0 /* SenTestingKit.framework */; }; 24 | 739100E017CBF03500383BD0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100B717CBF03500383BD0 /* UIKit.framework */; }; 25 | 739100E117CBF03500383BD0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100B917CBF03500383BD0 /* Foundation.framework */; }; 26 | 739100E917CBF03500383BD0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 739100E717CBF03500383BD0 /* InfoPlist.strings */; }; 27 | 739100EC17CBF03500383BD0 /* MHWMigrationFromModel1Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 739100EB17CBF03500383BD0 /* MHWMigrationFromModel1Tests.m */; }; 28 | 739100F817CBF06000383BD0 /* MHWCoreDataController.m in Sources */ = {isa = PBXBuildFile; fileRef = 739100F717CBF06000383BD0 /* MHWCoreDataController.m */; }; 29 | 739100FE17CBF13800383BD0 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 739100FC17CBF13800383BD0 /* Model.xcdatamodeld */; }; 30 | 7391010017CBF1A600383BD0 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100FF17CBF1A600383BD0 /* CoreData.framework */; }; 31 | 7391010417CBF26600383BD0 /* NSFileManager+MHWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7391010317CBF26600383BD0 /* NSFileManager+MHWAdditions.m */; }; 32 | 73BD5FE817CD36BA003D1AB8 /* MHWBookToBookPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 73BD5FE717CD36BA003D1AB8 /* MHWBookToBookPolicy.m */; }; 33 | 73BFFFD917D3AAED0094E0BB /* Model1_to_Model2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 73BFFFD817D3AAED0094E0BB /* Model1_to_Model2.xcmappingmodel */; }; 34 | 73BFFFDC17D3AEB40094E0BB /* Model2_to_Model3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 73BFFFDB17D3AEB40094E0BB /* Model2_to_Model3.xcmappingmodel */; }; 35 | 73BFFFE217D3B4510094E0BB /* NSMigrationManager+Lookup.m in Sources */ = {isa = PBXBuildFile; fileRef = 73BFFFE117D3B4510094E0BB /* NSMigrationManager+Lookup.m */; }; 36 | 73C2046B17D1124B0051D6BD /* MHWMigrationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 73C2046A17D1124B0051D6BD /* MHWMigrationManager.m */; }; 37 | 73C2EBF017DB972C00855DA5 /* NSManagedObjectModel+MHWAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 73C2EBEF17DB972C00855DA5 /* NSManagedObjectModel+MHWAdditions.m */; }; 38 | 73C2EBF317DBACAD00855DA5 /* Model2_to_Model3_User.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 73C2EBF217DBACAD00855DA5 /* Model2_to_Model3_User.xcmappingmodel */; }; 39 | 73DB63C417CE8BF0002CA975 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 739100FF17CBF1A600383BD0 /* CoreData.framework */; }; 40 | 73E1761A17DBBB730046504B /* Model1.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 73E1761917DBBB730046504B /* Model1.sqlite */; }; 41 | 73E1761C17DBBC660046504B /* Model1.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 73E1761917DBBB730046504B /* Model1.sqlite */; }; 42 | /* End PBXBuildFile section */ 43 | 44 | /* Begin PBXContainerItemProxy section */ 45 | 739100E217CBF03500383BD0 /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = 739100AC17CBF03500383BD0 /* Project object */; 48 | proxyType = 1; 49 | remoteGlobalIDString = 739100B317CBF03500383BD0; 50 | remoteInfo = BookMigration; 51 | }; 52 | /* End PBXContainerItemProxy section */ 53 | 54 | /* Begin PBXFileReference section */ 55 | 738AC52E17D26D01004DE3E5 /* MHWCoreDataTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHWCoreDataTests.h; sourceTree = ""; }; 56 | 738AC52F17D26D01004DE3E5 /* MHWCoreDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MHWCoreDataTests.m; sourceTree = ""; }; 57 | 739100B417CBF03500383BD0 /* BookMigration.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BookMigration.app; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 739100B717CBF03500383BD0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 59 | 739100B917CBF03500383BD0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 60 | 739100BB17CBF03500383BD0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 61 | 739100BF17CBF03500383BD0 /* BookMigration-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BookMigration-Info.plist"; sourceTree = ""; }; 62 | 739100C117CBF03500383BD0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 63 | 739100C317CBF03500383BD0 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 64 | 739100C517CBF03500383BD0 /* BookMigration-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BookMigration-Prefix.pch"; sourceTree = ""; }; 65 | 739100C617CBF03500383BD0 /* MHWAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHWAppDelegate.h; sourceTree = ""; }; 66 | 739100C717CBF03500383BD0 /* MHWAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHWAppDelegate.m; sourceTree = ""; }; 67 | 739100C917CBF03500383BD0 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 68 | 739100CB17CBF03500383BD0 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 69 | 739100CD17CBF03500383BD0 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 70 | 739100CF17CBF03500383BD0 /* MHWViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHWViewController.h; sourceTree = ""; }; 71 | 739100D017CBF03500383BD0 /* MHWViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHWViewController.m; sourceTree = ""; }; 72 | 739100D317CBF03500383BD0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MHWViewController_iPhone.xib; sourceTree = ""; }; 73 | 739100D617CBF03500383BD0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MHWViewController_iPad.xib; sourceTree = ""; }; 74 | 739100DD17CBF03500383BD0 /* BookMigrationTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BookMigrationTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 75 | 739100DE17CBF03500383BD0 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 76 | 739100E617CBF03500383BD0 /* BookMigrationTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BookMigrationTests-Info.plist"; sourceTree = ""; }; 77 | 739100E817CBF03500383BD0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 78 | 739100EA17CBF03500383BD0 /* MHWMigrationFromModel1Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHWMigrationFromModel1Tests.h; sourceTree = ""; }; 79 | 739100EB17CBF03500383BD0 /* MHWMigrationFromModel1Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHWMigrationFromModel1Tests.m; sourceTree = ""; }; 80 | 739100F617CBF06000383BD0 /* MHWCoreDataController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHWCoreDataController.h; sourceTree = ""; }; 81 | 739100F717CBF06000383BD0 /* MHWCoreDataController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MHWCoreDataController.m; sourceTree = ""; }; 82 | 739100FD17CBF13800383BD0 /* Model1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model1.xcdatamodel; sourceTree = ""; }; 83 | 739100FF17CBF1A600383BD0 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 84 | 7391010217CBF26600383BD0 /* NSFileManager+MHWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+MHWAdditions.h"; sourceTree = ""; }; 85 | 7391010317CBF26600383BD0 /* NSFileManager+MHWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFileManager+MHWAdditions.m"; sourceTree = ""; }; 86 | 7391010517CBF42000383BD0 /* Model2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model2.xcdatamodel; sourceTree = ""; }; 87 | 73BD5FE617CD36BA003D1AB8 /* MHWBookToBookPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHWBookToBookPolicy.h; sourceTree = ""; }; 88 | 73BD5FE717CD36BA003D1AB8 /* MHWBookToBookPolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MHWBookToBookPolicy.m; sourceTree = ""; }; 89 | 73BFFFD817D3AAED0094E0BB /* Model1_to_Model2.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = Model1_to_Model2.xcmappingmodel; sourceTree = ""; }; 90 | 73BFFFDA17D3AB2A0094E0BB /* Model3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model3.xcdatamodel; sourceTree = ""; }; 91 | 73BFFFDB17D3AEB40094E0BB /* Model2_to_Model3.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = Model2_to_Model3.xcmappingmodel; sourceTree = ""; }; 92 | 73BFFFE017D3B4510094E0BB /* NSMigrationManager+Lookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMigrationManager+Lookup.h"; sourceTree = ""; }; 93 | 73BFFFE117D3B4510094E0BB /* NSMigrationManager+Lookup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMigrationManager+Lookup.m"; sourceTree = ""; }; 94 | 73BFFFE317D3B6730094E0BB /* MHWMigrationFromModel2Tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHWMigrationFromModel2Tests.h; sourceTree = ""; }; 95 | 73BFFFE417D3B6730094E0BB /* MHWMigrationFromModel2Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MHWMigrationFromModel2Tests.m; sourceTree = ""; }; 96 | 73C2046917D1124B0051D6BD /* MHWMigrationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHWMigrationManager.h; sourceTree = ""; }; 97 | 73C2046A17D1124B0051D6BD /* MHWMigrationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MHWMigrationManager.m; sourceTree = ""; }; 98 | 73C2EBEE17DB972C00855DA5 /* NSManagedObjectModel+MHWAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectModel+MHWAdditions.h"; sourceTree = ""; }; 99 | 73C2EBEF17DB972C00855DA5 /* NSManagedObjectModel+MHWAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectModel+MHWAdditions.m"; sourceTree = ""; }; 100 | 73C2EBF217DBACAD00855DA5 /* Model2_to_Model3_User.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = Model2_to_Model3_User.xcmappingmodel; sourceTree = ""; }; 101 | 73E1761917DBBB730046504B /* Model1.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = Model1.sqlite; sourceTree = ""; }; 102 | /* End PBXFileReference section */ 103 | 104 | /* Begin PBXFrameworksBuildPhase section */ 105 | 739100B117CBF03500383BD0 /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | 7391010017CBF1A600383BD0 /* CoreData.framework in Frameworks */, 110 | 739100B817CBF03500383BD0 /* UIKit.framework in Frameworks */, 111 | 739100BA17CBF03500383BD0 /* Foundation.framework in Frameworks */, 112 | 739100BC17CBF03500383BD0 /* CoreGraphics.framework in Frameworks */, 113 | ); 114 | runOnlyForDeploymentPostprocessing = 0; 115 | }; 116 | 739100D917CBF03500383BD0 /* Frameworks */ = { 117 | isa = PBXFrameworksBuildPhase; 118 | buildActionMask = 2147483647; 119 | files = ( 120 | 73DB63C417CE8BF0002CA975 /* CoreData.framework in Frameworks */, 121 | 739100DF17CBF03500383BD0 /* SenTestingKit.framework in Frameworks */, 122 | 739100E017CBF03500383BD0 /* UIKit.framework in Frameworks */, 123 | 739100E117CBF03500383BD0 /* Foundation.framework in Frameworks */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXFrameworksBuildPhase section */ 128 | 129 | /* Begin PBXGroup section */ 130 | 739100AB17CBF03500383BD0 = { 131 | isa = PBXGroup; 132 | children = ( 133 | 739100BD17CBF03500383BD0 /* BookMigration */, 134 | 739100E417CBF03500383BD0 /* BookMigrationTests */, 135 | 739100B617CBF03500383BD0 /* Frameworks */, 136 | 739100B517CBF03500383BD0 /* Products */, 137 | ); 138 | sourceTree = ""; 139 | }; 140 | 739100B517CBF03500383BD0 /* Products */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 739100B417CBF03500383BD0 /* BookMigration.app */, 144 | 739100DD17CBF03500383BD0 /* BookMigrationTests.octest */, 145 | ); 146 | name = Products; 147 | sourceTree = ""; 148 | }; 149 | 739100B617CBF03500383BD0 /* Frameworks */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 739100FF17CBF1A600383BD0 /* CoreData.framework */, 153 | 739100B717CBF03500383BD0 /* UIKit.framework */, 154 | 739100B917CBF03500383BD0 /* Foundation.framework */, 155 | 739100BB17CBF03500383BD0 /* CoreGraphics.framework */, 156 | 739100DE17CBF03500383BD0 /* SenTestingKit.framework */, 157 | ); 158 | name = Frameworks; 159 | sourceTree = ""; 160 | }; 161 | 739100BD17CBF03500383BD0 /* BookMigration */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 7391010117CBF24A00383BD0 /* Additions */, 165 | 739100F517CBF04300383BD0 /* CoreData */, 166 | 739100C617CBF03500383BD0 /* MHWAppDelegate.h */, 167 | 739100C717CBF03500383BD0 /* MHWAppDelegate.m */, 168 | 739100CF17CBF03500383BD0 /* MHWViewController.h */, 169 | 739100D017CBF03500383BD0 /* MHWViewController.m */, 170 | 739100D217CBF03500383BD0 /* MHWViewController_iPhone.xib */, 171 | 739100D517CBF03500383BD0 /* MHWViewController_iPad.xib */, 172 | 739100BE17CBF03500383BD0 /* Supporting Files */, 173 | ); 174 | path = BookMigration; 175 | sourceTree = ""; 176 | }; 177 | 739100BE17CBF03500383BD0 /* Supporting Files */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | 73E1761917DBBB730046504B /* Model1.sqlite */, 181 | 739100BF17CBF03500383BD0 /* BookMigration-Info.plist */, 182 | 739100C017CBF03500383BD0 /* InfoPlist.strings */, 183 | 739100C317CBF03500383BD0 /* main.m */, 184 | 739100C517CBF03500383BD0 /* BookMigration-Prefix.pch */, 185 | 739100C917CBF03500383BD0 /* Default.png */, 186 | 739100CB17CBF03500383BD0 /* Default@2x.png */, 187 | 739100CD17CBF03500383BD0 /* Default-568h@2x.png */, 188 | 739100FC17CBF13800383BD0 /* Model.xcdatamodeld */, 189 | 73BFFFD817D3AAED0094E0BB /* Model1_to_Model2.xcmappingmodel */, 190 | 73BFFFDB17D3AEB40094E0BB /* Model2_to_Model3.xcmappingmodel */, 191 | 73C2EBF217DBACAD00855DA5 /* Model2_to_Model3_User.xcmappingmodel */, 192 | ); 193 | name = "Supporting Files"; 194 | sourceTree = ""; 195 | }; 196 | 739100E417CBF03500383BD0 /* BookMigrationTests */ = { 197 | isa = PBXGroup; 198 | children = ( 199 | 738AC52E17D26D01004DE3E5 /* MHWCoreDataTests.h */, 200 | 738AC52F17D26D01004DE3E5 /* MHWCoreDataTests.m */, 201 | 739100EA17CBF03500383BD0 /* MHWMigrationFromModel1Tests.h */, 202 | 739100EB17CBF03500383BD0 /* MHWMigrationFromModel1Tests.m */, 203 | 73BFFFE317D3B6730094E0BB /* MHWMigrationFromModel2Tests.h */, 204 | 73BFFFE417D3B6730094E0BB /* MHWMigrationFromModel2Tests.m */, 205 | 739100E517CBF03500383BD0 /* Supporting Files */, 206 | ); 207 | path = BookMigrationTests; 208 | sourceTree = ""; 209 | }; 210 | 739100E517CBF03500383BD0 /* Supporting Files */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 739100E617CBF03500383BD0 /* BookMigrationTests-Info.plist */, 214 | 739100E717CBF03500383BD0 /* InfoPlist.strings */, 215 | ); 216 | name = "Supporting Files"; 217 | sourceTree = ""; 218 | }; 219 | 739100F517CBF04300383BD0 /* CoreData */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 739100F617CBF06000383BD0 /* MHWCoreDataController.h */, 223 | 739100F717CBF06000383BD0 /* MHWCoreDataController.m */, 224 | 73C2046917D1124B0051D6BD /* MHWMigrationManager.h */, 225 | 73C2046A17D1124B0051D6BD /* MHWMigrationManager.m */, 226 | 73BFFFE017D3B4510094E0BB /* NSMigrationManager+Lookup.h */, 227 | 73BFFFE117D3B4510094E0BB /* NSMigrationManager+Lookup.m */, 228 | 73C2EBEE17DB972C00855DA5 /* NSManagedObjectModel+MHWAdditions.h */, 229 | 73C2EBEF17DB972C00855DA5 /* NSManagedObjectModel+MHWAdditions.m */, 230 | 73BD5FE517CD369D003D1AB8 /* Custom Policies */, 231 | ); 232 | name = CoreData; 233 | sourceTree = ""; 234 | }; 235 | 7391010117CBF24A00383BD0 /* Additions */ = { 236 | isa = PBXGroup; 237 | children = ( 238 | 7391010217CBF26600383BD0 /* NSFileManager+MHWAdditions.h */, 239 | 7391010317CBF26600383BD0 /* NSFileManager+MHWAdditions.m */, 240 | ); 241 | name = Additions; 242 | sourceTree = ""; 243 | }; 244 | 73BD5FE517CD369D003D1AB8 /* Custom Policies */ = { 245 | isa = PBXGroup; 246 | children = ( 247 | 73BD5FE617CD36BA003D1AB8 /* MHWBookToBookPolicy.h */, 248 | 73BD5FE717CD36BA003D1AB8 /* MHWBookToBookPolicy.m */, 249 | ); 250 | name = "Custom Policies"; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXGroup section */ 254 | 255 | /* Begin PBXNativeTarget section */ 256 | 739100B317CBF03500383BD0 /* BookMigration */ = { 257 | isa = PBXNativeTarget; 258 | buildConfigurationList = 739100EF17CBF03500383BD0 /* Build configuration list for PBXNativeTarget "BookMigration" */; 259 | buildPhases = ( 260 | 739100B017CBF03500383BD0 /* Sources */, 261 | 739100B117CBF03500383BD0 /* Frameworks */, 262 | 739100B217CBF03500383BD0 /* Resources */, 263 | ); 264 | buildRules = ( 265 | ); 266 | dependencies = ( 267 | ); 268 | name = BookMigration; 269 | productName = BookMigration; 270 | productReference = 739100B417CBF03500383BD0 /* BookMigration.app */; 271 | productType = "com.apple.product-type.application"; 272 | }; 273 | 739100DC17CBF03500383BD0 /* BookMigrationTests */ = { 274 | isa = PBXNativeTarget; 275 | buildConfigurationList = 739100F217CBF03500383BD0 /* Build configuration list for PBXNativeTarget "BookMigrationTests" */; 276 | buildPhases = ( 277 | 739100D817CBF03500383BD0 /* Sources */, 278 | 739100D917CBF03500383BD0 /* Frameworks */, 279 | 739100DA17CBF03500383BD0 /* Resources */, 280 | 739100DB17CBF03500383BD0 /* ShellScript */, 281 | ); 282 | buildRules = ( 283 | ); 284 | dependencies = ( 285 | 739100E317CBF03500383BD0 /* PBXTargetDependency */, 286 | ); 287 | name = BookMigrationTests; 288 | productName = BookMigrationTests; 289 | productReference = 739100DD17CBF03500383BD0 /* BookMigrationTests.octest */; 290 | productType = "com.apple.product-type.bundle"; 291 | }; 292 | /* End PBXNativeTarget section */ 293 | 294 | /* Begin PBXProject section */ 295 | 739100AC17CBF03500383BD0 /* Project object */ = { 296 | isa = PBXProject; 297 | attributes = { 298 | CLASSPREFIX = MHW; 299 | LastUpgradeCheck = 0460; 300 | ORGANIZATIONNAME = "Martin Hwasser"; 301 | }; 302 | buildConfigurationList = 739100AF17CBF03500383BD0 /* Build configuration list for PBXProject "BookMigration" */; 303 | compatibilityVersion = "Xcode 3.2"; 304 | developmentRegion = English; 305 | hasScannedForEncodings = 0; 306 | knownRegions = ( 307 | en, 308 | ); 309 | mainGroup = 739100AB17CBF03500383BD0; 310 | productRefGroup = 739100B517CBF03500383BD0 /* Products */; 311 | projectDirPath = ""; 312 | projectRoot = ""; 313 | targets = ( 314 | 739100B317CBF03500383BD0 /* BookMigration */, 315 | 739100DC17CBF03500383BD0 /* BookMigrationTests */, 316 | ); 317 | }; 318 | /* End PBXProject section */ 319 | 320 | /* Begin PBXResourcesBuildPhase section */ 321 | 739100B217CBF03500383BD0 /* Resources */ = { 322 | isa = PBXResourcesBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | 739100C217CBF03500383BD0 /* InfoPlist.strings in Resources */, 326 | 739100CA17CBF03500383BD0 /* Default.png in Resources */, 327 | 739100CC17CBF03500383BD0 /* Default@2x.png in Resources */, 328 | 739100CE17CBF03500383BD0 /* Default-568h@2x.png in Resources */, 329 | 739100D417CBF03500383BD0 /* MHWViewController_iPhone.xib in Resources */, 330 | 739100D717CBF03500383BD0 /* MHWViewController_iPad.xib in Resources */, 331 | 73E1761C17DBBC660046504B /* Model1.sqlite in Resources */, 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | 739100DA17CBF03500383BD0 /* Resources */ = { 336 | isa = PBXResourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 739100E917CBF03500383BD0 /* InfoPlist.strings in Resources */, 340 | 73E1761A17DBBB730046504B /* Model1.sqlite in Resources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | /* End PBXResourcesBuildPhase section */ 345 | 346 | /* Begin PBXShellScriptBuildPhase section */ 347 | 739100DB17CBF03500383BD0 /* ShellScript */ = { 348 | isa = PBXShellScriptBuildPhase; 349 | buildActionMask = 2147483647; 350 | files = ( 351 | ); 352 | inputPaths = ( 353 | ); 354 | outputPaths = ( 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | shellPath = /bin/sh; 358 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 359 | }; 360 | /* End PBXShellScriptBuildPhase section */ 361 | 362 | /* Begin PBXSourcesBuildPhase section */ 363 | 739100B017CBF03500383BD0 /* Sources */ = { 364 | isa = PBXSourcesBuildPhase; 365 | buildActionMask = 2147483647; 366 | files = ( 367 | 739100C417CBF03500383BD0 /* main.m in Sources */, 368 | 739100C817CBF03500383BD0 /* MHWAppDelegate.m in Sources */, 369 | 739100D117CBF03500383BD0 /* MHWViewController.m in Sources */, 370 | 739100F817CBF06000383BD0 /* MHWCoreDataController.m in Sources */, 371 | 739100FE17CBF13800383BD0 /* Model.xcdatamodeld in Sources */, 372 | 7391010417CBF26600383BD0 /* NSFileManager+MHWAdditions.m in Sources */, 373 | 73BD5FE817CD36BA003D1AB8 /* MHWBookToBookPolicy.m in Sources */, 374 | 73C2046B17D1124B0051D6BD /* MHWMigrationManager.m in Sources */, 375 | 73BFFFD917D3AAED0094E0BB /* Model1_to_Model2.xcmappingmodel in Sources */, 376 | 73BFFFDC17D3AEB40094E0BB /* Model2_to_Model3.xcmappingmodel in Sources */, 377 | 73BFFFE217D3B4510094E0BB /* NSMigrationManager+Lookup.m in Sources */, 378 | 73C2EBF017DB972C00855DA5 /* NSManagedObjectModel+MHWAdditions.m in Sources */, 379 | 73C2EBF317DBACAD00855DA5 /* Model2_to_Model3_User.xcmappingmodel in Sources */, 380 | ); 381 | runOnlyForDeploymentPostprocessing = 0; 382 | }; 383 | 739100D817CBF03500383BD0 /* Sources */ = { 384 | isa = PBXSourcesBuildPhase; 385 | buildActionMask = 2147483647; 386 | files = ( 387 | 739100EC17CBF03500383BD0 /* MHWMigrationFromModel1Tests.m in Sources */, 388 | 738AC53017D26D01004DE3E5 /* MHWCoreDataTests.m in Sources */, 389 | ); 390 | runOnlyForDeploymentPostprocessing = 0; 391 | }; 392 | /* End PBXSourcesBuildPhase section */ 393 | 394 | /* Begin PBXTargetDependency section */ 395 | 739100E317CBF03500383BD0 /* PBXTargetDependency */ = { 396 | isa = PBXTargetDependency; 397 | target = 739100B317CBF03500383BD0 /* BookMigration */; 398 | targetProxy = 739100E217CBF03500383BD0 /* PBXContainerItemProxy */; 399 | }; 400 | /* End PBXTargetDependency section */ 401 | 402 | /* Begin PBXVariantGroup section */ 403 | 739100C017CBF03500383BD0 /* InfoPlist.strings */ = { 404 | isa = PBXVariantGroup; 405 | children = ( 406 | 739100C117CBF03500383BD0 /* en */, 407 | ); 408 | name = InfoPlist.strings; 409 | sourceTree = ""; 410 | }; 411 | 739100D217CBF03500383BD0 /* MHWViewController_iPhone.xib */ = { 412 | isa = PBXVariantGroup; 413 | children = ( 414 | 739100D317CBF03500383BD0 /* en */, 415 | ); 416 | name = MHWViewController_iPhone.xib; 417 | sourceTree = ""; 418 | }; 419 | 739100D517CBF03500383BD0 /* MHWViewController_iPad.xib */ = { 420 | isa = PBXVariantGroup; 421 | children = ( 422 | 739100D617CBF03500383BD0 /* en */, 423 | ); 424 | name = MHWViewController_iPad.xib; 425 | sourceTree = ""; 426 | }; 427 | 739100E717CBF03500383BD0 /* InfoPlist.strings */ = { 428 | isa = PBXVariantGroup; 429 | children = ( 430 | 739100E817CBF03500383BD0 /* en */, 431 | ); 432 | name = InfoPlist.strings; 433 | sourceTree = ""; 434 | }; 435 | /* End PBXVariantGroup section */ 436 | 437 | /* Begin XCBuildConfiguration section */ 438 | 739100ED17CBF03500383BD0 /* Debug */ = { 439 | isa = XCBuildConfiguration; 440 | buildSettings = { 441 | ALWAYS_SEARCH_USER_PATHS = NO; 442 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 443 | CLANG_CXX_LIBRARY = "libc++"; 444 | CLANG_ENABLE_OBJC_ARC = YES; 445 | CLANG_WARN_CONSTANT_CONVERSION = YES; 446 | CLANG_WARN_EMPTY_BODY = YES; 447 | CLANG_WARN_ENUM_CONVERSION = YES; 448 | CLANG_WARN_INT_CONVERSION = YES; 449 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 450 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 451 | COPY_PHASE_STRIP = NO; 452 | GCC_C_LANGUAGE_STANDARD = gnu99; 453 | GCC_DYNAMIC_NO_PIC = NO; 454 | GCC_OPTIMIZATION_LEVEL = 0; 455 | GCC_PREPROCESSOR_DEFINITIONS = ( 456 | "DEBUG=1", 457 | "$(inherited)", 458 | ); 459 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 460 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 461 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 462 | GCC_WARN_UNUSED_VARIABLE = YES; 463 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 464 | ONLY_ACTIVE_ARCH = YES; 465 | SDKROOT = iphoneos; 466 | TARGETED_DEVICE_FAMILY = "1,2"; 467 | }; 468 | name = Debug; 469 | }; 470 | 739100EE17CBF03500383BD0 /* Release */ = { 471 | isa = XCBuildConfiguration; 472 | buildSettings = { 473 | ALWAYS_SEARCH_USER_PATHS = NO; 474 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 475 | CLANG_CXX_LIBRARY = "libc++"; 476 | CLANG_ENABLE_OBJC_ARC = YES; 477 | CLANG_WARN_CONSTANT_CONVERSION = YES; 478 | CLANG_WARN_EMPTY_BODY = YES; 479 | CLANG_WARN_ENUM_CONVERSION = YES; 480 | CLANG_WARN_INT_CONVERSION = YES; 481 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 482 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 483 | COPY_PHASE_STRIP = YES; 484 | GCC_C_LANGUAGE_STANDARD = gnu99; 485 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 486 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 487 | GCC_WARN_UNUSED_VARIABLE = YES; 488 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 489 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 490 | SDKROOT = iphoneos; 491 | TARGETED_DEVICE_FAMILY = "1,2"; 492 | VALIDATE_PRODUCT = YES; 493 | }; 494 | name = Release; 495 | }; 496 | 739100F017CBF03500383BD0 /* Debug */ = { 497 | isa = XCBuildConfiguration; 498 | buildSettings = { 499 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 500 | GCC_PREFIX_HEADER = "BookMigration/BookMigration-Prefix.pch"; 501 | INFOPLIST_FILE = "BookMigration/BookMigration-Info.plist"; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | WRAPPER_EXTENSION = app; 504 | }; 505 | name = Debug; 506 | }; 507 | 739100F117CBF03500383BD0 /* Release */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 511 | GCC_PREFIX_HEADER = "BookMigration/BookMigration-Prefix.pch"; 512 | INFOPLIST_FILE = "BookMigration/BookMigration-Info.plist"; 513 | PRODUCT_NAME = "$(TARGET_NAME)"; 514 | WRAPPER_EXTENSION = app; 515 | }; 516 | name = Release; 517 | }; 518 | 739100F317CBF03500383BD0 /* Debug */ = { 519 | isa = XCBuildConfiguration; 520 | buildSettings = { 521 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BookMigration.app/BookMigration"; 522 | FRAMEWORK_SEARCH_PATHS = ( 523 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 524 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 525 | ); 526 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 527 | GCC_PREFIX_HEADER = "BookMigration/BookMigration-Prefix.pch"; 528 | INFOPLIST_FILE = "BookMigrationTests/BookMigrationTests-Info.plist"; 529 | PRODUCT_NAME = "$(TARGET_NAME)"; 530 | TEST_HOST = "$(BUNDLE_LOADER)"; 531 | WRAPPER_EXTENSION = octest; 532 | }; 533 | name = Debug; 534 | }; 535 | 739100F417CBF03500383BD0 /* Release */ = { 536 | isa = XCBuildConfiguration; 537 | buildSettings = { 538 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BookMigration.app/BookMigration"; 539 | FRAMEWORK_SEARCH_PATHS = ( 540 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 541 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 542 | ); 543 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 544 | GCC_PREFIX_HEADER = "BookMigration/BookMigration-Prefix.pch"; 545 | INFOPLIST_FILE = "BookMigrationTests/BookMigrationTests-Info.plist"; 546 | PRODUCT_NAME = "$(TARGET_NAME)"; 547 | TEST_HOST = "$(BUNDLE_LOADER)"; 548 | WRAPPER_EXTENSION = octest; 549 | }; 550 | name = Release; 551 | }; 552 | /* End XCBuildConfiguration section */ 553 | 554 | /* Begin XCConfigurationList section */ 555 | 739100AF17CBF03500383BD0 /* Build configuration list for PBXProject "BookMigration" */ = { 556 | isa = XCConfigurationList; 557 | buildConfigurations = ( 558 | 739100ED17CBF03500383BD0 /* Debug */, 559 | 739100EE17CBF03500383BD0 /* Release */, 560 | ); 561 | defaultConfigurationIsVisible = 0; 562 | defaultConfigurationName = Release; 563 | }; 564 | 739100EF17CBF03500383BD0 /* Build configuration list for PBXNativeTarget "BookMigration" */ = { 565 | isa = XCConfigurationList; 566 | buildConfigurations = ( 567 | 739100F017CBF03500383BD0 /* Debug */, 568 | 739100F117CBF03500383BD0 /* Release */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | 739100F217CBF03500383BD0 /* Build configuration list for PBXNativeTarget "BookMigrationTests" */ = { 574 | isa = XCConfigurationList; 575 | buildConfigurations = ( 576 | 739100F317CBF03500383BD0 /* Debug */, 577 | 739100F417CBF03500383BD0 /* Release */, 578 | ); 579 | defaultConfigurationIsVisible = 0; 580 | defaultConfigurationName = Release; 581 | }; 582 | /* End XCConfigurationList section */ 583 | 584 | /* Begin XCVersionGroup section */ 585 | 739100FC17CBF13800383BD0 /* Model.xcdatamodeld */ = { 586 | isa = XCVersionGroup; 587 | children = ( 588 | 73BFFFDA17D3AB2A0094E0BB /* Model3.xcdatamodel */, 589 | 7391010517CBF42000383BD0 /* Model2.xcdatamodel */, 590 | 739100FD17CBF13800383BD0 /* Model1.xcdatamodel */, 591 | ); 592 | currentVersion = 73BFFFDA17D3AB2A0094E0BB /* Model3.xcdatamodel */; 593 | path = Model.xcdatamodeld; 594 | sourceTree = ""; 595 | versionGroupType = wrapper.xcdatamodel; 596 | }; 597 | /* End XCVersionGroup section */ 598 | }; 599 | rootObject = 739100AC17CBF03500383BD0 /* Project object */; 600 | } 601 | -------------------------------------------------------------------------------- /BookMigration.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BookMigration.xcodeproj/project.xcworkspace/xcuserdata/hwaxxer.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-4-core-data-migration/02002c93a4531ebcf8f40ee4c77986d01abc790e/BookMigration.xcodeproj/project.xcworkspace/xcuserdata/hwaxxer.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /BookMigration.xcodeproj/project.xcworkspace/xcuserdata/hwaxxer.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BookMigration.xcodeproj/xcuserdata/hwaxxer.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /BookMigration.xcodeproj/xcuserdata/hwaxxer.xcuserdatad/xcschemes/BookMigration.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 74 | 75 | 78 | 79 | 80 | 81 | 82 | 83 | 89 | 90 | 96 | 97 | 98 | 99 | 101 | 102 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /BookMigration.xcodeproj/xcuserdata/hwaxxer.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | BookMigration.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 739100B317CBF03500383BD0 16 | 17 | primary 18 | 19 | 20 | 739100DC17CBF03500383BD0 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /BookMigration/BookMigration-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.hwaxxer.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /BookMigration/BookMigration-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'BookMigration' target in the 'BookMigration' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #import 15 | #endif 16 | -------------------------------------------------------------------------------- /BookMigration/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-4-core-data-migration/02002c93a4531ebcf8f40ee4c77986d01abc790e/BookMigration/Default-568h@2x.png -------------------------------------------------------------------------------- /BookMigration/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-4-core-data-migration/02002c93a4531ebcf8f40ee4c77986d01abc790e/BookMigration/Default.png -------------------------------------------------------------------------------- /BookMigration/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-4-core-data-migration/02002c93a4531ebcf8f40ee4c77986d01abc790e/BookMigration/Default@2x.png -------------------------------------------------------------------------------- /BookMigration/MHWAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWAppDelegate.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MHWViewController; 12 | 13 | @interface MHWAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) MHWViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /BookMigration/MHWAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWAppDelegate.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWAppDelegate.h" 10 | 11 | #import "MHWViewController.h" 12 | #import "MHWCoreDataController.h" 13 | 14 | @implementation MHWAppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | 19 | // Fake an old store so that we migrate on each launch 20 | NSFileManager *fileManager = [NSFileManager defaultManager]; 21 | for (NSBundle *bundle in [NSBundle allBundles]) { 22 | NSURL *oldStoreURL = [bundle URLForResource:@"Model1" withExtension:@"sqlite"]; 23 | NSLog(@"old: %@", oldStoreURL); 24 | if (oldStoreURL) { 25 | [fileManager removeItemAtURL:[MHWCoreDataController sharedInstance].sourceStoreURL error:nil]; 26 | [fileManager copyItemAtURL:oldStoreURL 27 | toURL:[MHWCoreDataController sharedInstance].sourceStoreURL 28 | error:nil]; 29 | break; 30 | } 31 | } 32 | 33 | if ([MHWCoreDataController sharedInstance].isMigrationNeeded) { 34 | [[MHWCoreDataController sharedInstance] migrate:nil]; 35 | } 36 | 37 | return YES; 38 | 39 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 40 | // Override point for customization after application launch. 41 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 42 | self.viewController = [[MHWViewController alloc] initWithNibName:@"MHWViewController_iPhone" bundle:nil]; 43 | } else { 44 | self.viewController = [[MHWViewController alloc] initWithNibName:@"MHWViewController_iPad" bundle:nil]; 45 | } 46 | self.window.rootViewController = self.viewController; 47 | [self.window makeKeyAndVisible]; 48 | 49 | 50 | return YES; 51 | } 52 | 53 | - (void)populateLegacyDatabase 54 | { 55 | NSManagedObjectContext *moc = [MHWCoreDataController sharedInstance].managedObjectContext; 56 | 57 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Book"]; 58 | NSArray *result = [moc executeFetchRequest:request error:nil]; 59 | NSLog(@"results: %@", result); 60 | 61 | for (id mo in result) { 62 | [moc deleteObject:mo]; 63 | } 64 | 65 | NSManagedObject *mo; 66 | NSEntityDescription *entityDescription; 67 | 68 | entityDescription = [NSEntityDescription entityForName:@"User" inManagedObjectContext:moc]; 69 | mo = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 70 | [mo setValue:@(1) forKey:@"userId"]; 71 | NSManagedObject *user = mo; 72 | 73 | entityDescription = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:moc]; 74 | mo = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 75 | [mo setValue:@"Franz Kafka" forKey:@"authorName"]; 76 | [mo setValue:@"Metamorphosis" forKey:@"title"]; 77 | [mo setValue:[[mo valueForKey:@"title"] stringByAppendingPathExtension:@"file"] forKey:@"fileURL"]; 78 | [mo setValue:user forKey:@"user"]; 79 | 80 | mo = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 81 | [mo setValue:@"Franz Kafka" forKey:@"authorName"]; 82 | [mo setValue:@"The Trial" forKey:@"title"]; 83 | [mo setValue:[[mo valueForKey:@"title"] stringByAppendingPathExtension:@"file"] forKey:@"fileURL"]; 84 | [mo setValue:user forKey:@"user"]; 85 | 86 | mo = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 87 | [mo setValue:@"Witold Gombrowicz" forKey:@"authorName"]; 88 | [mo setValue:@"Cosmos" forKey:@"title"]; 89 | [mo setValue:[[mo valueForKey:@"title"] stringByAppendingPathExtension:@"file"] forKey:@"fileURL"]; 90 | [mo setValue:user forKey:@"user"]; 91 | 92 | mo = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 93 | [mo setValue:@"Thomas Bernhard" forKey:@"authorName"]; 94 | [mo setValue:@"Extinction" forKey:@"title"]; 95 | [mo setValue:[[mo valueForKey:@"title"] stringByAppendingPathExtension:@"file"] forKey:@"fileURL"]; 96 | [mo setValue:user forKey:@"user"]; 97 | 98 | [moc save:nil]; 99 | 100 | request = [[NSFetchRequest alloc] initWithEntityName:@"Book"]; 101 | result = [moc executeFetchRequest:request error:nil]; 102 | NSLog(@"results: %@", result); 103 | for (id mo in result) { 104 | NSLog(@"mo: %@", mo); 105 | } 106 | 107 | } 108 | 109 | 110 | - (void)applicationWillResignActive:(UIApplication *)application 111 | { 112 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 113 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 114 | } 115 | 116 | - (void)applicationDidEnterBackground:(UIApplication *)application 117 | { 118 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 119 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 120 | } 121 | 122 | - (void)applicationWillEnterForeground:(UIApplication *)application 123 | { 124 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 125 | } 126 | 127 | - (void)applicationDidBecomeActive:(UIApplication *)application 128 | { 129 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 130 | } 131 | 132 | - (void)applicationWillTerminate:(UIApplication *)application 133 | { 134 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /BookMigration/MHWBookToBookPolicy.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWBookToBookPolicy.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/27/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MHWBookToBookPolicy : NSEntityMigrationPolicy 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /BookMigration/MHWBookToBookPolicy.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWBookToBookPolicy.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/27/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWBookToBookPolicy.h" 10 | #import "NSMigrationManager+Lookup.h" 11 | 12 | @implementation MHWBookToBookPolicy 13 | 14 | - (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sourceInstance 15 | entityMapping:(NSEntityMapping *)mapping 16 | manager:(NSMigrationManager *)manager 17 | error:(NSError *__autoreleasing *)error 18 | { 19 | NSNumber *modelVersion = [mapping.userInfo valueForKey:@"modelVersion"]; 20 | if (modelVersion.integerValue == 2 || modelVersion.integerValue == 3) { 21 | 22 | NSMutableArray *sourceKeys = [sourceInstance.entity.attributesByName.allKeys mutableCopy]; 23 | NSDictionary *sourceValues = [sourceInstance dictionaryWithValuesForKeys:sourceKeys]; 24 | 25 | NSManagedObject *destinationInstance = [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] 26 | inManagedObjectContext:[manager destinationContext]]; 27 | NSArray *destinationKeys = destinationInstance.entity.attributesByName.allKeys; 28 | 29 | for (NSString *key in destinationKeys) { 30 | id value = [sourceValues valueForKey:key]; 31 | // Avoid NULL values 32 | if (value && ![value isEqual:[NSNull null]]) { 33 | [destinationInstance setValue:value forKey:key]; 34 | } 35 | } 36 | 37 | if (modelVersion.integerValue == 2) { 38 | // Check if we've already created the authors lookup 39 | NSMutableDictionary *authorLookup = [manager lookupWithKey:@"authors"]; 40 | // Check if we've already created this author 41 | NSString *authorName = [sourceInstance valueForKey:@"authorName"]; 42 | NSManagedObject *author = [authorLookup valueForKey:authorName]; 43 | if (!author) { 44 | // Create the author 45 | author = [NSEntityDescription insertNewObjectForEntityForName:@"Author" 46 | inManagedObjectContext:[manager destinationContext]]; 47 | 48 | [author setValue:authorName forKey:@"name"]; 49 | 50 | // Populate lookup for reuse 51 | [authorLookup setValue:author forKey:authorName]; 52 | } 53 | [destinationInstance performSelector:@selector(addAuthorsObject:) withObject:author]; 54 | } else if (modelVersion.integerValue == 3) { 55 | NSArray *sourceUsers = [sourceInstance valueForKey:@"users"]; 56 | for (NSManagedObject *sourceUser in sourceUsers) { 57 | 58 | NSManagedObject *file = [NSEntityDescription insertNewObjectForEntityForName:@"File" 59 | inManagedObjectContext:manager.destinationContext]; 60 | [file setValue:[sourceInstance valueForKey:@"fileURL"] forKey:@"fileURL"]; 61 | [file setValue:destinationInstance forKey:@"book"]; 62 | 63 | NSInteger userId = [[sourceUser valueForKey:@"userId"] integerValue]; 64 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"]; 65 | request.predicate = [NSPredicate predicateWithFormat:@"userId = %d", userId]; 66 | NSManagedObject *destinationUser = [[manager.destinationContext executeFetchRequest:request error:nil] lastObject]; 67 | [file setValue:destinationUser forKey:@"user"]; 68 | } 69 | } 70 | [manager associateSourceInstance:sourceInstance 71 | withDestinationInstance:destinationInstance 72 | forEntityMapping:mapping]; 73 | 74 | return YES; 75 | } else { 76 | return [super createDestinationInstancesForSourceInstance:sourceInstance 77 | entityMapping:mapping 78 | manager:manager 79 | error:error]; 80 | } 81 | } 82 | 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /BookMigration/MHWCoreDataController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWCoreDataController.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "MHWMigrationManager.h" 12 | 13 | @interface MHWCoreDataController : NSObject 14 | 15 | + (MHWCoreDataController *)sharedInstance; 16 | 17 | - (BOOL)isMigrationNeeded; 18 | - (BOOL)migrate:(NSError *__autoreleasing *)error; 19 | 20 | - (NSURL *)sourceStoreURL; 21 | 22 | @property (nonatomic, readonly, strong) NSManagedObjectModel *managedObjectModel; 23 | @property (nonatomic, readonly, strong) NSManagedObjectContext *managedObjectContext; 24 | @property (nonatomic, readonly, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /BookMigration/MHWCoreDataController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWCoreDataController.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWCoreDataController.h" 10 | #import "NSFileManager+MHWAdditions.h" 11 | #import "MHWMigrationManager.h" 12 | #import "NSManagedObjectModel+MHWAdditions.h" 13 | 14 | @interface MHWCoreDataController () 15 | 16 | @property (nonatomic, readwrite, strong) NSManagedObjectModel *managedObjectModel; 17 | @property (nonatomic, readwrite, strong) NSManagedObjectContext *managedObjectContext; 18 | @property (nonatomic, readwrite, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator; 19 | @end 20 | 21 | @implementation MHWCoreDataController 22 | 23 | + (MHWCoreDataController *)sharedInstance 24 | { 25 | static MHWCoreDataController *sharedInstance = nil; 26 | static dispatch_once_t onceToken; 27 | dispatch_once(&onceToken, ^{ 28 | sharedInstance = [MHWCoreDataController new]; 29 | }); 30 | return sharedInstance; 31 | } 32 | 33 | - (NSManagedObjectContext *)managedObjectContext 34 | { 35 | if (_managedObjectContext != nil) { 36 | return _managedObjectContext; 37 | } 38 | 39 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 40 | _managedObjectContext = [[NSManagedObjectContext alloc] init]; 41 | _managedObjectContext.persistentStoreCoordinator = coordinator; 42 | 43 | return _managedObjectContext; 44 | } 45 | 46 | - (NSManagedObjectModel *)managedObjectModel 47 | { 48 | if (_managedObjectModel != nil) { 49 | return _managedObjectModel; 50 | } 51 | 52 | NSString *momPath = [[NSBundle mainBundle] pathForResource:@"Model" 53 | ofType:@"momd"]; 54 | 55 | if (!momPath) { 56 | momPath = [[NSBundle mainBundle] pathForResource:@"Model" 57 | ofType:@"mom"]; 58 | } 59 | 60 | NSURL *url = [NSURL fileURLWithPath:momPath]; 61 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url]; 62 | return _managedObjectModel; 63 | } 64 | 65 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator 66 | { 67 | if (_persistentStoreCoordinator != nil) { 68 | return _persistentStoreCoordinator; 69 | } 70 | 71 | NSError *error = nil; 72 | 73 | NSDictionary *options = nil; 74 | if ([self isMigrationNeeded]) { 75 | options = @{ 76 | NSInferMappingModelAutomaticallyOption: @YES, 77 | NSSQLitePragmasOption: @{@"journal_mode": @"DELETE"} 78 | }; 79 | } else { 80 | options = @{ 81 | NSInferMappingModelAutomaticallyOption: @YES, 82 | NSSQLitePragmasOption: @{@"journal_mode": @"WAL"} 83 | }; 84 | } 85 | 86 | NSManagedObjectModel *mom = [self managedObjectModel]; 87 | 88 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 89 | 90 | if (![_persistentStoreCoordinator addPersistentStoreWithType:[self sourceStoreType] 91 | configuration:nil 92 | URL:[self sourceStoreURL] 93 | options:options 94 | error:&error]) { 95 | 96 | NSLog(@"error: %@", error); 97 | NSFileManager *fileManager = [NSFileManager new]; 98 | [fileManager removeItemAtPath:[self sourceStoreURL].path error:nil]; 99 | 100 | [[[UIAlertView alloc] initWithTitle:@"Ouch" 101 | message:error.localizedDescription 102 | delegate:nil 103 | cancelButtonTitle:@"OK" 104 | otherButtonTitles:nil] show]; 105 | } 106 | 107 | return _persistentStoreCoordinator; 108 | } 109 | 110 | - (NSURL *)sourceStoreURL 111 | { 112 | return [[NSFileManager urlToApplicationSupportDirectory] URLByAppendingPathComponent:@"Model.sqlite"]; 113 | } 114 | 115 | - (NSString *)sourceStoreType 116 | { 117 | return NSSQLiteStoreType; 118 | } 119 | 120 | - (NSDictionary *)sourceMetadata:(NSError **)error 121 | { 122 | return [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:[self sourceStoreType] 123 | URL:[self sourceStoreURL] 124 | error:error]; 125 | } 126 | 127 | - (BOOL)isMigrationNeeded 128 | { 129 | NSError *error = nil; 130 | 131 | // Check if we need to migrate 132 | NSDictionary *sourceMetadata = [self sourceMetadata:&error]; 133 | BOOL isMigrationNeeded = NO; 134 | 135 | if (sourceMetadata != nil) { 136 | NSManagedObjectModel *destinationModel = [self managedObjectModel]; 137 | // Migration is needed if destinationModel is NOT compatible 138 | isMigrationNeeded = ![destinationModel isConfiguration:nil 139 | compatibleWithStoreMetadata:sourceMetadata]; 140 | } 141 | NSLog(@"isMigrationNeeded: %d", isMigrationNeeded); 142 | return isMigrationNeeded; 143 | } 144 | 145 | - (BOOL)migrate:(NSError *__autoreleasing *)error 146 | { 147 | // Enable migrations to run even while user exits app 148 | __block UIBackgroundTaskIdentifier bgTask; 149 | bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 150 | [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 151 | bgTask = UIBackgroundTaskInvalid; 152 | }]; 153 | 154 | MHWMigrationManager *migrationManager = [MHWMigrationManager new]; 155 | migrationManager.delegate = self; 156 | 157 | BOOL OK = [migrationManager progressivelyMigrateURL:[self sourceStoreURL] 158 | ofType:[self sourceStoreType] 159 | toModel:[self managedObjectModel] 160 | error:error]; 161 | if (OK) { 162 | NSLog(@"migration complete"); 163 | } 164 | 165 | // Mark it as invalid 166 | [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 167 | bgTask = UIBackgroundTaskInvalid; 168 | return OK; 169 | } 170 | 171 | 172 | #pragma mark - 173 | #pragma mark - MHWMigrationManagerDelegate 174 | 175 | - (void)migrationManager:(MHWMigrationManager *)migrationManager migrationProgress:(float)migrationProgress 176 | { 177 | NSLog(@"migration progress: %f", migrationProgress); 178 | } 179 | 180 | - (NSArray *)migrationManager:(MHWMigrationManager *)migrationManager 181 | mappingModelsForSourceModel:(NSManagedObjectModel *)sourceModel 182 | { 183 | NSMutableArray *mappingModels = [@[] mutableCopy]; 184 | NSString *modelName = [sourceModel mhw_modelName]; 185 | if ([modelName isEqual:@"Model2"]) { 186 | // Migrating to Model3 187 | NSArray *urls = [[NSBundle bundleForClass:[self class]] 188 | URLsForResourcesWithExtension:@"cdm" 189 | subdirectory:nil]; 190 | for (NSURL *url in urls) { 191 | if ([url.lastPathComponent rangeOfString:@"Model2_to_Model"].length != 0) { 192 | NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:url]; 193 | if ([url.lastPathComponent rangeOfString:@"User"].length != 0) { 194 | // User first so we create new relationship 195 | [mappingModels insertObject:mappingModel atIndex:0]; 196 | } else { 197 | [mappingModels addObject:mappingModel]; 198 | } 199 | } 200 | } 201 | } 202 | return mappingModels; 203 | } 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /BookMigration/MHWMigrationManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWMigrationManager.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/30/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MHWMigrationManager; 12 | 13 | @protocol MHWMigrationManagerDelegate 14 | 15 | @optional 16 | - (void)migrationManager:(MHWMigrationManager *)migrationManager migrationProgress:(float)migrationProgress; 17 | - (NSArray *)migrationManager:(MHWMigrationManager *)migrationManager mappingModelsForSourceModel:(NSManagedObjectModel *)sourceModel; 18 | 19 | @end 20 | 21 | @interface MHWMigrationManager : NSObject 22 | 23 | - (BOOL)progressivelyMigrateURL:(NSURL *)sourceStoreURL 24 | ofType:(NSString *)type 25 | toModel:(NSManagedObjectModel *)finalModel 26 | error:(NSError **)error; 27 | 28 | @property (nonatomic, weak) id delegate; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /BookMigration/MHWMigrationManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWMigrationManager.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/30/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWMigrationManager.h" 10 | 11 | @implementation MHWMigrationManager 12 | 13 | #pragma mark - 14 | #pragma mark - Migration 15 | 16 | - (BOOL)progressivelyMigrateURL:(NSURL *)sourceStoreURL 17 | ofType:(NSString *)type 18 | toModel:(NSManagedObjectModel *)finalModel 19 | error:(NSError **)error 20 | { 21 | NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:type 22 | URL:sourceStoreURL 23 | error:error]; 24 | if (!sourceMetadata) { 25 | return NO; 26 | } 27 | if ([finalModel isConfiguration:nil 28 | compatibleWithStoreMetadata:sourceMetadata]) { 29 | if (NULL != error) { 30 | *error = nil; 31 | } 32 | return YES; 33 | } 34 | NSManagedObjectModel *sourceModel = [self sourceModelForSourceMetadata:sourceMetadata]; 35 | NSManagedObjectModel *destinationModel = nil; 36 | NSMappingModel *mappingModel = nil; 37 | NSString *modelName = nil; 38 | if (![self getDestinationModel:&destinationModel 39 | mappingModel:&mappingModel 40 | modelName:&modelName 41 | forSourceModel:sourceModel 42 | error:error]) { 43 | return NO; 44 | } 45 | 46 | NSArray *mappingModels = @[mappingModel]; 47 | if ([self.delegate respondsToSelector:@selector(migrationManager:mappingModelsForSourceModel:)]) { 48 | NSArray *explicitMappingModels = [self.delegate migrationManager:self mappingModelsForSourceModel:sourceModel]; 49 | if (0 < explicitMappingModels.count) { 50 | mappingModels = explicitMappingModels; 51 | } 52 | } 53 | NSURL *destinationStoreURL = [self destinationStoreURLWithSourceStoreURL:sourceStoreURL 54 | modelName:modelName]; 55 | NSMigrationManager *manager = [[NSMigrationManager alloc] initWithSourceModel:sourceModel 56 | destinationModel:destinationModel]; 57 | [manager addObserver:self 58 | forKeyPath:@"migrationProgress" 59 | options:NSKeyValueObservingOptionNew 60 | context:nil]; 61 | BOOL didMigrate = NO; 62 | for (NSMappingModel *mappingModel in mappingModels) { 63 | didMigrate = [manager migrateStoreFromURL:sourceStoreURL 64 | type:type 65 | options:nil 66 | withMappingModel:mappingModel 67 | toDestinationURL:destinationStoreURL 68 | destinationType:type 69 | destinationOptions:nil 70 | error:error]; 71 | } 72 | [manager removeObserver:self 73 | forKeyPath:@"migrationProgress"]; 74 | if (!didMigrate) { 75 | return NO; 76 | } 77 | // Migration was successful, move the files around to preserve the source in case things go bad 78 | if (![self backupSourceStoreAtURL:sourceStoreURL 79 | movingDestinationStoreAtURL:destinationStoreURL 80 | error:error]) { 81 | return NO; 82 | } 83 | // We may not be at the "current" model yet, so recurse 84 | return [self progressivelyMigrateURL:sourceStoreURL 85 | ofType:type 86 | toModel:finalModel 87 | error:error]; 88 | } 89 | 90 | - (NSArray *)modelPaths 91 | { 92 | //Find all of the mom and momd files in the Resources directory 93 | NSMutableArray *modelPaths = [NSMutableArray array]; 94 | NSArray *momdArray = [[NSBundle mainBundle] pathsForResourcesOfType:@"momd" 95 | inDirectory:nil]; 96 | for (NSString *momdPath in momdArray) { 97 | NSString *resourceSubpath = [momdPath lastPathComponent]; 98 | NSArray *array = [[NSBundle mainBundle] pathsForResourcesOfType:@"mom" 99 | inDirectory:resourceSubpath]; 100 | [modelPaths addObjectsFromArray:array]; 101 | } 102 | NSArray *otherModels = [[NSBundle mainBundle] pathsForResourcesOfType:@"mom" 103 | inDirectory:nil]; 104 | [modelPaths addObjectsFromArray:otherModels]; 105 | return modelPaths; 106 | } 107 | 108 | - (NSManagedObjectModel *)sourceModelForSourceMetadata:(NSDictionary *)sourceMetadata 109 | { 110 | return [NSManagedObjectModel mergedModelFromBundles:@[[NSBundle mainBundle]] 111 | forStoreMetadata:sourceMetadata]; 112 | } 113 | 114 | - (BOOL)getDestinationModel:(NSManagedObjectModel **)destinationModel 115 | mappingModel:(NSMappingModel **)mappingModel 116 | modelName:(NSString **)modelName 117 | forSourceModel:(NSManagedObjectModel *)sourceModel 118 | error:(NSError **)error 119 | { 120 | NSArray *modelPaths = [self modelPaths]; 121 | if (!modelPaths.count) { 122 | //Throw an error if there are no models 123 | if (NULL != error) { 124 | *error = [NSError errorWithDomain:@"Zarra" 125 | code:8001 126 | userInfo:@{ NSLocalizedDescriptionKey : @"No models found!" }]; 127 | } 128 | return NO; 129 | } 130 | 131 | //See if we can find a matching destination model 132 | NSManagedObjectModel *model = nil; 133 | NSMappingModel *mapping = nil; 134 | NSString *modelPath = nil; 135 | for (modelPath in modelPaths) { 136 | model = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]]; 137 | mapping = [NSMappingModel mappingModelFromBundles:@[[NSBundle mainBundle]] 138 | forSourceModel:sourceModel 139 | destinationModel:model]; 140 | //If we found a mapping model then proceed 141 | if (mapping) { 142 | break; 143 | } 144 | } 145 | //We have tested every model, if nil here we failed 146 | if (!mapping) { 147 | if (NULL != error) { 148 | *error = [NSError errorWithDomain:@"Zarra" 149 | code:8001 150 | userInfo:@{ NSLocalizedDescriptionKey : @"No mapping model found in bundle" }]; 151 | } 152 | return NO; 153 | } else { 154 | *destinationModel = model; 155 | *mappingModel = mapping; 156 | *modelName = modelPath.lastPathComponent.stringByDeletingPathExtension; 157 | } 158 | return YES; 159 | } 160 | 161 | - (NSURL *)destinationStoreURLWithSourceStoreURL:(NSURL *)sourceStoreURL 162 | modelName:(NSString *)modelName 163 | { 164 | // We have a mapping model, time to migrate 165 | NSString *storeExtension = sourceStoreURL.path.pathExtension; 166 | NSString *storePath = sourceStoreURL.path.stringByDeletingPathExtension; 167 | // Build a path to write the new store 168 | storePath = [NSString stringWithFormat:@"%@.%@.%@", storePath, modelName, storeExtension]; 169 | return [NSURL fileURLWithPath:storePath]; 170 | } 171 | 172 | - (BOOL)backupSourceStoreAtURL:(NSURL *)sourceStoreURL 173 | movingDestinationStoreAtURL:(NSURL *)destinationStoreURL 174 | error:(NSError **)error 175 | { 176 | NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString]; 177 | NSString *backupPath = [NSTemporaryDirectory() stringByAppendingPathComponent:guid]; 178 | 179 | NSFileManager *fileManager = [NSFileManager defaultManager]; 180 | if (![fileManager moveItemAtPath:sourceStoreURL.path 181 | toPath:backupPath 182 | error:error]) { 183 | //Failed to copy the file 184 | return NO; 185 | } 186 | //Move the destination to the source path 187 | if (![fileManager moveItemAtPath:destinationStoreURL.path 188 | toPath:sourceStoreURL.path 189 | error:error]) { 190 | //Try to back out the source move first, no point in checking it for errors 191 | [fileManager moveItemAtPath:backupPath 192 | toPath:sourceStoreURL.path 193 | error:nil]; 194 | return NO; 195 | } 196 | return YES; 197 | } 198 | 199 | - (void)observeValueForKeyPath:(NSString *)keyPath 200 | ofObject:(id)object 201 | change:(NSDictionary *)change 202 | context:(void *)context 203 | { 204 | if ([keyPath isEqualToString:@"migrationProgress"]) { 205 | NSLog(@"progress: %f", [object migrationProgress]); 206 | if ([self.delegate respondsToSelector:@selector(migrationManager:migrationProgress:)]) { 207 | [self.delegate migrationManager:self migrationProgress:[(NSMigrationManager *)object migrationProgress]]; 208 | } 209 | } else { 210 | [super observeValueForKeyPath:keyPath 211 | ofObject:object 212 | change:change 213 | context:context]; 214 | } 215 | } 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /BookMigration/MHWUserToUserPolicy.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWUserToUserPolicy.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/1/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MHWUserToUserPolicy : NSEntityMigrationPolicy 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /BookMigration/MHWUserToUserPolicy.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWUserToUserPolicy.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/1/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWUserToUserPolicy.h" 10 | #import "NSMigrationManager+Lookup.h" 11 | 12 | @implementation MHWUserToUserPolicy 13 | 14 | - (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sourceInstance 15 | entityMapping:(NSEntityMapping *)mapping 16 | manager:(NSMigrationManager *)manager 17 | error:(NSError *__autoreleasing *)error 18 | { 19 | NSNumber *modelVersion = [mapping.userInfo valueForKey:@"modelVersion"]; 20 | if (modelVersion.integerValue == 3) { 21 | NSManagedObject *destinationInstance = [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] 22 | inManagedObjectContext:[manager destinationContext]]; 23 | 24 | 25 | NSMutableArray *sourceKeys = [sourceInstance.entity.attributesByName.allKeys mutableCopy]; 26 | NSDictionary *sourceValues = [sourceInstance dictionaryWithValuesForKeys:sourceKeys]; 27 | 28 | NSArray *destinationKeys = destinationInstance.entity.attributesByName.allKeys; 29 | for (NSString *key in destinationKeys) { 30 | id value = [sourceValues valueForKey:key]; 31 | // Avoid NULL values 32 | if (value && ![value isEqual:[NSNull null]]) { 33 | [destinationInstance setValue:value forKey:key]; 34 | } 35 | } 36 | 37 | NSSet *books = [sourceInstance valueForKey:@"books"]; 38 | NSDictionary *filesLookup = [manager lookupWithKey:@"files"]; 39 | for (NSManagedObject *book in books) { 40 | NSString *bookObjectID = book.objectID.URIRepresentation.description; 41 | NSManagedObject *file = [filesLookup valueForKey:bookObjectID]; 42 | [file setValue:destinationInstance forKey:@"user"]; 43 | } 44 | 45 | [manager associateSourceInstance:sourceInstance 46 | withDestinationInstance:destinationInstance 47 | forEntityMapping:mapping]; 48 | return YES; 49 | } else { 50 | return [super createDestinationInstancesForSourceInstance:sourceInstance 51 | entityMapping:mapping 52 | manager:manager 53 | error:error]; 54 | } 55 | } 56 | @end 57 | -------------------------------------------------------------------------------- /BookMigration/MHWViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWViewController.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MHWViewController : UIViewController 12 | < 13 | UITableViewDataSource, 14 | UITableViewDelegate 15 | > 16 | 17 | @property (nonatomic, strong) IBOutlet UITableView *tableView; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /BookMigration/MHWViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWViewController.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWViewController.h" 10 | #import "MHWCoreDataController.h" 11 | 12 | @interface MHWViewController () 13 | 14 | @property (nonatomic, strong) NSFetchedResultsController *frc; 15 | 16 | @end 17 | 18 | @implementation MHWViewController 19 | 20 | static NSString *CellReuseIdentifier = @"Cell"; 21 | 22 | - (void)viewDidLoad 23 | { 24 | [super viewDidLoad]; 25 | // Do any additional setup after loading the view, typically from a nib. 26 | 27 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellReuseIdentifier]; 28 | 29 | [self.frc performFetch:nil]; 30 | [self.tableView reloadData]; 31 | } 32 | 33 | - (void)didReceiveMemoryWarning 34 | { 35 | [super didReceiveMemoryWarning]; 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | 40 | #pragma mark - 41 | #pragma mark - NSFetchedResultsController 42 | 43 | - (NSFetchedResultsController *)frc 44 | { 45 | if (!_frc) { 46 | 47 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"File"]; 48 | request.predicate = [NSPredicate predicateWithFormat:@"user.userId = 1"]; 49 | 50 | NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"book.title" ascending:NO]; 51 | request.sortDescriptors = @[sortDescriptor]; 52 | 53 | NSManagedObjectContext *moc = [MHWCoreDataController sharedInstance].managedObjectContext; 54 | _frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request 55 | managedObjectContext:moc 56 | sectionNameKeyPath:nil 57 | cacheName:nil]; 58 | _frc.delegate = self; 59 | } 60 | return _frc; 61 | } 62 | 63 | - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 64 | { 65 | [self.tableView beginUpdates]; 66 | } 67 | 68 | 69 | - (void)controller:(NSFetchedResultsController *)controller 70 | didChangeObject:(id)anObject 71 | atIndexPath:(NSIndexPath *)indexPath 72 | forChangeType:(NSFetchedResultsChangeType)type 73 | newIndexPath:(NSIndexPath *)newIndexPath 74 | { 75 | UITableView *tableView = self.tableView; 76 | 77 | switch (type) { 78 | case NSFetchedResultsChangeInsert: 79 | [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 80 | break; 81 | 82 | case NSFetchedResultsChangeDelete: 83 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 84 | break; 85 | 86 | case NSFetchedResultsChangeUpdate: 87 | [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 88 | break; 89 | 90 | case NSFetchedResultsChangeMove: 91 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 92 | [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 93 | break; 94 | } 95 | } 96 | 97 | 98 | - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 99 | 100 | switch(type) { 101 | 102 | case NSFetchedResultsChangeInsert: 103 | [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] 104 | withRowAnimation:UITableViewRowAnimationFade]; 105 | break; 106 | 107 | case NSFetchedResultsChangeDelete: 108 | [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] 109 | withRowAnimation:UITableViewRowAnimationFade]; 110 | break; 111 | } 112 | } 113 | 114 | 115 | - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 116 | { 117 | // The fetch controller has sent all current change notifications, so tell the table view to process all updates. 118 | [self.tableView endUpdates]; 119 | } 120 | 121 | 122 | #pragma mark - 123 | #pragma mark - UITableView 124 | 125 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 126 | { 127 | return 100; 128 | } 129 | 130 | - (NSInteger)tableView:(UITableView *)tableView 131 | numberOfRowsInSection:(NSInteger)section 132 | { 133 | id sectionInfo = [self.frc.sections objectAtIndex:section]; 134 | return [sectionInfo numberOfObjects]; 135 | } 136 | 137 | - (UITableViewCell *)tableView:(UITableView *)tableView 138 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 139 | { 140 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellReuseIdentifier]; 141 | 142 | [self configureCell:cell atIndexPath:indexPath]; 143 | 144 | return cell; 145 | } 146 | 147 | - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 148 | { 149 | // Set up the cell... 150 | NSManagedObject *file = [self.frc objectAtIndexPath:indexPath]; 151 | 152 | cell.textLabel.text = [[file valueForKey:@"book"] valueForKey:@"title"]; 153 | } 154 | 155 | @end 156 | -------------------------------------------------------------------------------- /BookMigration/Model.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | Model3.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /BookMigration/Model.xcdatamodeld/Model1.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /BookMigration/Model.xcdatamodeld/Model2.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /BookMigration/Model.xcdatamodeld/Model3.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /BookMigration/Model1.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objcio/issue-4-core-data-migration/02002c93a4531ebcf8f40ee4c77986d01abc790e/BookMigration/Model1.sqlite -------------------------------------------------------------------------------- /BookMigration/Model1_to_Model2.xcmappingmodel/xcmapping.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 134481920 7 | E7248607-A19C-432D-BA56-9629746E4B54 8 | 113 9 | 10 | 11 | 12 | NSPersistenceFrameworkVersion 13 | 481 14 | NSStoreModelVersionHashes 15 | 16 | XDDevAttributeMapping 17 | 18 | 0plcXXRN7XHKl5CcF+fwriFmUpON3ZtcI/AfK748aWc= 19 | 20 | XDDevEntityMapping 21 | 22 | qeN1Ym3TkWN1G6dU9RfX6Kd2ccEvcDVWHpd3LpLgboI= 23 | 24 | XDDevMappingModel 25 | 26 | EqtMzvRnVZWkXwBHu4VeVGy8UyoOe+bi67KC79kphlQ= 27 | 28 | XDDevPropertyMapping 29 | 30 | XN33V44TTGY4JETlMoOB5yyTKxB+u4slvDIinv0rtGA= 31 | 32 | XDDevRelationshipMapping 33 | 34 | akYY9LhehVA/mCb4ATLWuI9XGLcjpm14wWL1oEBtIcs= 35 | 36 | 37 | NSStoreModelVersionHashesVersion 38 | 3 39 | NSStoreModelVersionIdentifiers 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | title 49 | 50 | 51 | 52 | userId 53 | 54 | 55 | 56 | 1 57 | books 58 | 59 | 60 | 61 | BookMigration/Model.xcdatamodeld/Model1.xcdatamodel 62 | YnBsaXN0MDDUAAEAAgADAAQABQAGCgYKB1gkdmVyc2lvblgkb2JqZWN0c1kkYXJjaGl2ZXJUJHRv 63 | cBIAAYagrxD6AAcACAAXADMANAA1AD8AQABBAFwAXQBeAGQAZQBxAIUAhgCHAIgAiQCKAIsAjACNAKYAqQCwALYAxQDUAOMA5gBbAPYBBQEJAQ0BHAEiASMBKwE6AUMBTwFQAVEBUgFTAWgBaQFxAXIBcwF/AZMBlAGVAZYBlwGYAZkBmgGbAaoBuQHIAcwB2wHqAesB+gIJAhgCJAI2AjcCOAI5AjoCOwI8Aj0CTAJbAmoCeQJ6AokCmAKnAq8CxALFAs0C2QLtAvwDCwMaAx4DLQM8A0sDWgNpA3UDhwOWA6UDtAPDA8QD0wPiA/EEBgQHBA8EGwQvBD4ETQRcBGAEbwR+BI0EnASrBLcEyQTYBOcE9gUFBRQFIwUyBUcFSAVQBVEFXQVxBYAFjwWeBaIFsQXABc8F3gXtBfkGCwYMBg0GDgYPBhAGEQYSBiEGIgYxBkAGTwZpBmoGcAZ8BpAGnwaiBrEGwAbPBtIG4QbwBvQHAwcSBxoHGwccBzEHMgc6B0YHWgdpB3gHhweLB5oHqQe4B8cH1gfiB/QALQgDCBIIIQgwCD8ITghdCGUIegh7CIMIjwijCLIIwQjQCNQI4wjyCQEJEAkfCSsJPQlMCU0JXAlrCXoJewmKCZkJqAmpCawJtQnECdMJ4gnlCekJ7QnxCfkJ/AoACgFVJG51bGzXAAkACgALAAwADQAOAA8AEAARABIAEwAUABMAFl8QD194ZF9yb290UGFja2FnZVYkY2xhc3NcX3hkX2NvbW1lbnRzXxAQX3hkX21vZGVsTWFuYWdlcl8QFV9jb25maWd1cmF0aW9uc0J5TmFtZV1feGRfbW9kZWxOYW1lXxAXX21vZGVsVmVyc2lvbklkZW50aWZpZXKAAoD5gPaAAID3gACA+N4AGAAZABoAGwAcAB0AHgAKAB8AIAAhACIAIwAkACUAJgAnACgAJQATACsALAAtAC4ALwAlACUAE18QHFhEQnVja2V0Rm9yQ2xhc3Nlc3dhc0VuY29kZWRfEBpYREJ1Y2tldEZvclBhY2thZ2Vzc3RvcmFnZV8QHFhEQnVja2V0Rm9ySW50ZXJmYWNlc3N0b3JhZ2VfEA9feGRfb3duaW5nTW9kZWxfEB1YREJ1Y2tldEZvclBhY2thZ2Vzd2FzRW5jb2RlZFZfb3duZXJfEBtYREJ1Y2tldEZvckRhdGFUeXBlc3N0b3JhZ2VbX3Zpc2liaWxpdHlfEBlYREJ1Y2tldEZvckNsYXNzZXNzdG9yYWdlVV9uYW1lXxAfWERCdWNrZXRGb3JJbnRlcmZhY2Vzd2FzRW5jb2RlZF8QHlhEQnVja2V0Rm9yRGF0YVR5cGVzd2FzRW5jb2RlZF8QEF91bmlxdWVFbGVtZW50SUSABID0gPKAAYAEgACA84D1EACABYADgASABIAAUFNZRVPTADYANwAKADgAOwA+V05TLmtleXNaTlMub2JqZWN0c6IAOQA6gAaAB6IAPAA9gAiApoAjVEJvb2tUVXNlct8QEABCAEMARABFAB0ARgBHAB8ASABJAAoAIQBKAEsAJABMAE0ATgAlACUAEABSAFMALQAlAE0AVgA5AE0AWQBaAFtfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2VfECBYREJ1Y2tldEZvclN0ZXJlb3R5cGVzd2FzRW5jb2RlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNzdG9yYWdlXxAkWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNkdXBsaWNhdGVzXxAkWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnN3YXNFbmNvZGVkXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc29yZGVyZWRfECFYREJ1Y2tldEZvckdlbmVyYWxpemF0aW9uc29yZGVyZWRfECFYREJ1Y2tldEZvckdlbmVyYWxpemF0aW9uc3N0b3JhZ2VbX2lzQWJzdHJhY3SACoAqgASABIACgAuA64AEgAqA7YAGgAqA8YAJCBIufC1JV29yZGVyZWTTADYANwAKAF8AYQA+oQBggAyhAGKADYAjXlhEX1BTdGVyZW90eXBl2QAdACEAZgAKACQAZwAfAEwAaAA8AGAATQBsABMAJQAtAFsAcF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1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FRkXGTwZYBmHGasZrRmvGbEZsxm1GbcZuBm6GccZ2BnaGdwZ3hngGeIZ5BnmGegZ+Rn7Gf0Z/xoBGgMaBRoHGgkaCxpKGkwaThpQGlIaUxpUGlUaVhpYGloaWxpcGl4aXxqeGqAaohqkGqYapxqoGqkaqhqsGq4arxqwGrIasxryGvQa9hr4Gvoa+xr8Gv0a/hsAGwIbAxsEGwYbBxsUGxUbFhsYG1cbWRtbG10bXxtgG2EbYhtjG2UbZxtoG2kbaxtsG6sbrRuvG7Ebsxu0G7Ubthu3G7kbuxu8G70bvxvAG/8cARwDHAUcBxwIHAkcChwLHA0cDxwQHBEcExwUHFMcVRxXHFkcWxxcHF0cXhxfHGEcYxxkHGUcZxxoHKccqRyrHK0crxywHLEcshyzHLUctxy4HLkcuxy8HOEdBR0sHVAdUh1UHVYdWB1aHVwdXR1fHWwdex19HX8dgR2DHYUdhx2JHZgdmh2cHZ4doB2iHaQdph2oHecd6R3rHe0d7x3wHfEd8h3zHfUd9x34Hfkd+x38HjsePR4/HkEeQx5EHkUeRh5HHkkeSx5MHk0eTx5QHo8ekR6THpUelx6YHpkemh6bHp0enx6gHqEeox6kHuMe5R7nHuke6x7sHu0e7h7vHvEe8x70HvUe9x74HvsfOh88Hz4fQB9CH0MfRB9FH0YfSB9KH0sfTB9OH08fjh+QH5IflB+WH5cfmB+ZH5ofnB+eH58foB+iH6Mf4h/kH+Yf6B/qH+sf7B/tH+4f8B/yH/Mf9B/2H/cgQiBlIIUgpSCnIKkgqyCtIK8gsCCxILMgtCC2ILcguSC7ILwgvSC/IMAgxSDSINcg2SDbIOAg4iDkIOYhCyEvIVYheiF8IX4hgCGCIYQhhiGHIYkhliGnIakhqyGtIa8hsSGzIbUhtyHIIcohzCHOIdAh0iHUIdYh2CHaIhkiGyIdIh8iISIiIiMiJCIlIiciKSIqIisiLSIuIm0ibyJxInMidSJ2IncieCJ5InsifSJ+In8igSKCIsEiwyLFIsciySLKIssizCLNIs8i0SLSItMi1SLWIuMi5CLlIucjJiMoIyojLCMuIy8jMCMxIzIjNCM2IzcjOCM6IzsjeiN8I34jgCOCI4MjhCOFI4YjiCOKI4sjjCOOI48jziPQI9Ij1CPWI9cj2CPZI9oj3CPeI98j4CPiI+Mk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 64 | 65 | BookMigration/Model.xcdatamodeld/Model2.xcdatamodel 66 | YnBsaXN0MDDUAAEAAgADAAQABQAGDV4NX1gkdmVyc2lvblgkb2JqZWN0c1kkYXJjaGl2ZXJUJHRv 67 | cBIAAYagrxEBQAAHAAgAFwAzADQANQBBAEIAQwBEAF8AYABhAGcAaAB0AIgAiQCKAIsAjACNAI4AjwCQAKkArACzALkAyADXAOYA6QBeAPkBCAEMARABHwElASYBLgE9AUYBTgFPAVABZQFmAW4BbwFwAXwBkAGRAZIBkwGUAZUBlgGXAZgBpwG2AcUByQHYAecB6AH3AgYCFQIhAjMCNAI1AjYCNwI4AjkCOgAtAkkCWAJZAmgCdwKRApICmAKkArgCxwLKAtkC6AL3AvoDCQMYAxwDKwM6AzsDRwNIA0kDSgNLA2ADYQNpA2oDdgOKA5kDqAO3A7sDygPZA+gD9wQGBBIEJAQlBCYEJwQoBCkEKgQrBDoESQRYBGcEaAR3BIYElQSdBLIEswS7BMcE2wTqBPkFCAUMBRsFKgU5BUgFVwVjBXUFhAWTBZQFowWyBcEF0AXfBecF/AX9BgUGEQYlBjQGQwZSBlYGZQZ0BoMGkgahBq0GvwbOBt0G7Ab7BvwHCwcaBykHPgc/B0cHUwdnB3YHhQeUB5gHpwe2B8UH1AfjB+8IAQgQCB8ILgg9CFcIWAheCGoIfgiNCJAInwiuCL0IwAjPCN4I4gjxCQAJAQkJCQoJCwkgCSEJKQk1CUkJWAlnCXYJegmJCZgJpwm2CcUJ0QnjCfIKAQoQCh8KLgo9CkwKYQpiCmoKdgqKCpkKqAq3CrsKygrZCugK9wsGCxILJAszC0ILUQtgC28LfguNC44LkQuaC6kLuAvHC8oL2QvoC/cMDAwNDBUMIQw1DEQMUwxiDGYMdQyEDJMMogyxDL0MzwzeDN8M7gz9DQwNDQ0cDSsNOg09DUENRQ1JDVENVA1YDVlVJG51bGzXAAkACgALAAwADQAOAA8AEAARABIAEwAUABMAFl8QD194ZF9yb290UGFja2FnZVYkY2xhc3NcX3hkX2NvbW1lbnRzXxAQX3hkX21vZGVsTWFuYWdlcl8QFV9jb25maWd1cmF0aW9uc0J5TmFtZV1feGRfbW9kZWxOYW1lXxAXX21vZGVsVmVyc2lvbklkZW50aWZpZXKAAoEBP4EBPIAAgQE9gACBAT7eABgAGQAaABsAHAAdAB4ACgAfACAAIQAiACMAJAAlACYAJwAoACUAEwArACwALQAuAC8AJQAlABNfEBxYREJ1Y2tldEZvckNsYXNzZXN3YXNFbmNvZGVkXxAaWERCdWNrZXRGb3JQYWNrYWdlc3N0b3JhZ2VfEBxYREJ1Y2tldEZvckludGVyZmFjZXNzdG9yYWdlXxAPX3hkX293bmluZ01vZGVsXxAdWERCdWNrZXRGb3JQYWNrYWdlc3dhc0VuY29kZWRWX293bmVyXxAbWERCdWNrZXRGb3JEYXRhVHlwZXNzdG9yYWdlW192aXNpYmlsaXR5XxAZWERCdWNrZXRGb3JDbGFzc2Vzc3RvcmFnZVVfbmFtZV8QH1hEQnVja2V0Rm9ySW50ZXJmYWNlc3dhc0VuY29kZWRfEB5YREJ1Y2tldEZvckRhdGFUeXBlc3dhc0VuY29kZWRfEBBfdW5pcXVlRWxlbWVudElEgASBATqBATiAAYAEgACBATmBATsQAIAFgAOABIAEgABQU1lFU9MANgA3AAoAOAA8AEBXTlMua2V5c1pOUy5vYmplY3RzowA5ADoAO4AGgAeACKMAPQA+AD+ACYBWgNKAJFRVc2VyVEJvb2tWQXV0aG9y3xAQAEUARgBHAEgAHQBJAEoAHwBLAEwACgAhAE0ATgAkAE8AUABRACUAJQAQAFUAVgAtACUAUABZADkAUABcAF0AXl8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZV8QIFhEQnVja2V0Rm9yU3RlcmVvdHlwZXN3YXNFbmNvZGVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc3N0b3JhZ2VfECRYREJ1Y2tldEZvckdlbmVyYWxpemF0aW9uc2R1cGxpY2F0ZXNfECRYREJ1Y2tldEZvckdlbmVyYWxpemF0aW9uc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzb3JkZXJlZF8QIVhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zb3JkZXJlZF8QIVhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zc3RvcmFnZVtfaXNBYnN0cmFjdIALgCuABIAEgAKADIEBFIAEgAuBARaABoALgQE3gAoIEuVBN3tXb3JkZXJlZNMANgA3AAoAYgBkAEChAGOADaEAZYAOgCReWERfUFN0ZXJlb3R5cGXZAB0AIQBpAAoAJABqAB8ATwBrAD0AYwBQAG8AEwAlAC0AXgBzXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgAmADYALgCqAAIAECIAP0wA2ADcACgB1AH4AQKgAdgB3AHgAeQB6AHsAfAB9gBCAEYASgBOAFIAVgBaAF6gAfwCAAIEAggCDAIQAhQCGgBiAHIAdgB6AIIAigCWAKYAkXxATWERQTUNvbXBvdW5kSW5kZXhlc18QEFhEX1BTS19lbGVtZW50SURfEBpYRF9QU0tfdmVyc2lvbkhhc2hNb2RpZmllcl8QGVhEX1BTS19mZXRjaFJlcXVlc3RzQXJyYXlfEBFYRF9QU0tfaXNBYnN0cmFjdF8QD1hEX1BTS191c2VySW5mb18QE1hEX1BTS19jbGFzc01hcHBpbmdfEBZYRF9QU0tfZW50aXR5Q2xhc3NOYW1l3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAnAATAGUAXgBeAF4ALQBeAKMAdgBeAF4AEwBeVV90eXBlWF9kZWZhdWx0XF9hc3NvY2lhdGlvbltfaXNSZWFkT25seVlfaXNTdGF0aWNZX2lzVW5pcXVlWl9pc0Rlcml2ZWRaX2lzT3JkZXJlZFxfaXNDb21wb3NpdGVXX2lzTGVhZoAAgBmAAIAOCAgICIAbgBAICIAACNIANwAKAKoAq6CAGtIArQCuAK8AsFokY2xhc3NuYW1lWCRjbGFzc2VzXk5TTXV0YWJsZUFycmF5owCvALEAsldOU0FycmF5WE5TT2JqZWN00gCtAK4AtAC1XxAQWERVTUxQcm9wZXJ0eUltcKQAtgC3ALgAsl8QEFhEVU1MUHJvcGVydHlJbXBfEBRYRFVNTE5hbWVkRWxlbWVudEltcF8QD1hEVU1MRWxlbWVudEltcN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwBlAF4AXgBeAC0AXgCjAHcAXgBeABMAXoAAgACAAIAOCAgICIAbgBEICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwBlAF4AXgBeAC0AXgCjAHgAXgBeABMAXoAAgACAAIAOCAgICIAbgBIICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATANkAEwBlAF4AXgBeAC0AXgCjAHkAXgBeABMAXoAAgB+AAIAOCAgICIAbgBMICIAACNIANwAKAOcAq6CAGt8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwBlAF4AXgBeAC0AXgCjAHoAXgBeABMAXoAAgCGAAIAOCAgICIAbgBQICIAACAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwD7ABMAZQBeAF4AXgAtAF4AowB7AF4AXgATAF6AAIAjgACADggICAiAG4AVCAiAAAjTADYANwAKAQkBCgBAoKCAJNIArQCuAQ0BDl8QE05TTXV0YWJsZURpY3Rpb25hcnmjAQ0BDwCyXE5TRGljdGlvbmFyed8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATARIAEwBlAF4AXgBeAC0AXgCjAHwAXgBeABMAXoAAgCaAAIAOCAgICIAbgBYICIAACNYAIQAKACQATwAdAB8BIAEhABMAXgATAC2AJ4AogAAIgABfEBRYREdlbmVyaWNSZWNvcmRDbGFzc9IArQCuAScBKF1YRFVNTENsYXNzSW1wpgEpASoBKwEsAS0Asl1YRFVNTENsYXNzSW1wXxASWERVTUxDbGFzc2lmaWVySW1wXxARWERVTUxOYW1lc3BhY2VJbXBfEBRYRFVNTE5hbWVkRWxlbWVudEltcF8QD1hEVU1MRWxlbWVudEltcN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwBlAF4AXgBeAC0AXgCjAH0AXgBeABMAXoAAgACAAIAOCAgICIAbgBcICIAACNIArQCuAT4BP18QElhEVU1MU3RlcmVvdHlwZUltcKcBQAFBAUIBQwFEAUUAsl8QElhEVU1MU3RlcmVvdHlwZUltcF1YRFVNTENsYXNzSW1wXxASWERVTUxDbGFzc2lmaWVySW1wXxARWERVTUxOYW1lc3BhY2VJbXBfEBRYRFVNTE5hbWVkRWxlbWVudEltcF8QD1hEVU1MRWxlbWVudEltcNMANgA3AAoBRwFKAECiAUgBSYAsgC2iAUsBTIAugQEegCRVYm9va3NWdXNlcklk3xASAJEAkgCTAVEAHQCVAJYBUgAfAJQBUwCXAAoAIQCYAJkAJACaABMAEwATACUAPQBeAF4BWwAtAF4AUABeAV8BSABeAF4BYwBeXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkgACAAIAAgASACQgIgDAIgAsIgKWALAgIgC8IEhhhTwjTADYANwAKAWcBagBAogFoAWmAMYAyogFrAWyAM4BHgCRfEBJYRF9QUHJvcFN0ZXJlb3R5cGVfEBBYRF9QUl9TdGVyZW90eXBl2QAdACEBcQAKACQBcgAfAE8BcwFLAWgAUABvABMAJQAtAF4Be18QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYAugDGAC4AqgACABAiANNMANgA3AAoBfQGGAECoAX4BfwGAAYEBggGDAYQBhYA1gDaAN4A4gDmAOoA7gDyoAYcBiAGJAYoBiwGMAY0BjoA9gD6AP4BBgEKARIBFgEaAJF8QG1hEX1BQU0tfaXNTdG9yZWRJblRydXRoRmlsZV8QG1hEX1BQU0tfdmVyc2lvbkhhc2hNb2RpZmllcl8QEFhEX1BQU0tfdXNlckluZm9fEBFYRF9QUFNLX2lzSW5kZXhlZF8QElhEX1BQU0tfaXNPcHRpb25hbF8QGlhEX1BQU0tfaXNTcG90bGlnaHRJbmRleGVkXxARWERfUFBTS19lbGVtZW50SURfEBNYRF9QUFNLX2lzVHJhbnNpZW503xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATAWsAXgBeAF4ALQBeAKMBfgBeAF4AEwBegACAIYAAgDMICAgIgBuANQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATAWsAXgBeAF4ALQBeAKMBfwBeAF4AEwBegACAAIAAgDMICAgIgBuANggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMBuAATAWsAXgBeAF4ALQBeAKMBgABeAF4AEwBegACAQIAAgDMICAgIgBuANwgIgAAI0wA2ADcACgHGAccAQKCggCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMBawBeAF4AXgAtAF4AowGBAF4AXgATAF6AAIAhgACAMwgICAiAG4A4CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMBawBeAF4AXgAtAF4AowGCAF4AXgATAF6AAIBDgACAMwgICAiAG4A5CAiAAAgJ3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATAWsAXgBeAF4ALQBeAKMBgwBeAF4AEwBegACAIYAAgDMICAgIgBuAOggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATAWsAXgBeAF4ALQBeAKMBhABeAF4AEwBegACAAIAAgDMICAgIgBuAOwgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATAWsAXgBeAF4ALQBeAKMBhQBeAF4AEwBegACAIYAAgDMICAgIgBuAPAgIgAAI2QAdACECFgAKACQCFwAfAE8CGAFLAWkAUABvABMAJQAtAF4CIF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYAugDKAC4AqgACABAiASNMANgA3AAoCIgIqAECnAiMCJAIlAiYCJwIoAimASYBKgEuATIBNgE6AT6cCKwIsAi0CLgIvAjACMYBQgFKAVIBVgQEbgQEcgQEdgCRfEA9YRF9QUktfbWluQ291bnRfEBFYRF9QUktfZGVsZXRlUnVsZV8QD1hEX1BSS19tYXhDb3VudF8QElhEX1BSS19kZXN0aW5hdGlvbl8QD1hEX1BSS19pc1RvTWFueV5YRF9QUktfb3JkZXJlZF8QGlhEX1BSS19pbnZlcnNlUmVsYXRpb25zaGlw3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMCPAATAWwAXgBeAF4ALQBeAKMCIwBeAF4AEwBegACAUYAAgEcICAgIgBuASQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMCSwATAWwAXgBeAF4ALQBeAKMCJABeAF4AEwBegACAU4AAgEcICAgIgBuASggIgAAIEALfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwI8ABMBbABeAF4AXgAtAF4AowIlAF4AXgATAF6AAIBRgACARwgICAiAG4BLCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwA+ABMBbABeAF4AXgAtAF4AowImAF4AXgATAF6AAIBWgACARwgICAiAG4BMCAiAAAjfEBACeAJ5AnoCewAdAnwCfQAfAn4CfwAKACECgAKBACQATwBQAoMAJQAlABAChwBWAC0AJQBQAFkAOgBQAo4CjwBeXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zZHVwbGljYXRlc18QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNzdG9yYWdlgAuAZ4AEgASAAoBYgQEUgASAC4EBFoAHgAuBARqAVwgSeQQXJtMANgA3AAoCkwKVAEChAGOADaECloBZgCTZAB0AIQKZAAoAJAKaAB8ATwKbAD4AYwBQAG8AEwAlAC0AXgKjXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgFaADYALgCqAAIAECIBa0wA2ADcACgKlAq4AQKgAdgB3AHgAeQB6AHsAfAB9gBCAEYASgBOAFIAVgBaAF6gCrwKwArECsgKzArQCtQK2gFuAXYBegF+AYYBigGSAZYAk3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMCugATApYAXgBeAF4ALQBeAKMAdgBeAF4AEwBegACAXIAAgFkICAgIgBuAEAgIgAAI0gA3AAoCyACroIAa3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATApYAXgBeAF4ALQBeAKMAdwBeAF4AEwBegACAAIAAgFkICAgIgBuAEQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATApYAXgBeAF4ALQBeAKMAeABeAF4AEwBegACAAIAAgFkICAgIgBuAEggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMC6gATApYAXgBeAF4ALQBeAKMAeQBeAF4AEwBegACAYIAAgFkICAgIgBuAEwgIgAAI0gA3AAoC+ACroIAa3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATApYAXgBeAF4ALQBeAKMAegBeAF4AEwBegACAIYAAgFkICAgIgBuAFAgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMDCwATApYAXgBeAF4ALQBeAKMAewBeAF4AEwBegACAY4AAgFkICAgIgBuAFQgIgAAI0wA2ADcACgMZAxoAQKCggCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwESABMClgBeAF4AXgAtAF4AowB8AF4AXgATAF6AAIAmgACAWQgICAiAG4AWCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwMtABMClgBeAF4AXgAtAF4AowB9AF4AXgATAF6AAIBmgACAWQgICAiAG4AXCAiAAAhUQm9va9MANgA3AAoDPANBAECkAz0DPgM/A0CAaIBpgGqAa6QDQgNDA0QDRYBsgI2ApoC+gCRXZmlsZVVSTFV1c2Vyc1V0aXRsZVdhdXRob3Jz3xASAJEAkgCTA0wAHQCVAJYDTQAfAJQDTgCXAAoAIQCYAJkAJACaABMAEwATACUAPgBeAF4DVgAtAF4AUABeA1oDPQBeAF4DXgBeXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkgACAAIAAgASAVggIgG4IgAsIgIyAaAgIgG0IEktc5y/TADYANwAKA2IDZQBAogFoA2SAMYBvogNmA2eAcIB7gCRfEBJYRF9QQXR0X1N0ZXJlb3R5cGXZAB0AIQNrAAoAJANsAB8ATwNtA0IBaABQAG8AEwAlAC0AXgN1XxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgGyAMYALgCqAAIAECIBx0wA2ADcACgN3A4AAQKgBfgF/AYABgQGCAYMBhAGFgDWANoA3gDiAOYA6gDuAPKgDgQOCA4MDhAOFA4YDhwOIgHKAc4B0gHaAd4B4gHmAeoAk3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATA2YAXgBeAF4ALQBeAKMBfgBeAF4AEwBegACAIYAAgHAICAgIgBuANQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATA2YAXgBeAF4ALQBeAKMBfwBeAF4AEwBegACAAIAAgHAICAgIgBuANggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMDqgATA2YAXgBeAF4ALQBeAKMBgABeAF4AEwBegACAdYAAgHAICAgIgBuANwgIgAAI0wA2ADcACgO4A7kAQKCggCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMDZgBeAF4AXgAtAF4AowGBAF4AXgATAF6AAIAhgACAcAgICAiAG4A4CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMDZgBeAF4AXgAtAF4AowGCAF4AXgATAF6AAIBDgACAcAgICAiAG4A5CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMDZgBeAF4AXgAtAF4AowGDAF4AXgATAF6AAIAhgACAcAgICAiAG4A6CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMDZgBeAF4AXgAtAF4AowGEAF4AXgATAF6AAIAAgACAcAgICAiAG4A7CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMDZgBeAF4AXgAtAF4AowGFAF4AXgATAF6AAIAhgACAcAgICAiAG4A8CAiAAAjZAB0AIQQHAAoAJAQIAB8ATwQJA0IDZABQAG8AEwAlAC0AXgQRXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgGyAb4ALgCqAAIAECIB80wA2ADcACgQTBBsAQKcEFAQVBBYEFwQYBBkEGoB9gH6Af4CAgIGAgoCDpwQcBB0EHgQfBCAEIQQigISAhYCGgIeAiYCKgIuAJF8QHVhEX1BBdHRLX2RlZmF1bHRWYWx1ZUFzU3RyaW5nXxAoWERfUEF0dEtfYWxsb3dzRXh0ZXJuYWxCaW5hcnlEYXRhU3RvcmFnZV8QF1hEX1BBdHRLX21pblZhbHVlU3RyaW5nXxAWWERfUEF0dEtfYXR0cmlidXRlVHlwZV8QF1hEX1BBdHRLX21heFZhbHVlU3RyaW5nXxAdWERfUEF0dEtfdmFsdWVUcmFuc2Zvcm1lck5hbWVfECBYRF9QQXR0S19yZWd1bGFyRXhwcmVzc2lvblN0cmluZ98QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwNnAF4AXgBeAC0AXgCjBBQAXgBeABMAXoAAgACAAIB7CAgICIAbgH0ICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwNnAF4AXgBeAC0AXgCjBBUAXgBeABMAXoAAgCGAAIB7CAgICIAbgH4ICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwNnAF4AXgBeAC0AXgCjBBYAXgBeABMAXoAAgACAAIB7CAgICIAbgH8ICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATBFoAEwNnAF4AXgBeAC0AXgCjBBcAXgBeABMAXoAAgIiAAIB7CAgICIAbgIAICIAACBEHCN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwNnAF4AXgBeAC0AXgCjBBgAXgBeABMAXoAAgACAAIB7CAgICIAbgIEICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwNnAF4AXgBeAC0AXgCjBBkAXgBeABMAXoAAgACAAIB7CAgICIAbgIIICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwNnAF4AXgBeAC0AXgCjBBoAXgBeABMAXoAAgACAAIB7CAgICIAbgIMICIAACNIArQCuBJYEl11YRFBNQXR0cmlidXRlpgSYBJkEmgSbBJwAsl1YRFBNQXR0cmlidXRlXFhEUE1Qcm9wZXJ0eV8QEFhEVU1MUHJvcGVydHlJbXBfEBRYRFVNTE5hbWVkRWxlbWVudEltcF8QD1hEVU1MRWxlbWVudEltcN8QEgCRAJIAkwSeAB0AlQCWBJ8AHwCUBKAAlwAKACEAmACZACQAmgATABMAEwAlAD4AXgBeBKgALQBeAFAAXgFfAz4AXgBeBLAAXl8QIFhEQnVja2V0Rm9yU3RlcmVvdHlwZXN3YXNFbmNvZGVkXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc3N0b3JhZ2VfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzb3JkZXJlZIAAgACAAIAEgFYICICPCIALCIClgGkICICOCBKby5sH0wA2ADcACgS0BLcAQKIBaAFpgDGAMqIEuAS5gJCAm4Ak2QAdACEEvAAKACQEvQAfAE8EvgNDAWgAUABvABMAJQAtAF4Exl8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYCNgDGAC4AqgACABAiAkdMANgA3AAoEyATRAECoAX4BfwGAAYEBggGDAYQBhYA1gDaAN4A4gDmAOoA7gDyoBNIE0wTUBNUE1gTXBNgE2YCSgJOAlICWgJeAmICZgJqAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwS4AF4AXgBeAC0AXgCjAX4AXgBeABMAXoAAgCGAAICQCAgICIAbgDUICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwS4AF4AXgBeAC0AXgCjAX8AXgBeABMAXoAAgACAAICQCAgICIAbgDYICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATBPsAEwS4AF4AXgBeAC0AXgCjAYAAXgBeABMAXoAAgJWAAICQCAgICIAbgDcICIAACNMANgA3AAoFCQUKAECgoIAk3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATBLgAXgBeAF4ALQBeAKMBgQBeAF4AEwBegACAIYAAgJAICAgIgBuAOAgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMB2gATBLgAXgBeAF4ALQBeAKMBggBeAF4AEwBegACAQ4AAgJAICAgIgBuAOQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATBLgAXgBeAF4ALQBeAKMBgwBeAF4AEwBegACAIYAAgJAICAgIgBuAOggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATBLgAXgBeAF4ALQBeAKMBhABeAF4AEwBegACAAIAAgJAICAgIgBuAOwgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATBLgAXgBeAF4ALQBeAKMBhQBeAF4AEwBegACAIYAAgJAICAgIgBuAPAgIgAAI2QAdACEFWAAKACQFWQAfAE8FWgNDAWkAUABvABMAJQAtAF4FYl8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYCNgDKAC4AqgACABAiAnNMANgA3AAoFZAVsAECnAiMCJAIlAiYCJwIoAimASYBKgEuATIBNgE6AT6cFbQVuBW8FcAVxBXIFc4CdgJ6AoIChgKKAo4CkgCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwI8ABMEuQBeAF4AXgAtAF4AowIjAF4AXgATAF6AAIBRgACAmwgICAiAG4BJCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwWGABMEuQBeAF4AXgAtAF4AowIkAF4AXgATAF6AAICfgACAmwgICAiAG4BKCAiAAAgQAd8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAjwAEwS5AF4AXgBeAC0AXgCjAiUAXgBeABMAXoAAgFGAAICbCAgICIAbgEsICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAD0AEwS5AF4AXgBeAC0AXgCjAiYAXgBeABMAXoAAgAmAAICbCAgICIAbgEwICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAdoAEwS5AF4AXgBeAC0AXgCjAicAXgBeABMAXoAAgEOAAICbCAgICIAbgE0ICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwS5AF4AXgBeAC0AXgCjAigAXgBeABMAXoAAgCGAAICbCAgICIAbgE4ICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAUsAEwS5AF4AXgBeAC0AXgCjAikAXgBeABMAXoAAgC6AAICbCAgICIAbgE8ICIAACNIArQCuBeAF4V8QEFhEUE1SZWxhdGlvbnNoaXCmBeIF4wXkBeUF5gCyXxAQWERQTVJlbGF0aW9uc2hpcFxYRFBNUHJvcGVydHlfEBBYRFVNTFByb3BlcnR5SW1wXxAUWERVTUxOYW1lZEVsZW1lbnRJbXBfEA9YRFVNTEVsZW1lbnRJbXDfEBIAkQCSAJMF6AAdAJUAlgXpAB8AlAXqAJcACgAhAJgAmQAkAJoAEwATABMAJQA+AF4AXgXyAC0AXgBQAF4DWgM/AF4AXgX6AF5fECBYREJ1Y2tldEZvclN0ZXJlb3R5cGVzd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNzdG9yYWdlXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc29yZGVyZWSAAIAAgACABIBWCAiAqAiACwiAjIBqCAiApwgSxYtjztMANgA3AAoF/gYBAECiAWgDZIAxgG+iBgIGA4CpgLSAJNkAHQAhBgYACgAkBgcAHwBPBggDRAFoAFAAbwATACUALQBeBhBfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WApoAxgAuAKoAAgAQIgKrTADYANwAKBhIGGwBAqAF+AX8BgAGBAYIBgwGEAYWANYA2gDeAOIA5gDqAO4A8qAYcBh0GHgYfBiAGIQYiBiOAq4CsgK2Ar4CwgLGAsoCzgCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMGAgBeAF4AXgAtAF4AowF+AF4AXgATAF6AAIAhgACAqQgICAiAG4A1CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMGAgBeAF4AXgAtAF4AowF/AF4AXgATAF6AAIAAgACAqQgICAiAG4A2CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwZFABMGAgBeAF4AXgAtAF4AowGAAF4AXgATAF6AAICugACAqQgICAiAG4A3CAiAAAjTADYANwAKBlMGVABAoKCAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwYCAF4AXgBeAC0AXgCjAYEAXgBeABMAXoAAgCGAAICpCAgICIAbgDgICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAdoAEwYCAF4AXgBeAC0AXgCjAYIAXgBeABMAXoAAgEOAAICpCAgICIAbgDkICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwYCAF4AXgBeAC0AXgCjAYMAXgBeABMAXoAAgCGAAICpCAgICIAbgDoICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwYCAF4AXgBeAC0AXgCjAYQAXgBeABMAXoAAgACAAICpCAgICIAbgDsICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwYCAF4AXgBeAC0AXgCjAYUAXgBeABMAXoAAgCGAAICpCAgICIAbgDwICIAACNkAHQAhBqIACgAkBqMAHwBPBqQDRANkAFAAbwATACUALQBeBqxfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WApoBvgAuAKoAAgAQIgLXTADYANwAKBq4GtgBApwQUBBUEFgQXBBgEGQQagH2AfoB/gICAgYCCgIOnBrcGuAa5BroGuwa8Br2AtoC3gLiAuYC7gLyAvYAk3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATBgMAXgBeAF4ALQBeAKMEFABeAF4AEwBegACAAIAAgLQICAgIgBuAfQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATBgMAXgBeAF4ALQBeAKMEFQBeAF4AEwBegACAIYAAgLQICAgIgBuAfggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATBgMAXgBeAF4ALQBeAKMEFgBeAF4AEwBegACAAIAAgLQICAgIgBuAfwgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMG7gATBgMAXgBeAF4ALQBeAKMEFwBeAF4AEwBegACAuoAAgLQICAgIgBuAgAgIgAAIEQK83xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATBgMAXgBeAF4ALQBeAKMEGABeAF4AEwBegACAAIAAgLQICAgIgBuAgQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATBgMAXgBeAF4ALQBeAKMEGQBeAF4AEwBegACAAIAAgLQICAgIgBuAgggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATBgMAXgBeAF4ALQBeAKMEGgBeAF4AEwBegACAAIAAgLQICAgIgBuAgwgIgAAI3xASAJEAkgCTByoAHQCVAJYHKwAfAJQHLACXAAoAIQCYAJkAJACaABMAEwATACUAPgBeAF4HNAAtAF4AUABeAV8DQABeAF4HPABeXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkgACAAIAAgASAVggIgMAIgAsIgKWAawgIgL8IEm4ssMfTADYANwAKB0AHQwBAogFoAWmAMYAyogdEB0WAwYDMgCTZAB0AIQdIAAoAJAdJAB8ATwdKA0UBaABQAG8AEwAlAC0AXgdSXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgL6AMYALgCqAAIAECIDC0wA2ADcACgdUB10AQKgBfgF/AYABgQGCAYMBhAGFgDWANoA3gDiAOYA6gDuAPKgHXgdfB2AHYQdiB2MHZAdlgMOAxIDFgMeAyIDJgMqAy4Ak3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATB0QAXgBeAF4ALQBeAKMBfgBeAF4AEwBegACAIYAAgMEICAgIgBuANQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATB0QAXgBeAF4ALQBeAKMBfwBeAF4AEwBegACAAIAAgMEICAgIgBuANggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMHhwATB0QAXgBeAF4ALQBeAKMBgABeAF4AEwBegACAxoAAgMEICAgIgBuANwgIgAAI0wA2ADcACgeVB5YAQKCggCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMHRABeAF4AXgAtAF4AowGBAF4AXgATAF6AAIAhgACAwQgICAiAG4A4CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMHRABeAF4AXgAtAF4AowGCAF4AXgATAF6AAIBDgACAwQgICAiAG4A5CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMHRABeAF4AXgAtAF4AowGDAF4AXgATAF6AAIAhgACAwQgICAiAG4A6CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMHRABeAF4AXgAtAF4AowGEAF4AXgATAF6AAIAAgACAwQgICAiAG4A7CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMHRABeAF4AXgAtAF4AowGFAF4AXgATAF6AAIAhgACAwQgICAiAG4A8CAiAAAjZAB0AIQfkAAoAJAflAB8ATwfmA0UBaQBQAG8AEwAlAC0AXgfuXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgL6AMoALgCqAAIAECIDN0wA2ADcACgfwB/gAQKcCIwIkAiUCJgInAigCKYBJgEqAS4BMgE2AToBPpwf5B/oH+wf8B/0H/gf/gM6Az4DQgNGBAReBARiBARmAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAjwAEwdFAF4AXgBeAC0AXgCjAiMAXgBeABMAXoAAgFGAAIDMCAgICIAbgEkICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATBYYAEwdFAF4AXgBeAC0AXgCjAiQAXgBeABMAXoAAgJ+AAIDMCAgICIAbgEoICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAjwAEwdFAF4AXgBeAC0AXgCjAiUAXgBeABMAXoAAgFGAAIDMCAgICIAbgEsICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAD8AEwdFAF4AXgBeAC0AXgCjAiYAXgBeABMAXoAAgNKAAIDMCAgICIAbgEwICIAACN8QEAg+CD8IQAhBAB0IQghDAB8IRAhFAAoAIQhGCEcAJABPAFAISQAlACUAEAhNAFYALQAlAFAAWQA7AFAIVAhVAF5fECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2VfECBYREJ1Y2tldEZvclN0ZXJlb3R5cGVzd2FzRW5jb2RlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNzdG9yYWdlXxAkWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNkdXBsaWNhdGVzXxAkWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnN3YXNFbmNvZGVkXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc29yZGVyZWRfECFYREJ1Y2tldEZvckdlbmVyYWxpemF0aW9uc29yZGVyZWRfECFYREJ1Y2tldEZvckdlbmVyYWxpemF0aW9uc3N0b3JhZ2WAC4DjgASABIACgNSBARSABIALgQEWgAiAC4EBFYDTCBKLSiOf0wA2ADcACghZCFsAQKEAY4ANoQhcgNWAJNkAHQAhCF8ACgAkCGAAHwBPCGEAPwBjAFAAbwATACUALQBeCGlfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WA0oANgAuAKoAAgAQIgNbTADYANwAKCGsIdABAqAB2AHcAeAB5AHoAewB8AH2AEIARgBKAE4AUgBWAFoAXqAh1CHYIdwh4CHkIegh7CHyA14DZgNqA24DdgN6A4IDhgCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwiAABMIXABeAF4AXgAtAF4AowB2AF4AXgATAF6AAIDYgACA1QgICAiAG4AQCAiAAAjSADcACgiOAKuggBrfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMIXABeAF4AXgAtAF4AowB3AF4AXgATAF6AAIAAgACA1QgICAiAG4ARCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMIXABeAF4AXgAtAF4AowB4AF4AXgATAF6AAIAAgACA1QgICAiAG4ASCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwiwABMIXABeAF4AXgAtAF4AowB5AF4AXgATAF6AAIDcgACA1QgICAiAG4ATCAiAAAjSADcACgi+AKuggBrfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMIXABeAF4AXgAtAF4AowB6AF4AXgATAF6AAIAhgACA1QgICAiAG4AUCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwjRABMIXABeAF4AXgAtAF4AowB7AF4AXgATAF6AAIDfgACA1QgICAiAG4AVCAiAAAjTADYANwAKCN8I4ABAoKCAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATARIAEwhcAF4AXgBeAC0AXgCjAHwAXgBeABMAXoAAgCaAAIDVCAgICIAbgBYICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATCPMAEwhcAF4AXgBeAC0AXgCjAH0AXgBeABMAXoAAgOKAAIDVCAgICIAbgBcICIAACFZBdXRob3LTADYANwAKCQIJBQBAogkDCQSA5IDlogkGCQeA5oD9gCRUbmFtZVVib29rc98QEgCRAJIAkwkMAB0AlQCWCQ0AHwCUCQ4AlwAKACEAmACZACQAmgATABMAEwAlAD8AXgBeCRYALQBeAFAAXgNaCQMAXgBeCR4AXl8QIFhEQnVja2V0Rm9yU3RlcmVvdHlwZXN3YXNFbmNvZGVkXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc3N0b3JhZ2VfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzb3JkZXJlZIAAgACAAIAEgNIICIDoCIALCICMgOQICIDnCBI2Yumu0wA2ADcACgkiCSUAQKIBaANkgDGAb6IJJgkngOmA9IAk2QAdACEJKgAKACQJKwAfAE8JLAkGAWgAUABvABMAJQAtAF4JNF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYDmgDGAC4AqgACABAiA6tMANgA3AAoJNgk/AECoAX4BfwGAAYEBggGDAYQBhYA1gDaAN4A4gDmAOoA7gDyoCUAJQQlCCUMJRAlFCUYJR4DrgOyA7YDvgPCA8YDygPOAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwkmAF4AXgBeAC0AXgCjAX4AXgBeABMAXoAAgCGAAIDpCAgICIAbgDUICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwkmAF4AXgBeAC0AXgCjAX8AXgBeABMAXoAAgACAAIDpCAgICIAbgDYICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATCWkAEwkmAF4AXgBeAC0AXgCjAYAAXgBeABMAXoAAgO6AAIDpCAgICIAbgDcICIAACNMANgA3AAoJdwl4AECgoIAk3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATCSYAXgBeAF4ALQBeAKMBgQBeAF4AEwBegACAIYAAgOkICAgIgBuAOAgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMB2gATCSYAXgBeAF4ALQBeAKMBggBeAF4AEwBegACAQ4AAgOkICAgIgBuAOQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATCSYAXgBeAF4ALQBeAKMBgwBeAF4AEwBegACAIYAAgOkICAgIgBuAOggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATCSYAXgBeAF4ALQBeAKMBhABeAF4AEwBegACAAIAAgOkICAgIgBuAOwgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATCSYAXgBeAF4ALQBeAKMBhQBeAF4AEwBegACAIYAAgOkICAgIgBuAPAgIgAAI2QAdACEJxgAKACQJxwAfAE8JyAkGA2QAUABvABMAJQAtAF4J0F8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYDmgG+AC4AqgACABAiA9dMANgA3AAoJ0gnaAECnBBQEFQQWBBcEGAQZBBqAfYB+gH+AgICBgIKAg6cJ2wncCd0J3gnfCeAJ4YD2gPeA+ID5gPqA+4D8gCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMJJwBeAF4AXgAtAF4AowQUAF4AXgATAF6AAIAAgACA9AgICAiAG4B9CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMJJwBeAF4AXgAtAF4AowQVAF4AXgATAF6AAIAhgACA9AgICAiAG4B+CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMJJwBeAF4AXgAtAF4AowQWAF4AXgATAF6AAIAAgACA9AgICAiAG4B/CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwbuABMJJwBeAF4AXgAtAF4AowQXAF4AXgATAF6AAIC6gACA9AgICAiAG4CACAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMJJwBeAF4AXgAtAF4AowQYAF4AXgATAF6AAIAAgACA9AgICAiAG4CBCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMJJwBeAF4AXgAtAF4AowQZAF4AXgATAF6AAIAAgACA9AgICAiAG4CCCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMJJwBeAF4AXgAtAF4AowQaAF4AXgATAF6AAIAAgACA9AgICAiAG4CDCAiAAAjfEBIAkQCSAJMKTQAdAJUAlgpOAB8AlApPAJcACgAhAJgAmQAkAJoAEwATABMAJQA/AF4AXgpXAC0AXgBQAF4BXwkEAF4AXgpfAF5fECBYREJ1Y2tldEZvclN0ZXJlb3R5cGVzd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNzdG9yYWdlXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc29yZGVyZWSAAIAAgACABIDSCAiA/wiACwiApYDlCAiA/ggStOFaC9MANgA3AAoKYwpmAECiAWgBaYAxgDKiCmcKaIEBAIEBC4Ak2QAdACEKawAKACQKbAAfAE8KbQkHAWgAUABvABMAJQAtAF4KdV8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYD9gDGAC4AqgACABAiBAQHTADYANwAKCncKgABAqAF+AX8BgAGBAYIBgwGEAYWANYA2gDeAOIA5gDqAO4A8qAqBCoIKgwqECoUKhgqHCoiBAQKBAQOBAQSBAQaBAQeBAQiBAQmBAQqAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwpnAF4AXgBeAC0AXgCjAX4AXgBeABMAXoAAgCGAAIEBAAgICAiAG4A1CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMKZwBeAF4AXgAtAF4AowF/AF4AXgATAF6AAIAAgACBAQAICAgIgBuANggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMKqgATCmcAXgBeAF4ALQBeAKMBgABeAF4AEwBegACBAQWAAIEBAAgICAiAG4A3CAiAAAjTADYANwAKCrgKuQBAoKCAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwpnAF4AXgBeAC0AXgCjAYEAXgBeABMAXoAAgCGAAIEBAAgICAiAG4A4CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMKZwBeAF4AXgAtAF4AowGCAF4AXgATAF6AAIBDgACBAQAICAgIgBuAOQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATCmcAXgBeAF4ALQBeAKMBgwBeAF4AEwBegACAIYAAgQEACAgICIAbgDoICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwpnAF4AXgBeAC0AXgCjAYQAXgBeABMAXoAAgACAAIEBAAgICAiAG4A7CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMKZwBeAF4AXgAtAF4AowGFAF4AXgATAF6AAIAhgACBAQAICAgIgBuAPAgIgAAI2QAdACELBwAKACQLCAAfAE8LCQkHAWkAUABvABMAJQAtAF4LEV8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYD9gDKAC4AqgACABAiBAQzTADYANwAKCxMLGwBApwIjAiQCJQImAicCKAIpgEmASoBLgEyATYBOgE+nCxwLHQseCx8LIAshCyKBAQ2BAQ6BAQ+BARCBARGBARKBAROAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAjwAEwpoAF4AXgBeAC0AXgCjAiMAXgBeABMAXoAAgFGAAIEBCwgICAiAG4BJCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwWGABMKaABeAF4AXgAtAF4AowIkAF4AXgATAF6AAICfgACBAQsICAgIgBuASggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMCPAATCmgAXgBeAF4ALQBeAKMCJQBeAF4AEwBegACAUYAAgQELCAgICIAbgEsICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAD4AEwpoAF4AXgBeAC0AXgCjAiYAXgBeABMAXoAAgFaAAIEBCwgICAiAG4BMCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMKaABeAF4AXgAtAF4AowInAF4AXgATAF6AAIBDgACBAQsICAgIgBuATQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATCmgAXgBeAF4ALQBeAKMCKABeAF4AEwBegACAIYAAgQELCAgICIAbgE4ICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATA0UAEwpoAF4AXgBeAC0AXgCjAikAXgBeABMAXoAAgL6AAIEBCwgICAiAG4BPCAiAAAhaZHVwbGljYXRlc9IANwAKC48Aq6CAGtIArQCuC5ILk1pYRFBNRW50aXR5pwuUC5ULlguXC5gLmQCyWlhEUE1FbnRpdHldWERVTUxDbGFzc0ltcF8QElhEVU1MQ2xhc3NpZmllckltcF8QEVhEVU1MTmFtZXNwYWNlSW1wXxAUWERVTUxOYW1lZEVsZW1lbnRJbXBfEA9YRFVNTEVsZW1lbnRJbXDfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMHRQBeAF4AXgAtAF4AowInAF4AXgATAF6AAIBDgACAzAgICAiAG4BNCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMHRQBeAF4AXgAtAF4AowIoAF4AXgATAF6AAIAhgACAzAgICAiAG4BOCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwkHABMHRQBeAF4AXgAtAF4AowIpAF4AXgATAF6AAID9gACAzAgICAiAG4BPCAiAAAjSADcACgvIAKuggBrfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMBbABeAF4AXgAtAF4AowInAF4AXgATAF6AAIBDgACARwgICAiAG4BNCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMBbABeAF4AXgAtAF4AowIoAF4AXgATAF6AAIAhgACARwgICAiAG4BOCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwNDABMBbABeAF4AXgAtAF4AowIpAF4AXgATAF6AAICNgACARwgICAiAG4BPCAiAAAjfEBIAkQCSAJML+AAdAJUAlgv5AB8AlAv6AJcACgAhAJgAmQAkAJoAEwATABMAJQA9AF4AXgwCAC0AXgBQAF4DWgFJAF4AXgwKAF5fECBYREJ1Y2tldEZvclN0ZXJlb3R5cGVzd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNzdG9yYWdlXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc29yZGVyZWSAAIAAgACABIAJCAiBASAIgAsIgIyALQgIgQEfCBJp38BV0wA2ADcACgwODBEAQKIBaANkgDGAb6IMEgwTgQEhgQEsgCTZAB0AIQwWAAoAJAwXAB8ATwwYAUwBaABQAG8AEwAlAC0AXgwgXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgQEegDGAC4AqgACABAiBASLTADYANwAKDCIMKwBAqAF+AX8BgAGBAYIBgwGEAYWANYA2gDeAOIA5gDqAO4A8qAwsDC0MLgwvDDAMMQwyDDOBASOBASSBASWBASeBASiBASmBASqBASuAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwwSAF4AXgBeAC0AXgCjAX4AXgBeABMAXoAAgCGAAIEBIQgICAiAG4A1CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMMEgBeAF4AXgAtAF4AowF/AF4AXgATAF6AAIAAgACBASEICAgIgBuANggIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMMVQATDBIAXgBeAF4ALQBeAKMBgABeAF4AEwBegACBASaAAIEBIQgICAiAG4A3CAiAAAjTADYANwAKDGMMZABAoKCAJN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATAOsAEwwSAF4AXgBeAC0AXgCjAYEAXgBeABMAXoAAgCGAAIEBIQgICAiAG4A4CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwHaABMMEgBeAF4AXgAtAF4AowGCAF4AXgATAF6AAIBDgACBASEICAgIgBuAOQgIgAAI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATDBIAXgBeAF4ALQBeAKMBgwBeAF4AEwBegACAIYAAgQEhCAgICIAbgDoICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwwSAF4AXgBeAC0AXgCjAYQAXgBeABMAXoAAgACAAIEBIQgICAiAG4A7CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwDrABMMEgBeAF4AXgAtAF4AowGFAF4AXgATAF6AAIAhgACBASEICAgIgBuAPAgIgAAI2QAdACEMsgAKACQMswAfAE8MtAFMA2QAUABvABMAJQAtAF4MvF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzb3JkZXJlZF8QJFhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzd2FzRW5jb2RlZF8QIVhEQnVja2V0Rm9yT3duZWRBdHRyaWJ1dGVzc3RvcmFnZYEBHoBvgAuAKoAAgAQIgQEt0wA2ADcACgy+DMYAQKcEFAQVBBYEFwQYBBkEGoB9gH6Af4CAgIGAgoCDpwzHDMgMyQzKDMsMzAzNgQEugQEwgQExgQEygQE0gQE1gQE2gCTfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwzRABMMEwBeAF4AXgAtAF4AowQUAF4AXgATAF6AAIEBL4AAgQEsCAgICIAbgH0ICIAACFEw3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMA6wATDBMAXgBeAF4ALQBeAKMEFQBeAF4AEwBegACAIYAAgQEsCAgICIAbgH4ICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwwTAF4AXgBeAC0AXgCjBBYAXgBeABMAXoAAgACAAIEBLAgICAiAG4B/CAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwz/ABMMEwBeAF4AXgAtAF4AowQXAF4AXgATAF6AAIEBM4AAgQEsCAgICIAbgIAICIAACBDI3xAPAJEAkgCTAB0AlACVAJYAHwCXAAoAIQCYAJkAJACaABMAEwATDBMAXgBeAF4ALQBeAKMEGABeAF4AEwBegACAAIAAgQEsCAgICIAbgIEICIAACN8QDwCRAJIAkwAdAJQAlQCWAB8AlwAKACEAmACZACQAmgATABMAEwwTAF4AXgBeAC0AXgCjBBkAXgBeABMAXoAAgACAAIEBLAgICAiAG4CCCAiAAAjfEA8AkQCSAJMAHQCUAJUAlgAfAJcACgAhAJgAmQAkAJoAEwATABMMEwBeAF4AXgAtAF4AowQaAF4AXgATAF6AAIAAgACBASwICAgIgBuAgwgIgAAI0gA3AAoNOwCroIAa0wA2ADcACg0+DT8AQKCggCTTADYANwAKDUINQwBAoKCAJNMANgA3AAoNRg1HAECgoIAk0gCtAK4NSg1LXlhETW9kZWxQYWNrYWdlpg1MDU0NTg1PDVAAsl5YRE1vZGVsUGFja2FnZV8QD1hEVU1MUGFja2FnZUltcF8QEVhEVU1MTmFtZXNwYWNlSW1wXxAUWERVTUxOYW1lZEVsZW1lbnRJbXBfEA9YRFVNTEVsZW1lbnRJbXDSADcACg1SAKuggBrTADYANwAKDVUNVgBAoKCAJFDSAK0Arg1aDVtZWERQTU1vZGVsow1cDV0AsllYRFBNTW9kZWxXWERNb2RlbF8QD05TS2V5ZWRBcmNoaXZlctENYAAoVHJvb3SAAQAIABkAIgArADUAOgA/AsMCyQLmAvgC/wMMAx8DNwNFA18DYQNkA2cDaQNsA24DcQOqA8kD5gQFBBcENwQ+BFwEaASEBIoErATNBOAE4gTlBOgE6gTsBO4E8QT0BPYE+AT6BPwE/gUABQEFBQUSBRoFJQUsBS4FMAUyBTkFOwU9BT8FQQVGBUsFUgWVBbkF3QYABicGRwZuBpUGtQbZBv0HCQcLBw0HDwcRBxMHFQcYBxoHHAcfByEHIwcmBygHKQcuBzYHQwdGB0gHSwdNB08HXgeDB6cHzgfyB/QH9gf4B/oH/Af+B/8IAQgOCB8IIQgjCCUIJwgpCCsILQgvCEAIQghECEYISAhKCEwITghQCFIIaAh7CJgItAjICNoI8AkJCUgJTglXCWQJcAl6CYQJjwmaCacJrwmxCbMJtQm3CbgJuQm6CbsJvQm/CcAJwQnDCcQJzQnOCdAJ2QnkCe0J/AoDCgsKFAodCjAKOQpMCmMKdQq0CrYKuAq6CrwKvQq+Cr8KwArCCsQKxQrGCsgKyQsICwoLDAsOCxALEQsSCxMLFAsWCxgLGQsaCxwLHQtcC14LYAtiC2QLZQtmC2cLaAtqC2wLbQtuC3ALcQt6C3sLfQu8C74LwAvCC8QLxQvGC8cLyAvKC8wLzQvOC9AL0QvSDBEMEwwVDBcMGQwaDBsMHAwdDB8MIQwiDCMMJQwmDDMMNAw1DDcMQAxWDF0MagypDKsMrQyvDLEMsgyzDLQMtQy3DLkMugy7DL0MvgzXDNkM2wzdDN4M4Az3DQANDg0bDSkNPg1SDWkNew26DbwNvg3ADcINww3EDcUNxg3IDcoNyw3MDc4Nzw3YDe0N/A4RDh8ONA5IDl8OcQ5+DoMOhQ6HDowOjg6RDpMOmQ6gDusPDg8uD04PUA9SD1QPVg9YD1kPWg9cD10PXw9gD2IPZA9lD2YPaA9pD24Pew+AD4IPhA+JD4sPjQ+PD6QPtw/cEAAQJxBLEE0QTxBREFMQVRBXEFgQWhBnEHgQehB8EH4QgBCCEIQQhhCIEJkQmxCdEJ8QoRCjEKUQpxCpEKsQyRDnEPoRDhEjEUARVBFqEakRqxGtEa8RsRGyEbMRtBG1EbcRuRG6EbsRvRG+Ef0R/xIBEgMSBRIGEgcSCBIJEgsSDRIOEg8SERISElESUxJVElcSWRJaElsSXBJdEl8SYRJiEmMSZRJmEnMSdBJ1EncSthK4EroSvBK+Er8SwBLBEsISxBLGEscSyBLKEssTChMMEw4TEBMSExMTFBMVExYTGBMaExsTHBMeEx8TIBNfE2ETYxNlE2cTaBNpE2oTaxNtE28TcBNxE3MTdBOzE7UTtxO5E7sTvBO9E74TvxPBE8MTxBPFE8cTyBQHFAkUCxQNFA8UEBQRFBIUExQVFBcUGBQZFBsUHBRBFGUUjBSwFLIUtBS2FLgUuhS8FL0UvxTMFNsU3RTfFOEU4xTlFOcU6RT4FPoU/BT+FQAVAxUGFQkVCxUdFTEVQxVYFWoVeRWWFdUV1xXZFdsV3RXeFd8V4BXhFeMV5RXmFecV6RXqFikWKxYtFi8WMRYyFjMWNBY1FjcWORY6FjsWPRY+FkAWfxaBFoMWhRaHFogWiRaKFosWjRaPFpAWkRaTFpQW0xbVFtcW2RbbFtwW3RbeFt8W4RbjFuQW5RbnFugXKxdPF3MXlhe9F90YBBgrGEsYbxiTGJUYlxiZGJsYnRifGKIYpBimGKkYqxitGLAYshizGLgYxRjIGMoYzRjPGNEY9hkaGUEZZRlnGWkZaxltGW8ZcRlyGXQZgRmSGZQZlhmYGZoZnBmeGaAZohmzGbUZtxm5GbsZvRm/GcEZwxnFGgQaBhoIGgoaDBoNGg4aDxoQGhIaFBoVGhYaGBoZGiIaIxolGmQaZhpoGmoabBptGm4abxpwGnIadBp1GnYaeBp5Grgauhq8Gr4awBrBGsIawxrEGsYayBrJGsoazBrNGwwbDhsQGxIbFBsVGxYbFxsYGxobHBsdGx4bIBshGyobKxstG2wbbhtwG3IbdBt1G3Ybdxt4G3obfBt9G34bgBuBG8AbwhvEG8YbyBvJG8obyxvMG84b0BvRG9Ib1BvVG+Ib4xvkG+YcJRwnHCkcKxwtHC4cLxwwHDEcMxw1HDYcNxw5HDoceRx7HH0cfxyBHIIcgxyEHIUchxyJHIocixyNHI4ckxygHKkcqxytHK8csRy6HLwcvhzAHMIcxBzMHNIc2BzgHSsdTh1uHY4dkB2SHZQdlh2YHZkdmh2cHZ0dnx2gHaIdpB2lHaYdqB2pHa4dux3AHcIdxB3JHcsdzR3PHeQeCR4tHlQeeB56Hnwefh6AHoIehB6FHocelB6lHqceqR6rHq0erx6xHrMetR7GHsgeyh7MHs4e0B7SHtQe1h7YHxcfGR8bHx0fHx8gHyEfIh8jHyUfJx8oHykfKx8sH2sfbR9vH3Efcx90H3Ufdh93H3kfex98H30ffx+AH78fwR/DH8Ufxx/IH8kfyh/LH80fzx/QH9Ef0x/UH+Ef4h/jH+UgJCAmICggKiAsIC0gLiAvIDAgMiA0IDUgNiA4IDkgeCB6IHwgfiCAIIEggiCDIIQghiCIIIkgiiCMII0gzCDOINAg0iDU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OBc4GTgbOB04HzheOGA4YjhkOGY4ZzhoOGk4ajhsOG44bzhwOHI4cziyOLQ4tji4OLo4uzi8OL04vjjAOMI4wzjEOMY4xzkGOQg5CjkMOQ45DzkQORE5EjkUORY5FzkYORo5GzkoOSk5KjksOWs5bTlvOXE5czl0OXU5djl3OXk5ezl8OX05fzmAOb85wTnDOcU5xznIOck5yjnLOc05zznQOdE50znUOhM6FToXOhk6GzocOh06HjofOiE6IzokOiU6JzooOmc6aTprOm06bzpwOnE6cjpzOnU6dzp4Onk6ezp8Ors6vTq/OsE6wzrEOsU6xjrHOsk6yzrMOs06zzrQOvU7GTtAO2Q7ZjtoO2o7bDtuO3A7cTtzO4A7jzuRO5M7lTuXO5k7mzudO6w7rjuwO7I7tDu3O7o7vTu/O/48ADwCPAQ8BjwHPAg8CTwKPAw8DjwPPBA8EjwTPFI8VDxWPFg8WjxbPFw8XTxePGA8YjxjPGQ8ZjxnPKY8qDyqPKw8rjyvPLA8sTyyPLQ8tjy3PLg8ujy7PPo8/Dz+PQA9Aj0DPQQ9BT0GPQg9Cj0LPQw9Dj0PPVI9dj2aPb095D4EPis+Uj5yPpY+uj68Pr4+wD7CPsQ+xj7JPss+zT7QPtI+1D7XPtk+2j7fPuw+7z7xPvQ+9j74Px0/QT9oP4w/jj+QP5I/lD+WP5g/mT+bP6g/uT+7P70/vz/BP8M/xT/HP8k/2j/cP94/4D/iP+Q/5j/oP+o/7EArQC1AL0AxQDNANEA1QDZAN0A5QDtAPEA9QD9AQEBJQEpATECLQI1Aj0CRQJNAlECVQJZAl0CZQJtAnECdQJ9AoEDfQOFA40DlQOdA6EDpQOpA60DtQO9A8EDxQPNA9EEzQTVBN0E5QTtBPEE9QT5BP0FBQUNBREFFQUdBSEFRQVJBVEGTQZVBl0GZQZtBnEGdQZ5Bn0GhQaNBpEGlQadBqEHnQelB60HtQe9B8EHxQfJB80H1QfdB+EH5QftB/EIJQgpCC0INQkxCTkJQQlJCVEJVQlZCV0JYQlpCXEJdQl5CYEJhQqBCokKkQqZCqEKpQqpCq0KsQq5CsEKxQrJCtEK1QrxCyULOQtBC0kLXQtlC20LdQuJC6EMzQ1ZDdkOWQ5hDmkOcQ55DoEOhQ6JDpEOlQ6dDqEOqQ6xDrUOuQ7BDsUO2Q8NDyEPKQ8xD0UPTQ9VD10P8RCBER0RrRG1Eb0RxRHNEdUR3RHhEekSHRJhEmkScRJ5EoESiRKREpkSoRLlEu0S9RL9EwUTDRMVEx0TJRMtFCkUMRQ5FEEUSRRNFFEUVRRZFGEUaRRtFHEUeRR9FXkVgRWJFZEVmRWdFaEVpRWpFbEVuRW9FcEVyRXNFskW0RbZFuEW6RbtFvEW9Rb5FwEXCRcNFxEXGRcdF1EXVRdZF2EYXRhlGG0YdRh9GIEYhRiJGI0YlRidGKEYpRitGLEZrRm1Gb0ZxRnNGdEZ1RnZGd0Z5RntGfEZ9Rn9GgEa/RsFGw0bFRsdGyEbJRspGy0bNRs9G0EbRRtNG1EcTRxVHF0cZRxtHHEcdRx5HH0chRyNHJEclRydHKEdnR2lHa0dtR29HcEdxR3JHc0d1R3dHeEd5R3tHfEehR8VH7EgQSBJIFEgWSBhIGkgcSB1IH0gsSDtIPUg/SEFIQ0hFSEdISUhYSFpIXEheSGBIYkhkSGZIaEinSKlIq0itSK9IsEixSLJIs0i1SLdIuEi5SLtIvEj7SP1I/0kBSQNJBEkFSQZJB0kJSQtJDEkNSQ9JEElPSVFJU0lVSVdJWElZSVpJW0ldSV9JYElhSWNJZEmjSaVJp0mpSatJrEmtSa5Jr0mxSbNJtEm1SbdJuEn3SflJ+0n9Sf9KAEoBSgJKA0oFSgdKCEoJSgtKDEpLSk1KT0pRSlNKVEpVSlZKV0pZSltKXEpdSl9KYEqfSqFKo0qlSqdKqEqpSqpKq0qtSq9KsEqxSrNKtEr/SyJLQktiS2RLZktoS2pLbEttS25LcEtxS3NLdEt2S3hLeUt6S3xLfUuCS49LlEuWS5hLnUugS6NLpUvKS+5MFUw5TDtMPUw/TEFMQ0xFTEZMSUxWTGdMaUxrTG1Mb0xxTHNMdUx3TIhMi0yOTJFMlEyXTJpMnUygTKJM4UzjTOVM50zqTOtM7EztTO5M8EzyTPNM9Ez2TPdNNk04TTpNPE0/TUBNQU1CTUNNRU1HTUhNSU1LTUxNi02NTZBNkk2VTZZNl02YTZlNm02dTZ5Nn02hTaJNr02wTbFNs03yTfRN9k34TftN/E39Tf5N/04BTgNOBE4FTgdOCE5HTklOS05NTlBOUU5STlNOVE5WTlhOWU5aTlxOXU6cTp5OoE6iTqVOpk6nTqhOqU6rTq1Ork6vTrFOsk7xTvNO9U73TvpO+078Tv1O/k8ATwJPA08ETwZPB09GT0hPSk9MT09PUE9RT1JPU09VT1dPWE9ZT1tPXE+BT6VPzE/wT/JP9E/2T/hP+k/8T/1QAFANUBxQHlAgUCJQJFAmUChQKlA5UDxQP1BCUEVQSFBLUE5QUFCPUJFQk1CVUJhQmVCaUJtQnFCeUKBQoVCiUKRQpVDkUOZQ6FDqUO1Q7lDvUPBQ8VDzUPVQ9lD3UPlQ+lE5UTtRPVE/UUJRQ1FEUUVRRlFIUUpRS1FMUU5RT1GOUZBRklGUUZdRmFGZUZpRm1GdUZ9RoFGhUaNRpFHjUeVR51HpUexR7VHuUe9R8FHyUfRR9VH2UfhR+VI4UjpSPFI+UkFSQlJDUkRSRVJHUklSSlJLUk1STlKNUo9SkVKTUpZSl1KYUplSmlKcUp5Sn1KgUqJSo1KuUrdSuFK6UsNSzlLdUuhS9lMLUx9TNlNIU4dTiVOLU41Tj1OQU5FTklOTU5VTl1OYU5lTm1OcU9tT3VPfU+FT41PkU+VT5lPnU+lT61PsU+1T71PwVC9UMVQzVDVUN1Q4VDlUOlQ7VD1UP1RAVEFUQ1REVE1UTlRQVI9UkVSTVJVUl1SYVJlUmlSbVJ1Un1SgVKFUo1SkVONU5VTnVOlU61TsVO1U7lTvVPFU81T0VPVU91T4VTdVOVU7VT1VP1VAVUFVQlVDVUVVR1VIVUlVS1VMVZdVulXaVfpV/FX+VgBWAlYEVgVWBlYJVgpWDFYNVg9WEVYSVhNWFlYXVhxWKVYuVjBWMlY3VjpWPVY/VmRWiFavVtNW1lbYVtpW3FbeVuBW4VbkVvFXAlcEVwZXCFcKVwxXDlcQVxJXI1cmVylXLFcvVzJXNVc4VztXPVd8V35XgFeCV4VXhleHV4hXiVeLV41XjlePV5FXklfRV9NX1VfXV9pX21fcV91X3lfgV+JX41fkV+ZX51gmWChYK1gtWDBYMVgyWDNYNFg2WDhYOVg6WDxYPVhKWEtYTFhOWI1Yj1iRWJNYlliXWJhYmViaWJxYnlifWKBYolijWOJY5FjmWOhY61jsWO1Y7ljvWPFY81j0WPVY91j4WTdZOVk7WT1ZQFlBWUJZQ1lEWUZZSFlJWUpZTFlNWYxZjlmQWZJZlVmWWZdZmFmZWZtZnVmeWZ9ZoVmiWeFZ41nlWedZ6lnrWexZ7VnuWfBZ8lnzWfRZ9ln3WhxaQFpnWotajlqQWpJalFqWWphamVqcWqlauFq6WrxavlrAWsJaxFrGWtVa2FrbWt5a4VrkWuda6lrsWytbLVswWzJbNVs2WzdbOFs5WztbPVs+Wz9bQVtCW0Rbg1uFW4dbiVuMW41bjluPW5BbkluUW5VblluYW5lb2FvaW9xb3lvhW+Jb41vkW+Vb51vpW+pb61vtW+5cLVwvXDJcNFw3XDhcOVw6XDtcPVw/XEBcQVxDXERcRlyFXIdciVyLXI5cj1yQXJFcklyUXJZcl1yYXJpcm1zaXNxc3lzgXONc5FzlXOZc51zpXOtc7FztXO9c8F0vXTFdM101XThdOV06XTtdPF0+XUBdQV1CXURdRV1OXU9dUV1eXV9dYF1iXW9dcF1xXXNdgF2BXYJdhF2NXZxdqV24Xcpd3l31XgdeEF4RXhNeIF4hXiJeJF4lXi5eOF4/XkleUV5jXmhebQAAAAAAAAICAAAAAAAADWIAAAAAAAAAAAAAAAAAAF5v 68 | 69 | 70 | 71 | 72 | name 73 | 74 | 75 | 76 | 1 77 | books 78 | 79 | 80 | 81 | 1 82 | authors 83 | 84 | 85 | 86 | YnBsaXN0MDDUAQIDBAUGGhtYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoKUH 87 | CBESE1UkbnVsbNMJCgsMDhBXTlMua2V5c1pOUy5vYmplY3RzViRjbGFzc6ENgAKhD4ADgARcbW9kZWxWZXJzaW9uUTLSFBUWF1okY2xhc3NuYW1lWCRjbGFzc2VzXxATTlNNdXRhYmxlRGljdGlvbmFyeaMWGBlcTlNEaWN0aW9uYXJ5WE5TT2JqZWN0XxAPTlNLZXllZEFyY2hpdmVy0RwdVHJvb3SAAQgRGiMtMjc9Q0pSXWRmaGpsbnt9go2WrLC9xtjb4AAAAAAAAAEBAAAAAAAAAB4AAAAAAAAAAAAAAAAAAADi 88 | 89 | MHWBookToBookPolicy 90 | Book 91 | Undefined 92 | 3 93 | Book 94 | 1 95 | 96 | 97 | 98 | 99 | 100 | fileURL 101 | 102 | 103 | 104 | 1 105 | users 106 | 107 | 108 | 109 | Undefined 110 | 2 111 | Author 112 | 1 113 | 114 | 115 | 116 | 117 | 118 | User 119 | Undefined 120 | 1 121 | User 122 | 1 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /BookMigration/NSFileManager+MHWAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+MHWAdditions.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSFileManager (MHWAdditions) 12 | 13 | + (NSURL *)urlToApplicationSupportDirectory; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /BookMigration/NSFileManager+MHWAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+MHWAdditions.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "NSFileManager+MHWAdditions.h" 10 | 11 | @implementation NSFileManager (MHWAdditions) 12 | 13 | + (NSURL *)urlToApplicationSupportDirectory 14 | { 15 | NSString *applicationSupportDirectory = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, 16 | NSUserDomainMask, 17 | YES) objectAtIndex:0]; 18 | BOOL isDir = NO; 19 | NSError *error = nil; 20 | NSFileManager *fileManager = [[NSFileManager alloc] init]; 21 | if (![fileManager fileExistsAtPath:applicationSupportDirectory 22 | isDirectory:&isDir] && isDir == NO) { 23 | [fileManager createDirectoryAtPath:applicationSupportDirectory 24 | withIntermediateDirectories:NO 25 | attributes:nil 26 | error:&error]; 27 | } 28 | return [NSURL fileURLWithPath:applicationSupportDirectory]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /BookMigration/NSManagedObjectModel+MHWAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectModel+MHWAdditions.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/7/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSManagedObjectModel (MHWAdditions) 12 | 13 | + (NSArray *)mhw_allModelPaths; 14 | - (NSString *)mhw_modelName; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /BookMigration/NSManagedObjectModel+MHWAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectModel+MHWAdditions.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/7/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "NSManagedObjectModel+MHWAdditions.h" 10 | 11 | @implementation NSManagedObjectModel (MHWAdditions) 12 | 13 | + (NSArray *)mhw_allModelPaths 14 | { 15 | //Find all of the mom and momd files in the Resources directory 16 | NSMutableArray *modelPaths = [NSMutableArray array]; 17 | NSArray *momdArray = [[NSBundle mainBundle] pathsForResourcesOfType:@"momd" 18 | inDirectory:nil]; 19 | for (NSString *momdPath in momdArray) { 20 | NSString *resourceSubpath = [momdPath lastPathComponent]; 21 | NSArray *array = [[NSBundle mainBundle] pathsForResourcesOfType:@"mom" 22 | inDirectory:resourceSubpath]; 23 | [modelPaths addObjectsFromArray:array]; 24 | } 25 | NSArray *otherModels = [[NSBundle mainBundle] pathsForResourcesOfType:@"mom" 26 | inDirectory:nil]; 27 | [modelPaths addObjectsFromArray:otherModels]; 28 | return modelPaths; 29 | } 30 | 31 | - (NSString *)mhw_modelName 32 | { 33 | NSString *modelName = nil; 34 | NSArray *modelPaths = [[self class] mhw_allModelPaths]; 35 | for (NSString *modelPath in modelPaths) { 36 | NSURL *modelURL = [NSURL fileURLWithPath:modelPath]; 37 | NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 38 | if ([model isEqual:self]) { 39 | modelName = modelURL.lastPathComponent.stringByDeletingPathExtension; 40 | break; 41 | } 42 | } 43 | return modelName; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /BookMigration/NSMigrationManager+Lookup.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMigrationManager+Lookup.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/1/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMigrationManager (Lookup) 12 | 13 | - (NSMutableDictionary *)lookupWithKey:(NSString *)lookupKey; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /BookMigration/NSMigrationManager+Lookup.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMigrationManager+Lookup.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/1/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "NSMigrationManager+Lookup.h" 10 | 11 | @implementation NSMigrationManager (Lookup) 12 | 13 | - (NSMutableDictionary *)lookupWithKey:(NSString *)lookupKey 14 | { 15 | NSMutableDictionary *userInfo = (NSMutableDictionary *)self.userInfo; 16 | // Check if we've already created a userInfo dictionary 17 | if (!userInfo) { 18 | userInfo = [@{} mutableCopy]; 19 | self.userInfo = userInfo; 20 | } 21 | 22 | NSMutableDictionary *lookup = [userInfo valueForKey:lookupKey]; 23 | if (!lookup) { 24 | lookup = [@{} mutableCopy]; 25 | [userInfo setValue:lookup forKey:lookupKey]; 26 | } 27 | return lookup; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /BookMigration/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /BookMigration/en.lproj/MHWViewController_iPad.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 13A558 6 | 3084 7 | 1249.11 8 | 691.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUITableView 17 | IBUIView 18 | 19 | 20 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 21 | 22 | 23 | PluginDependencyRecalculationVersion 24 | 25 | 26 | 27 | 28 | IBFilesOwner 29 | IBIPadFramework 30 | 31 | 32 | IBFirstResponder 33 | IBIPadFramework 34 | 35 | 36 | 37 | 274 38 | 39 | 40 | 41 | 274 42 | {768, 1004} 43 | 44 | 45 | _NS:9 46 | 47 | 3 48 | MQA 49 | 50 | YES 51 | IBIPadFramework 52 | YES 53 | 1 54 | 0 55 | YES 56 | 44 57 | 22 58 | 22 59 | 60 | 61 | {{0, 20}, {768, 1004}} 62 | 63 | 64 | 65 | 66 | 3 67 | MQA 68 | 69 | 2 70 | 71 | 72 | 73 | 2 74 | 75 | IBIPadFramework 76 | 77 | 78 | 79 | 80 | 81 | 82 | view 83 | 84 | 85 | 86 | 3 87 | 88 | 89 | 90 | tableView 91 | 92 | 93 | 94 | 13 95 | 96 | 97 | 98 | dataSource 99 | 100 | 101 | 102 | 14 103 | 104 | 105 | 106 | delegate 107 | 108 | 109 | 110 | 15 111 | 112 | 113 | 114 | 115 | 116 | 0 117 | 118 | 119 | 120 | 121 | 122 | -1 123 | 124 | 125 | File's Owner 126 | 127 | 128 | -2 129 | 130 | 131 | 132 | 133 | 2 134 | 135 | 136 | 137 | 138 | 139 | 4 140 | 0 141 | 142 | 4 143 | 1 144 | 145 | 0.0 146 | 147 | 1000 148 | 149 | 8 150 | 29 151 | 3 152 | 153 | 154 | 155 | 3 156 | 0 157 | 158 | 3 159 | 1 160 | 161 | 0.0 162 | 163 | 1000 164 | 165 | 8 166 | 29 167 | 3 168 | 169 | 170 | 171 | 5 172 | 0 173 | 174 | 5 175 | 1 176 | 177 | 0.0 178 | 179 | 1000 180 | 181 | 8 182 | 29 183 | 3 184 | 185 | 186 | 187 | 6 188 | 0 189 | 190 | 6 191 | 1 192 | 193 | 0.0 194 | 195 | 1000 196 | 197 | 8 198 | 29 199 | 3 200 | 201 | 202 | 203 | 204 | 205 | 4 206 | 207 | 208 | 209 | 210 | 211 | 9 212 | 213 | 214 | 215 | 216 | 10 217 | 218 | 219 | 220 | 221 | 11 222 | 223 | 224 | 225 | 226 | 12 227 | 228 | 229 | 230 | 231 | 232 | 233 | MHWViewController 234 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 235 | UIResponder 236 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 237 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 238 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 239 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 240 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 241 | 242 | 243 | 244 | 245 | 246 | 247 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 248 | 249 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 250 | 251 | 252 | 253 | 254 | 255 | 15 256 | 257 | 258 | 259 | 260 | MHWViewController 261 | UIViewController 262 | 263 | tableView 264 | UITableView 265 | 266 | 267 | tableView 268 | 269 | tableView 270 | UITableView 271 | 272 | 273 | 274 | IBProjectSource 275 | ./Classes/MHWViewController.h 276 | 277 | 278 | 279 | NSLayoutConstraint 280 | NSObject 281 | 282 | IBProjectSource 283 | ./Classes/NSLayoutConstraint.h 284 | 285 | 286 | 287 | 288 | 0 289 | IBIPadFramework 290 | YES 291 | 3 292 | YES 293 | 2083 294 | 295 | 296 | -------------------------------------------------------------------------------- /BookMigration/en.lproj/MHWViewController_iPhone.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 13A558 6 | 3084 7 | 1249.11 8 | 691.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUITableView 17 | IBUIView 18 | 19 | 20 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 21 | 22 | 23 | PluginDependencyRecalculationVersion 24 | 25 | 26 | 27 | 28 | IBFilesOwner 29 | IBCocoaTouchFramework 30 | 31 | 32 | IBFirstResponder 33 | IBCocoaTouchFramework 34 | 35 | 36 | 37 | 274 38 | 39 | 40 | 41 | 274 42 | {320, 548} 43 | 44 | 45 | _NS:9 46 | 47 | 3 48 | MQA 49 | 50 | YES 51 | IBCocoaTouchFramework 52 | YES 53 | 1 54 | 0 55 | YES 56 | 44 57 | 22 58 | 22 59 | 60 | 61 | {{0, 20}, {320, 548}} 62 | 63 | 64 | 65 | 66 | 3 67 | MC43NQA 68 | 69 | 2 70 | 71 | 72 | NO 73 | 74 | 75 | IBUIScreenMetrics 76 | 77 | YES 78 | 79 | 80 | 81 | 82 | 83 | {320, 568} 84 | {568, 320} 85 | 86 | 87 | IBCocoaTouchFramework 88 | Retina 4 Full Screen 89 | 2 90 | 91 | IBCocoaTouchFramework 92 | 93 | 94 | 95 | 96 | 97 | 98 | view 99 | 100 | 101 | 102 | 7 103 | 104 | 105 | 106 | tableView 107 | 108 | 109 | 110 | 15 111 | 112 | 113 | 114 | dataSource 115 | 116 | 117 | 118 | 16 119 | 120 | 121 | 122 | delegate 123 | 124 | 125 | 126 | 17 127 | 128 | 129 | 130 | 131 | 132 | 0 133 | 134 | 135 | 136 | 137 | 138 | -1 139 | 140 | 141 | File's Owner 142 | 143 | 144 | -2 145 | 146 | 147 | 148 | 149 | 6 150 | 151 | 152 | 153 | 154 | 155 | 4 156 | 0 157 | 158 | 4 159 | 1 160 | 161 | 0.0 162 | 163 | 1000 164 | 165 | 8 166 | 29 167 | 3 168 | 169 | 170 | 171 | 3 172 | 0 173 | 174 | 3 175 | 1 176 | 177 | 0.0 178 | 179 | 1000 180 | 181 | 8 182 | 29 183 | 3 184 | 185 | 186 | 187 | 5 188 | 0 189 | 190 | 5 191 | 1 192 | 193 | 0.0 194 | 195 | 1000 196 | 197 | 8 198 | 29 199 | 3 200 | 201 | 202 | 203 | 6 204 | 0 205 | 206 | 6 207 | 1 208 | 209 | 0.0 210 | 211 | 1000 212 | 213 | 8 214 | 29 215 | 3 216 | 217 | 218 | 219 | 220 | 221 | 8 222 | 223 | 224 | 225 | 226 | 227 | 10 228 | 229 | 230 | 231 | 232 | 11 233 | 234 | 235 | 236 | 237 | 13 238 | 239 | 240 | 241 | 242 | 14 243 | 244 | 245 | 246 | 247 | 248 | 249 | MHWViewController 250 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 251 | UIResponder 252 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 253 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 254 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 255 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 256 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 257 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 258 | 259 | 260 | 261 | 262 | 263 | 264 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 265 | 266 | 267 | 268 | 269 | 270 | 271 | 17 272 | 273 | 274 | 275 | 276 | MHWViewController 277 | UIViewController 278 | 279 | tableView 280 | UITableView 281 | 282 | 283 | tableView 284 | 285 | tableView 286 | UITableView 287 | 288 | 289 | 290 | IBProjectSource 291 | ./Classes/MHWViewController.h 292 | 293 | 294 | 295 | NSLayoutConstraint 296 | NSObject 297 | 298 | IBProjectSource 299 | ./Classes/NSLayoutConstraint.h 300 | 301 | 302 | 303 | 304 | 0 305 | IBCocoaTouchFramework 306 | YES 307 | 3 308 | YES 309 | 2083 310 | 311 | 312 | -------------------------------------------------------------------------------- /BookMigration/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MHWAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([MHWAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /BookMigrationTests/BookMigrationTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.hwaxxer.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /BookMigrationTests/MHWCoreDataTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWCoreDataTests.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/31/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MHWCoreDataTests : SenTestCase 12 | 13 | 14 | - (void)setUpCoreDataStackMigratingFromStoreWithName:(NSString *)name; 15 | 16 | @property (nonatomic, strong) NSManagedObjectModel *managedObjectModel; 17 | @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 18 | @property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /BookMigrationTests/MHWCoreDataTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWCoreDataTests.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 8/31/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWCoreDataTests.h" 10 | #import "MHWMigrationManager.h" 11 | #import "MHWCoreDataController.h" 12 | 13 | @implementation MHWCoreDataTests 14 | 15 | - (void)setUpCoreDataStackMigratingFromStoreWithName:(NSString *)name 16 | { 17 | NSURL *storeURL = [self temporaryRandomURL]; 18 | [self copyStoreWithName:name toURL:storeURL]; 19 | 20 | NSURL *momURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"]; 21 | self.managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 22 | 23 | NSString *storeType = NSSQLiteStoreType; 24 | 25 | MHWMigrationManager *migrationManager = [MHWMigrationManager new]; 26 | migrationManager.delegate = [MHWCoreDataController sharedInstance]; 27 | NSError *error = nil; 28 | if (![migrationManager progressivelyMigrateURL:storeURL 29 | ofType:storeType 30 | toModel:self.managedObjectModel 31 | error:&error]) { 32 | NSLog(@"error migrating: %@", error); 33 | } 34 | 35 | self.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel]; 36 | [self.persistentStoreCoordinator addPersistentStoreWithType:storeType 37 | configuration:nil 38 | URL:storeURL 39 | options:nil 40 | error:nil]; 41 | 42 | self.managedObjectContext = [[NSManagedObjectContext alloc] init]; 43 | self.managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator; 44 | } 45 | 46 | - (NSURL *)temporaryRandomURL 47 | { 48 | NSString *uniqueName = [NSProcessInfo processInfo].globallyUniqueString; 49 | return [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingString:uniqueName]]; 50 | } 51 | 52 | - (void)copyStoreWithName:(NSString *)name toURL:(NSURL *)url 53 | { 54 | // Create a unique url every test so migration always runs 55 | NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 56 | NSFileManager *fileManager = [NSFileManager new]; 57 | NSString *path = [bundle pathForResource:[name stringByDeletingPathExtension] ofType:name.pathExtension]; 58 | [fileManager copyItemAtPath:path 59 | toPath:url.path error:nil]; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /BookMigrationTests/MHWMigrationFromModel1Tests.h: -------------------------------------------------------------------------------- 1 | // 2 | // BookMigrationTests.h 3 | // BookMigrationTests 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWCoreDataTests.h" 10 | 11 | @interface MHWMigrationFromModel1Tests : MHWCoreDataTests 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /BookMigrationTests/MHWMigrationFromModel1Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BookMigrationTests.m 3 | // BookMigrationTests 4 | // 5 | // Created by Martin Hwasser on 8/26/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWMigrationFromModel1Tests.h" 10 | #import "MHWMigrationManager.h" 11 | 12 | @implementation MHWMigrationFromModel1Tests 13 | 14 | - (void)tearDown 15 | { 16 | // Tear-down code here. 17 | 18 | [super tearDown]; 19 | } 20 | 21 | - (void)setUp 22 | { 23 | [super setUp]; 24 | [self setUpCoreDataStackMigratingFromStoreWithName:@"Model1.sqlite"]; 25 | } 26 | 27 | - (void)testThatUsersExist 28 | { 29 | NSManagedObjectContext *moc = self.managedObjectContext; 30 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"User"]; 31 | NSArray *users = [moc executeFetchRequest:request error:nil]; 32 | STAssertTrue(0 < users.count, @"Users have disappeared after migration"); 33 | } 34 | 35 | - (void)testThatAuthorsExists 36 | { 37 | NSManagedObjectContext *moc = self.managedObjectContext; 38 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Book"]; 39 | NSArray *books = [moc executeFetchRequest:request error:nil]; 40 | STAssertTrue(0 < books.count, @"Books have disappeared after migration"); 41 | for (NSManagedObject *book in books) { 42 | STAssertNotNil([book valueForKey:@"authors"], @"No authors"); 43 | } 44 | } 45 | 46 | - (void)testThatAuthorNameIsUnique 47 | { 48 | NSManagedObjectContext *moc = self.managedObjectContext; 49 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Author"]; 50 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name LIKE 'Franz Kafka'"]; 51 | request.predicate = predicate; 52 | NSInteger count = [moc countForFetchRequest:request error:nil]; 53 | STAssertTrue(1 == count, @"Wrong count for authors: %d", count); 54 | } 55 | 56 | - (void)testCreatedTwoBooksWithSameAuthor 57 | { 58 | NSManagedObjectContext *moc = self.managedObjectContext; 59 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Book"]; 60 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY authors.name LIKE 'Franz Kafka'"]; 61 | request.predicate = predicate; 62 | NSInteger count = [moc countForFetchRequest:request error:nil]; 63 | STAssertTrue(2 == count, @"Wrong count for authors: %d", count); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /BookMigrationTests/MHWMigrationFromModel2Tests.h: -------------------------------------------------------------------------------- 1 | // 2 | // MHWMigrationFromModel2Tests.h 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/1/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWCoreDataTests.h" 10 | 11 | @interface MHWMigrationFromModel2Tests : MHWCoreDataTests 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /BookMigrationTests/MHWMigrationFromModel2Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MHWMigrationFromModel2Tests.m 3 | // BookMigration 4 | // 5 | // Created by Martin Hwasser on 9/1/13. 6 | // Copyright (c) 2013 Martin Hwasser. All rights reserved. 7 | // 8 | 9 | #import "MHWMigrationFromModel2Tests.h" 10 | 11 | @implementation MHWMigrationFromModel2Tests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | [self setUpCoreDataStackMigratingFromStoreWithName:@"Model1.sqlite"]; 17 | } 18 | 19 | - (void)testThatUserHasFiles 20 | { 21 | NSManagedObjectContext *moc = self.managedObjectContext; 22 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"User"]; 23 | request.predicate = [NSPredicate predicateWithFormat:@"userId == 1"]; 24 | NSArray *users = [moc executeFetchRequest:request error:nil]; 25 | STAssertTrue(0 < users.count, @"Users have disappeared after migration"); 26 | NSManagedObject *user = users.lastObject; 27 | NSSet *files = [user valueForKey:@"files"]; 28 | STAssertTrue(files.count == 4, @"Wrong files count: %d", files.count); 29 | } 30 | 31 | - (void)testThatFilesHaveBooks 32 | { 33 | NSManagedObjectContext *moc = self.managedObjectContext; 34 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"File"]; 35 | NSArray *files = [moc executeFetchRequest:request error:nil]; 36 | for (NSManagedObject *file in files) { 37 | STAssertNotNil([file valueForKey:@"book"], @"No book on file"); 38 | } 39 | } 40 | 41 | - (void)testThatBooksHaveAuthors 42 | { 43 | NSManagedObjectContext *moc = self.managedObjectContext; 44 | NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Book"]; 45 | NSArray *books = [moc executeFetchRequest:request error:nil]; 46 | for (NSManagedObject *book in books) { 47 | STAssertNotNil([book valueForKey:@"authors"], @"No author on file"); 48 | } 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /BookMigrationTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Martin Hwasser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BookMigration 2 | ============= 3 | 4 | Simple app that demonstrates Core Data migration. 5 | 6 | 7 | ##Credits 8 | Thanks to [Gideon Wald](mailto:gideon@welkinhealth.com) and [Benedikt Hirmer](https://github.com/bhr) for pointing out an issue with SQLite's [write-ahead logging](https://github.com/hwaxxer/BookMigration/commit/baa5014391081e7b74223250281e3cad90603c56). 9 | --------------------------------------------------------------------------------