ib_ruby_proxy 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +77 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.rubocop.yml +143 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +130 -0
- data/Rakefile +12 -0
- data/bin/console +14 -0
- data/bin/generate_ruby_classes +13 -0
- data/bin/ibproxy +32 -0
- data/bin/setup +8 -0
- data/docs/diagrams.key +0 -0
- data/docs/images/architecture.png +0 -0
- data/examples/common.rb +14 -0
- data/examples/plain_req_historical_ticks.rb +19 -0
- data/examples/req_contract_details.rb +9 -0
- data/examples/req_historical_bars_data.rb +10 -0
- data/examples/req_historical_ticks.rb +10 -0
- data/examples/req_tick_by_tick_data.rb +9 -0
- data/ib_ruby_proxy.gemspec +43 -0
- data/lib/ib_ruby_proxy.rb +35 -0
- data/lib/ib_ruby_proxy/client/callbacks_response_handler.rb +135 -0
- data/lib/ib_ruby_proxy/client/client.rb +69 -0
- data/lib/ib_ruby_proxy/client/ib/bar.rb +36 -0
- data/lib/ib_ruby_proxy/client/ib/combo_leg.rb +36 -0
- data/lib/ib_ruby_proxy/client/ib/contract.rb +56 -0
- data/lib/ib_ruby_proxy/client/ib/contract_details.rb +100 -0
- data/lib/ib_ruby_proxy/client/ib/delta_neutral_contract.rb +26 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick.rb +26 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick_bid_ask.rb +32 -0
- data/lib/ib_ruby_proxy/client/ib/historical_tick_last.rb +32 -0
- data/lib/ib_ruby_proxy/client/ib/order.rb +262 -0
- data/lib/ib_ruby_proxy/client/ib/tick_attrib_bid_ask.rb +24 -0
- data/lib/ib_ruby_proxy/client/ib/tick_attrib_last.rb +24 -0
- data/lib/ib_ruby_proxy/client/ib_callbacks_observer.rb +25 -0
- data/lib/ib_ruby_proxy/config.yml +43 -0
- data/lib/ib_ruby_proxy/server/ext/array.rb +22 -0
- data/lib/ib_ruby_proxy/server/ext/enum.rb +20 -0
- data/lib/ib_ruby_proxy/server/ext/idempotent_types.rb +23 -0
- data/lib/ib_ruby_proxy/server/ib/bar.rb +21 -0
- data/lib/ib_ruby_proxy/server/ib/combo_leg.rb +21 -0
- data/lib/ib_ruby_proxy/server/ib/contract.rb +31 -0
- data/lib/ib_ruby_proxy/server/ib/contract_details.rb +53 -0
- data/lib/ib_ruby_proxy/server/ib/delta_neutral_contract.rb +16 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick.rb +16 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick_bid_ask.rb +19 -0
- data/lib/ib_ruby_proxy/server/ib/historical_tick_last.rb +19 -0
- data/lib/ib_ruby_proxy/server/ib/order.rb +134 -0
- data/lib/ib_ruby_proxy/server/ib/tick_attrib_bid_ask.rb +15 -0
- data/lib/ib_ruby_proxy/server/ib/tick_attrib_last.rb +15 -0
- data/lib/ib_ruby_proxy/server/ib_client_adapter.rb +51 -0
- data/lib/ib_ruby_proxy/server/ib_proxy_service.rb +85 -0
- data/lib/ib_ruby_proxy/server/ib_ruby_class_files_generator.rb +77 -0
- data/lib/ib_ruby_proxy/server/ib_ruby_class_source_generator.rb +155 -0
- data/lib/ib_ruby_proxy/server/ib_wrapper_adapter.rb +47 -0
- data/lib/ib_ruby_proxy/server/reflection/ib_class.rb +62 -0
- data/lib/ib_ruby_proxy/server/reflection/ib_field.rb +60 -0
- data/lib/ib_ruby_proxy/util/has_logger.rb +10 -0
- data/lib/ib_ruby_proxy/util/string_utils.rb +29 -0
- data/lib/ib_ruby_proxy/version.rb +3 -0
- data/lib/server.rb +4 -0
- data/sandbox/drb_performance/client.rb +46 -0
- data/sandbox/drb_performance/server.rb +26 -0
- data/vendor/TwsApi.jar +0 -0
- metadata +226 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
# ---------------------------------------------
|
2
|
+
# File generated automatically by ib_ruby_proxy
|
3
|
+
# ---------------------------------------------
|
4
|
+
|
5
|
+
java_import "com.ib.client.TickAttribBidAsk"
|
6
|
+
|
7
|
+
class Java::ComIbClient::TickAttribBidAsk
|
8
|
+
def to_ruby
|
9
|
+
ruby_object = IbRubyProxy::Client::Ib::TickAttribBidAsk.new
|
10
|
+
ruby_object.bid_past_low = bidPastLow().to_ruby
|
11
|
+
ruby_object.ask_past_high = askPastHigh().to_ruby
|
12
|
+
|
13
|
+
ruby_object
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# ---------------------------------------------
|
2
|
+
# File generated automatically by ib_ruby_proxy
|
3
|
+
# ---------------------------------------------
|
4
|
+
|
5
|
+
java_import "com.ib.client.TickAttribLast"
|
6
|
+
|
7
|
+
class Java::ComIbClient::TickAttribLast
|
8
|
+
def to_ruby
|
9
|
+
ruby_object = IbRubyProxy::Client::Ib::TickAttribLast.new
|
10
|
+
ruby_object.past_limit = pastLimit().to_ruby
|
11
|
+
ruby_object.unreported = unreported().to_ruby
|
12
|
+
|
13
|
+
ruby_object
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
java_import 'com.ib.client.EClient'
|
2
|
+
|
3
|
+
module IbRubyProxy
|
4
|
+
module Server
|
5
|
+
# This is the Ruby representation of the IB Java +EClient+ class. It adapts ruby invocations
|
6
|
+
# and arguments to invoke the corresponding Java API methods.
|
7
|
+
#
|
8
|
+
# It is the object DRb clients get when connecting to the {IbProxyService proxy service}.
|
9
|
+
#
|
10
|
+
# Mimicking how the Java API works, it collaborates with an {IbWrapperAdapter} that
|
11
|
+
# corresponds with an +EWrapper+ in the Java world. It works by observing callbacks
|
12
|
+
# in this wrapper.
|
13
|
+
#
|
14
|
+
# The usage of observers as a communication mechanism is because it is supported
|
15
|
+
# by DRb and, being DRb a standard implemented in JRuby, enables communicating Ruby and JRuby.
|
16
|
+
# If supporting other rubies was not required this level of indirection would be unnecessary.
|
17
|
+
class IbClientAdapter
|
18
|
+
extend IbRubyProxy::Util::StringUtils
|
19
|
+
|
20
|
+
attr_reader :ib_client, :ib_wrapper_adapter
|
21
|
+
|
22
|
+
# @param [com.ib.client.EClient] ib_client IB +EClient+ object
|
23
|
+
# @param [IbWrapperAdapter] ib_wrapper_adapter
|
24
|
+
def initialize(ib_client, ib_wrapper_adapter)
|
25
|
+
@ib_client = ib_client
|
26
|
+
@ib_wrapper_adapter = ib_wrapper_adapter
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param [IbRubyProxy::Client::IbCallbacksObserver] ib_callbacks_observer
|
30
|
+
def add_ib_callbacks_observer(ib_callbacks_observer)
|
31
|
+
ib_wrapper_adapter.add_observer(ib_callbacks_observer)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @private
|
35
|
+
def self.define_ruby_method_for(java_method)
|
36
|
+
ruby_method_name = to_underscore(java_method.name)
|
37
|
+
|
38
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
39
|
+
def #{ruby_method_name}(*arguments)
|
40
|
+
ib_arguments = arguments.collect(&:to_ib)
|
41
|
+
@ib_client.#{java_method.name} *ib_arguments
|
42
|
+
end
|
43
|
+
RUBY
|
44
|
+
end
|
45
|
+
|
46
|
+
EClient.java_class.declared_instance_methods.each do |java_method|
|
47
|
+
define_ruby_method_for(java_method)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'ib_ruby_proxy/version'
|
2
|
+
require_relative 'ib_wrapper_adapter'
|
3
|
+
require_relative 'ib_client_adapter'
|
4
|
+
require 'drb'
|
5
|
+
|
6
|
+
java_import 'com.ib.client.EClientSocket'
|
7
|
+
java_import 'com.ib.client.EJavaSignal'
|
8
|
+
java_import 'com.ib.client.EClientSocket'
|
9
|
+
java_import 'com.ib.client.EReader'
|
10
|
+
|
11
|
+
module IbRubyProxy
|
12
|
+
module Server
|
13
|
+
# Proxy service for invoking IB api through
|
14
|
+
# {https://ruby-doc.org/stdlib-2.6.1/libdoc/drb/rdoc/DRb.html DRb}
|
15
|
+
#
|
16
|
+
# The proxy does essentially 2 things:
|
17
|
+
#
|
18
|
+
# * Starts a DRb process you can connect to invoke the IB api. This will expose an {IbClientAdapter}
|
19
|
+
# object to its clients
|
20
|
+
# * Starts an IB message-processing thread that will dispatch messages sent to IB client app (
|
21
|
+
# gateway or TWS)
|
22
|
+
class IbProxyService
|
23
|
+
DEFAULT_IB_GATEWAY_PORT = 4002
|
24
|
+
DEFAULT_DRB_PORT = 1992
|
25
|
+
|
26
|
+
# @param [String] ib_host Hostname for the IB client app (gateway or TWS). Default +localhost+
|
27
|
+
# @param [Integer] ib_port Port for hte IB client app (gateway or TWS). Default +4002+ (gateway)
|
28
|
+
# @param [String] drb_host Hostname for the DRB process. Default +localhost+
|
29
|
+
# @param [Integer] drb_port Port for the . Default +1992+
|
30
|
+
def initialize(ib_host: 'localhost', ib_port: DEFAULT_IB_GATEWAY_PORT,
|
31
|
+
drb_host: 'localhost', drb_port: DEFAULT_DRB_PORT)
|
32
|
+
@ib_host = ib_host
|
33
|
+
@ib_port = ib_port
|
34
|
+
@drb_host = drb_host
|
35
|
+
@drb_port = drb_port
|
36
|
+
|
37
|
+
@wrapper = IbRubyProxy::Server::IbWrapperAdapter.new
|
38
|
+
@client = wrapper.client
|
39
|
+
@signal = wrapper.signal
|
40
|
+
|
41
|
+
connect
|
42
|
+
end
|
43
|
+
|
44
|
+
# Connects to IB and starts the DRb process
|
45
|
+
#
|
46
|
+
# Clients of the DRb service will get an {IbClientAdapter} object to interact with the IB api
|
47
|
+
# @return [void]
|
48
|
+
def start
|
49
|
+
DRb.start_service("druby://#{drb_host}:#{drb_port}", ib_client_adapter, verbose: true)
|
50
|
+
start_ib_message_processing_thread
|
51
|
+
puts "Ib proxy server started at druby://#{drb_host}:#{drb_port}. Connected to IB at"\
|
52
|
+
" #{ib_host}:#{ib_port}"
|
53
|
+
DRb.thread.join
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
attr_reader :wrapper, :client, :signal, :ib_host, :ib_port, :drb_host, :drb_port
|
59
|
+
|
60
|
+
def start_ib_message_processing_thread
|
61
|
+
reader = EReader.new(client, signal)
|
62
|
+
reader.start
|
63
|
+
|
64
|
+
Thread.new do
|
65
|
+
while client.isConnected
|
66
|
+
signal.waitForSignal
|
67
|
+
begin
|
68
|
+
reader.processMsgs
|
69
|
+
rescue StandardError => e
|
70
|
+
puts "Error while processing ib message: #{e}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def connect
|
77
|
+
client.eConnect(ib_host, ib_port, 2)
|
78
|
+
end
|
79
|
+
|
80
|
+
def ib_client_adapter
|
81
|
+
@ib_client_adapter ||= IbRubyProxy::Server::IbClientAdapter.new(client, wrapper)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module IbRubyProxy
|
2
|
+
module Server
|
3
|
+
# Source code generator that interacts with {IbRubyClassSourceGenerator} and writes down the
|
4
|
+
# actual files with the source for both Ruby classes representing IB classes and Ruby extensions
|
5
|
+
# for these.
|
6
|
+
class IbRubyClassFilesGenerator
|
7
|
+
attr_reader :client_code_dir, :server_code_dir
|
8
|
+
|
9
|
+
# @param [String] client_code_dir
|
10
|
+
# @param [String] server_code_dir
|
11
|
+
def initialize(client_code_dir:, server_code_dir:)
|
12
|
+
@client_code_dir = client_code_dir
|
13
|
+
@server_code_dir = server_code_dir
|
14
|
+
|
15
|
+
import_ruby_classes
|
16
|
+
end
|
17
|
+
|
18
|
+
# Generate client files and server class extensions
|
19
|
+
#
|
20
|
+
# It will format the generated code with {https://github.com/ruby-formatter/rufo Rufo}.
|
21
|
+
#
|
22
|
+
# @see IbRubyClassSourceGenerator#ruby_class_source
|
23
|
+
# @see IbRubyClassSourceGenerator#ib_class_extension_source
|
24
|
+
def generate_all
|
25
|
+
do_generate_all
|
26
|
+
format_code
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def import_ruby_classes
|
32
|
+
ruby_classes.each do |class_name|
|
33
|
+
java_import "com.ib.client.#{class_name}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def ruby_classes
|
38
|
+
@ruby_classes ||= IbRubyProxy.config['classes']
|
39
|
+
end
|
40
|
+
|
41
|
+
def do_generate_all
|
42
|
+
ruby_classes.each do |class_name|
|
43
|
+
generate_files class_name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_files(class_name)
|
48
|
+
ib_class = Java::ComIbClient.const_get(class_name)
|
49
|
+
generator = IbRubyClassSourceGenerator.new(ib_class,
|
50
|
+
namespace: 'IbRubyProxy::Client::Ib')
|
51
|
+
|
52
|
+
file_name = "#{IbRubyProxy::Util::StringUtils.to_underscore(class_name)}.rb"
|
53
|
+
generate_client_file(generator, file_name)
|
54
|
+
generate_server_file(generator, file_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def generate_client_file(generator, file_name)
|
58
|
+
target_file = File.join(client_code_dir, file_name)
|
59
|
+
puts "Generating client file: #{target_file}..."
|
60
|
+
File.open(target_file, 'w') { |file| file.write(generator.ruby_class_source) }
|
61
|
+
end
|
62
|
+
|
63
|
+
def generate_server_file(generator, file_name)
|
64
|
+
target_file = File.join(server_code_dir, file_name)
|
65
|
+
puts "Generating server file: #{target_file}..."
|
66
|
+
File.open(target_file, 'w') { |file| file.write(generator.ib_class_extension_source) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def format_code
|
70
|
+
[server_code_dir, client_code_dir].each do |dir|
|
71
|
+
puts "Formatting #{dir}..."
|
72
|
+
system "rufo #{dir}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module IbRubyProxy
|
2
|
+
module Server
|
3
|
+
# Given a value object class from Interactive Broker API, this generator can build Ruby source
|
4
|
+
# code for:
|
5
|
+
#
|
6
|
+
# * A ruby class to manipulate the same class in Ruby
|
7
|
+
# * An extension to the original Java class for converting instances into Ruby
|
8
|
+
class IbRubyClassSourceGenerator
|
9
|
+
include IbRubyProxy::Util::StringUtils
|
10
|
+
|
11
|
+
attr_reader :ib_class, :namespace_list
|
12
|
+
|
13
|
+
# @param [Class] ib_class Class from IB broker to mimic in Ruby. It is meant to be used with
|
14
|
+
# value objects, as only properties are translated. That is the case for classes that
|
15
|
+
# represent either arguments or returned values (via callbacks) in the API.
|
16
|
+
# @param [String] namespace The namespace to generate the classes in. Default
|
17
|
+
# +IbRubyProxy::Client::Ib+
|
18
|
+
def initialize(ib_class, namespace: 'IbRubyProxy::Client::Ib')
|
19
|
+
@ib_class = Reflection::IbClass.new(ib_class)
|
20
|
+
@namespace_list = namespace.split('::')
|
21
|
+
end
|
22
|
+
|
23
|
+
# Source for a ruby class translates into Ruby the Java properties of the target
|
24
|
+
# ib class.
|
25
|
+
#
|
26
|
+
# It generates a {Struct} with the list of properties, that admits a keyword-based
|
27
|
+
# constructor, and that includes a +to_ib+ method for converting the ruby back into its
|
28
|
+
# original Java counterpart.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
def ruby_class_source
|
32
|
+
<<-RUBY
|
33
|
+
#{header}
|
34
|
+
|
35
|
+
#{generate_ruby_class}
|
36
|
+
RUBY
|
37
|
+
end
|
38
|
+
|
39
|
+
# Source for a ruby class that extends the original IB Java class with a +to_ruby+ method,
|
40
|
+
# to convert Java Ib objects into their Ruby counterparts generated in {#ruby_class_source}
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
def ib_class_extension_source
|
44
|
+
<<-RUBY
|
45
|
+
#{header}
|
46
|
+
|
47
|
+
#{generate_ib_class_extension}
|
48
|
+
RUBY
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def header
|
54
|
+
<<-RUBY
|
55
|
+
# ---------------------------------------------
|
56
|
+
# File generated automatically by ib_ruby_proxy
|
57
|
+
# ---------------------------------------------
|
58
|
+
RUBY
|
59
|
+
end
|
60
|
+
|
61
|
+
def generate_ib_class_extension
|
62
|
+
<<-RUBY
|
63
|
+
java_import "com.ib.client.#{ib_class.name}"
|
64
|
+
|
65
|
+
class #{ib_class.full_name}
|
66
|
+
#{generate_to_ruby_method}
|
67
|
+
end
|
68
|
+
RUBY
|
69
|
+
end
|
70
|
+
|
71
|
+
def generate_ruby_class
|
72
|
+
<<-RUBY
|
73
|
+
#{generate_namespace_open}
|
74
|
+
|
75
|
+
#{generate_class_declaration}
|
76
|
+
#{generate_constructor}
|
77
|
+
#{generate_to_ib_method}
|
78
|
+
end
|
79
|
+
|
80
|
+
#{generate_namespace_close}
|
81
|
+
RUBY
|
82
|
+
end
|
83
|
+
|
84
|
+
def generate_namespace_open
|
85
|
+
namespace_list.collect { |namespace| "module #{namespace}" }.join("\n")
|
86
|
+
end
|
87
|
+
|
88
|
+
def generate_namespace_close
|
89
|
+
namespace_list.length.times.collect { 'end' }.join("\n")
|
90
|
+
end
|
91
|
+
|
92
|
+
def generate_class_declaration
|
93
|
+
struct_init_properties = ib_class.ruby_property_names.collect { |property| ":#{property}" }
|
94
|
+
.join(', ')
|
95
|
+
struct_init_properties << ', keyword_init: true'
|
96
|
+
|
97
|
+
<<-RUBY
|
98
|
+
#{ib_class.name} = Struct.new(#{struct_init_properties}) do
|
99
|
+
RUBY
|
100
|
+
end
|
101
|
+
|
102
|
+
def generate_constructor
|
103
|
+
constructor_declarations = ib_class.zipped_ruby_and_java_properties
|
104
|
+
.collect do |ruby_property, java_field|
|
105
|
+
"#{ruby_property}: #{java_field.default_value_as_string}"
|
106
|
+
end
|
107
|
+
|
108
|
+
assignment_statements = ib_class.ruby_property_names.collect do |ruby_property|
|
109
|
+
<<-RUBY
|
110
|
+
self.#{ruby_property} = #{ruby_property}
|
111
|
+
RUBY
|
112
|
+
end
|
113
|
+
<<-RUBY
|
114
|
+
def initialize(#{constructor_declarations.join(', ')})
|
115
|
+
#{assignment_statements.join('')}
|
116
|
+
end
|
117
|
+
RUBY
|
118
|
+
end
|
119
|
+
|
120
|
+
def generate_to_ib_method
|
121
|
+
property_copy_sentences = ib_class.zipped_ruby_and_java_properties
|
122
|
+
.collect do |ruby_property, java_field|
|
123
|
+
<<-RUBY
|
124
|
+
ib_object.#{java_field.name}(#{ruby_property}).to_java
|
125
|
+
RUBY
|
126
|
+
end
|
127
|
+
|
128
|
+
<<-RUBY
|
129
|
+
def to_ib
|
130
|
+
ib_object = #{ib_class.klass.name}.new
|
131
|
+
#{property_copy_sentences.join('')}
|
132
|
+
ib_object
|
133
|
+
end
|
134
|
+
RUBY
|
135
|
+
end
|
136
|
+
|
137
|
+
def generate_to_ruby_method
|
138
|
+
property_copy_sentences = ib_class.zipped_ruby_and_java_properties
|
139
|
+
.collect do |ruby_property, java_field|
|
140
|
+
<<-RUBY
|
141
|
+
ruby_object.#{ruby_property} = #{java_field.name}().to_ruby
|
142
|
+
RUBY
|
143
|
+
end
|
144
|
+
|
145
|
+
<<-RUBY
|
146
|
+
def to_ruby
|
147
|
+
ruby_object = #{namespace_list.join('::')}::#{ib_class.name}.new
|
148
|
+
#{property_copy_sentences.join('')}
|
149
|
+
ruby_object
|
150
|
+
end
|
151
|
+
RUBY
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
java_import 'com.ib.client.EWrapper'
|
2
|
+
require 'drb/observer'
|
3
|
+
|
4
|
+
module IbRubyProxy
|
5
|
+
module Server
|
6
|
+
# Ruby representation of the IB +EWrapper+ class. It delegates received callbacks by
|
7
|
+
# triggering an observer notification. It will translate the name of the java method to
|
8
|
+
# Ruby (underscore), as well as translate the parameters from IB to the Ruby world.
|
9
|
+
#
|
10
|
+
# @see IbClientAdapter
|
11
|
+
class IbWrapperAdapter
|
12
|
+
# include DRb::DRbObservable
|
13
|
+
include EWrapper
|
14
|
+
include DRb::DRbObservable
|
15
|
+
include IbRubyProxy::Util::HasLogger
|
16
|
+
extend IbRubyProxy::Util::StringUtils
|
17
|
+
|
18
|
+
attr_reader :signal, :client
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@signal = EJavaSignal.new
|
22
|
+
@client = EClientSocket.new(self, @signal)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @private
|
26
|
+
def self.define_ruby_method_for(java_method)
|
27
|
+
ruby_method_name = to_underscore(java_method.name)
|
28
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
29
|
+
def #{java_method.name}(*arguments)
|
30
|
+
ruby_arguments = arguments.collect(&:to_ruby)
|
31
|
+
if count_observers > 0
|
32
|
+
changed
|
33
|
+
notify_observers *(["#{ruby_method_name}"] + ruby_arguments)
|
34
|
+
else
|
35
|
+
logger.debug "Received #{ruby_method_name}"
|
36
|
+
logger.debug ruby_arguments.inspect
|
37
|
+
end
|
38
|
+
end
|
39
|
+
RUBY
|
40
|
+
end
|
41
|
+
|
42
|
+
EWrapper.java_class.declared_instance_methods.each do |java_method|
|
43
|
+
define_ruby_method_for(java_method)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|