sumac 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/README.md +2 -0
- data/lib/core_extensions.rb +207 -0
- data/lib/sumac.rb +94 -0
- data/lib/sumac/adapter.rb +5 -0
- data/lib/sumac/adapter/closed.rb +7 -0
- data/lib/sumac/argument_error.rb +5 -0
- data/lib/sumac/call_dispatcher.rb +70 -0
- data/lib/sumac/call_processor.rb +93 -0
- data/lib/sumac/closed_error.rb +5 -0
- data/lib/sumac/closer.rb +53 -0
- data/lib/sumac/connection.rb +94 -0
- data/lib/sumac/exposed_object.rb +131 -0
- data/lib/sumac/exposed_object_child.rb +158 -0
- data/lib/sumac/forgoten.rb +5 -0
- data/lib/sumac/handshake.rb +48 -0
- data/lib/sumac/id_allocator.rb +99 -0
- data/lib/sumac/local_reference.rb +16 -0
- data/lib/sumac/local_references.rb +80 -0
- data/lib/sumac/message.rb +19 -0
- data/lib/sumac/message/exchange.rb +30 -0
- data/lib/sumac/message/exchange/base.rb +15 -0
- data/lib/sumac/message/exchange/call_request.rb +96 -0
- data/lib/sumac/message/exchange/call_response.rb +83 -0
- data/lib/sumac/message/exchange/compatibility_notification.rb +53 -0
- data/lib/sumac/message/exchange/forget_notification.rb +77 -0
- data/lib/sumac/message/exchange/id.rb +30 -0
- data/lib/sumac/message/exchange/initialization_notification.rb +52 -0
- data/lib/sumac/message/exchange/notification.rb +9 -0
- data/lib/sumac/message/exchange/shutdown_notification.rb +27 -0
- data/lib/sumac/message/object.rb +72 -0
- data/lib/sumac/message/object/array.rb +57 -0
- data/lib/sumac/message/object/base.rb +21 -0
- data/lib/sumac/message/object/boolean.rb +45 -0
- data/lib/sumac/message/object/exception.rb +66 -0
- data/lib/sumac/message/object/exposed.rb +79 -0
- data/lib/sumac/message/object/exposed_child.rb +86 -0
- data/lib/sumac/message/object/float.rb +45 -0
- data/lib/sumac/message/object/hash_table.rb +75 -0
- data/lib/sumac/message/object/integer.rb +45 -0
- data/lib/sumac/message/object/native_exception.rb +56 -0
- data/lib/sumac/message/object/null.rb +44 -0
- data/lib/sumac/message/object/string.rb +45 -0
- data/lib/sumac/message_error.rb +5 -0
- data/lib/sumac/messenger.rb +65 -0
- data/lib/sumac/native_error.rb +17 -0
- data/lib/sumac/no_method_error.rb +9 -0
- data/lib/sumac/reference.rb +68 -0
- data/lib/sumac/remote_entry.rb +42 -0
- data/lib/sumac/remote_object.rb +39 -0
- data/lib/sumac/remote_object_child.rb +38 -0
- data/lib/sumac/remote_reference.rb +16 -0
- data/lib/sumac/remote_references.rb +70 -0
- data/lib/sumac/scheduler.rb +56 -0
- data/lib/sumac/shutdown.rb +32 -0
- data/lib/sumac/stale_object_error.rb +5 -0
- data/lib/sumac/unexposable_object_error.rb +9 -0
- data/lib/sumac/worker_pool.rb +35 -0
- data/test/test_id_allocator.rb +25 -0
- metadata +145 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
class Sumac
|
|
2
|
+
module ExposedObjectChild
|
|
3
|
+
|
|
4
|
+
def self.included(base)
|
|
5
|
+
base.extend(IncludedClassMethods)
|
|
6
|
+
base.include(IncludedInstanceMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.extended(base)
|
|
10
|
+
base.extend(ExtendedClassMethods)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
module IncludedClassMethods
|
|
15
|
+
|
|
16
|
+
def inherited(base)
|
|
17
|
+
base.instance_variable_set(:@__exposed_methods__, @__exposed_methods__.dup)
|
|
18
|
+
base.instance_variable_set(:@__parent_accessor__, @__parent_accessor__)
|
|
19
|
+
base.instance_variable_set(:@__key_accessor__, @__key_accessor__)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :__parent_accessor__, :__key_accessor__
|
|
23
|
+
|
|
24
|
+
def __exposed_methods__
|
|
25
|
+
@__exposed_methods__ ||= []
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def expose(*method_names)
|
|
29
|
+
raise ArgumentError, 'at least one argument expected' if method_names.empty?
|
|
30
|
+
unless method_names.each { |method_name| method_name.is_a?(Symbol) || method_name.is_a?(String) }
|
|
31
|
+
raise 'only symbols or strings expected'
|
|
32
|
+
end
|
|
33
|
+
@__exposed_methods__ ||= []
|
|
34
|
+
@__exposed_methods__.concat(method_names.map(&:to_s))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def parent_accessor(method_name = nil)
|
|
38
|
+
unless method_name.is_a?(Symbol) || method_name.is_a?(String)
|
|
39
|
+
raise ArgumentError, "'parent_accessor' expects a method name as a string for symbol"
|
|
40
|
+
end
|
|
41
|
+
@__parent_accessor__ = method_name.to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def key_accessor(method_name = nil)
|
|
45
|
+
unless method_name.is_a?(Symbol) || method_name.is_a?(String)
|
|
46
|
+
raise ArgumentError, "'parent_accessor' expects a method name as a string for symbol"
|
|
47
|
+
end
|
|
48
|
+
@__key_accessor__ = method_name.to_s
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
module IncludedInstanceMethods
|
|
54
|
+
|
|
55
|
+
def __exposed_methods__
|
|
56
|
+
@__exposed_methods__ ||= []
|
|
57
|
+
@__exposed_methods__ + self.class.__exposed_methods__
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def __parent__
|
|
61
|
+
raise 'parent_accessor not defined' unless __parent_accessor__
|
|
62
|
+
__send__(__parent_accessor__)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def __parent_accessor__
|
|
66
|
+
@__parent_accessor__ || self.class.__parent_accessor__
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def __key__
|
|
70
|
+
raise 'key_accessor not defined' unless __key_accessor__
|
|
71
|
+
__send__(__key_accessor__)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def __key_accessor__
|
|
75
|
+
@__key_accessor__ || self.class.__key_accessor__
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def __sumac_exposed_object__
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def expose(*method_names)
|
|
82
|
+
raise ArgumentError, 'at least one argument expected' if method_names.empty?
|
|
83
|
+
unless method_names.each { |method_name| method_name.is_a?(Symbol) || method_name.is_a?(String) }
|
|
84
|
+
raise 'only symbols or strings expected'
|
|
85
|
+
end
|
|
86
|
+
@__exposed_methods__ ||= []
|
|
87
|
+
@__exposed_methods__.concat(method_names.map(&:to_s))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def parent_accessor(method_name = nil)
|
|
91
|
+
unless method_name.is_a?(Symbol) || method_name.is_a?(String)
|
|
92
|
+
raise ArgumentError, "'parent_accessor' expects a method name as a string for symbol"
|
|
93
|
+
end
|
|
94
|
+
@__parent_accessor__ = method_name.to_s
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def key_accessor(method_name = nil)
|
|
98
|
+
unless method_name.is_a?(Symbol) || method_name.is_a?(String)
|
|
99
|
+
raise ArgumentError, "'parent_accessor' expects a method name as a string for symbol"
|
|
100
|
+
end
|
|
101
|
+
@__key_accessor__ = method_name.to_s
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
module ExtendedClassMethods
|
|
108
|
+
|
|
109
|
+
def inherited(base)
|
|
110
|
+
base.instance_variable_set(:@__exposed_methods__, @__exposed_methods__.dup)
|
|
111
|
+
base.instance_variable_set(:@__parent_accessor__, @__parent_accessor__)
|
|
112
|
+
base.instance_variable_set(:@__key_accessor__, @__key_accessor__)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def __exposed_methods__
|
|
116
|
+
@__exposed_methods__ ||= []
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def __parent__
|
|
120
|
+
raise 'parent_accessor not defined' unless @__parent_accessor__
|
|
121
|
+
__send__(@__parent_accessor__)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def __key__
|
|
125
|
+
raise 'key_accessor not defined' unless @__key_accessor__
|
|
126
|
+
__send__(@__key_accessor__)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def __sumac_exposed_object__
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def expose(*method_names)
|
|
133
|
+
raise ArgumentError, 'at least one argument expected' if method_names.empty?
|
|
134
|
+
unless method_names.each { |method_name| method_name.is_a?(Symbol) || method_name.is_a?(String) }
|
|
135
|
+
raise 'only symbols or strings expected'
|
|
136
|
+
end
|
|
137
|
+
@__exposed_methods__ ||= []
|
|
138
|
+
@__exposed_methods__.concat(method_names.map(&:to_s))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def parent_accessor(method_name = nil)
|
|
142
|
+
unless method_name.is_a?(Symbol) || method_name.is_a?(String)
|
|
143
|
+
raise ArgumentError, "'parent_accessor' expects a method name as a string for symbol"
|
|
144
|
+
end
|
|
145
|
+
@__parent_accessor__ = method_name.to_s
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def key_accessor(method_name = nil)
|
|
149
|
+
unless method_name.is_a?(Symbol) || method_name.is_a?(String)
|
|
150
|
+
raise ArgumentError, "'parent_accessor' expects a method name as a string for symbol"
|
|
151
|
+
end
|
|
152
|
+
@__key_accessor__ = method_name.to_s
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class Sumac
|
|
2
|
+
class Handshake
|
|
3
|
+
include Emittable
|
|
4
|
+
|
|
5
|
+
def initialize(connection)
|
|
6
|
+
raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
|
|
7
|
+
@connection = connection
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def send_compatibility_notification
|
|
11
|
+
message = Message::Exchange::CompatibilityNotification.new(@connection)
|
|
12
|
+
message.protocol_version = 1
|
|
13
|
+
@connection.messenger.send(message)
|
|
14
|
+
nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def send_initialization_notification
|
|
18
|
+
message = Message::Exchange::InitializationNotification.new(@connection)
|
|
19
|
+
begin
|
|
20
|
+
message.entry = @connection.local_entry
|
|
21
|
+
rescue UnexposableObjectError
|
|
22
|
+
@connection.to(:kill)
|
|
23
|
+
else
|
|
24
|
+
@connection.messenger.send(message)
|
|
25
|
+
end
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def receive(message)
|
|
30
|
+
case message
|
|
31
|
+
when Message::Exchange::CompatibilityNotification
|
|
32
|
+
raise MessageError unless @connection.at?(:compatibility_handshake)
|
|
33
|
+
#unless message.protocol_version == 1
|
|
34
|
+
# @connection.to(:kill)
|
|
35
|
+
#end
|
|
36
|
+
@connection.to(:initialization_handshake)
|
|
37
|
+
when Message::Exchange::InitializationNotification
|
|
38
|
+
raise MessageError unless @connection.at?(:initialization_handshake)
|
|
39
|
+
@connection.to(:active)
|
|
40
|
+
@connection.remote_entry.set(message.entry)
|
|
41
|
+
else
|
|
42
|
+
raise MessageError
|
|
43
|
+
end
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
class Sumac
|
|
2
|
+
class IDAllocator
|
|
3
|
+
|
|
4
|
+
def self.valid?(id)
|
|
5
|
+
id.is_a?(Integer) && id >= 0
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@allocated_ranges = []
|
|
10
|
+
@mutex = Mutex.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def valid?(id)
|
|
14
|
+
self.class.valid?(id)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def allocate
|
|
18
|
+
@mutex.lock
|
|
19
|
+
if @allocated_ranges.empty?
|
|
20
|
+
id = 0
|
|
21
|
+
elsif @allocated_ranges.first.first == 0
|
|
22
|
+
id = @allocated_ranges.first.last.succ
|
|
23
|
+
else
|
|
24
|
+
id = 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
preceding_range = @allocated_ranges.take_while{ |range| range.last < id }.last
|
|
28
|
+
preceding_range_index = @allocated_ranges.find_index(preceding_range) if preceding_range
|
|
29
|
+
|
|
30
|
+
following_range_index = @allocated_ranges.find_index { |range| range.first > id }
|
|
31
|
+
following_range = @allocated_ranges[following_range_index] if following_range_index
|
|
32
|
+
|
|
33
|
+
immediately_preceding_range = preceding_range if preceding_range && preceding_range.last.succ == id
|
|
34
|
+
immediately_following_range = following_range if following_range && following_range.first.pred == id
|
|
35
|
+
|
|
36
|
+
if immediately_preceding_range && immediately_following_range
|
|
37
|
+
@allocated_ranges[preceding_range_index] = (preceding_range.first..following_range.last)
|
|
38
|
+
@allocated_ranges.delete(following_range)
|
|
39
|
+
elsif immediately_preceding_range
|
|
40
|
+
@allocated_ranges[preceding_range_index] = (preceding_range.first..id)
|
|
41
|
+
elsif immediately_following_range
|
|
42
|
+
@allocated_ranges[following_range_index] = (id..following_range.last)
|
|
43
|
+
else
|
|
44
|
+
new_index = preceding_range ? preceding_range_index.succ : 0
|
|
45
|
+
@allocated_ranges.insert(new_index, (id..id))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
@mutex.unlock
|
|
49
|
+
|
|
50
|
+
if block_given?
|
|
51
|
+
begin
|
|
52
|
+
yield(id)
|
|
53
|
+
ensure
|
|
54
|
+
free(id)
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
id
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def free(id)
|
|
62
|
+
@mutex.lock
|
|
63
|
+
raise unless valid?(id) && allocated?(id)
|
|
64
|
+
|
|
65
|
+
enclosing_range = enclosing_range(id)
|
|
66
|
+
enclosing_range_index = @allocated_ranges.find_index(enclosing_range)
|
|
67
|
+
|
|
68
|
+
if enclosing_range.size == 1
|
|
69
|
+
@allocated_ranges.delete(enclosing_range)
|
|
70
|
+
elsif enclosing_range.first == id
|
|
71
|
+
@allocated_ranges[enclosing_range_index] = (enclosing_range.first.succ..enclosing_range.last)
|
|
72
|
+
elsif enclosing_range.last == id
|
|
73
|
+
@allocated_ranges[enclosing_range_index] = (enclosing_range.first..enclosing_range.last.pred)
|
|
74
|
+
else
|
|
75
|
+
@allocated_ranges[enclosing_range_index] = (enclosing_range.first..id.pred)
|
|
76
|
+
@allocated_ranges.insert(enclosing_range_index.succ, (id.succ..enclosing_range.last))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
@mutex.unlock
|
|
80
|
+
nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def allocated?(id)
|
|
84
|
+
enclosing_range(id)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def free?(id)
|
|
90
|
+
!allocated?(id)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def enclosing_range(id)
|
|
94
|
+
possible_range = @allocated_ranges.find{ |range| range.last >= id }
|
|
95
|
+
return possible_range if possible_range && possible_range.first <= id
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Sumac
|
|
2
|
+
class LocalReference < Reference
|
|
3
|
+
|
|
4
|
+
attr_reader :exposed_object
|
|
5
|
+
|
|
6
|
+
def initialize(connection, exposed_id, exposed_object)
|
|
7
|
+
super(connection, exposed_id)
|
|
8
|
+
@exposed_object = exposed_object
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def remove
|
|
12
|
+
@connection.local_references.remove(self)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
class Sumac
|
|
2
|
+
class LocalReferences
|
|
3
|
+
|
|
4
|
+
def initialize(connection)
|
|
5
|
+
raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
|
|
6
|
+
@connection = connection
|
|
7
|
+
@id_allocator = IDAllocator.new
|
|
8
|
+
@exposed_id_table = {}
|
|
9
|
+
@native_id_table = {}
|
|
10
|
+
@transaction = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def detach
|
|
14
|
+
@exposed_id_table.values.each { |reference| reference.detach }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def destroy
|
|
18
|
+
@exposed_id_table.values.each { |reference| reference.destroy }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def from_id(exposed_id)
|
|
22
|
+
raise unless @id_allocator.valid?(exposed_id)
|
|
23
|
+
reference = @exposed_id_table[exposed_id]
|
|
24
|
+
reference
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def from_object(exposed_object)
|
|
28
|
+
raise unless exposed_object.is_a?(ExposedObject)
|
|
29
|
+
reference = find(exposed_object) || create(exposed_object)
|
|
30
|
+
reference
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def remove(reference)
|
|
34
|
+
@exposed_id_table.delete(reference.exposed_id)
|
|
35
|
+
references = @native_id_table[reference.exposed_object.__native_id__]
|
|
36
|
+
references.delete(reference)
|
|
37
|
+
@native_id_table.delete(reference.exposed_object.__native_id__) if references.empty?
|
|
38
|
+
@id_allocator.free(reference.exposed_id)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def rollback_transaction
|
|
42
|
+
@transaction.each { |reference| reference.quiet_forget }
|
|
43
|
+
@transaction = []
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def commit_transaction
|
|
47
|
+
@transaction = nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def start_transaction
|
|
51
|
+
@transaction = []
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def create(exposed_object)
|
|
57
|
+
new_exposed_id = @id_allocator.allocate
|
|
58
|
+
new_reference = LocalReference.new(@connection, new_exposed_id, exposed_object)
|
|
59
|
+
@exposed_id_table[new_exposed_id] = new_reference
|
|
60
|
+
references = @native_id_table[exposed_object.__native_id__]
|
|
61
|
+
if references
|
|
62
|
+
references << new_reference
|
|
63
|
+
else
|
|
64
|
+
@native_id_table[exposed_object.__native_id__] = [new_reference]
|
|
65
|
+
end
|
|
66
|
+
@transaction << new_reference if @transaction
|
|
67
|
+
new_reference
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def find(exposed_object)
|
|
71
|
+
references = @native_id_table[exposed_object.__native_id__]
|
|
72
|
+
return nil unless references
|
|
73
|
+
callable_references = references.select { |reference| reference.callable? }
|
|
74
|
+
raise if callable_references.length > 1
|
|
75
|
+
reference = callable_references.first
|
|
76
|
+
reference
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Sumac
|
|
2
|
+
class Message
|
|
3
|
+
|
|
4
|
+
def self.from_json(connection, json)
|
|
5
|
+
json_structure = JSON.parse(json)
|
|
6
|
+
from_json_structure(connection, json_structure)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(connection)
|
|
10
|
+
raise "argument 'connection' must be a Connection" unless connection.is_a?(Connection)
|
|
11
|
+
@connection = connection
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_json
|
|
15
|
+
to_json_structure.to_json
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class Sumac
|
|
2
|
+
class Message
|
|
3
|
+
class Exchange < Message
|
|
4
|
+
|
|
5
|
+
def self.from_json_structure(connection, json_structure)
|
|
6
|
+
raise MessageError unless json_structure.is_a?(Hash) && json_structure['message_type'] == 'exchange'
|
|
7
|
+
exchange_class =
|
|
8
|
+
case json_structure['exchange_type']
|
|
9
|
+
when 'compatibility_notification'
|
|
10
|
+
CompatibilityNotification
|
|
11
|
+
when 'initialization_notification'
|
|
12
|
+
InitializationNotification
|
|
13
|
+
when 'shutdown_notification'
|
|
14
|
+
ShutdownNotification
|
|
15
|
+
when 'forget_notification'
|
|
16
|
+
ForgetNotification
|
|
17
|
+
when 'call_request'
|
|
18
|
+
CallRequest
|
|
19
|
+
when 'call_response'
|
|
20
|
+
CallResponse
|
|
21
|
+
else
|
|
22
|
+
raise MessageError
|
|
23
|
+
end
|
|
24
|
+
exchange = exchange_class.from_json_structure(connection, json_structure)
|
|
25
|
+
exchange
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|