1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.model;
35
36 import java.util.regex.Pattern;
37
38
39
40
41
42
43
44
45 public class Version {
46 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Version.class);
47
48 public static final Version UNDEFINED_FROM = new UndefinedEarlierVersion();
49 public static final Version UNDEFINED_TO = new UndefinedLaterVersion();
50 public static final Version UNDEFINED_DEVELOPMENT_VERSION = new UndefinedDevelopmentVersion();
51
52 private static final Pattern classifierValidation = Pattern.compile("[A-Za-z0-9-_]+");
53 private final short major;
54 private final short minor;
55 private final short patch;
56 private final String classifier;
57
58
59
60
61 protected Version(int major, int minor, int patch) {
62 this.major = (short) major;
63 this.minor = (short) minor;
64 this.patch = (short) patch;
65 this.classifier = null;
66 }
67
68 private Version(String versionStr) {
69 final String numbers;
70 final int classifierIdx = versionStr.indexOf('-');
71 if (classifierIdx > 0) {
72 classifier = versionStr.substring(classifierIdx + 1);
73 if (!classifierValidation.matcher(classifier).matches()) {
74 throw new IllegalArgumentException("Invalid classifier: \"" + classifier + "\" in version \"" + versionStr + "\"");
75 }
76 numbers = versionStr.substring(0, classifierIdx);
77 } else {
78 classifier = null;
79 numbers = versionStr;
80 }
81
82 final String[] strings = numbers.split("\\.", -1);
83 if (strings.length > 0) {
84 major = getShortFor("major revision", versionStr, strings[0]);
85 } else {
86 major = getShortFor("major revision", versionStr, versionStr);
87 }
88 if (strings.length > 1) {
89 minor = getShortFor("minor revision", versionStr, strings[1]);
90 } else {
91 minor = 0;
92 }
93 if (strings.length > 2) {
94 patch = getShortFor("patch revision", versionStr, strings[2]);
95 } else {
96 patch = 0;
97 }
98 }
99
100
101
102
103
104
105
106
107 public static Version parseVersion(String versionStr) {
108
109 versionStr = versionStr.trim();
110
111 log.debug("parsing version [{}]", versionStr);
112
113 if (UndefinedDevelopmentVersion.isDevelopmentVersion(versionStr)) {
114
115 return UNDEFINED_DEVELOPMENT_VERSION;
116 }
117
118 return new Version(versionStr);
119 }
120
121 public static Version parseVersion(int major, int minor, int patch) {
122 return new Version(major, minor, patch);
123 }
124
125
126
127
128
129 public boolean isEquivalent(final Version other) {
130 if(other == UNDEFINED_DEVELOPMENT_VERSION){
131 return true;
132 }
133 return this.getMajor() == other.getMajor() &&
134 this.getMinor() == other.getMinor() &&
135 this.getPatch() == other.getPatch();
136 }
137
138 public boolean isStrictlyAfter(final Version other) {
139 if(isEquivalent(other)){
140 return false;
141 }
142 if (this.getMajor() != other.getMajor()) {
143 return this.getMajor() > other.getMajor();
144 }
145 if (this.getMinor() != other.getMinor()) {
146 return this.getMinor() > other.getMinor();
147 }
148 if (this.getPatch() != other.getPatch()) {
149 return this.getPatch() > other.getPatch();
150 }
151 return false;
152 }
153
154 public boolean isBeforeOrEquivalent(final Version other) {
155 return !isStrictlyAfter(other);
156 }
157
158 public short getMajor() {
159 return major;
160 }
161
162 public short getMinor() {
163 return minor;
164 }
165
166 public short getPatch() {
167 return patch;
168 }
169
170 public String getClassifier() {
171 return classifier;
172 }
173
174 @Override
175 public String toString() {
176 return major + "." + minor + "." + patch + (classifier != null ? "-" + classifier : "");
177 }
178
179 private short getShortFor(String message, String versionStr, String input) {
180 try {
181 return Short.parseShort(input);
182 } catch (NumberFormatException e) {
183 throw new RuntimeException("Invalid " + message + ": \"" + input + "\" in version \"" + versionStr + "\"");
184 }
185 }
186
187 private static final class UndefinedLaterVersion extends Version {
188 public UndefinedLaterVersion() {
189 super(Short.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE);
190 }
191
192 @Override
193 public String toString() {
194 return "*";
195 }
196 }
197
198 private static final class UndefinedEarlierVersion extends Version {
199 public UndefinedEarlierVersion() {
200 super(Short.MIN_VALUE, Short.MIN_VALUE, Short.MIN_VALUE);
201 }
202
203 @Override
204 public String toString() {
205 return "*";
206 }
207 }
208
209
210
211
212
213 static final class UndefinedDevelopmentVersion extends Version {
214
215 @Deprecated
216 static final String KEY = "${project.version}";
217
218 public UndefinedDevelopmentVersion() {
219 super(0, 0, 0);
220 }
221
222 @Override
223 public boolean isEquivalent(Version other) {
224 return true;
225 }
226
227 @Override
228 public String toString() {
229 return KEY;
230 }
231
232 public static boolean isDevelopmentVersion(String version) {
233 return version != null && version.startsWith("${");
234 }
235
236 }
237
238
239 @Override
240 public boolean equals(Object o) {
241 if (this == o) {
242 return true;
243 }
244 if (o == null || getClass() != o.getClass()) {
245 return false;
246 }
247
248 Version version = (Version) o;
249
250 if (major != version.major) {
251 return false;
252 }
253 if (minor != version.minor) {
254 return false;
255 }
256 if (patch != version.patch) {
257 return false;
258 }
259 if (classifier != null ? !classifier.equals(version.classifier) : version.classifier != null) {
260 return false;
261 }
262
263 return true;
264 }
265
266 @Override
267 public int hashCode() {
268 int result;
269 result = major;
270 result = 31 * result + minor;
271 result = 31 * result + patch;
272 result = 31 * result + (classifier != null ? classifier.hashCode() : 0);
273 return result;
274 }
275 }