public static Optional<Object> getAdjacentValue(Type type, Object value, boolean isPrevious)
    {
        if (!type.isOrderable()) {
            throw new IllegalStateException("Type is not orderable: " + type);
        }
        requireNonNull(value, "value is null");

        if (type.equals(BIGINT) || type instanceof TimestampType) {
            return getBigintAdjacentValue(value, isPrevious);
        }

        if (type.equals(INTEGER) || type.equals(DATE)) {
            return getIntegerAdjacentValue(value, isPrevious);
        }

        if (type.equals(SMALLINT)) {
            return getSmallIntAdjacentValue(value, isPrevious);
        }

        if (type.equals(TINYINT)) {
            return getTinyIntAdjacentValue(value, isPrevious);
        }

        if (type.equals(DOUBLE)) {
            return getDoubleAdjacentValue(value, isPrevious);
        }

        if (type.equals(REAL)) {
            return getRealAdjacentValue(value, isPrevious);
        }

        return Optional.empty();
    }
@Test
    public void testPreviousValueForBigint()
    {
        long minValue = Long.MIN_VALUE;
        long maxValue = Long.MAX_VALUE;

        assertThat(getAdjacentValue(BIGINT, minValue, true))
                .isEqualTo(Optional.empty());
        assertThat(getAdjacentValue(BIGINT, minValue + 1, true))
                .isEqualTo(Optional.of(minValue));

        assertThat(getAdjacentValue(BIGINT, 1234L, true))
                .isEqualTo(Optional.of(1233L));

        assertThat(getAdjacentValue(BIGINT, maxValue - 1, true))
                .isEqualTo(Optional.of(maxValue - 2));
        assertThat(getAdjacentValue(BIGINT, maxValue, true))
                .isEqualTo(Optional.of(maxValue - 1));
    }