mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-31 22:53:04 +02:00
WIP: dynamic migrations
This commit is contained in:
@@ -187,7 +187,11 @@ public extension DynamicSchema {
|
|||||||
}
|
}
|
||||||
let indexedString = attribute.isIndexed ? ", isIndexed: true" : ""
|
let indexedString = attribute.isIndexed ? ", isIndexed: true" : ""
|
||||||
let transientString = attribute.isTransient ? ", isTransient: true" : ""
|
let transientString = attribute.isTransient ? ", isTransient: true" : ""
|
||||||
output.append(" let \(attributeName) = \(containerType)<\(String(describing: valueType))>(\"\(attributeName)\"\(indexedString)\(defaultString)\(transientString))\n")
|
// TODO: escape strings
|
||||||
|
let versionHashModifierString = attribute.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||||
|
// TODO: escape strings
|
||||||
|
let renamingIdentifierString = attribute.renamingIdentifier.flatMap({ ", renamingIdentifier: \"\($0)\"" }) ?? ""
|
||||||
|
output.append(" let \(attributeName) = \(containerType)<\(String(describing: valueType))>(\"\(attributeName)\"\(indexedString)\(defaultString)\(transientString)\(versionHashModifierString)\(renamingIdentifierString))\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +255,9 @@ public extension DynamicSchema {
|
|||||||
fatalError("Unsupported delete rule \((relationship.deleteRule)) for relationship \"\(relationshipQualifier)\"")
|
fatalError("Unsupported delete rule \((relationship.deleteRule)) for relationship \"\(relationshipQualifier)\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output.append(" let \(relationshipName) = \(containerType)<\(relationship.destinationEntity!.name!)>(\"\(relationshipName)\"\(inverseString)\(deleteRuleString)\(minCountString)\(maxCountString))\n")
|
let versionHashModifierString = relationship.versionHashModifier.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||||
|
let renamingIdentifierString = relationship.renamingIdentifier.flatMap({ ", renamingIdentifier: \"\($0)\"" }) ?? ""
|
||||||
|
output.append(" let \(relationshipName) = \(containerType)<\(relationship.destinationEntity!.name!)>(\"\(relationshipName)\"\(inverseString)\(deleteRuleString)\(minCountString)\(maxCountString)\(versionHashModifierString)\(renamingIdentifierString))\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,53 +27,78 @@ import CoreData
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
// MARK: - MigrationMappingProvider
|
// MARK: - SchemaMappingProvider
|
||||||
|
|
||||||
public protocol MigrationMappingProvider {
|
public protocol SchemaMappingProvider {
|
||||||
|
|
||||||
associatedtype SourceSchema: DynamicSchema
|
var sourceSchema: DynamicSchema { get }
|
||||||
associatedtype DestinationSchema: DynamicSchema
|
var destinationSchema: DynamicSchema { get }
|
||||||
|
|
||||||
var sourceSchema: SourceSchema { get }
|
func createMappingModel() throws -> (mappingModel: NSMappingModel, migrationType: MigrationType)
|
||||||
var destinationSchema: DestinationSchema { get }
|
|
||||||
|
|
||||||
init(source: SourceSchema, destination: DestinationSchema)
|
|
||||||
|
|
||||||
// func migrate(
|
|
||||||
// from oldObject: SourceType,
|
|
||||||
// to newObject: DestinationType,
|
|
||||||
// transaction: UnsafeDataTransaction
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// func forEachPropertyMapping(
|
|
||||||
// from oldObject: SourceType,
|
|
||||||
// to newObject: DestinationType,
|
|
||||||
// removed: (_ keyPath: KeyPath) -> Void,
|
|
||||||
// added: (_ keyPath: KeyPath) -> Void,
|
|
||||||
// transformed: (_ keyPath: KeyPath) -> Void,
|
|
||||||
// copied: (_ keyPath: KeyPath) -> Void
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension MigrationMappingProvider {
|
public protocol EntityMappingProvider {
|
||||||
|
|
||||||
// func migrate(from oldObject: SourceType, to newObject: DestinationType, transaction: UnsafeDataTransaction) {
|
var source: (schema: DynamicSchema, entity: DynamicEntity) { get }
|
||||||
//
|
var destination: (schema: DynamicSchema, entity: DynamicEntity) { get }
|
||||||
//
|
|
||||||
// }
|
func createEntityMapping() -> NSEntityMapping
|
||||||
//
|
|
||||||
// func forEachPropertyMapping(from oldObject: SourceType, to newObject: DestinationType, removed: (_ keyPath: KeyPath) -> Void, added: (_ keyPath: KeyPath) -> Void, transformed: (_ keyPath: KeyPath) -> Void) {
|
|
||||||
//
|
|
||||||
// let oldAttributes = oldObject.cs_toRaw().entity.attributesByName
|
|
||||||
// let newAttributes = newObject.cs_toRaw().entity.attributesByName
|
|
||||||
// let oldAttributeKeys = Set(oldAttributes.keys)
|
|
||||||
// let newAttributeKeys = Set(newAttributes.keys)
|
|
||||||
// for keyPath in
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension MigrationMappingProvider {
|
|
||||||
|
// MARK: - XcodeMappingModelProvider
|
||||||
|
|
||||||
|
open class XcodeMappingModelProvider<S: DynamicSchema, D: DynamicSchema>: SchemaMappingProvider {
|
||||||
|
|
||||||
|
private let mappingModelBundles: [Bundle]
|
||||||
|
|
||||||
|
public required init(source: SourceSchema, destination: DestinationSchema, mappingModelBundles: [Bundle] = Bundle.allBundles) {
|
||||||
|
|
||||||
|
self.sourceSchema = source
|
||||||
|
self.destinationSchema = destination
|
||||||
|
self.mappingModelBundles = mappingModelBundles
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: SchemaMappingProvider
|
||||||
|
|
||||||
|
public typealias SourceSchema = S
|
||||||
|
public typealias DestinationSchema = D
|
||||||
|
|
||||||
|
public let sourceSchema: SourceSchema
|
||||||
|
public let destinationSchema: DestinationSchema
|
||||||
|
|
||||||
|
public func createMappingModel() throws -> (mappingModel: NSMappingModel, migrationType: MigrationType) {
|
||||||
|
|
||||||
|
let sourceModel = self.sourceSchema.rawModel()
|
||||||
|
let destinationModel = self.destinationSchema.rawModel()
|
||||||
|
|
||||||
|
if let mappingModel = NSMappingModel(
|
||||||
|
from: self.mappingModelBundles,
|
||||||
|
forSourceModel: sourceModel,
|
||||||
|
destinationModel: destinationModel) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
mappingModel,
|
||||||
|
.heavyweight(
|
||||||
|
sourceVersion: self.sourceSchema.modelVersion,
|
||||||
|
destinationVersion: self.destinationSchema.modelVersion
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mappingModel = try NSMappingModel.inferredMappingModel(
|
||||||
|
forSourceModel: sourceModel,
|
||||||
|
destinationModel: destinationModel
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
mappingModel,
|
||||||
|
.lightweight(
|
||||||
|
sourceVersion: self.sourceSchema.modelVersion,
|
||||||
|
destinationVersion: self.destinationSchema.modelVersion
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ public final class DataStack: Equatable {
|
|||||||
let actualType = anyEntity.type
|
let actualType = anyEntity.type
|
||||||
if (actualType as AnyClass).isSubclass(of: type) {
|
if (actualType as AnyClass).isSubclass(of: type) {
|
||||||
|
|
||||||
entityTypesByName[entityDescription.name!] = actualType
|
entityTypesByName[entityDescription.name!] = (actualType as! CoreStoreObject.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal init(type: CoreStoreObject.Type, entityName: String, isAbstract: Bool, versionHashModifier: String?) {
|
internal init(type: DynamicObject.Type, entityName: String, isAbstract: Bool, versionHashModifier: String?) {
|
||||||
|
|
||||||
self.type = type
|
self.type = type
|
||||||
self.entityName = entityName
|
self.entityName = entityName
|
||||||
@@ -168,7 +168,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
|
|
||||||
// MARK: DynamicEntity
|
// MARK: DynamicEntity
|
||||||
|
|
||||||
internal let type: CoreStoreObject.Type
|
internal let type: DynamicObject.Type
|
||||||
internal let entityName: EntityName
|
internal let entityName: EntityName
|
||||||
internal let isAbstract: Bool
|
internal let isAbstract: Bool
|
||||||
internal let versionHashModifier: String?
|
internal let versionHashModifier: String?
|
||||||
@@ -223,7 +223,8 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
description.isIndexed = attribute.isIndexed
|
description.isIndexed = attribute.isIndexed
|
||||||
description.defaultValue = attribute.defaultValue
|
description.defaultValue = attribute.defaultValue
|
||||||
description.isTransient = attribute.isTransient
|
description.isTransient = attribute.isTransient
|
||||||
// TODO: versionHash, renamingIdentifier, etc
|
description.versionHashModifier = attribute.versionHashModifier
|
||||||
|
description.renamingIdentifier = attribute.renamingIdentifier
|
||||||
propertyDescriptions.append(description)
|
propertyDescriptions.append(description)
|
||||||
|
|
||||||
case let relationship as RelationshipProtocol:
|
case let relationship as RelationshipProtocol:
|
||||||
@@ -233,7 +234,8 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
description.maxCount = relationship.maxCount
|
description.maxCount = relationship.maxCount
|
||||||
description.isOrdered = relationship.isOrdered
|
description.isOrdered = relationship.isOrdered
|
||||||
description.deleteRule = relationship.deleteRule
|
description.deleteRule = relationship.deleteRule
|
||||||
// TODO: versionHash, renamingIdentifier, etc
|
description.versionHashModifier = relationship.versionHashModifier
|
||||||
|
description.renamingIdentifier = relationship.renamingIdentifier
|
||||||
propertyDescriptions.append(description)
|
propertyDescriptions.append(description)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -243,7 +245,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
return propertyDescriptions
|
return propertyDescriptions
|
||||||
}
|
}
|
||||||
|
|
||||||
entityDescription.properties = createProperties(for: entity.type)
|
entityDescription.properties = createProperties(for: entity.type as! CoreStoreObject.Type)
|
||||||
return entityDescription
|
return entityDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +295,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
for (entity, entityDescription) in entityDescriptionsByEntity {
|
for (entity, entityDescription) in entityDescriptionsByEntity {
|
||||||
|
|
||||||
let relationshipsByName = relationshipsByNameByEntity[entity]!
|
let relationshipsByName = relationshipsByNameByEntity[entity]!
|
||||||
for child in Mirror(reflecting: entity.type.meta).children {
|
for child in Mirror(reflecting: (entity.type as! CoreStoreObject.Type).meta).children {
|
||||||
|
|
||||||
switch child.value {
|
switch child.value {
|
||||||
|
|
||||||
@@ -360,7 +362,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
|||||||
for (entity, entityDescription) in entityDescriptionsByEntity {
|
for (entity, entityDescription) in entityDescriptionsByEntity {
|
||||||
|
|
||||||
connectBaseEntity(
|
connectBaseEntity(
|
||||||
mirror: Mirror(reflecting: entity.type.meta),
|
mirror: Mirror(reflecting: (entity.type as! CoreStoreObject.Type).meta),
|
||||||
entityDescription: entityDescription
|
entityDescription: entityDescription
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import ObjectiveC
|
|||||||
|
|
||||||
public protocol DynamicEntity {
|
public protocol DynamicEntity {
|
||||||
|
|
||||||
var type: CoreStoreObject.Type { get }
|
var type: DynamicObject.Type { get }
|
||||||
var entityName: EntityName { get }
|
var entityName: EntityName { get }
|
||||||
var isAbstract: Bool { get }
|
var isAbstract: Bool { get }
|
||||||
var versionHashModifier: String? { get }
|
var versionHashModifier: String? { get }
|
||||||
@@ -41,7 +41,7 @@ public protocol DynamicEntity {
|
|||||||
|
|
||||||
// MARK: Entity
|
// MARK: Entity
|
||||||
|
|
||||||
public struct Entity<O: CoreStoreObject>: DynamicEntity, Hashable {
|
public struct Entity<O: DynamicObject>: DynamicEntity, Hashable {
|
||||||
|
|
||||||
public init(_ entityName: String, isAbstract: Bool = false, versionHashModifier: String? = nil) {
|
public init(_ entityName: String, isAbstract: Bool = false, versionHashModifier: String? = nil) {
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ public struct Entity<O: CoreStoreObject>: DynamicEntity, Hashable {
|
|||||||
|
|
||||||
// MARK: DynamicEntity
|
// MARK: DynamicEntity
|
||||||
|
|
||||||
public let type: CoreStoreObject.Type
|
public let type: DynamicObject.Type
|
||||||
public let entityName: EntityName
|
public let entityName: EntityName
|
||||||
public let isAbstract: Bool
|
public let isAbstract: Bool
|
||||||
public let versionHashModifier: String?
|
public let versionHashModifier: String?
|
||||||
|
|||||||
@@ -60,24 +60,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
relationship.value = relationship2.value
|
relationship.value = relationship2.value
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify) {
|
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule)
|
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public var value: D? {
|
public var value: D? {
|
||||||
@@ -124,6 +124,8 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
internal let minCount: Int = 0
|
internal let minCount: Int = 0
|
||||||
internal let maxCount: Int = 1
|
internal let maxCount: Int = 1
|
||||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||||
|
internal let versionHashModifier: String?
|
||||||
|
internal let renamingIdentifier: String?
|
||||||
|
|
||||||
internal var parentObject: () -> CoreStoreObject = {
|
internal var parentObject: () -> CoreStoreObject = {
|
||||||
|
|
||||||
@@ -133,11 +135,13 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule) {
|
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||||
|
|
||||||
self.keyPath = keyPath
|
self.keyPath = keyPath
|
||||||
self.deleteRule = deleteRule.nativeValue
|
self.deleteRule = deleteRule.nativeValue
|
||||||
self.inverse = (D.self, inverseKeyPath)
|
self.inverse = (D.self, inverseKeyPath)
|
||||||
|
self.versionHashModifier = versionHashModifier
|
||||||
|
self.renamingIdentifier = renamingIdentifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,24 +167,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
relationship.value = relationship2.value
|
relationship.value = relationship2.value
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add subscripts, indexed operations for more performant single updates
|
// TODO: add subscripts, indexed operations for more performant single updates
|
||||||
@@ -237,6 +241,8 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
internal let minCount: Int
|
internal let minCount: Int
|
||||||
internal let maxCount: Int
|
internal let maxCount: Int
|
||||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||||
|
internal let versionHashModifier: String?
|
||||||
|
internal let renamingIdentifier: String?
|
||||||
|
|
||||||
internal var parentObject: () -> CoreStoreObject = {
|
internal var parentObject: () -> CoreStoreObject = {
|
||||||
|
|
||||||
@@ -246,11 +252,13 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
private init(keyPath: String, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, minCount: Int, maxCount: Int) {
|
private init(keyPath: String, inverseKeyPath: @escaping () -> String?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||||
|
|
||||||
self.keyPath = keyPath
|
self.keyPath = keyPath
|
||||||
self.deleteRule = deleteRule.nativeValue
|
self.deleteRule = deleteRule.nativeValue
|
||||||
self.inverse = (D.self, inverseKeyPath)
|
self.inverse = (D.self, inverseKeyPath)
|
||||||
|
self.versionHashModifier = versionHashModifier
|
||||||
|
self.renamingIdentifier = renamingIdentifier
|
||||||
|
|
||||||
let range = (max(0, minCount) ... maxCount)
|
let range = (max(0, minCount) ... maxCount)
|
||||||
self.minCount = range.lowerBound
|
self.minCount = range.lowerBound
|
||||||
@@ -285,24 +293,24 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
relationship.value = Set(relationship2.value)
|
relationship.value = Set(relationship2.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { nil }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToOne<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyOrdered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0) {
|
public convenience init(_ keyPath: KeyPath, inverse: @escaping (D) -> RelationshipContainer<D>.ToManyUnordered<O>, deleteRule: DeleteRule = .nullify, minCount: Int = 0, maxCount: Int = 0, versionHashModifier: String? = nil, renamingIdentifier: String? = nil) {
|
||||||
|
|
||||||
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount)
|
self.init(keyPath: keyPath, inverseKeyPath: { inverse(D.meta).keyPath }, deleteRule: deleteRule, minCount: minCount, maxCount: maxCount, versionHashModifier: versionHashModifier, renamingIdentifier: renamingIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add subscripts, indexed operations for more performant single updates
|
// TODO: add subscripts, indexed operations for more performant single updates
|
||||||
@@ -359,6 +367,8 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
internal let minCount: Int
|
internal let minCount: Int
|
||||||
internal let maxCount: Int
|
internal let maxCount: Int
|
||||||
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
internal let inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?)
|
||||||
|
internal let versionHashModifier: String?
|
||||||
|
internal let renamingIdentifier: String?
|
||||||
|
|
||||||
internal var parentObject: () -> CoreStoreObject = {
|
internal var parentObject: () -> CoreStoreObject = {
|
||||||
|
|
||||||
@@ -368,11 +378,13 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
|||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int) {
|
private init(keyPath: KeyPath, inverseKeyPath: @escaping () -> KeyPath?, deleteRule: DeleteRule, minCount: Int, maxCount: Int, versionHashModifier: String?, renamingIdentifier: String?) {
|
||||||
|
|
||||||
self.keyPath = keyPath
|
self.keyPath = keyPath
|
||||||
self.deleteRule = deleteRule.nativeValue
|
self.deleteRule = deleteRule.nativeValue
|
||||||
self.inverse = (D.self, inverseKeyPath)
|
self.inverse = (D.self, inverseKeyPath)
|
||||||
|
self.versionHashModifier = versionHashModifier
|
||||||
|
self.renamingIdentifier = renamingIdentifier
|
||||||
|
|
||||||
let range = (max(0, minCount) ... maxCount)
|
let range = (max(0, minCount) ... maxCount)
|
||||||
self.minCount = range.lowerBound
|
self.minCount = range.lowerBound
|
||||||
@@ -412,6 +424,8 @@ internal protocol RelationshipProtocol: class {
|
|||||||
var deleteRule: NSDeleteRule { get }
|
var deleteRule: NSDeleteRule { get }
|
||||||
var inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) { get }
|
var inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPath?) { get }
|
||||||
var parentObject: () -> CoreStoreObject { get set }
|
var parentObject: () -> CoreStoreObject { get set }
|
||||||
|
var versionHashModifier: String? { get }
|
||||||
|
var renamingIdentifier: String? { get }
|
||||||
var minCount: Int { get }
|
var minCount: Int { get }
|
||||||
var maxCount: Int { get }
|
var maxCount: Int { get }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,12 +59,14 @@ public enum ValueContainer<O: CoreStoreObject> {
|
|||||||
attribute.value = attribute2.value
|
attribute.value = attribute2.value
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ keyPath: KeyPath, `default`: V = V.cs_emptyValue(), isIndexed: Bool = false, isTransient: Bool = false, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V) -> Void, _ newValue: V) -> Void = { $1($2) }) {
|
public init(_ keyPath: KeyPath, `default`: V = V.cs_emptyValue(), isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V) -> Void, _ newValue: V) -> Void = { $1($2) }) {
|
||||||
|
|
||||||
self.keyPath = keyPath
|
self.keyPath = keyPath
|
||||||
self.isIndexed = isIndexed
|
self.isIndexed = isIndexed
|
||||||
self.isTransient = isTransient
|
self.isTransient = isTransient
|
||||||
self.defaultValue = `default`.cs_toImportableNativeType()
|
self.defaultValue = `default`.cs_toImportableNativeType()
|
||||||
|
self.versionHashModifier = versionHashModifier
|
||||||
|
self.renamingIdentifier = renamingIdentifier
|
||||||
self.customGetter = customGetter
|
self.customGetter = customGetter
|
||||||
self.customSetter = customSetter
|
self.customSetter = customSetter
|
||||||
}
|
}
|
||||||
@@ -129,6 +131,8 @@ public enum ValueContainer<O: CoreStoreObject> {
|
|||||||
internal let isIndexed: Bool
|
internal let isIndexed: Bool
|
||||||
internal let isTransient: Bool
|
internal let isTransient: Bool
|
||||||
internal let defaultValue: Any?
|
internal let defaultValue: Any?
|
||||||
|
internal let versionHashModifier: String?
|
||||||
|
internal let renamingIdentifier: String?
|
||||||
|
|
||||||
internal var parentObject: () -> CoreStoreObject = {
|
internal var parentObject: () -> CoreStoreObject = {
|
||||||
|
|
||||||
@@ -162,11 +166,13 @@ public enum ValueContainer<O: CoreStoreObject> {
|
|||||||
attribute.value = attribute2.value
|
attribute.value = attribute2.value
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ keyPath: KeyPath, `default`: V? = nil, isTransient: Bool = false, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V?) -> Void, _ newValue: V?) -> Void = { $1($2) }) {
|
public init(_ keyPath: KeyPath, `default`: V? = nil, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V?) -> Void, _ newValue: V?) -> Void = { $1($2) }) {
|
||||||
|
|
||||||
self.keyPath = keyPath
|
self.keyPath = keyPath
|
||||||
self.isTransient = isTransient
|
self.isTransient = isTransient
|
||||||
self.defaultValue = `default`?.cs_toImportableNativeType()
|
self.defaultValue = `default`?.cs_toImportableNativeType()
|
||||||
|
self.versionHashModifier = versionHashModifier
|
||||||
|
self.renamingIdentifier = renamingIdentifier
|
||||||
self.customGetter = customGetter
|
self.customGetter = customGetter
|
||||||
self.customSetter = customSetter
|
self.customSetter = customSetter
|
||||||
}
|
}
|
||||||
@@ -230,6 +236,8 @@ public enum ValueContainer<O: CoreStoreObject> {
|
|||||||
internal let isIndexed = false
|
internal let isIndexed = false
|
||||||
internal let isTransient: Bool
|
internal let isTransient: Bool
|
||||||
internal let defaultValue: Any?
|
internal let defaultValue: Any?
|
||||||
|
internal let versionHashModifier: String?
|
||||||
|
internal let renamingIdentifier: String?
|
||||||
|
|
||||||
internal var parentObject: () -> CoreStoreObject = {
|
internal var parentObject: () -> CoreStoreObject = {
|
||||||
|
|
||||||
@@ -263,12 +271,14 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
attribute.value = attribute2.value
|
attribute.value = attribute2.value
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ keyPath: KeyPath, `default`: V, isIndexed: Bool = false, isTransient: Bool = false, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V) -> Void, _ newValue: V) -> Void = { $1($2) }) {
|
public init(_ keyPath: KeyPath, `default`: V, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V) -> V = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V) -> Void, _ newValue: V) -> Void = { $1($2) }) {
|
||||||
|
|
||||||
self.keyPath = keyPath
|
self.keyPath = keyPath
|
||||||
self.defaultValue = `default`
|
self.defaultValue = `default`
|
||||||
self.isIndexed = isIndexed
|
self.isIndexed = isIndexed
|
||||||
self.isTransient = isTransient
|
self.isTransient = isTransient
|
||||||
|
self.versionHashModifier = versionHashModifier
|
||||||
|
self.renamingIdentifier = renamingIdentifier
|
||||||
self.customGetter = customGetter
|
self.customGetter = customGetter
|
||||||
self.customSetter = customSetter
|
self.customSetter = customSetter
|
||||||
}
|
}
|
||||||
@@ -332,6 +342,8 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
internal let isIndexed: Bool
|
internal let isIndexed: Bool
|
||||||
internal let isTransient: Bool
|
internal let isTransient: Bool
|
||||||
internal let defaultValue: Any?
|
internal let defaultValue: Any?
|
||||||
|
internal let versionHashModifier: String?
|
||||||
|
internal let renamingIdentifier: String?
|
||||||
|
|
||||||
internal var parentObject: () -> CoreStoreObject = {
|
internal var parentObject: () -> CoreStoreObject = {
|
||||||
|
|
||||||
@@ -365,12 +377,14 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
attribute.value = attribute2.value
|
attribute.value = attribute2.value
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ keyPath: KeyPath, `default`: V? = nil, isIndexed: Bool = false, isTransient: Bool = false, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V?) -> Void, _ newValue: V?) -> Void = { $1($2) }) {
|
public init(_ keyPath: KeyPath, `default`: V? = nil, isIndexed: Bool = false, isTransient: Bool = false, versionHashModifier: String? = nil, renamingIdentifier: String? = nil, customGetter: @escaping (_ `self`: O, _ getValue: () -> V?) -> V? = { $1() }, customSetter: @escaping (_ `self`: O, _ setValue: (V?) -> Void, _ newValue: V?) -> Void = { $1($2) }) {
|
||||||
|
|
||||||
self.keyPath = keyPath
|
self.keyPath = keyPath
|
||||||
self.defaultValue = `default`
|
self.defaultValue = `default`
|
||||||
self.isIndexed = isIndexed
|
self.isIndexed = isIndexed
|
||||||
self.isTransient = isTransient
|
self.isTransient = isTransient
|
||||||
|
self.versionHashModifier = versionHashModifier
|
||||||
|
self.renamingIdentifier = renamingIdentifier
|
||||||
self.customGetter = customGetter
|
self.customGetter = customGetter
|
||||||
self.customSetter = customSetter
|
self.customSetter = customSetter
|
||||||
}
|
}
|
||||||
@@ -434,6 +448,8 @@ public enum TransformableContainer<O: CoreStoreObject> {
|
|||||||
internal let isIndexed: Bool
|
internal let isIndexed: Bool
|
||||||
internal let isTransient: Bool
|
internal let isTransient: Bool
|
||||||
internal let defaultValue: Any?
|
internal let defaultValue: Any?
|
||||||
|
internal let versionHashModifier: String?
|
||||||
|
internal let renamingIdentifier: String?
|
||||||
|
|
||||||
internal var parentObject: () -> CoreStoreObject = {
|
internal var parentObject: () -> CoreStoreObject = {
|
||||||
|
|
||||||
@@ -460,5 +476,7 @@ internal protocol AttributeProtocol: class {
|
|||||||
var isIndexed: Bool { get }
|
var isIndexed: Bool { get }
|
||||||
var isTransient: Bool { get }
|
var isTransient: Bool { get }
|
||||||
var defaultValue: Any? { get }
|
var defaultValue: Any? { get }
|
||||||
|
var versionHashModifier: String? { get }
|
||||||
|
var renamingIdentifier: String? { get }
|
||||||
var parentObject: () -> CoreStoreObject { get set }
|
var parentObject: () -> CoreStoreObject { get set }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user