in core/src/main/java/com/twitter/elephantbird/util/ThriftToDynamicProto.java [433:502]
private int convertField(TBase<?, ?> thriftObj, Message.Builder builder,
TStructDescriptor fieldDesc, int fieldId, Field tField) {
int tmpFieldId = fieldId;
FieldDescriptor protoFieldDesc = builder.getDescriptorForType().findFieldByName(
tField.getName());
if (protoFieldDesc == null) {
// not finding a field might be ok if we're ignoring an unsupported types
Type protoType = thriftTypeToProtoType(tField);
if (protoType == null
&& (ignoreUnsupportedTypes
|| (!supportNestedObjects && hasNestedObject(tField)))) {
return tmpFieldId; // no-op
}
throw new RuntimeException("Field " + tField.getName() + " not found in dynamic protobuf.");
}
Object fieldValue = fieldDesc.getFieldValue(tmpFieldId++, thriftObj);
if (fieldValue == null) {
return tmpFieldId;
}
try {
// For non-Map containers that contain struct types,
// we have to convert each struct into a Message.
if (isStructContainer(tField)) {
List<Message> convertedStructs = Lists.newLinkedList();
Iterable<TBase<?, ?>> structIterator = (Iterable<TBase<?, ?>>) fieldValue;
for (TBase<?, ?> struct : structIterator) {
convertedStructs.add(doConvert(struct));
}
fieldValue = convertedStructs;
} else if (tField.isMap()) {
List<Message> convertedMapEntries = Lists.newLinkedList();
Map<?, ?> rawMap = (Map) fieldValue;
for (Map.Entry<?, ?> entry : rawMap.entrySet()) {
Message.Builder mapBuilder = mapEntryProtoBuilder(fieldDesc, tField);
Message msg = buildMapEntryMessage(mapBuilder, tField, entry.getKey(), entry.getValue());
convertedMapEntries.add(msg);
}
fieldValue = convertedMapEntries;
} else {
// protobufs throws an exception if you try to set byte on an int32 field so we need to
// convert it to an Integer before it gets set
fieldValue = sanitizeRawValue(fieldValue, tField);
}
// Container types have to be added as repeated fields
if (isContainer(tField)) {
Iterable<?> container = (Iterable) fieldValue;
for (Object obj : container) {
builder.addRepeatedField(protoFieldDesc, obj);
}
} else {
builder.setField(protoFieldDesc, fieldValue);
}
} catch (IllegalArgumentException e) {
LOG.error(String.format("Could not set protoField(index=%d, name=%s, type=%s) with "
+ "thriftField(index=%d, name=%s, type=%d, value=%s)",
protoFieldDesc.getIndex(), protoFieldDesc.getName(), protoFieldDesc.getType(),
tmpFieldId - 1, tField.getName(), tField.getType(), fieldValue), e);
throw e;
}
return tmpFieldId;
}