org.apache.kafka.connect.data.Time Java Examples

The following examples show how to use org.apache.kafka.connect.data.Time. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: StringParserTest.java    From connect-utils with Apache License 2.0 7 votes vote down vote up
@Test
public void nullableTests() {
  final Schema[] schemas = new Schema[]{
      Schema.OPTIONAL_BOOLEAN_SCHEMA,
      Schema.OPTIONAL_FLOAT32_SCHEMA,
      Schema.OPTIONAL_FLOAT64_SCHEMA,
      Schema.OPTIONAL_INT8_SCHEMA,
      Schema.OPTIONAL_INT16_SCHEMA,
      Schema.OPTIONAL_INT32_SCHEMA,
      Schema.OPTIONAL_INT64_SCHEMA,
      Schema.OPTIONAL_STRING_SCHEMA,
      Decimal.builder(1).optional().build(),
      Timestamp.builder().optional().build(),
      Date.builder().optional().build(),
      Time.builder().optional().build(),
  };

  for (Schema schema : schemas) {
    Object actual = this.parser.parseString(schema, null);
    assertNull(actual);
  }

}
 
Example #2
Source File: LogFieldConverterFactory.java    From kafka-connect-spooldir with Apache License 2.0 6 votes vote down vote up
static Schema schema(Class<?> logClass, String logFieldName) {
  final SchemaBuilder builder;
  if (LocalDate.class.equals(logClass)) {
    builder = Date.builder();
  } else if (LocalTime.class.equals(logClass)) {
    builder = Time.builder();
  } else if (Integer.class.equals(logClass)) {
    builder = SchemaBuilder.int32();
  } else if (Long.class.equals(logClass)) {
    builder = SchemaBuilder.int64();
  } else if (String.class.equals(logClass)) {
    builder = SchemaBuilder.string();
  } else {
    throw new UnsupportedOperationException(
        String.format("%s is not a supported type.", logClass.getName())
    );
  }
  builder.optional();


  return builder.build();
}
 
Example #3
Source File: Parser.java    From connect-utils with Apache License 2.0 6 votes vote down vote up
public Parser() {
  this.typeParsers = new HashMap<>();
  registerTypeParser(Schema.BOOLEAN_SCHEMA, new BooleanParser());
  registerTypeParser(Schema.BOOLEAN_SCHEMA, new BooleanParser());
  registerTypeParser(Schema.FLOAT32_SCHEMA, new Float32TypeParser());
  registerTypeParser(Schema.FLOAT64_SCHEMA, new Float64TypeParser());
  registerTypeParser(Schema.INT8_SCHEMA, new Int8TypeParser());
  registerTypeParser(Schema.INT16_SCHEMA, new Int16TypeParser());
  registerTypeParser(Schema.INT32_SCHEMA, new Int32TypeParser());
  registerTypeParser(Schema.INT64_SCHEMA, new Int64TypeParser());
  registerTypeParser(Schema.STRING_SCHEMA, new StringTypeParser());
  registerTypeParser(Decimal.schema(1), new DecimalTypeParser());
  registerTypeParser(Date.SCHEMA, new DateTypeParser());
  registerTypeParser(Time.SCHEMA, new TimeTypeParser());
  registerTypeParser(Timestamp.SCHEMA, new TimestampTypeParser());
}
 
Example #4
Source File: SchemaUtils.java    From kafka-connect-mongodb with Apache License 2.0 5 votes vote down vote up
public static Map<String, Object> toJsonMap(Struct struct) {
    Map<String, Object> jsonMap = new HashMap<String, Object>(0);
    List<Field> fields = struct.schema().fields();
    for (Field field : fields) {
        String fieldName = field.name();
        Schema.Type fieldType = field.schema().type();
        String schemaName=field.schema().name();
        switch (fieldType) {
            case STRING:
                jsonMap.put(fieldName, struct.getString(fieldName));
                break;
            case INT32:
            	if (Date.LOGICAL_NAME.equals(schemaName) 
            			|| Time.LOGICAL_NAME.equals(schemaName)) {
            		jsonMap.put(fieldName, (java.util.Date) struct.get(fieldName));
            	} else {
            		jsonMap.put(fieldName, struct.getInt32(fieldName));
            	}
                break;
            case INT16:
                jsonMap.put(fieldName, struct.getInt16(fieldName));
                break;
            case INT64:
            	if (Timestamp.LOGICAL_NAME.equals(schemaName)) {
            		jsonMap.put(fieldName, (java.util.Date) struct.get(fieldName));
            	} else {
            		jsonMap.put(fieldName, struct.getInt64(fieldName));
            	}
                break;
            case FLOAT32:
                jsonMap.put(fieldName, struct.getFloat32(fieldName));
                break;
            case STRUCT:
                jsonMap.put(fieldName, toJsonMap(struct.getStruct(fieldName)));
                break;
        }
    }
    return jsonMap;
}
 
