1 /*
2  * Hunt - A data validation for DLang based on hunt library.
3  *
4  * Copyright (C) 2015-2019, HuntLabs
5  *
6  * Website: https://www.huntlabs.net
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 module hunt.validation.DeclDef;
12 
13 import std.traits;
14 
15 import hunt.validation.validators.AssertFalseValidator;
16 import hunt.validation.validators.AssertTrueValidator;
17 import hunt.validation.validators.EmailValidator;
18 import hunt.validation.validators.LengthValidator;
19 import hunt.validation.validators.MaxValidator;
20 import hunt.validation.validators.MinValidator;
21 import hunt.validation.validators.NotBlankValidator;
22 import hunt.validation.validators.NotEmptyValidator;
23 import hunt.validation.validators.PatternValidator;
24 import hunt.validation.validators.SizeValidator;
25 import hunt.validation.constraints.AssertFalse;
26 import hunt.validation.constraints.AssertTrue;
27 import hunt.validation.constraints.Email;
28 import hunt.validation.constraints.Max;
29 import hunt.validation.constraints.Min;
30 import hunt.validation.constraints.NotBlank;
31 import hunt.validation.constraints.NotEmpty;
32 import hunt.validation.constraints.Pattern;
33 import hunt.validation.constraints.Size;
34 import hunt.validation.constraints.Length;
35 import hunt.validation.constraints.Range;
36 
37 
38 mixin template MakeValid()
39 {
40     mixin(makeValidInit);
41     mixin(makeDoValid!(typeof(this)));
42 }
43 
44 string makeValidInit()
45 {
46     string str = `
47         private ConstraintValidatorContext _context;
48         public ConstraintValidatorContext valid(){ return doValid() ;}
49     `;
50 
51     return str;
52 }
53 
54 bool hasAnnotation(T, A)() {
55     bool res = false;
56     foreach(a; __traits(getAttributes, T)) {
57         static if (is(typeof(a) == A) || a.stringof == A.stringof) {
58             res = true;
59             break;
60         }
61     }
62     return res;
63 }
64 
65 string makeDoValid(T)()
66 {
67     string str = `
68         private ConstraintValidatorContext doValid()
69         {
70             if(_context is null)
71                 _context = new DefaultConstraintValidatorContext();
72             return doValid(_context);
73         }
74 
75         public ConstraintValidatorContext doValid(ConstraintValidatorContext context)
76         {`;
77             foreach(memberName; __traits(derivedMembers, T)) {
78                 static if (__traits(getProtection, __traits(getMember, T, memberName)) == "public") {
79                     alias memType = typeof(__traits(getMember, T ,memberName));
80                     static if (!isFunction!(memType)) {
81                         static if(hasUDA!(__traits(getMember, T ,memberName), Max))
82                         {
83                 str    ~=`        {
84                                 MaxValidator validator = new MaxValidator();`;
85                                 static if((getUDAs!(__traits(getMember, T ,memberName), Max)[0]).stringof == Max.stringof)
86                                 {
87                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Max)[0]).stringof~ `());`; 
88                                 }
89                                 else
90                                 {
91                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Max)[0]).stringof~ `);`;
92                                 }
93                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
94                                 validator.isValid(this.` ~ memberName ~ `,context);
95                             }`;
96                         }
97                         static if(hasUDA!(__traits(getMember, T ,memberName), Min))
98                         {
99                 str    ~=`        {
100                                 MinValidator validator = new MinValidator();`;
101                                 static if((getUDAs!(__traits(getMember, T ,memberName), Min)[0]).stringof == Min.stringof)
102                                 {
103                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Min)[0]).stringof~ `());`; 
104                                 }
105                                 else
106                                 {
107                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Min)[0]).stringof~ `);`;
108                                 }
109                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
110                                 validator.isValid(this.` ~ memberName ~ `,context);
111                             }`;
112                         }
113                         static if(hasUDA!(__traits(getMember, T ,memberName), AssertFalse))
114                         {
115                 str    ~=`        {
116                                 AssertFalseValidator validator = new AssertFalseValidator();`;
117                                 static if((getUDAs!(__traits(getMember, T ,memberName), AssertFalse)[0]).stringof == AssertFalse.stringof)
118                                 {
119                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), AssertFalse)[0]).stringof~ `());`; 
120                                 }
121                                 else
122                                 {
123                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), AssertFalse)[0]).stringof~ `);`;
124                                 }
125                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
126                                 validator.isValid(this.` ~ memberName ~ `,context);
127                             }`;
128                         }
129                         static if(hasUDA!(__traits(getMember, T ,memberName), AssertTrue))
130                         {
131                 str    ~=`        {
132                                 AssertTrueValidator validator = new AssertTrueValidator();`;
133                                 static if((getUDAs!(__traits(getMember, T ,memberName), AssertTrue)[0]).stringof == AssertTrue.stringof)
134                                 {
135                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), AssertTrue)[0]).stringof~ `());`; 
136                                 }
137                                 else
138                                 {
139                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), AssertTrue)[0]).stringof~ `);`;
140                                 }
141                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
142                                 validator.isValid(this.` ~ memberName ~ `,context);
143                             }`;
144                         }
145                         static if(hasUDA!(__traits(getMember, T ,memberName), Email))
146                         {
147                 str    ~=`        {
148                                 EmailValidator validator = new EmailValidator();`;
149                                 static if((getUDAs!(__traits(getMember, T ,memberName), Email)[0]).stringof == Email.stringof)
150                                 {
151                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Email)[0]).stringof~ `());`; 
152                                 }
153                                 else
154                                 {
155                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Email)[0]).stringof~ `);`;
156                                 }
157                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
158                                 validator.isValid(this.` ~ memberName ~ `,context);
159                             }`;
160                         }
161                         static if(hasUDA!(__traits(getMember, T ,memberName), Length))
162                         {
163                 str    ~=`        {
164                                 LengthValidator validator = new LengthValidator();`;
165                                 static if((getUDAs!(__traits(getMember, T ,memberName), Length)[0]).stringof == Length.stringof)
166                                 {
167                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Length)[0]).stringof~ `());`; 
168                                 }
169                                 else
170                                 {
171                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Length)[0]).stringof~ `);`;
172                                 }
173                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
174                                 validator.isValid(this.` ~ memberName ~ `,context);
175                             }`;
176                         }
177                         static if(hasUDA!(__traits(getMember, T ,memberName), NotBlank))
178                         {
179                 str    ~=`        {
180                                 NotBlankValidator validator = new NotBlankValidator();`;
181                                 static if((getUDAs!(__traits(getMember, T ,memberName), NotBlank)[0]).stringof == NotBlank.stringof)
182                                 {
183                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), NotBlank)[0]).stringof~ `());`; 
184                                 }
185                                 else
186                                 {
187                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), NotBlank)[0]).stringof~ `);`;
188                                 }
189                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
190                                 validator.isValid(this.` ~ memberName ~ `,context);
191                             }`;
192                         }
193                         static if(hasUDA!(__traits(getMember, T ,memberName), NotEmpty))
194                         {
195                 str    ~=`        {
196                                 auto validator = new NotEmptyValidator!`~memType.stringof~`();`;
197                                 static if((getUDAs!(__traits(getMember, T ,memberName), NotEmpty)[0]).stringof == NotEmpty.stringof)
198                                 {
199                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), NotEmpty)[0]).stringof~ `());`; 
200                                 }
201                                 else
202                                 {
203                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), NotEmpty)[0]).stringof~ `);`;
204                                 }
205                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
206                                 validator.isValid(this.` ~ memberName ~ `,context);
207                             }`;
208                         }
209                         static if(hasUDA!(__traits(getMember, T ,memberName), Pattern))
210                         {
211                 str    ~=`        {
212                                 PatternValidator validator = new PatternValidator();`;
213                                 static if((getUDAs!(__traits(getMember, T ,memberName), Pattern)[0]).stringof == Pattern.stringof)
214                                 {
215                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Pattern)[0]).stringof~ `());`; 
216                                 }
217                                 else
218                                 {
219                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Pattern)[0]).stringof~ `);`;
220                                 }
221                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
222                                 validator.isValid(this.` ~ memberName ~ `,context);
223                             }`;
224                         }
225                         static if(hasUDA!(__traits(getMember, T ,memberName), Size))
226                         {
227                 str    ~=`        {
228                                 auto validator = new SizeValidator!`~memType.stringof~`();`;
229                                 static if((getUDAs!(__traits(getMember, T ,memberName), Size)[0]).stringof == Size.stringof)
230                                 {
231                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Size)[0]).stringof~ `());`; 
232                                 }
233                                 else
234                                 {
235                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Size)[0]).stringof~ `);`;
236                                 }
237                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
238                                 validator.isValid(this.` ~ memberName ~ `,context);
239                             }`;
240                         }
241                         static if(hasUDA!(__traits(getMember, T ,memberName), Range))
242                         {
243                 str    ~=`        {
244                                 RangeValidator validator = new RangeValidator();`;
245                                 static if((getUDAs!(__traits(getMember, T ,memberName), Range)[0]).stringof == Range.stringof)
246                                 {
247                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Range)[0]).stringof~ `());`; 
248                                 }
249                                 else
250                                 {
251                                     str    ~=`    validator.initialize(`~ (getUDAs!(__traits(getMember, T ,memberName), Range)[0]).stringof~ `);`;
252                                 }
253                     str    ~=`        validator.setPropertyName(`~memberName.stringof~`);
254                                 validator.isValid(this.` ~ memberName ~ `,context);
255                             }`;
256                         }
257                     }
258                 }
259             }
260     str ~= " return context;";
261     str ~=`}`;
262     return str;
263 }