public boolean compatibleVersion(String acceptableVersionRange, String actualVersion) {
    V pluginVersion = parseVersion(actualVersion);

    // Treat a single version "1.4" as a left bound, equivalent to "[1.4,)"
    if (acceptableVersionRange.matches(VERSION_REGEX)) {
      return ge(pluginVersion, parseVersion(acceptableVersionRange));
    }

    // Otherwise ensure it is a version range with bounds
    Matcher matcher = INTERVAL_PATTERN.matcher(acceptableVersionRange);
    Preconditions.checkArgument(matcher.matches(), "invalid version range");
    String leftBound = matcher.group("left");
    String rightBound = matcher.group("right");
    Preconditions.checkArgument(
        leftBound != null || rightBound != null, "left and right bounds cannot both be empty");
    BiPredicate<V, V> leftComparator =
        acceptableVersionRange.startsWith("[") ? VersionChecker::ge : VersionChecker::gt;
    BiPredicate<V, V> rightComparator =
        acceptableVersionRange.endsWith("]") ? VersionChecker::le : VersionChecker::lt;

    if (leftBound != null && !leftComparator.test(pluginVersion, parseVersion(leftBound))) {
      return false;
    }
    if (rightBound != null && !rightComparator.test(pluginVersion, parseVersion(rightBound))) {
      return false;
    }
    return true;
  }
@Test
  public void testRange_leftOpen() {
    Assert.assertFalse(checker.compatibleVersion("(2.3,4.3]", "1.0"));
    Assert.assertFalse(checker.compatibleVersion("(2.3,4.3)", "1.0"));
    Assert.assertFalse(checker.compatibleVersion("(2.3,)", "1.0"));
    Assert.assertFalse(checker.compatibleVersion("(2.3,]", "1.0"));
  }