Example #5
Source File: AvroData.java    From apicurio-registry with Apache License 2.0 5 votes vote down vote up
@Override
public Object convert(Schema schema, Object value) {
    if (!(value instanceof Integer)) {
        throw new DataException(
            "Invalid type for Time, underlying representation should be int32 but was "
            + value.getClass());
    }
    return Time.toLogical(schema, (int) value);
}
 
Example #6
Source File: AbstractSpoolDirSourceTask.java    From kafka-connect-spooldir with Apache License 2.0 5 votes vote down vote up
@Override
public void start(Map<String, String> settings) {
  super.start(settings);

  this.parser = new Parser();
  Map<Schema, TypeParser> dateTypeParsers = ImmutableMap.of(
      Timestamp.SCHEMA, new TimestampTypeParser(this.config.parserTimestampTimezone, this.config.parserTimestampDateFormats),
      Date.SCHEMA, new DateTypeParser(this.config.parserTimestampTimezone, this.config.parserTimestampDateFormats),
      Time.SCHEMA, new TimeTypeParser(this.config.parserTimestampTimezone, this.config.parserTimestampDateFormats)
  );

  for (Map.Entry<Schema, TypeParser> kvp : dateTypeParsers.entrySet()) {
    this.parser.registerTypeParser(kvp.getKey(), kvp.getValue());
  }
}
 
Example #7
Source File: StringParserTest.java    From connect-utils with Apache License 2.0 5 votes vote down vote up
@Test
public void timeTests() throws ParseException {
  SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

  Map<String, ?> tests = ImmutableMap.of(
      "12:08:56", dateFormat.parse("12:08:56")
  );
  Map<String, java.util.Date> results = assertConversion(Time.SCHEMA, java.util.Date.class, tests);
  for (Map.Entry<String, java.util.Date> kvp : results.entrySet()) {
    Time.fromLogical(Time.SCHEMA, kvp.getValue());
  }
}
 
Example #8
Source File: JsonNodeTest.java    From connect-utils with Apache License 2.0 5 votes vote down vote up
@Test
public void nullableTests() throws IOException {
  final Schema[] schemas = new Schema[]{
      Schema.OPTIONAL_BOOLEAN_SCHEMA,
      Schema.OPTIONAL_FLOAT32_SCHEMA,
      Schema.OPTIONAL_FLOAT64_SCHEMA,
      Schema.OPTIONAL_INT8_SCHEMA,
      Schema.OPTIONAL_INT16_SCHEMA,
      Schema.OPTIONAL_INT32_SCHEMA,
      Schema.OPTIONAL_INT64_SCHEMA,
      Schema.OPTIONAL_STRING_SCHEMA,
      Decimal.builder(1).optional().build(),
      Timestamp.builder().optional().build(),
      Date.builder().optional().build(),
      Time.builder().optional().build(),
  };

  for (Schema schema : schemas) {
    JsonNode inputNode = null;
    Object actual = this.parser.parseJsonNode(schema, inputNode);
    assertNull(actual);
    inputNode = objectMapper.readTree("{\"foo\": null}");
    inputNode = inputNode.findValue("foo");
    actual = this.parser.parseJsonNode(schema, inputNode);
    assertNull(actual);
  }

}
 
Example #9
Source File: ValueHelper.java    From connect-utils with Apache License 2.0 5 votes vote down vote up
static Object time(Schema schema, Object value) {
  if (value instanceof Number) {
    Number number = (Number) value;
    return Time.toLogical(schema, number.intValue());
  }
  return value;
}
 
Example #10
Source File: AvroData.java    From apicurio-registry with Apache License 2.0 5 votes vote down vote up
@Override
public Object convert(Schema schema, Object value) {
    if (!(value instanceof java.util.Date)) {
        throw new DataException(
            "Invalid type for Time, expected Date but was " + value.getClass());
    }
    return Time.fromLogical(schema, (java.util.Date) value);
}
 
