1 public final class ModuleRegistry: Sequence {
2   public typealias Element = ModuleHolder
3 
4   private weak var appContext: AppContext?
5 
6   private var registry: [String: ModuleHolder] = [:]
7 
8   init(appContext: AppContext) {
9     self.appContext = appContext
10   }
11 
12   /**
13    Registers an instance of module holder.
14    */
registernull15   internal func register(holder: ModuleHolder) {
16     log.info("Registering module '\(holder.name)'")
17     registry[holder.name] = holder
18   }
19 
20   /**
21    Registers an instance of the module.
22    */
registernull23   public func register(module: AnyModule) {
24     guard let appContext else {
25       log.error("Unable to register a module '\(module)', the app context is unavailable")
26       return
27     }
28     register(holder: ModuleHolder(appContext: appContext, module: module))
29   }
30 
31   /**
32    Registers a module by its type.
33    */
registernull34   public func register(moduleType: AnyModule.Type) {
35     guard let appContext else {
36       log.error("Unable to register a module '\(moduleType)', the app context is unavailable")
37       return
38     }
39     register(module: moduleType.init(appContext: appContext))
40   }
41 
42   /**
43    Registers modules exported by given modules provider.
44    */
registernull45   public func register(fromProvider provider: ModulesProviderProtocol) {
46     provider.getModuleClasses().forEach { moduleType in
47       register(moduleType: moduleType)
48     }
49   }
50 
51   /**
52    Unregisters given module from the registry.
53    */
unregisternull54   public func unregister(module: AnyModule) {
55     if let index = registry.firstIndex(where: { $1.module === module }) {
56       registry.remove(at: index)
57     }
58   }
59 
unregisternull60   public func unregister(moduleName: String) {
61     if registry[moduleName] != nil {
62       log.info("Unregistering module '\(moduleName)'")
63       registry[moduleName] = nil
64     }
65   }
66 
hasnull67   public func has(moduleWithName moduleName: String) -> Bool {
68     return registry[moduleName] != nil
69   }
70 
getnull71   public func get(moduleHolderForName moduleName: String) -> ModuleHolder? {
72     return registry[moduleName]
73   }
74 
getnull75   public func get(moduleWithName moduleName: String) -> AnyModule? {
76     return registry[moduleName]?.module
77   }
78 
getModuleNamesnull79   public func getModuleNames() -> [String] {
80     return Array(registry.keys)
81   }
82 
makeIteratornull83   public func makeIterator() -> IndexingIterator<[ModuleHolder]> {
84     return registry.map({ $1 }).makeIterator()
85   }
86 
postnull87   internal func post(event: EventName) {
88     log.info("Posting '\(event)' event to registered modules")
89     forEach { holder in
90       holder.post(event: event)
91     }
92   }
93 
post<PayloadType>null94   internal func post<PayloadType>(event: EventName, payload: PayloadType? = nil) {
95     log.info("Posting '\(event)' event to registered modules")
96     forEach { holder in
97       holder.post(event: event, payload: payload)
98     }
99   }
100 }
101