1 /**
2 Proof of concept of injecting environment and command line arguments.
3 
4 License:
5 	Boost Software License - Version 1.0 - August 17th, 2003
6 
7 	Permission is hereby granted, free of charge, to any person or organization
8 	obtaining a copy of the software and accompanying documentation covered by
9 	this license (the "Software") to use, reproduce, display, distribute,
10 	execute, and transmit the Software, and to prepare derivative works of the
11 	Software, and to permit third-parties to whom the Software is furnished to
12 	do so, all subject to the following:
13 	
14 	The copyright notices in the Software and this entire statement, including
15 	the above license grant, this restriction and the following disclaimer,
16 	must be included in all copies of the Software, in whole or in part, and
17 	all derivative works of the Software, unless such copies or derivative
18 	works are solely in the form of machine-executable object code generated by
19 	a source language processor.
20 	
21 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 	FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24 	SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25 	FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26 	ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 	DEALINGS IN THE SOFTWARE.
28 
29 Authors:
30 	aermicioi
31 **/
32 module aermicioi.aedi.configurer.register.environment;
33 
34 import aermicioi.aedi.configurer.register.register;
35 import aermicioi.aedi.storage.storage;
36 import aermicioi.aedi.storage.locator;
37 import aermicioi.aedi.exception;
38 
39 import std.process;
40 
41 auto env(T)(Storage!(Object, string) storage, string variable, T default_) {
42     import std.conv;
43     string stringValueRepresentation = environment.get(variable);
44     
45     return storage.register(stringValueRepresentation !is null ? stringValueRepresentation.to!T : default_, variable);
46 }
47 
48 auto env(T)(Storage!(Object, string) storage, string variable) {
49     return storage.env!T(variable, T.init);
50 }
51 
52 auto envs(T)(Storage!(Object, string) storage)
53     if (is(T == struct)) {
54     
55     return storage.envs(T.init);
56 }
57     
58 auto envs(T)(Storage!(Object, string) storage, T init)
59     if (is(T == struct)) {
60     
61     foreach (member; publicFields!T) {
62         import std.conv;
63         import std.process;
64         import std.array;
65         
66         string variable = environment.get(member.replace("__", "."));
67         
68         if (variable !is null) {
69             storage.register(
70                 variable.to!(typeof(getMember!(T, member))),
71                 member.replace("__", ".")
72             );
73         } else {
74             storage.register(
75                 __traits(getMember, init, member),
76                 member.replace("__", ".")
77             );
78         }
79     }
80     
81     return storage;
82 }
83 
84 auto args(T)(Storage!(Object, string) storage, string[] args, auto ref T container)
85     if (is(T == struct)) {
86     
87     import std.getopt;
88     import std.array;
89             
90     string generate(T)() {
91         import std.algorithm;
92         
93         string statement;
94         
95         string[] members = [ publicFields!T ];
96         sort(members);
97         
98         string[] getWithCommonPrefix(string[] args) {
99             if (args.length > 0) {
100                 string[] res;
101                 res ~= args[0];
102                 
103                 foreach (arg; args[1 .. $]) {
104                     if (commonPrefix(res[$ - 1], arg).length > 0) {
105                         res ~= arg;
106                     }
107                 }
108                 
109                 return res;
110             }
111             
112             return null;
113         }
114         while (!members.empty) {
115             string[] common = getWithCommonPrefix(members);
116             if (common.length == 1) {
117                 statement ~= "\"" ~ common[0][0] ~ "|" ~ common[0].replace("__", ".") ~ "\", &container." ~ common[0] ~ ",";
118             } else {
119             
120                 foreach (element; common)  {
121                     statement ~= '"' ~ element.replace("__", ".") ~ "\", &container." ~ element ~ ",";
122                 }
123             }
124             
125             members = members[common.length .. $];
126         }
127         
128         return statement;
129     }
130     mixin ("auto options = getopt(args, config.passThrough," ~ generate!T ~ ");");
131     
132     foreach (member; publicFields!T) {
133         storage.register(
134             __traits(getMember, container, member),
135             member.replace("__", ".")
136         );
137     }
138     
139     return storage;
140 }
141     
142 auto args(T)(Storage!(Object, string) storage, string[] args) {
143     storage.args(args, T.init);
144 }
145     
146 auto envs(T, R : Locator!())(R locator, string storageId = "parameters")
147     if (!is(R : Storage!(Object, string)) && is(T == struct)) {
148     import std.algorithm;
149     
150     auto storage = locator.locate!(Storage!(Object, string))(storageId);
151     
152     storage.envs!T;
153     return locator;
154 }
155     
156 auto args(T, R : Locator!())(R locator, string[] args, T initial, string storageId = "parameters")
157     if (!is(R : Storage!(Object, string)) && is(T == struct)) {
158     import std.algorithm;
159     
160     auto storage = locator.locate!(Storage!(Object, string))(storageId);
161     
162     storage.args(args, initial);
163     return locator;
164 }
165     
166 auto args(T, R : Locator!())(R locator, string[] args, string storageId = "parameters")
167     if (!is(R : Storage!(Object, string))) {
168     
169     locator.args!T(args, T.init, storageId);
170     return locator;
171 }
172 
173 private {
174     import aermicioi.util.traits;
175     import std.meta;
176     
177     template publicFields(T) {
178          alias publicFieldsImpl = chain!(
179             partialPrefixed!(
180                 Filter,
181                 partialPrefixed!(
182                     isField,
183                     T
184                 )
185             ),
186             partialPrefixed!(
187                 Filter,
188                 partialSuffixed!(
189                     partialPrefixed!(
190                         isProtection,
191                         T
192                     ),
193                     "public"
194                 )
195             ),
196             allMembers
197         );
198          
199          alias publicFields = publicFieldsImpl!T;
200     }
201 }