1
0

Reflection.swift 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //
  2. // Relfection.swift
  3. // Swifter
  4. //
  5. // Copyright (c) 2014-2016 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. public protocol DatabaseReflectionProtocol {
  9. var id: UInt64? { get }
  10. init()
  11. }
  12. public class DatabaseReflection: DatabaseReflectionProtocol {
  13. static var sharedDatabase: SQLite?
  14. public var id: UInt64? = nil
  15. required public init() { }
  16. }
  17. public extension DatabaseReflectionProtocol {
  18. public func schemeWithValuesMethod1() -> (String, [String: Any?]) {
  19. let reflections = _reflect(self)
  20. var fields = [String: Any?]()
  21. for index in 0.stride(to: reflections.count, by: 1) {
  22. let reflection = reflections[index]
  23. fields[reflection.0] = reflection.1.value
  24. }
  25. return (reflections.summary, fields)
  26. }
  27. public func schemeWithValuesMethod2() -> (String, [String: Any?]) {
  28. let mirror = Mirror(reflecting: self)
  29. var fields = [String: Any?]()
  30. for case let (label?, value) in mirror.children {
  31. fields[label] = value
  32. }
  33. return ("\(mirror.subjectType)", fields)
  34. }
  35. public func schemeWithValuesAsString() -> (String, [(String, String?)]) {
  36. let (name, fields) = schemeWithValuesMethod2()
  37. var map = [(String, String?)]()
  38. for (key, value) in fields {
  39. // TODO - Replace this by extending all supported types by a protocol.
  40. // Example: 'extenstion Int: DatabaseConvertible { convert() -> something ( not necessary String type ) }'
  41. if let intValue = value as? Int { map.append((key, String(intValue))) }
  42. if let int32Value = value as? Int32 { map.append((key, String(int32Value))) }
  43. if let int64Value = value as? Int64 { map.append((key, String(int64Value))) }
  44. if let doubleValue = value as? Double { map.append((key, String(doubleValue))) }
  45. if let stringValue = value as? String { map.append((key, stringValue)) }
  46. }
  47. return (name, map)
  48. }
  49. public static func classInstanceWithSchemeMethod1() -> (Self, String, [String: Any?]) {
  50. let instance = Self()
  51. let (name, fields) = instance.schemeWithValuesMethod1()
  52. return (instance, name, fields)
  53. }
  54. public static func classInstanceWithSchemeMethod2() -> (Self, String, [String: Any?]) {
  55. let instance = Self()
  56. let (name, fields) = instance.schemeWithValuesMethod2()
  57. return (instance, name, fields)
  58. }
  59. static func find(id: UInt64) -> Self? {
  60. let (instance, _, _) = classInstanceWithSchemeMethod1()
  61. // TODO - make a query to DB
  62. return instance
  63. }
  64. public func insert() throws {
  65. guard let database = DatabaseReflection.sharedDatabase else {
  66. throw SQLiteError.OpenFailed("Database connection is not opened.")
  67. }
  68. let (name, fields) = schemeWithValuesAsString()
  69. try database.exec("CREATE TABLE IF NOT EXISTS \(name) (" + fields.map { "\($0.0) TEXT" }.joinWithSeparator(", ") + ");")
  70. let names = fields.map { "\($0.0)" }.joinWithSeparator(", ")
  71. let values = Array(count: fields.count, repeatedValue: "?").joinWithSeparator(", ")
  72. try database.exec("INSERT INTO \(name)(" + names + ") VALUES(" + values + ");", fields.map { $0.1 })
  73. }
  74. }