require_relative 'abstract/abstract_invocation_context' require_relative '../../core/interpreter/interpreter' require_relative '../../core/exceptions/exception_thrower' require_relative 'invocation_context_iterator' class InvocationContext < AbstractInvocationContext include Enumerable def initialize(runtime_name, connection_type, tcp_ip_address, command, is_executed = false) @is_executed = is_executed @runtime_name = runtime_name @connection_type = connection_type @tcp_ip_address = tcp_ip_address @current_command = command @response_command = nil @interpreter = Interpreter.new ObjectSpace.define_finalizer(self, self.finalize(@current_command, @is_executed, @interpreter, @connection_type, @tcp_ip_address)) end def finalize(command, is_executed, interpreter, connection_type, tcp_ip_address) proc do if command.command_type == CommandType::REFERENCE && is_executed == true destructCommand = Command.new(@runtime_name, CommandType::DESTRUCT_REFERENCE, command.payload) interpreter.execute(destructCommand, connection_type, tcp_ip_address) end end end def iterator if @current_command.command_type != CommandType::REFERENCE raise "Object is not iterable" else return InvocationContextIterator.new(self) end end def [](i) if @current_command.command_type != CommandType::REFERENCE raise "Object is not iterable" else invocation_context_iterator = InvocationContextIterator.new(self) return invocation_context_iterator[i] end end def []=(i, value) if @current_command.command_type != CommandType::REFERENCE raise "Object is not iterable" else invocation_context_iterator = InvocationContextIterator.new(self) return invocation_context_iterator[i] = value end end def execute @response_command = @interpreter.execute(@current_command, @connection_type, @tcp_ip_address) if @response_command.command_type == CommandType::EXCEPTION raise ExceptionThrower.throw_exception(@response_command) end if @response_command.command_type == CommandType::CREATE_CLASS_INSTANCE @current_command = @response_command @is_executed = true return self end return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, @response_command, true) end def invoke_instance_method(*args) local_command = Command.new(@runtime_name, CommandType::INVOKE_INSTANCE_METHOD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def create_instance(*args) local_command = Command.new(@runtime_name, CommandType::CREATE_CLASS_INSTANCE, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def get_static_field(*args) local_command = Command.new(@runtime_name, CommandType::GET_STATIC_FIELD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def set_static_field(*args) local_command = Command.new(@runtime_name, CommandType::SET_STATIC_FIELD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def get_instance_field(*args) local_command = Command.new(@runtime_name, CommandType::GET_INSTANCE_FIELD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def set_instance_field(*args) local_command = Command.new(@runtime_name, CommandType::SET_INSTANCE_FIELD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def invoke_static_method(*args) local_command = Command.new(@runtime_name, CommandType::INVOKE_STATIC_METHOD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def get_index(*args) local_command = Command.new(@runtime_name, CommandType::ARRAY_GET_ITEM, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def get_size(*args) local_command = Command.new(@runtime_name, CommandType::ARRAY_GET_SIZE, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def get_rank(*args) local_command = Command.new(@runtime_name, CommandType::ARRAY_GET_RANK, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def set_index(*args) local_command = Command.new(@runtime_name, CommandType::ARRAY_SET_ITEM, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def invoke_generic_static_method(*args) local_command = Command.new(@runtime_name, CommandType::INVOKE_GENERIC_STATIC_METHOD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def invoke_generic_method(*args) local_command = Command.new(@runtime_name, CommandType::INVOKE_GENERIC_METHOD, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def get_enum_name(*args) local_command = Command.new(@runtime_name, CommandType::GET_ENUM_NAME, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def get_enum_value(*args) local_command = Command.new(@runtime_name, CommandType::GET_ENUM_VALUE, [*args]) return InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) end def retrieve_array(*args) local_command = Command.new(@runtime_name, CommandType::RETRIEVE_ARRAY, [*args]) localInvCtx = InvocationContext.new(@runtime_name, @connection_type, @tcp_ip_address, build_command(local_command)) localInvCtx.execute return localInvCtx.response_command.payload end def get_value return @current_command.payload[0] end def build_command(command) command.payload.each_index { |i| command.payload[i] = encapsulate_payload_item(command.payload[i]) } return command.prepend_arg_to_payload(@current_command) end def encapsulate_payload_item(payload_item) if payload_item.is_a? Command payload_item.payload.each_index { |i| payload_item.payload[i] = encapsulate_payload_item(payload_item.payload[i]) } return payload_item elsif payload_item.is_a? InvocationContext return payload_item.current_command elsif payload_item.is_a? Array payload_item.each_index { |i| payload_item[i] = encapsulate_payload_item(payload_item[i]) } return Command.new(@runtime_name, CommandType::ARRAY, [*payload_item]) else return Command.new(@runtime_name, CommandType::VALUE, [*payload_item]) end end def current_command @current_command end def response_command @response_command end end