Compare commits

...

17 Commits

Author SHA1 Message Date
Matt Bruce
8858f89a5c create new ModelHandler protocol/classes
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2022-03-03 16:01:23 -06:00
Matt Bruce
669a4c4726 made Category public property
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2022-03-03 16:00:31 -06:00
Matt Bruce
07cf145686 refactored to new throws JSONAny
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2022-02-15 11:00:34 -06:00
Matt Bruce
5f3daa573f Merge branch 'develop' into feature/JSONValue-base
# Conflicts:
#	MVMCore/MVMCore/Models/Extensions/Encoder.swift

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2022-02-15 10:40:23 -06:00
Pfeil, Scott Robert
7f57d493f6 Merge branch 'feature/TrialFraud-DEVAO-1533' into 'develop'
TrialFraud extension additions

See merge request BPHV_MIPS/mvm_core!194
2022-02-15 16:11:37 +00:00
Bruce, Matt R
3e06f6ee44 TrialFraud extension additions 2022-02-15 16:11:33 +00:00
Pfeil, Scott Robert
e0d3bfb9e3 Merge branch 'release/9_6_0' into 'develop'
release/9_6_0 hotfix merge

See merge request BPHV_MIPS/mvm_core!191
2022-02-07 17:02:49 +00:00
Hedden, Kyle Matthew
d3d198b007 Merge branch 'bugfix/urlQueryParameters' into 'release/9_6_0'
Added helper functions

See merge request BPHV_MIPS/mvm_core!192
2022-01-24 23:57:09 +00:00
Scott Pfeil
40c365829a JSONARRAY fix 2022-01-24 18:51:05 -05:00
Scott Pfeil
306e66a3b2 review changes 2022-01-24 18:14:37 -05:00
Krishna Kishore Bandaru
f2d824f829 added helper functions 2022-01-22 00:42:17 +05:30
Hedden, Kyle Matthew
1dcdc12919 Merge branch 'feature/remove_mdn_dependency' into 'develop'
change mdn calculation

See merge request BPHV_MIPS/mvm_core!188
2021-12-28 21:06:06 +00:00
Scott Pfeil
0711efee00 Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core into feature/remove_mdn_dependency 2021-11-22 10:31:54 -05:00
Scott Pfeil
324be22ad2 Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core into feature/remove_mdn_dependency 2021-11-09 11:50:57 -05:00
Scott Pfeil
c93bb7f0f6 Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core into feature/remove_mdn_dependency 2021-11-02 15:26:39 -04:00
Scott Pfeil
d3bf9481fc change mdn calculation
default errors not received from server
2021-10-25 17:32:18 -04:00
Scott Pfeil
d1ea9518a0 NSA launch 2021-10-25 13:56:39 -04:00
11 changed files with 239 additions and 36 deletions

View File

