View Javadoc

1   /*
2   Karma core - Core of the Karma application
3   Copyright (C) 2004  Toolforge <www.toolforge.nl>
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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           // We also have a third digit to take into account.
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 }