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