下面列出了com.google.protobuf.Descriptors.FieldDescriptor#isMapField ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
static public Message toMessage(Builder b, Map<String, Object> params, Map<String, Object> ctx) {
for (FieldDescriptor field : b.getDescriptorForType().getFields()) {
String name = field.getName();
Object value = getValue(params, ctx, name);
if (value == null) continue;
if (field.isMapField()) {
objToMap(b, field, value);
} else if (field.isRepeated()) {
objToMessageObjRepeated(b, value, field);
} else {
if (value instanceof List) {
value = ((List) value).get(0);
if (value == null) continue;
}
objToMessageObj(b, value, field);
}
}
return b.build();
}
static public void parseMessage(Message message, Map<String, Object> results, boolean withDefault, int maxRepeatedSizeToGet) {
Map<FieldDescriptor, Object> fields = getFields(message, withDefault);
for (Map.Entry<FieldDescriptor, Object> i : fields.entrySet()) {
FieldDescriptor field = i.getKey();
Object value = i.getValue();
if (field.isMapField()) {
parseMapFieldValue(field, value, results, withDefault, maxRepeatedSizeToGet);
} else if (field.isRepeated()) {
int count = 0;
for (Object element : (List<?>) value) {
count++;
if (count <= maxRepeatedSizeToGet) {
parseSingleField(field, element, results, true, withDefault, maxRepeatedSizeToGet);
}
}
} else {
parseSingleField(field, value, results, false, withDefault, maxRepeatedSizeToGet);
}
}
}
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;
}
}
/** Get a hash code for given fields and values, using the given seed. */
@SuppressWarnings("unchecked")
protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) {
for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
FieldDescriptor field = entry.getKey();
Object value = entry.getValue();
hash = (37 * hash) + field.getNumber();
if (field.isMapField()) {
hash = (53 * hash) + hashMapField(value);
} else if (field.getType() != FieldDescriptor.Type.ENUM){
hash = (53 * hash) + value.hashCode();
} else if (field.isRepeated()) {
List<? extends EnumLite> list = (List<? extends EnumLite>) value;
hash = (53 * hash) + Internal.hashEnumList(list);
} else {
hash = (53 * hash) + Internal.hashEnum((EnumLite) value);
}
}
return hash;
}
/**
* Recursively checks whether the specified class uses any Protocol Buffers fields that cannot be
* deterministically encoded.
*
* @throws NonDeterministicException if the object cannot be encoded deterministically.
*/
static void verifyDeterministic(ProtoCoder<?> coder) throws NonDeterministicException {
Class<? extends Message> message = coder.getMessageType();
ExtensionRegistry registry = coder.getExtensionRegistry();
Set<Descriptor> descriptors = getRecursiveDescriptorsForClass(message, registry);
for (Descriptor d : descriptors) {
for (FieldDescriptor fd : d.getFields()) {
// If there is a transitively reachable Protocol Buffers map field, then this object cannot
// be encoded deterministically.
if (fd.isMapField()) {
String reason =
String.format(
"Protocol Buffers message %s transitively includes Map field %s (from file %s)."
+ " Maps cannot be deterministically encoded.",
message.getName(), fd.getFullName(), fd.getFile().getFullName());
throw new NonDeterministicException(coder, reason);
}
}
}
}
@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;
}
}
private static Object mapValue(FieldDescriptor field, Object value) {
if (value instanceof Message) {
Message message = (Message) value;
return messageToMap(message);
} else if (field.isMapField()) {
// TODO: add support and test for maps
return value;
}
// TODO: add support and tests for enums
return value;
}
private void handleMessageField(ConfigSource.Builder builder, FieldDescriptor field, Node value,
String path){
if (field.isMapField()) {
MappingNode map = NodeConverterUtils.expectMap(helper, field, value);
FieldDescriptor keyField = field.getMessageType().getFields().get(0);
FieldDescriptor valueField = field.getMessageType().getFields().get(1);
boolean isNested =
field.getMessageType().getFields().get(1).getType() == FieldDescriptor.Type.MESSAGE;
for (NodeTuple entry : map.getValue()) {
Object keyObj = NodeConverterUtils.convert(helper, keyField, entry.getKeyNode());
if (keyObj == null) {
continue;
}
if (isNested) {
String nestedPath = appendToPath(path, keyObj);
helper.checkAndAddPath(nestedPath, value, field);
builder.withBuilder(field, keyObj, new ReadNodeBuildAction(helper, entry.getValueNode(),
appendToPath(nestedPath, keyObj)));
} else {
Object valueObj = NodeConverterUtils.convert(helper, valueField, entry.getValueNode());
if (valueObj != null) {
builder.setValue(field, keyObj, valueObj, helper.getLocation(entry.getValueNode()));
}
}
}
} else if (field.isRepeated()) {
SequenceNode list = NodeConverterUtils.expectList(helper, field, value);
int index = 0;
for (Node elem : list.getValue()) {
String indexedPath = String.format("%s[%s]", path, index++);
builder.withAddedBuilder(field, new ReadNodeBuildAction(helper, elem, indexedPath));
}
} else {
builder.withBuilder(field, new ReadNodeBuildAction(helper, value, path));
}
addExplicitLocationField(builder, field, value);
}
/**
* Converts a message into a string.
*/
public String printToString(MessageOrBuilder message) {
StringBuilder result = new StringBuilder();
for (FieldDescriptor field : getFieldsInNumberOrder(message.getDescriptorForType())) {
// Skip empty fields.
if ((field.isRepeated() && message.getRepeatedFieldCount(field) == 0)
|| (!field.isRepeated() && !message.hasField(field))) {
continue;
}
// Normalize repeated and singleton fields.
Object rawValue = message.getField(field);
@SuppressWarnings("unchecked")
List<Object> values =
field.isMapField()
? sortMapEntries(field, rawValue)
: field.isRepeated()
? (List<Object>) rawValue
: ImmutableList.of(rawValue);
// Print field values.
for (Object value : values) {
result.append(printFieldToString(field, value));
}
}
return result.toString();
}
private FieldWriter createMessageWriter(FieldDescriptor fieldDescriptor, Type type) {
if (fieldDescriptor.isMapField() && writeSpecsCompliant) {
return createMapWriter(fieldDescriptor, type);
}
return new MessageWriter(fieldDescriptor.getMessageType(), getGroupType(type));
}
private <T> GroupBuilder<GroupBuilder<T>> addMessageField(FieldDescriptor descriptor, final GroupBuilder<T> builder) {
if (descriptor.isMapField() && parquetSpecsCompliant) {
// the old schema style did not include the MAP wrapper around map groups
return addMapField(descriptor, builder);
}
if (descriptor.isRepeated() && parquetSpecsCompliant) {
// the old schema style did not include the LIST wrapper around repeated messages
return addRepeatedMessage(descriptor, builder);
}
// Plain message
GroupBuilder<GroupBuilder<T>> group = builder.group(getRepetition(descriptor));
convertFields(group, descriptor.getMessageType().getFields());
return group;
}
private boolean matchRepeatedFieldIndices(
Message message1,
Message message2,
FieldDescriptor repeatedField,
int[] matchList1,
int[] matchList2,
List<SpecificField> stack) {
MapKeyComparator keyComparator = mapKeyComparatorMap.get(repeatedField);
if (repeatedField.isMapField() && (keyComparator == null)) {
keyComparator = PROTO_MAP_KEY_COMPARATOR;
}
int count1 = matchList1.length;
int count2 = matchList2.length;
Arrays.fill(matchList1, -1);
Arrays.fill(matchList2, -1);
boolean success = true;
// Find potential match if this is a special repeated field.
if ((keyComparator != null) || isTreatedAsSet(repeatedField)) {
for (int i = 0; i < count1; i++) {
// Indicates any matched elements for this repeated field.
boolean match = false;
int newIndex = i;
for (int j = 0; j < count2; j++) {
if (matchList2[j] != -1) {
continue;
}
newIndex = j;
match = isMatch(repeatedField, keyComparator, message1, message2, i, j, stack);
if (match) {
matchList1[i] = newIndex;
matchList2[newIndex] = i;
break;
}
}
success = success && match;
}
} else {
// If this field should be treated as list, just label the match_list.
for (int i = 0; (i < count1) && (i < count2); i++) {
matchList1[i] = matchList2[i] = i;
}
}
return success;
}
/**
* Ensures the field accessors are initialized. This method is thread-safe.
*
* @param messageClass The message type.
* @param builderClass The builder type.
* @return this
*/
public FieldAccessorTable ensureFieldAccessorsInitialized(
Class<? extends GeneratedMessage> messageClass,
Class<? extends Builder> builderClass) {
if (initialized) { return this; }
synchronized (this) {
if (initialized) { return this; }
int fieldsSize = fields.length;
for (int i = 0; i < fieldsSize; i++) {
FieldDescriptor field = descriptor.getFields().get(i);
String containingOneofCamelCaseName = null;
if (field.getContainingOneof() != null) {
containingOneofCamelCaseName =
camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()];
}
if (field.isRepeated()) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (field.isMapField() && isMapFieldEnabled(field)) {
fields[i] = new MapFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass);
} else {
fields[i] = new RepeatedMessageFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass);
}
} else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
fields[i] = new RepeatedEnumFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass);
} else {
fields[i] = new RepeatedFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass);
}
} else {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
fields[i] = new SingularMessageFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass,
containingOneofCamelCaseName);
} else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
fields[i] = new SingularEnumFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass,
containingOneofCamelCaseName);
} else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
fields[i] = new SingularStringFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass,
containingOneofCamelCaseName);
} else {
fields[i] = new SingularFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass,
containingOneofCamelCaseName);
}
}
}
int oneofsSize = oneofs.length;
for (int i = 0; i < oneofsSize; i++) {
oneofs[i] = new OneofAccessor(
descriptor, camelCaseNames[i + fieldsSize],
messageClass, builderClass);
}
initialized = true;
camelCaseNames = null;
return this;
}
}
/**
* Compares two set of fields.
* This method is used to implement {@link AbstractMessage#equals(Object)}
* and {@link AbstractMutableMessage#equals(Object)}. It takes special care
* of bytes fields because immutable messages and mutable messages use
* different Java type to reprensent a bytes field and this method should be
* able to compare immutable messages, mutable messages and also an immutable
* message to a mutable message.
*/
static boolean compareFields(Map<FieldDescriptor, Object> a,
Map<FieldDescriptor, Object> b) {
if (a.size() != b.size()) {
return false;
}
for (FieldDescriptor descriptor : a.keySet()) {
if (!b.containsKey(descriptor)) {
return false;
}
Object value1 = a.get(descriptor);
Object value2 = b.get(descriptor);
if (descriptor.getType() == FieldDescriptor.Type.BYTES) {
if (descriptor.isRepeated()) {
List list1 = (List) value1;
List list2 = (List) value2;
if (list1.size() != list2.size()) {
return false;
}
for (int i = 0; i < list1.size(); i++) {
if (!compareBytes(list1.get(i), list2.get(i))) {
return false;
}
}
} else {
// Compares a singular bytes field.
if (!compareBytes(value1, value2)) {
return false;
}
}
} else if (descriptor.isMapField()) {
if (!compareMapField(value1, value2)) {
return false;
}
} else {
// Compare non-bytes fields.
if (!value1.equals(value2)) {
return false;
}
}
}
return true;
}
@VisibleForTesting
static TypeSignature newFieldTypeInfo(FieldDescriptor fieldDescriptor) {
if (fieldDescriptor.isMapField()) {
return TypeSignature.ofMap(
newFieldTypeInfo(fieldDescriptor.getMessageType().findFieldByNumber(1)),
newFieldTypeInfo(fieldDescriptor.getMessageType().findFieldByNumber(2)));
}
final TypeSignature fieldType;
switch (fieldDescriptor.getType()) {
case BOOL:
fieldType = BOOL;
break;
case BYTES:
fieldType = BYTES;
break;
case DOUBLE:
fieldType = DOUBLE;
break;
case FIXED32:
fieldType = FIXED32;
break;
case FIXED64:
fieldType = FIXED64;
break;
case FLOAT:
fieldType = FLOAT;
break;
case INT32:
fieldType = INT32;
break;
case INT64:
fieldType = INT64;
break;
case SFIXED32:
fieldType = SFIXED32;
break;
case SFIXED64:
fieldType = SFIXED64;
break;
case SINT32:
fieldType = SINT32;
break;
case SINT64:
fieldType = SINT64;
break;
case STRING:
fieldType = STRING;
break;
case UINT32:
fieldType = UINT32;
break;
case UINT64:
fieldType = UINT64;
break;
case MESSAGE:
fieldType = namedMessageSignature(fieldDescriptor.getMessageType());
break;
case GROUP:
// This type has been deprecated since the launch of protocol buffers to open source.
// There is no real metadata for this in the descriptor so we just treat as UNKNOWN
// since it shouldn't happen in practice anyways.
fieldType = UNKNOWN;
break;
case ENUM:
fieldType = TypeSignature.ofNamed(
fieldDescriptor.getEnumType().getFullName(), fieldDescriptor.getEnumType());
break;
default:
fieldType = UNKNOWN;
break;
}
return fieldDescriptor.isRepeated() ? TypeSignature.ofContainer("repeated", fieldType) : fieldType;
}
@Override
public void serialize(
MessageOrBuilder message,
JsonGenerator generator,
SerializerProvider serializerProvider
) throws IOException {
generator.writeStartObject();
boolean proto3 = message.getDescriptorForType().getFile().getSyntax() == Syntax.PROTO3;
Include include = serializerProvider.getConfig().getDefaultPropertyInclusion().getValueInclusion();
boolean writeDefaultValues = proto3 && include != Include.NON_DEFAULT;
boolean writeEmptyCollections = include != Include.NON_DEFAULT && include != Include.NON_EMPTY;
PropertyNamingStrategyBase namingStrategy =
new PropertyNamingStrategyWrapper(serializerProvider.getConfig().getPropertyNamingStrategy());
Descriptor descriptor = message.getDescriptorForType();
List<FieldDescriptor> fields = new ArrayList<>(descriptor.getFields());
if (message instanceof ExtendableMessageOrBuilder<?>) {
for (ExtensionInfo extensionInfo : config.extensionRegistry().getExtensionsByDescriptor(descriptor)) {
fields.add(extensionInfo.descriptor);
}
}
for (FieldDescriptor field : fields) {
if (field.isRepeated()) {
List<?> valueList = (List<?>) message.getField(field);
if (!valueList.isEmpty() || writeEmptyCollections) {
if (field.isMapField()) {
generator.writeFieldName(namingStrategy.translate(field.getName()));
writeMap(field, valueList, generator, serializerProvider);
} else if (valueList.size() == 1 && writeSingleElementArraysUnwrapped(serializerProvider)) {
generator.writeFieldName(namingStrategy.translate(field.getName()));
writeValue(field, valueList.get(0), generator, serializerProvider);
} else {
generator.writeArrayFieldStart(namingStrategy.translate(field.getName()));
for (Object subValue : valueList) {
writeValue(field, subValue, generator, serializerProvider);
}
generator.writeEndArray();
}
}
} else if (message.hasField(field) || (writeDefaultValues && !supportsFieldPresence(field) && field.getContainingOneof() == null)) {
generator.writeFieldName(namingStrategy.translate(field.getName()));
writeValue(field, message.getField(field), generator, serializerProvider);
} else if (include == Include.ALWAYS && field.getContainingOneof() == null) {
generator.writeFieldName(namingStrategy.translate(field.getName()));
generator.writeNull();
}
}
generator.writeEndObject();
}