Name changes and cleanup

This commit is contained in:
Pfeil, Scott Robert 2019-12-17 14:12:07 -05:00
parent 4a05db9c9a
commit fc108373cb
2 changed files with 65 additions and 72 deletions

View File

@ -12,33 +12,33 @@ public protocol Model: Codable {
static var identifier: String { get }
static func mvmdecode<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, 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<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, 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<K:CodingKey>(keyedContainer: inout KeyedEncodingContainer<K>, codingKey: K) throws
/// Convenience function to encode model using an unkeyed container.
func encode(unkeyedContainer: inout UnkeyedEncodingContainer) throws
}
extension Model {
static public func mvmdecode<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, codingKey: K) throws -> Self? {
static public func decode<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, 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<K:CodingKey>(keyedContainer: inout KeyedEncodingContainer<K>, 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<K:CodingKey>(keyedContainer: inout KeyedEncodingContainer<K>, 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)
}
}

View File

@ -19,6 +19,7 @@ public struct ModelRegistry {
fileprivate static var types = [String: Model.Type]()
/// Register the model.
public static func register<M: Model>(_ type: M.Type) {
types[M.identifier] = type
}
@ -31,8 +32,9 @@ public struct ModelRegistry {
extension KeyedDecodingContainer where Key: CodingKey {
//MARK: - Decode
public func decode<T, C:CodingKey>(codingKey: KeyedDecodingContainer<K>.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<T, C: CodingKey>(codingKey: KeyedDecodingContainer<K>.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<T, C:CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> T? {
//get the type string
var meta: KeyedDecodingContainer<C>?
/// Decodes to a registered model based on the identifier, optional.
public func decodeModelIfPresent<T, C: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> T? {
//get the identifier string
var container: KeyedDecodingContainer<C>?
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<C:CodingKey>(codingKey: KeyedDecodingContainer<K>.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<C: CodingKey>(codingKey: KeyedDecodingContainer<K>.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<C:CodingKey>(codingKey: KeyedDecodingContainer<K>.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<C: CodingKey>(codingKey: KeyedDecodingContainer<K>.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<K>.Key) throws {
/// Encodes a model, optional.
public mutating func encodeModelIfPresent(_ value: Model?, forKey key: KeyedEncodingContainer<K>.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<K>.Key) throws {
/// Encodes a model.
public mutating func encodeModel(_ value: Model, forKey key: KeyedEncodingContainer<K>.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<K>.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<K>.Key) throws {
try encodeModelsIfPresent(list, forKey: key)
}
public mutating func encodeArrayIfPresent(_ list:[Model]?, forKey key:KeyedEncodingContainer<K>.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<K>.Key) throws {
guard let list = list else { return }
var unkeyedContainer = self.nestedUnkeyedContainer(forKey: key)
for model in list {
try model.encode(unkeyedContainer: &unkeyedContainer)
}
}
}