github.com/CyCoreSystems/ari@v4.8.4+incompatible/key.go (about) 1 package ari 2 3 import "fmt" 4 5 const ( 6 // ApplicationKey is the key kind for ARI Application resources. 7 ApplicationKey = "application" 8 9 // BridgeKey is the key kind for the ARI Bridge resources. 10 BridgeKey = "bridge" 11 12 // ChannelKey is the key kind for the ARI Channel resource 13 ChannelKey = "channel" 14 15 // DeviceStateKey is the key kind for the ARI DeviceState resource 16 DeviceStateKey = "devicestate" 17 18 // EndpointKey is the key kind for the ARI Endpoint resource 19 EndpointKey = "endpoint" 20 21 // LiveRecordingKey is the key kind for the ARI LiveRecording resource 22 LiveRecordingKey = "liverecording" 23 24 // LoggingKey is the key kind for the ARI Logging resource 25 LoggingKey = "logging" 26 27 // MailboxKey is the key kind for the ARI Mailbox resource 28 MailboxKey = "mailbox" 29 30 // ModuleKey is the key kind for the ARI Module resource 31 ModuleKey = "module" 32 33 // PlaybackKey is the key kind for the ARI Playback resource 34 PlaybackKey = "playback" 35 36 // SoundKey is the key kind for the ARI Sound resource 37 SoundKey = "sound" 38 39 // StoredRecordingKey is the key kind for the ARI StoredRecording resource 40 StoredRecordingKey = "storedrecording" 41 42 // VariableKey is the key kind for the ARI Asterisk Variable resource 43 VariableKey = "variable" 44 ) 45 46 // Keys is a list of keys 47 type Keys []*Key 48 49 // Filter filters the key list using the given key type match 50 func (kx Keys) Filter(mx ...Matcher) (ret Keys) { 51 for _, m := range mx { 52 for _, k := range kx { 53 if m.Match(k) { 54 ret = append(ret, k) 55 } 56 } 57 } 58 return 59 } 60 61 // Without removes keys that match the given matcher 62 func (kx Keys) Without(m Matcher) (ret Keys) { 63 for _, k := range kx { 64 if !m.Match(k) { 65 ret = append(ret, k) 66 } 67 } 68 return 69 } 70 71 // 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. 72 func (kx Keys) First() *Key { 73 if len(kx) < 1 { 74 return nil 75 } 76 return kx[0] 77 } 78 79 // Bridges returns just the bridge keys from a set of Keys 80 func (kx Keys) Bridges() Keys { 81 return kx.Filter(NewKey(BridgeKey, "")) 82 } 83 84 // Channels returns just the channel keys from a set of Keys 85 func (kx Keys) Channels() Keys { 86 return kx.Filter(NewKey(ChannelKey, "")) 87 } 88 89 // ID returns the key from a set of keys with ID matching the given ID. If the 90 // key does not exist in the set, nil is returned. 91 func (kx Keys) ID(id string) *Key { 92 return kx.Filter(NewKey("", id)).First() 93 } 94 95 // A Matcher provides the functionality for matching against a key. 96 type Matcher interface { 97 Match(o *Key) bool 98 } 99 100 // MatchFunc is the functional type alias for providing functional `Matcher` implementations 101 type MatchFunc func(*Key) bool 102 103 // Match invokes the match function given the key 104 func (mf MatchFunc) Match(o *Key) bool { 105 return mf(o) 106 } 107 108 // KeyOptionFunc is a functional argument alias for providing options for ARI keys 109 type KeyOptionFunc func(Key) Key 110 111 // WithDialog sets the given dialog identifier on the key. 112 func WithDialog(dialog string) KeyOptionFunc { 113 return func(key Key) Key { 114 key.Dialog = dialog 115 return key 116 } 117 } 118 119 // WithNode sets the given node identifier on the key. 120 func WithNode(node string) KeyOptionFunc { 121 return func(key Key) Key { 122 key.Node = node 123 return key 124 } 125 } 126 127 // WithApp sets the given node identifier on the key. 128 func WithApp(app string) KeyOptionFunc { 129 return func(key Key) Key { 130 key.App = app 131 return key 132 } 133 } 134 135 // WithLocationOf copies the partial key fields Node, Application, Dialog from the reference key 136 func WithLocationOf(ref *Key) KeyOptionFunc { 137 return func(key Key) Key { 138 if ref != nil { 139 key.Node = ref.Node 140 key.Dialog = ref.Dialog 141 key.App = ref.App 142 } 143 return key 144 } 145 } 146 147 // NewKey builds a new key given the kind, identifier, and any optional arguments. 148 func NewKey(kind string, id string, opts ...KeyOptionFunc) *Key { 149 k := Key{ 150 Kind: kind, 151 ID: id, 152 } 153 for _, o := range opts { 154 k = o(k) 155 } 156 157 return &k 158 } 159 160 // AppKey returns a key that is bound to the given application. 161 func AppKey(app string) *Key { 162 return NewKey("", "", WithApp(app)) 163 } 164 165 // ConfigID returns the configuration Key ID for the given configuration class, type/kind, and id. 166 func ConfigID(class, kind, id string) string { 167 return fmt.Sprintf("%s/%s/%s", class, kind, id) 168 } 169 170 // EndpointID returns the endpoint Key ID for the given tech and resource 171 func EndpointID(tech, resource string) string { 172 return fmt.Sprintf("%s/%s", tech, resource) 173 } 174 175 // DialogKey returns a key that is bound to the given dialog. 176 func DialogKey(dialog string) *Key { 177 return NewKey("", "", WithDialog(dialog)) 178 } 179 180 // NodeKey returns a key that is bound to the given application and node 181 func NodeKey(app, node string) *Key { 182 return NewKey("", "", WithApp(app), WithNode(node)) 183 } 184 185 // KindKey returns a key that is bound by a type only 186 func KindKey(kind string, opts ...KeyOptionFunc) *Key { 187 return NewKey(kind, "", opts...) 188 } 189 190 // Match returns true if the given key matches the subject. Empty partial key fields are wildcards. 191 func (k *Key) Match(o *Key) bool { 192 if k == o { 193 return true 194 } 195 196 if k == nil || o == nil { 197 return true 198 } 199 200 if k.App != "" && o.App != "" && k.App != o.App { 201 return false 202 } 203 if k.Dialog != "" && o.Dialog != "" && k.Dialog != o.Dialog { 204 return false 205 } 206 if k.Node != "" && o.Node != "" && k.Node != o.Node { 207 return false 208 } 209 if k.Kind != "" && o.Kind != "" && k.Kind != o.Kind { 210 return false 211 } 212 if k.ID != "" && o.ID != "" && k.ID != o.ID { 213 return false 214 } 215 216 return true 217 } 218 219 // New returns a new key with the location information from the source key. 220 // This includes the App, the Node, and the Dialog. the `kind` and `id` 221 // parameters are optional. If kind is empty, the resulting key will not be 222 // typed. If id is empty, the key will not be unique. 223 func (k *Key) New(kind, id string) *Key { 224 n := NodeKey(k.App, k.Node) 225 n.Dialog = k.Dialog 226 n.Kind = kind 227 n.ID = id 228 229 return n 230 } 231 232 func (k *Key) String() string { 233 if k.ID != "" { 234 return k.ID 235 } 236 237 if k.Dialog != "" { 238 return "[" + k.Dialog + "]" 239 } 240 241 if k.Node != "" { 242 return k.App + "@" + k.Node 243 } 244 245 return "emptyKey" 246 }