1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package nl.toolforge.karma.core;
20
21 import java.util.StringTokenizer;
22 import java.util.regex.PatternSyntaxException;
23
24 /***
25 * A <code>Version</code> is the container object for the <code>version</code> attribute of a module. The implementation
26 * is independent of the version control system.
27 *
28 * @author D.A. Smedes
29 * @version $Id: Version.java,v 1.12 2004/11/02 22:57:08 amooy Exp $
30 */
31 public class Version implements Cloneable, Comparable {
32
33 public static String VERSION_PATTERN_STRING = "//d{1,2}-//d{1,2}";
34
35 /*** Separator for version digits. */
36 public static final String VERSION_SEPARATOR_CHAR = "-";
37
38 /*** The initial version for a module. */
39 public static Version INITIAL_VERSION = new Version("0"+VERSION_SEPARATOR_CHAR+"0");
40
41 public static final int FIRST_DIGIT = 0;
42 public static final int SECOND_DIGIT = 1;
43 public static final int THIRD_DIGIT = 2;
44
45 private String versionNumber = null;
46
47 private int[] versionDigits = null;
48
49 /***
50 * Constructs a version number using the <code>versionIdentifier</code> parameter.
51 *
52 * @param versionIdentifier
53 */
54 public Version(String versionIdentifier) {
55
56 if (!versionIdentifier.matches(getPatternString())) {
57 throw new PatternSyntaxException(
58 "Pattern mismatch for version. Should match " + getPatternString(), versionIdentifier, -1);
59 }
60
61
62 StringTokenizer tokenizer = new StringTokenizer(versionIdentifier, VERSION_SEPARATOR_CHAR);
63
64 versionDigits = new int[tokenizer.countTokens()];
65 int i = 0;
66 while (tokenizer.hasMoreTokens()) {
67 versionDigits[i] = new Integer(tokenizer.nextToken()).intValue();
68 i++;
69 }
70
71 createVersionNumber();
72 }
73
74 public String getPatternString() {
75 return VERSION_PATTERN_STRING;
76 }
77
78 /***
79 * Returns the initial version for a module. Right now, this is implemented as <code>new Version("0-0")</code>.
80 *
81 * @return
82 */
83 protected static Version getInitialVersion() {
84 return new Version("0"+VERSION_SEPARATOR_CHAR+"0");
85 }
86
87 /***
88 * Creates a <code>Patch</code> based on this version.
89 *
90 * @param patchNumber
91 * @return
92 */
93 public Patch createPatch(int patchNumber) {
94 return new Patch(getVersionNumber() + VERSION_SEPARATOR_CHAR + patchNumber);
95 }
96
97 /***
98 * Constructs a version number concatenating each item in <code>versionDigits</code>, using the <code>'-'</code>
99 * separator. <code>{1, 0, 9}</code> translates into a version number <code>1-0-9</code>.
100 *
101 * @param versionDigits An array, containing all version components (maximum of three is allowed).
102 */
103 public Version(int[] versionDigits) {
104
105 if (versionDigits.length < 2) {
106 throw new IllegalArgumentException(
107 "Pattern mismatch for version. Should match " + getPatternString() +
108 "; provide 'int'-array");
109 }
110
111 StringBuffer versionStringBuffer = new StringBuffer();
112 for (int i = 0; i < versionDigits.length; i++) {
113 versionStringBuffer.append(versionDigits[i]);
114 if (i < versionDigits.length - 1);
115 }
116
117 this.versionDigits = versionDigits;
118
119 createVersionNumber();
120 }
121
122 private void createVersionNumber() {
123 this.versionNumber = "" + versionDigits[0];
124 for (int i = 1; i < versionDigits.length; i++) {
125 this.versionNumber += VERSION_SEPARATOR_CHAR + versionDigits[i];
126 }
127 }
128
129 public String getVersionNumber() {
130 return versionNumber;
131 }
132
133 private int getLastDigit() {
134 return versionDigits[versionDigits.length - 1];
135 }
136
137 private int getLastDigitIndex() {
138 return versionDigits.length - 1;
139 }
140
141 /***
142 * Gets the string representation of this version.
143 *
144 * @return A string representation of this version.
145 */
146 public String toString() {
147 return versionNumber;
148 }
149
150 public final int hashCode() {
151 return versionNumber.hashCode();
152 }
153
154 public final boolean equals(Object o) {
155 if (!(o instanceof Version)) {
156 return false;
157 }
158
159 return ((Version) o).versionNumber.equals(this.versionNumber);
160 }
161
162 /***
163 * Compares two <code>Version</code> instances.
164 *
165 * @param o The other <code>Version</code> instance to match against.
166 * @return Returns <code>-1</code> when <code>this < o</code>, <code>0</code> when
167 * <code>this == o</code> or <code>1</code> when <code>this > o</code>.
168 */
169 public final int compareTo(Object o) {
170
171 int[] zis = versionDigits;
172 int[] zat = ((Version) o).versionDigits;
173
174 if (zis[0] < zat[0]) {
175 return -1;
176 } else if (zis[0] == zat[0]) {
177 if (zis[1] < zat[1]) {
178 return -1;
179 } else if (zis[1] == zat[1]) {
180 if (o instanceof Patch) {
181
182
183 if (zis[2] < zat[2]) {
184 return -1;
185 } else if (zis[2] == zat[2]) {
186 return 0;
187 } else {
188 return 1;
189 }
190 }
191 return 0;
192 } else {
193 return 1;
194 }
195 } else {
196 return 1;
197 }
198 }
199
200 public void setDigit(int index, int nextDigit) {
201 versionDigits[index] = nextDigit;
202 createVersionNumber();
203 }
204
205 public final boolean isLowerThan(Version version) {
206 return this.compareTo(version) == -1;
207 }
208
209 public final boolean isHigherThan(Version version) {
210 return this.compareTo(version) == 1;
211 }
212
213 /***
214 * Increases this versions' last digit by 1.
215 */
216 public final void increase() {
217 setDigit(getLastDigitIndex(), getLastDigit() + 1);
218 }
219
220 /***
221 * Increases this Version to the next major version by increasing
222 * the first digit of the version and setting the second digit to "0".
223 */
224 public void increaseMajor() {
225 setDigit(FIRST_DIGIT, versionDigits[0] + 1);
226 setDigit(SECOND_DIGIT, 0);
227 }
228
229 public Object clone() throws CloneNotSupportedException {
230 return super.clone();
231 }
232 }