From fc108373cba96fbe2b11b2e98d6380fd6bcef7c4 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 17 Dec 2019 14:12:07 -0500 Subject: [PATCH] Name changes and cleanup --- MVMCore/MVMCore/Models/Model/Model.swift | 28 ++--- .../MVMCore/Models/Model/ModelRegistry.swift | 109 ++++++++---------- 2 files changed, 65 insertions(+), 72 deletions(-) diff --git a/MVMCore/MVMCore/Models/Model/Model.swift b/MVMCore/MVMCore/Models/Model/Model.swift index 0de3bdd..544cb3a 100644 --- a/MVMCore/MVMCore/Models/Model/Model.swift +++ b/MVMCore/MVMCore/Models/Model/Model.swift @@ -12,33 +12,33 @@ public protocol Model: Codable { static var identifier: String { get } - static func mvmdecode(keyedContainer: KeyedDecodingContainer, codingKey: K) throws -> Self? - static func mvmdecode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? + /// Convenience function to decode to model using a keyed container. + static func decode(keyedContainer: KeyedDecodingContainer, codingKey: K) throws -> Self? + /// Convenience function to decode to model using an unkeyed container. + static func decode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? + /// Convenience function to encode model using a keyed container. + func encode(keyedContainer: inout KeyedEncodingContainer, codingKey: K) throws + /// Convenience function to encode model using an unkeyed container. + func encode(unkeyedContainer: inout UnkeyedEncodingContainer) throws } extension Model { - static public func mvmdecode(keyedContainer: KeyedDecodingContainer, codingKey: K) throws -> Self? { + static public func decode(keyedContainer: KeyedDecodingContainer, codingKey: K) throws -> Self? { let m = try keyedContainer.decodeIfPresent(self, forKey: codingKey) return m } - static public func mvmdecode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? { + static public func decode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? { let m = try unkeyedContainer.decodeIfPresent(self) return m } - static public func mvmencode(keyedContainer: inout KeyedEncodingContainer, codingKey: K, model: Model) throws { - guard let typedModel = model as? Self else { - throw ModelRegistry.Error.encoderError - } - try keyedContainer.encode(typedModel, forKey: codingKey) + public func encode(keyedContainer: inout KeyedEncodingContainer, codingKey: K) throws { + try keyedContainer.encode(self, forKey: codingKey) } - static public func mvmencode(unkeyedContainer: inout UnkeyedEncodingContainer, model: Model) throws{ - guard let typedModel = model as? Self else { - throw ModelRegistry.Error.encoderError - } - try unkeyedContainer.encode(typedModel) + public func encode(unkeyedContainer: inout UnkeyedEncodingContainer) throws{ + try unkeyedContainer.encode(self) } } diff --git a/MVMCore/MVMCore/Models/Model/ModelRegistry.swift b/MVMCore/MVMCore/Models/Model/ModelRegistry.swift index 75866fe..b811646 100644 --- a/MVMCore/MVMCore/Models/Model/ModelRegistry.swift +++ b/MVMCore/MVMCore/Models/Model/ModelRegistry.swift @@ -19,6 +19,7 @@ public struct ModelRegistry { fileprivate static var types = [String: Model.Type]() + /// Register the model. public static func register(_ type: M.Type) { types[M.identifier] = type } @@ -31,8 +32,9 @@ public struct ModelRegistry { extension KeyedDecodingContainer where Key: CodingKey { //MARK: - Decode - public func decode(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> T { - guard let model: Model = try decodeIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else { + /// Decodes to a registered model based on the identifier + public func decodeModel(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> T { + guard let model: Model = try decodeModelIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else { throw ModelRegistry.Error.decoderErrorObjectNotPresent } @@ -44,26 +46,27 @@ extension KeyedDecodingContainer where Key: CodingKey { } //MARK: - DecodeIfPresent - public func decodeIfPresent(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> T? { - //get the type string - var meta: KeyedDecodingContainer? + /// Decodes to a registered model based on the identifier, optional. + public func decodeModelIfPresent(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> T? { + //get the identifier string + var container: KeyedDecodingContainer? do { - meta = try self.nestedContainer(keyedBy: C.self, forKey: codingKey) + container = try nestedContainer(keyedBy: C.self, forKey: codingKey) } catch { return nil } - guard let type = try meta?.decodeIfPresent(String.self, forKey: typeCodingKey) else { + guard let identifier = try container?.decodeIfPresent(String.self, forKey: typeCodingKey) else { return nil } //get the type - guard let found = ModelRegistry.types[type] else { - MVMCoreLoggingHandler.logDebugMessage(withDelegate: "Model not mapped: \(type)") + guard let type = ModelRegistry.types[identifier] else { + MVMCoreLoggingHandler.logDebugMessage(withDelegate: "Model not mapped: \(identifier)") throw ModelRegistry.Error.decoderErrorModelNotMapped } //decode the type using the decoder - let model = try found.mvmdecode(keyedContainer: self, codingKey: codingKey) + let model = try type.decode(keyedContainer: self, codingKey: codingKey) guard let m = model as? T else { throw ModelRegistry.Error.decoderError @@ -72,80 +75,70 @@ extension KeyedDecodingContainer where Key: CodingKey { return m } - - public func decodeArrayIfPresent(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> [Model]? { - var unkeyedContainer: UnkeyedDecodingContainer? - do { - unkeyedContainer = try nestedUnkeyedContainer(forKey: codingKey) - } catch { - return nil - } - var otherUnkeyedContainer = try nestedUnkeyedContainer(forKey: codingKey) - var attributes = [Model.Type]() - while !unkeyedContainer!.isAtEnd { - - let meta = try unkeyedContainer!.nestedContainer(keyedBy: C.self) - guard let type = try meta.decodeIfPresent(String.self, forKey: typeCodingKey) else { - return nil - } - //get the type - guard let found = ModelRegistry.types[type] else { - throw ModelRegistry.Error.decoderErrorModelNotMapped - } - attributes.append(found) - } + /// Decodes an array of registered model based on the identifiers, optional. + public func decodeModelsIfPresent(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> [Model]? { + var models = [Model]() + var container = try nestedUnkeyedContainer(forKey: codingKey) + var containerCopy = container var i = 0 - var models = [Model]() - while !otherUnkeyedContainer.isAtEnd { - let foundModel = attributes[i] - if let model = try foundModel.mvmdecode(unkeyedContainer: &otherUnkeyedContainer) { - models.append(model) + let count = container.count ?? 0 + + while !container.isAtEnd { + if i < count { + let nestedContainer = try container.nestedContainer(keyedBy: C.self) + if let identifier = try nestedContainer.decodeIfPresent(String.self, forKey: typeCodingKey) { + //get the type + guard let type = ModelRegistry.types[identifier] else { + throw ModelRegistry.Error.decoderErrorModelNotMapped + } + //now get the decoder to use for the type + let decoder = try containerCopy.superDecoder() + let model = try type.init(from: decoder) + models.append(model) + } + i+=1 } - i += 1 } - return models + return models.count > 0 ? models : nil } - public func decodeArray(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> [Model] { - guard let models: [Model] = try decodeArrayIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else { + /// Decodes an array of registered model based on the identifiers. + public func decodeModels(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> [Model] { + guard let models: [Model] = try decodeModelsIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else { throw ModelRegistry.Error.decoderErrorObjectNotPresent } return models } } - extension KeyedEncodingContainer where Key: CodingKey { - public mutating func encodeIfPresent(_ value: Model?, forKey key: KeyedEncodingContainer.Key) throws { + /// Encodes a model, optional. + public mutating func encodeModelIfPresent(_ value: Model?, forKey key: KeyedEncodingContainer.Key) throws { if let v = value { let encoder = self.superEncoder(forKey: key) try v.encode(to: encoder) } } - public mutating func encode(_ value: Model, forKey key: KeyedEncodingContainer.Key) throws { + /// Encodes a model. + public mutating func encodeModel(_ value: Model, forKey key: KeyedEncodingContainer.Key) throws { let encoder = self.superEncoder(forKey: key) try value.encode(to: encoder) } - ///need instance type as input paramaeter list - public mutating func encodeArray(_ list:[Model], forKey key:KeyedEncodingContainer.Key) throws { - var unkeyedContainer = self.nestedUnkeyedContainer(forKey: key) - for model in list { - let typeString = type(of: model).identifier - let type = ModelRegistry.getType(for: typeString) - try type?.mvmencode(unkeyedContainer: &unkeyedContainer, model: model) - } + /// Encodes an array of models + public mutating func encodeModels(_ list: [Model], forKey key:KeyedEncodingContainer.Key) throws { + try encodeModelsIfPresent(list, forKey: key) } - public mutating func encodeArrayIfPresent(_ list:[Model]?, forKey key:KeyedEncodingContainer.Key) throws { - guard let models = list else { return } - do { - try self.encodeArray(models, forKey: key) - } catch { - return + /// Encodes an array of models, optional, need instance type as input paramaeter list + public mutating func encodeModelsIfPresent(_ list: [Model]?, forKey key:KeyedEncodingContainer.Key) throws { + guard let list = list else { return } + var unkeyedContainer = self.nestedUnkeyedContainer(forKey: key) + for model in list { + try model.encode(unkeyedContainer: &unkeyedContainer) } } }