1   /**
2    * Copyright (c) 2000-2008 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.StringMaker;
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 String getMajor() {
56          if (_major == null) {
57              return "0";
58          }
59  
60          return _major;
61      }
62  
63      public String getMinor() {
64          if (_minor == null) {
65              return "0";
66          }
67  
68          return _minor;
69      }
70  
71      public String getBugFix() {
72          if (_bugFix == null) {
73              return "0";
74          }
75  
76          return _bugFix;
77      }
78  
79      public String getBuildNumber() {
80          return _buildNumber;
81      }
82  
83      public boolean isLaterVersionThan(String version) {
84          if (compareTo(getInstance(version)) > 0) {
85              return true;
86          }
87          else {
88              return false;
89          }
90      }
91  
92      public boolean isPreviousVersionThan(String version) {
93          if (compareTo(getInstance(version)) < 0) {
94              return true;
95          }
96          else {
97              return false;
98          }
99      }
100 
101     public boolean isSameVersionAs(String version) {
102         if (compareTo(getInstance(version)) == 0) {
103             return true;
104         }
105         else {
106             return false;
107         }
108     }
109 
110     public boolean includes(Version version) {
111         if (equals(version)) {
112             return true;
113         }
114 
115         if (getMajor().equals(StringPool.STAR)) {
116             return true;
117         }
118 
119         if (getMajor().equals(version.getMajor())) {
120             if (getMinor().equals(StringPool.STAR)) {
121                 return true;
122             }
123 
124             if (getMinor().equals(version.getMinor())) {
125                 if (getBugFix().equals(StringPool.STAR)) {
126                     return true;
127                 }
128 
129                 if (getBugFix().equals(version.getBugFix())) {
130                     if (getBuildNumber().equals(StringPool.STAR) ||
131                         getBuildNumber().equals(version.getBuildNumber())) {
132 
133                         return true;
134                     }
135                 }
136                 else if (_contains(getBugFix(), version.getBugFix())) {
137                     return true;
138                 }
139             }
140             else if (_contains(getMinor(), version.getMinor())) {
141                 return true;
142             }
143         }
144         else if (_contains(getMajor(), version.getMajor())) {
145             return true;
146         }
147 
148         return false;
149     }
150 
151     public int compareTo(Version version) {
152         if (version == null) {
153             return 1;
154         }
155 
156         // Unknown is always considered a lower version
157 
158         if (version.toString().equals(UNKNOWN)) {
159             return 1;
160         }
161 
162         if (toString().equals(UNKNOWN)) {
163             return -1;
164         }
165 
166         int result = getMajor().compareTo(version.getMajor());
167 
168         if (result != 0) {
169             return result;
170         }
171 
172         result = getMinor().compareTo(version.getMinor());
173 
174         if (result != 0) {
175             return result;
176         }
177 
178         result = getBugFix().compareTo(version.getBugFix());
179 
180         if (result != 0) {
181             return result;
182         }
183 
184         return getBuildNumber().compareTo(version.getBuildNumber());
185     }
186 
187     public boolean equals(Object obj) {
188         if ((obj == null) || (!(obj instanceof Version))) {
189             return false;
190         }
191 
192         Version version = (Version)obj;
193 
194         String versionString1 = toString();
195         String versionString2 = version.toString();
196 
197         if (versionString1.equals(UNKNOWN) || versionString2.equals(UNKNOWN)) {
198             return false;
199         }
200 
201         return versionString1.equals(versionString2);
202     }
203 
204     public int hashCode() {
205         return toString().hashCode();
206     }
207 
208     public String toString() {
209         StringMaker sm = new StringMaker();
210 
211         sm.append(_major);
212 
213         if (Validator.isNotNull(_minor)) {
214             sm.append(_SEPARATOR);
215             sm.append(_minor);
216 
217             if (Validator.isNotNull(_bugFix)) {
218                 sm.append(_SEPARATOR);
219                 sm.append(_bugFix);
220 
221                 if (Validator.isNotNull(_buildNumber)) {
222                     sm.append(_SEPARATOR);
223                     sm.append(_buildNumber);
224                 }
225             }
226         }
227 
228         return sm.toString();
229     }
230 
231     protected Version(String version) {
232         StringTokenizer st = new StringTokenizer(version, _SEPARATOR);
233 
234         _major = st.nextToken();
235 
236         if (st.hasMoreTokens()) {
237             _minor = st.nextToken();
238         }
239 
240         if (st.hasMoreTokens()) {
241             _bugFix = st.nextToken();
242         }
243 
244         StringMaker buildNumber = new StringMaker();
245 
246         while (st.hasMoreTokens()) {
247             buildNumber.append(st.nextToken());
248 
249             if (st.hasMoreTokens()) {
250                 buildNumber.append(_SEPARATOR);
251             }
252         }
253 
254         _buildNumber = buildNumber.toString();
255     }
256 
257     private boolean _contains(String containerStr, String numberStr) {
258         if (containerStr.endsWith(StringPool.PLUS)) {
259             String containerNumberStr =
260                     containerStr.substring(0, containerStr.length() - 1);
261 
262             try {
263                 int containerNumber = Integer.parseInt(containerNumberStr);
264                 int number = Integer.parseInt(numberStr);
265 
266                 return containerNumber <= number;
267             } catch (NumberFormatException nfe) {
268                 return false;
269             }
270         }
271         return false;
272     }
273 
274     private static final String _SEPARATOR = StringPool.PERIOD;
275 
276     private static Map<String, Version> _versions =
277         new ConcurrentHashMap<String, Version>();
278 
279     private String _major;
280     private String _minor;
281     private String _bugFix;
282     private String _buildNumber;
283 
284 }