This repository has been archived by the owner on Jun 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
routing_key_creator.go
134 lines (104 loc) · 3.63 KB
/
routing_key_creator.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
package main
import (
"fmt"
"regexp"
"strconv"
"strings"
)
func CreateRoutingKey(rk string, record *map[string]interface{}, rkDelimiter string) (string, error) {
var recordAccessorLookupTable map[string]string
var builder strings.Builder
recordAccessorRegex, err := regexp.Compile(`(\'[^\s\']+\')|(\"[^\s\"]+\")|(\[0\])|(\[[1-9][0-9]*\])`)
if err != nil {
return "", err
}
recordAccessorLookupTable = make(map[string]string)
recordAccessors := strings.Split(rk, rkDelimiter)
for idx, recordAccessor := range recordAccessors {
if strings.HasPrefix(recordAccessor, "$") {
val, containsRecordAccessor := recordAccessorLookupTable[recordAccessor]
if containsRecordAccessor {
builder.WriteString(val)
} else {
subRk, err := extractValueFromRecord(record, recordAccessorRegex.FindAllString(recordAccessor, -1))
if err != nil {
return "", err
}
recordAccessorLookupTable[recordAccessor] = subRk
builder.WriteString(subRk)
}
} else {
builder.WriteString(recordAccessor)
}
if idx != (len(recordAccessors) - 1) {
builder.WriteString(rkDelimiter)
}
}
return builder.String(), nil
}
func extractValueFromRecord(record *map[string]interface{}, keys []string) (string, error) {
if len(keys) > 0 {
arrKey := []rune(keys[0])
currentKey := string(arrKey[1:(len(arrKey) - 1)])
if strings.HasPrefix(keys[0], "[") {
return "", fmt.Errorf("Couldn't access the Record with the array-accessor '%s', record-accessor is required", currentKey)
}
val, recordContainsKey := (*record)[currentKey]
if len(keys) == 1 {
if recordContainsKey {
if removeRkValuesFromRecord {
delete(*record, currentKey)
}
return fmt.Sprintf("%v", val), nil
}
return "", fmt.Errorf("Can't access the record with the given record-accessor '%s'", currentKey)
}
subRecord, recordContainsSubRecord := val.(map[string]interface{})
if recordContainsSubRecord {
return extractValueFromRecord(&subRecord, keys[1:])
}
recordArray, recordContainsArray := val.(*[]interface{})
if recordContainsArray {
return extractValueFromArray(recordArray, keys[1:])
}
return "", fmt.Errorf("Couldn't access the Record with the record-accessor '%s'", currentKey)
}
return "", fmt.Errorf("The given routing-key doesn't contain any values")
}
func extractValueFromArray(recordArray *[]interface{}, keys []string) (string, error) {
if len(keys) > 0 {
arrKey := []rune(keys[0])
currentKey := string(arrKey[1:(len(arrKey) - 1)])
idx, err := strconv.Atoi(currentKey)
arr := *recordArray
if err != nil {
return "", fmt.Errorf("Couldn't parse the array-accessor '%s' to int", currentKey)
}
if strings.HasPrefix(keys[0], "\"") || strings.HasPrefix(keys[0], "'") {
return "", fmt.Errorf("Couldn't access the array with the record-accessor '%s', array-accessor is required", currentKey)
}
if len(arr) <= idx {
return "", fmt.Errorf("The given index '%s' exceededs the array-size", currentKey)
}
val := arr[idx]
if len(keys) == 1 {
if removeRkValuesFromRecord {
copy(arr[idx:], arr[idx+1:])
arr[len(arr)-1] = ""
arr = arr[:len(arr)-1]
*recordArray = arr
}
return fmt.Sprintf("%v", val), nil
}
subRecord, recordContainsSubRecord := val.(map[string]interface{})
if recordContainsSubRecord {
return extractValueFromRecord(&subRecord, keys[1:])
}
recordArray, recordContainsArray := val.(*[]interface{})
if recordContainsArray {
return extractValueFromArray(recordArray, keys[1:])
}
return "", fmt.Errorf("Couldn't access the Record with the record-accessor '%s'", currentKey)
}
return "", fmt.Errorf("The given routing-key doesn't contain any values")
}