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 public String toString() {
175 return major + "." + minor + "." + patch + (classifier != null ? "-" + classifier : "");
176 }
177
178 private short getShortFor(String message, String versionStr, String input) {
179 try {
180 return Short.parseShort(input);
181 } catch (NumberFormatException e) {
182 throw new RuntimeException("Invalid " + message + ": \"" + input + "\" in version \"" + versionStr + "\"");
183 }
184 }
185
186 private static final class UndefinedLaterVersion extends Version {
187 public UndefinedLaterVersion() {
188 super(Short.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE);
189 }
190
191 public String toString() {
192 return "*";
193 }
194 }
195
196 private static final class UndefinedEarlierVersion extends Version {
197 public UndefinedEarlierVersion() {
198 super(Short.MIN_VALUE, Short.MIN_VALUE, Short.MIN_VALUE);
199 }
200
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 public boolean isEquivalent(Version other) {
220 return true;
221 }
222
223 public String toString() {
224 return KEY;
225 }
226
227 public static boolean isDevelopmentVersion(String version) {
228 return version != null && version.startsWith("${");
229 }
230
231 }
232
233
234 public boolean equals(Object o) {
235 if (this == o) {
236 return true;
237 }
238 if (o == null || getClass() != o.getClass()) {
239 return false;
240 }
241
242 Version version = (Version) o;
243
244 if (major != version.major) {
245 return false;
246 }
247 if (minor != version.minor) {
248 return false;
249 }
250 if (patch != version.patch) {
251 return false;
252 }
253 if (classifier != null ? !classifier.equals(version.classifier) : version.classifier != null) {
254 return false;
255 }
256
257 return true;
258 }
259
260 public int hashCode() {
261 int result;
262 result = (int) major;
263 result = 31 * result + (int) minor;
264 result = 31 * result + (int) patch;
265 result = 31 * result + (classifier != null ? classifier.hashCode() : 0);
266 return result;
267 }
268 }