void t_java_deprecated_generator::generate_service_client()

in thrift/compiler/generate/t_java_deprecated_generator.cc [2485:2716]


void t_java_deprecated_generator::generate_service_client(
    const t_service* tservice) {
  string extends = "";
  string extends_client = "";
  if (tservice->get_extends() != nullptr) {
    extends = type_name(tservice->get_extends());
    extends_client = " extends " + extends + ".Client";
  } else {
    // Client base class
    extends_client = " extends EventHandlerBase";
  }

  indent(f_service_) << "public static class Client" << extends_client
                     << " implements Iface, TClientIf {" << endl;
  indent_up();

  indent(f_service_) << "public Client(TProtocol prot)" << endl;
  scope_up(f_service_);
  indent(f_service_) << "this(prot, prot);" << endl;
  scope_down(f_service_);
  f_service_ << endl;

  indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)"
                     << endl;
  scope_up(f_service_);
  if (extends.empty()) {
    f_service_ << indent() << "iprot_ = iprot;" << endl
               << indent() << "oprot_ = oprot;" << endl;
  } else {
    f_service_ << indent() << "super(iprot, oprot);" << endl;
  }
  scope_down(f_service_);
  f_service_ << endl;

  if (extends.empty()) {
    f_service_ << indent() << "protected TProtocol iprot_;" << endl
               << indent() << "protected TProtocol oprot_;" << endl
               << endl
               << indent() << "protected int seqid_;" << endl
               << endl;

    f_service_ << indent() << "@Override" << endl
               << indent() << "public TProtocol getInputProtocol()" << endl;
    scope_up(f_service_);
    indent(f_service_) << "return this.iprot_;" << endl;
    scope_down(f_service_);
    f_service_ << endl;

    f_service_ << indent() << "@Override" << endl
               << indent() << "public TProtocol getOutputProtocol()" << endl;
    scope_up(f_service_);
    indent(f_service_) << "return this.oprot_;" << endl;
    scope_down(f_service_);
    f_service_ << endl;
  }

  // Generate client method implementations
  vector<t_function*> functions = tservice->get_functions();
  vector<t_function*>::const_iterator f_iter;
  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
    if (!can_generate_method(*f_iter)) {
      continue;
    }
    string funname = (*f_iter)->get_name();
    string service_func_name =
        "\"" + tservice->get_name() + "." + (*f_iter)->get_name() + "\"";
    // Open function
    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
    scope_up(f_service_);

    f_service_ << indent() << "ContextStack ctx = getContextStack("
               << service_func_name << ", null);" << endl
               << indent() << "this.setContextStack(ctx);" << endl
               << indent() << "send_" << funname << "(";

    // Get the struct of function call params
    const t_struct* arg_struct = (*f_iter)->get_paramlist();

    // Declare the function arguments
    const vector<t_field*>& fields = arg_struct->get_members();
    vector<t_field*>::const_iterator fld_iter;
    bool first = true;
    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
      if (first) {
        first = false;
      } else {
        f_service_ << ", ";
      }
      f_service_ << (*fld_iter)->get_name();
    }
    f_service_ << ");" << endl;

    if ((*f_iter)->qualifier() != t_function_qualifier::one_way) {
      f_service_ << indent();
      if (!(*f_iter)->get_returntype()->is_void()) {
        f_service_ << "return ";
      }
      f_service_ << "recv_" << funname << "();" << endl;
    }

    scope_down(f_service_);
    f_service_ << endl;

    t_function send_function(
        &t_base_type::t_void(),
        string("send_") + (*f_iter)->get_name(),
        t_struct::clone_DO_NOT_USE((*f_iter)->get_paramlist()));

    string argsname = (*f_iter)->get_name() + "_args";

    // Open function
    indent(f_service_) << "public " << function_signature(&send_function)
                       << endl;
    scope_up(f_service_);

    // Serialize the request
    indent(f_service_) << "ContextStack ctx = "
                       << "this.getContextStack();" << endl;
    indent(f_service_) << "super.preWrite(ctx, " << service_func_name
                       << ", null);" << endl;

    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\""
               << funname << "\", TMessageType.CALL, seqid_));" << endl
               << indent() << argsname << " args = new " << argsname << "();"
               << endl;

    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
                 << (*fld_iter)->get_name() << ";" << endl;
    }

    string bytes = tmp("_bytes");

    string flush = (*f_iter)->qualifier() == t_function_qualifier::one_way
        ? "onewayFlush"
        : "flush";
    f_service_ << indent() << "args.write(oprot_);" << endl
               << indent() << "oprot_.writeMessageEnd();" << endl
               << indent() << "oprot_.getTransport()." << flush << "();" << endl
               << indent() << "super.postWrite(ctx, " << service_func_name
               << ", args);" << endl
               << indent() << "return;" << endl;

    scope_down(f_service_);
    f_service_ << endl;

    // Generate recv function only if not a oneway function
    if ((*f_iter)->qualifier() != t_function_qualifier::one_way) {
      string resultname = (*f_iter)->get_name() + "_result";

      t_function recv_function(
          (*f_iter)->get_returntype(),
          string("recv_") + (*f_iter)->get_name(),
          std::make_unique<t_paramlist>(program_),
          t_struct::clone_DO_NOT_USE((*f_iter)->get_xceptions()));
      // Open the recv function
      indent(f_service_) << "public " << function_signature(&recv_function)
                         << endl;
      scope_up(f_service_);

      indent(f_service_) << "ContextStack ctx = "
                         << "super.getContextStack();" << endl; // newversion
      indent(f_service_) << "long bytes;" << endl;

      indent(f_service_) << "TMessageType mtype;" << endl
                         << indent() << "super.preRead(ctx, "
                         << service_func_name << ");" << endl;

      // TODO(mcslee): Message validation here, was the seqid etc ok?

      f_service_
          << indent() << "TMessage msg = iprot_.readMessageBegin();" << endl
          << indent() << "if (msg.type == TMessageType.EXCEPTION) {" << endl
          << indent()
          << "  TApplicationException x = TApplicationException.read(iprot_);"
          << endl
          << indent() << "  iprot_.readMessageEnd();" << endl
          << indent() << "  throw x;" << endl
          << indent() << "}" << endl;

      if (generate_immutable_structs_) {
        f_service_ << indent() << resultname << " result = " << resultname
                   << ".deserialize(iprot_);" << endl;
      } else {
        f_service_ << indent() << resultname << " result = new " << resultname
                   << "();" << endl
                   << indent() << "result.read(iprot_);" << endl;
      }

      f_service_ << indent() << "iprot_.readMessageEnd();" << endl
                 << indent() << "super.postRead(ctx, " << service_func_name
                 << ", result);" << endl
                 << endl;

      // Careful, only return _result if not a void function
      if (!(*f_iter)->get_returntype()->is_void()) {
        f_service_ << indent() << "if (result."
                   << generate_isset_check("success") << ") {" << endl
                   << indent() << "  return result.success;" << endl
                   << indent() << "}" << endl;
      }

      const t_struct* xs = (*f_iter)->get_xceptions();
      const std::vector<t_field*>& xceptions = xs->get_members();
      vector<t_field*>::const_iterator x_iter;
      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
        f_service_ << indent() << "if (result." << (*x_iter)->get_name()
                   << " != null) {" << endl
                   << indent() << "  throw result." << (*x_iter)->get_name()
                   << ";" << endl
                   << indent() << "}" << endl;
      }

      // If you get here it's an exception, unless a void function
      if ((*f_iter)->get_returntype()->is_void()) {
        indent(f_service_) << "return;" << endl;
      } else {
        f_service_
            << indent()
            << "throw new TApplicationException(TApplicationException.MISSING_RESULT, \""
            << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
      }

      // Close function
      scope_down(f_service_);
      f_service_ << endl;
    }
  }

  indent_down();
  indent(f_service_) << "}" << endl;
}