core/src/main/java/com/twitter/elephantbird/util/ThriftToDynamicProto.java
@SuppressWarnings("unchecked")
  public <F extends TFieldIdEnum> Message doConvert(TBase<?, F> thriftObj) {
    if (thriftObj == null) { return null; }

    Class<TBase<?, F>> clazz = (Class<TBase<?, F>>) thriftObj.getClass();
    checkState(clazz);

    Message.Builder builder = getBuilder(clazz);

    TStructDescriptor fieldDesc = TStructDescriptor.getInstance(clazz);
    int fieldId = 0;
    for (Field tField : fieldDesc.getFields()) {
      // don't want to carry over default values from unset fields
      if (!thriftObj.isSet((F) tField.getFieldIdEnum())
          || (!supportNestedObjects && hasNestedObject(tField))) {
        fieldId++;
        continue;
      }

      // recurse into the object if it's a struct, otherwise just add the field
      if (supportNestedObjects && tField.getType() == TType.STRUCT) {
        TBase<?, ?> fieldValue = (TBase<?, ?>) fieldDesc.getFieldValue(fieldId++, thriftObj);
        Message message = doConvert(fieldValue);
        if (message != null) {
          FieldDescriptor protoFieldDesc = builder.getDescriptorForType().findFieldByName(
              tField.getName());
          builder.setField(protoFieldDesc, message);
        }
      } else {
        fieldId = convertField(thriftObj, builder, fieldDesc, fieldId, tField);
      }
    }
    return builder.build();
  }
@SuppressWarnings("unchecked")
  public <F extends TFieldIdEnum> Message doConvert(TBase<?, F> thriftObj) {
    if (thriftObj == null) { return null; }

    Class<TBase<?, F>> clazz = (Class<TBase<?, F>>) thriftObj.getClass();
    checkState(clazz);

    Message.Builder builder = getBuilder(clazz);

    TStructDescriptor fieldDesc = TStructDescriptor.getInstance(clazz);
    int fieldId = 0;
    for (Field tField : fieldDesc.getFields()) {
      // don't want to carry over default values from unset fields
      if (!thriftObj.isSet((F) tField.getFieldIdEnum())
          || (!supportNestedObjects && hasNestedObject(tField))) {
        fieldId++;
        continue;
      }

      // recurse into the object if it's a struct, otherwise just add the field
      if (supportNestedObjects && tField.getType() == TType.STRUCT) {
        TBase<?, ?> fieldValue = (TBase<?, ?>) fieldDesc.getFieldValue(fieldId++, thriftObj);
        Message message = doConvert(fieldValue);
        if (message != null) {
          FieldDescriptor protoFieldDesc = builder.getDescriptorForType().findFieldByName(
              tField.getName());
          builder.setField(protoFieldDesc, message);
        }
      } else {
        fieldId = convertField(thriftObj, builder, fieldDesc, fieldId, tField);
      }
    }
    return builder.build();
  }
conver TBase object to Message object
@param thriftObj