1 /** 2 Copyright: Copyright 2018 Mark Fisher 3 4 License: 5 Permission is hereby granted, free of charge, to any person obtaining a copy of 6 this software and associated documentation files (the "Software"), to deal in 7 the Software without restriction, including without limitation the rights to 8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 of the Software, and to permit persons to whom the Software is furnished to do 10 so, subject to the following conditions: 11 12 The above copyright notice and this permission notice shall be included in all 13 copies or substantial portions of the Software. 14 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 SOFTWARE. 22 **/ 23 module dxx.app.properties; 24 25 private import std.variant; 26 private import std.algorithm; 27 private import std.range; 28 29 //private import hunt.cache; 30 31 private import dxx.util; 32 33 /++ 34 Static methods to lookup application properties at 35 runtime. Firstly, the methods queries the LocalConfig. 36 If the key is not found, then the method consults the 37 local injector. If the key is still not found, then a 38 static variant map comprising default values is consulted. 39 If the key is still not found, the methods return null. 40 41 The lookup methods are nothrow. 42 43 The expand method takes a string and replaces 44 occurences of "{{fullyQualifiedIdentifier}}" 45 with the value obtained by looking up the id. 46 ++/ 47 class Properties { 48 49 nothrow 50 static T lookup(T)(string k,T delegate() _t=null) { 51 /*try { 52 Cache c = resolve!Cache; 53 if(c !is null) { 54 Nullable!T a = c.get!T(k); 55 if(!a.isNull) return cast(T)a; 56 } 57 } catch(Exception e) { 58 }*/ 59 try { 60 auto v = LocalConfig.get(k); 61 if(v != null) return v.get!T; 62 } catch(Exception e) { 63 } 64 try { 65 return getInjectorProperty!T(k); 66 } catch(Exception e) { 67 /*if(k in property_defaults) { 68 try { 69 return property_defaults[k].get!T; 70 } catch(Exception e) { 71 } 72 }*/ 73 } 74 try { 75 if(_t !is null) return _t(); 76 } catch(Exception e) { 77 } 78 static if(typeid(T) is typeid(bool)) { 79 return false; 80 } else { 81 return null; 82 } 83 } 84 85 nothrow 86 static T lookup(T,k : string)(T delegate() _t=null) { 87 return lookup!T(k,_t); 88 } 89 90 nothrow 91 static void assign(T)(string k,T t) { 92 /*try { 93 resolve!Cache.set(k,t); 94 } catch(Exception e) { 95 }*/ 96 } 97 98 nothrow 99 static auto resolve(T)() { 100 try { 101 return resolveInjector!T; 102 } catch(Exception e) { 103 } 104 return null; 105 } 106 107 nothrow static 108 auto idParser(string k) { 109 return lookup!string(k,()=>k); 110 } 111 nothrow static 112 auto expand(string v) { 113 try { 114 return miniInterpreter!(idParser)(v); 115 } catch(Exception e) { 116 } 117 return v; 118 } 119 /*template expand(alias F) { 120 nothrow static 121 auto lookupStringF(k : string)() { 122 auto n = lookup!(string,k); 123 if(n is null) return F(k); 124 else return n; 125 } 126 auto expand(string v) { 127 return miniTemplate!(lookupStringF,v); 128 } 129 }*/ 130 /*static string opDispatch(string s)() { 131 return lookupString(s); 132 }*/ 133 static T opIndex(T)(string s) { 134 return _!T(s); 135 } 136 /++ 137 Shorthand - lookup a key with value type T. 138 ++/ 139 static auto _(T)(string v) { 140 return Properties.lookup!T(v); 141 } 142 /++ 143 Shorthand - lookup a key with value type string. 144 ++/ 145 static auto __(string v) { 146 //return expand(_!string(v)); 147 return _!string(v); 148 } 149 /++ 150 Shorthand - lookup a key with value type string[]. 151 ++/ 152 static auto ___(string v) { 153 //return _!(string[])(v).map!(x=>expand(x)).array; 154 return _!(string[])(v); 155 } 156 157 } 158 159 unittest { 160 import dxx; 161 auto n = Properties.lookup!string(DXXConfig.keys.appName); 162 assert(n == RTConstants.constants.appBaseName); 163 } 164 165 unittest { 166 import dxx; 167 auto n = Properties.expand("{{"~DXXConfig.keys.appName~"}}"); 168 assert(n == RTConstants.constants.appBaseName); 169 } 170 171 unittest { 172 import dxx; 173 auto n = Properties.expand("XX{{"~DXXConfig.keys.appName~"}}XX"); 174 assert(n == "XX"~RTConstants.constants.appBaseName~"XX"); 175 } 176 177 unittest { 178 import dxx; 179 auto n = Properties.expand("XX{{"~DXXConfig.keys.appName~"}}XX{{"~DXXConfig.keys.appName~"}}XX"); 180 assert(n == "XX"~RTConstants.constants.appBaseName~"XX"~RTConstants.constants.appBaseName~"XX"); 181 } 182 183 unittest { 184 import dxx; 185 auto n = Properties.__(DXXConfig.keys.appName); 186 assert(n == RTConstants.constants.appBaseName); 187 }