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