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  public class Version implements Comparable<Version> {
39  
40      public static final String UNKNOWN = "unknown";
41  
42      public static Version getInstance(String version) {
43          Version versionObj = _versions.get(version);
44  
45          if (versionObj == null) {
46              versionObj = new Version(version);
47  
48              _versions.put(version, versionObj);
49          }
50  
51          return versionObj;
52      }
53  
54      public static Version incrementBugFix(Version version) {
55          String bugFix = version.getBugFix();
56  
57          int bugFixInt = GetterUtil.getInteger(bugFix);
58  
59          if (bugFixInt > 0) {
60              bugFix = String.valueOf(bugFixInt + 1);
61          }
62  
63          return getInstance(
64              _toString(
65                  version.getMajor(), version.getMinor(), bugFix,
66                  version.getBuildNumber()));
67      }
68  
69      public static Version incrementBuildNumber(Version version) {
70          String buildNumber = version.getBuildNumber();
71  
72          int buildNumberInt = GetterUtil.getInteger(buildNumber);
73  
74          if (buildNumberInt > 0) {
75              buildNumber = String.valueOf(buildNumberInt + 1);
76          }
77  
78          return getInstance(
79              _toString(
80                  version.getMajor(), version.getMinor(), version.getBugFix(),
81                  buildNumber));
82      }
83  
84      public static Version incrementMajor(Version version) {
85          String major = version.getMajor();
86  
87          int majorInt = GetterUtil.getInteger(major);
88  
89          if (majorInt > 0) {
90              major = String.valueOf(majorInt + 1);
91          }
92  
93          return getInstance(
94              _toString(
95                  major, version.getMinor(), version.getBugFix(),
96                  version.getBuildNumber()));
97      }
98  
99      public static Version incrementMinor(Version version) {
100         String minor = version.getMinor();
101 
102         int minorInt = GetterUtil.getInteger(minor);
103 
104         if (minorInt > 0) {
105             minor = String.valueOf(minorInt + 1);
106         }
107 
108         return getInstance(
109             _toString(
110                 version.getMajor(), minor, version.getBugFix(),
111                 version.getBuildNumber()));
112     }
113 
114     protected Version(String version) {
115         StringTokenizer st = new StringTokenizer(version, _SEPARATOR);
116 
117         _major = st.nextToken();
118 
119         if (st.hasMoreTokens()) {
120             _minor = st.nextToken();
121         }
122 
123         if (st.hasMoreTokens()) {
124             _bugFix = st.nextToken();
125         }
126 
127         StringBuilder sb = new StringBuilder();
128 
129         while (st.hasMoreTokens()) {
130             sb.append(st.nextToken());
131 
132             if (st.hasMoreTokens()) {
133                 sb.append(_SEPARATOR);
134             }
135         }
136 
137         _buildNumber = sb.toString();
138     }
139 
140     public int compareTo(Version version) {
141         if (version == null) {
142             return 1;
143         }
144 
145         // Unknown is always considered a lower version
146 
147         if (version.toString().equals(UNKNOWN)) {
148             return 1;
149         }
150 
151         if (toString().equals(UNKNOWN)) {
152             return -1;
153         }
154 
155         int result = getMajor().compareTo(version.getMajor());
156 
157         if (result != 0) {
158             return result;
159         }
160 
161         result = getMinor().compareTo(version.getMinor());
162 
163         if (result != 0) {
164             return result;
165         }
166 
167         result = getBugFix().compareTo(version.getBugFix());
168 
169         if (result != 0) {
170             return result;
171         }
172 
173         return getBuildNumber().compareTo(version.getBuildNumber());
174     }
175 
176     public boolean equals(Object obj) {
177         if ((obj == null) || (!(obj instanceof Version))) {
178             return false;
179         }
180 
181         Version version = (Version)obj;
182 
183         String versionString1 = toString();
184         String versionString2 = version.toString();
185 
186         if (versionString1.equals(UNKNOWN) || versionString2.equals(UNKNOWN)) {
187             return false;
188         }
189 
190         return versionString1.equals(versionString2);
191     }
192 
193     public String getBugFix() {
194         if (_bugFix == null) {
195             return "0";
196         }
197 
198         return _bugFix;
199     }
200 
201     public String getBuildNumber() {
202         return _buildNumber;
203     }
204 
205     public String getMajor() {
206         if (_major == null) {
207             return "0";
208         }
209 
210         return _major;
211     }
212 
213     public String getMinor() {
214         if (_minor == null) {
215             return "0";
216         }
217 
218         return _minor;
219     }
220 
221     public int hashCode() {
222         return toString().hashCode();
223     }
224 
225     public boolean includes(Version version) {
226         if (equals(version)) {
227             return true;
228         }
229 
230         if (getMajor().equals(StringPool.STAR)) {
231             return true;
232         }
233 
234         if (getMajor().equals(version.getMajor())) {
235             if (getMinor().equals(StringPool.STAR)) {
236                 return true;
237             }
238 
239             if (getMinor().equals(version.getMinor())) {
240                 if (getBugFix().equals(StringPool.STAR)) {
241                     return true;
242                 }
243 
244                 if (getBugFix().equals(version.getBugFix())) {
245                     if (getBuildNumber().equals(StringPool.STAR) ||
246                         getBuildNumber().equals(version.getBuildNumber())) {
247 
248                         return true;
249                     }
250                 }
251                 else if (_contains(getBugFix(), version.getBugFix())) {
252                     return true;
253                 }
254             }
255             else if (_contains(getMinor(), version.getMinor())) {
256                 return true;
257             }
258         }
259         else if (_contains(getMajor(), version.getMajor())) {
260             return true;
261         }
262 
263         return false;
264     }
265 
266     public boolean isLaterVersionThan(String version) {
267         if (compareTo(getInstance(version)) > 0) {
268             return true;
269         }
270         else {
271             return false;
272         }
273     }
274 
275     public boolean isPreviousVersionThan(String version) {
276         if (compareTo(getInstance(version)) < 0) {
277             return true;
278         }
279         else {
280             return false;
281         }
282     }
283 
284     public boolean isSameVersionAs(String version) {
285         if (compareTo(getInstance(version)) == 0) {
286             return true;
287         }
288         else {
289             return false;
290         }
291     }
292 
293     public String toString() {
294         return _toString(_major, _minor, _bugFix, _buildNumber);
295     }
296 
297     private static boolean _contains(
298         String containerString, String numberString) {
299 
300         if (containerString.endsWith(StringPool.PLUS)) {
301             String containerNumberString = containerString.substring(
302                 0, containerString.length() - 1);
303 
304             try {
305                 int containerNumber = Integer.parseInt(containerNumberString);
306                 int number = Integer.parseInt(numberString);
307 
308                 return containerNumber <= number;
309             }
310             catch (NumberFormatException nfe) {
311                 return false;
312             }
313         }
314 
315         return false;
316     }
317 
318     public static String _toString(
319         String major, String minor, String bugFix, String buildNumber) {
320 
321         StringBuilder sb = new StringBuilder();
322 
323         sb.append(major);
324 
325         if (Validator.isNotNull(minor)) {
326             sb.append(_SEPARATOR);
327             sb.append(minor);
328 
329             if (Validator.isNotNull(bugFix)) {
330                 sb.append(_SEPARATOR);
331                 sb.append(bugFix);
332 
333                 if (Validator.isNotNull(buildNumber)) {
334                     sb.append(_SEPARATOR);
335                     sb.append(buildNumber);
336                 }
337             }
338         }
339 
340         return sb.toString();
341     }
342 
343     private static final String _SEPARATOR = StringPool.PERIOD;
344 
345     private static Map<String, Version> _versions =
346         new ConcurrentHashMap<String, Version>();
347 
348     private String _major;
349     private String _minor;
350     private String _bugFix;
351     private String _buildNumber;
352 
353 }