-
Notifications
You must be signed in to change notification settings - Fork 73
/
key.go
254 lines (199 loc) · 5.9 KB
/
key.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
package ari
import "fmt"
const (
// ApplicationKey is the key kind for ARI Application resources.
ApplicationKey = "application"
// BridgeKey is the key kind for the ARI Bridge resources.
BridgeKey = "bridge"
// ChannelKey is the key kind for the ARI Channel resource
ChannelKey = "channel"
// DeviceStateKey is the key kind for the ARI DeviceState resource
DeviceStateKey = "devicestate"
// EndpointKey is the key kind for the ARI Endpoint resource
EndpointKey = "endpoint"
// LiveRecordingKey is the key kind for the ARI LiveRecording resource
LiveRecordingKey = "liverecording"
// LoggingKey is the key kind for the ARI Logging resource
LoggingKey = "logging"
// MailboxKey is the key kind for the ARI Mailbox resource
MailboxKey = "mailbox"
// ModuleKey is the key kind for the ARI Module resource
ModuleKey = "module"
// PlaybackKey is the key kind for the ARI Playback resource
PlaybackKey = "playback"
// SoundKey is the key kind for the ARI Sound resource
SoundKey = "sound"
// StoredRecordingKey is the key kind for the ARI StoredRecording resource
StoredRecordingKey = "storedrecording"
// VariableKey is the key kind for the ARI Asterisk Variable resource
VariableKey = "variable"
)
// Keys is a list of keys
type Keys []*Key
// Filter filters the key list using the given key type match
func (kx Keys) Filter(mx ...Matcher) (ret Keys) {
for _, m := range mx {
for _, k := range kx {
if m.Match(k) {
ret = append(ret, k)
}
}
}
return
}
// Without removes keys that match the given matcher
func (kx Keys) Without(m Matcher) (ret Keys) {
for _, k := range kx {
if !m.Match(k) {
ret = append(ret, k)
}
}
return
}
// First returns the first key from a list of keys. It is safe to use on empty lists, in which case, it will return nil.
func (kx Keys) First() *Key {
if len(kx) < 1 {
return nil
}
return kx[0]
}
// Bridges returns just the bridge keys from a set of Keys
func (kx Keys) Bridges() Keys {
return kx.Filter(NewKey(BridgeKey, ""))
}
// Channels returns just the channel keys from a set of Keys
func (kx Keys) Channels() Keys {
return kx.Filter(NewKey(ChannelKey, ""))
}
// ID returns the key from a set of keys with ID matching the given ID. If the
// key does not exist in the set, nil is returned.
func (kx Keys) ID(id string) *Key {
return kx.Filter(NewKey("", id)).First()
}
// A Matcher provides the functionality for matching against a key.
type Matcher interface {
Match(o *Key) bool
}
// MatchFunc is the functional type alias for providing functional `Matcher` implementations
type MatchFunc func(*Key) bool
// Match invokes the match function given the key
func (mf MatchFunc) Match(o *Key) bool {
return mf(o)
}
// KeyOptionFunc is a functional argument alias for providing options for ARI keys
type KeyOptionFunc func(Key) Key
// WithDialog sets the given dialog identifier on the key.
func WithDialog(dialog string) KeyOptionFunc {
return func(key Key) Key {
key.Dialog = dialog
return key
}
}
// WithNode sets the given node identifier on the key.
func WithNode(node string) KeyOptionFunc {
return func(key Key) Key {
key.Node = node
return key
}
}
// WithApp sets the given node identifier on the key.
func WithApp(app string) KeyOptionFunc {
return func(key Key) Key {
key.App = app
return key
}
}
// WithLocationOf copies the partial key fields Node, Application, Dialog from the reference key
func WithLocationOf(ref *Key) KeyOptionFunc {
return func(key Key) Key {
if ref != nil {
key.Node = ref.Node
key.Dialog = ref.Dialog
key.App = ref.App
}
return key
}
}
// NewKey builds a new key given the kind, identifier, and any optional arguments.
func NewKey(kind string, id string, opts ...KeyOptionFunc) *Key {
k := Key{
Kind: kind,
ID: id,
}
for _, o := range opts {
k = o(k)
}
return &k
}
// AppKey returns a key that is bound to the given application.
func AppKey(app string) *Key {
return NewKey("", "", WithApp(app))
}
// ConfigID returns the configuration Key ID for the given configuration class, type/kind, and id.
func ConfigID(class, kind, id string) string {
return fmt.Sprintf("%s/%s/%s", class, kind, id)
}
// EndpointID returns the endpoint Key ID for the given tech and resource
func EndpointID(tech, resource string) string {
return fmt.Sprintf("%s/%s", tech, resource)
}
// DialogKey returns a key that is bound to the given dialog.
func DialogKey(dialog string) *Key {
return NewKey("", "", WithDialog(dialog))
}
// NodeKey returns a key that is bound to the given application and node
func NodeKey(app, node string) *Key {
return NewKey("", "", WithApp(app), WithNode(node))
}
// KindKey returns a key that is bound by a type only
func KindKey(kind string, opts ...KeyOptionFunc) *Key {
return NewKey(kind, "", opts...)
}
// Match returns true if the given key matches the subject. Empty partial key fields are wildcards.
func (k *Key) Match(o *Key) bool {
if k == o {
return true
}
if k == nil || o == nil {
return true
}
if k.App != "" && o.App != "" && k.App != o.App {
return false
}
if k.Dialog != "" && o.Dialog != "" && k.Dialog != o.Dialog {
return false
}
if k.Node != "" && o.Node != "" && k.Node != o.Node {
return false
}
if k.Kind != "" && o.Kind != "" && k.Kind != o.Kind {
return false
}
if k.ID != "" && o.ID != "" && k.ID != o.ID {
return false
}
return true
}
// New returns a new key with the location information from the source key.
// This includes the App, the Node, and the Dialog. the `kind` and `id`
// parameters are optional. If kind is empty, the resulting key will not be
// typed. If id is empty, the key will not be unique.
func (k *Key) New(kind, id string) *Key {
n := NodeKey(k.App, k.Node)
n.Dialog = k.Dialog
n.Kind = kind
n.ID = id
return n
}
func (k *Key) String() string {
if k.ID != "" {
return k.ID
}
if k.Dialog != "" {
return "[" + k.Dialog + "]"
}
if k.Node != "" {
return k.App + "@" + k.Node
}
return "emptyKey"
}