Commit 66643e0906de058cd0c4a4bbfaa154175f6c37ce
1 parent
4f226ef305
Exists in
master
added support for !=
Showing
1 changed file
with
2 additions
and
2 deletions
Show diff stats
filtering.go
1 | package webutility | 1 | package webutility |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "net/http" | 5 | "net/http" |
6 | "net/url" | 6 | "net/url" |
7 | "strings" | 7 | "strings" |
8 | ) | 8 | ) |
9 | 9 | ||
10 | type Filter map[string][]string | 10 | type Filter map[string][]string |
11 | 11 | ||
12 | func (f Filter) Get(key string) (values []string, ok bool) { | 12 | func (f Filter) Get(key string) (values []string, ok bool) { |
13 | values, ok = f[key] | 13 | values, ok = f[key] |
14 | return values, ok | 14 | return values, ok |
15 | } | 15 | } |
16 | 16 | ||
17 | func (f Filter) Size() int { | 17 | func (f Filter) Size() int { |
18 | return len(f) | 18 | return len(f) |
19 | } | 19 | } |
20 | 20 | ||
21 | func (f Filter) IsNotEmpty() bool { | 21 | func (f Filter) IsNotEmpty() bool { |
22 | return len(f) > 0 | 22 | return len(f) > 0 |
23 | } | 23 | } |
24 | 24 | ||
25 | func (f Filter) ValueAt(val string, index int) string { | 25 | func (f Filter) ValueAt(val string, index int) string { |
26 | if filter, ok := f[val]; ok { | 26 | if filter, ok := f[val]; ok { |
27 | if len(filter) > index { | 27 | if len(filter) > index { |
28 | return filter[index] | 28 | return filter[index] |
29 | } | 29 | } |
30 | } | 30 | } |
31 | 31 | ||
32 | return "" | 32 | return "" |
33 | } | 33 | } |
34 | 34 | ||
35 | func (fs Filter) validate(validFilters []string) (Filter, bool) { | 35 | func (fs Filter) validate(validFilters []string) (Filter, bool) { |
36 | goodFilters := make(Filter) | 36 | goodFilters := make(Filter) |
37 | cnt, len := 0, 0 | 37 | cnt, len := 0, 0 |
38 | for f, _ := range fs { | 38 | for f, _ := range fs { |
39 | len++ | 39 | len++ |
40 | for _, v := range validFilters { | 40 | for _, v := range validFilters { |
41 | if f == v { | 41 | if f == v { |
42 | cnt++ | 42 | cnt++ |
43 | goodFilters[f] = fs[f] | 43 | goodFilters[f] = fs[f] |
44 | } | 44 | } |
45 | } | 45 | } |
46 | } | 46 | } |
47 | 47 | ||
48 | result := true | 48 | result := true |
49 | if len > 0 && cnt == 0 { | 49 | if len > 0 && cnt == 0 { |
50 | // if no valid filters are found declare filtering request as invalid | 50 | // if no valid filters are found declare filtering request as invalid |
51 | result = false | 51 | result = false |
52 | } | 52 | } |
53 | 53 | ||
54 | return goodFilters, result | 54 | return goodFilters, result |
55 | } | 55 | } |
56 | 56 | ||
57 | // requires input in format: "param1::value1|param2::value2..." | 57 | // requires input in format: "param1::value1|param2::value2..." |
58 | func ParseFilters(req *http.Request, header string) (filters Filter) { | 58 | func ParseFilters(req *http.Request, header string) (filters Filter) { |
59 | q := req.FormValue(header) | 59 | q := req.FormValue(header) |
60 | q = strings.Trim(q, "\"") | 60 | q = strings.Trim(q, "\"") |
61 | kvp := strings.Split(q, "|") | 61 | kvp := strings.Split(q, "|") |
62 | filters = make(Filter, len(kvp)) | 62 | filters = make(Filter, len(kvp)) |
63 | 63 | ||
64 | for i, _ := range kvp { | 64 | for i, _ := range kvp { |
65 | kv := strings.Split(kvp[i], "::") | 65 | kv := strings.Split(kvp[i], "::") |
66 | if len(kv) == 2 { | 66 | if len(kv) == 2 { |
67 | key, _ := url.QueryUnescape(kv[0]) | 67 | key, _ := url.QueryUnescape(kv[0]) |
68 | 68 | ||
69 | // get values (if more than 1) | 69 | // get values (if more than 1) |
70 | vals := strings.Split(kv[1], ",") | 70 | vals := strings.Split(kv[1], ",") |
71 | for _, v := range vals { | 71 | for _, v := range vals { |
72 | u, _ := url.QueryUnescape(v) | 72 | u, _ := url.QueryUnescape(v) |
73 | filters[key] = append(filters[key], u) | 73 | filters[key] = append(filters[key], u) |
74 | } | 74 | } |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | return filters | 78 | return filters |
79 | } | 79 | } |
80 | 80 | ||
81 | // TODO(marko): very dodgy, needs more robustness | 81 | // TODO(marko): very dodgy, needs more robustness |
82 | func MakeFilterString(prefix string, filters Filter, validFilters []string) (res string, ok bool) { | 82 | func MakeFilterString(prefix string, filters Filter, validFilters []string) (res string, ok bool) { |
83 | if prefix != "" { | 83 | if prefix != "" { |
84 | prefix += "." | 84 | prefix += "." |
85 | } | 85 | } |
86 | 86 | ||
87 | if !filters.IsNotEmpty() { | 87 | if !filters.IsNotEmpty() { |
88 | return "", true | 88 | return "", true |
89 | } | 89 | } |
90 | 90 | ||
91 | filters, ok = filters.validate(validFilters) | 91 | filters, ok = filters.validate(validFilters) |
92 | if !ok { | 92 | if !ok { |
93 | return "", false | 93 | return "", false |
94 | } | 94 | } |
95 | 95 | ||
96 | for k, filter := range filters { | 96 | for k, filter := range filters { |
97 | first := true | 97 | first := true |
98 | symbol := "=" | 98 | symbol := "=" |
99 | 99 | ||
100 | if first { | 100 | if first { |
101 | res += " where " | 101 | res += " where " |
102 | first = false | 102 | first = false |
103 | } else { | 103 | } else { |
104 | res += " and " | 104 | res += " and " |
105 | } | 105 | } |
106 | 106 | ||
107 | res += "(" | 107 | res += "(" |
108 | for i, f := range filter { | 108 | for i, f := range filter { |
109 | if strings.HasPrefix(f, "<") || strings.HasPrefix(f, ">") { | 109 | if strings.HasPrefix(f, "<") || strings.HasPrefix(f, ">") || strings.HasPrefix(f, "!") { |
110 | symbol = string(f[0]) | 110 | symbol = string(f[0]) |
111 | f = strings.TrimLeft(f, "<>") | 111 | f = strings.TrimLeft(f, "<>!") |
112 | if strings.HasPrefix(f, "=") { | 112 | if strings.HasPrefix(f, "=") { |
113 | f = strings.TrimLeft(f, "=") | 113 | f = strings.TrimLeft(f, "=") |
114 | symbol += "=" | 114 | symbol += "=" |
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
118 | res += fmt.Sprintf("%s%s %s '%s'", prefix, k, symbol, f) | 118 | res += fmt.Sprintf("%s%s %s '%s'", prefix, k, symbol, f) |
119 | 119 | ||
120 | if i < len(filter)-1 { | 120 | if i < len(filter)-1 { |
121 | res += " or " | 121 | res += " or " |
122 | } | 122 | } |
123 | } | 123 | } |
124 | res += ")" | 124 | res += ")" |
125 | } | 125 | } |
126 | 126 | ||
127 | return res, ok | 127 | return res, ok |
128 | } | 128 | } |
129 | 129 |