izeni-team / retrolux

The all in one networking solution for iOS.
MIT License
30 stars 3 forks source link

Retrolux v0.6.0 #18

Closed cbh2000 closed 6 years ago

cbh2000 commented 7 years ago

Plan:

//: Playground - noun: a place where people can play

import UIKit

enum PropertyCustomizations {
    case ignored
    case nullable
    case mapped(to: String)
    case transformed(TransformerType)
}

class Config {
    internal var storage = [String: [PropertyCustomizations]]()
    subscript(property: String) -> [PropertyCustomizations] {
        get {
            return storage[property] ?? []
        }
        set {
            storage[property] = newValue
        }
    }
}

protocol Reflectable: NSObjectProtocol {
    static func config(_ c: Config)
}

class Reflection: NSObject, Reflectable {
    class func config(_ c: Config) {

    }
}

protocol TransformerType {
    var propertyType: Any.Type { get }
    var dataType: Any.Type { get }

    func set(value: Any, propertyName: String, instance: Reflectable)
    func getValue(propertyName: String, instance: Reflectable) -> Any
}

class Transformer<PropertyType, DataType>: TransformerType {
    var propertyType: Any.Type {
        return PropertyType.self
    }

    var dataType: Any.Type {
        return DataType.self
    }

    private let setter: (DataType) -> PropertyType
    private let getter: (PropertyType) -> DataType

    init(setter: @escaping (DataType) -> PropertyType, getter: @escaping (PropertyType) -> DataType) {
        self.setter = setter
        self.getter = getter
    }

    func set(value: Any, propertyName: String, instance: Reflectable) {
        let transformed = setter(value as! DataType)
        (instance as! NSObject).setValue(transformed, forKey: propertyName)
    }

    func getValue(propertyName: String, instance: Reflectable) -> Any {
        return getter((instance as! NSObject).value(forKey: propertyName) as! PropertyType)
    }
}

class CustomTransformer<ClassType, PropertyType, DataType>: TransformerType {
    var propertyType: Any.Type {
        return PropertyType.self
    }

    var dataType: Any.Type {
        return DataType.self
    }

    init(setter: @escaping (ClassType, DataType) -> Void, getter: @escaping (ClassType, PropertyType) -> DataType) {

    }

    func set(value: Any, propertyName: String, instance: Reflectable) {

    }

    func getValue(propertyName: String, instance: Reflectable) -> Any {
        return () as Any
    }
}

let dateTransformer: TransformerType =
    Transformer<Date, String>(setter: { (value) -> Date in
        print("input: \(value)")
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'hh:mm:ssZ"
        return formatter.date(from: value as! String)!
    }, getter: { (value: Date) -> String in
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'hh:mm:ssZ"
        return formatter.string(from: value)
    })

class Person: Reflection {
    var name = ""
    var age = Data()

    var born = Date()

    override class func config(_ c: Config) {
        c["name"] = [.ignored]
        c["born"] = [.transformed(dateTransformer)]

        let customTransformer = CustomTransformer<Person, Data, Int>(setter: { (person, value) in
            person.age = Data()
        }, getter: { _ in
            Int()
        })
        c["age"] = [.nullable, .mapped(to: "user_age"), .transformed(customTransformer)]
    }
}

let config = Config()
let p = Person()
let type: Reflectable.Type = type(of: p)
type.config(config)
config["name"]

if case PropertyCustomizations.transformed(let transformer) = PropertyCustomizations.transformed(dateTransformer) {
    let value: Any = "2005-04-03T12:00:00Z"
    if type(of: value) == transformer.dataType || transformer.dataType == Any.self {
        transformer.set(value: value, propertyName: "born", instance: p)
    } else {
        print("Type \(type(of: value)) is not supported type. Should be \(transformer.dataType).")
    }
    print("person.born:", p.born)

    let gotBack = transformer.getValue(propertyName: "born", instance: p)
    print("Value back was: \(gotBack)")
}