2 * Copyright 2018-present Open Networking Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package io.atomix.utils;
18 import com.google.common.collect.ComparisonChain;
20 import java.util.Objects;
22 import static com.google.common.base.Preconditions.checkArgument;
23 import static java.lang.Integer.parseInt;
26 * Atomix software version.
28 public final class Version implements Comparable<Version> {
31 * Returns a new version from the given version string.
33 * @param version the version string
34 * @return the version object
35 * @throws IllegalArgumentException if the version string is invalid
37 public static Version from(String version) {
38 String[] fields = version.split("[.-]", 4);
39 checkArgument(fields.length >= 3, "version number is invalid");
44 fields.length == 4 ? fields[3] : null);
48 * Returns a new version from the given parts.
50 * @param major the major version number
51 * @param minor the minor version number
52 * @param patch the patch version number
53 * @param build the build version number
54 * @return the version object
56 public static Version from(int major, int minor, int patch, String build) {
57 return new Version(major, minor, patch, build);
60 private final int major;
61 private final int minor;
62 private final int patch;
63 private final String build;
65 private Version(int major, int minor, int patch, String build) {
66 checkArgument(major >= 0, "major version must be >= 0");
67 checkArgument(minor >= 0, "minor version must be >= 0");
68 checkArgument(patch >= 0, "patch version must be >= 0");
72 this.build = Build.from(build).toString();
76 * Returns the major version number.
78 * @return the major version number
85 * Returns the minor version number.
87 * @return the minor version number
94 * Returns the patch version number.
96 * @return the patch version number
103 * Returns the build version number.
105 * @return the build version number
107 public String build() {
112 public int compareTo(Version that) {
113 return ComparisonChain.start()
114 .compare(this.major, that.major)
115 .compare(this.minor, that.minor)
116 .compare(this.patch, that.patch)
117 .compare(Build.from(this.build), Build.from(that.build))
122 public int hashCode() {
123 return Objects.hash(major, minor, patch, build);
127 public boolean equals(Object object) {
128 if (object == this) {
131 if (!(object instanceof Version)) {
134 Version that = (Version) object;
135 return this.major == that.major
136 && this.minor == that.minor
137 && this.patch == that.patch
138 && Objects.equals(this.build, that.build);
142 public String toString() {
143 StringBuilder builder = new StringBuilder()
149 String build = Build.from(this.build).toString();
151 builder.append('-').append(build);
153 return builder.toString();
159 private static class Build implements Comparable<Build> {
162 * Creates a new build version from the given string.
164 * @param build the build version string
165 * @return the build version
166 * @throws IllegalArgumentException if the build version string is invalid
168 public static Build from(String build) {
170 return new Build(Type.FINAL, 0);
171 } else if (build.equalsIgnoreCase(Type.SNAPSHOT.name())) {
172 return new Build(Type.SNAPSHOT, 0);
175 for (Type type : Type.values()) {
176 if (type.name != null && build.length() >= type.name.length() && build.substring(0, type.name.length()).equalsIgnoreCase(type.name)) {
178 int version = parseInt(build.substring(type.name.length()));
179 return new Build(type, version);
180 } catch (NumberFormatException e) {
181 throw new IllegalArgumentException(build + " is not a valid build version string");
185 throw new IllegalArgumentException(build + " is not a valid build version string");
188 private final Type type;
189 private final int version;
191 private Build(Type type, int version) {
193 this.version = version;
197 public int compareTo(Build that) {
198 return ComparisonChain.start()
199 .compare(this.type.ordinal(), that.type.ordinal())
200 .compare(this.version, that.version)
205 public int hashCode() {
206 return Objects.hash(type, version);
210 public boolean equals(Object object) {
211 if (object == this) {
214 if (!(object instanceof Build)) {
217 Build that = (Build) object;
218 return Objects.equals(this.type, that.type) && this.version == that.version;
222 public String toString() {
223 return type.format(version);
230 SNAPSHOT("snapshot"),
236 private final String name;
242 String format(int version) {
245 } else if ("snapshot".equals(name)) {
248 return String.format("%s%d", name, version);
253 public String toString() {