Skip to content

Commit 759a38c

Browse files
Expand core service architecture to make way for better module management
1 parent c00e3a0 commit 759a38c

21 files changed

+539
-57
lines changed

Lib/Shared/AppLib/App/AppBase.ahk

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ class AppBase {
117117

118118
services := (config.Has("services") && config["services"]) ? config["services"] : Map()
119119

120+
if (!services.Has("App") || !services["App"]) {
121+
services["App"] := this
122+
}
120123

121124
if (!services.Has("Shell") || !services["Shell"]) {
122125
shell := ""
@@ -155,7 +158,12 @@ class AppBase {
155158
}
156159

157160
this.Services := ServiceContainer(services)
158-
this.Services.Set("ModuleManager", ModuleManager(this).LoadModules(config))
161+
162+
moduleConfigPath := this.dataDir . "\Modules.json"
163+
defaultModules := this.GetDefaultModules(config)
164+
moduleDirs := config.Has("moduleDirs") ? config["moduleDirs"] : []
165+
this.Services.Set("ModuleManager", ModuleManager(this, moduleConfigPath, moduleDirs, defaultModules))
166+
159167
this.errorCallback := ObjBindMethod(this, "OnException")
160168
OnError(this.errorCallback)
161169
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class ClassFileComponentDiscoverer extends FileComponentDiscovererBase {
2+
DiscoverComponent(fileName, filePath) {
3+
componentName := this.GetComponentName(fileName, filePath)
4+
5+
if (!this.results.Has(componentName)) {
6+
this.results[componentName] := this.GetComponentClass(fileName, filePath)
7+
}
8+
}
9+
10+
GetComponentName(fileName, filePath) {
11+
parts := StrSplit(fileName, ".", " \t", 2)
12+
return parts[1]
13+
}
14+
15+
GetComponentClassName(fileName, filePath) {
16+
return this.GetComponent(fileName, filePath)
17+
}
18+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
class ComponentDiscovererBase extends BulkOperationBase {
2+
componentName := "component"
3+
componentNamePlural := "components"
4+
useProgress := false
5+
shouldNotify := false
6+
componentManager := ""
7+
8+
__New(componentManager, owner := "") {
9+
this.componentManager := componentManager
10+
super.__New(componentManager.app, owner)
11+
}
12+
13+
RunAction() {
14+
this.StartItem(1, "Discovering " . this.componentNamePlural . "...")
15+
this.results := this.CreateComponentInfo()
16+
this.DiscoverComponents()
17+
this.FinishItem(1, "Finished discovering " . this.componentNamePlural . ".")
18+
}
19+
20+
CreateComponentInfo() {
21+
componentInfo := this.componentManager.defaultComponentInfo ? this.componentManager.defaultComponentInfo : Map()
22+
return componentInfo.Clone()
23+
}
24+
25+
DiscoverComponents() {
26+
if (this.componentManager.discoverEvent) {
27+
event := ComponentInfoEvent(this.componentManager.discoverEvent, this.results)
28+
this.app.Service("EventManager").DispatchEvent(this.componentManager.discoverEvent, event)
29+
this.results := event.ComponentInfo
30+
}
31+
32+
if (this.componentManager.discoverAlterEvent) {
33+
event := ComponentInfoEvent(this.componentManager.discoverAlterEvent, this.results)
34+
this.app.Service("EventManager").DispatchEvent(this.componentManager.discoverAlterEvent, event)
35+
this.results := event.ComponentInfo
36+
}
37+
}
38+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class ConfigComponentDiscoverer extends ComponentDiscovererBase {
2+
configObj := ""
3+
parentKey := ""
4+
5+
__New(componentManager, configObj, parentKey := "", owner := "") {
6+
this.configObj := configObj
7+
this.parentKey := parentKey
8+
9+
super.__New(componentManager, owner)
10+
}
11+
12+
DiscoverComponents() {
13+
parentKey := this.parentKey
14+
15+
for componentName, componentConfig in this.configObj.%parentKey% {
16+
this.DiscoverComponent(componentName, componentConfig)
17+
}
18+
19+
super.DiscoverComponents()
20+
}
21+
22+
DiscoverComponent(componentName, componentConfig) {
23+
this.results[componentName] := componentConfig
24+
}
25+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
class FileComponentDiscovererBase extends ComponentDiscovererBase {
2+
searchDirs := ""
3+
filePattern := ""
4+
5+
__New(componentManager, searchDirs, filePattern := "", owner := "") {
6+
if (Type(searchDirs) != "Array") {
7+
searchDirs := [searchDirs]
8+
}
9+
10+
if (!filePattern) {
11+
filePattern := "*"
12+
}
13+
14+
this.searchDirs := searchDirs
15+
this.filePattern := filePattern
16+
17+
super.__New(componentManager, owner)
18+
}
19+
20+
DiscoverComponents() {
21+
for index, dir in this.searchDirs {
22+
Loop Files dir . "\" . this.filePattern, "R" {
23+
this.DiscoverComponent(A_LoopFileName, A_LoopFileFullPath)
24+
}
25+
}
26+
27+
super.DiscoverComponents()
28+
}
29+
30+
DiscoverComponent(fileName, filePath) {
31+
throw MethodNotImplementedException("FileComponentDiscovererBase", "DiscoverComponent")
32+
}
33+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
class ClassComponentLoader extends ComponentLoaderBase {
2+
defaultClassConfig := Map()
3+
4+
LoadComponent(key, componentInfo) {
5+
if (Type(componentInfo) == "String") {
6+
componentInfo := Map("class", componentInfo)
7+
}
8+
9+
className := this.GetComponentClass(key, componentInfo)
10+
componentConfig := this.GetComponentConfig(key, componentInfo)
11+
12+
isEnabled := true
13+
14+
if (componentConfig && componentConfig.Has("enabled")) {
15+
isEnabled := componentConfig["enabled"]
16+
}
17+
18+
if (isEnabled) {
19+
if (className && IsObject(%className%)) {
20+
if (HasMethod(%className%, "Create")) {
21+
this.results[key] := %className%.Create(this.app.Services, componentConfig)
22+
} else {
23+
this.results[key] := %className%(this.app, componentConfig)
24+
}
25+
}
26+
27+
super.LoadComponent(key, componentInfo)
28+
29+
if (!this.results.Has(key)) {
30+
throw AppException("Cannot load component " . key)
31+
}
32+
}
33+
}
34+
35+
GetComponentClass(key, componentInfo) {
36+
return componentInfo.Has("class") ? componentInfo["class"] : ""
37+
}
38+
39+
GetComponentConfig(key, componentInfo) {
40+
componentConfig := this.defaultClassConfig
41+
42+
if (componentInfo.Has("config")) {
43+
for key, val in componentInfo["config"] {
44+
componentConfig[key] := val
45+
}
46+
}
47+
48+
managerConfig := this.componentManager.GetComponentConfig(key, componentInfo)
49+
50+
if (managerConfig) {
51+
for key, val in managerConfig {
52+
componentConfig[key] := val
53+
}
54+
}
55+
56+
return componentConfig
57+
}
58+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
class ComponentLoaderBase extends BulkOperationBase {
2+
componentInfo := ""
3+
useProgress := false
4+
shouldNotify := false
5+
componentManager := ""
6+
7+
__New(componentManager, componentInfo, owner := "") {
8+
this.componentManager := componentManager
9+
this.componentInfo := componentInfo
10+
11+
super.__New(componentManager.app, owner)
12+
}
13+
14+
RunAction() {
15+
componentInfoType := Type(this.componentInfo)
16+
17+
if (this.componentManager.defaultComponents) {
18+
for defaultKey, defaultComponent in this.componentManager.defaultComponents {
19+
this.results[defaultKey] := defaultComponent
20+
}
21+
}
22+
23+
if (this.useProgress) {
24+
totalCount := 1
25+
26+
if (componentInfoType == "Map") {
27+
totalCount := this.componentInfo.Count
28+
} else if (componentInfoType == "Array") {
29+
totalCount := this.componentInfo.Length
30+
}
31+
32+
this.progress.SetRange(0, totalCount)
33+
}
34+
35+
if (componentInfoType == "Map") {
36+
index := 1
37+
38+
for key, info in this.componentInfo {
39+
this.StartItem(index, "Loading " . key . "...")
40+
this.LoadComponent(key, info)
41+
this.FinishItem(index, "Finished loading " . key)
42+
index++
43+
}
44+
} else if (componentInfoType == "Array") {
45+
for index, info in this.componentInfo {
46+
this.StartItem(index, "Loading component " . index . "...")
47+
this.LoadComponent(index, info)
48+
this.FinishItem(index, "Finished loading component " . index)
49+
}
50+
} else {
51+
this.StartItem(1, "Loading component...")
52+
this.LoadComponent(1, this.componentInfo)
53+
this.FinishItem(1, "Finished loading component")
54+
}
55+
}
56+
57+
/*
58+
This method should be called AFTER any overridden method loads the component.
59+
60+
It calls a load event if the component has not been loaded already.
61+
Then it calls an alter event allowing the component to be modified or replaced.
62+
*/
63+
LoadComponent(key, componentInfo) {
64+
if (this.componentManager.loadEvent && (!this.results.Has(key) || !this.results[key])) {
65+
event := LoadComponentEvent(this.componentManager.loadEvent, key, componentInfo)
66+
this.app.Service("EventManager").DispatchEvent(this.componentManager.loadEvent, event)
67+
68+
if (event.Component) {
69+
this.results[key] := event.Component
70+
}
71+
}
72+
73+
if (this.componentManager.loadAlterEvent) {
74+
event := LoadComponentEvent(this.componentManager.loadAlterEvent, key, componentInfo)
75+
76+
if (this.results.Has(key)) {
77+
event.Component := this.results[key]
78+
}
79+
80+
this.app.Service("EventManager").DispatchEvent(this.componentManager.loadAlterEvent, event)
81+
82+
this.results[key] := event.Component
83+
}
84+
}
85+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class SimpleComponentLoader extends ComponentLoaderBase {
2+
LoadComponent(key, componentInfo) {
3+
isEnabled := true
4+
5+
if (componentInfo && Type(componentInfo) == "Map" && componentInfo.Has("enabled")) {
6+
isEnabled := componentInfo["enabled"]
7+
}
8+
9+
if (isEnabled) {
10+
this.results[key] := componentInfo
11+
super.LoadComponent(key, componentInfo)
12+
}
13+
}
14+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class ModuleConfig extends JsonConfig {
2+
primaryConfigKey := "Modules"
3+
4+
Modules {
5+
get => this.config[this.primaryConfigKey]
6+
set => this.config[this.primaryConfigKey] := value
7+
}
8+
}

Lib/Shared/AppLib/Container/ContainerBase.ahk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ContainerBase {
1717
if (this.Items.Has(key)) {
1818
result := this.Items[key]
1919

20-
if (IsString(result)) {
20+
if (Type(result) == "String") {
2121
result := this.DereferenceValue(result)
2222
}
2323
}

0 commit comments

Comments
 (0)