下面列出了com.google.protobuf.Descriptors.Descriptor#getFields ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void generateProtoFromDescriptor(Descriptor descriptor,
Appendable out, String indent, Map<Descriptor, Boolean> descriptors)
throws IOException {
descriptors.put(descriptor, true);
out.append(indent + "message " + descriptor.getName() + " {\n");
for (FieldDescriptor fieldDescriptor : descriptor.getFields()) {
generateProtoFromDescriptor(fieldDescriptor, out, indent + " ",
descriptors);
}
for (Descriptor nested : descriptor.getNestedTypes()) {
generateProtoFromDescriptor(nested, out, indent + " ",
descriptors);
}
for (EnumDescriptor enumDescriptor : descriptor.getEnumTypes()) {
generateProtoFromDescriptor(enumDescriptor, out, indent + " ");
}
out.append(indent + "}\n");
}
/** Internal helper which returns a mutable map. */
private Map<FieldDescriptor, Object> getAllFieldsMutable() {
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
for (final FieldDescriptor field : descriptor.getFields()) {
if (field.isRepeated()) {
final List<?> value = (List<?>) getField(field);
if (!value.isEmpty()) {
result.put(field, value);
}
} else {
if (hasField(field)) {
result.put(field, getField(field));
}
}
}
return result;
}
public GroupConverter(Group group, Descriptor groupMessage) {
super(group.getRoot().getTableId(), groupMessage);
Map<String,Table> tablesByUuid = new HashMap<>();
getUuids(group.getRoot(), tablesByUuid);
tableConvertersByTableId = new HashMap<>(tablesByUuid.size());
groupFieldsByTabelId = new HashMap<>(tablesByUuid.size());
tableConvertersByField = new HashMap<>(tablesByUuid.size());
for (FieldDescriptor field : groupMessage.getFields()) {
String uuid = field.getOptions().getExtension(ColumnOptions.fdbsql).getUuid();
Table table = tablesByUuid.get(uuid);
if (table != null) {
ProtobufRowDataConverter converter = new TableConverter(table, field.getMessageType());
tableConvertersByTableId.put(table.getTableId(), converter);
groupFieldsByTabelId.put(table.getTableId(), field);
tableConvertersByField.put(field, converter);
}
}
}
public GroupConverter(Group group, Descriptor groupMessage) {
super(group.getRoot().getTableId(), groupMessage);
Map<String,Table> tablesByUuid = new HashMap<>();
getUuids(group.getRoot(), tablesByUuid);
tableConvertersByTableId = new HashMap<>(tablesByUuid.size());
groupFieldsByTabelId = new HashMap<>(tablesByUuid.size());
tableConvertersByField = new HashMap<>(tablesByUuid.size());
for (FieldDescriptor field : groupMessage.getFields()) {
String uuid = field.getOptions().getExtension(ColumnOptions.fdbsql).getUuid();
Table table = tablesByUuid.get(uuid);
if (table != null) {
ProtobufRowConverter converter = new TableConverter(table, field.getMessageType());
tableConvertersByTableId.put(table.getTableId(), converter);
groupFieldsByTabelId.put(table.getTableId(), field);
tableConvertersByField.put(field, converter);
}
}
}
/** Internal helper which returns a mutable map. */
private Map<FieldDescriptor, Object> getAllFieldsMutable() {
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
for (final FieldDescriptor field : descriptor.getFields()) {
if (field.isRepeated()) {
final List value = (List) getField(field);
if (!value.isEmpty()) {
result.put(field, value);
}
} else {
if (hasField(field)) {
result.put(field, getField(field));
}
}
}
return result;
}
/** Internal helper which returns a mutable map. */
private Map<FieldDescriptor, Object> getAllFieldsMutable() {
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
for (final FieldDescriptor field : descriptor.getFields()) {
if (field.isRepeated()) {
final List<?> value = (List<?>) getField(field);
if (!value.isEmpty()) {
result.put(field, value);
}
} else {
if (hasField(field)) {
result.put(field, getField(field));
}
}
}
return result;
}
@SuppressWarnings("unchecked")
MessageWriter(Descriptor descriptor, GroupType schema) {
List<FieldDescriptor> fields = descriptor.getFields();
fieldWriters = (FieldWriter[]) Array.newInstance(FieldWriter.class, fields.size());
for (FieldDescriptor fieldDescriptor: fields) {
String name = fieldDescriptor.getName();
Type type = schema.getType(name);
FieldWriter writer = createWriter(fieldDescriptor, type);
if(writeSpecsCompliant && fieldDescriptor.isRepeated() && !fieldDescriptor.isMapField()) {
writer = new ArrayWriter(writer);
}
else if (!writeSpecsCompliant && fieldDescriptor.isRepeated()) {
// the old schemas style used to write maps as repeated fields instead of wrapping them in a LIST
writer = new RepeatedWriter(writer);
}
writer.setFieldName(name);
writer.setIndex(schema.getFieldIndex(name));
fieldWriters[fieldDescriptor.getIndex()] = writer;
}
}
@SuppressWarnings("PMD.CompareObjectsWithEquals")
@Nonnull
private Map<String, String> getTypeRenames(@Nonnull Descriptor oldUnionDescriptor, @Nonnull Descriptor newUnionDescriptor) {
if (oldUnionDescriptor == newUnionDescriptor) {
return Collections.emptyMap();
}
final Map<String, String> renames = disallowTypeRenames ? Collections.emptyMap() : new HashMap<>();
for (FieldDescriptor oldField : oldUnionDescriptor.getFields()) {
Descriptor oldRecord = oldField.getMessageType();
Descriptor newRecord = newUnionDescriptor.findFieldByNumber(oldField.getNumber()).getMessageType();
if (!oldRecord.getName().equals(newRecord.getName())) {
if (disallowTypeRenames) {
throw new MetaDataException("record type name changed",
LogMessageKeys.OLD_RECORD_TYPE, oldRecord.getName(),
LogMessageKeys.NEW_RECORD_TYPE, newRecord.getName());
}
String existingName = renames.putIfAbsent(oldRecord.getName(), newRecord.getName());
if (existingName != null && !existingName.equals(newRecord.getName())) {
// This shouldn't be possible because of the validation done in validateUnion, but it's easy enough to check here.
throw new MetaDataException("record type corresponds to multiple types in new meta-data",
LogMessageKeys.OLD_RECORD_TYPE, oldRecord.getName(),
LogMessageKeys.NEW_RECORD_TYPE, newRecord.getName() + " & " + existingName);
}
}
}
return renames;
}
private static boolean isInitialized(Descriptor type,
FieldSet<FieldDescriptor> fields) {
// Check that all required fields are present.
for (final FieldDescriptor field : type.getFields()) {
if (field.isRequired()) {
if (!fields.hasField(field)) {
return false;
}
}
}
// Check that embedded messages are initialized.
return fields.isInitialized();
}
private static boolean isInitialized(Descriptor type,
FieldSet<FieldDescriptor> fields) {
// Check that all required fields are present.
for (final FieldDescriptor field : type.getFields()) {
if (field.isRequired()) {
if (!fields.hasField(field)) {
return false;
}
}
}
// Check that embedded messages are initialized.
return fields.isInitialized();
}
/**
* Collects messages referred to by a message and its nested messages.
*
* @return {@code referenced}
*/
private static Collection<Descriptor> collectMessages(
Descriptor message, Collection<Descriptor> referenced) {
for (FieldDescriptor fd : message.getFields()) {
if (fd.getJavaType() == JavaType.MESSAGE) {
referenced.add(fd.getMessageType());
}
}
for (Descriptor nd : message.getNestedTypes()) {
collectMessages(nd, referenced);
}
return referenced;
}
/**
* Generates a random protocol buffer, filling in all required fields but
* with a p chance of not setting an optional field and p chance of having
* an empty repeated field.
*/
@SuppressWarnings("unchecked")
public E generate(double p) {
Builder builder = instance.newBuilderForType();
Descriptor descriptor = instance.getDescriptorForType();
for (FieldDescriptor field : descriptor.getFields()) {
if (!field.isRequired() && random.nextDouble() < p) {
continue;
}
builder.setField(field, getRandomValue(field, p));
}
return (E) builder.build();
}
/** validates mapping between protobuffer fields and parquet fields.*/
private void validatedMapping(Descriptor descriptor, GroupType parquetSchema) {
List<FieldDescriptor> allFields = descriptor.getFields();
for (FieldDescriptor fieldDescriptor: allFields) {
String fieldName = fieldDescriptor.getName();
int fieldIndex = fieldDescriptor.getIndex();
int parquetIndex = parquetSchema.getFieldIndex(fieldName);
if (fieldIndex != parquetIndex) {
String message = "FieldIndex mismatch name=" + fieldName + ": " + fieldIndex + " != " + parquetIndex;
throw new IncompatibleSchemaModificationException(message);
}
}
}
/**
* Collects messages referred to by a message and its nested messages.
*
* @return {@code referenced}
*/
private static Collection<Descriptor> collectMessages(
Descriptor message, Collection<Descriptor> referenced) {
for (FieldDescriptor fd : message.getFields()) {
if (fd.getJavaType() == JavaType.MESSAGE) {
referenced.add(fd.getMessageType());
}
}
for (Descriptor nd : message.getNestedTypes()) {
collectMessages(nd, referenced);
}
return referenced;
}
/**
* Generates a random protocol buffer, filling in all required fields but
* with a p chance of not setting an optional field and p chance of having
* an empty repeated field.
*/
@SuppressWarnings("unchecked")
public E generate(double p) {
Builder builder = instance.newBuilderForType();
Descriptor descriptor = instance.getDescriptorForType();
for (FieldDescriptor field : descriptor.getFields()) {
if (!field.isRequired() && random.nextDouble() < p) {
continue;
}
builder.setField(field, getRandomValue(field, p));
}
return (E) builder.build();
}
private static void compare(
FieldMask.Builder mask, String currentField, Message original, Message modified) {
Descriptor descriptor = original.getDescriptorForType();
for (FieldDescriptor field : descriptor.getFields()) {
String fieldName = getFieldName(currentField, field);
Object originalValue = original.getField(field);
Object modifiedValue = modified.getField(field);
if (field.isRepeated()) {
if (!Objects.equals(originalValue, modifiedValue)) {
mask.addPaths(fieldName);
}
} else {
switch (field.getJavaType()) {
case MESSAGE:
// Because getField never returns null, we use hasField to distinguish null
// from empty message when getType() == MESSAGE
if (original.hasField(field) != modified.hasField(field)
|| !Objects.equals(originalValue, modifiedValue)) {
if (isWrapperType(field.getMessageType())) {
// For wrapper types, just emit the field name.
mask.addPaths(fieldName);
} else if (!modified.hasField(field)) {
// Just emit the deleted field name
mask.addPaths(fieldName);
} else {
// Recursively compare to find different values
compare(mask, fieldName, (Message) originalValue, (Message) modifiedValue);
}
}
break;
case INT:
case LONG:
case FLOAT:
case DOUBLE:
case BOOLEAN:
case STRING:
case BYTE_STRING:
case ENUM:
// Handle all java types except MESSAGE
if (!Objects.equals(originalValue, modifiedValue)) {
mask.addPaths(fieldName);
}
break;
default:
throw new IllegalArgumentException(
"Unexpected java type "
+ field.getJavaType()
+ " encountered for field "
+ fieldName);
}
}
}
}
public MessageDescriptorContainer(Descriptor descriptor) {
this.descriptor = descriptor;
for (FieldDescriptor fieldDescriptor : descriptor.getFields()) {
fieldDescriptors.put(fieldDescriptor.getName(), fieldDescriptor);
}
}
/**
* Internal helper to return a modifiable map containing all the fields.
* The returned Map is modifialbe so that the caller can add additional
* extension fields to implement {@link #getAllFields()}.
*
* @param getBytesForString whether to generate ByteString for string fields
*/
private Map<FieldDescriptor, Object> getAllFieldsMutable(
boolean getBytesForString) {
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
final List<FieldDescriptor> fields = descriptor.getFields();
for (int i = 0; i < fields.size(); i++) {
FieldDescriptor field = fields.get(i);
final OneofDescriptor oneofDescriptor = field.getContainingOneof();
/*
* If the field is part of a Oneof, then at maximum one field in the Oneof is set
* and it is not repeated. There is no need to iterate through the others.
*/
if (oneofDescriptor != null) {
// Skip other fields in the Oneof we know are not set
i += oneofDescriptor.getFieldCount() - 1;
if (!hasOneof(oneofDescriptor)) {
// If no field is set in the Oneof, skip all the fields in the Oneof
continue;
}
// Get the pointer to the only field which is set in the Oneof
field = getOneofFieldDescriptor(oneofDescriptor);
} else {
// If we are not in a Oneof, we need to check if the field is set and if it is repeated
if (field.isRepeated()) {
final List<?> value = (List<?>) getField(field);
if (!value.isEmpty()) {
result.put(field, value);
}
continue;
}
if (!hasField(field)) {
continue;
}
}
// Add the field to the map
if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
result.put(field, getFieldRaw(field));
} else {
result.put(field, getField(field));
}
}
return result;
}
/** Internal helper which returns a mutable map. */
private Map<FieldDescriptor, Object> getAllFieldsMutable() {
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
final List<FieldDescriptor> fields = descriptor.getFields();
for (int i = 0; i < fields.size(); i++) {
FieldDescriptor field = fields.get(i);
final OneofDescriptor oneofDescriptor = field.getContainingOneof();
/*
* If the field is part of a Oneof, then at maximum one field in the Oneof is set
* and it is not repeated. There is no need to iterate through the others.
*/
if (oneofDescriptor != null) {
// Skip other fields in the Oneof we know are not set
i += oneofDescriptor.getFieldCount() - 1;
if (!hasOneof(oneofDescriptor)) {
// If no field is set in the Oneof, skip all the fields in the Oneof
continue;
}
// Get the pointer to the only field which is set in the Oneof
field = getOneofFieldDescriptor(oneofDescriptor);
} else {
// If we are not in a Oneof, we need to check if the field is set and if it is repeated
if (field.isRepeated()) {
final List<?> value = (List<?>) getField(field);
if (!value.isEmpty()) {
result.put(field, value);
}
continue;
}
if (!hasField(field)) {
continue;
}
}
// Add the field to the map
result.put(field, getField(field));
}
return result;
}
/**
* Tests the translate/crosslink for an example where a message field's name
* and type name are the same.
*/
public void testDescriptorComplexCrosslink() throws Exception {
FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
.setName("foo.proto")
.addMessageType(DescriptorProto.newBuilder()
.setName("Foo")
.addField(FieldDescriptorProto.newBuilder()
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_INT32)
.setName("foo")
.setNumber(1)
.build())
.build())
.addMessageType(DescriptorProto.newBuilder()
.setName("Bar")
.addField(FieldDescriptorProto.newBuilder()
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setTypeName("Foo")
.setName("Foo")
.setNumber(1)
.build())
.build())
.build();
// translate and crosslink
FileDescriptor file =
Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
new FileDescriptor[0]);
// verify resulting descriptors
assertNotNull(file);
List<Descriptor> msglist = file.getMessageTypes();
assertNotNull(msglist);
assertTrue(msglist.size() == 2);
boolean barFound = false;
for (Descriptor desc : msglist) {
if (desc.getName().equals("Bar")) {
barFound = true;
assertNotNull(desc.getFields());
List<FieldDescriptor> fieldlist = desc.getFields();
assertNotNull(fieldlist);
assertTrue(fieldlist.size() == 1);
assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
}
}
assertTrue(barFound);
}