-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypes_map.go
141 lines (121 loc) · 4.94 KB
/
types_map.go
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
129
130
131
132
133
134
135
136
137
138
139
140
141
package f8n
import (
"fmt"
"net/http"
"sort"
"strings"
kitModuleAns "github.com/webnice/kit/v4/module/ans"
)
// Origin Структура константы описывающей происхождение тега.
type Origin string
// Map Структура настроек сложной фильтрации.
type Map struct {
parent *impl `` // Ссылка на объект пакета.
TagBegin string `json:"beg"` // Для парных тегов - открывающий тег, для одиночных весь тег целиком.
TagEnd string `json:"end"` // Для парных тегов - закрывающий тег, для одиночных весь тег целиком.
Origin Origin `json:"origin"` // Константа описывающая сущность тега.
Content string `json:"content"` // Контент тега - наименование фильтрации.
Filter *Filter `json:"filter"` // Контент фильтра, разобранный в объект описания простой фильтрации.
Size int `json:"size"` // Общий размер тега в байтах.
Node []*Map `json:"node"` // Массив узлов, в порядке следования, сложенных в текущий узел.
}
func init() {
// Сортировка констант справочника тегов в обратном порядке по длине тега.
// Чем длиннее тег, тем он более релевантен при совпадении поиска, по отношению к короткому тегу.
// Пример: list и list-item, при поиске совпадения первым должен сравниваться list-item.
sort.SliceStable(OriginAll, func(i int, j int) bool {
return len(OriginAll[i].String()) > len(OriginAll[j].String())
})
}
// String Реализация интерфейса Stringify.
func (origin Origin) String() string { return string(origin) }
// Экспорт значения настроек сортировки.
func (direction Direction) exportAsString() (ret string) {
if direction.Field == "" {
return
}
ret = fmt.Sprintf("%s%s%s", direction.Field, keyDelimiter, direction.By.String())
return
}
// Рекурсивная установка parent для всех узлов карты.
// Применяется после импорта настроек фильтрации.
func (mp *Map) setParent(f8n *impl) {
var n int
mp.parent = f8n
for n = range mp.Node {
mp.Node[n].setParent(f8n)
}
}
// SumSize Выполняет суммирование всех размеров узла и всех подчинённых узлов.
// Возвращается размер в байтах.
func (mp *Map) SumSize() (ret int) {
var (
size int
n int
)
for n = range mp.Node {
size += mp.Node[n].SumSize()
}
return mp.Size + size
}
// IsEmpty Возвращает истину если узел карты пустой - не является тегом и не содержит подчинённых узлов.
func (mp *Map) IsEmpty() bool {
return mp.TagBegin == "" && mp.TagEnd == "" && mp.Content == "" && len(mp.Node) == 0
}
// Analysis Выполнение анализатора карты рекурсивно.
func (mp *Map) Analysis() (ret []*ParseError) {
var (
n int
tmp []*ParseError
)
for n = range mp.Node {
if tmp = mp.Node[n].Analysis(); len(tmp) > 0 {
ret = append(ret, tmp...)
}
}
if tmp = mp.parent.analysis(mp); len(tmp) > 0 {
ret = append(ret, tmp...)
}
return
}
// LoadAndParseFilter Рекурсивное копирование фильтров из запроса в DOM объект, а так же разбор фильтров
// в соответствии с синтаксисом.
func (mp *Map) LoadAndParseFilter(rq *http.Request) (ret []*ParseError) {
var (
errs []*ParseError
ero *ParseError
filter Filter
n int
ok bool
keyFilter string
filters []string
tmp string
)
// Обработка текущего узла.
if mp.Origin == OriginFiltration && mp.Content != "" {
keyFilter = strings.TrimSpace(mp.Content)
if filters, ok = rq.URL.Query()[keyFilter]; !ok {
ero = &ParseError{Ei: mp.parent.Errors().FilterCalledByNameWasNotFound(keyFilter)}
ero.Ev = append(ero.Ev, kitModuleAns.RestErrorField{
Field: keyMap,
FieldValue: keyFilter,
Message: ero.Ei.Error(),
})
ret, filters = append(ret, ero), filters[:0]
}
if len(filters) > 0 {
tmp = strings.Join(filters, keyAnd)
if filter, errs = mp.parent.parseFilterSimple(tmp); len(errs) == 0 {
mp.Filter = &filter
}
ret = append(ret, errs...)
}
}
// Обработка всех подчинённых узлов.
for n = range mp.Node {
if errs = mp.Node[n].LoadAndParseFilter(rq); len(errs) > 0 {
ret = append(ret, errs...)
}
}
return
}