mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
95 lines
2.8 KiB
Swift
95 lines
2.8 KiB
Swift
//
|
|
// EntityCheck.swift
|
|
// JSONAPITesting
|
|
//
|
|
// Created by Mathew Polzin on 11/27/18.
|
|
//
|
|
|
|
import JSONAPI
|
|
|
|
public enum EntityCheckError: Swift.Error {
|
|
/// The attributes should live in a struct, not
|
|
/// another type class.
|
|
case attributesNotStruct
|
|
|
|
/// The relationships should live in a struct, not
|
|
/// another type class.
|
|
case relationshipsNotStruct
|
|
|
|
/// All stored properties on an Attributes struct should
|
|
/// be one of the supplied Attribute types.
|
|
case nonAttribute(named: String)
|
|
|
|
/// All stored properties on a Relationships struct should
|
|
/// be one of the supplied Relationship types.
|
|
case nonRelationship(named: String)
|
|
|
|
/// It is explicitly stated by the JSON spec
|
|
/// a "none" value for arrays is an empty array, not `nil`.
|
|
case nullArray(named: String)
|
|
}
|
|
|
|
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 {}
|
|
extension Attribute: AttributeTypeWithOptionalArray where RawValue: OptionalArray {}
|
|
|
|
private protocol OptionalRelationshipType {}
|
|
extension Optional: OptionalRelationshipType where Wrapped: RelationshipType {}
|
|
|
|
private protocol _RelationshipType {}
|
|
extension ToOneRelationship: _RelationshipType {}
|
|
extension ToManyRelationship: _RelationshipType {}
|
|
|
|
private protocol _AttributeType {}
|
|
extension TransformedAttribute: _AttributeType {}
|
|
extension Attribute: _AttributeType {}
|
|
|
|
public extension Entity {
|
|
static func check(_ entity: Entity) throws {
|
|
var problems = [EntityCheckError]()
|
|
|
|
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,
|
|
relationship.value as? OptionalRelationshipType == nil {
|
|
problems.append(.nonRelationship(named: relationship.label ?? "unnamed"))
|
|
}
|
|
}
|
|
|
|
guard problems.count == 0 else {
|
|
throw EntityCheckErrors(problems: problems)
|
|
}
|
|
}
|
|
}
|