private static void addDefaultsAndExtensions( Map<String, Set<Descriptors.FieldDescriptor>> e, Map<String, Object> defaultValueMap, Descriptors.Descriptor d) { for (Descriptors.FieldDescriptor fieldDescriptor : d.getExtensions()) { String containingType = fieldDescriptor.getContainingType().getFullName(); Set<Descriptors.FieldDescriptor> fieldDescriptors = e.get(containingType); if (fieldDescriptors == null) { fieldDescriptors = new LinkedHashSet<>(); e.put(containingType, fieldDescriptors); } fieldDescriptors.add(fieldDescriptor); if (fieldDescriptor.hasDefaultValue()) { defaultValueMap.put( fieldDescriptor.getContainingType().getFullName() + "." + fieldDescriptor.getName(), fieldDescriptor.getDefaultValue()); } } for (Descriptors.FieldDescriptor fieldDescriptor : d.getFields()) { if (fieldDescriptor.hasDefaultValue()) { defaultValueMap.put( d.getFullName() + "." + fieldDescriptor.getName(), fieldDescriptor.getDefaultValue()); } } for (Descriptors.Descriptor nestedType : d.getNestedTypes()) { addDefaultsAndExtensions(e, defaultValueMap, nestedType); } }
/** * Populates a map of protobuf extensions and map with the default values for each message field * from a map of file descriptors. * * @param fileDescriptorMap Map of file descriptors * @param typeToExtensionMap Map of extensions to populate * @param defaultValueMap Map of default values to populate */ public static void populateDefaultsAndExtensions( Map<String, Descriptors.FileDescriptor> fileDescriptorMap, Map<String, Set<Descriptors.FieldDescriptor>> typeToExtensionMap, Map<String, Object> defaultValueMap) { for (Descriptors.FileDescriptor f : fileDescriptorMap.values()) { // go over every file descriptor and look for extensions and default values of those // extensions for (Descriptors.FieldDescriptor fieldDescriptor : f.getExtensions()) { String containingType = fieldDescriptor.getContainingType().getFullName(); Set<Descriptors.FieldDescriptor> fieldDescriptors = typeToExtensionMap.get(containingType); if (fieldDescriptors == null) { fieldDescriptors = new LinkedHashSet<>(); typeToExtensionMap.put(containingType, fieldDescriptors); } fieldDescriptors.add(fieldDescriptor); if (fieldDescriptor.hasDefaultValue()) { defaultValueMap.put( containingType + "." + fieldDescriptor.getName(), fieldDescriptor.getDefaultValue()); } } // go over messages within file descriptor and look for all fields and extensions and their // defaults for (Descriptors.Descriptor d : f.getMessageTypes()) { addDefaultsAndExtensions(typeToExtensionMap, defaultValueMap, d); } } }
/** * Creates an SDC Record Field from the provided protobuf message and descriptor. * * @param record record to be augmented * @param fieldPath field path in the record to insert new Field * @param fieldDescriptor descriptor for this message * @param messageTypeToExtensionMap protobuf type extensions * @param message protobuf message to decode * @return reference to the Field added to the record. * @throws DataParserException */ @SuppressWarnings("unchecked") private static Field createField( Record record, String fieldPath, Descriptors.FieldDescriptor fieldDescriptor, Map<String, Set<Descriptors.FieldDescriptor>> messageTypeToExtensionMap, Object message) throws DataParserException { Field newField; if (message == null) { // If the message does not contain required fields then builder.build() throws // UninitializedMessageException Object defaultValue = null; // get default values only for optional fields and non-message types if (fieldDescriptor.isOptional() && fieldDescriptor.getJavaType() != Descriptors.FieldDescriptor.JavaType.MESSAGE) { defaultValue = fieldDescriptor.getDefaultValue(); } newField = Field.create(getFieldType(fieldDescriptor.getJavaType()), defaultValue); } else if (fieldDescriptor.isMapField()) { // Map entry (protobuf 3 map) Map<String, Field> sdcMapFieldValues = new HashMap<>(); Collection<DynamicMessage> mapEntries = (Collection<DynamicMessage>) message; // MapEntry for (DynamicMessage dynamicMessage : mapEntries) { // MapEntry has 2 fields, key and value Map<Descriptors.FieldDescriptor, Object> kv = dynamicMessage.getAllFields(); String key = null; Object value = null; Descriptors.FieldDescriptor valueDescriptor = null; for (Map.Entry<Descriptors.FieldDescriptor, Object> entry : kv.entrySet()) { switch (entry.getKey().getName()) { case KEY: key = entry.getValue().toString(); break; case VALUE: value = entry.getValue(); valueDescriptor = entry.getKey(); break; default: throw new DataParserException(Errors.PROTOBUF_09, entry.getKey().getName()); } } if (key != null && valueDescriptor != null) { sdcMapFieldValues.put( key, createSdcField(record, fieldPath, valueDescriptor, messageTypeToExtensionMap, value)); } } newField = Field.create(sdcMapFieldValues); } else if (fieldDescriptor.isRepeated()) { // List entry (repeated) List<?> list = (List<?>) message; List<Field> listField = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { if (fieldDescriptor.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { listField.add( protobufToSdcField( record, fieldPath + "[" + i + "]", fieldDescriptor.getMessageType(), messageTypeToExtensionMap, list.get(i))); } else { listField.add( createSdcField( record, fieldPath + "[" + i + "]", fieldDescriptor, messageTypeToExtensionMap, list.get(i))); } } newField = Field.create(listField); } else { // normal entry newField = createSdcField(record, fieldPath, fieldDescriptor, messageTypeToExtensionMap, message); } return newField; }