1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.util;
24  
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.StringPool;
27  import com.liferay.portal.kernel.util.Validator;
28  
29  import java.util.Map;
30  import java.util.StringTokenizer;
31  import java.util.concurrent.ConcurrentHashMap;
32  
33  /**
34   * <a href="Version.java.html"><b><i>View Source</i></b></a>
35   *
36   * @author Jorge Ferrer
37   *
38   */
39  public class Version implements Comparable<Version> {
40  
41      public static final String UNKNOWN = "unknown";
42  
43      public static Version getInstance(String version) {
44          Version versionObj = _versions.get(version);
45  
46          if (versionObj == null) {
47              versionObj = new Version(version);
48  
49              _versions.put(version, versionObj);
50          }
51  
52          return versionObj;
53      }
54  
55      public static Version incrementBugFix(Version version) {
56          String bugFix = version.getBugFix();
57  
58          int bugFixInt = GetterUtil.getInteger(bugFix);
59  
60          if (bugFixInt > 0) {
61              bugFix = String.valueOf(bugFixInt + 1);
62          }
63  
64          return getInstance(
65              _toString(
66                  version.getMajor(), version.getMinor(), bugFix,
67                  version.getBuildNumber()));
68      }
69  
70      public static Version incrementBuildNumber(Version version) {
71          String buildNumber = version.getBuildNumber();
72  
73          int buildNumberInt = GetterUtil.getInteger(buildNumber);
74  
75          if (buildNumberInt > 0) {
76              buildNumber = String.valueOf(buildNumberInt + 1);
77          }
78  
79          return getInstance(
80              _toString(
81                  version.getMajor(), version.getMinor(), version.getBugFix(),
82                  buildNumber));
83      }
84  
85      public static Version incrementMajor(Version version) {
86          String major = version.getMajor();
87  
88          int majorInt = GetterUtil.getInteger(major);
89  
90          if (majorInt > 0) {
91              major = String.valueOf(majorInt + 1);
92          }
93  
94          return getInstance(
95              _toString(
96                  major, version.getMinor(), version.getBugFix(),
97                  version.getBuildNumber()));
98      }
99  
100     public static Version incrementMinor(Version version) {
101         String minor = version.getMinor();
102 
103         int minorInt = GetterUtil.getInteger(minor);
104 
105         if (minorInt > 0) {
106             minor = String.valueOf(minorInt + 1);
107         }
108 
109         return getInstance(
110             _toString(
111                 version.getMajor(), minor, version.getBugFix(),
112                 version.getBuildNumber()));
113     }
114 
115     protected Version(String version) {
116         StringTokenizer st = new StringTokenizer(version, _SEPARATOR);
117 
118         _major = st.nextToken();
119 
120         if (st.hasMoreTokens()) {
121             _minor = st.nextToken();
122         }
123 
124         if (st.hasMoreTokens()) {
125             _bugFix = st.nextToken();
126         }
127 
128         StringBuilder sb = new StringBuilder();
129 
130         while (st.hasMoreTokens()) {
131             sb.append(st.nextToken());
132 
133             if (st.hasMoreTokens()) {
134                 sb.append(_SEPARATOR);
135             }
136         }
137 
138         _buildNumber = sb.toString();
139     }
140 
141     public int compareTo(Version version) {
142         if (version == null) {
143             return 1;
144         }
145 
146         // Unknown is always considered a lower version
147 
148         if (version.toString().equals(UNKNOWN)) {
149             return 1;
150         }
151 
152         if (toString().equals(UNKNOWN)) {
153             return -1;
154         }
155 
156         int result = getMajor().compareTo(version.getMajor());
157 
158         if (result != 0) {
159             return result;
160         }
161 
162         result = getMinor().compareTo(version.getMinor());
163 
164         if (result != 0) {
165             return result;
166         }
167 
168         result = getBugFix().compareTo(version.getBugFix());
169 
170         if (result != 0) {
171             return result;
172         }
173 
174         return getBuildNumber().compareTo(version.getBuildNumber());
175     }
176 
177     public boolean equals(Object obj) {
178         if ((obj == null) || (!(obj instanceof Version))) {
179             return false;
180         }
181 
182         Version version = (Version)obj;
183 
184         String versionString1 = toString();
185         String versionString2 = version.toString();
186 
187         if (versionString1.equals(UNKNOWN) || versionString2.equals(UNKNOWN)) {
188             return false;
189         }
190 
191         return versionString1.equals(versionString2);
192     }
193 
194     public String getBugFix() {
195         if (_bugFix == null) {
196             return "0";
197         }
198 
199         return _bugFix;
200     }
201 
202     public String getBuildNumber() {
203         return _buildNumber;
204     }
205 
206     public String getMajor() {
207         if (_major == null) {
208             return "0";
209         }
210 
211         return _major;
212     }
213 
214     public String getMinor() {
215         if (_minor == null) {
216             return "0";
217         }
218 
219         return _minor;
220     }
221 
222     public int hashCode() {
223         return toString().hashCode();
224     }
225 
226     public boolean includes(Version version) {
227         if (equals(version)) {
228             return true;
229         }
230 
231         if (getMajor().equals(StringPool.STAR)) {
232             return true;
233         }
234 
235         if (getMajor().equals(version.getMajor())) {
236             if (getMinor().equals(StringPool.STAR)) {
237                 return true;
238             }
239 
240             if (getMinor().equals(version.getMinor())) {
241                 if (getBugFix().equals(StringPool.STAR)) {
242                     return true;
243                 }
244 
245                 if (getBugFix().equals(version.getBugFix())) {
246                     if (getBuildNumber().equals(StringPool.STAR) ||
247                         getBuildNumber().equals(version.getBuildNumber())) {
248 
249                         return true;
250                     }
251                 }
252                 else if (_contains(getBugFix(), version.getBugFix())) {
253                     return true;
254                 }
255             }
256             else if (_contains(getMinor(), version.getMinor())) {
257                 return true;
258             }
259         }
260         else if (_contains(getMajor(), version.getMajor())) {
261             return true;
262         }
263 
264         return false;
265     }
266 
267     public boolean isLaterVersionThan(String version) {
268         if (compareTo(getInstance(version)) > 0) {
269             return true;
270         }
271         else {
272             return false;
273         }
274     }
275 
276     public boolean isPreviousVersionThan(String version) {
277         if (compareTo(getInstance(version)) < 0) {
278             return true;
279         }
280         else {
281             return false;
282         }
283     }
284 
285     public boolean isSameVersionAs(String version) {
286         if (compareTo(getInstance(version)) == 0) {
287             return true;
288         }
289         else {
290             return false;
291         }
292     }
293 
294     public String toString() {
295         return _toString(_major, _minor, _bugFix, _buildNumber);
296     }
297 
298     private static boolean _contains(
299         String containerString, String numberString) {
300 
301         if (containerString.endsWith(StringPool.PLUS)) {
302             String containerNumberString = containerString.substring(
303                 0, containerString.length() - 1);
304 
305             try {
306                 int containerNumber = Integer.parseInt(containerNumberString);
307                 int number = Integer.parseInt(numberString);
308 
309                 return containerNumber <= number;
310             }
311             catch (NumberFormatException nfe) {
312                 return false;
313             }
314         }
315 
316         return false;
317     }
318 
319     public static String _toString(
320         String major, String minor, String bugFix, String buildNumber) {
321 
322         StringBuilder sb = new StringBuilder();
323 
324         sb.append(major);
325 
326         if (Validator.isNotNull(minor)) {
327             sb.append(_SEPARATOR);
328             sb.append(minor);
329 
330             if (Validator.isNotNull(bugFix)) {
331                 sb.append(_SEPARATOR);
332                 sb.append(bugFix);
333 
334                 if (Validator.isNotNull(buildNumber)) {
335                     sb.append(_SEPARATOR);
336                     sb.append(buildNumber);
337                 }
338             }
339         }
340 
341         return sb.toString();
342     }
343 
344     private static final String _SEPARATOR = StringPool.PERIOD;
345 
346     private static Map<String, Version> _versions =
347         new ConcurrentHashMap<String, Version>();
348 
349     private String _major;
350     private String _minor;
351     private String _bugFix;
352     private String _buildNumber;
353 
354 }