public static SemanticVersion parse(String version) throws SemanticVersionParseException {
    Matcher matcher = PATTERN.matcher(version);

    if (!matcher.matches()) {
      throw new SemanticVersionParseException("" + version + " does not match format " + FORMAT);
    }

    final int major;
    final int minor;
    final int patch;

    try {
      major = Integer.parseInt(matcher.group(1));
      minor = Integer.parseInt(matcher.group(2));
      patch = Integer.parseInt(matcher.group(3));
    } catch (NumberFormatException e) {
      throw new SemanticVersionParseException(e);
    }

    final String unknown = matcher.group(4);
    final String prerelease = matcher.group(5);
    final String buildInfo = matcher.group(6);

    if (major < 0 || minor < 0 || patch < 0) {
      throw new SemanticVersionParseException(
          String.format("major(%d), minor(%d), and patch(%d) must all be >= 0", major, minor, patch));
    }

    return new SemanticVersion(major, minor, patch, unknown, prerelease, buildInfo);
  }
@Test
  public void testParse() throws Exception {
    assertEquals(new SemanticVersion(1, 8, 0), SemanticVersion.parse("1.8.0"));
    assertEquals(new SemanticVersion(1, 8, 0, true), SemanticVersion.parse("1.8.0rc3"));
    assertEquals(new SemanticVersion(1, 8, 0, "rc3", "SNAPSHOT", null), SemanticVersion.parse("1.8.0rc3-SNAPSHOT"));
    assertEquals(new SemanticVersion(1, 8, 0, null, "SNAPSHOT", null), SemanticVersion.parse("1.8.0-SNAPSHOT"));
    assertEquals(new SemanticVersion(1, 5, 0, null, "cdh5.5.0", null), SemanticVersion.parse("1.5.0-cdh5.5.0"));
  }