void t_java_generator::generate_java_struct_parcelable()

in compiler/cpp/src/thrift/generate/t_java_generator.cc [1797:2019]


void t_java_generator::generate_java_struct_parcelable(ostream& out, t_struct* tstruct) {
  string tname = tstruct->get_name();

  const vector<t_field*>& members = tstruct->get_members();
  vector<t_field*>::const_iterator m_iter;

  out << indent() << java_override_annotation() << '\n'
      << indent() << "public void writeToParcel(android.os.Parcel out, int flags) {" << '\n';
  indent_up();
  string bitsetPrimitiveType = "";
  switch (needs_isset(tstruct, &bitsetPrimitiveType)) {
  case ISSET_NONE:
    break;
  case ISSET_PRIMITIVE:
    indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << '\n';
    if (bitsetPrimitiveType == "byte") {
      indent(out) << "out.writeByte(__isset_bitfield);" << '\n';
    } else if (bitsetPrimitiveType == "short") {
      indent(out) << "out.writeInt(new Short(__isset_bitfield).intValue());" << '\n';
    } else if (bitsetPrimitiveType == "int") {
      indent(out) << "out.writeInt(__isset_bitfield);" << '\n';
    } else if (bitsetPrimitiveType == "long") {
      indent(out) << "out.writeLong(__isset_bitfield);" << '\n';
    }
    out << '\n';
    break;
  case ISSET_BITSET:
    indent(out) << "//BitSet" << '\n';
    indent(out) << "out.writeSerializable(__isset_bit_vector);" << '\n';
    out << '\n';
    break;
  }
  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
    t_type* t = get_true_type((*m_iter)->get_type());
    string name = (*m_iter)->get_name();

    if (t->is_struct()) {
      indent(out) << "out.writeParcelable(" << name << ", flags);" << '\n';
    } else if (type_name(t) == "float") {
      indent(out) << "out.writeFloat(" << name << ");" << '\n';
    } else if (t->is_enum()) {
      indent(out) << "out.writeInt(" << name << " != null ? " << name << ".getValue() : -1);"
                  << '\n';
    } else if (t->is_list()) {
      if (((t_list*)t)->get_elem_type()->get_true_type()->is_struct()) {
        indent(out) << "out.writeTypedList(" << name << ");" << '\n';
      } else {
        indent(out) << "out.writeList(" << name << ");" << '\n';
      }
    } else if (t->is_map()) {
      indent(out) << "out.writeMap(" << name << ");" << '\n';
    } else if (t->is_base_type()) {
      if (t->is_binary()) {
        indent(out) << "out.writeInt(" << name << "!=null ? 1 : 0);" << '\n';
        indent(out) << "if(" << name << " != null) { " << '\n';
        indent_up();
        indent(out) << "out.writeByteArray(" << name << ".array(), " << name << ".position() + "
                    << name << ".arrayOffset(), " << name << ".limit() - " << name
                    << ".position() );" << '\n';
        scope_down(out);
      } else {
        switch (((t_base_type*)t)->get_base()) {
        case t_base_type::TYPE_I16:
          indent(out) << "out.writeInt(new Short(" << name << ").intValue());" << '\n';
          break;
        case t_base_type::TYPE_UUID:
          indent(out) << "out.writeUuid(" << name << ");" << '\n';
          break;
        case t_base_type::TYPE_I32:
          indent(out) << "out.writeInt(" << name << ");" << '\n';
          break;
        case t_base_type::TYPE_I64:
          indent(out) << "out.writeLong(" << name << ");" << '\n';
          break;
        case t_base_type::TYPE_BOOL:
          indent(out) << "out.writeInt(" << name << " ? 1 : 0);" << '\n';
          break;
        case t_base_type::TYPE_I8:
          indent(out) << "out.writeByte(" << name << ");" << '\n';
          break;
        case t_base_type::TYPE_DOUBLE:
          indent(out) << "out.writeDouble(" << name << ");" << '\n';
          break;
        case t_base_type::TYPE_STRING:
          indent(out) << "out.writeString(" << name << ");" << '\n';
          break;
        case t_base_type::TYPE_VOID:
          break;
        default:
          throw "compiler error: unhandled type";
        }
      }
    }
  }
  scope_down(out);
  out << '\n';

  out << indent() << java_override_annotation() << '\n'
      << indent() << "public int describeContents() {" << '\n';
  indent_up();
  out << indent() << "return 0;" << '\n';
  scope_down(out);
  out << '\n';

  indent(out) << "public " << tname << "(android.os.Parcel in) {" << '\n';
  indent_up();
  // read in the required bitfield
  switch (needs_isset(tstruct, &bitsetPrimitiveType)) {
  case ISSET_NONE:
    break;
  case ISSET_PRIMITIVE:
    indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << '\n';
    if (bitsetPrimitiveType == "byte") {
      indent(out) << "__isset_bitfield = in.readByte();" << '\n';
    } else if (bitsetPrimitiveType == "short") {
      indent(out) << "__isset_bitfield = (short) in.readInt();" << '\n';
    } else if (bitsetPrimitiveType == "int") {
      indent(out) << "__isset_bitfield = in.readInt();" << '\n';
    } else if (bitsetPrimitiveType == "long") {
      indent(out) << "__isset_bitfield = in.readLong();" << '\n';
    }
    out << '\n';
    break;
  case ISSET_BITSET:
    indent(out) << "//BitSet" << '\n';
    indent(out) << "__isset_bit_vector = (java.util.BitSet) in.readSerializable();" << '\n';
    out << '\n';
    break;
  }
  // read all the fields
  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
    t_type* t = get_true_type((*m_iter)->get_type());
    string name = (*m_iter)->get_name();
    string prefix = "this." + name;

    if (t->is_struct()) {
      indent(out) << prefix << "= in.readParcelable(" << tname << ".class.getClassLoader());"
                  << '\n';
    } else if (t->is_enum()) {
      indent(out) << prefix << " = " << type_name(t) << ".findByValue(in.readInt());" << '\n';
    } else if (t->is_list()) {
      t_list* list = (t_list*)t;
      indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << '\n';
      if (list->get_elem_type()->get_true_type()->is_struct()) {
        indent(out) << "in.readTypedList(" << prefix << ", " << type_name(list->get_elem_type())
                    << ".CREATOR);" << '\n';
      } else {
        indent(out) << "in.readList(" << prefix << ", " << tname << ".class.getClassLoader());"
                    << '\n';
      }
    } else if (t->is_map()) {
      indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << '\n';
      indent(out) << " in.readMap(" << prefix << ", " << tname << ".class.getClassLoader());"
                  << '\n';
    } else if (type_name(t) == "float") {
      indent(out) << prefix << " = in.readFloat();" << '\n';
    } else if (t->is_base_type()) {
      t_base_type* bt = (t_base_type*)t;
      if (bt->is_binary()) {
        indent(out) << "if(in.readInt()==1) {" << '\n';
        indent_up();
        indent(out) << prefix << " = java.nio.ByteBuffer.wrap(in.createByteArray());" << '\n';
        scope_down(out);
      } else {
        switch (bt->get_base()) {
        case t_base_type::TYPE_I8:
          indent(out) << prefix << " = in.readByte();" << '\n';
          break;
        case t_base_type::TYPE_I16:
          indent(out) << prefix << " = (short) in.readInt();" << '\n';
          break;
        case t_base_type::TYPE_I32:
          indent(out) << prefix << " = in.readInt();" << '\n';
          break;
        case t_base_type::TYPE_I64:
          indent(out) << prefix << " = in.readLong();" << '\n';
          break;
        case t_base_type::TYPE_UUID:
          indent(out) << prefix << " = in.readUuid();" << '\n';
          break;
        case t_base_type::TYPE_BOOL:
          indent(out) << prefix << " = (in.readInt()==1);" << '\n';
          break;
        case t_base_type::TYPE_DOUBLE:
          indent(out) << prefix << " = in.readDouble();" << '\n';
          break;
        case t_base_type::TYPE_STRING:
          indent(out) << prefix << "= in.readString();" << '\n';
          break;
        case t_base_type::TYPE_VOID:
          break;
        default:
          throw "compiler error: unhandled type";
        }
      }
    }
  }

  scope_down(out);
  out << '\n';

  indent(out) << "public static final android.os.Parcelable.Creator<" << tname
              << "> CREATOR = new android.os.Parcelable.Creator<" << tname << ">() {" << '\n';
  indent_up();

  indent(out) << java_override_annotation() << '\n'
              << indent() << "public " << tname << "[] newArray(int size) {" << '\n';
  indent_up();
  indent(out) << "return new " << tname << "[size];" << '\n';
  scope_down(out);
  out << '\n';

  indent(out) << java_override_annotation() << '\n'
              << indent() << "public " << tname << " createFromParcel(android.os.Parcel in) {"
              << '\n';
  indent_up();
  indent(out) << "return new " << tname << "(in);" << '\n';
  scope_down(out);

  indent_down();
  indent(out) << "};" << '\n';
  out << '\n';
}