-
Notifications
You must be signed in to change notification settings - Fork 0
/
query.go
135 lines (124 loc) · 2.93 KB
/
query.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
package indexing
import (
"github.com/emirpasic/gods/maps/linkedhashmap"
"reflect"
"strings"
)
//Key is a primary key or an indexing key, this can be a composite key as well
//[]string
type Key struct {
Fields []string
fieldsCache map[string]interface{}
//This can be used to prefix the value of the key.
//ValuePrefix string
}
func (k *Key) IsEmpty() bool {
return len(k.Fields) == 0
}
//NewKey creates a new keyParts using an array of fields.
func NewKey(fieldNames ...string) *Key {
var key Key
key.fieldsCache = make(map[string]interface{})
for _, item := range fieldNames {
_, exists := key.fieldsCache[item]
if exists {
continue
}
key.Fields = append(key.Fields, item)
key.fieldsCache[item] = true
}
return &key
}
//func (k *Key) SetPrefix(val string) *Key {
// k.ValuePrefix = val
// return k
//}
//AddKeys adds multiple keys
func (k *Key) AddKeys(newKeys *Key) {
if k.fieldsCache == nil {
k.fieldsCache = make(map[string]interface{})
}
for _, newKey := range newKeys.Fields {
_, exists := k.fieldsCache[newKey]
if exists {
continue
}
k.Fields = append(k.Fields, newKey)
k.fieldsCache[newKey] = true
}
}
//Add a new key field
func (k *Key) Add(s string) {
_, exists := k.fieldsCache[s]
if exists {
return
}
k.Fields = append(k.Fields, s)
k.fieldsCache[s] = true
}
//KeyHasValue checks if all the key fields in an item have a value.
func KeyHasValue(key *Key, item interface{}) bool {
val := reflect.ValueOf(item).Elem()
fieldsField := val.FieldByName("ExtraFields")
for _, key := range key.Fields {
isExtra := strings.HasPrefix(key, "ExtraFields.")
if isExtra {
key = key[12:]
}
fld := val.FieldByName(key)
if fld.IsValid() {
val := fld.Interface()
if val == nil || val.(string) == "" {
return false
}
continue
}
if fieldsField.IsValid() {
if val, found := fieldsField.Interface().(map[string]interface{})[key]; found {
if val == nil || val.(string) == "" {
return false
}
continue
}
}
return false
}
return true
}
type Query interface {
Put(k, v interface{})
Size() int
Keys() []interface{}
Values() []interface{}
Get(key interface{}) (value interface{}, found bool)
}
func NewQuery() Query {
query := linkedhashmap.New()
return query
}
//GetKeyQueryFromItem gets the query that matches an item with the given keyParts.
func GetKeyQueryFromItem(keyParts *Key, item interface{}) Query {
output := NewQuery()
val := reflect.ValueOf(item).Elem()
fieldsField := val.FieldByName("ExtraFields")
for _, key := range keyParts.Fields {
isExtra := strings.HasPrefix(key, "ExtraFields.")
parsedKey := key
if isExtra {
parsedKey = key[12:]
}
fld := val.FieldByName(parsedKey)
if fld.IsValid() {
val := fld.Interface()
output.Put(key, val)
continue
}
if !fieldsField.IsValid() {
continue
}
if val, found := fieldsField.Interface().(map[string]interface{})[parsedKey]; found {
output.Put(key, val)
}
}
return output
}