Example #11
Source File: AssertStructTest.java    From connect-utils with Apache License 2.0 4 votes vote down vote up
@BeforeEach
public void createSchemas() {
  this.decimalSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Decimal")
      .field("decimal", Decimal.builder(1).optional().build())
      .build();
  this.timestampSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Timestamp")
      .field("timestamp", Timestamp.builder().optional().build())
      .build();
  this.dateSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Date")
      .field("date", Date.builder().optional().build())
      .build();
  this.timeSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Time")
      .field("time", Time.builder().optional().build())
      .build();

  this.simple = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Simple")
      .optional()
      .field("text", Schema.OPTIONAL_STRING_SCHEMA)
      .build();

  this.pointSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Point")
      .optional()
      .field("latitude", Schema.FLOAT32_SCHEMA)
      .field("longitude", Schema.FLOAT32_SCHEMA)
      .build();

  this.nestedSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Nested")
      .field("point", this.pointSchema)
      .build();

  this.arraySchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.ArrayOfPoint")
      .field("array", SchemaBuilder.array(this.pointSchema).optional().build())
      .build();

  this.mapSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.MapOfPoint")
      .field("map", SchemaBuilder.map(Schema.STRING_SCHEMA, this.pointSchema).optional().build())
      .build();

  this.structBytesSchema = SchemaBuilder.struct()
      .name("com.github.jcustenborder.kafka.connect.utils.Bytes")
      .field("bytes", Schema.OPTIONAL_BYTES_SCHEMA)
      .build();
  this.buffer = new byte[10];
  new Random().nextBytes(this.buffer);
}
 
Example #12
Source File: AssertStruct.java    From connect-utils with Apache License 2.0 4 votes vote down vote up
public static void assertStruct(final Struct expected, final Struct actual, String message) {
  String prefix = Strings.isNullOrEmpty(message) ? "" : message + ": ";

  if (null == expected) {
    assertNull(actual, prefix + "actual should be null.");
    return;
  }

  assertSchema(expected.schema(), actual.schema(), "schema does not match.");
  for (Field expectedField : expected.schema().fields()) {
    log.trace("assertStruct() - testing field '{}'", expectedField.name());
    final Object expectedValue = expected.get(expectedField.name());
    final Object actualValue = actual.get(expectedField.name());

    if (Decimal.LOGICAL_NAME.equals(expectedField.schema().name())) {
      final BigDecimal expectedDecimal = castAndVerify(BigDecimal.class, expected, expectedField, true);
      final BigDecimal actualDecimal = castAndVerify(BigDecimal.class, actual, expectedField, false);
      assertEquals(expectedDecimal, actualDecimal, prefix + expectedField.name() + " does not match.");
    } else if (Timestamp.LOGICAL_NAME.equals(expectedField.schema().name())
        || Date.LOGICAL_NAME.equals(expectedField.schema().name())
        || Time.LOGICAL_NAME.equals(expectedField.schema().name())) {
      final java.util.Date expectedDate = castAndVerify(java.util.Date.class, expected, expectedField, true);
      final java.util.Date actualDate = castAndVerify(java.util.Date.class, actual, expectedField, false);
      assertEquals(expectedDate, actualDate, prefix + expectedField.name() + " does not match.");
    } else {
      switch (expectedField.schema().type()) {
        case ARRAY:
          final List<Object> expectedArray = castAndVerify(List.class, expected, expectedField, true);
          final List<Object> actualArray = castAndVerify(List.class, actual, expectedField, false);
          assertEquals(expectedArray, actualArray, prefix + expectedField.name() + " does not match.");
          break;
        case MAP:
          final Map<Object, Object> expectedMap = castAndVerify(Map.class, expected, expectedField, true);
          final Map<Object, Object> actualMap = castAndVerify(Map.class, actual, expectedField, false);
          assertEquals(expectedMap, actualMap, prefix + expectedField.name() + " does not match.");
          break;
        case STRUCT:
          final Struct expectedStruct = castAndVerify(Struct.class, expected, expectedField, true);
          final Struct actualStruct = castAndVerify(Struct.class, actual, expectedField, false);
          assertStruct(expectedStruct, actualStruct, prefix + expectedField.name() + " does not match.");
          break;
        case BYTES:
          final byte[] expectedByteArray = castAndVerify(byte[].class, expected, expectedField, true);
          final byte[] actualByteArray = castAndVerify(byte[].class, actual, expectedField, false);
          assertEquals(
              null == expectedByteArray ? "" : BaseEncoding.base32Hex().encode(expectedByteArray).toString(),
              null == actualByteArray ? "" : BaseEncoding.base32Hex().encode(actualByteArray).toString(),
              prefix + expectedField.name() + " does not match."
          );
          break;
        default:
          assertEquals(expectedValue, actualValue, prefix + expectedField.name() + " does not match.");
          break;
      }
    }
  }
}
 
