diff --git a/LeStorage/Codables/ApiCall.swift b/LeStorage/Codables/ApiCall.swift index 07eda98..dd7ef90 100644 --- a/LeStorage/Codables/ApiCall.swift +++ b/LeStorage/Codables/ApiCall.swift @@ -107,6 +107,9 @@ public class ApiCall: ModelObject, Storable, SomeCall { var storeId: String? { return self.urlParameters?[Services.storeIdURLParameter] } public static func relationships() -> [Relationship] { return [] } + public static func parentRelationships() -> [Relationship] { return [] } + public static func childrenRelationships() -> [Relationship] { return [] } + } class OldApiCall: ModelObject, Storable, SomeCall { @@ -188,7 +191,9 @@ class OldApiCall: ModelObject, Storable, SomeCall { var dataContent: String? { return self.body } static func relationships() -> [Relationship] { return [] } - + public static func parentRelationships() -> [Relationship] { return [] } + public static func childrenRelationships() -> [Relationship] { return [] } + func toNewApiCall() -> ApiCall? { if let instance: T = try? self.body?.decode() { let apiCall = ApiCall(method: self.method, data: instance, transactionId: self.transactionId) diff --git a/LeStorage/Codables/DataAccess.swift b/LeStorage/Codables/DataAccess.swift index 0b8ffb9..568cbfa 100644 --- a/LeStorage/Codables/DataAccess.swift +++ b/LeStorage/Codables/DataAccess.swift @@ -12,6 +12,9 @@ class DataAccess: SyncedModelObject, SyncedStorable { static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func resourceName() -> String { return "data-access" } static func relationships() -> [Relationship] { return [] } + public static func parentRelationships() -> [Relationship] { return [] } + public static func childrenRelationships() -> [Relationship] { return [] } + static var copyServerResponse: Bool = false static func storeParent() -> Bool { return false } diff --git a/LeStorage/Codables/DataLog.swift b/LeStorage/Codables/DataLog.swift index c7da4db..f4e23ee 100644 --- a/LeStorage/Codables/DataLog.swift +++ b/LeStorage/Codables/DataLog.swift @@ -12,6 +12,9 @@ class DataLog: ModelObject, Storable { static func resourceName() -> String { return "data-logs" } static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func relationships() -> [Relationship] { return [] } + public static func parentRelationships() -> [Relationship] { return [] } + public static func childrenRelationships() -> [Relationship] { return [] } + static func storeParent() -> Bool { return false } var id: String = Store.randomId() diff --git a/LeStorage/Codables/FailedAPICall.swift b/LeStorage/Codables/FailedAPICall.swift index b592984..3bbc571 100644 --- a/LeStorage/Codables/FailedAPICall.swift +++ b/LeStorage/Codables/FailedAPICall.swift @@ -12,6 +12,9 @@ class FailedAPICall: SyncedModelObject, SyncedStorable { static func resourceName() -> String { return "failed-api-calls" } static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func relationships() -> [Relationship] { return [] } + public static func parentRelationships() -> [Relationship] { return [] } + public static func childrenRelationships() -> [Relationship] { return [] } + static var copyServerResponse: Bool = false static func storeParent() -> Bool { return false } diff --git a/LeStorage/Codables/GetSyncData.swift b/LeStorage/Codables/GetSyncData.swift index e19dedf..fe0d1a5 100644 --- a/LeStorage/Codables/GetSyncData.swift +++ b/LeStorage/Codables/GetSyncData.swift @@ -12,13 +12,13 @@ class GetSyncData: SyncedModelObject, SyncedStorable, URLParameterConvertible { static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static var copyServerResponse: Bool = false static func storeParent() -> Bool { return false } - + var date: String = "" - + enum CodingKeys: String, CodingKey { case date } - + override required init() { super.init() } @@ -49,6 +49,9 @@ class GetSyncData: SyncedModelObject, SyncedStorable, URLParameterConvertible { let encodedDate = self.date.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" return encodedDate.replacingOccurrences(of: "+", with: "%2B") } - + static func relationships() -> [Relationship] { return [] } + public static func parentRelationships() -> [Relationship] { return [] } + public static func childrenRelationships() -> [Relationship] { return [] } + } diff --git a/LeStorage/Codables/Log.swift b/LeStorage/Codables/Log.swift index 994478d..eecb5de 100644 --- a/LeStorage/Codables/Log.swift +++ b/LeStorage/Codables/Log.swift @@ -12,6 +12,9 @@ class Log: SyncedModelObject, SyncedStorable { static func resourceName() -> String { return "logs" } static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func relationships() -> [Relationship] { return [] } + public static func parentRelationships() -> [Relationship] { return [] } + public static func childrenRelationships() -> [Relationship] { return [] } + static var copyServerResponse: Bool = false static func storeParent() -> Bool { return false } diff --git a/LeStorage/Storable.swift b/LeStorage/Storable.swift index acde2d1..73f5f16 100644 --- a/LeStorage/Storable.swift +++ b/LeStorage/Storable.swift @@ -34,6 +34,8 @@ public protocol Storable: Codable, Identifiable, NSObjectProtocol { /// This method returns RelationShips objects of the type static func relationships() -> [Relationship] + static func parentRelationships() -> [Relationship] + static func childrenRelationships() -> [Relationship] static func storeParent() -> Bool diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index 747aa34..aece6cc 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -288,7 +288,7 @@ final public class Store { func isReferenced(collectionType: S.Type, type: T.Type, id: String) -> Bool { if let collection = self._baseCollections[S.resourceName()] { - return collection.isReferenced(type: type, id: id) + return collection.hasParentReferences(type: type, id: id) } else { return false } diff --git a/LeStorage/StoreCenter.swift b/LeStorage/StoreCenter.swift index 13df1bf..fc751e6 100644 --- a/LeStorage/StoreCenter.swift +++ b/LeStorage/StoreCenter.swift @@ -813,6 +813,10 @@ public class StoreCenter { self._deleteLogs.addOrUpdate(instance: dataLog) } + /// Returns the appropriate store for a relationship + /// - Parameters: + /// - instance: some Storable instance + /// - relationship: the relationship func relationshipStore(instance: T, relationship: Relationship) -> Store? { switch relationship.storeLookup { case .main: return Store.main @@ -821,8 +825,13 @@ public class StoreCenter { } } - func hasDirectReference(instance: T, relationshipType: S.Type, relationship: Relationship) -> Bool { - if let referenceId = instance[keyPath: relationship.keyPath] as? S.ID, let store = self.relationshipStore(instance: instance, relationship: relationship) { + /// Returns if an instance has at least one valid parent relationship by checking if the id of the parent exists + /// - Parameters: + /// - instance: some Storable instance + /// - relationship: the relationship + func hasParentReferences(instance: T, relationshipType: S.Type, relationship: Relationship) -> Bool { + if let referenceId = instance[keyPath: relationship.keyPath] as? S.ID, + let store = self.relationshipStore(instance: instance, relationship: relationship) { let instance: S? = store.findById(referenceId) return instance != nil } @@ -830,12 +839,14 @@ public class StoreCenter { } func isReferenced(instance: T) -> Bool { - let relationships = T.relationships() - for relationship in relationships { - if self.hasDirectReference(instance: instance, relationshipType: relationship.type, relationship: relationship) { + + for relationship in T.parentRelationships() { + if self.hasParentReferences(instance: instance, relationshipType: relationship.type, relationship: relationship) { return true } - + } + + for relationship in T.childrenRelationships() { if let store = self.relationshipStore(instance: instance, relationship: relationship) { if store.isReferenced(collectionType: relationship.type, type: T.self, id: instance.stringId) { return true diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index a472a44..ea3e9bd 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -17,7 +17,7 @@ public protocol SomeCollection: Identifiable { var type: any Storable.Type { get } func reset() - func isReferenced(type: S.Type, id: String) -> Bool + func hasParentReferences(type: S.Type, id: String) -> Bool var items: [Item] { get } @@ -528,8 +528,8 @@ public class StoredCollection: SomeCollection { // MARK: - Reference count /// Counts the references to an object - given its type and id - inside the collection - public func isReferenced(type: S.Type, id: String) -> Bool { - let relationships = T.relationships().filter { $0.type == type } + public func hasParentReferences(type: S.Type, id: String) -> Bool { + let relationships = T.parentRelationships().filter { $0.type == type } guard relationships.count > 0 else { return false } for item in self.items { @@ -540,13 +540,6 @@ public class StoredCollection: SomeCollection { } } return false - -// return self.items.reduce(0) { count, item in -// count -// + relationships.filter { relationship in -// (item[keyPath: relationship.keyPath] as? String) == id -// }.count -// } } // MARK: - for Synced Collection diff --git a/LeStorage/SyncedCollection.swift b/LeStorage/SyncedCollection.swift index eeb4178..5babc7c 100644 --- a/LeStorage/SyncedCollection.swift +++ b/LeStorage/SyncedCollection.swift @@ -458,8 +458,8 @@ public class SyncedCollection: SomeSyncedCollection, Collect public var type: any Storable.Type { return T.self } - public func isReferenced(type: S.Type, id: String) -> Bool where S : Storable { - return self.collection.isReferenced(type: type, id: id) + public func hasParentReferences(type: S.Type, id: String) -> Bool where S : Storable { + return self.collection.hasParentReferences(type: type, id: id) } public func reset() {