Slather logo

Coverage for "CompleteFactoryChainAssembly.swift" : 94.92%

(56 of 59 relevant lines covered)

RouteComposer/Classes/Assemblies/Helpers/CompleteFactoryChainAssembly.swift

1
//
2
// RouteComposer
3
// CompleteFactoryChainAssembly.swift
4
// https://github.com/ekazaev/route-composer
5
//
6
// Created by Eugene Kazaev in 2018-2022.
7
// Distributed under the MIT license.
8
//
9
// Become a sponsor:
10
// https://github.com/sponsors/ekazaev
11
//
12
13
import Foundation
14
import UIKit
15
16
/// Builds the chain of assemblies to fulfill the `ContainerFactory`.
17
public final class CompleteFactoryChainAssembly<FC: ContainerFactory, ChildVC: UIViewController, ChildContext> {
18
19
    // MARK: Properties
20
21
    private var factory: FC
22
23
    private let childFactories: [PostponedIntegrationFactory]
24
25
    private let previousChildFactory: PostponedIntegrationFactory?
26
27
    private var integratedChildFactories: [PostponedIntegrationFactory] {
23x
28
        var childFactories = childFactories
23x
29
        if let previousChildFactory {
23x
30
            childFactories.append(previousChildFactory)
17x
31
        }
23x
32
        return childFactories
23x
33
    }
23x
34
35
    // MARK: Methods
36
37
    init(factory: FC, childFactories: [PostponedIntegrationFactory], previousChildFactory: PostponedIntegrationFactory?) {
30x
38
        self.factory = factory
30x
39
        self.childFactories = childFactories
30x
40
        self.previousChildFactory = previousChildFactory
30x
41
    }
30x
42
43
    /// Adds a `Factory` that is going to be used as a child
44
    ///
45
    /// - Parameters:
46
    ///   - childFactory: The instance of `Factory`.
47
    ///   - action: The instance of `Factory` to be used to integrate the view controller produced by the factory.
48
    public final func with<ChildFC: Factory, A: ContainerAction, T: ContextTransformer>(_ childFactory: ChildFC, using action: A, adapting transformer: T) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>
49
        where
50
        T.TargetContext == ChildFC.Context, T.SourceContext == FC.Context, A.ViewController == FC.ViewController {
4x
51
        guard let factoryBox = FactoryBox(childFactory, action: ContainerActionBox(action)) else {
4x
52
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>(factory: factory, childFactories: integratedChildFactories, previousChildFactory: nil)
1x
53
        }
3x
54
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>(factory: factory,
3x
55
                                                                                         childFactories: integratedChildFactories,
3x
56
                                                                                         previousChildFactory: PostponedIntegrationFactory(for: factoryBox, transformer: ContextTransformerBox(transformer)))
3x
57
    }
4x
58
59
    /// Adds a `ContainerFactory` that is going to be used as a child
60
    ///
61
    /// - Parameters:
62
    ///   - childContainer: The instance of `ContainerFactory`.
63
    ///   - action: The instance of `ContainerFactory` to be used to integrate the view controller produced by the factory.
64
    public final func with<ChildFC: ContainerFactory, A: ContainerAction, T: ContextTransformer>(_ childContainer: ChildFC, using action: A, adapting transformer: T) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>
65
        where
66
        T.TargetContext == ChildFC.Context, T.SourceContext == FC.Context, A.ViewController == FC.ViewController {
7x
67
        guard let factoryBox = ContainerFactoryBox(childContainer, action: ContainerActionBox(action)) else {
7x
68
            return CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>(factory: factory, childFactories: integratedChildFactories, previousChildFactory: nil)
3x
69
        }
4x
70
4x
71
        return CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>(factory: factory,
4x
72
                                                                                         childFactories: integratedChildFactories,
4x
73
                                                                                         previousChildFactory: PostponedIntegrationFactory(for: factoryBox, transformer: ContextTransformerBox(transformer)))
4x
74
    }
7x
75
76
    /// Adds a `Factory` as the last view controller in the stack.
77
    ///
78
    /// - Parameters:
79
    ///   - childFactory: The instance of `Factory`.
80
    ///   - transformer: The instance of `ContextTransformer` to use to adapt parent `ContainerFactory` `Context`.
81
    public final func with<ChildFC: Factory, T: ContextTransformer>(_ childFactory: ChildFC, adapting transformer: T) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context> where T.TargetContext == ChildFC.Context, T.SourceContext == FC.Context {
1x
82
        return with(childFactory, using: CompleteFactoryAssembly<FC>.SimpleAddAction<FC>(), adapting: transformer)
1x
83
    }
1x
84
85
    /// Adds a `ContainerFactory` as the last view controller in the stack.
86
    ///
87
    /// - Parameters:
88
    ///   - childContainer: The instance of `ContainerFactory`.
89
    ///   - transformer: The instance of `ContextTransformer` to use to adapt parent `ContainerFactory` `Context`.
90
    public final func with<ChildFC: ContainerFactory, T: ContextTransformer>(_ childContainer: ChildFC, adapting transformer: T) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context> where T.TargetContext == ChildFC.Context, T.SourceContext == FC.Context {
!
91
        return with(childContainer, using: CompleteFactoryAssembly<FC>.SimpleAddAction<FC>(), adapting: transformer)
!
92
    }
!
93
94
    /// Adds a `Factory` that is going to be used as a child
95
    ///
96
    /// - Parameters:
97
    ///   - childFactory: The instance of `Factory`.
98
    ///   - action: The instance of `Factory` to be used to integrate the view controller produced by the factory.
99
    public final func with<ChildFC: Factory, A: ContainerAction>(_ childFactory: ChildFC, using action: A) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>
100
        where
101
        ChildFC.Context == FC.Context, A.ViewController == FC.ViewController {
2x
102
        return with(childFactory, using: action, adapting: NilContextTransformer())
2x
103
    }
2x
104
105
    /// Adds a `ContainerFactory` that is going to be used as a child
106
    ///
107
    /// - Parameters:
108
    ///   - childContainer: The instance of `ContainerFactory`.
109
    ///   - action: The instance of `ContainerFactory` to be used to integrate the view controller produced by the factory.
110
    public final func with<ChildFC: ContainerFactory, A: ContainerAction>(_ childContainer: ChildFC, using action: A) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context>
111
        where
112
        ChildFC.Context == FC.Context, A.ViewController == FC.ViewController {
6x
113
        return with(childContainer, using: action, adapting: NilContextTransformer())
6x
114
    }
6x
115
116
    /// Adds a `Factory` as the last view controller in the stack.
117
    ///
118
    /// - Parameters:
119
    ///   - childFactory: The instance of `Factory`.
120
    public final func with<ChildFC: Factory>(_ childFactory: ChildFC) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context> where ChildFC.Context == FC.Context {
1x
121
        return with(childFactory, using: CompleteFactoryAssembly<FC>.SimpleAddAction<FC>())
1x
122
    }
1x
123
124
    /// Adds a `ContainerFactory` as the last view controller in the stack.
125
    ///
126
    /// - Parameters:
127
    ///   - childContainer: The instance of `ContainerFactory`.
128
    public final func with<ChildFC: ContainerFactory>(_ childContainer: ChildFC) -> CompleteFactoryChainAssembly<FC, ChildFC.ViewController, ChildFC.Context> where ChildFC.Context == FC.Context {
6x
129
        return with(childContainer, using: CompleteFactoryAssembly<FC>.SimpleAddAction<FC>())
6x
130
    }
6x
131
132
    /// Applies a `ContextTask` to the child factory after its `UIViewController` been built.
133
    ///
134
    /// - Parameters:
135
    ///   - contextTask: The instance of `ContextTask`.
136
    public final func adding<CT: ContextTask>(_ contextTask: CT) -> CompleteFactoryChainAssembly<FC, ChildVC, ChildContext> where CT.ViewController == ChildVC, CT.Context == ChildContext {
7x
137
        guard var previousChildFactory else {
7x
138
            return CompleteFactoryChainAssembly<FC, ChildVC, ChildContext>(factory: factory, childFactories: childFactories, previousChildFactory: nil)
1x
139
        }
6x
140
        previousChildFactory.add(ContextTaskBox(contextTask))
6x
141
        return CompleteFactoryChainAssembly<FC, ChildVC, ChildContext>(factory: factory,
6x
142
                                                                       childFactories: childFactories,
6x
143
                                                                       previousChildFactory: previousChildFactory)
6x
144
    }
7x
145
146
    /// Assembles all the children factories provided and returns a `ContainerFactory` instance.
147
    ///
148
    /// - Returns: The `CompleteFactory` with child factories provided.
149
    public final func assemble() -> CompleteFactory<FC> {
12x
150
        CompleteFactory<FC>(factory: factory, childFactories: integratedChildFactories)
12x
151
    }
12x
152
153
}