WIP: dynamic migrations

This commit is contained in:
John Estropia
2017-04-25 18:08:43 +09:00
parent 53ab140341
commit 54c81d23f5
7 changed files with 147 additions and 82 deletions

View File

@@ -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")
} }
} }
} }

View File

@@ -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
)
)
}
} }

View File

@@ -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)
} }
} }
} }

View File

@@ -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
) )
} }

View File

@@ -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?

View File

@@ -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 }
} }

View File

@@ -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 }
} }