/
router.ts
119 lines (97 loc) · 3.33 KB
/
router.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { Application } from "./application"
import { Context } from "./context"
import { Definition } from "./definition"
import { Module } from "./module"
import { Multimap } from "../multimap"
import { Scope } from "./scope"
import { ScopeObserver, ScopeObserverDelegate } from "./scope_observer"
export class Router implements ScopeObserverDelegate {
readonly application: Application
private scopeObserver: ScopeObserver
private scopesByIdentifier: Multimap<string, Scope>
private modulesByIdentifier: Map<string, Module>
constructor(application: Application) {
this.application = application
this.scopeObserver = new ScopeObserver(this.element, this.schema, this)
this.scopesByIdentifier = new Multimap()
this.modulesByIdentifier = new Map()
}
get element() {
return this.application.element
}
get schema() {
return this.application.schema
}
get logger() {
return this.application.logger
}
get controllerAttribute(): string {
return this.schema.controllerAttribute
}
get modules() {
return Array.from(this.modulesByIdentifier.values())
}
get contexts() {
return this.modules.reduce((contexts, module) => contexts.concat(module.contexts), [] as Context[])
}
start() {
this.scopeObserver.start()
}
stop() {
this.scopeObserver.stop()
}
loadDefinition(definition: Definition) {
this.unloadIdentifier(definition.identifier)
const module = new Module(this.application, definition)
this.connectModule(module)
const afterLoad = (definition.controllerConstructor as any).afterLoad
if (afterLoad) {
afterLoad(definition.identifier, this.application)
}
}
unloadIdentifier(identifier: string) {
const module = this.modulesByIdentifier.get(identifier)
if (module) {
this.disconnectModule(module)
}
}
getContextForElementAndIdentifier(element: Element, identifier: string) {
const module = this.modulesByIdentifier.get(identifier)
if (module) {
return module.contexts.find((context) => context.element == element)
}
}
// Error handler delegate
handleError(error: Error, message: string, detail: any) {
this.application.handleError(error, message, detail)
}
// Scope observer delegate
createScopeForElementAndIdentifier(element: Element, identifier: string) {
return new Scope(this.schema, element, identifier, this.logger)
}
scopeConnected(scope: Scope) {
this.scopesByIdentifier.add(scope.identifier, scope)
const module = this.modulesByIdentifier.get(scope.identifier)
if (module) {
module.connectContextForScope(scope)
}
}
scopeDisconnected(scope: Scope) {
this.scopesByIdentifier.delete(scope.identifier, scope)
const module = this.modulesByIdentifier.get(scope.identifier)
if (module) {
module.disconnectContextForScope(scope)
}
}
// Modules
private connectModule(module: Module) {
this.modulesByIdentifier.set(module.identifier, module)
const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier)
scopes.forEach((scope) => module.connectContextForScope(scope))
}
private disconnectModule(module: Module) {
this.modulesByIdentifier.delete(module.identifier)
const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier)
scopes.forEach((scope) => module.disconnectContextForScope(scope))
}
}