Files
CoreStore/Sources/CustomSchemaMappingProvider.swift
John Estropia e0abb9b0af Merge branch 'develop' into corestore4_develop
# Conflicts:
#	CoreStore.podspec
#	Sources/CoreStoreImportableAttributeType.swift
#	Sources/CoreStoreQueryableAttributeType.swift
#	Sources/Info.plist
#	Sources/NSManagedObjectModel+Setup.swift
2017-05-10 19:11:01 +09:00

659 lines
31 KiB
Swift

//
// CustomSchemaMappingProvider.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import CoreData
import Foundation
// MARK: - CustomSchemaMappingProvider
open class CustomSchemaMappingProvider: Hashable, SchemaMappingProvider {
public let sourceVersion: ModelVersion
public let destinationVersion: ModelVersion
public required init(from sourceVersion: ModelVersion, to destinationVersion: ModelVersion, entityMappings: Set<CustomMapping> = []) {
CoreStore.assert(
cs_lazy {
let sources = entityMappings.flatMap({ $0.entityMappingSourceEntity })
let destinations = entityMappings.flatMap({ $0.entityMappingDestinationEntity })
return sources.count == Set(sources).count
&& destinations.count == Set(destinations).count
},
"Duplicate source/destination entities found in provided \"entityMappings\" argument."
)
self.sourceVersion = sourceVersion
self.destinationVersion = destinationVersion
self.entityMappings = entityMappings
}
// MARK: - CustomMapping
public enum CustomMapping: Hashable {
public typealias Transformer = (_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void
case deleteEntity(sourceEntity: EntityName)
case insertEntity(destinationEntity: EntityName)
case copyEntity(sourceEntity: EntityName, destinationEntity: EntityName)
case transformEntity(sourceEntity: EntityName, destinationEntity: EntityName, transformer: Transformer)
static func inferredTransformation(_ sourceObject: UnsafeSourceObject, _ createDestinationObject: () -> UnsafeDestinationObject) throws -> Void {
let destinationObject = createDestinationObject()
destinationObject.enumerateAttributes { (attribute, sourceAttribute) in
if let sourceAttribute = sourceAttribute {
destinationObject[attribute] = sourceObject[sourceAttribute]
}
}
}
var entityMappingSourceEntity: EntityName? {
switch self {
case .deleteEntity(let sourceEntity),
.copyEntity(let sourceEntity, _),
.transformEntity(let sourceEntity, _, _):
return sourceEntity
case .insertEntity:
return nil
}
}
var entityMappingDestinationEntity: EntityName? {
switch self {
case .insertEntity(let destinationEntity),
.copyEntity(_, let destinationEntity),
.transformEntity(_, let destinationEntity, _):
return destinationEntity
case .deleteEntity:
return nil
}
}
// MARK: Equatable
public static func == (lhs: CustomMapping, rhs: CustomMapping) -> Bool {
switch (lhs, rhs) {
case (.deleteEntity(let sourceEntity1), .deleteEntity(let sourceEntity2)):
return sourceEntity1 == sourceEntity2
case (.insertEntity(let destinationEntity1), .insertEntity(let destinationEntity2)):
return destinationEntity1 == destinationEntity2
case (.copyEntity(let sourceEntity1, let destinationEntity1), .copyEntity(let sourceEntity2, let destinationEntity2)):
return sourceEntity1 == sourceEntity2
&& destinationEntity1 == destinationEntity2
case (.transformEntity(let sourceEntity1, let destinationEntity1, _), .transformEntity(let sourceEntity2, let destinationEntity2, _)):
return sourceEntity1 == sourceEntity2
&& destinationEntity1 == destinationEntity2
default:
return false
}
}
// MARK: Hashable
public var hashValue: Int {
switch self {
case .deleteEntity(let sourceEntity):
return sourceEntity.hashValue
case .insertEntity(let destinationEntity):
return destinationEntity.hashValue
case .copyEntity(let sourceEntity, let destinationEntity):
return sourceEntity.hashValue
^ destinationEntity.hashValue
case .transformEntity(let sourceEntity, let destinationEntity, _):
return sourceEntity.hashValue
^ destinationEntity.hashValue
}
}
}
// MARK: - UnsafeSourceObject
public final class UnsafeSourceObject {
public subscript(attribute: KeyPath) -> Any? {
return self.rawObject.cs_accessValueForKVCKey(attribute)
}
public subscript(attribute: NSAttributeDescription) -> Any? {
return self.rawObject.cs_accessValueForKVCKey(attribute.name)
}
public func enumerateAttributes(_ closure: (_ attribute: NSAttributeDescription) -> Void) {
for case let attribute as NSAttributeDescription in self.rawObject.entity.properties {
closure(attribute)
}
}
// MARK: Internal
internal init(_ rawObject: NSManagedObject) {
self.rawObject = rawObject
}
// MARK: Private
private let rawObject: NSManagedObject
}
// MARK: - UnsafeDestinationObject
public final class UnsafeDestinationObject {
public subscript(attribute: KeyPath) -> Any? {
get { return self.rawObject.cs_accessValueForKVCKey(attribute) }
set { self.rawObject.cs_setValue(newValue, forKVCKey: attribute) }
}
public subscript(attribute: NSAttributeDescription) -> Any? {
get { return self.rawObject.cs_accessValueForKVCKey(attribute.name) }
set { self.rawObject.cs_setValue(newValue, forKVCKey: attribute.name) }
}
public func enumerateAttributes(_ closure: (_ attribute: NSAttributeDescription, _ sourceAttribute: NSAttributeDescription?) -> Void) {
for case let attribute as NSAttributeDescription in self.rawObject.entity.properties {
closure(attribute, self.sourceAttributesByDestinationKey[attribute.name])
}
}
// MARK: Internal
internal init(_ rawObject: NSManagedObject, _ sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription]) {
self.rawObject = rawObject
self.sourceAttributesByDestinationKey = sourceAttributesByDestinationKey
}
// MARK: Private
private let rawObject: NSManagedObject
private let sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription]
}
// MARK: Equatable
public static func == (lhs: CustomSchemaMappingProvider, rhs: CustomSchemaMappingProvider) -> Bool {
return lhs.sourceVersion == rhs.sourceVersion
&& lhs.destinationVersion == rhs.destinationVersion
&& type(of: lhs) == type(of: rhs)
}
// MARK: Hashable
public var hashValue: Int {
return self.sourceVersion.hashValue
^ self.destinationVersion.hashValue
}
// MARK: SchemaMappingProvider
public func createMappingModel(from sourceSchema: DynamicSchema, to destinationSchema: DynamicSchema, storage: LocalStorage) throws -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
let sourceModel = sourceSchema.rawModel()
let destinationModel = destinationSchema.rawModel()
let mappingModel = NSMappingModel()
let (deleteMappings, insertMappings, copyMappings, transformMappings) = self.resolveEntityMappings(
sourceModel: sourceModel,
destinationModel: destinationModel
)
func expression(forSource sourceEntity: NSEntityDescription) -> NSExpression {
return NSExpression(format: "FETCH(FUNCTION($\(NSMigrationManagerKey), \"fetchRequestForSourceEntityNamed:predicateString:\" , \"\(sourceEntity.name!)\", \"\(NSPredicate(value: true))\"), $\(NSMigrationManagerKey).\(#keyPath(NSMigrationManager.sourceContext)), \(false))")
}
let sourceEntitiesByName = sourceModel.entitiesByName
let destinationEntitiesByName = destinationModel.entitiesByName
var entityMappings: [NSEntityMapping] = []
for case .deleteEntity(let sourceEntityName) in deleteMappings {
let sourceEntity = sourceEntitiesByName[sourceEntityName]!
let entityMapping = NSEntityMapping()
entityMapping.sourceEntityName = sourceEntity.name
entityMapping.sourceEntityVersionHash = sourceEntity.versionHash
entityMapping.mappingType = .removeEntityMappingType
entityMapping.sourceExpression = expression(forSource: sourceEntity)
entityMappings.append(entityMapping)
}
for case .insertEntity(let destinationEntityName) in insertMappings {
let destinationEntity = destinationEntitiesByName[destinationEntityName]!
let entityMapping = NSEntityMapping()
entityMapping.destinationEntityName = destinationEntity.name
entityMapping.destinationEntityVersionHash = destinationEntity.versionHash
entityMapping.mappingType = .addEntityMappingType
entityMapping.attributeMappings = autoreleasepool { () -> [NSPropertyMapping] in
var attributeMappings: [NSPropertyMapping] = []
for (_, destinationAttribute) in destinationEntity.attributesByName {
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationAttribute.name
attributeMappings.append(propertyMapping)
}
return attributeMappings
}
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
var relationshipMappings: [NSPropertyMapping] = []
for (_, destinationRelationship) in destinationEntity.relationshipsByName {
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationRelationship.name
relationshipMappings.append(propertyMapping)
}
return relationshipMappings
}
entityMappings.append(entityMapping)
}
for case .copyEntity(let sourceEntityName, let destinationEntityName) in copyMappings {
let sourceEntity = sourceEntitiesByName[sourceEntityName]!
let destinationEntity = destinationEntitiesByName[destinationEntityName]!
let entityMapping = NSEntityMapping()
entityMapping.sourceEntityName = sourceEntity.name
entityMapping.sourceEntityVersionHash = sourceEntity.versionHash
entityMapping.destinationEntityName = destinationEntity.name
entityMapping.destinationEntityVersionHash = destinationEntity.versionHash
entityMapping.mappingType = .copyEntityMappingType
entityMapping.sourceExpression = expression(forSource: sourceEntity)
entityMapping.attributeMappings = autoreleasepool { () -> [NSPropertyMapping] in
let sourceAttributes = sourceEntity.cs_resolvedAttributeRenamingIdentities()
let destinationAttributes = destinationEntity.cs_resolvedAttributeRenamingIdentities()
var attributeMappings: [NSPropertyMapping] = []
for (renamingIdentifier, destination) in destinationAttributes {
let sourceAttribute = sourceAttributes[renamingIdentifier]!.attribute
let destinationAttribute = destination.attribute
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationAttribute.name
propertyMapping.valueExpression = NSExpression(format: "$\(NSMigrationSourceObjectKey).\(sourceAttribute.name)")
attributeMappings.append(propertyMapping)
}
return attributeMappings
}
let entityMappingName = entityMapping.name!
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
var relationshipMappings: [NSPropertyMapping] = []
for (_, destination) in destinationRelationships {
let destinationRelationship = destination.relationship
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationRelationship.name
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
relationshipMappings.append(propertyMapping)
}
return relationshipMappings
}
entityMappings.append(entityMapping)
}
for case .transformEntity(let sourceEntityName, let destinationEntityName, let transformEntity) in transformMappings {
let sourceEntity = sourceEntitiesByName[sourceEntityName]!
let destinationEntity = destinationEntitiesByName[destinationEntityName]!
let entityMapping = NSEntityMapping()
entityMapping.sourceEntityName = sourceEntity.name
entityMapping.sourceEntityVersionHash = sourceEntity.versionHash
entityMapping.destinationEntityName = destinationEntity.name
entityMapping.destinationEntityVersionHash = destinationEntity.versionHash
entityMapping.mappingType = .customEntityMappingType
entityMapping.sourceExpression = expression(forSource: sourceEntity)
entityMapping.entityMigrationPolicyClassName = NSStringFromClass(CustomEntityMigrationPolicy.self)
var userInfo: [AnyHashable: Any] = [
CustomEntityMigrationPolicy.UserInfoKey.transformer: transformEntity
]
autoreleasepool {
let sourceAttributes = sourceEntity.cs_resolvedAttributeRenamingIdentities()
let destinationAttributes = destinationEntity.cs_resolvedAttributeRenamingIdentities()
let transformedRenamingIdentifiers = Set(destinationAttributes.keys)
.intersection(sourceAttributes.keys)
var sourceAttributesByDestinationKey: [KeyPath: NSAttributeDescription] = [:]
for renamingIdentifier in transformedRenamingIdentifiers {
let sourceAttribute = sourceAttributes[renamingIdentifier]!.attribute
let destinationAttribute = destinationAttributes[renamingIdentifier]!.attribute
sourceAttributesByDestinationKey[destinationAttribute.name] = sourceAttribute
}
userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] = sourceAttributesByDestinationKey
}
let entityMappingName = entityMapping.name!
entityMapping.relationshipMappings = autoreleasepool { () -> [NSPropertyMapping] in
let destinationRelationships = destinationEntity.cs_resolvedRelationshipRenamingIdentities()
var relationshipMappings: [NSPropertyMapping] = []
for (_, destination) in destinationRelationships {
let destinationRelationship = destination.relationship
let propertyMapping = NSPropertyMapping()
propertyMapping.name = destinationRelationship.name
propertyMapping.valueExpression = NSExpression(format: "FUNCTION($\(NSMigrationManagerKey), \"\(#selector(NSMigrationManager.destinationInstances(forEntityMappingName:sourceInstances:)))\" , \"\(entityMappingName)\", $\(NSMigrationSourceObjectKey))[0]")
relationshipMappings.append(propertyMapping)
}
return relationshipMappings
}
entityMapping.userInfo = userInfo
entityMappings.append(entityMapping)
}
mappingModel.entityMappings = entityMappings
return (
mappingModel,
.heavyweight(
sourceVersion: self.sourceVersion,
destinationVersion: self.destinationVersion
)
)
}
// MARK: Private
// MARK: - CustomEntityMigrationPolicy
private final class CustomEntityMigrationPolicy: NSEntityMigrationPolicy {
// MARK: NSEntityMigrationPolicy
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
let userInfo = mapping.userInfo!
let transformer = userInfo[CustomEntityMigrationPolicy.UserInfoKey.transformer]! as! CustomMapping.Transformer
let sourceAttributesByDestinationKey = userInfo[CustomEntityMigrationPolicy.UserInfoKey.sourceAttributesByDestinationKey] as! [KeyPath: NSAttributeDescription]
var dInstance: NSManagedObject?
try transformer(
UnsafeSourceObject(sInstance),
{
let rawObject = NSEntityDescription.insertNewObject(
forEntityName: mapping.destinationEntityName!,
into: manager.destinationContext
)
dInstance = rawObject
return UnsafeDestinationObject(rawObject, sourceAttributesByDestinationKey)
}
)
if let dInstance = dInstance {
manager.associate(
sourceInstance: sInstance,
withDestinationInstance: dInstance,
for: mapping
)
}
}
override func createRelationships(forDestination dInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
try super.createRelationships(forDestination: dInstance, in: mapping, manager: manager)
}
// MARK: FilePrivate
fileprivate enum UserInfoKey {
fileprivate static let transformer = "CoreStore.CustomEntityMigrationPolicy.transformer"
fileprivate static let sourceAttributesByDestinationKey = "CoreStore.CustomEntityMigrationPolicy.sourceAttributesByDestinationKey"
}
}
// MARK: -
private let entityMappings: Set<CustomMapping>
private func resolveEntityMappings(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel) -> (delete: Set<CustomMapping>, insert: Set<CustomMapping>, copy: Set<CustomMapping>, transform: Set<CustomMapping>) {
var deleteMappings: Set<CustomMapping> = []
var insertMappings: Set<CustomMapping> = []
var copyMappings: Set<CustomMapping> = []
var transformMappings: Set<CustomMapping> = []
var allMappedSourceKeys: [KeyPath: KeyPath] = [:]
var allMappedDestinationKeys: [KeyPath: KeyPath] = [:]
let sourceRenamingIdentifiers = sourceModel.cs_resolvedRenamingIdentities()
let sourceEntityNames = sourceModel.entitiesByName
let destinationRenamingIdentifiers = destinationModel.cs_resolvedRenamingIdentities()
let destinationEntityNames = destinationModel.entitiesByName
let removedRenamingIdentifiers = Set(sourceRenamingIdentifiers.keys)
.subtracting(destinationRenamingIdentifiers.keys)
let addedRenamingIdentifiers = Set(destinationRenamingIdentifiers.keys)
.subtracting(sourceRenamingIdentifiers.keys)
let transformedRenamingIdentifiers = Set(destinationRenamingIdentifiers.keys)
.subtracting(addedRenamingIdentifiers)
.subtracting(removedRenamingIdentifiers)
// First pass: resolve source-destination entities
for mapping in self.entityMappings {
switch mapping {
case .deleteEntity(let sourceEntity):
CoreStore.assert(
sourceEntityNames[sourceEntity] != nil,
"A \(cs_typeName(CustomMapping.self)) with value '\(mapping)' passed to \(cs_typeName(CustomSchemaMappingProvider.self)) could not be mapped to any \(cs_typeName(NSEntityDescription.self)) from the source \(cs_typeName(NSManagedObjectModel.self))."
)
CoreStore.assert(
allMappedSourceKeys[sourceEntity] == nil,
"Duplicate \(cs_typeName(CustomMapping.self))s found for source entity name \"\(sourceEntity)\" in \(cs_typeName(CustomSchemaMappingProvider.self))."
)
deleteMappings.insert(mapping)
allMappedSourceKeys[sourceEntity] = ""
case .insertEntity(let destinationEntity):
CoreStore.assert(
destinationEntityNames[destinationEntity] != nil,
"A \(cs_typeName(CustomMapping.self)) with value '\(mapping)' passed to \(cs_typeName(CustomSchemaMappingProvider.self)) could not be mapped to any \(cs_typeName(NSEntityDescription.self)) from the destination \(cs_typeName(NSManagedObjectModel.self))."
)
CoreStore.assert(
allMappedDestinationKeys[destinationEntity] == nil,
"Duplicate \(cs_typeName(CustomMapping.self))s found for destination entity name \"\(destinationEntity)\" in \(cs_typeName(CustomSchemaMappingProvider.self))."
)
insertMappings.insert(mapping)
allMappedDestinationKeys[destinationEntity] = ""
case .transformEntity(let sourceEntity, let destinationEntity, _):
CoreStore.assert(
sourceEntityNames[sourceEntity] != nil,
"A \(cs_typeName(CustomMapping.self)) with value '\(mapping)' passed to \(cs_typeName(CustomSchemaMappingProvider.self)) could not be mapped to any \(cs_typeName(NSEntityDescription.self)) from the source \(cs_typeName(NSManagedObjectModel.self))."
)
CoreStore.assert(
destinationEntityNames[destinationEntity] != nil,
"A \(cs_typeName(CustomMapping.self)) with value '\(mapping)' passed to \(cs_typeName(CustomSchemaMappingProvider.self)) could not be mapped to any \(cs_typeName(NSEntityDescription.self)) from the destination \(cs_typeName(NSManagedObjectModel.self))."
)
CoreStore.assert(
allMappedSourceKeys[sourceEntity] == nil,
"Duplicate \(cs_typeName(CustomMapping.self))s found for source entity name \"\(sourceEntity)\" in \(cs_typeName(CustomSchemaMappingProvider.self))."
)
CoreStore.assert(
allMappedDestinationKeys[destinationEntity] == nil,
"Duplicate \(cs_typeName(CustomMapping.self))s found for destination entity name \"\(destinationEntity)\" in \(cs_typeName(CustomSchemaMappingProvider.self))."
)
transformMappings.insert(mapping)
allMappedSourceKeys[sourceEntity] = destinationEntity
allMappedDestinationKeys[destinationEntity] = sourceEntity
case .copyEntity(let sourceEntity, let destinationEntity):
CoreStore.assert(
sourceEntityNames[sourceEntity] != nil,
"A \(cs_typeName(CustomMapping.self)) with value '\(mapping)' passed to \(cs_typeName(CustomSchemaMappingProvider.self)) could not be mapped to any \(cs_typeName(NSEntityDescription.self)) from the source \(cs_typeName(NSManagedObjectModel.self))."
)
CoreStore.assert(
destinationEntityNames[destinationEntity] != nil,
"A \(cs_typeName(CustomMapping.self)) with value '\(mapping)' passed to \(cs_typeName(CustomSchemaMappingProvider.self)) could not be mapped to any \(cs_typeName(NSEntityDescription.self)) from the destination \(cs_typeName(NSManagedObjectModel.self))."
)
CoreStore.assert(
sourceEntityNames[sourceEntity]!.versionHash == destinationEntityNames[destinationEntity]!.versionHash,
"A \(cs_typeName(CustomMapping.self)) with value '\(mapping)' was passed to \(cs_typeName(CustomSchemaMappingProvider.self)) but the \(cs_typeName(NSEntityDescription.self))'s \"versionHash\" of the source and destination entities do not match."
)
CoreStore.assert(
allMappedSourceKeys[sourceEntity] == nil,
"Duplicate \(cs_typeName(CustomMapping.self))s found for source entity name \"\(sourceEntity)\" in \(cs_typeName(CustomSchemaMappingProvider.self))."
)
CoreStore.assert(
allMappedDestinationKeys[destinationEntity] == nil,
"Duplicate \(cs_typeName(CustomMapping.self))s found for destination entity name \"\(destinationEntity)\" in \(cs_typeName(CustomSchemaMappingProvider.self))."
)
copyMappings.insert(mapping)
allMappedSourceKeys[sourceEntity] = destinationEntity
allMappedDestinationKeys[destinationEntity] = sourceEntity
}
for renamingIdentifier in transformedRenamingIdentifiers {
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
let sourceEntityName = sourceEntity.name!
let destinationEntityName = destinationEntity.name!
switch (allMappedSourceKeys[sourceEntityName], allMappedDestinationKeys[destinationEntityName]) {
case (nil, nil):
if sourceEntity.versionHash == destinationEntity.versionHash {
copyMappings.insert(
.copyEntity(
sourceEntity: sourceEntityName,
destinationEntity: destinationEntityName
)
)
}
else {
transformMappings.insert(
.transformEntity(
sourceEntity: sourceEntityName,
destinationEntity: destinationEntityName,
transformer: CustomMapping.inferredTransformation
)
)
}
allMappedSourceKeys[sourceEntityName] = destinationEntityName
allMappedDestinationKeys[destinationEntityName] = sourceEntityName
case (""?, nil):
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
allMappedDestinationKeys[destinationEntityName] = ""
case (nil, ""?):
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
allMappedSourceKeys[sourceEntityName] = ""
default:
continue
}
}
for renamingIdentifier in removedRenamingIdentifiers {
let sourceEntity = sourceRenamingIdentifiers[renamingIdentifier]!.entity
let sourceEntityName = sourceEntity.name!
switch allMappedSourceKeys[sourceEntityName] {
case nil:
deleteMappings.insert(.deleteEntity(sourceEntity: sourceEntityName))
allMappedSourceKeys[sourceEntityName] = ""
default:
continue
}
}
for renamingIdentifier in addedRenamingIdentifiers {
let destinationEntity = destinationRenamingIdentifiers[renamingIdentifier]!.entity
let destinationEntityName = destinationEntity.name!
switch allMappedDestinationKeys[destinationEntityName] {
case nil:
insertMappings.insert(.insertEntity(destinationEntity: destinationEntityName))
allMappedDestinationKeys[destinationEntityName] = ""
default:
continue
}
}
}
return (deleteMappings, insertMappings, copyMappings, transformMappings)
}
}