1 module hunt.http.routing.impl.AbstractPatternMatcher;
2 
3 import hunt.http.routing.Matcher;
4 import hunt.http.routing.Router;
5 
6 import hunt.Exceptions;
7 import hunt.collection;
8 
9 import hunt.logging;
10 import hunt.text;
11 
12 import std.conv;
13 import std.regex;
14 import std.array;
15 
16 /**
17  * 
18  */
19 abstract class AbstractPatternMatcher : Matcher {
20 
21     protected Map!(PatternRule, Set!(Router)) _patternMap;
22 
23     protected static class PatternRule {
24         string rule;
25         Pattern pattern;
26 
27         protected this(string rule) {
28             this.rule = rule;
29             string[] rules = rule.split("*").array;
30             pattern = Pattern.compile(rule, "*");
31         }
32 
33         override
34         bool opEquals(Object o) {
35             if (this is o) return true;
36             PatternRule that = cast(PatternRule) o;
37             if(that is null)   return false;
38             return rule == that.rule;
39         }
40 
41         override
42         size_t toHash() @trusted nothrow {
43             return hashOf(rule);
44         }
45     }
46 
47     this()
48     {
49         _patternMap = new HashMap!(PatternRule, Set!(Router))();
50     }
51 
52     // protected Map!(PatternRule, Set!(Router)) patternMap() {
53     //     if (_patternMap is null) {
54     //         _patternMap = new HashMap!(PatternRule, Set!(Router))();
55     //     }
56     //     return _patternMap;
57     // }
58 
59     abstract MatchType getMatchType() { implementationMissing(); return MatchType.PATH; }
60 
61     void add(string rule, Router router) {
62         _patternMap.computeIfAbsent(new PatternRule(rule), k => new HashSet!Router()).add(router);
63         //trace("_patternMap size: ", _patternMap.size()) ;
64     }
65 
66     MatchResult match(string v) {
67         if (_patternMap is null) {
68             return null;
69         }
70 
71         Set!Router routers = new HashSet!Router();
72         Map!(Router, Map!(string, string)) parameters = new HashMap!(Router, Map!(string, string))();
73 
74         foreach(PatternRule rule, Set!(Router) routerSet; _patternMap)
75         {
76             // tracef("v=%s, pattern=%s", v, rule.rule);
77             string[] strings = rule.pattern.match(v);
78             if (strings.length == 0) 
79                 continue;
80 
81             routers.addAll(routerSet);
82             Map!(string, string) param = new HashMap!(string, string)();
83 
84             int i=0;
85             foreach(string item; strings) {
86                 // tracef("%d => %s", i, item);
87                 // FIXME: Needing refactor or cleanup -@zhangxueping at 2020-03-09T19:24:20+08:00
88                 // check this
89                 // param.put("param" ~ i.to!string(), item);
90                 i++;
91             }
92 
93             foreach(router; routerSet) {
94                 parameters.put(router, param);
95             }
96 
97         }
98         if (routers.isEmpty()) {
99             return null;
100         } else {
101             return new MatchResult(routers, parameters, getMatchType());
102         }
103     }
104 
105 }