Files
JSONAPI/Sources/JSONAPITestLib/EntityCheck.swift
T
2018-11-27 13:57:55 -08:00

76 lines
2.1 KiB
Swift

//
// EntityCheck.swift
// JSONAPITestLib
//
// Created by Mathew Polzin on 11/27/18.
//
import JSONAPI
public enum EntityCheckError: Swift.Error {
case attributesNotStruct
case relationshipsNotStruct
case nonAttribute(named: String)
case nonRelationship(named: String)
case nullArray(named: String)
case badId
}
public struct EntityCheckErrors: Swift.Error {
let problems: [EntityCheckError]
}
private protocol OptionalAttributeType {}
extension Optional: OptionalAttributeType where Wrapped: AttributeType {}
private protocol OptionalArray {}
extension Optional: OptionalArray where Wrapped: ArrayType {}
private protocol AttributeTypeWithOptionalArray {}
extension TransformedAttribute: AttributeTypeWithOptionalArray where RawValue: OptionalArray {}
private protocol OptionalRelationshipType {}
extension Optional: OptionalRelationshipType where Wrapped: RelationshipType {}
public extension Entity {
public static func check(_ entity: Entity) throws {
var problems = [EntityCheckError]()
if Swift.type(of: entity.id).EntityDescription.self != Description.self {
problems.append(.badId)
}
let attributesMirror = Mirror(reflecting: entity.attributes)
if attributesMirror.displayStyle != .`struct` {
problems.append(.attributesNotStruct)
}
for attribute in attributesMirror.children {
if attribute.value as? AttributeType == nil,
attribute.value as? OptionalAttributeType == nil {
problems.append(.nonAttribute(named: attribute.label ?? "unnamed"))
}
if attribute.value as? AttributeTypeWithOptionalArray != nil {
problems.append(.nullArray(named: attribute.label ?? "unnamed"))
}
}
let relationshipsMirror = Mirror(reflecting: entity.relationships)
if relationshipsMirror.displayStyle != .`struct` {
problems.append(.relationshipsNotStruct)
}
for relationship in relationshipsMirror.children {
if relationship.value as? RelationshipType == nil {
problems.append(.nonRelationship(named: relationship.label ?? "unnamed"))
}
}
guard problems.count == 0 else {
throw EntityCheckErrors(problems: problems)
}
}
}