Code review comment: We want to switch this metadata to use options. However you are translating proto option names directly to field names, which means there's no guarantee that these other options won't conflict. Maybe prefix all of these options with something to prevent potential conflict?

Code before review:
static Schema getSchema(Descriptors.Descriptor descriptor) {
Set<Integer> oneOfFields = Sets.newHashSet();
List<Field> fields = Lists.newArrayListWithCapacity(descriptor.getFields().size());
for (OneofDescriptor oneofDescriptor : descriptor.getOneofs()) {
List<Field> subFields = Lists.newArrayListWithCapacity(oneofDescriptor.getFieldCount());
Map<String, Integer> enumIds = Maps.newHashMap();
for (FieldDescriptor fieldDescriptor : oneofDescriptor.getFields()) {
oneOfFields.add(fieldDescriptor.getNumber());
FieldType fieldType =
withMetaData(beamFieldTypeFromProtoField(fieldDescriptor), fieldDescriptor);
subFields.add(Field.nullable(fieldDescriptor.getName(), fieldType));
checkArgument(
enumIds.putIfAbsent(fieldDescriptor.getName(), fieldDescriptor.getNumber()) == null);
}
FieldType oneOfType = FieldType.logicalType(OneOfType.create(subFields, enumIds));
fields.add(Field.of(oneofDescriptor.getName(), oneOfType));
}
for (Descriptors.FieldDescriptor fieldDescriptor : descriptor.getFields()) {
if (!oneOfFields.contains(fieldDescriptor.getNumber())) {
FieldType fieldType =
withMetaData(beamFieldTypeFromProtoField(fieldDescriptor), fieldDescriptor);
fields.add(
Field.of(fieldDescriptor.getName(), fieldType)
.withOptions(getFieldOptions(fieldDescriptor)));
}
}
return Schema.builder().addFields(fields).setOptions(getSchemaOptions(descriptor)).build();
}

Line under review: return Schema.builder().addFields(fields).setOptions(getSchemaOptions(descriptor)).build();

Code after addressing the review:
static Schema getSchema(Descriptors.Descriptor descriptor) {
Set<Integer> oneOfFields = Sets.newHashSet();
List<Field> fields = Lists.newArrayListWithCapacity(descriptor.getFields().size());
for (OneofDescriptor oneofDescriptor : descriptor.getOneofs()) {
List<Field> subFields = Lists.newArrayListWithCapacity(oneofDescriptor.getFieldCount());
Map<String, Integer> enumIds = Maps.newHashMap();
for (FieldDescriptor fieldDescriptor : oneofDescriptor.getFields()) {
oneOfFields.add(fieldDescriptor.getNumber());
FieldType fieldType = beamFieldTypeFromProtoField(fieldDescriptor);
subFields.add(
withFieldNumber(
Field.nullable(fieldDescriptor.getName(), fieldType), fieldDescriptor.getNumber()));
checkArgument(
enumIds.putIfAbsent(fieldDescriptor.getName(), fieldDescriptor.getNumber()) == null);
}
FieldType oneOfType = FieldType.logicalType(OneOfType.create(subFields, enumIds));
fields.add(Field.of(oneofDescriptor.getName(), oneOfType));
}
for (Descriptors.FieldDescriptor fieldDescriptor : descriptor.getFields()) {
if (!oneOfFields.contains(fieldDescriptor.getNumber())) {
FieldType fieldType = beamFieldTypeFromProtoField(fieldDescriptor);
fields.add(
withFieldNumber(
Field.of(fieldDescriptor.getName(), fieldType), fieldDescriptor.getNumber())
.withOptions(getFieldOptions(fieldDescriptor)));
}
}
return Schema.builder()
.addFields(fields)
.setOptions(
getSchemaOptions(descriptor)
.setOption(
SCHEMA_OPTION_META_TYPE_NAME, FieldType.STRING, descriptor.getFullName()))
.build();
}