下面列出了怎么用com.google.protobuf.Descriptors.FieldDescriptor.JavaType的API类实例代码及写法,或者点击链接到github查看源代码。
private static Descriptors.FieldDescriptor.JavaType getJavaType(@Nonnull Object o) {
if (o instanceof Boolean) {
return JavaType.BOOLEAN;
} else if (o instanceof ByteString || o instanceof byte[]) {
return JavaType.BYTE_STRING;
} else if (o instanceof Double) {
return JavaType.DOUBLE;
} else if (o instanceof Float) {
return JavaType.FLOAT;
} else if (o instanceof Long) {
return JavaType.LONG;
} else if (o instanceof Integer) {
return JavaType.INT;
} else if (o instanceof String) {
return JavaType.STRING;
} else if (o instanceof Internal.EnumLite) {
return JavaType.ENUM;
} else {
throw new RecordCoreException(o.getClass() + " is an invalid type for a comparand");
}
}
/**
* The elements of the given repeated field will be treated as a map for diffing purposes, with
* {@code key} being the map key. Thus, elements with the same key will be compared even if they
* do not appear at the same index. Differences are reported similarly to {@link #treatAsSet},
* except that {@link ReportType#MODIFIED} is used to report elements with the same key but
* different values. Note that if an element is both moved and modified, only {@link
* ReportType#MODIFIED} will be used. As with {@link #treatAsSet}, if the only differences
* between the compared messages is that some fields have been moved, then {@link #compare} will
* return true.
*
* @throws IllegalArgumentException if the field is not repeated, is not a message, is already
* being as a set for comparison, or is not a containing type of the key
*/
public Builder treatAsMap(FieldDescriptor field, FieldDescriptor key) {
Preconditions.checkArgument(
field.isRepeated(), "Field must be repeated: %s", field.getFullName());
Preconditions.checkArgument(
field.getJavaType() == JavaType.MESSAGE,
"Field has to be message type: %s",
field.getFullName());
Preconditions.checkArgument(
key.getContainingType().equals(field.getMessageType()),
"%s must be a direct subfield within the repeated field: %s",
key.getFullName(),
field.getFullName());
Preconditions.checkArgument(
!setFields.contains(field),
"Cannot treat this repeated field as both Map and Set for comparison: %s",
key.getFullName());
MultipleFieldsMapKeyComparator keyComparator = new MultipleFieldsMapKeyComparator(key);
mapKeyComparatorMap.put(field, keyComparator);
return this;
}
public Builder treatAsMapWithMultipleFieldsAsKey(
FieldDescriptor field, List<FieldDescriptor> keyFields) {
Preconditions.checkArgument(
field.isRepeated(), "Field must be repeated " + field.getFullName());
Preconditions.checkArgument(
JavaType.MESSAGE.equals(field.getJavaType()),
"Field has to be message type. Field name is: " + field.getFullName());
for (int i = 0; i < keyFields.size(); ++i) {
FieldDescriptor key = keyFields.get(i);
Preconditions.checkArgument(
key.getContainingType().equals(field.getMessageType()),
key.getFullName()
+ " must be a direct subfield within the repeated field: "
+ field.getFullName());
}
Preconditions.checkArgument(
!setFields.contains(field),
"Cannot treat this repeated field as both Map and Set for comparison.");
MapKeyComparator keyComparator = new MultipleFieldsMapKeyComparator(keyFields);
mapKeyComparatorMap.put(field, keyComparator);
return this;
}
/** Recursively crawls the proto message while clearing each field of type {@link Source}. */
@VisibleForTesting
static void stripSourceReferences(Message.Builder msg) {
for (FieldDescriptor fieldDesc : msg.getAllFields().keySet()) {
if (!fieldDesc.getJavaType().equals(JavaType.MESSAGE)) {
continue;
}
if (fieldDesc.getMessageType().getFullName().equals(Source.getDescriptor().getFullName())) {
msg.clearField(fieldDesc);
} else {
if (fieldDesc.isRepeated()) {
int repeatCount = msg.getRepeatedFieldCount(fieldDesc);
for (int i = 0; i < repeatCount; i++) {
stripSourceReferences(msg.getRepeatedFieldBuilder(fieldDesc, i));
}
} else {
stripSourceReferences(msg.getFieldBuilder(fieldDesc));
}
}
}
}
private static void shuffleRepeatedFields(Message.Builder shuffled) {
for (FieldDescriptor field : shuffled.getAllFields().keySet()) {
// Shuffle all contained proto messages recursively.
if (field.getJavaType() == JavaType.MESSAGE) {
if (field.isRepeated()) {
IntStream.range(0, shuffled.getRepeatedFieldCount(field))
.forEach(i -> shuffleRepeatedFields(shuffled.getRepeatedFieldBuilder(field, i)));
} else {
shuffleRepeatedFields(shuffled.getFieldBuilder(field));
}
}
// Shuffle values of the field itself.
if (field.isRepeated()) {
int len = shuffled.getRepeatedFieldCount(field);
for (int i = 0; i < len - 1; i++) {
swapRepeatedFieldValues(shuffled, field, i, i + RAND.nextInt(len - i));
}
}
}
}
/**
* Returns the method to get the value for the field within its message. The message must already
* be on the execution stack. For map fields, this will be the method that returns a {@link
* java.util.Map} and for repeated fields it will be the method that returns a {@link List}.
*/
Method getValueMethod() {
StringBuilder methodName = new StringBuilder().append("get").append(camelCaseName);
if (valueJavaType() == JavaType.ENUM) {
methodName.append("Value");
}
if (isMapField()) {
methodName.append("Map");
} else if (field.isRepeated()) {
methodName.append("List");
}
try {
return containingPrototype.getClass().getDeclaredMethod(methodName.toString());
} catch (NoSuchMethodException e) {
throw new IllegalStateException("Could not find generated getter method.", e);
}
}
private SingularField compareSingularValue(
@NullableDecl Object actual,
@NullableDecl Object expected,
@NullableDecl Object defaultValue,
boolean excludeNonRecursive,
FieldDescriptor fieldDescriptor,
String fieldName,
FluentEqualityConfig config) {
if (fieldDescriptor.getJavaType() == JavaType.MESSAGE) {
return compareSingularMessage(
(Message) actual,
(Message) expected,
(Message) defaultValue,
excludeNonRecursive,
fieldDescriptor,
fieldName,
config);
} else if (excludeNonRecursive) {
return SingularField.ignored(fieldName);
} else {
return compareSingularPrimitive(
actual, expected, defaultValue, fieldDescriptor, fieldName, config);
}
}
private void dumpValue(DynamicMessage.Builder builder, Descriptors.FieldDescriptor fd, Object val) {
if (JavaType.ENUM == fd.getJavaType()) {
Descriptors.EnumValueDescriptor enum_val = null;
if (val instanceof Descriptors.EnumValueDescriptor) {
enum_val = (Descriptors.EnumValueDescriptor) val;
} else {
val = get_enum_value(cachePbs, fd.getEnumType(), (Integer) val);
}
if (null == enum_val) {
return;
}
if (fd.isRepeated()) {
builder.addRepeatedField(fd, enum_val);
} else {
builder.setField(fd, enum_val);
}
} else {
if (fd.isRepeated()) {
builder.addRepeatedField(fd, val);
} else {
builder.setField(fd, val);
}
}
}
private ParquetType getParquetType(FieldDescriptor fieldDescriptor) {
JavaType javaType = fieldDescriptor.getJavaType();
switch (javaType) {
case INT: return ParquetType.of(INT32);
case LONG: return ParquetType.of(INT64);
case DOUBLE: return ParquetType.of(DOUBLE);
case BOOLEAN: return ParquetType.of(BOOLEAN);
case FLOAT: return ParquetType.of(FLOAT);
case STRING: return ParquetType.of(BINARY, stringType());
case ENUM: return ParquetType.of(BINARY, enumType());
case BYTE_STRING: return ParquetType.of(BINARY);
default:
throw new UnsupportedOperationException("Cannot convert Protocol Buffer: unknown type " + javaType);
}
}
protected Class<?> getJavaType(FieldDescriptor fieldDescriptor) {
if (fieldDescriptor.getJavaType() == JavaType.BOOLEAN) {
return Boolean.class;
} else if (fieldDescriptor.getJavaType() == JavaType.BYTE_STRING) {
return DataHandler.class;
} else if (fieldDescriptor.getJavaType() == JavaType.DOUBLE) {
return Double.class;
} else if (fieldDescriptor.getJavaType() == JavaType.FLOAT) {
return Float.class;
} else if (fieldDescriptor.getJavaType() == JavaType.INT) {
return Integer.class;
} else if (fieldDescriptor.getJavaType() == JavaType.LONG) {
return Long.class;
} else if (fieldDescriptor.getJavaType() == JavaType.STRING) {
return String.class;
} else if (fieldDescriptor.getJavaType() == JavaType.ENUM) {
try {
return Class.forName("org.bimserver.interfaces.objects." + fieldDescriptor.getEnumType().getName());
} catch (ClassNotFoundException e) {
LOGGER.error("", e);
}
}
return null;
}
protected Class<?> getJavaPrimitiveType(FieldDescriptor fieldDescriptor) {
if (fieldDescriptor.getJavaType() == JavaType.BOOLEAN) {
return boolean.class;
} else if (fieldDescriptor.getJavaType() == JavaType.BYTE_STRING) {
return DataHandler.class;
} else if (fieldDescriptor.getJavaType() == JavaType.DOUBLE) {
return double.class;
} else if (fieldDescriptor.getJavaType() == JavaType.FLOAT) {
return float.class;
} else if (fieldDescriptor.getJavaType() == JavaType.INT) {
return int.class;
} else if (fieldDescriptor.getJavaType() == JavaType.LONG) {
return long.class;
} else if (fieldDescriptor.getJavaType() == JavaType.STRING) {
return String.class;
} else if (fieldDescriptor.getJavaType() == JavaType.ENUM) {
try {
return Class.forName("org.bimserver.interfaces.objects." + fieldDescriptor.getEnumType().getName());
} catch (ClassNotFoundException e) {
LOGGER.error("", e);
}
}
return null;
}
public static ExtensionRegistry getInstance() {
ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
Iterable<FieldDescriptor> extensionDescriptors = Iterables.concat(
AllExtensions.getDescriptor().getExtensions(),
RepeatedExtensions.getDescriptor().getExtensions()
);
for (FieldDescriptor extension : extensionDescriptors) {
if (extension.getJavaType() == JavaType.MESSAGE) {
extensionRegistry.add(extension, Nested.getDefaultInstance());
} else {
extensionRegistry.add(extension);
}
}
return extensionRegistry;
}
public Builder treatAsMapUsingKeyComparator(
FieldDescriptor field, MapKeyComparator keyComparator) {
Preconditions.checkArgument(
field.isRepeated(), "Field must be repeated " + field.getFullName());
Preconditions.checkArgument(
JavaType.MESSAGE.equals(field.getJavaType()),
"Field has to be message type. Field name is: " + field.getFullName());
Preconditions.checkArgument(
!setFields.contains(field),
"Cannot treat this repeated field as both Map and Set for comparison.");
mapKeyComparatorMap.put(field, keyComparator);
return this;
}
boolean compareFieldValueUsingParentFields(
Message message1,
Message message2,
FieldDescriptor field,
int index1,
int index2,
@Nullable Reporter reporter,
List<SpecificField> stack) {
FieldComparator.ComparisonResult result =
fieldComparator.compare(
message1, message2, field, index1, index2, ImmutableList.copyOf(stack));
if (result == FieldComparator.ComparisonResult.RECURSE) {
Preconditions.checkArgument(
field.getJavaType() == JavaType.MESSAGE,
"FieldComparator should not return RECURSE for fields not being submessages!");
// Get the nested messages and compare them using one of the
// methods.
Message nextMessage1 =
field.isRepeated()
? (Message) message1.getRepeatedField(field, index1)
: (Message) message1.getField(field);
Message nextMessage2 =
field.isRepeated()
? (Message) message2.getRepeatedField(field, index2)
: (Message) message2.getField(field);
stack.add(
field.isRepeated()
? SpecificField.forRepeatedField(field, index1, index2)
: SpecificField.forField(field));
boolean isSame = compare(nextMessage1, nextMessage2, reporter, stack);
pop(stack);
return isSame;
}
return result == FieldComparator.ComparisonResult.SAME;
}
/**
* Gets the {@link Class} object corresponding to the given message field.
*
* <p>If the field is repeated, then returns the class of the single item, rather than the
* collection class.
*/
@SuppressWarnings("unchecked") // The unchecked cast is executed for proto message field only.
public static <T extends Message> Class<? extends Message> getJavaClassOfMessageField(
T message, FieldDescriptor field) {
checkArgument(field.getType().getJavaType().equals(JavaType.MESSAGE));
if (field.isRepeated()) {
String fieldGetterName = getterNameForProtoField(field);
try {
Method fieldGetter = message.getClass().getMethod(fieldGetterName);
ParameterizedType fieldTypeArg = (ParameterizedType) fieldGetter.getGenericReturnType();
checkState(
fieldTypeArg.getActualTypeArguments().length == 1,
"Collection representing a repeated field should have exactly one type argument.");
return (Class<? extends Message>) fieldTypeArg.getActualTypeArguments()[0];
} catch (NoSuchMethodException e) {
throw new RuntimeException(
"Failed to resolve getter of repeated field "
+ field.getName()
+ " in proto "
+ message.getClass().getName(),
e);
}
} else {
return (Class<? extends Message>) message.getField(field).getClass();
}
}
/**
* Return the Java {@link Class} that corresponds to the value of this field. Generally used for
* method resolution and casting generics.
*/
Class<?> javaClass() {
if (isMapField() && valueJavaType() == JavaType.MESSAGE) {
Message mapEntry = containingPrototype.newBuilderForType().newBuilderForField(field).build();
return mapEntry.getField(mapEntry.getDescriptorForType().findFieldByName("value")).getClass();
}
switch (valueJavaType()) {
case INT:
return int.class;
case LONG:
return long.class;
case FLOAT:
return float.class;
case DOUBLE:
return double.class;
case BOOLEAN:
return boolean.class;
case STRING:
return String.class;
case BYTE_STRING:
return ByteString.class;
case ENUM:
return int.class;
case MESSAGE:
return containingPrototype
.newBuilderForType()
.newBuilderForField(valueField().descriptor())
.build()
.getClass();
default:
throw new IllegalArgumentException("Unknown field type: " + valueJavaType());
}
}
/**
* Returns the {@link StackManipulation} for setting the value of a field. This will be all the
* elements for a repeated field.
*
* @param info description of the field to set.
* @param beforeReadField jump target for before reading a field, used once this field is
* completed being set.
* @param locals the method local variables
* @param fieldsByName the instance fields
*/
private StackManipulation setFieldValue(
ProtoFieldInfo info,
Label beforeReadField,
LocalVariables<LocalVariable> locals,
Map<String, FieldDescription> fieldsByName) {
if (info.isMapField()) {
return setMapFieldValue(info, beforeReadField, locals, fieldsByName);
} else {
final StackManipulation setConcreteValue = invoke(info.setValueMethod());
final StackManipulation setSingleValue;
if (info.valueJavaType() == JavaType.MESSAGE) {
setSingleValue =
new StackManipulation.Compound(
TypeCasting.to(new ForLoadedType(info.javaClass())), setConcreteValue);
} else if (info.valueType() == Type.ENUM && !info.isRepeated()) {
// For non-repeated enums, we treat unknown as the default value.
setSingleValue =
new StackManipulation.Compound(ParseSupport_mapUnknownEnumValue, setConcreteValue);
} else {
setSingleValue = setConcreteValue;
}
if (info.descriptor().isRepeated()) {
return setRepeatedFieldValue(info, beforeReadField, locals, fieldsByName, setSingleValue);
} else {
// Set a singular value, e.g.,
// builder.setFoo(readValue());
return new StackManipulation.Compound(
locals.load(LocalVariable.builder),
locals.load(LocalVariable.parser),
readValue(info, fieldsByName, locals),
setSingleValue,
Removal.SINGLE,
new Goto(beforeReadField));
}
}
}
/**
* Determines whether we skip processing of the field if it is null. We usually skip null values
* in the JSON to treat them as default, but must actually process the null for {@link Value} and
* {@link NullValue} because it means their value must be set.
*/
private static boolean mustSkipNull(FieldDescriptor field) {
if (field.isRepeated()) {
return true;
}
if (field.getJavaType() == JavaType.MESSAGE
&& field.getMessageType() == Value.getDescriptor()) {
return false;
}
if (field.getJavaType() == JavaType.ENUM && field.getEnumType() == NullValue.getDescriptor()) {
return false;
}
return true;
}
/**
* 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;
}
/**
* Collects enums referred to by a message and its nested messages.
*
* @return {@code referenced}
*/
private static Collection<EnumDescriptor> collectEnums(
Descriptor d, Collection<EnumDescriptor> referenced) {
for (FieldDescriptor fd : d.getFields()) {
if (fd.getJavaType() == JavaType.ENUM) {
referenced.add(fd.getEnumType());
}
}
for (Descriptor nd : d.getNestedTypes()) {
collectEnums(nd, referenced);
}
return referenced;
}
private <T> Builder<? extends Builder<?, GroupBuilder<T>>, GroupBuilder<T>> addField(FieldDescriptor descriptor, final GroupBuilder<T> builder) {
if (descriptor.getJavaType() == JavaType.MESSAGE) {
return addMessageField(descriptor, builder);
}
ParquetType parquetType = getParquetType(descriptor);
if (descriptor.isRepeated() && parquetSpecsCompliant) {
// the old schema style did not include the LIST wrapper around repeated fields
return addRepeatedPrimitive(parquetType.primitiveType, parquetType.logicalTypeAnnotation, builder);
}
return builder.primitive(parquetType.primitiveType, getRepetition(descriptor)).as(parquetType.logicalTypeAnnotation);
}
/**
* 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;
}
/**
* Collects enums referred to by a message and its nested messages.
*
* @return {@code referenced}
*/
private static Collection<EnumDescriptor> collectEnums(
Descriptor d, Collection<EnumDescriptor> referenced) {
for (FieldDescriptor fd : d.getFields()) {
if (fd.getJavaType() == JavaType.ENUM) {
referenced.add(fd.getEnumType());
}
}
for (Descriptor nd : d.getNestedTypes()) {
collectEnums(nd, referenced);
}
return referenced;
}
@Override
public void report(
ReportType type,
Message message1,
Message message2,
ImmutableList<SpecificField> fieldPath) {
try {
if ((type == ReportType.MODIFIED) && !reportModifiedAggregates) {
SpecificField specificField = Iterables.getLast(fieldPath);
if (specificField.getField() == null) {
if (specificField.getUnknown().getFieldType() == UnknownFieldType.GROUP) {
// Any changes to the subfields have already been printed.
return;
}
} else if (specificField.getField().getJavaType() == JavaType.MESSAGE) {
// Any changes to the subfields have already been printed.
return;
}
}
String tentativeNewline = "";
if (fieldPath.size() == 1) {
tentativeNewline = "\n";
}
output.append(type.name().toLowerCase()).append(": ");
switch (type) {
case ADDED:
appendPath(fieldPath, false);
output.append(": ");
appendValue(message2, fieldPath, false);
break;
case DELETED:
appendPath(fieldPath, true);
output.append(": ");
appendValue(message1, fieldPath, true);
break;
case IGNORED:
appendPath(fieldPath, false);
break;
case MOVED:
appendPath(fieldPath, true);
output.append(" -> ");
appendPath(fieldPath, false);
output.append(" : ");
appendValue(message1, fieldPath, true);
break;
case MODIFIED:
appendPath(fieldPath, true);
if (checkPathChanged(fieldPath)) {
output.append(" -> ");
appendPath(fieldPath, false);
}
output.append(":" + tentativeNewline);
appendValue(message1, fieldPath, true);
output.append(" -> " + tentativeNewline);
appendValue(message2, fieldPath, false);
break;
case MATCHED:
appendPath(fieldPath, true);
if (checkPathChanged(fieldPath)) {
output.append(" -> ");
appendPath(fieldPath, false);
}
output.append(" : ");
appendValue(message1, fieldPath, true);
break;
default:
throw new RuntimeException("Unknown ReportType");
}
output.append("\n" + tentativeNewline);
} catch (IOException e) {
throw new StreamException(e);
}
}
/**
* Returns the {@link StackManipulation} for setting the value of a map field.
*
* <p>Roughly equivalent to:
*
* <pre>{@code
* ParseSupport.parseObjectStart(parser);
* while (!ParseSupport.checkObjectEnd(parser.currentToken())) {
* builder.putFoo(readKey(), readValue());
* }
* }</pre>
*/
private StackManipulation setMapFieldValue(
ProtoFieldInfo info,
Label beforeReadField,
LocalVariables<LocalVariable> locals,
Map<String, FieldDescription> fieldsByName) {
final StackManipulation setConcreteValue = invoke(info.setValueMethod());
final StackManipulation setMapEntry;
if (info.valueJavaType() == JavaType.MESSAGE) {
setMapEntry =
new StackManipulation.Compound(
TypeCasting.to(new ForLoadedType(info.javaClass())), setConcreteValue);
} else {
setMapEntry = setConcreteValue;
}
Label mapStart = new Label();
Label afterSet = new Label();
StackManipulation.Compound beforeReadKey =
new StackManipulation.Compound(
locals.load(LocalVariable.parser),
ParseSupport_parseObjectStart,
new SetJumpTargetLabel(mapStart),
locals.load(LocalVariable.parser),
Parser_currentToken,
ParseSupport_checkObjectEnd,
new IfTrue(beforeReadField));
StackManipulation.Compound setValueAndPrepareForNext =
new StackManipulation.Compound(
setMapEntry,
Removal.SINGLE,
new SetJumpTargetLabel(afterSet),
locals.load(LocalVariable.parser),
Parser_nextToken,
Removal.SINGLE,
new Goto(mapStart));
if (info.valueType() == Type.ENUM) {
// We special-case enum since we may need to skip unknown values.
final LocalVariable keyVar;
switch (info.mapKeyField().valueJavaType()) {
case INT:
keyVar = LocalVariable.intMapKey;
break;
case LONG:
keyVar = LocalVariable.longMapKey;
break;
case BOOLEAN:
keyVar = LocalVariable.boolMapKey;
break;
case STRING:
keyVar = LocalVariable.stringMapKey;
break;
default:
throw new IllegalArgumentException("Invalid map key type");
}
return new StackManipulation.Compound(
beforeReadKey,
locals.load(LocalVariable.parser),
readValue(info.mapKeyField(), fieldsByName, locals),
locals.store(keyVar),
locals.load(LocalVariable.parser),
Parser_nextToken,
Removal.SINGLE,
locals.load(LocalVariable.parser),
readValue(info, fieldsByName, locals),
locals.store(LocalVariable.intvalue),
locals.load(LocalVariable.intvalue),
IntegerConstant.forValue(-1),
new IfEqual(int.class, afterSet),
locals.load(LocalVariable.builder),
locals.load(keyVar),
locals.load(LocalVariable.intvalue),
setValueAndPrepareForNext);
} else {
return new StackManipulation.Compound(
beforeReadKey,
locals.load(LocalVariable.builder),
locals.load(LocalVariable.parser),
readValue(info.mapKeyField(), fieldsByName, locals),
locals.load(LocalVariable.parser),
Parser_nextToken,
Removal.SINGLE,
locals.load(LocalVariable.parser),
readValue(info, fieldsByName, locals),
setValueAndPrepareForNext);
}
}
private static boolean supportsFieldPresence(FieldDescriptor field) {
// messages still support field presence in proto3
return field.getJavaType() == JavaType.MESSAGE;
}
/**
* Returns the {@link JavaType} of the actual value of this field, which for map fields is the
* type of the map's value.
*/
FieldDescriptor.JavaType valueJavaType() {
return valueField().descriptor().getJavaType();
}