public VersionRange<T> intersectionWith(VersionRange<T> that) {
        if (this.isAll())
            return that;
        if (that.isAll())
            return this;

        if (!isOverlappedBy(that))
            return empty();

        T newMinimum;
        if (this.minimum == null)
            newMinimum = that.minimum;
        else if (that.minimum == null)
            newMinimum = this.minimum;
        else
            newMinimum = this.minimum.compareTo(that.minimum) >= 0 ? this.minimum : that.minimum;

        T newMaximum;
        if (this.maximum == null)
            newMaximum = that.maximum;
        else if (that.maximum == null)
            newMaximum = this.maximum;
        else
            newMaximum = this.maximum.compareTo(that.maximum) <= 0 ? this.maximum : that.maximum;

        return new VersionRange<>(newMinimum, newMaximum);
    }
@Test
    public void testIntersectionWith() {
        assertIntersectionWith(all(), all(), all());
        assertIntersectionWith(all(), empty(), empty());
        assertIntersectionWith(all(), VersionNumber.between("10", "20"), VersionNumber.between("10", "20"));
        assertIntersectionWith(all(), VersionNumber.atLeast("10"), VersionNumber.atLeast("10"));
        assertIntersectionWith(all(), VersionNumber.atMost("10"), VersionNumber.atMost("10"));

        assertIntersectionWith(empty(), empty(), empty());
        assertIntersectionWith(empty(), VersionNumber.between("10", "20"), empty());
        assertIntersectionWith(empty(), VersionNumber.atLeast("10"), empty());
        assertIntersectionWith(empty(), VersionNumber.atMost("10"), empty());

        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("10", "20"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("5", "20"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("10", "25"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("5", "25"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("15", "20"), VersionNumber.between("15", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("10", "15"), VersionNumber.between("10", "15"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.between("14", "16"), VersionNumber.between("14", "16"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("5"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("10"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("15"), VersionNumber.between("15", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("20"), VersionNumber.between("20", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atLeast("25"), empty());
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("25"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("20"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("15"), VersionNumber.between("10", "15"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("10"), VersionNumber.between("10", "10"));
        assertIntersectionWith(VersionNumber.between("10", "20"), VersionNumber.atMost("5"), empty());

        assertIntersectionWith(VersionNumber.atLeast("10"), VersionNumber.atMost("10"), VersionNumber.between("10", "10"));
        assertIntersectionWith(VersionNumber.atLeast("10"), VersionNumber.atMost("20"), VersionNumber.between("10", "20"));
        assertIntersectionWith(VersionNumber.atLeast("10"), VersionNumber.atMost("5"), empty());
    }