@ -157,6 +157,9 @@
D2DEDCBB23C65BC300C44CC4 /* Percent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DEDCBA23C65BC300C44CC4 /* Percent.swift */; };
D2E1FAD92260C3E400AEFD8C /* DelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAD82260C3E400AEFD8C /* DelegateObject.swift */; };
EA3B264C25FC0B7600008074 /* ModelHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3B264B25FC0B7600008074 /* ModelHandlerProtocol.swift */; };
EA48AAE427D16DE400678D5C /* AnyHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA48AAE327D16DE400678D5C /* AnyHandler.swift */; };
EA48AAE627D16DF500678D5C /* ModelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA48AAE527D16DF500678D5C /* ModelHandler.swift */; };
EA48AAE827D16E2900678D5C /* HandlerRequestProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@ -304,6 +307,9 @@
D2DEDCBA23C65BC300C44CC4 /* Percent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Percent.swift; sourceTree = "<group>"; };
D2E1FAD82260C3E400AEFD8C /* DelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelegateObject.swift; sourceTree = "<group>"; };
EA3B264B25FC0B7600008074 /* ModelHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelHandlerProtocol.swift; sourceTree = "<group>"; };
EA48AAE327D16DE400678D5C /* AnyHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyHandler.swift; sourceTree = "<group>"; };
EA48AAE527D16DF500678D5C /* ModelHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelHandler.swift; sourceTree = "<group>"; };
EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandlerRequestProtocol.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -615,6 +621,9 @@
AFBB96B61FBA3CEC0008D868 /* MVMCoreActionHandler.h */,
AFBB96B71FBA3CEC0008D868 /* MVMCoreActionHandler.m */,
D27073CC25BB4CEF001C7246 /* MVMCoreActionHandler+Extension.swift */,
EA48AAE327D16DE400678D5C /* AnyHandler.swift */,
EA48AAE527D16DF500678D5C /* ModelHandler.swift */,
EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */,
);
path = ActionHandling;
sourceTree = "<group>";
@ -850,6 +859,7 @@
01F2A03623A80A7300D954D8 /* ActionModelProtocol.swift in Sources */,
AFBB96991FBA3A9A0008D868 /* MVMCoreAlertController.m in Sources */,
881D26941FCC9D180079C521 /* MVMCoreOperation.m in Sources */,
EA48AAE627D16DF500678D5C /* ModelHandler.swift in Sources */,
AFED77A41FCCA29400BAE689 /* MVMCoreViewControllerMappingObject.m in Sources */,
01C851CF23CF7B260021F976 /* JSONMap.swift in Sources */,
01F2A04C23A82B1B00D954D8 /* ActionCallModel.swift in Sources */,
@ -867,9 +877,11 @@
881D26931FCC9D180079C521 /* MVMCoreErrorObject.m in Sources */,
94C014D124211869005811A9 /* ActionRestartModel.swift in Sources */,
D288D5F526C6EFE000A5C365 /* MVMCoreLoggingHandler+Extension.swift in Sources */,
EA48AAE427D16DE400678D5C /* AnyHandler.swift in Sources */,
946EE1B0237B5EF70036751F /* JSONHelper.swift in Sources */,
30349BF21FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m in Sources */,
D2DEDCB923C6400600C44CC4 /* UnitInterval.swift in Sources */,
EA48AAE827D16E2900678D5C /* HandlerRequestProtocol.swift in Sources */,
94C014D3242119E6005811A9 /* ActionPreviousSubmitModel.swift in Sources */,
8876D5E91FB50AB000EB2E3D /* NSArray+MFConvenience.m in Sources */,
D27073B725BB45C4001C7246 /* ActionActionsModel.swift in Sources */,

View File

@ -0,0 +1,36 @@
//
// AnyHandler.swift
// MVMCore
//
// Created by Matt Bruce on 3/3/22.
// Copyright © 2022 myverizon. All rights reserved.
//
import Foundation
/// Type Erased class for HandlerRequestProtocol
public class AnyHandler<Response, Error: Swift.Error>: HandlerRequestProtocol {
//Performable method
private let performObject: () -> Void
//HandlerRequestProtocol method
private let performHandlerObject: (@escaping (Result<Response, Error>) -> Void) -> Void
//Ensures the Request and Handler Response and Error Type match
public init<Request: HandlerRequestProtocol>(wrappedRequest: Request) where Request.Response == Response, Request.Error == Error{
self.performObject = wrappedRequest.perform
self.performHandlerObject = wrappedRequest.perform
}
/// Implementation to call wrapped method
public func perform() {
self.performObject()
}
/// Implementation that calls the wrapped method
/// - Parameter handler: <#handler description#>
public func perform(then handler: @escaping Handler) {
self.performHandlerObject(handler)
}
}

View File

@ -0,0 +1,23 @@
//
// HandlerRequestProtocol.swift
// MVMCore
//
// Created by Matt Bruce on 3/3/22.
// Copyright © 2022 myverizon. All rights reserved.
//
import Foundation
//Protocol following Request to Response/Error Contract
public protocol HandlerRequestProtocol: Performable {
//Type returned in Success
associatedtype Response
//Type returned in Error
associatedtype Error: Swift.Error
//Handler alias
typealias Handler = (Result<Response, Error>) -> Void
//Method to be implemented by Request
func perform(then handler: @escaping Handler)
}

View File