Example #13
Source File: BaseTransformation.java    From kafka-connect-transform-common with Apache License 2.0 4 votes vote down vote up
protected SchemaAndValue process(R record, Schema inputSchema, Object input) {
  final SchemaAndValue result;

  if (null == inputSchema && null == input) {
    return new SchemaAndValue(
        null,
        null
    );
  }

  if (input instanceof Map) {
    log.trace("process() - Processing as map");
    result = processMap(record, (Map<String, Object>) input);
    return result;
  }

  if (null == inputSchema) {
    log.trace("process() - Determining schema");
    inputSchema = SchemaHelper.schema(input);
  }

  log.trace("process() - Input has as schema. schema = {}", inputSchema);
  if (Schema.Type.STRUCT == inputSchema.type()) {
    result = processStruct(record, inputSchema, (Struct) input);
  } else if (Timestamp.LOGICAL_NAME.equals(inputSchema.name())) {
    result = processTimestamp(record, inputSchema, (Date) input);
  } else if (org.apache.kafka.connect.data.Date.LOGICAL_NAME.equals(inputSchema.name())) {
    result = processDate(record, inputSchema, (Date) input);
  } else if (Time.LOGICAL_NAME.equals(inputSchema.name())) {
    result = processTime(record, inputSchema, (Date) input);
  } else if (Decimal.LOGICAL_NAME.equals(inputSchema.name())) {
    result = processDecimal(record, inputSchema, (BigDecimal) input);
  } else if (Schema.Type.STRING == inputSchema.type()) {
    result = processString(record, inputSchema, (String) input);
  } else if (Schema.Type.BYTES == inputSchema.type()) {
    result = processBytes(record, inputSchema, (byte[]) input);
  } else if (Schema.Type.INT8 == inputSchema.type()) {
    result = processInt8(record, inputSchema, (byte) input);
  } else if (Schema.Type.INT16 == inputSchema.type()) {
    result = processInt16(record, inputSchema, (short) input);
  } else if (Schema.Type.INT32 == inputSchema.type()) {
    result = processInt32(record, inputSchema, (int) input);
  } else if (Schema.Type.INT64 == inputSchema.type()) {
    result = processInt64(record, inputSchema, (long) input);
  } else if (Schema.Type.FLOAT32 == inputSchema.type()) {
    result = processFloat32(record, inputSchema, (float) input);
  } else if (Schema.Type.FLOAT64 == inputSchema.type()) {
    result = processFloat64(record, inputSchema, (double) input);
  } else if (Schema.Type.ARRAY == inputSchema.type()) {
    result = processArray(record, inputSchema, (List<Object>) input);
  } else if (Schema.Type.MAP == inputSchema.type()) {
    result = processMap(record, inputSchema, (Map<Object, Object>) input);
  } else {
    throw new UnsupportedOperationException(
        String.format(
            "Schema is not supported. type='%s' name='%s'",
            inputSchema.type(),
            inputSchema.name()
        )
    );
  }

  return result;
}
 
Example #14
Source File: MsSqlTableMetadataProvider.java    From kafka-connect-cdc-mssql with Apache License 2.0 4 votes vote down vote up
Schema generateSchema(ResultSet resultSet,
                      final ChangeKey changeKey,
                      final String columnName) throws SQLException {
  boolean optional = resultSet.getBoolean(2);
  String dataType = resultSet.getString(3);
  int scale = resultSet.getInt(4);
  SchemaBuilder builder;

  log.trace("{}: columnName='{}' dataType='{}' scale={} optional={}", changeKey, columnName, dataType, scale, optional);

  switch (dataType) {
    case "bigint":
      builder = SchemaBuilder.int64();
      break;
    case "bit":
      builder = SchemaBuilder.bool();
      break;
    case "char":
    case "varchar":
    case "text":
    case "nchar":
    case "nvarchar":
    case "ntext":
    case "uniqueidentifier":
      builder = SchemaBuilder.string();
      break;
    case "smallmoney":
    case "money":
    case "decimal":
    case "numeric":
      builder = Decimal.builder(scale);
      break;
    case "binary":
    case "image":
    case "varbinary":
      builder = SchemaBuilder.bytes();
      break;
    case "date":
      builder = Date.builder();
      break;
    case "datetime":
    case "datetime2":
    case "smalldatetime":
      builder = Timestamp.builder();
      break;
    case "time":
      builder = Time.builder();
      break;
    case "int":
      builder = SchemaBuilder.int32();
      break;
    case "smallint":
      builder = SchemaBuilder.int16();
      break;
    case "tinyint":
      builder = SchemaBuilder.int8();
      break;
    case "real":
      builder = SchemaBuilder.float32();
      break;
    case "float":
      builder = SchemaBuilder.float64();
      break;

    default:
      throw new DataException(
          String.format("Could not process (dataType = '%s', optional = %s, scale = %d) for %s.",
              dataType, optional, scale, changeKey
          )
      );
  }

  log.trace("{}: columnName='{}' schema.type='{}' schema.name='{}'", changeKey, columnName, builder.type(), builder.name());

  builder.parameters(
      ImmutableMap.of(Change.ColumnValue.COLUMN_NAME, columnName)
  );

  if (optional) {
    builder.optional();
  }

  return builder.build();
}
 
