147 lines
4.0 KiB
Swift
147 lines
4.0 KiB
Swift
|
//
|
||
|
// Node.swift
|
||
|
// MongoView
|
||
|
//
|
||
|
// Created by Shadowfacts on 1/9/20.
|
||
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
import MongoSwift
|
||
|
|
||
|
class Node {
|
||
|
let key: Key?
|
||
|
let value: BSON
|
||
|
|
||
|
lazy private(set) var children: [Node] = {
|
||
|
switch value {
|
||
|
case let .array(array):
|
||
|
return array.enumerated().map { (index, val) in
|
||
|
Node(key: .index(index), value: val)
|
||
|
}
|
||
|
case let .document(doc):
|
||
|
return doc.map { (key, val) in
|
||
|
Node(key: .name(key), value: val)
|
||
|
}
|
||
|
default:
|
||
|
return []
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
var numberOfChildren: Int {
|
||
|
children.count
|
||
|
}
|
||
|
|
||
|
var hasChildren: Bool {
|
||
|
numberOfChildren > 0
|
||
|
}
|
||
|
|
||
|
init(key: Key? = nil, value: BSON) {
|
||
|
self.key = key
|
||
|
self.value = value
|
||
|
}
|
||
|
|
||
|
convenience init(document: Document) {
|
||
|
if case let .objectId(id) = document["_id"] {
|
||
|
self.init(key: .objectId(id), value: .document(document))
|
||
|
} else {
|
||
|
self.init(key: nil, value: .document(document))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extension Node {
|
||
|
enum Key {
|
||
|
case index(Int)
|
||
|
case name(String)
|
||
|
case objectId(ObjectId)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extension Node {
|
||
|
static let dateFormatter: DateFormatter = {
|
||
|
let formatter = DateFormatter()
|
||
|
formatter.locale = .current
|
||
|
formatter.setLocalizedDateFormatFromTemplate("yyyy-MM-dd HH:mm:ss ZZ")
|
||
|
return formatter
|
||
|
}()
|
||
|
|
||
|
var keyString: String {
|
||
|
switch key {
|
||
|
case nil:
|
||
|
return ""
|
||
|
case let .index(index):
|
||
|
return index.description
|
||
|
case let .name(name):
|
||
|
return name
|
||
|
case let .objectId(id):
|
||
|
return id.description
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var valueString: String {
|
||
|
switch value {
|
||
|
case let .double(value):
|
||
|
return value.description
|
||
|
case let .string(value):
|
||
|
return value
|
||
|
case let .document(doc):
|
||
|
return "(\(doc.count) field\(doc.count == 1 ? "" : "s"))"
|
||
|
case let .array(array):
|
||
|
return "(\(array.count) element\(array.count == 1 ? "" : "s"))"
|
||
|
case let .binary(value):
|
||
|
switch Binary.Subtype(rawValue: value.subtype) {
|
||
|
case nil:
|
||
|
return "(unknown binary data)"
|
||
|
case .generic:
|
||
|
return "(generic binary data)"
|
||
|
case .function:
|
||
|
return "(function binary data)"
|
||
|
case .binaryDeprecated:
|
||
|
return "(binary data)"
|
||
|
case .uuidDeprecated:
|
||
|
fallthrough
|
||
|
case .uuid:
|
||
|
return try! UUID(from: value).description
|
||
|
case .md5:
|
||
|
return "(MD5 binary data)"
|
||
|
case .userDefined:
|
||
|
return "(user defined binary data)"
|
||
|
}
|
||
|
case .undefined:
|
||
|
return "undefined"
|
||
|
case let .objectId(value):
|
||
|
return value.description
|
||
|
case let .bool(value):
|
||
|
return value.description
|
||
|
case let .datetime(value):
|
||
|
return value.description
|
||
|
case .null:
|
||
|
return "null"
|
||
|
case let .regex(value):
|
||
|
return try! NSRegularExpression(from: value).description
|
||
|
case let .dbPointer(value):
|
||
|
return "\(value.ref)(\(value.id))"
|
||
|
case let .symbol(value):
|
||
|
return value.description
|
||
|
case let .code(value):
|
||
|
return value.code
|
||
|
case let .codeWithScope(value):
|
||
|
return value.code
|
||
|
case let .int32(value):
|
||
|
return value.description
|
||
|
case let .timestamp(value):
|
||
|
let date = Date(timeIntervalSince1970: TimeInterval(value.timestamp))
|
||
|
return Node.dateFormatter.string(from: date)
|
||
|
case let .int64(value):
|
||
|
return value.description
|
||
|
case let .decimal128(value):
|
||
|
return value.description
|
||
|
case .minKey:
|
||
|
return "(min key)"
|
||
|
case .maxKey:
|
||
|
return "(max key)"
|
||
|
}
|
||
|
}
|
||
|
}
|