Skip to content
This repository has been archived by the owner on Jan 25, 2019. It is now read-only.

Commit

Permalink
- Updated SpineError.serializerError to wrap underlying SerializerError.
Browse files Browse the repository at this point in the history
- Updated filtering methods of Query.
- Documentation and code cleanup.
  • Loading branch information
wvteijlingen committed Oct 22, 2016
1 parent 67022c1 commit 13c650d
Show file tree
Hide file tree
Showing 16 changed files with 515 additions and 817 deletions.
107 changes: 45 additions & 62 deletions Spine/DeserializeOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ class DeserializeOperation: Operation {

// MARK: Deserializing

/**
Maps a single resource representation into a resource object of the given type.

- parameter representation: The JSON representation of a single resource.
- parameter mappingTargetIndex: The index of the matching mapping target.

- returns: A Resource object with values mapped from the representation.
*/
/// Maps a single resource representation into a resource object of the given type.
///
/// - parameter representation: The JSON representation of a single resource.
/// - parameter mappingTargetIndex: The index of the matching mapping target.
///
/// - throws: A SerializerError when an error occurs in serializing.
///
/// - returns: A Resource object with values mapped from the representation.
fileprivate func deserializeSingleRepresentation(_ representation: JSON, mappingTargetIndex: Int? = nil) throws -> Resource {
guard representation.dictionary != nil else {
throw SerializerError.invalidResourceStructure
Expand Down Expand Up @@ -183,16 +183,10 @@ class DeserializeOperation: Operation {

// MARK: Attributes

/**
Extracts the attributes from the given data into the given resource.

This method loops over all the attributes in the passed resource, maps the attribute name
to the key for the serialized form and invokes `extractAttribute`. It then formats the extracted
attribute and sets the formatted value on the resource.

- parameter serializedData: The data from which to extract the attributes.
- parameter resource: The resource into which to extract the attributes.
*/
/// Extracts the attributes from the given data into the given resource.
///
/// - parameter serializedData: The data from which to extract the attributes.
/// - parameter resource: The resource into which to extract the attributes.
fileprivate func extractAttributes(from serializedData: JSON, intoResource resource: Resource) {
for case let field as Attribute in resource.fields {
let key = keyFormatter.format(field)
Expand All @@ -203,14 +197,12 @@ class DeserializeOperation: Operation {
}
}

/**
Extracts the value for the given key from the passed serialized data.

- parameter serializedData: The data from which to extract the attribute.
- parameter key: The key for which to extract the value from the data.

- returns: The extracted value or nil if no attribute with the given key was found in the data.
*/
/// Extracts the value for the given key from the passed serialized data.
///
/// - parameter key: The data from which to extract the attribute.
/// - parameter serializedData: The key for which to extract the value from the data.
///
/// - returns: The extracted value or nil if no attribute with the given key was found in the data.
fileprivate func extractAttribute(_ key: String, from serializedData: JSON) -> Any? {
let value = serializedData["attributes"][key]

Expand All @@ -224,17 +216,10 @@ class DeserializeOperation: Operation {

// MARK: Relationships

/**
Extracts the relationships from the given data into the given resource.

This method loops over all the relationships in the passed resource, maps the relationship name
to the key for the serialized form and invokes `extractToOneRelationship` or `extractToManyRelationship`.
It then sets the extracted ResourceRelationship on the resource.
It also sets `relationships` dictionary on parent resource containing the links to all related resources.

- parameter serializedData: The data from which to extract the relationships.
- parameter resource: The resource into which to extract the relationships.
*/
/// Extracts the relationships from the given data into the given resource.
///
/// - parameter serializedData: The data from which to extract the relationships.
/// - parameter resource: The resource into which to extract the relationships.
fileprivate func extractRelationships(from serializedData: JSON, intoResource resource: Resource) {
for field in resource.fields {
let key = keyFormatter.format(field)
Expand All @@ -257,17 +242,15 @@ class DeserializeOperation: Operation {
}
}
}

/**
Extracts the to-one relationship for the given key from the passed serialized data.

This method supports both the single ID form and the resource object forms.

- parameter serializedData: The data from which to extract the relationship.
- parameter key: The key for which to extract the relationship from the data.

- returns: The extracted relationship or nil if no relationship with the given key was found in the data.
*/

/// Extracts the to-one relationship for the given key from the passed serialized data.
/// This method supports both the single ID form and the resource object forms.
///
/// - parameter key: The key for which to extract the relationship from the data.
/// - parameter serializedData: The data from which to extract the relationship.
/// - parameter linkedType: The type of the linked resource as it is defined on the parent resource.
///
/// - returns: The extracted relationship or nil if no relationship with the given key was found in the data.
fileprivate func extractToOneRelationship(_ key: String, from serializedData: JSON, linkedType: ResourceType) -> Resource? {
var resource: Resource? = nil

Expand Down Expand Up @@ -295,17 +278,14 @@ class DeserializeOperation: Operation {

return resource
}

/**
Extracts the to-many relationship for the given key from the passed serialized data.

This method supports both the array of IDs form and the resource object forms.

- parameter serializedData: The data from which to extract the relationship.
- parameter key: The key for which to extract the relationship from the data.

- returns: The extracted relationship or nil if no relationship with the given key was found in the data.
*/

/// Extracts the to-many relationship for the given key from the passed serialized data.
/// This method supports both the array of IDs form and the resource object forms.
///
/// - parameter key: The key for which to extract the relationship from the data.
/// - parameter serializedData: The data from which to extract the relationship.
///
/// - returns: The extracted relationship or nil if no relationship with the given key was found in the data.
fileprivate func extractToManyRelationship(_ key: String, from serializedData: JSON) -> LinkedResourceCollection? {
var resourceCollection: LinkedResourceCollection? = nil

Expand All @@ -324,6 +304,11 @@ class DeserializeOperation: Operation {
return resourceCollection
}

/// Extract the relationship data from the given JSON.
///
/// - parameter linkData: The JSON from which to extract relationship data.
///
/// - returns: A RelationshipData object.
fileprivate func extractRelationshipData(_ linkData: JSON) -> RelationshipData {
let selfURL = linkData["links"]["self"].URL
let relatedURL = linkData["links"]["related"].URL
Expand All @@ -342,9 +327,7 @@ class DeserializeOperation: Operation {
return RelationshipData(selfURL: selfURL, relatedURL: relatedURL, data: data)
}

/**
Resolves the relations of the fetched resources.
*/
/// Resolves the relations of the fetched resources.
fileprivate func resolveRelationships() {
for resource in resourcePool {
for case let field as ToManyRelationship in resource.fields {
Expand Down
6 changes: 3 additions & 3 deletions Spine/Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public enum SpineError: Error, Equatable {
case resourceNotFound

/// An error occured during (de)serializing.
case serializerError
case serializerError(SerializerError)

/// A error response was received from the API.
case serverError(statusCode: Int, apiErrors: [APIError]?)
Expand Down Expand Up @@ -97,8 +97,8 @@ public func ==(lhs: SpineError, rhs: SpineError) -> Bool {
return true
case (.resourceNotFound, .resourceNotFound):
return true
case (.serializerError, .serializerError):
return true
case (let .serializerError(lhsError), let .serializerError(rhsError)):
return lhsError == rhsError
case (let .serverError(lhsStatusCode, lhsApiErrors), let .serverError(rhsStatusCode, rhsApiErrors)):
if lhsStatusCode != rhsStatusCode { return false }
if lhsApiErrors == nil && rhsApiErrors == nil { return true }
Expand Down
20 changes: 6 additions & 14 deletions Spine/KeyFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@

import Foundation

/**
The KeyFormatter protocol declares methods and properties that a key formatter must implement.
A key formatter transforms field names as they appear in Resources to keys as they appear in a JSONAPI document.
*/
/// The KeyFormatter protocol declares methods and properties that a key formatter must implement.
/// A key formatter transforms field names as they appear in Resources to keys as they appear in a JSONAPI document.
public protocol KeyFormatter {
func format(_ name: String) -> String
}
Expand All @@ -22,10 +20,8 @@ extension KeyFormatter {
}
}

/**
AsIsKeyFormatter does not format anything, i.e. it returns the field name as it. Use this if your field names correspond to
keys in a JSONAPI document one to one.
*/
/// AsIsKeyFormatter does not format anything, i.e. it returns the field name as it. Use this if your field names correspond to
/// keys in a JSONAPI document one to one.
public struct AsIsKeyFormatter: KeyFormatter {
public func format(_ name: String) -> String {
return name;
Expand All @@ -34,9 +30,7 @@ public struct AsIsKeyFormatter: KeyFormatter {
public init() { }
}

/**
DasherizedKeyFormatter formats field names as dasherized keys. Eg. someFieldName -> some-field-name.
*/
/// DasherizedKeyFormatter formats field names as dasherized keys. Eg. someFieldName -> some-field-name.
public struct DasherizedKeyFormatter: KeyFormatter {
let regex: NSRegularExpression

Expand All @@ -50,9 +44,7 @@ public struct DasherizedKeyFormatter: KeyFormatter {
}
}

/*
UnderscoredKeyFormatter formats field names as underscored keys. Eg. someFieldName -> some_field_name.
*/
/// UnderscoredKeyFormatter formats field names as underscored keys. Eg. someFieldName -> some_field_name.
public struct UnderscoredKeyFormatter: KeyFormatter {
let regex: NSRegularExpression

Expand Down
11 changes: 5 additions & 6 deletions Spine/Logging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,11 @@ public enum LogLevel: Int {
}
}

/**
Logging domains
- Spine: The main Spine component.
- Networking: The networking component, requests, responses etc.
- Serializing: The (de)serializing component.
*/
/// Logging domains
///
/// - spine: The main Spine component.
/// - networking: The networking component, requests, responses etc.
/// - serializing: The (de)serializing component.
public enum LogDomain {
case spine, networking, serializing
}
Expand Down
18 changes: 8 additions & 10 deletions Spine/Operation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ fileprivate func statusCodeIsSuccess(_ statusCode: Int?) -> Bool {
}

fileprivate extension Error {
/// Promotes an ErrorType to a higher level SpineError.
/// Errors that cannot be represented as a SpineError will be returned as SpineError.UnknownError
/// Promotes the rror to a SpineError.
/// Errors that cannot be represented as a SpineError will be returned as SpineError.unknownError
var asSpineError: SpineError {
switch self {
case is SpineError:
return self as! SpineError
case is SerializerError:
return .serializerError
return .serializerError(self as! SerializerError)
default:
return .unknownError
}
Expand Down Expand Up @@ -195,7 +195,7 @@ class DeleteOperation: ConcurrentOperation {
self.result = .success()
} else if let data = responseData , data.count > 0 {
do {
let document = try self.serializer.deserializeData(data, mappingTargets: nil)
let document = try self.serializer.deserializeData(data)
self.result = .failure(.serverError(statusCode: statusCode!, apiErrors: document.errors))
} catch let error {
self.result = .failure(error.asSpineError)
Expand Down Expand Up @@ -380,14 +380,12 @@ private class RelationshipOperation: ConcurrentOperation {

if statusCodeIsSuccess(statusCode) {
self.result = .success()
} else if let data = responseData , data.count > 0 {
} else if let data = responseData, data.count > 0 {
do {
let document = try serializer.deserializeData(data, mappingTargets: nil)
let document = try serializer.deserializeData(data)
self.result = .failure(.serverError(statusCode: statusCode!, apiErrors: document.errors))
} catch let error as SpineError {
self.result = .failure(error)
} catch {
self.result = .failure(.serializerError)
} catch let error {
self.result = .failure(error.asSpineError)
}
} else {
self.result = .failure(.serverError(statusCode: statusCode!, apiErrors: nil))
Expand Down
Loading

0 comments on commit 13c650d

Please sign in to comment.