Example #15
Source File: TimeFieldConverter.java    From kafka-connect-mongodb with Apache License 2.0 4 votes vote down vote up
public TimeFieldConverter() {
    super(Time.SCHEMA);
}
 
Example #16
Source File: AssertStruct.java    From connect-utils with Apache License 2.0 4 votes vote down vote up
public static void assertStruct(final Struct expected, final Struct actual, String message) {
  String prefix = Strings.isNullOrEmpty(message) ? "" : message + ": ";

  if (null == expected) {
    assertNull(actual, prefix + "actual should be null.");
    return;
  }

  assertSchema(expected.schema(), actual.schema(), "schema does not match.");

  final Set<String> logicalTypes = ImmutableSet.of(
      Timestamp.LOGICAL_NAME,
      Date.LOGICAL_NAME,
      Time.LOGICAL_NAME,
      Decimal.LOGICAL_NAME
  );

  for (Field field : expected.schema().fields()) {
    log.trace("assertStruct() - testing field '{}'", field.name());
    final Object expectedValue = expected.get(field.name());
    final Object actualValue = actual.get(field.name());

    if (!Strings.isNullOrEmpty(field.schema().name()) && logicalTypes.contains(field.schema().name())) {
      assertEquals(expectedValue, actualValue, prefix + field.name() + " does not match.");
    } else {
      switch (field.schema().type()) {
        case ARRAY:
          assertTrue(null == expectedValue || expectedValue instanceof List);
          assertTrue(null == actualValue || actualValue instanceof List);
          List<Object> expectedArray = (List<Object>) expectedValue;
          List<Object> actualArray = (List<Object>) actualValue;
          assertEquals(expectedArray, actualArray, prefix + field.name() + " does not match.");
          break;
        case MAP:
          assertTrue(null == expectedValue || expectedValue instanceof Map);
          assertTrue(null == actualValue || actualValue instanceof Map);
          Map<Object, Object> expectedMap = (Map<Object, Object>) expectedValue;
          Map<Object, Object> actualMap = (Map<Object, Object>) actualValue;
          assertEquals(expectedMap, actualMap, prefix + field.name() + " does not match.");
          break;
        case STRUCT:
          assertTrue(null == expectedValue || expectedValue instanceof Struct);
          assertTrue(null == actualValue || actualValue instanceof Struct);
          Struct expectedStruct = (Struct) expectedValue;
          Struct actualStruct = (Struct) actualValue;
          assertStruct(expectedStruct, actualStruct, prefix + field.name() + " does not match.");
          break;
        case BYTES:
          assertTrue(null == expectedValue || expectedValue instanceof byte[]);
          assertTrue(null == actualValue || actualValue instanceof byte[]);
          byte[] expectedByteArray = (byte[]) expectedValue;
          byte[] actualByteArray = (byte[]) actualValue;
          assertEquals(
              null == expectedByteArray ? "" : BaseEncoding.base32Hex().encode(expectedByteArray).toString(),
              null == actualByteArray ? "" : BaseEncoding.base32Hex().encode(actualByteArray).toString(),
              prefix + field.name() + " does not match."
          );
          break;
        default:
          assertEquals(expectedValue, actualValue, prefix + field.name() + " does not match.");
          break;
      }
    }
  }
}
 
