-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCMessageManager.cls
233 lines (195 loc) · 5.73 KB
/
CMessageManager.cls
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
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "CMessageManager"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Compare Database
Option Explicit
Private mlstSubscribers As CList
'
' Class error context
'
Private mlErr As Long
Private msErrCtx As String
Private msErr As String
Private Sub ClearErr()
mlErr = 0&
msErr = ""
msErrCtx = ""
End Sub
Private Sub SetErr(ByVal psErrCtx As String, ByVal plErr As Long, ByVal psErr As String)
mlErr = plErr
msErr = psErr
msErrCtx = psErrCtx
End Sub
Public Property Get LastErr() As Long
LastErr = mlErr
End Property
Public Property Get LastErrDesc() As String
LastErrDesc = msErr
End Property
Public Property Get LastErrContext() As String
LastErrContext = msErrCtx
End Property
Private Sub Class_Initialize()
Const LOCAL_ERR_CTX As String = "Class_Initialize"
On Error GoTo Class_Initialize_Err
ClearErr
Set mlstSubscribers = New CList
mlstSubscribers.ArrayDefine Array("Topic", "ClientID", "IMessageReceiver"), Array(vbString, vbString, vbObject)
Class_Initialize_Exit:
Exit Sub
Class_Initialize_Err:
SetErr LOCAL_ERR_CTX, Err.Number, Err.Description
Resume Class_Initialize_Exit
End Sub
Private Sub Class_Terminate()
On Error Resume Next
Set mlstSubscribers = Nothing
End Sub
Public Function IsSubscribed(ByVal psClientID As String, ByVal psTopic As String) As Boolean
Dim iFind As Long
iFind = mlstSubscribers.Find(Array("Topic", "ClientID"), Array(psTopic, psClientID))
If iFind > 0 Then
IsSubscribed = True
End If
End Function
Public Function Subscribe(ByRef pIIMessageReceiver As IMessageReceiver, ByVal psTopic As String) As Boolean
Const LOCAL_ERR_CTX As String = "Subscribe"
On Error GoTo Subscribe_Err
ClearErr
Dim sClientID As String
sClientID = pIIMessageReceiver.ClientID
If IsSubscribed(sClientID, psTopic) Then
Subscribe = True
Exit Function
End If
mlstSubscribers.AddValues psTopic, sClientID, pIIMessageReceiver
If mlstSubscribers.Count > 2 Then
mlstSubscribers.Sort "Topic;ClientID"
End If
Subscribe = True
Subscribe_Exit:
Exit Function
Subscribe_Err:
SetErr LOCAL_ERR_CTX, Err.Number, Err.Description
Resume Subscribe_Exit
End Function
Public Function SubscribeMulti(ByRef pIIMessageReceiver As IMessageReceiver, pavTopics As Variant) As Boolean
Const LOCAL_ERR_CTX As String = "SubscribeMulti"
On Error GoTo SubscribeMulti_Err
ClearErr
Dim sClientID As String
Dim vTopic As Variant
Dim sTopic As String
Dim iSubscrCt As Integer
sClientID = pIIMessageReceiver.ClientID
For Each vTopic In pavTopics
If Not IsSubscribed(sClientID, vTopic) Then
sTopic = vTopic
mlstSubscribers.AddValues sTopic, sClientID, pIIMessageReceiver
iSubscrCt = iSubscrCt + 1
End If
Next
If iSubscrCt > 0 Then
If mlstSubscribers.Count > 2 Then
mlstSubscribers.Sort "Topic;ClientID"
End If
End If
SubscribeMulti = True
SubscribeMulti_Exit:
Exit Function
SubscribeMulti_Err:
SetErr LOCAL_ERR_CTX, Err.Number, Err.Description
Resume SubscribeMulti_Exit
End Function
'if psTopic = "" then unsubscribe from all topics
Public Sub Unsubscribe(ByVal psClientID As String, ByVal psTopic As String)
Dim i As Long
Dim fFound As Boolean
On Error Resume Next
If Len(psTopic) = 0 Then
Do
fFound = False
For i = 1 To mlstSubscribers.Count
If mlstSubscribers("ClientID", i) = psClientID Then
fFound = True
mlstSubscribers.Remove i
Exit For
End If
Next i
Loop Until fFound = False
Else
i = mlstSubscribers.Find(Array("Topic", "ClientID"), Array(psTopic, psClientID))
If i > 0 Then
mlstSubscribers.Remove i
End If
End If
End Sub
'A subscriber can return a value <> 0& to break the broadcase
Public Function Broadcast( _
ByVal psClientID As String, _
ByVal psTopic As String, _
ByVal pvData As Variant, _
Optional ByVal psTargetClientIDS As String _
) As Long
Const LOCAL_ERR_CTX As String = "Broadcast"
On Error GoTo Broadcast_Err
ClearErr
Dim iFind As Long
Dim i As Long
Dim iiMsgReceiver As IMessageReceiver
Dim lRet As Long
Dim sReceiverID As String
Dim iTargetIDCt As Integer
Dim asTargetID() As String
Dim fDoSend As Boolean
Dim k As Integer
iFind = mlstSubscribers.FindFirst("Topic", psTopic)
If iFind <= 0 Then
'nobody to notify
Broadcast = 0&
Exit Function
End If
If Len(psTargetClientIDS) > 0 Then
iTargetIDCt = SplitString(asTargetID(), psTargetClientIDS, ";")
End If
For i = 1 To mlstSubscribers.Count
If mlstSubscribers("Topic", i) = psTopic Then
sReceiverID = mlstSubscribers("ClientID", i)
If iTargetIDCt = 0 Then
fDoSend = True
Else
fDoSend = False
For k = 1 To iTargetIDCt
If asTargetID(k) = sReceiverID Then
fDoSend = True
End If
Next k
End If
If fDoSend Then
On Error Resume Next
Set iiMsgReceiver = mlstSubscribers("IMessageReceiver", i)
If Err.Number = 0 Then
On Error GoTo Broadcast_Err
lRet = iiMsgReceiver.OnMessageReceived(psClientID, psTopic, pvData)
'If a receiver returns anything else than 0, we exit the loop
If lRet <> 0& Then Exit For
End If
On Error GoTo Broadcast_Err
End If
End If
Next i
Broadcast_Exit:
Broadcast = lRet
Set iiMsgReceiver = Nothing
Exit Function
Broadcast_Err:
SetErr LOCAL_ERR_CTX, Err.Number, Err.Description
Resume Broadcast_Exit
Resume
End Function