public static Object project(Schema source, Object record, Schema target) throws SchemaProjectorException {
        checkMaybeCompatible(source, target);
        if (source.isOptional() && !target.isOptional()) {
            if (target.defaultValue() != null) {
                if (record != null) {
                    return projectRequiredSchema(source, record, target);
                } else {
                    return target.defaultValue();
                }
            } else {
                throw new SchemaProjectorException("Writer schema is optional, however, target schema does not provide a default value.");
            }
        } else {
            if (record != null) {
                return projectRequiredSchema(source, record, target);
            } else {
                return null;
            }
        }
    }
@Test
    public void testLogicalTypeProjection() {
        Schema[] logicalTypeSchemas = {Decimal.schema(2), Date.SCHEMA, Time.SCHEMA, Timestamp.SCHEMA};
        Object projected;

        BigDecimal testDecimal = new BigDecimal(new BigInteger("156"), 2);
        projected = SchemaProjector.project(Decimal.schema(2), testDecimal, Decimal.schema(2));
        assertEquals(testDecimal, projected);

        projected = SchemaProjector.project(Date.SCHEMA, 1000, Date.SCHEMA);
        assertEquals(1000, projected);

        projected = SchemaProjector.project(Time.SCHEMA, 231, Time.SCHEMA);
        assertEquals(231, projected);

        projected = SchemaProjector.project(Timestamp.SCHEMA, 34567L, Timestamp.SCHEMA);
        assertEquals(34567L, projected);

        java.util.Date date = new java.util.Date();

        projected = SchemaProjector.project(Date.SCHEMA, date, Date.SCHEMA);
        assertEquals(date, projected);

        projected = SchemaProjector.project(Time.SCHEMA, date, Time.SCHEMA);
        assertEquals(date, projected);

        projected = SchemaProjector.project(Timestamp.SCHEMA, date, Timestamp.SCHEMA);
        assertEquals(date, projected);

        Schema namedSchema = SchemaBuilder.int32().name("invalidLogicalTypeName").build();
        for (Schema logicalTypeSchema: logicalTypeSchemas) {
            assertThrows(SchemaProjectorException.class, () -> SchemaProjector.project(logicalTypeSchema, null,
                    Schema.BOOLEAN_SCHEMA), "Cannot project logical types to non-logical types.");

            assertThrows(SchemaProjectorException.class, () -> SchemaProjector.project(logicalTypeSchema, null,
                    namedSchema), "Reader name is not a valid logical type name.");

            assertThrows(SchemaProjectorException.class, () -> SchemaProjector.project(Schema.BOOLEAN_SCHEMA,
                    null, logicalTypeSchema), "Cannot project non-logical types to logical types.");
        }
    }