Example #17
Source File: SinkFieldConverterTest.java    From mongo-kafka with Apache License 2.0 4 votes vote down vote up
@TestFactory
@DisplayName("tests for logical type time field conversions")
List<DynamicTest> testTimeFieldConverter() {
  SinkFieldConverter converter = new TimeFieldConverter();
  List<DynamicTest> tests = new ArrayList<>();

  asList(
          java.util.Date.from(
              ZonedDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.MIDNIGHT, ZoneOffset.UTC)
                  .toInstant()),
          java.util.Date.from(
              ZonedDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.NOON, ZoneOffset.UTC)
                  .toInstant()))
      .forEach(
          el ->
              tests.add(
                  dynamicTest(
                      "conversion with " + converter.getClass().getSimpleName() + " for " + el,
                      () ->
                          assertEquals(
                              el.toInstant().getEpochSecond() * 1000,
                              ((BsonDateTime) converter.toBson(el)).getValue()))));

  tests.add(
      dynamicTest(
          "optional type conversions",
          () -> {
            Schema valueOptionalDefault =
                Time.builder()
                    .optional()
                    .defaultValue(
                        java.util.Date.from(
                            ZonedDateTime.of(
                                    LocalDate.of(1970, 1, 1), LocalTime.MIDNIGHT, ZoneOffset.UTC)
                                .toInstant()));
            assertAll(
                "checks",
                () ->
                    assertThrows(DataException.class, () -> converter.toBson(null, Time.SCHEMA)),
                () ->
                    assertEquals(
                        new BsonNull(), converter.toBson(null, Time.builder().optional())),
                () ->
                    assertEquals(
                        ((java.util.Date) valueOptionalDefault.defaultValue())
                                .toInstant()
                                .getEpochSecond()
                            * 1000,
                        ((BsonDateTime) converter.toBson(null, valueOptionalDefault))
                            .getValue()));
          }));

  return tests;
}
 
Example #18
Source File: TimeFieldConverter.java    From mongo-kafka with Apache License 2.0 4 votes vote down vote up
public TimeFieldConverter() {
  super(Time.SCHEMA);
}
 
Example #19
Source File: LogFieldConverterFactory.java    From kafka-connect-spooldir with Apache License 2.0 4 votes vote down vote up
public LogFieldConverter create(
    SchemaBuilder builder,
    Class<?> logClass,
    String logFieldName,
    String schemaFieldName) {

  final Schema fieldSchema;
  final Field field;
  final LogFieldConverter converter;

  if (LocalDate.class.equals(logClass)) {
    fieldSchema = Date.builder()
        .optional()
        .parameter(LOGFIELD_PARAM, logFieldName)
        .build();
    builder.field(schemaFieldName, fieldSchema);
    field = builder.field(schemaFieldName);
    converter = new LocalDateLogFieldConverter(logFieldName, field);
  } else if (LocalTime.class.equals(logClass)) {
    fieldSchema = Time.builder()
        .optional()
        .parameter(LOGFIELD_PARAM, logFieldName)
        .build();
    builder.field(schemaFieldName, fieldSchema);
    field = builder.field(schemaFieldName);
    converter = new LocalTimeLogFieldConverter(logFieldName, field);
  } else if (Integer.class.equals(logClass)) {
    fieldSchema = SchemaBuilder.int32()
        .optional()
        .parameter(LOGFIELD_PARAM, logFieldName)
        .build();
    builder.field(schemaFieldName, fieldSchema);
    field = builder.field(schemaFieldName);
    converter = new PrimitiveLogFieldConverter(logFieldName, field);
  } else if (Long.class.equals(logClass)) {
    fieldSchema = SchemaBuilder.int64()
        .optional()
        .parameter(LOGFIELD_PARAM, logFieldName)
        .build();
    builder.field(schemaFieldName, fieldSchema);
    field = builder.field(schemaFieldName);
    converter = new PrimitiveLogFieldConverter(logFieldName, field);
  } else if (String.class.equals(logClass)) {
    fieldSchema = SchemaBuilder.string()
        .optional()
        .parameter(LOGFIELD_PARAM, logFieldName)
        .build();
    builder.field(schemaFieldName, fieldSchema);
    field = builder.field(schemaFieldName);
    converter = new PrimitiveLogFieldConverter(logFieldName, field);
  } else if (Double.class.equals(logClass)) {
    fieldSchema = SchemaBuilder.float64()
        .optional()
        .parameter(LOGFIELD_PARAM, logFieldName)
        .build();
    builder.field(schemaFieldName, fieldSchema);
    field = builder.field(schemaFieldName);
    converter = new PrimitiveLogFieldConverter(logFieldName, field);
  } else {
    throw new UnsupportedOperationException(
        String.format("%s is not a supported type.", logClass.getName())
    );
  }

  return converter;
}