@ -7,10 +7,19 @@
//
import Foundation
import UIKit
public protocol MVMCoreActionHandlerProtocol: ModelHandlerProtocol {
init()
func handleAction(_ model: ActionModelProtocol, additionalData: [AnyHashable : Any]?, delegateObject: DelegateObject?)
public protocol Performable{
func perform()
}
//Base Signature for a Handler - Model relationship
public protocol MVMCoreHandlerProtocol: ModelHandlerProtocol, Performable {
var baseModel: ModelProtocol { get set }
var additionalData: [AnyHashable: Any]? { get set }
var delegateObject: DelegateObject? { get set }
init (baseModel: ModelProtocol, additionalData: [AnyHashable : Any]?, delegateObject: DelegateObject?) throws
}
public extension MVMCoreActionHandler {
@ -40,7 +49,7 @@ public extension MVMCoreActionHandler {
//esnure the actionModelType
let actionModelType = ModelRegistry.getType(for: actionType, with: ActionModelProtocol.self),
//ensure there is handlerType for the action of MVMCoreActionHandlerProtocol
let actionHandlerType = try? ModelRegistry.getHandlerType(for: actionModelType) as? MVMCoreActionHandlerProtocol.Type
let actionHandlerType = try? ModelRegistry.getHandlerType(for: actionModelType) as? MVMCoreHandlerProtocol.Type
else { return false }
do {
@ -49,11 +58,12 @@ public extension MVMCoreActionHandler {
throw ModelRegistry.Error.decoderOther(message: "Could not decode to ActionModelProtocol")
}
//create the handler since we know it can initialize
let actionHandler = actionHandlerType.init()
//call the handleAction of the handler
actionHandler.handleAction(actionModel, additionalData: additionalData, delegateObject: delegateObject)
//create the handler since we know it can initialize
let actionHandler = try? actionHandlerType.init(baseModel: actionModel,
additionalData: additionalData,
delegateObject: delegateObject)
actionHandler?.perform()
} catch {
//log the error

View File

@ -0,0 +1,61 @@
//
// ModelHandler.swift
// MVMCore
//
// Created by Matt Bruce on 3/3/22.
// Copyright © 2022 myverizon. All rights reserved.
//
import Foundation
/// Abstract Handler class for any type of ModelProtocol
open class ModelHandler<Model: ModelProtocol, Response>: NSObject, MVMCoreHandlerProtocol, HandlerRequestProtocol {
//Success Type from the Result
public typealias Response = Response
//Error Type from the Result
public typealias Error = Swift.Error
//base properties
//baseModel that is tied to this handler
public var baseModel: ModelProtocol
public var additionalData: [AnyHashable: Any]?
public weak var delegateObject: DelegateObject?
//Need to be a property so that you can access
//the handler outside of the "perform(then: handler)
public var handler: Handler!
//typed ModelProtocl this handler is expecting
public var model: Model
//initilization
required public init (baseModel: ModelProtocol,
additionalData: [AnyHashable : Any]?,
delegateObject: DelegateObject?) throws {
//set the properties
self.baseModel = baseModel
self.additionalData = additionalData
self.delegateObject = delegateObject
//ensure the baseModel is of the Model type you are expecting
guard let castedBridgeModel = baseModel as? Model else {
throw ModelRegistry.Error.other(message: "Models Don't match")
}
//set the model
self.model = castedBridgeModel
super.init()
}
//only called in a Void scenario
open func perform() {
fatalError("must override perform")
}
//only called when you want a completion handler.
open func perform(then handler: @escaping Handler) {
self.handler = handler
self.perform()
}
}

View File

@ -9,13 +9,6 @@
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
typedef NS_ENUM(NSInteger, MVMAppContext) {
MVMAppContextNone = 0,
MVMAppContextMF,
MVMAppContextMFPrepay,
MVMAppContextContentTransfer
};
typedef NS_ENUM(NSInteger, NavigationType) {
NavigationTypePush = 0,
NavigationTypeSet,

View File

@ -25,11 +25,15 @@ extension Encodable {
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? JSONDictionary }
}
public func toJSONAny() -> [String: Any]? {
guard let data = try? self.encode() else { return nil }
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
public func toJSONAny() throws -> [String: Any] {
let data = try self.encode()
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
guard let jsonAny = json as? [String: Any] else {
throw JSONError.error(message: "JSON Dictionary not found")
}
return jsonAny
}
public func toJSONString() -> String? {
guard let json = self.toJSON(),
let data = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted),

View File

@ -8,11 +8,54 @@
import Foundation
public typealias JSONArray = [[String: Any]]
public typealias JSONArray = [AnyHashable]
public typealias JSONDictionary = [String: AnyHashable]
public enum JSONError: Error {
case pathNotFound
case data(path: String)
case other(error: Error)
case error(message: String)
}
extension JSONDictionary {
public func toJSONString(options: JSONSerialization.WritingOptions = []) throws -> String {
let data = try JSONSerialization.data(withJSONObject: self, options: options)
guard let string = String(data: data, encoding: .utf8) else {
throw JSONError.error(message: "Failed to convert data to string")
}
return string
}
public func toUrlQueryItems() throws -> [URLQueryItem] {
var queryItems: [URLQueryItem] = []
for (key, value) in self {
var valueString: String
if let value = value as? JSONDictionary {
valueString = try value.toJSONString()
} else if let value = value as? JSONArray {
valueString = try value.toJSONString()
} else {
guard let baseValueString = String(describing: value.base).removingPercentEncoding else {
throw JSONError.error(message: "query item failed: \(key) value \(value.base)")
}
valueString = baseValueString
}
let queryItem = URLQueryItem(name: key, value: valueString)
queryItems.append(queryItem)
}
return queryItems
}
}
extension JSONArray {
public func toJSONString(options: JSONSerialization.WritingOptions = []) throws -> String {
let data = try JSONSerialization.data(withJSONObject: self, options: options)
guard let string = String(data: data, encoding: .utf8) else {
throw JSONError.error(message: "Failed to convert data to string")
}
return string
}
}

View File

@ -13,6 +13,7 @@ public typealias JSONValueDictionary = [String: JSONValue]
public enum JSONValueError: Error {
case encode
case TypeMismatch
}
extension Optional {
@ -69,25 +70,36 @@ public enum JSONValue: Codable, Equatable {
}
}
public var base: Any? {
public var base: Any {
switch self {
case .string(let string): return string
case .int(let int): return int
case .double(let double): return double
case .bool(let bool): return bool
case .object(let object): return object.toJSONAny()
case .array(let array): return ["array": array].toJSONAny()?["array"]
case .null: return nil
case .object(let object): return try! object.toJSONAny()
case .array(let array): return try! ["array": array].toJSONAny()["array"]!
case .null: return NSNull()
}
}
public func value<T>() -> T? { self.base as? T }
public func toString() -> String? { self.base as? String }
public func toDouble() -> Double? { self.base as? Double }
public func toInt() -> Int? { self.base as? Int }
public func toBool() -> Bool? { self.base as? Bool }
public func toArray<T>(of type: T.Type) -> [T]?{ self.base as? [T] }
public func toObject<T>(of type: T.Type) -> T? { self.base as? T }
public func value<T>() throws -> T {
guard let base = self.base as? T else {
throw JSONValueError.TypeMismatch
}
return base
}
private func value<T>(type: T.Type) throws -> T {
let base: T = try value()
return base
}
public func toString() throws -> String { try value(type: String.self) }
public func toDouble() throws -> Double { try value(type: Double.self) }
public func toInt() throws -> Int { try value(type: Int.self) }
public func toBool() throws -> Bool { try value(type: Bool.self) }
public func toArray<T>(of type: T.Type) throws -> [T]{ try value(type: [T].self) }
public func toObject<T>(of type: T.Type) throws -> T { try value(type: T.self) }
}
@ -140,6 +152,13 @@ extension Dictionary where Key == String, Value == Any {
}
}
extension Dictionary where Key == String, Value == AnyHashable {
public func toJSONValue() throws -> [String: JSONValue] {
let data = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return try JSONDecoder().decode([String:JSONValue].self, from: data)
}
}
extension Dictionary where Key == String, Value == JSONValue {
public func toJSONObject() throws -> JSONDictionary {
let encoded = try JSONEncoder().encode(self)

View File

@ -24,10 +24,10 @@ public struct ModelRegistry {
}
public struct Category {
var name: String
var codingKey: String
var instanceTypes: [String: ModelProtocol.Type] = [:]
var handlerTypes: [String: ModelHandlerProtocol.Type] = [:]
public var name: String
public var codingKey: String
public var instanceTypes: [String: ModelProtocol.Type] = [:]
public var handlerTypes: [String: ModelHandlerProtocol.Type] = [:]
}
public static var categories: [String: Category] = [:]

View File

@ -91,7 +91,9 @@
NSString *type = [errorInfo string:KeyType];
if (![ValueTypeSuccess isEqualToString:type]) {
MVMCoreErrorObject *error = [[MVMCoreErrorObject alloc] initWithTitle:[errorInfo stringForKey:KeyErrorHeading] message:[errorInfo stringForKey:KeyUserMessage] messageToLog:[errorInfo stringForKey:KeyMessage] code:errorCode domain:ErrorDomainServer location:location];
NSString *title = [errorInfo string:KeyErrorHeading] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
NSString *message = [errorInfo string:KeyUserMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
MVMCoreErrorObject *error = [[MVMCoreErrorObject alloc] initWithTitle:title message:message messageToLog:[errorInfo string:KeyMessage] code:errorCode domain:ErrorDomainServer location:location];
if ([ValueTypeErrorScreen isEqualToString:type]) {
// If this is a server error screen, there should be no additional alerts... It will be handled by the load handler.