package org.elixir_lang.sdk; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class ElixirSdkRelease implements Comparable<ElixirSdkRelease> { /* * CONSTANTS */ public static final ElixirSdkRelease V_1_0_4 = new ElixirSdkRelease("1", "0", "4", null, null); public static final ElixirSdkRelease V_1_2 = new ElixirSdkRelease("1", "2", null, null, null); public static final ElixirSdkRelease V_1_3 = new ElixirSdkRelease("1", "3", null, null, null); public static final ElixirSdkRelease V_1_4 = new ElixirSdkRelease("1", "4", null, null, null); public static final ElixirSdkRelease LATEST = V_1_4; private static final Pattern VERSION_PATTERN = Pattern.compile( // @version_regex from Version in elixir itself "(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?(?:\\-([\\d\\w\\.\\-]+))?(?:\\+([\\d\\w\\-]+))?" ); /* * * Static Methods * */ /* * Public Static Methods */ @Nullable public static ElixirSdkRelease fromString(@Nullable String versionString){ Matcher m = versionString != null ? VERSION_PATTERN.matcher(versionString) : null; return m != null && m.matches() ? new ElixirSdkRelease(m.group(1), m.group(2), m.group(3), m.group(4), m.group(5)) : null; } /* * Private Static Methods */ @Contract(pure = true) private static int compareMaybeFormattedDecimals(@Nullable String mine, @Nullable String others) { int comparison; if (mine == null && others == null) { comparison = 0; } else if (mine == null) { comparison = -1; } else if (others == null) { comparison = 1; } else { try { int myInt = Integer.parseInt(mine); try { int othersInt = Integer.parseInt(others); if (myInt > othersInt) { comparison = 1; } else if (myInt < othersInt) { comparison = -1; } else { comparison = 0; } } catch (NumberFormatException numberFormatException) { comparison = mine.compareTo(others); } } catch (NumberFormatException numberFormatException) { comparison = mine.compareTo(others); } } return comparison; } /** * @see <a href="https://github.com/elixir-lang/elixir/blob/27c350da06ee4df5a4710507abe443ffba5b07dd/lib/elixir/lib/version.ex#L203-L206">Version.to_compare</a> */ @Contract(pure = true) private static int comparePre(@Nullable String mine, @Nullable String others) { int comparison; if (mine == null && others == null) { comparison = 0; } else if (mine == null) { // https://github.com/elixir-lang/elixir/blob/27c350da06ee4df5a4710507abe443ffba5b07dd/lib/elixir/lib/version.ex#L203 comparison = 1; } else if (others == null) { // https://github.com/elixir-lang/elixir/blob/27c350da06ee4df5a4710507abe443ffba5b07dd/lib/elixir/lib/version.ex#L204 comparison = -1; } else { comparison = mine.compareTo(others); } return comparison; } /* * Fields */ @Nullable private final String build; @NotNull private final String major; @Nullable private final String minor; @Nullable private final String patch; @Nullable private final String pre; /* * Constructors */ public ElixirSdkRelease(@NotNull String major, @Nullable String minor, @Nullable String patch, @Nullable String pre, @Nullable String build) { this.major = major; this.minor = minor; this.patch = patch; this.pre = pre; this.build = build; if (minor == null && patch != null) { throw new IllegalArgumentException("patch MUST be null if minor is null"); } } /* * Instance Methods */ @Override public int compareTo(@NotNull ElixirSdkRelease other) { int comparison = compareMaybeFormattedDecimals(major, other.major); if (comparison == 0) { comparison = compareMaybeFormattedDecimals(minor, other.minor); if (comparison == 0) { comparison = compareMaybeFormattedDecimals(patch, other.patch); if (comparison == 0) { comparison = comparePre(pre, other.pre); } } } return comparison; } @Override public String toString() { return "Elixir " + version(); } @NotNull public String version(){ StringBuilder version = new StringBuilder(major); if (minor != null) { version.append('.').append(minor); } if (patch != null) { version.append('.').append(patch); } if (pre != null) { version.append('-').append(pre); } if (build != null) { version.append('+').append(build); } return version.toString(); } }