blob: 2183d59f51a35129b8e8834442d391d5ab6489c6 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.core;
tom53efab52014-10-07 17:43:48 -070017
18import java.util.Objects;
19
Thomas Vachuska045c01d2014-12-04 00:18:06 -080020import static com.google.common.base.Preconditions.checkArgument;
21import static com.google.common.base.Strings.isNullOrEmpty;
tom53efab52014-10-07 17:43:48 -070022import static java.lang.Integer.parseInt;
23
24/**
25 * Representation of the product version.
26 */
Jordan Haltermanab7d1f32018-04-04 11:59:11 -070027public final class Version implements Comparable<Version> {
tom53efab52014-10-07 17:43:48 -070028
Thomas Vachuska93d944c2015-06-16 09:48:55 -070029 public static final String FORMAT_MINIMAL = "%d.%d";
Thomas Vachuska045c01d2014-12-04 00:18:06 -080030 public static final String FORMAT_SHORT = "%d.%d.%s";
Thomas Vachuska93d944c2015-06-16 09:48:55 -070031 public static final String FORMAT_LONG = "%d.%d.%s.%s";
Thomas Vachuska045c01d2014-12-04 00:18:06 -080032
33 private static final String NEGATIVE = "Version segment cannot be negative";
Thomas Vachuskaafb11da2015-06-16 10:01:13 -070034 public static final String TOO_SHORT = "Version must have at least major and minor numbers";
tom53efab52014-10-07 17:43:48 -070035
36 private final int major;
37 private final int minor;
Thomas Vachuska045c01d2014-12-04 00:18:06 -080038 private final String patch;
tom53efab52014-10-07 17:43:48 -070039 private final String build;
40
41 private final String format;
42
43 // Creates a new version descriptor
Thomas Vachuska045c01d2014-12-04 00:18:06 -080044 private Version(int major, int minor, String patch, String build) {
tom53efab52014-10-07 17:43:48 -070045 this.major = major;
46 this.minor = minor;
47 this.patch = patch;
48 this.build = build;
Thomas Vachuska93d944c2015-06-16 09:48:55 -070049 this.format =
50 isNullOrEmpty(patch) ?
51 String.format(FORMAT_MINIMAL, major, minor) :
52 (isNullOrEmpty(build) ?
53 String.format(FORMAT_SHORT, major, minor, patch) :
54 String.format(FORMAT_LONG, major, minor, patch, build));
tom53efab52014-10-07 17:43:48 -070055 }
56
57
58 /**
59 * Creates a new version from the specified constituent numbers.
60 *
61 * @param major major version number
Yuta HIGUCHIc7aa5072015-02-02 15:01:02 -080062 * @param minor minor version number
Thomas Vachuska045c01d2014-12-04 00:18:06 -080063 * @param patch version patch segment
64 * @param build optional build string
tom53efab52014-10-07 17:43:48 -070065 * @return version descriptor
66 */
Thomas Vachuska045c01d2014-12-04 00:18:06 -080067 public static Version version(int major, int minor, String patch, String build) {
Thomas Vachuskaafb11da2015-06-16 10:01:13 -070068 checkArgument(major >= 0, NEGATIVE);
69 checkArgument(minor >= 0, NEGATIVE);
tom53efab52014-10-07 17:43:48 -070070 return new Version(major, minor, patch, build);
71 }
72
73 /**
74 * Creates a new version by parsing the specified string.
75 *
76 * @param string version string
77 * @return version descriptor
78 */
79 public static Version version(String string) {
Ray Milkey16570322018-04-17 10:26:54 -070080 checkArgument(string != null, TOO_SHORT);
David K. Bainbridgeae06fc42016-06-07 19:13:07 -070081 String[] fields = string.split("[.-]", 4);
Thomas Vachuskaafb11da2015-06-16 10:01:13 -070082 checkArgument(fields.length >= 2, TOO_SHORT);
tom53efab52014-10-07 17:43:48 -070083 return new Version(parseInt(fields[0]), parseInt(fields[1]),
Thomas Vachuska93d944c2015-06-16 09:48:55 -070084 fields.length >= 3 ? fields[2] : null,
85 fields.length >= 4 ? fields[3] : null);
tom53efab52014-10-07 17:43:48 -070086 }
87
88 /**
Jordan Haltermanab7d1f32018-04-04 11:59:11 -070089 * Returns an version from integer.
90 * <p>
91 * The version integer must be in the following format (big endian):
92 * <ul>
93 * <li>8-bit unsigned major version</li>
94 * <li>8-bit unsigned minor version</li>
95 * <li>16-bit unsigned patch version</li>
96 * </ul>
97 *
98 * @param version the version integer
99 * @return the version instance
100 */
101 public static Version fromInt(int version) {
102 int major = (version >> 24) & 0xff;
103 int minor = (version >> 16) & 0xff;
Jordan Haltermanca7660a2018-04-04 23:43:23 -0700104 int patch = (version >> 8) & 0xff;
105 int build = version & 0xff;
106 return new Version(major, minor, String.valueOf(patch), String.valueOf(build));
Jordan Haltermanab7d1f32018-04-04 11:59:11 -0700107 }
108
109 /**
tom53efab52014-10-07 17:43:48 -0700110 * Returns the major version number.
111 *
112 * @return major version number
113 */
114 public int major() {
115 return major;
116 }
117
118 /**
119 * Returns the minor version number.
120 *
121 * @return minor version number
122 */
123 public int minor() {
124 return minor;
125 }
126
127 /**
Thomas Vachuska045c01d2014-12-04 00:18:06 -0800128 * Returns the version patch segment.
tom53efab52014-10-07 17:43:48 -0700129 *
130 * @return patch number
131 */
Thomas Vachuska045c01d2014-12-04 00:18:06 -0800132 public String patch() {
tom53efab52014-10-07 17:43:48 -0700133 return patch;
134 }
135
136 /**
137 * Returns the version build string.
138 *
139 * @return build string
140 */
141 public String build() {
142 return build;
143 }
144
Jordan Haltermanab7d1f32018-04-04 11:59:11 -0700145 /**
146 * Returns an integer representation of the version.
147 * <p>
148 * The version integer can be used to compare two versions to one another.
149 * The integer representation of the version number is in the following format (big endian):
150 * <ul>
151 * <li>8-bit unsigned major version</li>
152 * <li>8-bit unsigned minor version</li>
153 * <li>16-bit unsigned patch version</li>
154 * </ul>
155 * If the {@link #patch()} is not a number, it will default to {@code 0}.
156 *
157 * @return an integer representation of the version
158 */
159 public int toInt() {
160 byte major = (byte) this.major;
161 byte minor = (byte) this.minor;
Jordan Haltermanca7660a2018-04-04 23:43:23 -0700162
163 byte patch;
164 if (this.patch != null) {
165 try {
166 patch = (byte) Integer.parseInt(this.patch.replaceAll("[^0-9]", ""));
167 } catch (NumberFormatException e) {
168 patch = 0;
169 }
170 } else {
Jordan Haltermanab7d1f32018-04-04 11:59:11 -0700171 patch = 0;
172 }
Jordan Haltermanca7660a2018-04-04 23:43:23 -0700173
174 byte build;
175 if (this.build != null) {
176 try {
177 build = (byte) Integer.parseInt(this.build.replaceAll("[^0-9]", ""));
178 } catch (NumberFormatException e) {
179 build = 0;
180 }
181 } else {
182 build = 0;
183 }
184
185 return major << 24 | (minor & 0xff) << 16 | (patch & 0xff) << 8 | (build & 0xff);
Jordan Haltermanab7d1f32018-04-04 11:59:11 -0700186 }
187
188 @Override
189 public int compareTo(Version other) {
190 return Integer.compare(toInt(), other.toInt());
191 }
192
tom53efab52014-10-07 17:43:48 -0700193 @Override
194 public String toString() {
195 return format;
196 }
197
198 @Override
199 public int hashCode() {
HIGUCHI Yutaca9cc8e2015-10-29 23:26:51 -0700200 return format.hashCode();
tom53efab52014-10-07 17:43:48 -0700201 }
202
203 @Override
204 public boolean equals(Object obj) {
205 if (this == obj) {
206 return true;
207 }
208 if (obj instanceof Version) {
209 final Version other = (Version) obj;
210 return Objects.equals(this.format, other.format);
211 }
212 return false;
213 }
214}