private static void handleNonRepeatedField( Record record, Map<String, Field> valueAsMap, String fieldPath, Map<String, Set<Descriptors.FieldDescriptor>> messageTypeToExtensionMap, Map<String, Object> defaultValueMap, Descriptors.Descriptor desc, Descriptors.FieldDescriptor f, DynamicMessage.Builder builder) throws DataGeneratorException { Object val; String keyName = f.getName(); if (valueAsMap.containsKey(keyName)) { val = getValue( f, valueAsMap.get(keyName), record, fieldPath + FORWARD_SLASH + f.getName(), messageTypeToExtensionMap, defaultValueMap); } else { // record does not contain field, look up default value String key = desc.getFullName() + "." + f.getName(); if (!defaultValueMap.containsKey(key) && !f.isOptional()) { throw new DataGeneratorException(Errors.PROTOBUF_04, record.getHeader().getSourceId(), key); } val = defaultValueMap.get(key); } if (val != null) { builder.setField(f, val); } }
/** * 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; }