aboutsummaryrefslogtreecommitdiffstats
path: root/cache/query.go
blob: d8df00fe4063af0fca6bb6cbc76105cda68c638a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package cache

import (
	"fmt"
	"strings"
)

type Query struct {
	Filters
	OrderBy
	OrderDirection
}

// ParseQuery parse a query DSL
//
// Ex: "status:open author:descartes sort:edit-asc"
//
// Supported filter fields are:
// - status:
// - author:
// - label:
// - no:
//
// Sorting is done with:
// - sort:
//
// Todo: write a complete doc
func ParseQuery(query string) (*Query, error) {
	fields := strings.Fields(query)

	result := &Query{
		OrderBy:        OrderByCreation,
		OrderDirection: OrderDescending,
	}

	sortingDone := false

	for _, field := range fields {
		split := strings.Split(field, ":")
		if len(split) != 2 {
			return nil, fmt.Errorf("can't parse \"%s\"", field)
		}

		switch split[0] {
		case "status":
			f, err := StatusFilter(split[1])
			if err != nil {
				return nil, err
			}
			result.Status = append(result.Status, f)

		case "author":
			f := AuthorFilter(split[1])
			result.Author = append(result.Author, f)

		case "label":
			f := LabelFilter(split[1])
			result.Label = append(result.Label, f)

		case "no":
			err := result.parseNoFilter(split[1])
			if err != nil {
				return nil, err
			}

		case "sort":
			if sortingDone {
				return nil, fmt.Errorf("multiple sorting")
			}

			err := result.parseSorting(split[1])
			if err != nil {
				return nil, err
			}

			sortingDone = true

		default:
			return nil, fmt.Errorf("unknow query field %s", split[0])
		}
	}

	return result, nil
}

func (q *Query) parseNoFilter(query string) error {
	switch query {
	case "label":
		q.NoFilters = append(q.NoFilters, NoLabelFilter())
	default:
		return fmt.Errorf("unknown \"no\" filter")
	}

	return nil
}

func (q *Query) parseSorting(query string) error {
	switch query {
	// default ASC
	case "id-desc":
		q.OrderBy = OrderById
		q.OrderDirection = OrderDescending
	case "id", "id-asc":
		q.OrderBy = OrderById
		q.OrderDirection = OrderAscending

	// default DESC
	case "creation", "creation-desc":
		q.OrderBy = OrderByCreation
		q.OrderDirection = OrderDescending
	case "creation-asc":
		q.OrderBy = OrderByCreation
		q.OrderDirection = OrderAscending

	// default DESC
	case "edit", "edit-desc":
		q.OrderBy = OrderByEdit
		q.OrderDirection = OrderDescending
	case "edit-asc":
		q.OrderBy = OrderByEdit
		q.OrderDirection = OrderAscending

	default:
		return fmt.Errorf("unknow sorting %s", query)
	}

	return nil
}