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