1 module glued.adhesives.config; 2 3 import std.algorithm; 4 5 public import glued.pathtree; 6 import glued.logging; 7 8 import glued.adhesives.bundles; 9 10 import optional; 11 import properd; 12 13 //todo no tests at all 14 15 struct ConfigEntry { 16 string text; 17 Asset source; 18 } 19 20 //todo Environment seems more natural 21 //todo would this gain anything from making previous value versions visible or reachable? 22 class Config { 23 //todo CreateLogger -> DefineLogger; CreateLogger(name) = DefineLogger + Logger <name> 24 mixin CreateLogger; 25 Logger log; 26 27 this(LogSink sink){ 28 log = Logger(sink); 29 } 30 31 private PathTree!ConfigEntry backend = new ConcretePathTree!ConfigEntry(); 32 33 void feed(Asset asset){ 34 log.debug_.emit("Feeding config from ", asset); 35 auto aa = parseProperties(asset.content); 36 foreach(k; aa.keys()){ 37 backend.put(k, ConfigEntry(aa[k], asset)); 38 } 39 } 40 41 //todo introduce interface ViewClosure(Result), normalize all closures, e.g. ValuesClosure: ViewClosure!string? 42 43 @property 44 PathTreeView!ConfigEntry view(){ 45 return backend; 46 } 47 48 struct ValuesClosure { 49 private Config config; 50 51 string get(string path){ 52 return find(path).front(); 53 } 54 55 Optional!string find(string path){ 56 return config.backend.get(path).map!(x => x.text).toOptional; 57 } 58 59 Optional!string resolve(string path){ 60 return config.backend.resolve(path).map!(x => x.text).toOptional; 61 } 62 } 63 64 @property 65 ValuesClosure values(){ 66 return ValuesClosure(); 67 } 68 69 struct SourcesClosure { 70 private Config config; 71 72 Asset get(string path){ 73 return find(path).front(); 74 } 75 76 Optional!Asset find(string path){ 77 return config.backend.get(path).map!(x => x.source).toOptional; 78 } 79 80 Optional!Asset resolve(string path){ 81 return config.backend.resolve(path).map!(x => x.source).toOptional; 82 } 83 } 84 85 @property 86 SourcesClosure sources(){ 87 return SourcesClosure(); 88 } 89 90 struct EntriesClosure { 91 private Config config; 92 93 ConfigEntry get(string path){ 94 return find(path).front(); 95 } 96 97 Optional!ConfigEntry find(string path){ 98 return config.backend.get(path); 99 } 100 101 Optional!ConfigEntry resolve(string path){ 102 return config.backend.resolve(path); 103 } 104 } 105 106 @property 107 EntriesClosure entries(){ 108 return EntriesClosure(); 109 } 110 }