下面列出了com.google.protobuf.Descriptors.Descriptor#findFieldByName ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
ProtoFieldInfo(FieldDescriptor field, Message containingPrototype) {
this.field = checkNotNull(field, "field");
this.containingPrototype = checkNotNull(containingPrototype, "containingPrototype");
builderClass = containingPrototype.newBuilderForType().getClass();
camelCaseName = underscoresToUpperCamelCase(field.getName());
if (field.isMapField()) {
Descriptor mapType = field.getMessageType();
mapKeyField = new ProtoFieldInfo(mapType.findFieldByName("key"), containingPrototype);
mapValueField = new ProtoFieldInfo(mapType.findFieldByName("value"), containingPrototype);
} else {
mapKeyField = null;
mapValueField = null;
}
}
public void testGetFieldBuilderWithInitializedValue() {
Descriptor descriptor = TestAllTypes.getDescriptor();
FieldDescriptor fieldDescriptor =
descriptor.findFieldByName("optional_nested_message");
// Before setting field, builder is initialized by default value.
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
NestedMessage.Builder fieldBuilder =
(NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
assertEquals(0, fieldBuilder.getBb());
// Setting field value with new field builder instance.
builder = TestAllTypes.newBuilder();
NestedMessage.Builder newFieldBuilder =
builder.getOptionalNestedMessageBuilder();
newFieldBuilder.setBb(2);
// Then get the field builder instance by getFieldBuilder().
fieldBuilder =
(NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
// It should contain new value.
assertEquals(2, fieldBuilder.getBb());
// These two builder should be equal.
assertSame(fieldBuilder, newFieldBuilder);
}
@Test
public void testGetDescriptor() throws IOException {
Descriptor descriptor2 = AddressBookProtos.AddressBook.getDescriptor();
FieldDescriptor stringMapFD = descriptor2.findFieldByName("person");
byte[] bytes = getProtoBytes2();
DynamicMessage parseFrom = DynamicMessage.parseFrom(descriptor2, bytes);
Object field = parseFrom.getField(stringMapFD);
Assert.assertTrue(field instanceof List);
Codec<AddressBookProtosPOJO> codec = ProtobufProxy.create(AddressBookProtosPOJO.class, true);
Descriptor descriptor = codec.getDescriptor();
stringMapFD = descriptor.findFieldByName("list");
bytes = getProtoBytes2();
parseFrom = DynamicMessage.parseFrom(descriptor, bytes);
Object field2 = parseFrom.getField(stringMapFD);
Assert.assertTrue(field2 instanceof List);
}
@SuppressWarnings("unchecked")
protected void writeMap(
FieldDescriptor field,
Object entries,
JsonGenerator generator,
SerializerProvider serializerProvider
) throws IOException {
Descriptor entryDescriptor = field.getMessageType();
FieldDescriptor keyDescriptor = entryDescriptor.findFieldByName("key");
FieldDescriptor valueDescriptor = entryDescriptor.findFieldByName("value");
generator.writeStartObject();
for (Message entry : (List<? extends Message>) entries) {
// map keys can only be integers or strings so this should be fine
generator.writeFieldName(entry.getField(keyDescriptor).toString());
Object value = entry.getField(valueDescriptor);
// map values can't be maps or repeated so this should be fine
writeValue(valueDescriptor, value, generator, serializerProvider);
}
generator.writeEndObject();
}
private void setOption(Message.Builder builder, Option option, String expectedPrefix) {
if (!option.getName().startsWith(expectedPrefix)) {
return;
}
Descriptor descriptor = builder.getDescriptorForType();
String optionName = option.getName().substring(expectedPrefix.length());
FieldDescriptor optionField = descriptor.findFieldByName(optionName);
if (optionField != null) {
if (optionField.isRepeated()) {
builder.addRepeatedField(optionField, fieldValueFrom(option.getValue(), optionField));
} else {
builder.setField(optionField, fieldValueFrom(option.getValue(), optionField));
}
}
}
@Test
public void testGetDescriptor() throws IOException {
Codec<SimpleMapPOJO> codec = ProtobufProxy.create(SimpleMapPOJO.class, false);
Descriptor descriptor = codec.getDescriptor();
String escapeBytes = StringUtils.escapeBytes(descriptor.toProto().toByteArray());
System.out.println(escapeBytes);
FieldDescriptor stringMapFD = descriptor.findFieldByName("stringMap");
byte[] bytes = getProtoBytes2();
DynamicMessage parseFrom = DynamicMessage.parseFrom(descriptor, bytes);
Object field = parseFrom.getField(stringMapFD);
Assert.assertTrue(field instanceof List);
Assert.assertEquals(2, ((List) field).size());
Descriptor descriptor2 = AddressBookProtos.Person.getDescriptor();
stringMapFD = descriptor2.findFieldByName("stringMap");
bytes = getProtoBytes2();
parseFrom = DynamicMessage.parseFrom(descriptor2, bytes);
field = parseFrom.getField(stringMapFD);
Assert.assertTrue(field instanceof List);
Assert.assertEquals(2, ((List) field).size());
}
@Override
final void writeRawValue(Object value) {
Collection<Message> collection = (Collection<Message>) value;
if (collection.isEmpty()) {
return;
}
recordConsumer.startField(fieldName, index);
recordConsumer.startGroup();
recordConsumer.startField("key_value", 0); // This is the wrapper group for the map field
for (Message msg : collection) {
recordConsumer.startGroup();
final Descriptor descriptorForType = msg.getDescriptorForType();
final FieldDescriptor keyDesc = descriptorForType.findFieldByName("key");
final FieldDescriptor valueDesc = descriptorForType.findFieldByName("value");
keyWriter.writeField(msg.getField(keyDesc));
valueWriter.writeField(msg.getField(valueDesc));
recordConsumer.endGroup();
}
recordConsumer.endField("key_value", 0);
recordConsumer.endGroup();
recordConsumer.endField(fieldName, index);
}
protected List<Message> readMap(
Message.Builder builder,
FieldDescriptor field,
JsonParser parser,
DeserializationContext context
) throws IOException {
if (parser.getCurrentToken() == JsonToken.VALUE_NULL) {
// Seems like we should treat null as an empty map rather than fail?
return Collections.emptyList();
} else if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
throw reportWrongToken(
JsonToken.START_OBJECT,
context,
"Can't parse map field out of " + parser.currentToken() + " token"
);
}
Descriptor entryDescriptor = field.getMessageType();
FieldDescriptor keyDescriptor = entryDescriptor.findFieldByName("key");
FieldDescriptor valueDescriptor = entryDescriptor.findFieldByName("value");
List<Message> entries = new ArrayList<>();
while (parser.nextToken() != JsonToken.END_OBJECT) {
Message.Builder entryBuilder = builder.newBuilderForField(field);
Object key = readKey(keyDescriptor, parser, context);
parser.nextToken(); // move from key to value
Object value = readValue(entryBuilder, valueDescriptor, null, parser, context);
entryBuilder.setField(keyDescriptor, key);
entryBuilder.setField(valueDescriptor, value);
entries.add(entryBuilder.build());
}
return entries;
}
/**
* Parse a single field from {@code tokenizer} and merge it into {@code builder}. If a ',' is
* detected after the field ends, the next field will be parsed automatically
*/
protected static void mergeField(Tokenizer tokenizer,
ExtensionRegistry extensionRegistry, Message.Builder builder,
boolean selfType) throws ParseException {
FieldDescriptor field;
Descriptor type = builder.getDescriptorForType();
final ExtensionRegistry.ExtensionInfo extension;
boolean unknown = false;
String name = tokenizer.consumeIdentifier();
field = type.findFieldByName(name);
// Group names are expected to be capitalized as they appear in the
// .proto file, which actually matches their type names, not their field
// names.
if (field == null) {
// Explicitly specify US locale so that this code does not break when
// executing in Turkey.
String lowerName = name.toLowerCase(Locale.US);
field = type.findFieldByName(lowerName);
// If the case-insensitive match worked but the field is NOT a group,
if ((field != null) && (field.getType() != FieldDescriptor.Type.GROUP)) {
field = null;
}
}
// Again, special-case group names as described above.
if ((field != null) && (field.getType() == FieldDescriptor.Type.GROUP)
&& !field.getMessageType().getName().equals(name)) {
field = null;
}
// Last try to lookup by field-index if 'name' is numeric,
// which indicates a possible unknown field
if (field == null && DIGITS.matcher(name).matches()) {
field = type.findFieldByNumber(Integer.parseInt(name));
unknown = true;
}
// Finally, look for extensions
extension = extensionRegistry.findExtensionByName(name);
if (extension != null) {
if (extension.descriptor.getContainingType() != type) {
throw tokenizer.parseExceptionPreviousToken("Extension \"" + name
+ "\" does not extend message type \""
+ type.getFullName() + "\".");
}
field = extension.descriptor;
}
// Disabled throwing exception if field not found, since it could be a different version.
if (field == null) {
handleMissingField(tokenizer, extensionRegistry, builder);
//throw tokenizer.parseExceptionPreviousToken("Message type \"" + type.getFullName()
// + "\" has no field named \"" + name
// + "\".");
}
if (field != null) {
tokenizer.consume(":");
boolean array = tokenizer.tryConsume("[");
if (array) {
while (!tokenizer.tryConsume("]")) {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown, selfType);
tokenizer.tryConsume(",");
}
} else {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown, selfType);
}
}
if (tokenizer.tryConsume(",")) {
// Continue with the next field
mergeField(tokenizer, extensionRegistry, builder, selfType);
}
}
/**
* Parse a single field from {@code parser} and merge it into {@code builder}. If a ',' is
* detected after the field ends, the next field will be parsed automatically
* @throws IOException
* @throws JsonParseException
*/
protected void mergeField(JsonParser parser,
ExtensionRegistry extensionRegistry,
Message.Builder builder) throws JsonParseException, IOException {
FieldDescriptor field = null;
Descriptor type = builder.getDescriptorForType();
boolean unknown = false;
ExtensionRegistry.ExtensionInfo extension = null;
JsonToken token = parser.getCurrentToken();
if (token != null) {
String name = parser.getCurrentName();
if (name.contains(".")) {
// should be an extension
extension = extensionRegistry.findExtensionByName(name);
if (extension == null) {
throw new RuntimeException("Extension \""
+ name + "\" not found in the ExtensionRegistry.");
} else if (extension.descriptor.getContainingType() != type) {
throw new RuntimeException("Extension \"" + name
+ "\" does not extend message type \""
+ type.getFullName() + "\".");
}
field = extension.descriptor;
} else {
field = type.findFieldByName(name);
}
// Group names are expected to be capitalized as they appear in the
// .proto file, which actually matches their type names, not their field
// names.
if (field == null) {
// Explicitly specify US locale so that this code does not break when
// executing in Turkey.
String lowerName = name.toLowerCase(Locale.US);
field = type.findFieldByName(lowerName);
// If the case-insensitive match worked but the field is NOT a group,
if ((field != null) && (field.getType() != FieldDescriptor.Type.GROUP)) {
field = null;
}
}
// Again, special-case group names as described above.
if ((field != null) && (field.getType() == FieldDescriptor.Type.GROUP)
&& !field.getMessageType().getName().equals(name)
&& !field.getMessageType().getFullName().equalsIgnoreCase(name) /* extension */) {
field = null;
}
// Last try to lookup by field-index if 'name' is numeric,
// which indicates a possible unknown field
if (field == null && TextUtils.isDigits(name)) {
field = type.findFieldByNumber(Integer.parseInt(name));
unknown = true;
}
// no throwing exceptions if field not found, since it could be a different version.
if (field == null) {
UnknownFieldSet.Builder unknownsBuilder = UnknownFieldSet.newBuilder();
handleMissingField(name, parser, extensionRegistry, unknownsBuilder);
builder.setUnknownFields(unknownsBuilder.build());
}
}
if (field != null) {
token = parser.nextToken();
boolean array = token.equals(JsonToken.START_ARRAY);
if (array) {
token = parser.nextToken();
while (!token.equals(JsonToken.END_ARRAY)) {
handleValue(parser, extensionRegistry, builder, field, extension, unknown);
token = parser.nextToken();
}
} else {
handleValue(parser, extensionRegistry, builder, field, extension, unknown);
}
}
}
/**
* Parse a single field from {@code tokenizer} and merge it into {@code builder}. If a ',' is
* detected after the field ends, the next field will be parsed automatically
*/
protected void mergeField(Tokenizer tokenizer,
ExtensionRegistry extensionRegistry,
Message.Builder builder) throws ParseException {
FieldDescriptor field;
Descriptor type = builder.getDescriptorForType();
ExtensionRegistry.ExtensionInfo extension = null;
boolean unknown = false;
String name = tokenizer.consumeIdentifier();
field = type.findFieldByName(name);
// Group names are expected to be capitalized as they appear in the
// .proto file, which actually matches their type names, not their field
// names.
if (field == null) {
// Explicitly specify US locale so that this code does not break when
// executing in Turkey.
String lowerName = name.toLowerCase(Locale.US);
field = type.findFieldByName(lowerName);
// If the case-insensitive match worked but the field is NOT a group,
if ((field != null) && (field.getType() != FieldDescriptor.Type.GROUP)) {
field = null;
}
}
// Again, special-case group names as described above.
if ((field != null) && (field.getType() == FieldDescriptor.Type.GROUP)
&& !field.getMessageType().getName().equals(name)) {
field = null;
}
// Last try to lookup by field-index if 'name' is numeric,
// which indicates a possible unknown field
if (field == null && TextUtils.isDigits(name)) {
field = type.findFieldByNumber(Integer.parseInt(name));
unknown = true;
}
// Finally, look for extensions
extension = extensionRegistry.findExtensionByName(name);
if (extension != null) {
if (extension.descriptor.getContainingType() != type) {
throw tokenizer.parseExceptionPreviousToken("Extension \"" + name
+ "\" does not extend message type \""
+ type.getFullName() + "\".");
}
field = extension.descriptor;
}
// Disabled throwing exception if field not found, since it could be a different version.
if (field == null) {
handleMissingField(tokenizer, extensionRegistry, builder);
//throw tokenizer.parseExceptionPreviousToken("Message type \"" + type.getFullName()
// + "\" has no field named \"" + name
// + "\".");
}
if (field != null) {
tokenizer.consume(":");
boolean array = tokenizer.tryConsume("[");
if (array) {
while (!tokenizer.tryConsume("]")) {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown);
tokenizer.tryConsume(",");
}
} else {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown);
}
}
if (tokenizer.tryConsume(",")) {
// Continue with the next field
mergeField(tokenizer, extensionRegistry, builder);
}
}
private static FieldDescriptor getField(Descriptor descriptor, String name) {
return descriptor.findFieldByName(CAMEL_TO_UNDERSCORE.convert(name));
}
public void testGetFieldBuilder() {
Descriptor descriptor = TestAllTypes.getDescriptor();
FieldDescriptor fieldDescriptor =
descriptor.findFieldByName("optional_nested_message");
FieldDescriptor foreignFieldDescriptor =
descriptor.findFieldByName("optional_foreign_message");
FieldDescriptor importFieldDescriptor =
descriptor.findFieldByName("optional_import_message");
// Mutate the message with new field builder
// Mutate nested message
TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
.mergeFrom((Message) builder1.getField(fieldDescriptor));
FieldDescriptor subFieldDescriptor1 =
fieldBuilder1.getDescriptorForType().findFieldByName("bb");
fieldBuilder1.setField(subFieldDescriptor1, 1);
builder1.setField(fieldDescriptor, fieldBuilder1.build());
// Mutate foreign message
Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
foreignFieldDescriptor)
.mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
FieldDescriptor subForeignFieldDescriptor1 =
foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
// Mutate import message
Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
importFieldDescriptor)
.mergeFrom((Message) builder1.getField(importFieldDescriptor));
FieldDescriptor subImportFieldDescriptor1 =
importFieldBuilder1.getDescriptorForType().findFieldByName("d");
importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
Message newMessage1 = builder1.build();
// Mutate the message with existing field builder
// Mutate nested message
TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
FieldDescriptor subFieldDescriptor2 =
fieldBuilder2.getDescriptorForType().findFieldByName("bb");
fieldBuilder2.setField(subFieldDescriptor2, 1);
builder2.setField(fieldDescriptor, fieldBuilder2.build());
// Mutate foreign message
Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
foreignFieldDescriptor)
.mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
FieldDescriptor subForeignFieldDescriptor2 =
foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
// Mutate import message
Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
importFieldDescriptor)
.mergeFrom((Message) builder2.getField(importFieldDescriptor));
FieldDescriptor subImportFieldDescriptor2 =
importFieldBuilder2.getDescriptorForType().findFieldByName("d");
importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
Message newMessage2 = builder2.build();
// These two messages should be equal.
assertEquals(newMessage1, newMessage2);
}
public void testFieldDescriptor() throws Exception {
Descriptor messageType = TestAllTypes.getDescriptor();
FieldDescriptor primitiveField =
messageType.findFieldByName("optional_int32");
FieldDescriptor enumField =
messageType.findFieldByName("optional_nested_enum");
FieldDescriptor messageField =
messageType.findFieldByName("optional_foreign_message");
FieldDescriptor cordField =
messageType.findFieldByName("optional_cord");
FieldDescriptor extension =
UnittestProto.optionalInt32Extension.getDescriptor();
FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
assertEquals("optional_int32", primitiveField.getName());
assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
primitiveField.getFullName());
assertEquals(1, primitiveField.getNumber());
assertEquals(messageType, primitiveField.getContainingType());
assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
primitiveField.getOptions());
assertFalse(primitiveField.isExtension());
assertEquals("optional_int32", primitiveField.toProto().getName());
assertEquals("optional_nested_enum", enumField.getName());
assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
enumField.getEnumType());
assertEquals("optional_foreign_message", messageField.getName());
assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
assertEquals("optional_cord", cordField.getName());
assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
cordField.getOptions().getCtype());
assertEquals("optional_int32_extension", extension.getName());
assertEquals("protobuf_unittest.optional_int32_extension",
extension.getFullName());
assertEquals(1, extension.getNumber());
assertEquals(TestAllExtensions.getDescriptor(),
extension.getContainingType());
assertEquals(UnittestProto.getDescriptor(), extension.getFile());
assertEquals(FieldDescriptor.Type.INT32, extension.getType());
assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
extension.getOptions());
assertTrue(extension.isExtension());
assertEquals(null, extension.getExtensionScope());
assertEquals("optional_int32_extension", extension.toProto().getName());
assertEquals("single", nestedExtension.getName());
assertEquals("protobuf_unittest.TestRequired.single",
nestedExtension.getFullName());
assertEquals(TestRequired.getDescriptor(),
nestedExtension.getExtensionScope());
}
public void testCustomOptions() throws Exception {
Descriptor descriptor =
UnittestCustomOptions.TestMessageWithCustomOptions.getDescriptor();
assertTrue(
descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
assertEquals(Integer.valueOf(-56),
descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
FieldDescriptor field = descriptor.findFieldByName("field1");
assertNotNull(field);
assertTrue(
field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
assertEquals(Long.valueOf(8765432109L),
field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
EnumDescriptor enumType =
UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
assertTrue(
enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
assertEquals(Integer.valueOf(-789),
enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
ServiceDescriptor service =
UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
assertTrue(
service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
assertEquals(Long.valueOf(-9876543210L),
service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
MethodDescriptor method = service.findMethodByName("Foo");
assertNotNull(method);
assertTrue(
method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
}
/**
* Parse a single field from {@code tokenizer} and merge it into {@code builder}. If a ',' is
* detected after the field ends, the next field will be parsed automatically
*/
protected void mergeField(Tokenizer tokenizer,
ExtensionRegistry extensionRegistry,
Message.Builder builder) throws ParseException {
FieldDescriptor field;
Descriptor type = builder.getDescriptorForType();
ExtensionRegistry.ExtensionInfo extension = null;
boolean unknown = false;
String name = tokenizer.consumeIdentifier();
field = type.findFieldByName(name);
// Group names are expected to be capitalized as they appear in the
// .proto file, which actually matches their type names, not their field
// names.
if (field == null) {
// Explicitly specify US locale so that this code does not break when
// executing in Turkey.
String lowerName = name.toLowerCase(Locale.US);
field = type.findFieldByName(lowerName);
// If the case-insensitive match worked but the field is NOT a group,
if ((field != null) && (field.getType() != FieldDescriptor.Type.GROUP)) {
field = null;
}
}
// Again, special-case group names as described above.
if ((field != null) && (field.getType() == FieldDescriptor.Type.GROUP)
&& !field.getMessageType().getName().equals(name)) {
field = null;
}
// Last try to lookup by field-index if 'name' is numeric,
// which indicates a possible unknown field
if (field == null && TextUtils.isDigits(name)) {
field = type.findFieldByNumber(Integer.parseInt(name));
unknown = true;
}
// Finally, look for extensions
extension = extensionRegistry.findExtensionByName(name);
if (extension != null) {
if (extension.descriptor.getContainingType() != type) {
throw tokenizer.parseExceptionPreviousToken("Extension \"" + name
+ "\" does not extend message type \""
+ type.getFullName() + "\".");
}
field = extension.descriptor;
}
// Disabled throwing exception if field not found, since it could be a different version.
if (field == null) {
handleMissingField(tokenizer, extensionRegistry, builder);
//throw tokenizer.parseExceptionPreviousToken("Message type \"" + type.getFullName()
// + "\" has no field named \"" + name
// + "\".");
}
if (field != null) {
tokenizer.consume(":");
boolean array = tokenizer.tryConsume("[");
if (array) {
while (!tokenizer.tryConsume("]")) {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown);
tokenizer.tryConsume(",");
}
} else {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown);
}
}
if (tokenizer.tryConsume(",")) {
// Continue with the next field
mergeField(tokenizer, extensionRegistry, builder);
}
}
/**
* Parse a single field from {@code tokenizer} and merge it into {@code builder}. If a ',' is
* detected after the field ends, the next field will be parsed automatically
*/
protected void mergeField(Tokenizer tokenizer,
ExtensionRegistry extensionRegistry,
Message.Builder builder) throws ParseException {
FieldDescriptor field;
Descriptor type = builder.getDescriptorForType();
ExtensionRegistry.ExtensionInfo extension = null;
boolean unknown = false;
String name = tokenizer.consumeIdentifier();
field = type.findFieldByName(name);
// Group names are expected to be capitalized as they appear in the
// .proto file, which actually matches their type names, not their field
// names.
if (field == null) {
// Explicitly specify US locale so that this code does not break when
// executing in Turkey.
String lowerName = name.toLowerCase(Locale.US);
field = type.findFieldByName(lowerName);
// If the case-insensitive match worked but the field is NOT a group,
if ((field != null) && (field.getType() != FieldDescriptor.Type.GROUP)) {
field = null;
}
}
// Again, special-case group names as described above.
if ((field != null) && (field.getType() == FieldDescriptor.Type.GROUP)
&& !field.getMessageType().getName().equals(name)) {
field = null;
}
// Last try to lookup by field-index if 'name' is numeric,
// which indicates a possible unknown field
if (field == null && TextUtils.isDigits(name)) {
field = type.findFieldByNumber(Integer.parseInt(name));
unknown = true;
}
// Finally, look for extensions
extension = extensionRegistry.findExtensionByName(name);
if (extension != null) {
if (extension.descriptor.getContainingType() != type) {
throw tokenizer.parseExceptionPreviousToken("Extension \"" + name
+ "\" does not extend message type \""
+ type.getFullName() + "\".");
}
field = extension.descriptor;
}
// Disabled throwing exception if field not found, since it could be a different version.
if (field == null) {
handleMissingField(tokenizer, extensionRegistry, builder);
//throw tokenizer.parseExceptionPreviousToken("Message type \"" + type.getFullName()
// + "\" has no field named \"" + name
// + "\".");
}
if (field != null) {
tokenizer.consume(":");
boolean array = tokenizer.tryConsume("[");
if (array) {
while (!tokenizer.tryConsume("]")) {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown);
tokenizer.tryConsume(",");
}
} else {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown);
}
}
if (tokenizer.tryConsume(",")) {
// Continue with the next field
mergeField(tokenizer, extensionRegistry, builder);
}
}